Offline
Newbie
Karma: 0
Posts: 17
|
 |
« on: November 16, 2012, 09:18:53 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 100
Posts: 9548
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #1 on: November 16, 2012, 10:08:42 am » |
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
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #2 on: November 16, 2012, 10:17:54 am » |
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 #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 //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
Newbie
Karma: 0
Posts: 4
|
 |
« Reply #3 on: November 16, 2012, 01:49:11 pm » |
There is a little bug at "converteStringParaBeacon" method.
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
Newbie
Karma: 0
Posts: 4
|
 |
« Reply #4 on: November 16, 2012, 02:10:33 pm » |
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
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #5 on: November 16, 2012, 02:23:43 pm » |
@ Sergio I appreciate your attention. The bug is already corrected I've put 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
Newbie
Karma: 0
Posts: 4
|
 |
« Reply #6 on: November 16, 2012, 02:38:02 pm » |
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: for (c = i = 0; c < 3; c++) {
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #7 on: November 16, 2012, 02:47:03 pm » |
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! 
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 100
Posts: 9548
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #8 on: November 16, 2012, 05:26:16 pm » |
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
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 332
Posts: 36396
Seattle, WA USA
|
 |
« Reply #9 on: November 16, 2012, 05:46:05 pm » |
Serial.flush(); Block until all pending serial data has been sent. How is this useful?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #10 on: November 16, 2012, 06:43:03 pm » |
Hey, about the 255 code I've put this, but it doesnt function!!! 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
Online
Edison Member
Karma: 50
Posts: 2156
|
 |
« Reply #11 on: November 16, 2012, 06:59:02 pm » |
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
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #12 on: November 16, 2012, 07:02:35 pm » |
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
Brattain Member
Karma: 332
Posts: 36396
Seattle, WA USA
|
 |
« Reply #13 on: November 16, 2012, 07:05:20 pm » |
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
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #14 on: November 16, 2012, 07:16:18 pm » |
Ok, here is my whole code: What suggestion you give me with String class?? thanks #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; }
#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
#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; }
#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 #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) #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
|
|
|
|
|
|