valore numerico da un array e assegnazione a variabile intera

Onde evitare GROSSI problemi DEVI sempre verificare di non andare oltre lo spazio di memoria allocato, quindi il "do" va così corretto:

do
   {
       while( !Serial.available());
       inData[index] = Serial.read();
       delay(10);
       
   } while( (inData[index++] != '\n') && (index < 20) );

Guglielmo

il delay() peggiora la ricezione, è quindi da togliere!
Il perché è semplice, delay() per funzionare usa micros() che a sua volta per funzionare disattiva e riattiva in continuazione gli interrupt, questo fa si che si ha buona probabilità di ritardi nel prelevare il byte dal registro o comunque rallentamenti inutili.
ecco perché ho inserito

while( !Serial.available());

ovvero un ciclo che attende dati sulla seriale, se proprio si vuole introdurre un piccolo ritardo si può aggiungere un pò di NOP anche se per me sono inutili

while( !Serial.available()){
    uint8_t r = 16; //poco più di un us di ritardo
    do{ ASM_NOP; --r; } while( r > 0);
}

VB ... tu puoi dire quello che vuoi, ma considera che è una cosa provata e riprovata ...
... se NON metti quel delay(1); a volte NON funziona ... non ho ancora ben capito il perché, ma, pur essendoci caratteri nel buffer, spesso e volentieri esce dal while() :confused:

Sarà per come gestisce il buffer, sarà quel che sarà ... ma è così ...

Guglielmo

gpb01:
Sarà per come gestisce il buffer, sarà quel che sarà ... ma è così ...

Confermo, il motivo è proprio in come viene gestita la seriale da wiring, dato che la trasmissione seriale è lenta, sopratutto se fatta a bassi bps, è sempre possibile che viene fatto il controllo mentre in atto la ricezione di un byte, pertanto il relativo interrupt non è ancora settato e il controllo ritorna false anche se è in corso la ricezione.

secondo me state ragionando in maniera contraria a quello che fa il codice.
il ciclo while sul available controlla se ci sono dati nel buffer e rimane in tale ciclo fino a che non viene completata l'effettiva lettura del byte e quindi fino a che ci sono 0 byte nel buffer, mettiamo l'ipotesi che l'interrupt viene generato in mezzo alla available succederà che comunque available ritorna 0 e il ciclo continua, dunque si avrà semplicemente un secondo controllo un pò ridondante.

@gbp01 mostra il codice incriminato, posta un codice che possa riprodurre il problema, forse ti posso trovare la causa.
quello che ho postato io l'ho testato anche con baud a 500000 con 0% di errori!
Test eseguito per 24h consecutive con pacchetti da 128byte l'uno, alla ricezione veniva controllato il crc8 e rispediva il pacchetto al mittente che contava la percentuale di errore.
Quindi so quello che dico.

@ Torn24 Ho provato a caricare l'ultimo codice che hai postato e FUNZIONA non riesco a capire come mai il primo non funzionasse ma comunque Grazie! :slight_smile:

Ora però sto provando ad implementare il codice, l'obiettivo sarebbe quello di muovere un motorino passo passo in avanti quando da seriale invio la stringa "AVANTI" e fermarlo quando digito "STOP".

Ora però alla ricezione della stringa "AVANTI" il motorino parte ma non non riesco piu a fermarlo.
Il problema penso di averlo capito ma non capisco invece come rimediare.
In pratica ho fatto in modo che alla ricezione della stringa "AVANTI", l'array di caratteri si cancelli e venga chiamata una funzione avanti() dove all'interno di un ciclo while vengono eseguite le operazioni per far compiere al motorino uno step. Il ciclo idealmente dovrebbe interrompersi non appena viene ricevuta la stringa STOP. Il problema è che non riesco più ad uscire dal ciclo e la seriale non accetta più nessun input.
(P.S. vorrei evitare di utilizzare la libreria Stepper.h)
Qualche suggerimento? Grazie a tutti

Ecco il mio codice:

char inData[20];
char inChar;
byte index = 0;
int primoValore = 0;
int secondoValore = 0;
const int stepPin = 3;
const int dirPin = 4;
bool avantiStato;
bool stopStato;


void setup()
{
  Serial.begin(9600);
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  Serial.println("begin");
}

void loop() {

  int i = 0;
  char c;

  do
  {
    while ( !Serial.available());
    inData[index] = Serial.read();
    delay(10);

  } while ( (inData[index++] != '\n') && (index < 20) );

  inData[--index] = '\0';//sovrascrivo il \n

  index = 0;

  if (strcmp(inData, "AVANTI")  == 0)
  {
    avantiStato = true;
    stopStato = false;
    Azzera(inData);
    avanti();

  }

  else
  {

    for (i = 0; inData[i] != 0; i++)
    { // Scorre tutta la striga alla ricerca di 'A' O 'B'
      if (inData[i] == 'A' || inData[i] == 'B')
      {
        c = inData[i];
        break;//Esce dal for se trova A o B
      }
    }// end for

    if (c == 'A')
    {
      primoValore = PrelevaNumero(inData);
      Serial.println(primoValore);
      Azzera(inData);
    }
    else if (c == 'B')
    {
      secondoValore = PrelevaNumero(inData);
      Serial.println(secondoValore);
      Azzera(inData);
    }
  }//end else


}


int PrelevaNumero(char *s) {


  int i = 0, j = 0;
  char numero[10];
  for (i = 0; !(s[i] >= '0' && s[i] <= '9'); i++); // Trova inizio numero
  for (j = 0; s[i] != 0; j++, i++) {

    numero[j] = s[i];
  }

  numero[j] = 0; //terminatore stringa

  return atoi(numero);

}

void Azzera(char *s) {

  int i = 0;
  for (i = 0; i < 19; i++)
    s[i] = 0;
}

void avanti()
{
  while (avantiStato == true && stopStato == false)
  {
    digitalWrite(dirPin, HIGH);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1500);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1500);
    if (strcmp(inData, "STOP")  == 0)
    {
      stopStato = true;
    }
  }
}

perchè il tuo codice è bloccante e a te serve qualcosa di non bloccante.
ad esempio una cosa simile a questa:

/*** EXTRAS ***/
uint8_t _delayAsync(uint8_t id, uint32_t ms, uint32_t(*fnctime)(void))
{
    struct ellapsed
    {
        uint8_t id;
        uint32_t start;
        struct ellapsed* next;
    };
    static struct ellapsed* allDelay = NULL;
    struct ellapsed** ad;
    
    uint32_t now = fnctime();
    
    for( ad = &allDelay; NULL != *ad && (*ad)->id != id; ad = &(*ad)->next);

    if ( NULL == *ad )
    {
        struct ellapsed* newd = (struct ellapsed*) malloc( sizeof(struct ellapsed) );
            if ( NULL == newd ) return 0;
        newd->id = id;
        newd->start = now;
        newd->next = allDelay;
        allDelay = newd;
        return 0;
    }

    if ( fnctime() - (*ad)->start >= ms)
    {
        struct ellapsed* freed = *ad;
        *ad = (*ad)->next;
        free(freed);
        return 1;
    }
    return 0;
}

uint8_t sex_read(char* b, uint8_t sz)
{
    static char *br = NULL;

    if ( br == NULL ) br = b;
    
    if ( !Serial.available() ) return 0;

    *br = Serial.read();
    if ( *br == '\r' ) return 0;

    if (*br == '\n' )
    {
        *br = '\0';
        br = NULL;
        return 1;
    }
    
    ++br;
    if ( br - b >= sz -1 )
    {
        *br = '\0';
        br = NULL;
        return 1;
    }

    return 0;
}


#define delayAsync(MS) _delayAsync(__COUNTER__, MS, millis)
#define delayAsyncMicroseconds(MS) _delayAsync(__COUNTER__, MS, micros)


#define stropcmp(A,OP,B) ( strcmp(A,B) OP 0 )

/*** END EXTRAS ***/




#define MOTORE_STOP   0
#define MOTORE_AVANTI 1


uint8_t stato = MOTORE_STOP;
uint8_t vA = 0;
uint8_t vB = 0;
 char comando[20];

#define PIN_STEP 3
#define PIN_DIR  4



void setup()
{
  Serial.begin(9600);
  pinMode(PIN_STEP, OUTPUT);
  pinMode(PIN_DIR, OUTPUT);
  Serial.println("begin");
}

void parseComando(char* com)
{
    if ( stropcmp(com, ==, "AVANTI") )
    {
        stato = MOTORE_AVANTI;
        Serial.println("Motore Avanti");
    }
    else if ( stropcmp(com, ==, "STOP") )
    {
        stato = MOTORE_STOP;
        Serial.println("Motore Stop");
    }
    else
    {
        char* f = strchr(com,'A');
        if ( f ) vA = strtol(f+1,NULL,10);
        f = strchr(com,'B');
        if ( f ) vB = strtol(f+1,NULL,10);
        Serial.print("vA: ");
        Serial.println(vA);
        Serial.print("vB: ");
        Serial.println(vB);
    }
}

void motorRun(void)
{
    static uint8_t stepm = 0;
    
    if ( stato == MOTORE_AVANTI )
    {
        if ( stepm == 0 )
        {
            if ( delayAsyncMicroseconds(1500) )
            {
                digitalWrite(PIN_DIR, HIGH);
                digitalWrite(PIN_STEP, HIGH);
                stepm = 1;
                Serial.println("STEP H");
            }
        }
        else    
        {
            if ( delayAsyncMicroseconds(1500) )
            {
                digitalWrite(PIN_STEP, LOW);
                stepm = 0;
                Serial.println("STEP L");
            }
        }
    }
}

void loop() {
  
  if ( sex_read(comando,20) ) parseComando(comando);

  motorRun();
}

Grazie vbextreme il tuo codice funziona alla grande peccato solo che non saprei nemmeno aggiungere una virgola visto che un buon 80% di quello che hai scritto per me è arabo :frowning:

la parte contrassegnata come extras fai finta che sia il core Arduino, ovvero una sua estensione.
Quindi hai la funzione delayAsync() che ritorna 1 se il tempo in millisecondi è passato altrimenti 0, naturalmente delayAsyncMicroseconds() prende il tempo in microsecondi.

Poi hai sex_read() (Serial Extension) anch'essa lavora in modo asincrono , tu li passi un vettore di caratteri, la sua dimensione e lei ritorna 1 se ha letto una stringa terminata da '\n' altrimenti ritorna 0.

Infine hai la stropcmp() questa è la versione semplificata di strcmp.

Quindi il codice chiede a sex_read() se ha letto, in caso affermativo si richiama la funzione parseCommand() che analizzerà il comando e lo processera.
In caso negativo o comunque dopo il parsing del comando si va a richiamare la funzione che contiene il controllo motore, la funzione è asincrona, ovvero non blocca il ciclo del programma. Tale funzione controlla se il motore deve girare e in caso affermativo usa ha uno stato interno 0/1 che gli ricorda cosa deve fare.
In caso di stato 0 controlla se è trascorso il tempo e in caso affermativo alza i pin e cambia stato in 1.
In caso di stato 1 controlla se è trascorso il tempo , abbassa i pin e porta lo stato a 0.

meglio?