[RISOLTO] Unire e convertire serie di 8 bit in numero decimale

Buongiorno,
Volevo chiedere gentilmente come fare ad unire e convertire una serie di 8 bit in un numero decimale. Il numero decimale mi serve come valore per essere inviato tramite libreria Wire (e quindi in I2C) da Arduino ad un integrato.

Per unire intendo mettere in sequenza. A partire da delle variabili a cui assegno un valore di 0 o 1, metto in sequenza le variabili in un numero binario di 8 bit ad esempio così: 1000 1010

I vari bit controllano delle funzioni all’interno dell’integrato e mi servirebbe averli divisi e ordinati in modo
da cambiarli a mio piacimento senza andare a cercare un convertitore binario-decimale su internet ogni volta.

Ho visto che la libreria Wire invia i dati inserendo un valore decimale, se metto i numeri in binario non mi pare funzionasse.

Questo è il mio codice con commenti più esplicativi

#include <Wire.h>; //include libreria per comunicazione I2C

void setup()
{
  Wire.begin(); // join i2c bus
  Serial.begin(9600);
}

void loop()
{    

//Bit singoli da accorpare in una sequenza come questa 1001 0011

//RGB PROCESSING-1
  bool MAT = 0;
  bool EBB = 0;
  bool SBL = 0;
  bool RBL = 1;
  bool BLS = 0;
  bool BKS = 0;
  bool IE1 = 1; 
  bool IE2 = 1;

//RGB PROCESSING-2
  bool MUS = 0;
  bool FBC = 1;
  bool OBL = 0;
  bool AKB = 0;
  bool CL3 = 0;
  bool CL2 = 0;
  bool CL1 = 0;
  bool CL0 = 0;

//Wide Horizontal Blanking
  bool HBL = 1;
  bool TFBC = 1;
  bool GAI = 0;
  bool STB0 = 1;
  bool HB3 = 0;
  bool HB2 = 1;
  bool HB1 = 1;
  bool HB0 = 1;

//Horizontal Deflection
  bool HDTV = 1;
  bool VSR = 0;
  bool ZERO = 0;
  bool STB1 = 1; 
  bool POC = 0;
  bool PRD = 1;
  bool VGA = 0;
  bool ESS = 1;

//Vertical Deflection
  bool OPC = 0;
  bool VFF = 0;
  bool LBM = 0;
  bool DIP = 1;
  bool OSO = 0;
  bool SVF = 1;
  bool EVG = 1;
  bool DL= 1;
  
// Stadio di conversione di accorpamento e conversione in DEC (ma che non funziona)

  String sRGB1 = String(MAT&SBL&RBL&BLS&BKS&IE1&IE2,DEC);
  String sRGB2 = String(MUS&FBC&OBL&AKB&CL3&CL2&CL1&CL0,DEC);
  String sWHD = String(HBL&TFBC&GAI&STB0&HB3&HB2&HB1&HB0,DEC);
  String sHD = String(HDTV&VSR&ZERO&STB1&POC&PRD&VGA&ESS,DEC);
  String sVD = String(OPC&VFF&LBM&DIP&OSO&SVF&EVG&DL,DEC);

//Stampa i numeri in decimale sul monitor seriale (al momento appaiono solo 5 zeri e i numeri in decimale)

Serial.print(sRGB1);
Serial.print(sRGB2);
Serial.print(sWHD);
Serial.print(sHD);
Serial.print(sVD);

Se le informazioni che ho scritto non sono abbastanza esplicative, chiedete pure. Putroppo non mi è molto semplice spiegarlo. Poi… ci saranno evidenti errori di programmazione ma purtroppo sono alle basi basi :sweat_smile:

Buongiorno,
NON avendolo tu ancora fatto, nel rispetto del regolamento della sezione Italiana del forum (punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

gpb01:
P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

Buongiorno Guglielmo,

Grazie del suo accorgimento e mi scuso di non averlo fatto prima. Ho riletto meglio il regolamento e provveduto poco fa segnando le informazioni richieste (vedi link: Presentazione Agozzi (in fondo) . Se queste sono sufficienti, le chiedo cordialmente di sbloccare il post. Grazie.

Andrea

Non mi è molto chiaro. Ma tu vuoi un modo semplice per poter scrivere i singoli bit ma poi al Wire spedirai il byte (come numero), giusto ? E stamparlo a video è solo per controllarlo !?

  1. NON usare String su Arduino, poca memoria.
  2. La & di concatenazione sà molto di visual basic
  3. per lavorare con i bit devi usare operatori sui bit bitwise, Arduino ha poi delle sue funzioni sui bit, ad esempio bitSet()
    in alternativa puoi usare la tecnica di union con dentro una struct bitfield, tecnica un pò complicata, ma rende poi molto leggibile:
union 
{ struct  t_WideHorBlank //Wide Horizontal Blanking
  { unsigned char HBL :1;                    // 1 bit, bit 0
    unsigned char TFBC:1;                    // 1 bit, bit 1
    unsigned char GAI :1;
    unsigned char STB0:1;
    unsigned char HB3 :1;
    unsigned char HB2 :1;
    unsigned char HB1 :1;
    unsigned char HB0 :1;
  } bits;
  unsigned char byteval;       // 8 bit
};

t_WideHorBlank varWHB;

void setup()
{ delay(1000);
  Serial.begin(9600);
  Serial.println("avvio...");
  varWHB.bits.HBL =1;
  varWHB.bits.TFBC=1; 
  varWHB.bits.GAI =0;
  varWHB.bits.STB0=1;
  varWHB.bits.HB3 =0;
  varWHB.bits.HB2 =1;
  varWHB.bits.HB1 =1;
  varWHB.bits.HB0 =1;
  Serial.println(varWHB.byteval);
  varWHB.byteval=0b11101011;   // 0xEB  ovvero 235
  Serial.println(varWHB.byteval);
  varWHB.byteval=0xEB;               // 0b11101011  ovvero 235
  Serial.println(varWHB.byteval);
}
void loop() {}

Essendo alle prime esperienze software con Arduino prima ti indico un possibile problma generale, l’uso della classe String su Arduino è “il male” ti porta quasi sempre a problemi difficili da diagnosticare e comprendere. Se hai necessità di stringhe abituati fin da subito ad usare le stringhe classiche del C e le relative funzioni (strncat, strncpy, ecc)
Venendo al tuo problema quel che tu vuoi fare si può fare usando le operazioni sui bit ma non puoi pensare di concatenarli come hai fatto tu.
Un possibile sistema è quello di usare i confronti e lo shift dei bit:

byte bit_1 = 1;
byte bit_2 = 1;
byte bit_3 = 1;
byte risultato = 4&bit_3<<2 | 2&bit_2<<1 | bit_1;

Edit Sovrapposto a nid69ita che ha fornito due soluzioni altrnative

Grazie delle risposte!

nid69ita: Si, dato che sono alle prime armi, volevo stampare il numero decimale a video solo per verificare che l'operazione di conversione è riuscita e il numero inviato è effettivamente quello corretto. Poi il codice va avanti con le funzioni Wire.beginTransmission per inviare i dati, vi ho postato solo una parte del codice .

fabpolli: Ok, grazie per il chiarimento sulle Strings e per le funzioni che hai suggerito.

Ammetto che alcune delle variabili non le conosco bene. Mi informo e verifico su codice le vostre soluzioni prima di chiedere chiarimenti in più.

Andrea

Per completare quello che ti indica @fabpolli:

//0b11101011
unsigned char val= 1<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1 | 1<<0;
Serial.println(val);  // stampa 235

è un pò come se tu scrivessi:
val = 0b10000000 + 0b01000000 … etc. | è or sui bit, quindi un +

Però poco leggibile, se allora quei 7,6,5 ne fai delle define con nomi “utili”:

#define HB0 7
#define HB1 6
...  etc
unsigned char val= 1<<HBO | 1<<HB1 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1 | 1<<0;
Serial.println(val);

P.S. occhio, io non ho capito bene se x te HB0 è il bit 0 o il bit 7 (l’ordine dei bits)

Allora ho provato e adattato i codici forniti. Quello con union e struct purtroppo non mi è riuscito al momento anche cercando su Google le descrizioni ed esempi di queste due funzioni. Quindi ho provato ad usare questo codice:

//0b11101011
unsigned char val= 1<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1 | 1<<0;
Serial.println(val);  // stampa 235

e mi è riuscito apparentemente.

Qui il codice adattato e semplificato:

//RGB PROCESSING-1
  unsigned char MAT = 0;
  unsigned char EBB = 0;
  unsigned char SBL = 0;
  unsigned char RBL = 1;
  unsigned char BLS = 0;
  unsigned char BKS = 0;
  unsigned char IE1 = 1; 
  unsigned char IE2 = 1;

  unsigned char RGB1= MAT<<7 | EBB<<6 | SBL<<5 | RBL<<4 | BLS<<3 | BKS<<2 | IE1<<1 | IE2<<0;


void setup()
{
  Wire.begin(); // join i2c bus
  Serial.begin(9600);
}

void loop()
{  

  Serial.println(RGB1);
  delay(3000);  
}

Questo è il codice “completo” al momento:

Dichiarazione variabili:

int val = 0;
#include <Wire.h>; //libreria i2c

//RGB PROCESSING-1
  unsigned char MAT = 0;
  unsigned char EBB = 0;
  unsigned char SBL = 0;
  unsigned char RBL = 1;
  unsigned char BLS = 0;
  unsigned char BKS = 0;
  unsigned char IE1 = 1; 
  unsigned char IE2 = 1;

//RGB PROCESSING-2
  unsigned char MUS = 0;
  unsigned char FBC = 1;
  unsigned char OBL = 0;
  unsigned char AKB = 0;
  unsigned char CL3 = 0;
  unsigned char CL2 = 0;
  unsigned char CL1 = 0;
  unsigned char CL0 = 0;

//Wide Horizontal Blanking
  unsigned char HBL = 1;
  unsigned char TFBC = 1;
  unsigned char GAI = 0;
  unsigned char STB0 = 1;
  unsigned char HB3 = 0;
  unsigned char HB2 = 1;
  unsigned char HB1 = 1;
  unsigned char HB0 = 1;

//Horizontal Deflection
  unsigned char HDTV = 1;
  unsigned char VSR = 0;
  unsigned char ZERO = 0;
  unsigned char STB1 = 1; 
  unsigned char POC = 0;
  unsigned char PRD = 1;
  unsigned char VGA = 0;
  unsigned char ESS = 1;

//Vertical Deflection
  unsigned char OPC = 0;
  unsigned char VFF = 0;
  unsigned char LBM = 0;
  unsigned char DIP = 1;
  unsigned char OSO = 0;
  unsigned char SVF = 1;
  unsigned char EVG = 1;
  unsigned char DL= 1;

Sezione di unione delle variabili in Byte

  unsigned char RGB1= MAT<<7 | EBB<<6 | SBL<<5 | RBL<<4 | BLS<<3 | BKS<<2 | IE1<<1 | IE2<<0;
  unsigned char RGB2= MUS<<7 | FBC<<6 | OBL<<5 | AKB<<4 | CL3<<3 | CL2<<2 | CL1<<1 | CL0<<0;
  unsigned char WHD= HBL<<7 | TFBC<<6 | GAI<<5 | STB0<<4 | HB3<<3 | HB2<<2 | HB1<<1 | HB0<<0;
  unsigned char HD= HDTV<<7 | VSR<<6 | ZERO<<5 | STB1<<4 | POC<<3 | PRD<<2 | VGA<<1 | ESS<<0;
  unsigned char VD= OPC<<7 | VFF<<6 | LBM<<5 | DIP<<4 | OSO<<3 | SVF<<2 | EVG<<1 | DL<<0;

Il resto:

void setup()
{
  Wire.begin(); // inizializza bus i2c come Master
  Serial.begin(9600);

  //Verifica i numeri  
  Serial.println("BYTES Inviati");
  Serial.println();
  Serial.print("RGB1: ");
  Serial.println(RGB1);  
  Serial.print("RGB2: "); 
  Serial.println(RGB2);
  Serial.print("WHD: ");
  Serial.println(WHD);
  Serial.print("HD: ");
  Serial.println(HD);
  Serial.print("VD: ");
  Serial.println(VD); 
  Serial.println();
}

void loop()
{  
    Serial.print("Gli OUTPUT bytes sono questi: "); 
  Wire.requestFrom(70,3); //all'integrato con indirizzo 70 richiedi 3 byte
  
  while(Wire.available())    // slave may send less than requested
  {
    int c = Wire.read();    // receive a byte as character
    String Bytes = String(c,BIN);
    Bytes = (Bytes + " ");
    Serial.print(Bytes);         // print the character
  }
       Serial.println();
       Serial.println();
       delay(50000);
}


void WriteAllBytes()
{
   Wire.beginTransmission(70); // transmit to device #70 (0x8c)
                              // device address is specified in datasheet
  Wire.write (RGB1&RGB2&WHD&HD&VD); //sends all bytes to device
  Wire.endTransmission();     // stop transmitting

  val++;        // increment value
  if(val == 64) // if reached 64th position (max)
  {
    val = 0;    // start over from lowest value
  }
  
  Serial.println( "INPUT Bytes inviati!");
}

Pensavo di controllare le funzioni come WriteAllBytes ed eventuali altre con un telecomando IR. Poi aggiornerò il codice e farò altre prove con il telecomando alla mano.

Grazie delle risposte!

Dopo verifico con l’analizzatore I2C che i bit inviati siano corretti e nel caso non funzioni come sperato, provo a trovare una soluzione e nel caso vi riscrivo

Andrea

Testato con l’analizzatore logico e funziona. Grazie! :slight_smile:

Per alleggerire l'uso della memoria SRAM, invece di:
unsigned char MAT = 0;
fai
#define MAT 0