Serial between Arduinos

Seems I'm late to the party :slight_smile:

It would be much easier and simpler if you used SerialTransfer.h to automatically packetize and parse your data for inter-Arduino communication without the headace. The library is installable through the Arduino IDE and includes many examples.

Here are the library's features:

This library:

  • can be downloaded via the Arduino IDE's Libraries Manager (search "SerialTransfer.h")
  • works with "software-serial" libraries
  • is non blocking
  • uses packet delimiters
  • uses consistent overhead byte stuffing
  • uses CRC-8 (Polynomial 0x9B with lookup table)
  • allows the use of dynamically sized packets (packets can have payload lengths anywhere from 1 to 254 bytes)
  • can transfer bytes, ints, floats, and even structs!!

Example TX Arduino Sketch:

#include "SerialTransfer.h"

SerialTransfer myTransfer;

void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
  myTransfer.begin(Serial1);
}

void loop()
{
  char buff[] = "hi";

  myTransfer.txObj(buff, sizeof(buff));
  myTransfer.sendData(sizeof(buff));
  delay(100);
}

Example RX Arduino Sketch:

#include "SerialTransfer.h"

SerialTransfer myTransfer;

void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
  myTransfer.begin(Serial1);
}

void loop()
{
  if(myTransfer.available())
  {
    char buff[40];
    
    myTransfer.rxObj(buff, sizeof(buff));
    
    Serial.println("New Data: ");
    Serial.write(buff, sizeof(buff));
    Serial.println();
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
}

For theory behind robust serial communication, check out the tutorials Serial Input Basics and Serial Input Advanced.

pathogenex:
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

1. You have an analog signal (range: 0V - 5V) feeding to NANO via A5-pin. Let us assume that the present input signal is 3.3V which after digitization by the internal ADC of NANO will appear as 0x02A3 (675 = (1023/5)*3.3).

2. You want to send the value 0x02A3 (Step-1) from NANO to MEGA using hard UART Ports (UART). You have planned to use UART Port of NANO and UART3 Port (Serial3) of MEGA for communication. This is fine; however, I would suggest to use soft UART Port (SUART) for NANO as the UART Port is engaged with Serial Monitor/IDE for sketch debugging/uploading. The revised connection could be like this (Fig-1):
uartNanoMega.png
Figure-1:

3. You want that the MEGA should receive the data (0x02A3) and show it on its Serial Monitor (SM2 of Fig-1), which has been sent by NANO using write() method. You may upload the following sketch to NANO (the Sender).

#include <SoftwareSerial.h>  //needed to create SUART Port
SoftwareSerial SUART (4, 5); // SRX = DPin-4, STX = DPIn-5

void setup()
{
  SUART.begin(9600);  //needed to create/open SUART Port 
  Serial.begin(9600);
  //----------------
  analogReference(DEFAULT);  //5V Vref for the ADC of NANO
}

void loop()
{
  unsigned int sensorValue = analogRead(A5);   //3.3V --> 0x02A3
  if(sensorValue < 0x1000)
  {
    Serial.print('0'); //shows: leading 0
  }
  Serial.println(sensorValue, HEX);
  SUART.write(highByte(sensorValue));//send higher byte )0x02) as natural binary
  SUART.write(lowByte(sensorValue));//send lower byte (0xA3) as natural binary 
  delay(1500);   //test interval 
}

4. Upload the following sketch in MEGA (the Receiver)

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

void loop()
{
  byte n = Serial3.available(); //checki that a byte has arrived/stored in FIFO BUFFer
  if (n == 2 ) //check if 2 bytes have arrivd/stored
  {
    byte higByteSensorValue = Serial3.read();  //upper 8-bit
    byte lowByteSensorValue = Serial3.read();  //lower 8-bit
    //----------
    unsigned int sensorValue = (higByteSensorValue <<8)| lowByteSensorValue; //make 0x02A3
    if(sensorValue <0x1000)
    {
      Serial.print('0');   //show: leading 0
    }
    Serial.println(sensorValue, HEX); //Serial Monitor showsL 02A3 
  }
}

5. NANO's Serial Monitor (Fig-2)
smnano1x.png
Figure-2:

6. Check that MEGA's Serial Monitor (Fig-3) shows approx. 02A3 for 3.3V input in NANO.
sman.png
Figure-3:

uartNanoMega.png

sman.png

smnano1x.png

Wow thats alot thanks for the help :o
Gonna take a day to read through as see what i can do with it.
I've had a small look at the newer suggestions and the Serial.Transfer library looks very promising.
I will get back to you lot once i've learnt more.

I am changing the scope of my project to overcome some limitations, if anyone can tell me any downsides to changing this far in please dont hesitate to ask.

Changes-
-- Replace Rx MEGA with Teensy 3.2 (Multiple serials for bulk packet transfers + small form factor)
-- Replace Tx Nano with MEGA (Larger storage for internal audio proccessing before transfer)

-- Convert the Received signal to a usable analog reference for use in this code?
---OR Proccess the signal before sending it through serial and reading multiple output values at the Rx?

Also big sorry i should have mentioned earlier that the input for the audio is setup as follows. (Please ignore the D1,D2 pins output to wireless and the push switch, I have since been schooled as to why that was stupid)

From what i remember when i made this a year ago. The resitor and capacitor setup is a very simple beat detection system. Am i being special thinking mabye there is a better way to be transmitting this beat detection through serial? I feel like i might have gone in the wrong direction...

Managed to learn alot about serial transmitting yesterday so thanks again what i have learnt will not goto waste :slight_smile:

Power_Broker:
Seems I'm late to the party :slight_smile:

It would be much easier and simpler if you used SerialTransfer.h to automatically packetize and parse your data for inter-Arduino communication without the headace. The library is installable through the Arduino IDE and includes many examples.

SerialTransfer looks promising. Any more examples/Tutorials you can link through?

In short im not trying to send audio data across UART only a representation of it for use in proccessing.
I only want to convert close to every 0.5 second of audio onboard the Tx, convert them into about 20/30 variables then send these to the Rx which will then proccess/compile and output the data as needed.

Something like this.

#include <math.h>
#include <SoftwareSerial.h>

#define AUDIOPIN A0 // Analog audio input pin
#define SAMPLE_WINDOW   10  // Sample window for average level
#define INPUT_FLOOR 10 //Lower range of analogRead input
#define INPUT_CEILING 300 //Max range of analogRead input, the lower the value the more sensitive (1023 = max)300 (150)
#define NOISE     10  // Noise/hum/interference in mic signal
#define SAMPLES   64  // Length of buffer for dynamic level adjustment
#define POT_PIN    4 ////Pot for manual adjustment


////////////////////////////SAMPLES////////////////////////////
#define NSAMPLES 64
unsigned int samplearray[NSAMPLES];
unsigned long samplesum = 0;
unsigned int sampleavg = 0;
int samplecount = 0;
//unsigned int sample = 0;
unsigned long oldtime = 0;
unsigned long newtime = 0;
////////////////////////////SAMPLES////////////////////////////

///////UNSURE////////
int step = -1;
///////UNSURE////////


unsigned int sample;


int peakspersec = 0;
int peakcount = 0;


void setup() {
  
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  soundmems();
  
  ///////////////////////////////???WOULD IT BE POSSIBLE TO???///////////////////////////////
/////////////////???CONVERT TO MULITPLE ARRAYS BEFORE TRANSFER???/////////////////
///////////////////////////////////DATA TO SEND////////////////////////////////////////

  Serial.print('<');
  Serial.print(samplearray[NSAMPLES]);
  Serial.print('>');

  Serial.print('<');
  Serial.print(samplesum);
  Serial.print('>');

  Serial.print('<');
  Serial.print(sampleavg);
  Serial.print('>');
  
  Serial.print('<');
  Serial.print(samplecount);
  Serial.print('>');

  Serial.print('<');
  Serial.print(oldtime);
  Serial.print('>');

  Serial.print('<');
  Serial.print(newtime);
  Serial.print('>');

  Serial.print('<');
  Serial.print(oldtime);
  Serial.print('>');

  Serial.print('<');
  Serial.print(sample);
  Serial.print('>');

  Serial.print('<');
  Serial.print(peakspersec);
  Serial.print('>');

  Serial.print('<');
  Serial.print(peakcount);
  Serial.print('>');

///////////////////////////////???WOULD IT BE POSSIBLE TO???///////////////////////////////
/////////////////???CONVERT TO MULITPLE ARRAYS BEFORE TRANSFER???/////////////////

///////////////////////////////////DATA TO SEND////////////////////////////////////////
  
  }

void soundmems() {                                                  // Rolling average counter - means we don't have to go through an array each time.
  newtime = millis();
  int tmp = analogRead(AUDIOPIN) - 512;
  sample = abs(tmp);

  int potin = map(analogRead(POT_PIN), 0, 1023, 0, 60);

  samplesum = samplesum + sample - samplearray[samplecount];        // Add the new sample and remove the oldest sample in the array 
  sampleavg = samplesum / NSAMPLES;                                 // Get an average
  samplearray[samplecount] = sample;                                // Update oldest sample in the array with new sample
  samplecount = (samplecount + 1) % NSAMPLES;                       // Update the counter for the array

  if (newtime > (oldtime + 200)) digitalWrite(13, LOW);             // Turn the LED off 200ms after the last peak.

  if ((sample > (sampleavg + potin)) && (newtime > (oldtime + 60)) ) { // Check for a peak, which is 30 > the average, but wait at least 60ms for another.
    step = -1;
    peakcount++;
    digitalWrite(13, HIGH);
    oldtime = newtime;
  }
}  // soundmems()

So each Serial.print will only take up 3 characters (8bit) maximum
(3 * 8bits = 24bits)
There are a total of 10 Variables to send. So 10 * 24bits = 240bits Or 30Bytes
UART can communicate at 12 Mbit/sec on the teensy (From the little i have found)
What am i missing that means this won't be feasable...

Then after i have done this my plan is to replace the Tx/Rx connections with BLE modules.

I understand there are limitation of sending audio through Tx/Rx but considering its not the actual audio i want to send through and is instead 20/30 variables referencing characteristics of that signal, does that not overcome the limitations by reducing the input into managable packets?

I anyone wants to help i can pm across the file im working on.
I am happy to consider changing "Transmit method" (I.E. Serial/Wifi/BLE) if you can prove that its a benefit.