Envio de informação via Serial para outro arduino

Neste último caso, você sugere um char array no lugar de string?

Sim sem duvida.Para fazer comparaçoes podes sempre usar o strcmp() para fazeres comparaçoes entre strings

HugoPT:
Sim sem duvida.Para fazer comparaçoes podes sempre usar o strcmp() para fazeres comparaçoes entre strings

Valeu a Dica!!! Farei testes com strcmd() :smiley:

Quando programamos no ambiente Windows temos certos hábitos que levamos para outra linguagens.

Obrigado!

Mortis:
Como os dois arduinos estão ligados, por cabo nos pinos TX/RX -> RX/TX?

Presumo que já sabes como imprimir no LCD, então o que te falta é ler a serial?

se for isso, testa o abaixo:

String SerialBuffer = "";

void setup(){
 SerialBuffer.reserve(200);

Serial1.begin(9600); //os dois devem ter o mesmo rate
}

void loop(){
 if (Serial1.available() > 0){
   while (Serial1.available() != 0) {
     char inChar = (char)Serial1.read();
     
     if (inChar == '\n') {
       //Imprime no LCD a string do SerialBuffer
       SerialBuffer = "";
     }
     else {
       SerialBuffer += inChar; \Add to buffer
     }
   }
 }
}




Assim o primeiro arduino imprime uma linha na serial e o segundo recebe todos os bytes, armazena no buffer (string) e quando encontrar a quebra de linha você pega o conteúdo do buffer e imprime no LCD.

Sim estão ligados TX/RX -> RX/TX
Desculpem a minha ignorância mas sou novo nestas coisas... :slight_smile:

Quanto ao codigo, Serial1 é por algum motivo em especial? As placas que estou a usar são Uno, não será apenas Serial?

Não existe uma maneira mais simples?
Por exemplo...

Arduino 1 lê valor de 975 na analógica 0
leituraa = analogRead(0);
envia para Arduino 2
Serial.println(leituturaa);

No Arduino 2 algo tipo do género
leiturab = Serial.read(); sendo o valor de "leituraa" igual a 975...
lcd.setCursor(0,0);
lcd.print(leiturab,1);

Isto é possível?

leiturab = Serial.read(); sendo o valor de "leituraa" igual a 975...

975 ao serem enviados pela porta serie cada digito ocupa um byte.
logo tens de ler todos os bytes e reconstruir o numero.
Nao é possivel duma só vez

joaquim_lopes:
Quanto ao codigo, Serial1 é por algum motivo em especial? As placas que estou a usar são Uno, não será apenas Serial?

Perdoa-me, mas eu copiei partes do meu código e eu uso o Mega, que possui mais portas seriais. :roll_eyes:

Sobre ser novato, eu também sou, então não se preocupe! Mas logo mais deixaremos de ser :wink:

joaquim_lopes:
Arduino 1 lê valor de 975 na analógica 0
leituraa = analogRead(0);
envia para Arduino 2
Serial.println(leituturaa);

No Arduino 2 algo tipo do género
leiturab = Serial.read(); sendo o valor de "leituraa" igual a 975...
lcd.setCursor(0,0);
lcd.print(leiturab,1);

Isto é possível?

Bom, primeiro você precisa saber se tem dados na serial, então não tem como fugir do Serial.available()

O segundo o HugoPT já respondeu, você terá de passar pelo Serial.read() três vezes, uma para cada byte, logo não tem como fazer de forma diferente daquela que o bubulindo exemplificou.

Ok... depois de ler um pouco sobre o Serial... experimenta algo assim:

Arduino 1

void loop() {

unsigned int valor = 0;

valor = analogRead(A0);
Serial.write(valor >> 8);
Serial.write(valor);
Serial.println(); //importante
}

no Arduino 2

void loop() {
  unsigned int value = 0;
  if (Serial.available() >=3) {//dois bytes do int mais carriage return
    value = (Serial.read()<<8) + Serial.read();
    Serial.read();//skip \n
    Serial.print("received ");
    Serial.println(value);
  }
}

Assim é melhor porque são sempre apenas enviados 2 bytes. Se enviares em ASCII podes enviar entre 2 a 5 bytes (ou 6 se olhares ao tamanho dum int) e isso é bem mais complicado de programar. Também é mais rápido...

Nota que não coloquei aqui protecções para sincronizar ambos os arduinos. Ou seja, têm de ser ligados ambos ao mesmo tempo para garantir que um está a ouvir o que o outro está a mandar, mas isso é simples de fazer colocando o Arduino 2 à espera do \n.

Esta é uma maneira mais simples e correcta de fazer isto. :slight_smile:

Bom, abaixo como ficaram meus códigos, para o Joaquim Lopes pode ser um próximo passo, passar o valor de vários sensores e ou comandos entre os arduinos (?).

Eu executo uma série de comandos via bluetooth, esse é para eu gravar os valores de referencia para sensores IR de um seguidor de linhas, valores usados para aumentar ou reduzir a sensibilidade das condições.

Lembrando que ainda sou muito noob! :disappointed_relieved:

char SerialBuffer[100]; //sem String aqui rs
byte CharIndex = 0;

int paramR = 0; //Right Sensor ref
int paramC = 0; //Center Sensor ref
int paramL = 0; //Left Sensor ref

void setup(){
  Serial1.begin(57600);
}

void loop(){
  if (Serial1.available() > 0){
    while (Serial1.available() != 0) {
      char inChar = (char)Serial1.read(); 
      
      if (inChar == '\n') {
        ExecuteCommand(SerialBuffer);

        CharIndex = 0;
        memset(SerialBuffer, 0, 100);
      }
      else {
        SerialBuffer[CharIndex] = inChar;
        CharIndex++;
      }
    }
  }
}

void ExecuteCommand(char Value[]){
  char Command[100];

  strcpy(Command, Value);

  char *chpt = strtok(Value, "("); //Split string into tokens
  if (chpt == NULL) {
      Serial1.println("No Command in the First strok");
      return;
  }
  
  if(strcmp(chpt, "SetSensorParams") == 0)
    SetSensorParams(Command);
}

void SetSensorParams(char Params[]){
  int newParamL,newParamC,newParamR;

  Serial1.print("Values: ");
  Serial1.println(Params);

  int errors = 0;
  
  char *chpt = strtok(Params, "("); //Split string into tokens
  if (chpt == NULL) {
      Serial1.println("Params strok returns NULL");
      ++errors;
  }
  
  if (errors == 0) {
      chpt = strtok(NULL, ",");
      if (chpt == NULL) {
          Serial1.println("First param strok returns NULL");
          ++errors;
      }
      else {
          newParamL = atoi(chpt); //Convert to integer
      }
  }
  
  if (errors == 0) {
      chpt = strtok(NULL, ",");
      if (chpt == NULL) {
          Serial1.println("Second param strok returns NULL");
          ++errors;
      }
      else {
          newParamC = atoi(chpt);
      }
  }
  
  if (errors == 0) {
      chpt = strtok(NULL, ")");
      if (chpt == NULL) {
          Serial1.println("Third Param strok returns NULL");
          ++errors;
      }
      newParamR = atoi(chpt);
  }
  
  if (errors == 0) {
    paramL = newParamL;
    paramC = newParamC; 
    paramR = newParamR;
  }
}

o que vocês acham?

HugoPT, esta melhor assim?

PS: Lembrando que eu uso o Serial1 do arduino mega, assim posso trabalhar com a serial usb e bluetooth simultaneamente

Assim por uma vista de olhos rapida parece que está la tudo.
Ha algumas coisas que podem ser melhoradas a titulo de uma boa programaçao.
Vejamos aqui:

