Conversione Binario in Esadecimale

Salve, sto provando un circuito utilizzando un Shift-Register74HCT595 ma mi stò incartando... esso accetta in ingresso solo Byte in Esadecimale.... mentre riesco a convertire con bitWrite, una serie di 8 variabili boolean in un byte binario utilizzato correttamente con un PCF8574, non riesco a capire come convertire questo risultato binario in un esadecimale da inviare ad un 74HCT595..... qualcuno può cortesemente darmi qualche dritta? grazie

Di solito, quando ci sono problemi con l'esadecimale in realtà è per come bisogna dividere le cifre...

  1. Se posti il codice magari vediamo dove ti incarti.
  2. Un byte è un byte. 8 bits. Che poi lo puoi stampare a video come sequenza 8 bits, decimale o esa è solo una rappresentazione umana. I chip lavorano a bit.
  3. Se hai 8 valori boolean separati in variabili varie è più lungo, se sono invece 8 boolean in un unico array/vettore è più semplice/corto

Es.

byte val=0;
bool arrB[8]={true,false,true,false,true,false,false,true} ;  
// b10101001  = 169  = 0xA9
//  01234567  indice array, x bitSet devi invertire sequenza da 7 a 0
for(int i=0;i<8;i++)
{ if(arrB[i]==true) bitSet(val,7-i) ;
}

questo è il codice....

void controllo_Periferiche() {

#ifdef Debug
  //Serial.println(F("Effettuo Controllo Periferiche..."));
#endif
 
  byte cBit = 0;

  if (cBeeper) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 0, cBit); 

  if (cBlocco) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 1, cBit);

  if (cAvviamento) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 2, cBit); 
  
  if (cLuci) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 3, cBit);

  if (cSirena) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 4, cBit); 

  if (cUtenze) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 5, cBit); 

  if (cModem) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 6, cBit); 
  
  if (cAllarme) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 7, cBit); 
 
   
  delay(100);
          
  // se il Byte è cambiato eseguo Trasmissione
  if (cByte != cLast_Byte)
    {  
    
       #ifdef Debug
        Serial.println("Beeper      : " + String(cBeeper));
        Serial.println("Blocco      : " + String(cBlocco));
        Serial.println("Avviamento  : " + String(cAvviamento));
        Serial.println("Luci        : " + String(cLuci));
        Serial.println("Sirena      : " + String(cSirena));
        Serial.println("Utenza      : " + String(cUtenze));
        Serial.println("Modem       : " + String(cModem));
        Serial.println("Allarme     : " + String(cAllarme));
        Serial.println(F(""));

        Serial.println("cByte = " + String(cByte, BIN));
        Serial.println("cLast_Byte = " + String(cLast_Byte, BIN));
    
      #endif
       
      cLast_Byte = cByte; 
      updateShiftRegister();      // invio il valore corrispondente cByte
      
      delay(100);
   } 
   
} // END controllo periferiche ********************
void updateShiftRegister()
{
 
  digitalWrite(Pin_Latch, LOW);
  shiftOut(Pin_Data, Pin_Clock, MSBFIRST, cByte);  
  digitalWrite(Pin_Latch, HIGH);
  
}

le uscite del 74HCT595 si accendono in modo strano... si accendono tutte escluso l'ultima....
inoltre, come posso fare per evitare che in fase di caricamento tutte le uscite sono a livello alto anche se nel setup cerco di mettere le stesse tutte a livello basso?

pinMode(Pin_Latch, OUTPUT);
  pinMode(Pin_Data, OUTPUT);
  pinMode(Pin_Clock, OUTPUT);
  pinMode(Pin_Open, OUTPUT);
  pinMode(Pin_Close, OUTPUT);
  pinMode(Pin_Porta, INPUT_PULLUP);
  pinMode(Pin_Telec, INPUT_PULLUP);
  pinMode(Pin_RF_Interno, INPUT_PULLUP);
  pinMode(Pin_Status_Door, INPUT);
  pinMode(Pin_Chiave, INPUT);
  pinMode(Pin_TX, OUTPUT);
    
  digitalWrite(Pin_Open, LOW);
  digitalWrite(Pin_Close, LOW);

  digitalWrite(Pin_Latch, LOW);
   
  cByte = 0x00;
  updateShiftRegister();      // invio il valore 0 (0000 0000 Binario oppure 0x00 esadecimale)



  // Pin Out 74HCT595N
      
      0; //   pin 1  - Uscita Beeper
      1; //   pin 2  - Uscita Blocco Motore 
      2; //   Pin 3  - Uscita Avviamento 
      3; //   pin 4  - Uscita Luci  
      4; //   pin 5  - Uscita Sirena
      5; //   pin 6  - Uscita Utenze  
      6; //   pin 7  - Uscita Modem CAM                             
      7; //   pin 8  - Uscita Allarme

