Strange output to serial monitor

Hi

I’m running the following code and I’m getting a strange output and I wondered if anybody knew why. so here’s the code:

//transmitter
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(10, A0); // CE, CSN

const byte address[6] = "300ZX";
char text[32];
void setup() {
  Serial.begin(115200);
  radio.begin();
  radio.openWritingPipe(address);
  //radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}

void loop() {
uint8_t i = 0;

  if (Serial.available()) {
    while (Serial.available()) {
      text[i] = Serial.read();
      ++i;
    }
    Serial.println(text);
    radio.write(&text, sizeof(text));
  }
}

If I type “Hello World” and enter it into the serial monitor, I get printed out on transmitter side:
H
ello World

and if anybody wondered… same output on receiver code.

and it does that for any text I enter! there seems to be a carriage return added after the first character every time!

anybody have any ideas as to why?

Post the receiver code.

outsider:
Post the receiver code.

receiver code just prints what it receives and is irrelevant for now as its a wireless system.

problem is at SOURCE.

to repeat my original post…

if I try in “hello world” at transmitter, on TRANSMITTER serial monitor prints:

h
ello world

instead of “hello world”.

why is a carriage return added after the first character only… is it a library problem?

here’s the receiver code anyway…

//receiver
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CE, CSN

const byte address[6] = "300ZX";

void setup() {
  Serial.begin(115200);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}

void loop() {
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

Look carefully at your transmitter code.

if (Serial.available()) {
    while (Serial.available()) {
      text[i] = Serial.read();
      ++i;
    }

How much data does that loop grab?
(How many times does the while loop repeat?)

And no, it is not a library problem.

TolpuddleSartre:
Look carefully at your transmitter code.

if (Serial.available()) {

while (Serial.available()) {
      text[i] = Serial.read();
      ++i;
    }


How much data does that loop grab?
(How many times does the while loop repeat?)

And no, it is not a library problem.

sorry not quite following your thought...

in case of tx "hello world"
Serial.available() would be at least 12 I reckon... so the while loop would loop 12 times (0-11)

again not sure what you're pointing at... please clarify for me

could it rather the Tx/Rx delay issue whereby when "hello world" is entered, there is a sufficient delay between uC buffering in "h" and the remaining letter that they are then printed out separately? ie that code is therefore executed twice (maybe because the code execution is faster than Serial.available can be updated)

Here's another hint: serial, even at 115200, is slooooow

sherzaad:
in case of tx "hello world"
Serial.available() would be at least 12 I reckon... so the while loop would loop 12 times (0-11)
be updated)

Probably it wont.

Data is transmitted byte after byte with some control bits added.
The speed of that transmission is specified through the baud rate.
Your 115200 translates roughly to 12000 bytes per second.

If loop is repeated more often, it will see each byte on its own.

So your loop picks up the first byte, after reading that there is no second waiting, because it is still on transmission.
You assemble and send a packet with the single character,
while doing so you give the system time to receive the rest of the data before reaching available()==0 again.

If you change the baudrate to 9600 you would probably see each character in its own packet (try it).

You need a better way to receive serial data (collect until packetsize or CR/LF).

Whandall:
Probably it wont.

Data is transmitted byte after byte with some control bits added.
The speed of that transmission is specified through the baud rate.
Your 115200 translates roughly to 12000 bytes per second.

If loop is repeated more often, it will see each byte on its own.

So your loop picks up the first byte, after reading that there is no second waiting, because it is still on transmission.
You assemble and send a packet with the single character,
while doing so you give the system time to receive the rest of the data before reaching available()==0 again.

so that you're kind of confirming what I said at the end of reply #4! :slight_smile:

code execution is faster than serial.available() can be updated... makes sense

ok so here another question then... to avoid this, is there away of picking up ALL the characters and tx them all without using delimiters. ie what would be the delimiter here (sending "hello world")? carriage return?

Sorry, I added that later.

Whandall:
You need a better way to receive serial data (collect until packetsize or CR/LF).

Why are you sending always 32 bytes, without adding any delimiter?

The receiving side has no means to distinguish old data from new data.

You could try sending "Hello world" followed by an "ok" to see what I mean.

You do not check for messages longer than your buffer,
so entering text longer than 30 characters could overwrite your memory. That’s a bad bug.

Likewise not adding a trailing 0 before the print in the receiver could print much more than you expect.

Whandall:
Sorry, I added that later.

Why are you sending always 32 bytes, without adding any delimiter?

The receiving side has no means to distinguish old data from new data.

You could try sending "Hello world" followed by an "ok" to see what I mean.

If I do that with my current code I get

H
ello world
o
k

printed on the RX side

so no problem here.

funny you mention the trailing 0... did add it in my original code but did not seem make any difference whether I included it or not (so I took it out). got the same output on the RX side

sherzaad:
If I do that with my current code I get

H
ello world
o
k

printed on the RX side

so no problem here.

Then you use different programs than you are showing.

It should display something like:

H
ello world
ollo world
kllo world

There is no code that clears your static transmit buffer and you are sending all of it.

This is what I get (no delimiters on the serial monitor) after “Hello World” “ok”

H
ello World
ollo World
kllo World
char text[32];

void setup() {
  Serial.begin(115200);
}
void loop() {
uint8_t i = 0;

  if (Serial.available()) {
    while (Serial.available()) {
      text[i] = Serial.read();
      ++i;
    }
    Serial.println(text);
    delayMicroseconds(800);
  }
}

Whandall:
This is what I get (no delimiters on the serial monitor) after “Hello World” “ok”

good for you… weird that I’m getting a different result.

anyhow… from what you say a sensible conclusion to my followup question is that " there is not default delimiter so best to include one and code it in." :slight_smile:

Maybe there are minor differences between arduino types, I was using a Mega for that.

There is no way to get the claimed results (for example the single 'o') with the code you posted.

You could only send as much data as there is (up to the max of 32) and add the string delimiter in the receiver.

You should at least make shure that you don't write outside the transmit buffer.

code execution is faster than serial.available() can be updated... makes sense

ok so here another question then... to avoid this, is there away of picking up ALL the characters and tx them all without using delimiters. ie what would be the delimiter here (sending "hello world")? carriage return?

No. When it printed the "H" by itself, the other characters had not yet arrived. It is like asking you to read all the emails in your inbox. You do not know if someone is going to send you an email tomorrow so you can't read that email yet.

Carriage-return is a great delimiter to use. The Serial Monitor can be set to send different delimiters but CR+LF is the most common.

There are some Serial protocols which use the time gap between characters as the delimiter. That usually makes the protocol much more complex so I don't recommend it.