Go Down

Topic: Problems on serial.read() (Read 1 time) previous topic - next topic

AugustoSantos

Hi fellows,

I am new in Arduino world, and Im trying to make my final project in the plataform Arduino UNO. But I am having a kind of problem that I am not being able to solve. That´s why I am here to ask the community help.

So, what I am trying to do is make two hops with three Arduinos. In a nutshell, I´m trying to send by Xbee Shield a packet in this format
(2#1#0#) -> (destinationHost, sourceHost, hop). To you understand, my 3 arduinos, have an identification such as 1, 2 and 3.
If I tell you that I am sending a packet from (1) to (2), I wold use this  (2#1#0#).

But as I told, I am having problem in a method of my code that is displayed bellow:

Beacon Service::recebeBeacon(short id) {

   Beacon beacon;
   String msg;
   
   while(Serial.available() > 0) {
      byte temp = Serial.read();
      msg = msg + (char) temp;            
   }
   Serial.flush();
   
   if (msg.length() > 0) {
      beacon = converteStringParaBeacon(msg);
      delay(1000);
      Serial.flush();
      
      
      if (verificaMensagemBeacon(beacon,id)) {
         return beacon;
      }
   }
   return beacon;
}

My arduino (1) just sends the packet like this (2#1#0#), and it is ok!
void loop() {
         
           //Send beacon com Dest(2), Source(1), Hop(0)
           beacon = Beacon(2,1,0);
           service.enviaBeacon(beacon);
           delay(2000);
               
}
But, when I get the message with Arduino (2), I get a lot of garbage, however the message comes two. Look at the picture attached and
you´ll understand. Please, does anyone knows what is happening???
void loop() {
 
           recebe = service.recebeBeacon(ard_8);
           delay(2000);

           //recebe.getDhost(), recebe.getShost(), recebe.getSALTO() are short types
           beacon = Beacon(recebe.getDhost(), recebe.getShost(), recebe.getSALTO());         
           Serial.println(service.converteBeaconParaString(beacon));
               
            delay(2000);
}

Am I being clear, guys?

Thank you so muck for your attention.

robtillaart


1) The String class is a memory killer, you better use char array's . A bit more work but they work better.
2) do you synchronize your packets somehow? begin/end of the message (tip use a special chat like < and > )
3) you are not posting the whole code that makes it harder to analyze

and if you post please use the # button (above the smileys) to get code proper tagged. Makes it more readable.


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

AugustoSantos

1) char array´s.
How can I do it, please? Can you give a tip?

I think if you see the whole code it´ll get clear;
This is my Beacon.cpp
Code: [Select]


#include "Beacon.h"
#include <stdio.h>
#include <string.h>

Beacon::Beacon() {
}

Beacon::Beacon(short meu_id) {
this->dhost = 0; // host de destino
this->shost = 0; // host de origem
this->salto = 0; // (metrica SALTO, numero de saltos para cada no)
//this->meu_id = meu_id;
}

Beacon::Beacon(short dhost, short shost, short salto) {
this->dhost = dhost; // destination host
this->shost = shost; // source host
this->salto = salto; // hops

}


This is my Service.cpp
Code: [Select]

//send beacon
void Service::enviaBeacon(Beacon beacon) {
if(beacon.getDhost() != 0){
  String msg = converteBeaconParaString(beacon);
  Serial.println(msg);
}

}
//receive beacon
Beacon Service::recebeBeacon(short id) {

Beacon beacon;
String msg;

while(Serial.available() > 0) {
byte temp = Serial.read();
msg = msg + (char) temp;

}
Serial.flush();


if (msg.length() > 0) {
beacon = converteStringParaBeacon(msg);
delay(1000);
Serial.flush();


if (verificaMensagemBeacon(beacon,id)) {
return beacon;
}
}
return beacon;
}
//convert Beacon to String
String Service::converteBeaconParaString(Beacon beacon) {
char buf[10];
sprintf(buf, "%d#%d#%d#", beacon.getDhost(), beacon.getShost(), beacon.getSALTO());
return buf;
}

//convert  String to Beacon
Beacon Service::converteStringParaBeacon(String msg) {
int c, i;
short vet[2];
Beacon beacon;
for (c = i = 0; c < 2; c++) {
vet[c] = (short) msg.substring(i, msg.indexOf('#', i)).toInt();
i = msg.indexOf("#", i) + 1;
}

beacon.setDhost(vet[0]);
beacon.setShost(vet[1]);
beacon.setSALTO(vet[2]);

return beacon;
}


Clear now? Any suggestion?

Thank a lot.

smarcelo

There is a little bug at "converteStringParaBeacon" method.

Code: [Select]
Beacon Service::converteStringParaBeacon(String msg) {
int c, i;
short vet[2];   // must be vet[3]: you are using three elements at [0], [1] and [2] below
Beacon beacon;
for (c = i = 0; c < 2; c++) { 
              // 'c' will be 0 and 1 values only. The third element (index [2])will not be read.
              // because when 'c=2' then 'c<2' is false.
vet[c] = (short) msg.substring(i, msg.indexOf('#', i)).toInt();
i = msg.indexOf("#", i) + 1;
}

beacon.setDhost(vet[0]);
beacon.setShost(vet[1]);
beacon.setSALTO(vet[2]);   // vet[2] POINTS TO A INVALID LOCATION you have only 2 elements...

return beacon;
}


Fix this and see if works.

Sergio Figueiredo
http://blog.devdelver.com/archives/category/arduino

smarcelo

#4
Nov 16, 2012, 08:10 pm Last Edit: Nov 16, 2012, 08:32 pm by smarcelo Reason: 1
I have seen a more serious problem with your converteStringParaBeacon() method: It returns a local object reference (beacon). This may cause a "Undefined behavior".

You can see more here:
http://stackoverflow.com/questions/10930509/scope-of-a-local-object

EDITED: I am wrong and your code is valid. You are not returning a reference to a object. The C++ will make a copy of the local object to return it.

Go Up