Bit, byte e conversioni

Forse mi sto perdendo in un bicchiere d'acqua, però non ci arrivo.

Ho una String formata da tre bytes, cioè 24 caratteri scritti letteralmente in binario.
Questo perché leggo una cella di carico con la HX711 in binario e la leggo così:

    for (int i = 0; i <= 23; i++) {

      digitalWrite (SCK, HIGH); // SCK
      data = digitalRead (DATAIN); // DATA
      digitalWrite (SCK, LOW);  // SCK
      StringOne = String(StringOne + String(data));

    }

Ora questi bit li devo sparare ad un PLC su un suo ingresso, opportunamente temporizzato (e questo non è un problema), ma vorrei un metodo semplice per trasmettere il primo bit a sinistra, poi il secondo, poi il terzo eccetera.

All'inizio, con un programma PLC di poche righe, era semplicissimo: leggevo il bit dalla HX711 e lo trasmettevo paro-paro al PLC. E funziona alla grande.
Però se le righe di programma del PLC aumentano il PLC, giustamente, rallenta e questo metodo non va più bene perché nel frattempo la HX711 si spegne (questo succede se il CLK sta spento troppo a lungo, dove "lungo" significa millisecondi o anche meno...)

Allora leggo tutto il peso (e cioè 24 bit) e poi, con "calma", lo ritrasmetto al PLC

  • Con bitRead non sarebbe male, ma ho una String e non una int.
    Ma se converto questa String in una int con String.toInt () non ottengo un numero binario ma una cifra senza senso:
000001010101011001001111     -1946532713
000000101101001001010000     588907344
000000100110011110001111     1387006423

Qualche idea?

Ciao Steve,

perchè usi una String per salvare il valore del bit di ritorno dall'HX711?

Non lo so, è la prima cosa che mi è venuta in mente.
Come faresti a memorizzare un byte direttamente bit per bit?

E poi come lo rileggo per rispedirlo?

Ci sono le macro bitSet() e bitClear()

bitSet() - Arduino Reference

Grazie mille.

    for (int i = 0; i <= 23; i++) {

      digitalWrite (SCK, HIGH); // SCK
      data = digitalRead (DATAIN); // DATA
      digitalWrite (SCK, LOW);  // SCK
      StringOne = String(StringOne + String(data));
      bitSet (cifra, i);

    }

Però perché "cifra" mi da sempre -1 ?

No, la facevo troppo semplice... :grinning:

Penso vada scritto così...

  if (digitalRead (DATAIN) == LOW) {
    for (int i = 0; i <= 23; i++) {

      digitalWrite (SCK, HIGH); // SCK
      data = digitalRead (DATAIN); // DATA
      digitalWrite (SCK, LOW);  // SCK
      StringOne = String(StringOne + String(data));
      if (data == 1) bitSet (cifra, i);
      if (data == 0) bitClear (cifra, i);
    }

Però anche qui ho numeri senza senso e non ho dei bit

000000100110011101000000     -6592
000000100110011101101110     -6592
000000100110100110011000     -27072
000000100111001111110011     -12736
000000100111001110111010     -12736
000000101000011111110100     -7872
000000110101010101011100     -21824
000001001101011001100111     27424

Sprecone una String con un bit per ogni carattere. :grinning:

uint32_t bitBuff = 0;  // deve essere azzerata prima di eseguire il for.
bitBuff = 0;

for (int i = 0; i < 24; i++) {

      digitalWrite (SCK, HIGH); // SCK
      data = digitalRead (DATAIN); // DATA
      digitalWrite (SCK, LOW);  // SCK
      bitBuff |= (data << i);

    }

Se vuoi i bit memorizzati partendo da 23 ti serve il for che parte da 24 e termina con i>0 e data << i-1.
Faccio prima a riscriverlo:

for (int i = 24; i >0; i--) {

      digitalWrite (SCK, HIGH); // SCK
      data = digitalRead (DATAIN); // DATA
      digitalWrite (SCK, LOW);  // SCK
      bitBuff |= (data << i-1);

    }

Ciao.

Grazie mille agli intervenuti, per adesso, però il risultato è così...

000000101111101100000110     4294966022
000000101100010000100101     4294951973
000001010011111101100000     16224
000001010000001111100011     995
000000110011110100011011     15643
000001100100101100110010     19250
000001010101110010000101     23685
000000101010001100100101     4294943525


io pensavo, ma scusatemi se sbaglio, di avere la "fotocopia" della stringa StringOne però in formato decimale, sicuramente long, e da qui io con bitRead sparavo i vari 1 e 0 all'uscita di Nano verso il PLC...

ciao

scusa fa una cosa...stampa man mano i bit che ti arrivano e poi quello che hai registrato e confronta i due formati....almeno così ti togli il dubbio se gestisci le posizioni dei bit correttamente...

Così?

0     0
00     0
000     0
0000     0
00000     0
000000     0
0000001     0
00000010     0
000000100     0
0000001001     16384
00000010011     24576
000000100110     24576
0000001001100     24576
00000010011001     25600
000000100110011     26112
0000001001100111     26368
00000010011001111     26496
000000100110011111     26560
0000001001100111111     26592
00000010011001111111     26608
000000100110011111111     26616
0000001001100111111110     26616
00000010011001111111101     26618
000000100110011111111010     26618

Il codice ora è così

    for (int i = 24; i > 0; i--) {

      digitalWrite (SCK, HIGH); // SCK
      data = digitalRead (DATAIN); // DATA
      digitalWrite (SCK, LOW);  // SCK
      StringOne = String(StringOne + String(data));
      bitBuff |= (data << i-1);

    Serial.print (StringOne); Serial.print ("     "); Serial.println (bitBuff);
      
    }

Sicuro di avere usato uint32_t, perché a me sembra tu abbia usato int che è grande 16 bit sulla uno.

Ciao.

ho usato uint32_t oppure anche long

La lettura dei 24 bit è corretta, è la conversione che non ha senso...

24   0
23   0
22   0
21   0
20   0
19   0
18   1
17   0
16   0
15   1
14   1
13   0
12   1
11   0
10   0
9   0
8   0
7   0
6   1
5   1
4   0
3   0
2   0
1   1
000000100110100000110001     26673

A questo valore ci manca il bit18 acceso infatti se lo accendi ottieni 157745 che dovrebbe essere il valore corretto.

Ciao.

26673 prende solo i primi 16 bit da destra a sinistra...in pratica è un INT16...e ti perdi i 00000010
da sinistra a destra

anche "data" è INT32...giusto?

Quando leggi bit per bit dall'HX711 devi spegnere gli interrupt o comunque usare ATOMIC_BLOCK.

Ciao.

Pubblica sempre tutto il codice, così è possibile vedere anche i tipi delle variabili! :slight_smile: