I'm receiving a character string from a radio signal on my arduino. This character string consists of four character digits, which I want to convert into an integer. The four digit sequence may contain zeros padded in front of the integer, such as '0025' to represent the integer 25.

So, I saved this character string onto a character array of length 5:

char left[5];

The first four characters in this array have the four character digits received in the radio signal. I have a fifth character which I set to the character '\0' to signify a termination character.

The message received is any number ranging from 0 to 1023, but I need to use values between -255 and +255. To convert the character into an integer, I use the atoi function as follows:

int leftpower = (atoi(left)-512)/2;

When I print out the variable "leftpower", it seems to give the correct value. I'm even able to use "leftpower" in an if then statement as follows:

So, as far as I can tell, everything is working fine. I want to use "myvalue" as a command to an analogWrite function call as follows:

//analogWrite(enablePinA,myvalue);

However, something strange happens when I uncomment this line. WHen I uncomment it, the program seems to hang at the if statement, as if it paused at that point and neither crashes nor gives any error. The program no longer prints out "inside the if-then statement" at all, but no other errors seem to be detected. No other compilation or runtime errors.

The strange thing about this is that if I change "leftpower" to a number like 223 as follows:

analogWrite(enablePinA,223);

the program works as I expected it to, producing a motor command. So, I know the problem is not with my wiring. The problem seems to be associated with the variable "leftpower", which was converted from a character array to an integer using the atoi function.

What exactly is going on? What problem is actually occurring and how can I fix it? Any help would be greatly appreciated!

1 Answer
1

You don't check the value of buflen after calling the recv() method.
I didn't read the doc of the RH_ASK library you are using. Are you sure
it does preserve message boundaries? I let you check. If it only
transports bytes (rather than full messages), then you will have to
repeatedly recv() until you have a full message.

Edit: Looked at the doc. The communication is indeed packetized, so
you don't need to collect the message chunk by chunk. It is, however,
still a good idea to check whether the received size is what you expect:

if (driver.recv(buf, &buflen) && buflen == 8) { ... }

sprintf(temp,"%s",(char*) buf);

This is a serious bug, and most probably the reason your program behaves
inconsistently. Here buf is not a NUL-terminated string. The
sprintf() function will copy bytes from buf into temp until it
finds a NUL. It can potentially overwrite the receiving buffer and start
clobbering whatever happens to be past temp in your memory. This is
called “memory corruption” and can lead to any kind of unpredictable
behaviors.

Note that the whole copying you do here serves no useful purpose. You
can work from the initial buffer to start with:

The reason for the copy step is that the message received by the radio signal is actually 8 characters (two 4 character digit commands). To convert to an integer, i need to split the message into 2 separate 4 character arrays.
– PaulMar 23 '18 at 13:25

@Paul: That's why I suggest doing the splitting using two partial copies (with memcpy()), as buf → (left, right). However, your original code did the splitting as buf → temp → (left, right), where you first make a full copy (buf → temp) for no good reason. Note that the splitting could even be made zero-copy if we were after that kind of optimization.
– Edgar BonetMar 23 '18 at 14:27

I think the reason i used sprintf is because the message received in the buffer was originally an unsigned integer uint8_t (not a character array) and i thought converting to a character array would be simpler (for parsing purposes) using sprintf. Could i have parsed the two numbers out to a regular integer without converting to a character array first?
– PaulMar 23 '18 at 19:17

@Paul: Yes. buf is just an array of bytes. Same for temp. uint8_t, which is the same as unsigned char, means the bytes are interpreted as 8-bit unsigned integers. With int8_t (or signed char, or just char on Arduino), it's interpreted as a signed integer. The difference is irrelevant unless you plan to do arithmetics on those bytes, which you don't.
– Edgar BonetMar 23 '18 at 19:30