questo è il monitor seriale:

Serial Monitor avviato regolarmente....
Sistema Disarmato....
Beeper : 0
Blocco : 0
Avviamento : 1
Luci : 0
Sirena : 0
Utenza : 1
Modem : 0
Allarme : 0

cByte = 100100
cLast_Byte = 11111111

Hai sbagliato a collegare lo shift register

vedi un po' qui...

 // tutta questa roba...
  byte cBit = 0;

  if (cBeeper) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 0, cBit); 

  if (cBlocco) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 1, cBit);

  if (cAvviamento) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 2, cBit); 
  
  if (cLuci) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 3, cBit);

  if (cSirena) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 4, cBit); 

  if (cUtenze) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 5, cBit); 

  if (cModem) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 6, cBit); 
  
  if (cAllarme) { cBit = 1; } else { cBit = 0; }
  bitWrite(cByte, 7, cBit); 
 
   
// potrebbe dicentare così...
bitWrite(cByte, 0, cBeeper);
bitWrite(cByte, 1, cBlocco);
bitWrite(cByte, 2, cAvviamento);
bitWrite(cByte, 3, cLuci);
bitWrite(cByte, 4, cSirena);
bitWrite(cByte, 5, cUtenze);
bitWrite(cByte, 6, cModem);
bitWrite(cByte, 7, cAllarme);
// ammesso che le varie variabili siano bool
// altrimenti ci sono comunque strade migliori della tua...

ti consiglio vivamente di lasciar stare "inutilità" come nomi camelCase (che fanno schifo a vedersi)
e concentrarti di più sulla "programmazione dura e pura"

anche il tuo uso inutile di oggetti Stringa denota solo una scarsa "attenzione" al problema

ricordo la
Prima legge di Nelson (che sono io): A parità di risultato maggiore è il pensiero, minore il lavoro. Quindi prima di fare pensa!

O, comunque, possano assumere solo i valori 0 e 1.

Grazie per i consigli, Standaroil.... cmq il risultato non cambia, credo che lo shift register sia collegato regolarmente infatti, se carico un semplice sketch con il led che scorre, funziona.... all'accensione i led sono tutti spenti e poi iniziano a scorrere... invece con il mio Sketch, all'inizio si accendono tutti (anche se invio un byte 0 o 0x00 nel setup) mentre successivamente, inviando un valore di 100100 rimane spento solo il led collegato al pin 15 (q0) .... anzichè rimanere acceso solo i led q2 (Avviamento) e q5 (Utenze)... non capisco inoltre, perchè il byte che si compone e che invio è formato da 100100 anzichè 00100100...

PS :roll_eyes:non ho capito la "scarsa attenzione al problema" per l'uso inutile di oggetti Stringa.... :sweat_smile: come posso fare il debug sul monitor seriale?
grazie di nuovo...

ho provato questo semplice sketch...

const int Pin_Data        = 10; // pin 2   13    D10     Outpu Signal Data   
const int Pin_Latch       =  9; // pin 3   12    D9      Outpu Signal Latch    
const int Pin_Clock       =  8; // pin 5   11    D8      Outpu Signal Clock

byte cByte = 0;    // Variable to hold the pattern of which LEDs are currently turned on or off

void setup() {
 Serial.begin(9600);
   
  pinMode(Pin_Latch, OUTPUT);
  pinMode(Pin_Data, OUTPUT);
  pinMode(Pin_Clock, OUTPUT);
}

void loop() 
{ 
  Serial.println("Tutto Spento....");
  cByte = 0; 
  updateShiftRegister();
  delay(5000);
  bitWrite(cByte, 0, false);
  bitWrite(cByte, 1, false);
  bitWrite(cByte, 2, true);
  bitWrite(cByte, 3, false);
  bitWrite(cByte, 4, false);
  bitWrite(cByte, 5, true);
  bitWrite(cByte, 6, false);
  bitWrite(cByte, 7, false);  

  Serial.println("Acceso solo Q2 e Q5..." + String(cByte, BIN));
  updateShiftRegister();
  delay(10000);
}

void updateShiftRegister()
{
   digitalWrite(Pin_Latch, LOW);
   shiftOut(Pin_Data, Pin_Clock, MSBFIRST, cByte);
   digitalWrite(Pin_Latch, HIGH);
}

cosa è sbagliato visto che i led rimangono sempre tutti spenti?

bitWrite (Byte, bit_n, val=1)
è semplicemente uguale a
Byte |= 1<<bit_n;

oppure, per val=0:
bitWrite (Byte, bit_n, val=0)
è uguale a
Byte &= ~(1<<bit_n);

Qui, d'altra parte, trovi il sorgente di bitWrite:

:hot_face: perdonami ma, potresti essere più 'terra terra' :blush: sto cercando ci capire come fare per inviare un comando allo Shift Register in modo da accendere solo i led interessati....
questo esempio funziona regolarmente e accende i led in modo sequenziale....

const int Pin_Data        = 10; // pin 2   13    D10     Outpu Signal Data   
const int Pin_Latch       =  9; // pin 3   12    D9      Outpu Signal Latch    
const int Pin_Clock       =  8; // pin 5   11    D8      Outpu Signal Clock

byte n = 0x01;  //0000 0001

void setup() {
 Serial.begin(9600);
   pinMode(Pin_Latch, OUTPUT);
  pinMode(Pin_Data, OUTPUT);
  pinMode(Pin_Clock, OUTPUT);
}

void loop() 
{ 
  for (int i = 0; i < 8; i ++) {
    updateShiftRegister();
    n = n << 1; 
    delay(1000);
  }
  n = 0x01;
}

n = n << 1;
fa scorrere n a sinistra di un bit alla volta. Se n=1:
0000 0001
0000 0010
0000 0100
...

Se n=5, cioè 0b0000 0101 o 0x05:
0000 0101
0000 1010
0001 0100
...

Quindi, per esempio:

const int Pin_Data        = 10; // pin 2     13    D10     Outpu Signal Data   
const int Pin_Latch       =  9; // pin 3   12    D9      Outpu Signal Latch    
const int Pin_Clock       =  8; // pin 5   11    D8      Outpu Signal Clock

byte cByte = 0x05;  // 0000 0101

void setup() {
  Serial.begin(9600);
  pinMode(Pin_Latch, OUTPUT);
  pinMode(Pin_Data, OUTPUT);
  pinMode(Pin_Clock, OUTPUT);
}

void loop() 
{ 
  for (int i=0; i<9; i++) {
    updateShiftRegister(n);
    cBye = cByte<<1; 
    delay(1000);
  }
 cByte = 0x05;
}

dovrebbe farti scorrere a sinistra due LED spaziati di uno fino a uscire.

Serve la funzione!

void updateShiftRegister()
{
   digitalWrite(Pin_Latch, LOW);
   shiftOut(Pin_Data, Pin_Clock, MSBFIRST, cByte);
   digitalWrite(Pin_Latch, HIGH);
}

Ma updateShiftRegister non vuole un valore?...
updateShiftRegister (n);

No: usa variabili globali, tra cui cByte in cui va inserito il valore da assegnare alle uscite.

... ho capito lo scorrere dei bit ma .... non capisco se si può fare un comando che accende solo i led a me interessati....
precedentemente ho lavorato un po con PCF8574 o MCP 23008 ma lavorano tramite i2c e con arduino o ESP32 non ho avuto problemi.... in considerazione che vorrei utilizzare un processore come attiny84 non riesco a trovare una libreria funzionante per questo processore in modalità master quindi sto cercando un alternativa per ampliare le uscite dell'Attiny, senza utilizzare librerie troppo pesanti perchè altrimenti vado fuori con le memoria a disposizione.... ma ora ho il dubbio che il 74HC595 non sia idoneo allo scopo....

Sì!

updateShiftRegister(0b01001100);

No! Deve essere così:

cByte=0b01001100;
updateShiftRegister();

Prova a mettere nel setup() questo:

  cByte = 0xff;  // 255 decimale
  updateShiftRegister(); 

Se tutti i led ti risultano spenti allora devi invertire il collegamento dei
led, cioè tutti i catodi dei led a GND.

Per quanto riguarda la rappresentazione binaria, esadecimale o ottale, considera che sono appunto rappresentazioni: I dati nella memoria sono sempre sotto forma di collezioni di bit.

Qui c'è il primo convertitore online che ho trovato, ma se cerchi ne trovi molti altri:

Ciao.

Oppure

for(int i=7; i>=0; i--)
  {
  val |= arrB[i]<<i;
  }

Manca l'argomento!
updateShiftRegister(cByte);

No, perché il valore va inserito nella variabile globale cByte.