Seriale Arduino

Ciao a tutti!
Ho un problema per quanto riguarda la porta seriale di arduino. Ho fatto un programma che dovrebbe, tramite due comandi seriali, accendere due led e farli lampeggiare( uno con il millis e uno no), il problema è che non riesco a capire perchè mi lampeggia un led solo per volta mentre io li vorrei in contemporanea. posto il codice e ringrazio per un eventuale risposta.

int inByte = 0;
int stato,stato1 =0;

int flash = 0;
const int ledPin = 7;

int ledState = LOW;
long previousMillis = 0;

long interval = 1000;
void setup()
{

Serial.begin(9600);
pinMode(9, OUTPUT);
pinMode(ledPin, OUTPUT);
}

void loop()
{

if (Serial.available() > 0) {

inByte = Serial.read();

stato = inByte;
stato1 = inByte;

}
if (stato1 == 'h') {
if (flash == 0) {
flash = 1;
digitalWrite(9, LOW);
}
else {
flash = 0;
digitalWrite(9, HIGH);
}

delay(250);

}

if (stato == 'f') {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {

previousMillis = currentMillis;
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(ledPin, ledState);
}
}
}

ciao,
il problema è qui

if (Serial.available() > 0)
{
    inByte = Serial.read();
    stato = inByte;
    stato1 = inByte;
}

stato e stato1 sono sempre uguali

dovresti fare una cosa del genere

if (Serial.available() > 0)
{
   stato = Serial.read();
   delay(2); //giusto per essere sicuro che sia arrivato anche il secondo byte
   stato1 = Serial.read();
}

avendo l'accortezza di trasmettere sempre due caratteri alla volta

Ciao ho letto questo post e visto che ho trovato lo stesso problema aggiungo;
ma se non voglio mandare due caratteri per volta come posso risolvere???
fidelpoli2 ha la necessita di usare solo 2 uscite ma se ne volessi usare 10 come posso fare?
La mia idea sarebbe quella di gestirle tipo interrupt mi spiego non è possibile con arduino una volta entrata in un if lo continui a fare all'infinito fina a che tramite un altro if lo spengo?

Nessuno sa risolvere questo problema?
Ho fatto delle prove anche con i case, ma non riesco a risolvere, una volta entrato nel case mi fa lampeggiare il led solo per un numero di volte e poi si spenge
Grazie

ho una mezza idea in testa, però in questo periodo sono un po' fuso per il lavoro. Se riesco butto giù qualche riga di codice nel fine settimana

Ti ringrazio per l'aiuto sto diventando pazzo ho letto praticamente tutti i post di questo forum
Sicuramente per i non programmatori come me questo forum è una nave scuola notevolissima e quello che colpisce è che nonostante gran parte delle domande fatte da noi "principianti" siano per un guro sciocche tutti abbiamo sempre le proprie risposte
Un grazie sentito a tutte le persone che con pazzienza portano avanti questo progetto open source :wink: :wink:

la giusta correzione sarebbe:

if (Serial.available() > 1)//ci devono essere ALMENO 2 byte disponibili, per più bite basta modificare... e per la lettura usare un'array di stati e un for...
{
   stato = Serial.read();
//via il delay!
   stato1 = Serial.read();
}

secondo problema:
ochhio che se interval è < del delay succedono casini :slight_smile:
consiglio vivamente di imparare a usare i millis, si sprecano molti meno clock :slight_smile:

@lesto
è sì, togliere il delay e aspettare di ricevere due caratteri è molto meglio e "un po' " più sicuro

@ARDUIX
il seguente codice dovrebbe gestire 8 uscite in maniera indipendente tramite l'invio di un carattere da seriale. il "dovrebbe" è perché non l'ho testato fisicamente. Le 8 uscite possono avere tempi di accensione e spegnimento anche diversi

// variabili per la gestione delle uscite
const int num_output = 8;
int stato_uscita     = 0;      // indica se l'uscita n-esima è ON o OFF
int comando_uscita   = 0;      // indica se l'uscita n-esima è abilitata a lampeggiare
// i seguenti define servono solo a ricordare che l'uscita 1 è mappata sul primo bit, la 2 sul secondo e così via
#define      OUT_1      0x01
#define      OUT_2      0x02
#define      OUT_3      0x04
#define      OUT_4      0x08
#define      OUT_5      0x10
#define      OUT_6      0x20
#define      OUT_7      0x40
#define      OUT_8      0x80

// permette di utilizzare non necessariamente le prime 8 uscite digitali
int trascodifica_uscite[num_output] = { 4,      // OUT_1
                                            5,      // OUT_2
                                            7,      // OUT_3
                                           10,      // OUT_4
                                            9,      // OUT_5
                                           11,      // OUT_6
                                           12,      // OUT_7
                                           13};      // OUT_8

// variabili per le tempistiche
unsigned long istante_cambio_stato[num_output];
unsigned long tempo_on[num_output] = {200,      // OUT_1
                                                      200,      // OUT_2
                                                      200,      // OUT_3
                                                      200,      // OUT_4
                                                      200,      // OUT_5
                                                      200,      // OUT_6
                                                        200,      // OUT_7
                                                        200};      // OUT_8

unsigned long tempo_off[num_output] = {200,      // OUT_1
                                                        200,      // OUT_2
                                                         200,      // OUT_3
                                                         200,      // OUT_4
                                                         200,      // OUT_5
                                                         200,      // OUT_6
                                                         200,      // OUT_7
                                                         200};      // OUT_8
// variabili relative alla seriale
int serial_rx;
// elenco dei comandi
// i comandi per abilitare il blink devono essere consecutivi
#define      BLINK_OUT_1             int('a')
#define      BLINK_OUT_2             int('b')
#define      BLINK_OUT_3             int('c')
#define      BLINK_OUT_4             int('d')
#define      BLINK_OUT_5             int('e')
#define      BLINK_OUT_6             int('f')
#define      BLINK_OUT_7             int('g')
#define      BLINK_OUT_8             int('h')
// può esserci un buco tra i comandi di blink e di disabilitazione
// i comandi per disabilitare il blink devono essere consecutivi
#define      DISABLE_OUT_1      int('k')
#define      DISABLE_OUT_2      int('l')
#define      DISABLE_OUT_3      int('m')
#define      DISABLE_OUT_4      int('n')
#define      DISABLE_OUT_5      int('o')
#define      DISABLE_OUT_6      int('p')
#define      DISABLE_OUT_7      int('q')
#define      DISABLE_OUT_8      int('r')


void gestione_comandi(int serial_rx)
{
      if ((serial_rx >= BLINK_OUT_1) && (serial_rx <= BLINK_OUT_8))
      {
            comando_uscita |= (1 << (serial_rx - BLINK_OUT_1));
      }
      if ((serial_rx >= DISABLE_OUT_1) && (serial_rx <= DISABLE_OUT_8))
      {
            comando_uscita &= ~(1 << (serial_rx - DISABLE_OUT_1));
      }
}

void gestione_uscite()
{
      unsigned long currentMillis = millis();
      int i;
      
      for (i = 0; i < num_output - 1; i++)
      {
            if(comando_uscita & (1 << i))
            {
                  // l'i-esima uscita deve lampeggiare
                  if (stato_uscita & (1 << i))
                  {
                        // l'i-esima uscita è ON
                        if((currentMillis - istante_cambio_stato[i]) >= tempo_on[i])
                        {
                              digitalWrite(trascodifica_uscite[i], LOW);
                              stato_uscita ^= (1 << i);
                              istante_cambio_stato[i] = currentMillis;
                        }
                  }
                  else
                  {
                        // l'i-esima uscita è OFF
                        if((currentMillis - istante_cambio_stato[i]) >= tempo_off[i])
                        {
                              digitalWrite(trascodifica_uscite[i], HIGH);
                              stato_uscita ^= (1 << i);
                              istante_cambio_stato[i] = currentMillis;
                        }
                  }
                  
            }
            else
            {
                  // l'i-esima uscita deve essere disabilitata
                  digitalWrite(trascodifica_uscite[i], LOW);
            }
      }
}

void setup()
{
      byte i;
      
      for (i = 0; i < num_output - 1; i++)
      {
            pinMode(trascodifica_uscite[i], OUTPUT);
            digitalWrite(trascodifica_uscite[i], LOW);
      }
      Serial.begin(9600); 
}

void loop()
{
      if (Serial.available() > 0)
      {
            serial_rx = Serial.read();
            gestione_comandi(serial_rx);
      }
      gestione_uscite();
}

Ciao Frog, è 4 giorni che studio sul tuo codice e delle cose le ho capite bene e ti faccio i complimenti perchè io non ci sarei mai arrivato!Però ci sono delle cose che non riesco a capire:

if (stato_uscita & (1 << i)){ // è un puntatore?? (perchè se faccio la moltiplicazione di bit mi da sempre 0 e credo che non abbia significato)
if((currentMillis - istante_cambio_stato) >= tempo_on*)// cosa fa precisamente questo if? ho notato che quando si usa millis questa espressione è ricorrente{
digitalWrite(trascodifica_uscite, LOW);
stato_uscita ^= (1 << i);// anche in questo caso mi servono spiegazioni
istante_cambio_stato = currentMillis;// questo serve per resettare il millis???}
_}

else
{
// stesse cose del pezzo sopra _

if((currentMillis - istante_cambio_stato) >= tempo_off)
_{_
digitalWrite(trascodifica_uscite, HIGH);
stato_uscita ^= (1 << i);
istante_cambio_stato = currentMillis;
_}
}*_

dunque:
if (stato_uscita & (1 << i))controlle se l'i-esimo bit della variabile stato_uscita è uguale a uno
& è l'AND bit-a-bit
<< è l'operatore shift_a_sinistra

if((currentMillis - istante_cambio_stato[i]) >= tempo_on[i])se da quando mi sono acceso (istante_cambio_stato) è passato abbastanza tempo (>= tempo_on) sono pronto a spegnermi digitalWrite(trascodifica_uscite*, LOW).
stato_uscita ^= (1 << i);l'i-esimo bit della variabile stato_uscita viene cambiato di valore. (^ è lo XOR bit-a-bit)
Si poteva anche fare (in maniere probabilmente più leggibile)
stato_uscita &= ~(1 << i); in questa parte di codice e*

stato_uscita |= (1 << i); in quella successiva
istante_cambio_stato[i] = currentMillis;più che reset direi che è l'aggiornamento della variabile per tenere memoria dell'istante in cui l'uscita è stato accesa/spenta.
_*la spiegazione un po' più approfondita dei vari operatori ~, &, ... la trovi sulle reference http://arduino.cc/en/Reference/HomePage*_