Go Down

Topic: Receber dados numéricos e texto enviado pelo Termianl do IDE arduino (Read 800 times) previous topic - next topic

tretas

Boas,

Ando aqui de volta de uma treta, que é o seguinte.

Queria enviar atravez do terminal.exe do arduino a seguinte trama

Texto1,numero1,numero2,numero3,texto2,numero4

(char[10],int numero1, int numero2, int numero3, char[5] texto2, int numero4)

escrever no terminal blabla,10,100,9,fdx,10

Mas como o terminal envia tudo em ascci não tou a ver como converter isso :(

Code: [Select]

 int x=0;
 char Buffer[8];
 memset(Buffer, '\0', 9);
 

 while (Serial.available()>0)
    {
     Buffer[x]=Serial.read();
     delay(10);
      x++;
    }

      if (Buffer[0] > 1)
       {
        Serial.print("recebeu >> :");
        Serial.println((char*)Buffer);
        int resultado = atoi(Buffer);
        F_OUTPUT_ON(resultado,0);       
       }


Com esse código consigo recuperar um dados mas não todos como eu gostava.


Cpts

Zé Tretas
Arduino Mega 2560
Arduino Nano
Arduino UNO Rev3
Raspberry PI Model B
EasyPIC v4

bubulindo

atoi() é o que estás à procura...
Normalmente, eu pegaria na trama inteira e usaria o strtok(trama, ',') para dividir essa string em várias strings.

Depois a primeira string podia ser usada literalmente ou copiada para outro array.
As restantes seriam convertidas com o atoi(). Claro que convém haver uma verificação do que estás a tentar converter (o atoi apenas converte para inteiros).

Outra possível alternativa, que nunca usei no arduino mas valerá a pena pesquisar era o sscanf.
Seria algo como:

Code: [Select]


int num1, num2, num3, num4;
char str1[];
char str2[];
sscanf(trama, "%s,%d,%d,%d,%s,%d", str1, &num1, &num2, &num3, str2, &num4);


Aqui será talvez preciso pesquisar um pouco, mas é uma alternativa viável... muito provavelmente o código que esta função gera será um pouco grande para um Arduino normal... mas nada como experimentar.

Analisando o teu código... tens um problema aqui:

Code: [Select]

char Buffer[8]; //buffer tem 8 posições
 memset(Buffer, '\0', 9); //estás a apagar 9 posições. Isto pode vir a dar sarilhos...


Eu acho que deves testar se a Porta série está disponível, mas também se já recebeste um caracter de termino. Normalmente em protocolos coloca-se um caracter para indicar o inicio da trama (por exemplo um $) e um caracter para indicar o final da trama (por exemplo *), isto juntamente com um carriage return é indicativo que a trama terminou e pode ser processada de forma a não perder nenhum dado.
Como tens isso pode não acontecer e quebrares isso ao meio.
This... is a hobby.

bubulindo

Decidi experimentar já que tenho aqui o Arduino...

O site em que me baseei foi este:

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#ga5507d0e1bbfd387fbb2ffcfd8f5dca6f

Code: [Select]

void setup() {
  Serial.begin(19200);
  Serial.setTimeout(200); //isto é usado para a função readBytesUntil
  Serial.println("Im ready");
}

void loop() {
  char trama[21];
  char str1[10];
  int num1 = 0;
  int numRead = -1;
  int ret = 0;
  if (Serial.available() > 5) { //random size
    Serial.println("sscanf"); //debug
    numRead = Serial.readBytesUntil('\n', trama, 20);//this is blocking...
    Serial.println("hello");//debug
    Serial.println(numRead);//debug
    if (numRead > 0) {//encontrou e copiou dados.
      //vamos fazer um parsing disto
      ret = sscanf(trama, "%s %d", str1, &num1);
      Serial.println("you sent");
      Serial.print("str ");
      Serial.println(str1);
      Serial.print("num ");
      Serial.println(num1);
    }
  }//end if serial available.
}


O problema disto, comparativamente a um computador é que a string de formatação, tanto quanto eu pude ver, não aceita separadores senão espaços. Ou seja, para esse código em cima funcionar, tens de enviar strings como esta:

card 9
dilb 10

Depois na porta série escolhes "retorno de linha" para ser enviado com essas strings.
Espero que ajude.
This... is a hobby.

tretas

Boas,

Tinha encontrado este codigo parecido ao teu, o problema é não o perceber a 100%, e pelos vistos, da para usar o separador ";"

Code: [Select]

// Buffer qui va contenir la trame série
#define TAILLE_MAX 32
 
// Buffer qui va contenir le texte (taille du buffer / 2, oui j'ai mis ça au pif)
char texte[TAILLE_MAX / 2], unite;
// Données utiles extraites
int valeur, index, diviseur;
 
// setup()
void setup() {
  // Initialisation du port série
  Serial.begin(9600);
}
 
// loop()
void loop() {
  // Récupération d'une trame + parsing
  if(recupInfo(texte, &valeur, &index, &diviseur, &unite)) {
    Serial.println("Erreur de trame !");
    return;
  }
   
  // Affichage
  Serial.print("Texte: ");
  Serial.println(texte);
  Serial.print("Valeur: ");
  Serial.println(valeur);
  Serial.print("Index: ");
  Serial.println(index);
  Serial.print("Diviseur: ");
  Serial.println(diviseur);
  Serial.print("Unité: ");
  Serial.println(unite);
}
 
/*
 * Parse une chaine au format $ texte;valeur;index;diviseur;°c/f;
 * Et retourne la valeur des différents champs.
 */
int recupInfo(char *texte, int *valeur, int *index, int *diviseur, char *unite) {
  char c, buf[TAILLE_MAX + 1];
  unsigned char i = 0;
 
  /* Attente du $ espace */
  do {
    /* Attente de 2 char sur le port série */
    while(Serial.available() < 2);
 
    /* Tant que chaine != $ espace -> boucle */
  }
  while(Serial.read() != '$' && Serial.read() != ' ');
 
  /* Remplissage du buffer */
  do{
    /* Si la chaine a dépassé la taille max du buffer*/
    if(i == (TAILLE_MAX + 1))
      /* retourne 1 -> erreur */
      return 1;
 
    /* Attente d'un char sur le port série */
    while(Serial.available() < 1);
 
    /* Tant que char != 0x1A (fléche) -> boucle */
  }
  while((buf[i++] = Serial.read()) != 0x1A);
 
  /* Cloture la chaine de char */
  buf[i] = '\0';
 
  /* Copie le texte au début de buf[] dans texte[] */
  i = 0;
  while((texte[i] = buf[i]) != ';') i++;
  texte[i] = '\0';
 
  /* Parse la chaine de caractères et extrait les champs */
  if(sscanf(buf + i, ";%d;%d;%d;%*c%c;", valeur, index, diviseur, unite) != 4)
    /* Si sscanf n'as pas pu extraire les 4 champs -> erreur*/
    return 1;
 
  /* retourne 0 -> pas d'erreur */
  return 0;
}
Arduino Mega 2560
Arduino Nano
Arduino UNO Rev3
Raspberry PI Model B
EasyPIC v4

tretas

Boas,

Obrigado com o teu código e com o código que postei esta a funcionar a 100%, mesmo que eu não tenha percebido tudo.

Cpts

Zé tretas
Arduino Mega 2560
Arduino Nano
Arduino UNO Rev3
Raspberry PI Model B
EasyPIC v4


tretas

Boas

pegando aqui no teu código
Code: [Select]

void setup() {
  Serial.begin(19200);
  Serial.setTimeout(200); //isto é usado para a função readBytesUntil
  Serial.println("Im ready");
}

void loop() {
  char trama[21];
  char str1[10];
  int num1 = 0;
  int numRead = -1;
  int ret = 0;
  if (Serial.available() > 5) { //random size
    Serial.println("sscanf"); //debug
    numRead = Serial.readBytesUntil('\n', trama, 20);//this is blocking...
    Serial.println("hello");//debug
    Serial.println(numRead);//debug
    if (numRead > 0) {//encontrou e copiou dados.
      //vamos fazer um parsing disto
      ret = sscanf(trama, "%s %d", str1, &num1);
      Serial.println("you sent");
      Serial.print("str ");
      Serial.println(str1);
      Serial.print("num ");
      Serial.println(num1);
    }
  }//end if serial available.
}


gostava de fazer algo do estilo, mas não sei como o codar.

Code: [Select]


if(str1 == "liga")
{
   Serial.print("liga);
}

f(str1 == "desliga")
{
   Serial.print("desliga");
}




Cpts

Zé tretas
Arduino Mega 2560
Arduino Nano
Arduino UNO Rev3
Raspberry PI Model B
EasyPIC v4

tretas

Problema resolvido, aqui fica pode ser que ajude alguém

Code: [Select]

if( strcmp(str1, "liga") == 0)
{
  Serial.print("liga");
}
 

if(strcmp(str1, "desliga") == 0)
{
   Serial.print("desliga");
}


Arduino Mega 2560
Arduino Nano
Arduino UNO Rev3
Raspberry PI Model B
EasyPIC v4

Go Up