Arreglos de comunicación serie y lectura de bytes con Arduino

5

Estoy estableciendo una conexión serial con mi Arduino. Para obtener datos de ellos, debo enviar datos en forma de matrices de bytes. Puedo enviar el comando y leer el ACK. Pero no puedo averiguar cómo obtener los datos después del ACK.

La documentación del desarrollador para el protocolo que estoy usando dice que va: comando para acceder a los datos - > ACK REPONSE - > DATOS

No puedo averiguar cómo obtener los datos después de la respuesta de acuse de recibo. Debe ser una matriz de bytes de 14 valores hexadecimales.

Este es mi código

byte GetData[] = {0x02,0x12,0x00}
byte GetDataACK[] = {0x02,0x06,0x06,0x06,0x06,0x06}; 

void setup(){

  Serial.begin(9600); 
  Serial.write(GetData,sizeof(GetData)); //Send the byte array
  delay(200); 
  if(Serial.available() > 5) {
    for(int i=0;i<6;i++){
      if(ackmodule[i]!=Serial.read()){
        // Do something
      }
    }
  }

}

void loop(){

}  
    
pregunta Nick T

2 respuestas

2

¿No debería estar parte de ese código dentro de loop() ? Específicamente, ¿todo menos Serial.begin(9600) ? De todos modos, este código no funcionará porque no se define ackmodule . ¿Se supone que es GetDataACK ? También es una buena idea implementar manejo de errores , especialmente cuando se tiene que depurar, como esto:

  if(Serial.available() > 0) {
    received_byte[i] = Serial.read();
    if(received_byte[i++] == -1) {  // no data available
      // error handling
    }
  }

No estoy seguro de qué tipos son compatibles las bibliotecas Arduino sketch , pero i puede ser simplemente unsigned char (yo lo llamaría uint8_t ) en lugar de un completo 16- número de bit ( int ). Como mencionó Chris Stratton, hay mejores maneras de esperar a los personajes; por ejemplo, el ejemplo de manejo de errores, o esto:

while(Serial.available() < 5) {}; // 5 can be 0 to fetch 1 char at a time

Esto se puede implementar sin la biblioteca de esta forma:

char rx()
{
        while ((UCSRA & (1<<RXC)) == 0) {};
        return UDR;
}

... Llamándolo con algo como char nextbyte = rx() . El tutorial serial de Arduino está aquí.

    
respondido por el tyblu
0

Si solo desea enviar el comando una vez al inicio, y luego lea la respuesta que desea hacer:

byte GetData[] = {0x02,0x12,0x00}
byte GetDataACK[] = {0x02,0x06,0x06,0x06,0x06,0x06}; 

void setup(){   
  Serial.begin(9600); 
  Serial.write(GetData,sizeof(GetData)); //Send the byte array    
}

void loop(){
  if(Serial.available() > 5) {
    for(int i=0;i<6;i++){
      if(GetDataACK[i]!=Serial.read()){
        // Do something
      }
    }
  }    
}  

Ahora no estoy seguro de lo que estás tratando de lograr con la declaración de bucle if interna, pero a mí me parece al revés. ¿No solo querría "hacer algo" después de haber leído con éxito los datos Ack? Creo que lo que realmente quieres es una pequeña máquina de estado:

#define DATA_LENGTH           14 // or whatever the length of your data segment is

#define STATE_IDLE            0
#define STATE_SEND_COMMAND    1
#define STATE_WAITING_FOR_ACK 2
#define STATE_GET_DATA        3

byte GetData[] = {0x02,0x12,0x00}
byte GetDataACK[] = {0x02,0x06,0x06,0x06,0x06,0x06}; 
byte RxData[DATA_LENGTH] = {0};
byte state = STATE_SEND_COMMAND;

void setup(){   
  Serial.begin(9600); 
  state = STATE_SEND_COMMAND;            // redundant
}

void loop(){
  switch(state){
  case STATE_IDLE: break;
  case STATE_SEND_COMMAND:
     Serial.write(GetData,sizeof(GetData)); //Send the byte array             
     state = STATE_WAITING_FOR_ACK;
     break;
  case STATE_WAITING_FOR_ACK:
     if(Serial.available() > 5) {
        for(int i=0;i<6;i++){
           if(GetDataACK[i]!=Serial.read()){
           // ACK doesn't match what you expect
           // you should go to some other state at this point
           // i'll just send you to idle
              state = STATE_IDLE;
              break;
           }
        }
     }
     break;
  case STATE_GET_DATA:
     if(Serial.available() > DATA_LENGTH) {
        for(int i = 0; i < DATA_LENGTH; i++){
           RxData[i] = Serial.read();
        }

        // congratulations you have data in your array
        // presumably now you want to something with it

        // and then switch back to some other state
        // i'll send you back to IDLE :)
        state = STATE_IDLE;
        break;
     }       
  }      
}  
    
respondido por el vicatcu

Lea otras preguntas en las etiquetas