void ExecuteCommand(char Value[]){

Estas a passar um parametro com o Value[].Quando passas um array ele por si só é um ponteiro para a primeira posiçao do vector.Eu teria colocado ou esperar um ponteiro em vez de Value[]
Eu modificava para:

ExecuteCommand(char * Value)

Agora ha aqui outra questao. O vector que estas a passar é global o que poderá nao fazer muito sentido passa-lo como argumento na funçao...
Irá funcionar na mesma assim.

char Command[100];

strcpy(Command, Value);

Se passas o vector por parametro porque é que depois o copias para outro array dentro da funçao?
A idea é usalo la dentro nao copia-lo.
Assim comeste mais 100 bytes de RAM para nada.Faz uso dos ponteiros!

Hmm, acho que nos estamos a deixar levar por dois problemas diferentes.

O do Mortis em que uma pessoa comunica com o Arduino (já agora, tens um código extremamente complexo para algo tão simples) e o do joaquim em que dois arduinos comunicam entre si.
No problema do Mortis, os humanos preferem ASCII então a comunicação é feita assim e como tal tem um overhead maior e é mais complexo.
No caso do Joaquim é escusado colocar duas máquinas a falar linguagem de humanos (ASCII) já que elas se entendem melhor em binário e a programação é bem menos complexa como exemplifiquei em cima.

A única coisa que me preocupa é o efeito que o chip FTDI tem na comunicação... Alguém experimentou os dois códigos?

Antes de mais obrigado a todos.

Tal como disse, sou novato nestas coisas e alguma linguagem passa-me ao lado...
mas vou testar os vários códigos e depois dou o meu feedback.

HugoPT:

char Command[100];

strcpy(Command, Value);

Se passas o vector por parametro porque é que depois o copias para outro array dentro da funçao?
A idea é usalo la dentro nao copia-lo.
Assim comeste mais 100 bytes de RAM para nada.Faz uso dos ponteiros!

HugoPT,

Eu copio o array porque após o strtok eu via apenas "SetSensorParams" exemplo:
Value passado "SetSensorParams(200,300,200)"

char *chpt = strtok(Value, "(");

O resultado era
chpt = "SetSensorParams"
Value = "SetSensorParams"

Farei mais testes e seguirei teus conselhos.

Muitíssimo obrigado.

bubulindo:
Hmm, acho que nos estamos a deixar levar por dois problemas diferentes.

Desculpem-me, acho que me empolguei e não tinha a intenção de complicar =/

Por favor, voltemos ao problema do tópico:

bubulindo:
A única coisa que me preocupa é o efeito que o chip FTDI tem na comunicação... Alguém experimentou os dois códigos?

A qual efeito te referes?

joaquim_lopes:
Antes de mais obrigado a todos.

Tal como disse, sou novato nestas coisas e alguma linguagem passa-me ao lado...
mas vou testar os vários códigos e depois dou o meu feedback.

Joaquim, desculpa-me se compliquei muito para ti, o bubulindo esta correto, os códigos que coloco estão muito longe da linguagem de comunicação entre máquinas (estou habituado a programar para Windows :(), diga-nos o que ocorreu por ai e se podemos ajudar!

Malta após alguns teste eis o que consegui até agora.

No Arduino 1

loop()
{
val = analogRead(0);
Serial.write("T");
Serial.write(val);
delay(1500);
}

No Arduino 2

loop()
{
if ((incomingByte)=='T')
{
valor = Serial.read();
lcd.setCursor(0,1);
lcd.print(valor);
}
}

O que acontece é que isto funciona desde que o valor enviado (neste caso val) não seja superior a 255, caso isso aconteça o Arduino 2 lê outro valor
Por exemplo

Arduino 1 - valor enviado -> Arduino 2 - Valor LCD
0 -> 0
1 -> 1
... -> ...
255 -> 255
256 -> 0
257 -> 1
258 -> 2
259 -> 3
260 -> 4
261 -> 5
262 -> 6
263 -> 7
264 -> 8
265 -> 9
266 -> 10
267 -> 11
268 -> 12
269 -> 13
.... - > ....

Ou seja, de 255 em 255 ele reinicia a contagem... :frowning: alguma ideia?

O que acontece é que isto funciona desde que o valor enviado (neste caso val) não seja superior a 255, caso isso aconteça o Arduino 2 lê outro valor
Por exemplo

Arduino 1 - valor enviado -> Arduino 2 - Valor LCD
0 -> 0
1 -> 1

Logico o valor maximo de um byte é 255 no caso de ser unsigned !
Como escreves alem disso ele da a volta e recomeça de 0

Serial.write(val);

Voltamos a mesma questao.Nao consegues passar o valor todo num só byte!
O valor maximo que pode ser lido no ADC é 1023 ou seja necessitas de no minimo 4 bytes e talvez mais um para usar um caracter terminador

HugoPT:

O que acontece é que isto funciona desde que o valor enviado (neste caso val) não seja superior a 255, caso isso aconteça o Arduino 2 lê outro valor
Por exemplo

Arduino 1 - valor enviado -> Arduino 2 - Valor LCD
0 -> 0
1 -> 1

Logico o valor maximo de um byte é 255 no caso de ser unsigned !
Como escreves alem disso ele da a volta e recomeça de 0

Ok, e como posso contornar isso?

Com a resposta que o Bubulindo te postou :grin:

HugoPT:
Com a resposta que o Bubulindo te postou :grin:

Ok. Já experimentei o código e está funcionar perfeitamente.
Obrigado a todos. :slight_smile:

Bons estudos colega :grin:

Yeay... :slight_smile: