Serial between Arduinos

I require some help with serial transmittion between arduinos.
I am trying to use the nano to speak to the mega on serial3 then have the mega print what it receives to the serial monitor on serial

I am fairly new to serial comms on arduino so don’t hate on me.

This code is running on a nano.
It has to be an analog input unless you have a good idea for converting analog audio input into digital output. Which i am going to google now because i’m sure its fairly simple…

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

}

void loop() {

int sensorValue = analogRead(A5)+ '\n';

///Serial.print("I Sent: ");
  //Serial.println(sensorValue + '\n'); // Carriage end? NO 
  ///Serial.print(sensorValue, BIN); ////Binary NO
  ///Serial.write(sensorValue); ////random/Null characters NO
Serial.write((byte)sensorValue);


delay(1);
}

This code is running on the mega
I need to output as an int so i can use it for the purpose i need.
The serial3 print is so i can see /compare results on serial monitor.

// Example 2 - Receive with an end-marker

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial3.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {
    recvWithEndMarker();
    showNewData();
}

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
   
    while (Serial3.available() > 0 && newData == false) {
        rc = Serial3.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
///Serial.print("This just in ... ");
        Serial.println(receivedChars);
        newData = false;
    }
}
int sensorValue = analogRead(A5)+ '\n';

What result does your calculator give when you add a carriage return to 37, for instance?

Serial.write((byte)sensorValue);

Casting to a byte will lose data. That does not make sense to do.

PaulS:
What result does your calculator give when you add a carriage return to 37, for instance?

Fair point, I started laughing when i read this. Thank you that it’s sorely needed atm.
Removed Carriage return

PaulS:
Casting to a byte will lose data. That does not make sense to do.

What else could i cast it to? If i send as an int then what should i change about Serial3.read();

Because i can’t see any data coming in…

There's an example packaged with the IDE called AnalogInOutSerial. Have a look at that instead of trying to invent your own syntax. You can delete the parts related to the analog output. But you can at least see how to send the data via serial.

You also need to make sure you send the end marker if you want that code on the receiver to work. If you don't send a '\n' then it will never do anything.

pathogenex:
Because i can't see any data coming in...

You never sent the end marker.

Use print instead of write and don't cast it to anything. Then be sure to print a '\n' after that.

Serial.print(sensorValue);
Serial.print('\n');

Delta_G:
You never sent the end marker.

Use print instead of write and don't cast it to anything. Then be sure to print a '\n' after that.

Delta_G:
There's an example packaged with the IDE called AnalogInOutSerial. Have a look at that instead of trying to invent your own syntax. You can delete the parts related to the analog output. But you can at least see how to send the data via serial.

You also need to make sure you send the end marker if you want that code on the receiver to work. If you don't send a '\n' then it will never do anything.

You absolute legend thank you. Used print and \n in transmit file and it seems to be working to a degree except it seems to be grouping some of the readings as follows

Transmit log

21:06:33.673 -> 0
21:06:33.673 -> 0
21:06:33.706 -> 23
21:06:33.706 -> 141
21:06:33.706 -> 18
21:06:33.706 -> 0

Receive Log

21:06:33.833 -> 0
21:06:33.833 -> 02314118
21:06:33.867 -> 
21:06:33.867 -> 0
21:06:33.867 ->

So why is this happening?

What do you mean grouping? That they all come at the same time? You don't have much delay between them in the sender. It will spam readings as fast as it can until it gets the send buffer full. Then once it's full the next call to print will block until there is room, so it waits for a little space to open up and then spams in a bunch more readings.

But since that output didn't come from the program you posted I'm really just guessing. It may also be that the bytes are getting there and being read out in bursts. I don't know where the time stamps are coming from.

Delta_G:
What do you mean grouping? That they all come at the same time? You don't have much delay between them in the sender. It will spam readings as fast as it can until it gets the send buffer full. Then once it's full the next call to print will block until there is room, so it waits for a little space to open up and then spams in a bunch more readings.

So there's no way to have it read and receive data from a single line at the same time or at least on a one in one out basis?

I just need the serial.read to match the write. Can i do this by setting the max character sent to 3 so it never reads higher? Im trying to transmit audio if that helps? So i need the timing to be close enough to work.

Delta_G:
I don't know where the time stamps are coming from. But since that output didn't come from the program you posted I'm really just guessing. It may also be that the bytes are getting there and being read out in bursts.

Sorry im in the distant past and am stuck in a timeloop... Just ignore the timestamps...

