Pages: [1] 2 3   Go Down
Author Topic: Problems on serial.read()  (Read 1150 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


* recebe(Arduino2).jpg (103.19 KB, 778x519 - viewed 12 times.)
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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.


Logged

Rob Tillaart

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

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

#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:
//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.
Logged

Rio de Janeiro, Brazil
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a little bug at "converteStringParaBeacon" method.

Code:
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
Logged


Rio de Janeiro, Brazil
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: November 16, 2012, 02:32:03 pm by smarcelo » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ Sergio

I appreciate your attention. The bug is already corrected I've put
Code:
short vet [3];

@smarcelo
Thanks too. I didnt understand, but can you help me solve it? Do you know how to solve it?
I'd appreciate.
Logged

Rio de Janeiro, Brazil
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I was wrong about return local objects. The problem of 'undefined behavior' only happens if you are return references to a local object. A local object is always destroyed at the end of function/method. But, in your case, you are return a object by value. So, the C++ will make a safe copy before destroy it.
----
Are you corrected the 'for' loop too?

I think must be like this to get the 'salto' value from string:
Code:
for (c = i = 0; c < 3; c++) {

Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Beacon Service::converteStringParaBeacon(String msg) {
int c, i;
short vet[3];
Beacon beacon;
for (c = i = 0; c < 3; c++) {         [b]  // If I put c<3 and not c<2 it get worst [/b]
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;
}

Look at the picture!!! At leat with C<2 I still get in the midle of garbage 2#1#0# ahuahuahah

But, I thank you so much for help. Please, stay with me! smiley



* Captura de tela de 2012-11-16 17:42:26.png (125 KB, 1280x800 - viewed 6 times.)
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Beacon Service::converteStringParaBeacon(String msg) {
   int c, i;

c and i can probably be of the type uint8_t (byte) as the values will not exceed 255 (or do they?)
Logged

Rob Tillaart

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

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46266
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Serial.flush();
Block until all pending serial data has been sent. How is this useful?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey, about the 255 code I've  put this, but it doesnt function!!!

Code:
Beacon beacon;
String msg;

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

}

Do you have more suggestion?

Thanks folks,
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey, about the 255 code I've  put this, but it doesnt function!!!

Oh, it functions. How it functions may not be congruent with how you're expecting it to function, and unless you tell us what you're expecting it to do, and what it is doing, it's hard to determine what is causing the difference.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok Ok, I agree with your comment!!!
I really need that when the arduino get the packet, it doen not come with so much garbage. I think the problem is with the "recebe" method.
But I really do not know what is happening. One told me to handle XCTU for xbee, I'm looking for information about this.
What do you think??

thanks
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46266
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But I really do not know what is happening.
Until you do, you shouldn't be shooting yourself in the foot with the String class.

By the way, snippets-r-us.com is down the internet a ways. Here, we expect to see ALL of your code.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, here is my whole code:
What suggestion you give me with String class??
thanks

Code:
#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;

}

Beacon::Beacon(short dhost, short shost, short salto) {
this->dhost = dhost;
this->shost = shost;
this->salto = salto;

}

Beacon::~Beacon() {/*nothing to destruct*/
}


short Beacon::getDhost() const {
return dhost;
}

short Beacon::getShost() const {
return shost;
}

short Beacon::getSALTO() const {
return salto;
}

void Beacon::setDhost(short dhost) {
this->dhost = dhost;
}

void Beacon::setShost(short shost) {
this->shost = shost;
}

void Beacon::setSALTO(short salto) {
this->salto = salto;
}

Code:
#ifndef BEACON_H_
#define BEACON_H_

#include <Arduino.h>
#include <string.h>

class Beacon {
public:
Beacon();
Beacon(short meu_id);
Beacon(short dhost,short shost, short salto);
~Beacon();
    short getDhost() const;
    short getShost() const;
    short getSALTO() const;
    void setDhost(short dhost);
    void setShost(short shost);
    void setSALTO(short salto);
   
private:
short dhost;
short shost;
short salto;
};

#endif

Code:
#include "Service.h"

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


short meu_id; //identificação do no raiz

//Estrutura do pacote de controle
Service::Service() {
}

Service::~Service() {/*nothing to destruct*/
}

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

}

Beacon Service::recebeBeacon(short id) {

Beacon beacon;
String msg;

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

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

if (verificaMensagemBeacon(beacon,id)) {
return beacon;
}
}
return beacon;
}

// Funcao que converte inteiro para String. Arduino trata somente string
String Service::converteBeaconParaString(Beacon beacon) {
char buf[10];
sprintf(buf, "%d#%d#%d#", beacon.getDhost(), beacon.getShost(), beacon.getSALTO());
return buf;
}


Beacon Service::converteStringParaBeacon(String msg) {
int c, i;
short vet[3];
Beacon beacon;
for (c = i = 0; c < 3; 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;
}


bool Service::verificaMensagemBeacon(Beacon beacon, short id) {

      //Verifica se a mensagem é para ele.
if (beacon.getDhost() == id) {
  return true;
}

return false;
}


Code:
#ifndef SERVICE_H_
#define SERVICE_H_

#include <Arduino.h>
#include <string.h>
#include <Beacon.h>


class Service {
public:
Service();
~Service();
    String converteBeaconParaString(Beacon beacon);
    Beacon converteStringParaBeacon(String msg);
    void enviaBeacon(Beacon beacon);
    Beacon recebeBeacon(short id);
    bool verificaMensagemBeacon(Beacon beacon,short id);

};

#endif

//Arduino that sends the packet
Code:
#include <Service.h>
#include <Beacon.h>

Beacon beacon;
Service service;

short ard_8 = 1; //Arduino 08
short ard_5 = 2; //Arduino 05



void setup() {     
   Serial.begin(9600); 
}


void loop() {
         
           //Enviar beacon com D(ard_5), S(ard_8), 0
           beacon = Beacon(ard_5, ard_8, 0);
           service.enviaBeacon(beacon);
           delay(2000);
               
}

//Arduino that receives packet (The problem is here)
Code:
#include <Beacon.h>
#include <Service.h>

Beacon beacon;
Beacon recebe;
Service service;

short ard_8 = 1; //Arduino 08
short ard_5 = 2; //Arduino 05



void setup() {     
   Serial.begin(9600); 
}


void loop() {
 
           recebe = service.recebeBeacon(ard_8);
           
           delay(2000);
           
           //recebe.getSALTO() ta dando problema no metodo recebe que nao sei qual e. Isso ta afetando o getSALTO()
            beacon = Beacon(recebe.getDhost(), recebe.getShost(), recebe.getSALTO());         
           Serial.println(service.converteBeaconParaString(beacon));
Logged

Pages: [1] 2 3   Go Up
Jump to: