Arduino ShiftOut tramite porta seriale - Help!

Scusate ragazzi ho un problema con questo codice, praticamente io gli invio una serie tipo "0b00110011" tramite php ad arduino,
però praticamente, quando invio il messaggio, i led si spengono, si accendono 3 led (che non corrispondono al messaggio) e poi si riaccendono tutti i led e rimangono così fin quando non invio dell'altro.
Ma come is fa a fargli cambiare stato solo quando invio qualcosa tramite seriale?
questo è il codice:

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
   Serial.begin(9600);
}

void loop() {
  if (Serial.read())
  {
    digitalWrite(latchPin, LOW);
    // shift out the bits:
    shiftOut(dataPin, clockPin, MSBFIRST, Serial.read());  
    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);
    // pause before next value:
    delay(500);
  }
}

Usi in modo errato la funzione serial read.

  1. non controlli se ci sono dati nel buffer della seriale
  2. leggi un dato del buffer e poi mandi al shift register un altro dato letto nel secondo serial read.

devi controllare se sono dati disponibili nel buffer (con serial.aviable()) e poi leggere il dato e mandarlo sul 595.

Ciao Uwe

In pratica l'errore è qui:

if (Serial.read())

Questo dice di estrarre un carattere dalla seriale, non di controllare se c'è un carattere e basta. Quindi come ti ha spiegato Uwe il primo carattere che arriva lo perdi per strada perché esso non viene assegnato a nessuna variabile ma usato come test per l'if.

ah non lo sapevo xD Grazie mille :slight_smile:

Ma cmq vedo un comportamento anomalo XD
mi spiego,
io invio la serie di bit
ad esempio con 0b10000001 si accendono due led (che non mi sembrano il 1° e l'ultimo) mentre 2 led rimangono accesi sempre, dopo mezzo secondo di delay torna tutto spento tranne i due led perenni, invece senza delay i led che comando si accendono e si spengono così velocemente che quasi non si vedono e i due led perenni continuano ad essere accesi.
Potreste darmi un aiuto? xD

Dacci il Sketch da te modificato.
Ciao Uwe

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
   Serial.begin(9600);
}

void loop() {
  if (Serial.available())
  {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, Serial.read());  
    digitalWrite(latchPin, HIGH);
    // non credo serva il delay, dato che aspetta un altro valore 
    // delay(500);
  }
}

Inizia con un pò di debug altrimenti non riuscirai ad isolare il problema.
Cioè, cerchiamo di capire se il dato arriva corretto ma viene scritto male oppure non arriva per niente.

Quindi modifica il loop() così:

void loop() {
  if (Serial.available()) {
    digitalWrite(latchPin, LOW);
    byte temp = Serial.read();
    Serial.println(temp); //eco per vedere cos'è stato ricevuto
    shiftOut(dataPin, clockPin, MSBFIRST, temp);  
    digitalWrite(latchPin, HIGH);
  }
}

si penso che sia un problema di come invia la variabile .
io ho inviato "0b10000001" e sul monitor seriale mi ha stampato

48
98
49
48
48
48
48
48
48
49

è normale? XD
Inoltre comunque i led 5 e 6 rimangono sempre accesi, sarà un problema di arduino? c'è un modo per spegnerli?

Se hai spedito "0b10000001" con Serial.print è normale. La Serial ha trattato il dato come stringa per cui l'ha spedita byte per byte, e quelli che vedi sono i codici ASCII dei singoli caratteri che componevano quella stringa.

Devi usare

Serial.write(0b10000001)

e ti verrà spedito il byte corrispondente a quel valore.

si ora sul monitor esce esattamente ciò che scrito, ovvero "0b10000001", ma arduino non cambia comportamento

Codice please

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
   Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    digitalWrite(latchPin, LOW);
    byte temp = Serial.read();
    Serial.write(temp); //eco per vedere cos'è stato ricevuto
    shiftOut(dataPin, clockPin, MSBFIRST, temp);  
    digitalWrite(latchPin, HIGH);
  }
}

Ma "come" vengono spediti questi dati?
Se non spedisci in formato byte, siamo punto e a capo. :wink:

io scrivo 0bxxxxxxxx questo non è il formato byte?

up

Ascolta, Se io metto un Serial.write(1) sul monitor seriale dell'Arduino leggo un carattere senza senso, corrispondente al byte di valore 1, non leggo 0b00000001.
Quindi io temo che il tuo programma lato PC non spedisca i dati in formato byte.

Elimina per ora questo problema e modifica il tuo programma così:

void loop() {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, 0b10101010);  
  digitalWrite(latchPin, HIGH);
  delay(500);
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, 0b01010101);  
  digitalWrite(latchPin, HIGH);
  delay(500);
}

Ti deve accendere i led alternativamente. Se così funziona, il problema sta nella comunicazione fra PC ed Arduino, altrimenti hai sbagliato i collegamenti dei registri all'Arduino.

Si così funziona bene XD
Quindi cosa sbagliavo?
cioè se invio la sequenza tramite seriale, non devo scrivere così?

shiftOut(dataPin, clockPin, MSBFIRST, Serial.read());

Probabilmente tu non invii il dato in formato numerico.
Io non conosco PHP per cui non so come ragiona. Se scrivi print(1) sulla seriale esso cosa spedisce? una stringa di valore "1" oppure un byte di valore 1?

si in effetti in php io invio una stringa "0bxxxxxxxx" non invio numeri