pathogenex:
So there's no way to have it read and receive data from a single line at the same time or at least on a one in one out basis?

To send and receive takes two lines, an Rx and a Tx. Yes they can send and receive at the same time. I'm not sure what you mean here. Can you describe in words what you want to have happen? Explicitly describe, not abstractly. Like what is the actual project idea supposed to be doing here.

pathogenex:
I just need the serial.read to match the write. Can i do this by setting the max character sent to 3 so it never reads higher?

I have no idea what you're talking about. The reads always match the writes. What gets written on one end gets read on the other. Do remember that it isn't instantaneous, it takes some time and goes one byte at a time.

pathogenex:
Sorry im in the distant past and am stuck in a timeloop... Just ignore the timestamps...

OK, then I have no idea what you meant by the last comment. What is the problem with that data that you showed. What do you mean by "seems to be grouping some of the readings". What is the desired behavior? What is the actual behavior? How do those two things differ?

I use the third example in Serial Input Basics for communication between Arduinos. Having start and end markers makes it more reliable. You can send data in a compatible format with code like this

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

…R

Delta_G:
To send and receive takes two lines, an Rx and a Tx. Yes they can send and receive at the same time. I'm not sure what you mean here. Can you describe in words what you want to have happen? Explicitly describe, not abstractly. Like what is the actual project idea supposed to be doing here.

Thank you for helping.
End result is to have audio data transmitted from one arduino to another using Serial Comms and having a usable received int the same length as was seen in the serial monitor output.

Delta_G:
I have no idea what you're talking about. The reads always match the writes. What gets written on one end gets read on the other. Do remember that it isn't instantaneous, it takes some time and goes one byte at a time.

What speeds are we talking about? A few milli seconds doesnt really bother me but seconds or more becomes problematic...

Delta_G:
OK, then I have no idea what you meant by the last comment. What is the problem with that data that you showed. What do you mean by "seems to be grouping some of the readings". What is the desired behavior? What is the actual behavior? How do those two things differ?

So if the nano sends two lines

0
28

I want the Mega to read out at reasonable speed (millis no seconds)

0
28

But if i have to asign a 3charater limit to prevent the data being clumped together in the buffer then could i have the nano send

000
028

And have the mega only take in 3 characters then proccess them? Again all time related.

The end marker is what keeps them from being clumped together. It lets the receiver know that it has one complete transmission and it can do whatever with that.

The problem with the clumping is in your receiving code. I know you told me to ignore the time-stamps, but they mean that the output you posted comes from a different program and not the one you posted. We can't help you with the clumping because we can't see the source of the clumping. You haven't posted the code that's causing it.

When we talk about speed, that's the baud rate. You select the baud rate. Do some googling and see if you can see how baud rate relates to the speed of your characters.

You mention audio, let me pause you and ask what your end goal is. You know most Arduino are woefully underpowered to do much with audio. Usually when someone mentions audio around here they usually end up at a dead end needing a different chip.

Robin2:
I use the third example in Serial Input Basics for communication between Arduinos. Having start and end markers makes it more reliable. You can send data in a compatible format with code like this

Serial.print('<'); // start marker

Serial.print(value1);
Serial.print(’,’); // comma separator
Serial.print(value2);
Serial.println(’>’); // end marker




...R

I think you just did it… Well both of you helped clearly but i think ive got it working.

Nano Tx - Serial Input Basics 3

const int analogInPin = A5;  // Analog input pin that the potentiometer is attached to


int sensorValue = 0;        // value read from the pot

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  // read the analog in value:
  sensorValue = analogRead(analogInPin);
  // map it to the range of the analog out:


  // print the results to the Serial Monitor:
  //Serial.print("sensor = ");
  Serial.print('<');
  Serial.print(sensorValue);
  Serial.print('>');


  // wait 2 milliseconds before the next loop for the analog-to-digital
  // converter to settle after the last reading:
  delay(2);
}

Mega Rx

// Example 3 - Receive with start- and end-markers

const byte numChars = 32;
char receivedChars[numChars];

boolean newData = false;

void setup() {
    Serial3.begin(9600);
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {
    recvWithStartEndMarkers();
    showNewData();
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (Serial3.available() > 0 && newData == false) {
        rc = Serial3.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        ///Serial.print("This just in ... ");
        Serial.println(receivedChars);
        newData = false;
    }
}

Delta_G:
The end marker is what keeps them from being clumped together. It lets the receiver know that it has one complete transmission and it can do whatever with that.

The problem with the clumping is in your receiving code. I know you told me to ignore the time-stamps, but they mean that the output you posted comes from a different program and not the one you posted. We can’t help you with the clumping because we can’t see the source of the clumping. You haven’t posted the code that’s causing it.

When we talk about speed, that’s the baud rate. You select the baud rate. Do some googling and see if you can see how baud rate relates to the speed of your characters.

You mention audio, let me pause you and ask what your end goal is. You know most Arduino are woefully underpowered to do much with audio. Usually when someone mentions audio around here they usually end up at a dead end needing a different chip.

Those bits of code i posted are what the serial was outputting.
Now it looks like so

Nano Tx

22:09:42.694 → <0><28><15><66>

Mega Rx

22:09:44.681 →
22:10:08.798 → 0
22:10:08.798 → 28
22:10:08.798 → 15
22:10:08.798 → 66

This is what im using to read the input but i want the serial data in to replace the analogRead( BASS PIN);

uint16_t auxReading(uint8_t channel) {

  int n = 0;
  uint16_t height = 0;

  if(channel == 0) {
    int n = analogRead( BASS_PIN); // Raw reading from left line in
    n = abs(n - 512 - DC_OFFSET); // Center on zero
    n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
    lvlLeft = ((lvlLeft * 7) + n) >> 3; // "Dampened" reading (else looks twitchy)
    volLeft[volCountLeft] = n; // Save sample for dynamic leveling
    volCountLeft = ++volCountLeft % SAMPLES;
    // Calculate bar height based on dynamic min/max levels (fixed point):
    height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft);
  }
  
  else {
    int n = analogRead( MID_PIN); // Raw reading from mic
    n = abs(n - 512 - DC_OFFSET); // Center on zero
    n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
    lvlRight = ((lvlRight * 7) + n) >> 3; // "Dampened" reading (else looks twitchy)
    volRight[volCountRight] = n; // Save sample for dynamic leveling
    volCountRight = ++volCountRight % SAMPLES;
    // Calculate bar height based on dynamic min/max levels (fixed point):
    height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight);
  }

Ok so those time stamps and clumping are an artifact of how your aerial terminal is getting the data from the mega, not necessarily anything g to do with what the mega sees. Start taking some actions on the mega based on what you receive. Light a light or something when you get a certain character.

Delta_G:
Ok so those time stamps and clumping are an artifact of how your aerial terminal is getting the data from the mega, not necessarily anything g to do with what the mega sees. Start taking some actions on the mega based on what you receive. Light a light or something when you get a certain character.

I have added code above showing where i want this Rx signal to be read. So now i need to find a way to get it in there.
I’m guessing i can use

BASSPIN = map(char receivedChars[numChars], 0, 1023, 0, 255);

Or have i gone to far again?

Yeah you’re almost there. Don’t get distracted by the terminal output on the computer. You have a packet with the data in it. Mega is getting it and acting. You just need an atoi command to convert the ascii value back to an int variable and you can use it where that analogRead was.

 char receivedChars[numChars] = map(sensorValue, 0, 1023, 0, 255);

You need to understand the difference between a number with a numerical value and a string of ascii text. They aren’t as interchangeable as you seem to want them to be.

Let the print function handle conversion on the sender. It just needs Serial.print(sensorValue); and lines to print start and end markers. Or if you want to scale to 255 on the sender side do that but still just print the number with Serial.print and let print do conversion to ascii.

Then the receiver has to collect ascii characters into a buffer until it gets to the end (you’ve got that already) then use atoi to get an int variable from that.

Delta_G:

 char receivedChars[numChars] = map(sensorValue, 0, 1023, 0, 255);

You need to understand the difference between a number with a numerical value and a string of ascii text. They aren’t as interchangeable as you seem to want them to be.

Let the print function handle conversion on the sender. It just needs Serial.print(sensorValue); and lines to print start and end markers. Or if you want to scale to 255 on the sender side do that but still just print the number with Serial.print and let print do conversion to ascii.

Then the receiver has to collect ascii characters into a buffer until it gets to the end (you’ve got that already) then use atoi to get an int variable from that.

So in void loop should convert the char string to an int?

BASSPIN = atoi(receivedChars[numChars]);

Not exactly. atoi wants a pointer. So lose the [numChars] part and just put

BASSPIN = atoi(receivedChars);

Do that in your function that processes your new message.