Problems on serial.read()

And use what?

Isn't that obvious? What are you storing in the String? Hint: It's not doubles, floats, longs, booleans, bytes, or instances of classes.

And the reason to not use it.

Because it has a destructor. Now, normally having a destructor is a good thing. But, the destructor calls free() to return the memory that it has allocated, and free() has a bug that causes the destruction of memory.

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

buf is NOT a String.

buf is a local variable that is going out of scope as soon as the function ends. Returning buf by any means is a bad idea.

The String class suffers from memory management problems and memory leaks.

Use 'C' strings instead i.e. null terminated char arrays. There is a rich library of functions in the C runtime library for dealing with strings, and you can also manipulate them simply by accessing the array elements directly.

Ok guys, I'll work on it!!!
I would search for C String and choose one wich fits better.

thanks a lot

:0Augusto, before C++ is C which handles text in byte or char arrays longer than the text will be. Always the way the text ends is with a character '\0' which = 0, also called NULL.

So you could have

char hello[ 16 ] = "Hello World";

hello[ 16 ] would be 16 chars == 'H' 'e' 'l' 'l' 'o' ' ' 'W' 'o' 'r' 'l' 'd' '\0' '\0' '\0' '\0' '\0' '\0'
'H' is also '\72'... here is an ASCII Table:

Once you understand that, spend time learning and getting used to C string functions. You might want to get a book (an old one, at deep discount) on just C language or look online for C tutorials and find the part(s) that deal with strings.
Please note that C strings are not C++ String Class Objects. Do not confuse string with String!

Here is the site where Arduino gets C++, link is to the libraries page:
http://www.nongnu.org/avr-libc/user-manual/modules.html

Most C string functions and defines are in the string library. Some are automatic, others you must #include <string.h> to get:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

strcpy() lets you copy strings. You can use it to load a string constant into an array.

char buffer[ 20 ]; // you can cut & paste these lines into a test sketch if you want
strcpy( buffer, "Hello" ); // but you will have to fill in the rest ]:smiley:
Serial.println( buffer );

strcat() lets you add a string to a string.

strcat( buffer, " World" );
Serial.println( buffer );

There are too many for this post, for many uses.

I think of sprintf() as a string command though it is not, but it lets you format text and variables with fine control into a C string. You don't need to include a library but working out how to make the format string, you will want a guide! sprintf() is in stdio (standard in/out):
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

You might want to find a tutorial page depending on your current coding skills, here below is the section from the stdio.h page. Even if you do learn elsewhere, the short tight layout makes a good memory helper for later that fits on a page or screen. 8) Always keep references for quick check if you have the slightest doubt. To misspell a word or get things out of order means time spent bug hunting, it would be a shame to spend 1 hour finding out you should have spent 1 minute looking up syntax!

The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the % character. The arguments must properly correspond (after type promotion) with the conversion specifier. After the %, the following appear in sequence:

Zero or more of the following flags:

The value should be converted to an "alternate form". For c, d, i, s, and u conversions, this option has no effect. For o conversions, the precision of the number is increased to force the first character of the output string to a zero (except if a zero value is printed with an explicit precision of zero). For x and X conversions, a non-zero result has the string 0x' (or 0X' for X conversions) prepended to it.

0 (zero) Zero padding. For all conversions, the converted value is padded on the left with zeros rather than blanks. If a precision is given with a numeric conversion (d, i, o, u, i, x, and X), the 0 flag is ignored.

  • A negative field width flag; the converted value is to be left adjusted on the field boundary. The converted value is padded on the right with blanks, rather than on the left with blanks or zeros. A - overrides a 0 if both are given.
    ' ' (space) A blank should be left before a positive number produced by a signed conversion (d, or i).
  • A sign must always be placed before a number produced by a signed conversion. A + overrides a space if both are used.

An optional decimal digit string specifying a minimum field width. If the converted value has fewer characters than the field width, it will be padded with spaces on the left (or right, if the left-adjustment flag has been given) to fill out the field width.
An optional precision, in the form of a period . followed by an optional digit string. If the digit string is omitted, the precision is taken as zero. This gives the minimum number of digits to appear for d, i, o, u, x, and X conversions, or the maximum number of characters to be printed from a string for s conversions.
An optional l or h length modifier, that specifies that the argument for the d, i, o, u, x, or X conversion is a "long int" rather than int. The h is ignored, as "short int" is equivalent to int.
A character that specifies the type of conversion to be applied.

The conversion specifiers and their meanings are:

diouxX The int (or appropriate variant) argument is converted to signed decimal (d and i), unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) notation. The letters "abcdef" are used for x conversions; the letters "ABCDEF" are used for X conversions. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with zeros.
p The void * argument is taken as an unsigned integer, and converted similarly as a %#x command would do.
c The int argument is converted to an "unsigned char", and the resulting character is written.
s The "char *" argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating NUL character; if a precision is specified, no more than the number specified are written. If a precision is given, no null character need be present; if the precision is not specified, or is greater than the size of the array, the array must contain a terminating NUL character.
% A % is written. No argument is converted. The complete conversion specification is "%%".
eE The double argument is rounded and converted in the format "[-]d.ddde±dd" where there is one digit before the decimal-point character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An E conversion uses the letter 'E' (rather than 'e') to introduce the exponent. The exponent always contains two digits; if the value is zero, the exponent is 00.
fF The double argument is rounded and converted to decimal notation in the format "[-]ddd.ddd", where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.
gG The double argument is converted in style f or e (or F or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.
S Similar to the s format, except the pointer is expected to point to a program-memory (ROM) string instead of a RAM string.

In no case does a non-existent or small field width cause truncation of a numeric field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.

This might be enough to get you started. Hey, I never said this would be a snap but it is something you should learn if you're going to write tight C code for small machines like UNO.

BTW, Good Luck and Good Future to You.

Augusto,

I think that PaulS response is the probable solution for your problem. The method return is not a String type as declared. Is a array to char. And buf[] is out of scope, because is a local pointer to char. Did you try fix it?

PaulS:

String Service::converteBeaconParaString(Beacon beacon) {
char buf[10];
sprintf(buf, "%d#%d#%d#", beacon.getDhost(), beacon.getShost(), beacon.getSALTO());
return buf;

}



buf is NOT a String. 

buf is a local variable that is going out of scope as soon as the function ends. Returning buf by any means is a bad idea.

Hi guys, I've been really diligent to solve this problem and I have to appreciate your help. A good news is that 50% of the problem was solved. In the code I changed what you suggested below on methods "converteBeaconParaString", "enviaBeacon" and "converteStringParaBeacon". Look that in the last now I looking for the "#" ah hand an

#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){
	  converteBeaconParaString(beacon);
	}
}

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;
}


void Service::converteBeaconParaString(Beacon beacon){

	Serial.print(beacon.getDhost());
	Serial.print("#");
	Serial.print(beacon.getShost());
	Serial.print("#");
	Serial.println(beacon.getSALTO());
}


Beacon Service::converteStringParaBeacon(String msg) {
	int c=0;
	int i=0;
	short vet[3];
	Beacon beacon;

	while (msg[i] == '\0') {
		if (msg[i] != '#') {
			vet[c] = vet[c] * 10 + (msg[i] - '0');
		}
		else {
			c = c + 1;
		}
		i = i + 1;
	}

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


bool Service::verificaMensagemBeacon(Beacon beacon, short id) {
	
	if (beacon.getDhost() == id) {
	  return true;
	}
		
	return false;
}

Now, when I send the information from ard_8 -> ard_5, I get what I wanted (2#1#0+1). 50% of the problem solved!!!!
HOWEVER, when I get this information (2#1#0+1) and change de destination for ard_x, the thrird arduino, I get like this (76656#56663#88877)
Really, annoying!!!

Any suggestion?

Thanks a lot folks.

Hi guys, I've been really diligent to solve this problem and I have to appreciate your help.

But, you are ignoring our advice. "Get rid of the String class!". It's still there. "Do not return local variables!" You're still doing it.

You want more help? Fix the problems you currently have, then we'll talk.

Hey buddy!! Calm down, I'm not ignoring your suggestion. You can note that I am having difficult to solve it!! Could you be a little bit humble and pacient??? I am new here, ok?
I'm being humble, I am always being grateful four your help!!! So, calm down!! If you do not want to help, ok? I think it would have more people wanting to help.
However, I am grateful for your attention to solve my problem.

AugustoSantos:
Hey buddy!! Calm down, I'm not ignoring your suggestion. You can note that I am having difficult to solve it!! Could you be a little bit humble and pacient??? I am new here, ok?
I'm being humble, I am always being grateful four your help!!! So, calm down!! If you do not want to help, ok? I think it would have more people wanting to help.
However, I am grateful for your attention to solve my problem.

You tell him to calm down twice, but you're the one that sounds wound up about this; there was nothing "uncalm" about his post.

AugustoSantos:
Hey buddy!! Calm down, I'm not ignoring your suggestion. You can note that I am having difficult to solve it!! Could you be a little bit humble and pacient??? I am new here, ok?
I'm being humble, I am always being grateful four your help!!! So, calm down!! If you do not want to help, ok? I think it would have more people wanting to help.
However, I am grateful for your attention to solve my problem.

Understood by someone, that is me.

But make the changes pointed out in your code before asking for help with it again. This time you left too many undone.

Replace -all- use of C++ Strings with C strings, not just some. You may want to work out the replacement code in other small test sketches that you can test the results before trying to jam it into your problem sketch that you cannot test anything with the way it is now.

There is also problem pointed out of returning the address to buf[] array that goes out of scope when the function it is made in ends. Do you understand what is scope?
Easy fix is to make the buffer global. Global never goes out of scope.

If there is some step you are stuck on then present -only that-, not the whole program.

Best thing I think you can do is write small test sketches to work out one thing at a time. It is far easier than trying to make everything work at once when one problem prevents you from testing the new parts.

Why so many people feel confident to write a mass of code they understand little of and then expect to debug it all together is beyond my understanding.

PaulS:

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.

The String class psychic at work! String class causing the issue without seeing all the code!

LOL! Troubleshooting is about simplifying and one way to do that is get rid of needless crap.
Annnnd check the posts, he did post the whole thing on Nov. 16.

OTOH he can have both Strings and strings. Surely (cough) there must be space for both?

You can drive a car down the sidewalk, that doesn't make it a good idea.

AugustoSantos:
Hey buddy!! Calm down, I'm not ignoring your suggestion. ...
However, I am grateful for your attention to solve my problem.

Two Three pages already, .

Did you read the sticky? Read this before posting a programming question

If you had you would have put your initial code into code tags. And read about the problems with the String class.


Please note that, at present, the String library has bugs as discussed here and here.

In particular, the dynamic memory allocation used by the String class may fail and cause random crashes.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.).


The first thing in solving a problem is trying to help yourself. Read the FAQ and the "sticky". Then you don't have to ask so much and wonder why people are getting a bit snippy.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.).

If the op post the full code that has the described issues are you willing to rework the String parts of the code to the C-style strings? I'm most interested to see if this will fix the current issues, or if there is something else causing the problem.

OK guys, I followed your advice and now I'm using C string. However, I am getting some problen, at least less than the others!
I put some debugs in tge code to identify where are them. So, I identified that the problem is between the points
"Ponto 3------------" and "Ponto 3.1------------", that is, on the method

void Service::converteBeaconParaArrayChar(Beacon beacon)

I won't put my Beacon.cpp e .h again. I just have to say that I changed all my "short's" to "byte's"

Here is my Service.cpp

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

byte 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){
	  converteBeaconParaArrayChar(beacon);
	}

}

Beacon Service::recebeBeacon(short id) {

	Beacon beacon;
	int i = 0;
	char msg[20];
	
	while(Serial.available() > 0) {
		byte temp = Serial.read();
		if (temp != 255){
			msg[i] = (char) temp;	
			i = i + 1;
		}				
	}
	Serial.println("Ponto_1 -----------------");
	Serial.println(msg);
	/* Aqui to recebendo 2#1#0 redondinho*/
	
	msg[i] = '\0';
	if (i > 0) {
	  beacon = converteArrayCharParaBeacon(msg);
	 
	 Serial.println("Ponto_2-----------------");
	  Serial.println(msg);
	  
	  delay(1000);
	  Serial.flush();
		
		if (verificaMensagemBeacon(beacon,id)) {
			return beacon;
		}
	}
}	
void Service::converteBeaconParaArrayChar(Beacon beacon) {
	Serial.println("Ponto_3-----------------");
	
	Serial.print(beacon.getDhost());
	Serial.print("#");
	Serial.print(beacon.getShost());
	Serial.print("#");
	Serial.println(beacon.getSALTO());
	
	/* Aqui to recebendo 2#1#0 e num aleat.*/
	Serial.println("Ponto_3.1-----------------");
}


Beacon Service::converteArrayCharParaBeacon(char msg[]) {
	int c =0;
	int  i=0;
	short vet[3];
	Beacon beacon;
	
	while (msg[i] != '\0') {
		if (msg[i] != '#') {
			vet[c] = vet[c] * 10 + (msg[i] - '0');
		}
		else {
			c = c + 1;
		}
		i = i + 1;
	}
	Serial.println("Ponto_4-----------------");
	Serial.println(msg);

	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;
}

I dont have any ideia why in the "void Service::converteBeaconParaArrayChar(Beacon beacon)" is doing what I attached in the picture?

Does anyone knows?

thanks

	Serial.print(beacon.getDhost());
	Serial.print("#");
	Serial.print(beacon.getShost());
	Serial.print("#");
	Serial.println(beacon.getSALTO());

What for example should that print? Is that making the 45#45#9 in the png?

What do those gets return?

example of printing different results from the same variable:
short x = 65; // same way with int but not byte or char
Serial.println(x); // prints 65, x as byte or char prints A
Serial.println((char) x); // prints A

Could your problem be due to this type of thing?

OK. I trying to make multhops. I have three arduinos UNO.
I calling them ard_5 (id = 2), ard_8 (id = 1) and ard_3 (id = 3).
So, if you look on my first post you'll se that I put my beacon.ccp code.
Now everything on every code that had "int " or "short" I changed for "byte".

Good news!!! I am getting 2#1#0 at my first hop from ard_5 arduino to ard_8!!!
Like this ard_8 (2#1#0) -> ard_5(2#1#0) -> ard_5(3#1#0)-> ard_x(3#1#0), that is:

ard_8 just send, ard_5 receives from ard_8 and send for ard_x changing the destination, but keeping the source.

Howerver, with ard_x, I am getting like this ( 13448#88787#7878)

ard_8

#include <Service.h>
#include <Beacon.h>

//Arduino 08 -> ard_8 -> Somente envia!!!

Beacon beacon;
Service service;

// Identidade dos Arduinos
byte ard_8 = 1; //Arduino 08
byte ard_5 = 2; //Arduino 05
byte ard_x = 3; //arduino X


void setup() {     
  // comunicação XBEE a taxa de 9600 bps
   Serial.begin(9600);  
}


void loop() {
          
            
           beacon = Beacon(ard_5, ard_8, 0);
           service.enviaBeacon(beacon);
           delay(2000);
               
}

ard_5

#include <Beacon.h>
#include <Service.h>

Beacon beacon;
Beacon recebe;
Service service;

byte ard_8 = 1; //Arduino 08
byte ard_5 = 2; //Arduino 05
byte ard_x = 3; //arduino X


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


void loop() {
  
             recebe = service.recebeBeacon(ard_5);
           
             if (recebe.getDhost() == ard_5){
             delay(2000); 
             //byte i = recebe.getSALTO()+1;
             beacon = Beacon(recebe.getDhost(), recebe.getShost(), recebe.getSALTO());         
             service.converteBeaconParaArrayChar(beacon);
               
              if (recebe.getDhost() == ard_5){
                  Serial.println("Ponto N");
                  beacon = Beacon(ard_x, ard_8,recebe.getSALTO() );
                  service.enviaBeacon(beacon);                 
              }  
    }     
}

ard_x

#include <Service.h>
#include <Beacon.h>

Service service;
Beacon beacon;
Beacon recebe;

byte ard_8 = 1; //Arduino 08
byte ard_5 = 2; //Arduino 05
byte ard_x = 3; //arduino X

//int led = 13;

void setup() {     
   Serial.begin(9600);  
 //  pinMode(led, OUTPUT);
}

void loop() {
  
          
              recebe = service.recebeBeacon(ard_x); 
           
              if (recebe.getDhost() == ard_x){
              delay(2000);
          
              beacon = Beacon(recebe.getDhost(), recebe.getShost(), recebe.getSALTO());         
              service.converteBeaconParaArrayChar(beacon);
          }

One more thing, I changed my while from method converteArrayCharParaBeacon to:

	byte  i=0;
	byte vet[3];
	Beacon beacon;
	
	
	for (i=0; i <= 2; i++){
	    vet[i] = msg[2 * i] - '0';
	    i++;
	}

Do you see any mistake?

I see no obvious mistake but then I've only posted about parts of the code anyway.
I am trying not to dig into the whole thing and don't know what's in those libraries.
It's a matter of time and energy, I am not so young.

I see the 13448#88787#7878. 88787 is more than 16 bits.
Should that be possible from the get? Get like beacon.getDhost() type get?
Does the get return certain values on error?

Perhaps some more simple debug:

long dbg = beacon.getDhost()); // unless getDhost() should return an int or a byte?
Serial.print( dbg, HEX );

Sometimes print the return from a function is a bit different than I expect.

Sometimes when breaking code down to simpler I finally see what I didn't spell or arrange quite right.

	Serial.print(beacon.getDhost());

What type does beacon.getDhost() return? Byte? Char? Int?