Arduino Uno, trouble using 2 serial devices

Hello, I am fairly new to arduino, and I have a project I'm working on with an Arduino Uno R3, a laser distance sensor, an accelerometer, and an lcd display. It will be a golf rangefinder, where I point the laser at the hole, and it tells me the lateral distance to the hole, which is calculated using the distance measured by the laser, combined with the angle relative to the horizon that the accelerometer measures.

Everything I have done so far works in isolation, the laser measures the distance very accurately, and the accelerometer gives the correct angle. The problem is when I have both going at the same time. It seems the serial data being sent is being interfered with. When the laser sends its distance measurement, the accelerometer measures less than 1 degrees no matter the orientation, but if I disconnect the laser or move it around quickly so it can't get a measurement, then the accelerometer displays the correct angle for the orientation. I have tried many different solutions, including AltSoftSerial, and NeoSWSerial plus using the built-in hardware serial connection. With AltSoftSerial, I tried the laser in pins 8, 9, accelerometer in 2, 3, same issue, with NeoSWSerial, I tried the laser in pins 8, 9, and the accelerometer in 0, 1, again with the same issue.

Again, I'm not very experienced, so maybe there is a combination that I've overlooked that could fix this using these different software serial libraries, so I would be willing to try suggestions for this. I had hoped that by staggering the laser and accelerometer, as well as using the listen command, that I could avoid the interference that can occur between multiple software serial connections. If it doesn't seem like this can be done on an Uno, I'm assuming a Mega would be able to work with two hardware serial connections, therefore avoiding interference?

The code is shown below. If you would like me to add the code I used when testing out the AltSoftSerial or NeoSWSerial combinations, I can, but I didn't want to make this too long of a post.

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


SoftwareSerial laserSerial(10,11); // Laser Serial Connection, (10, 11)
SoftwareSerial angleSerial(12,13); // Accelerometer Serial Connection, (12, 13)
LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C Setup for LCD Display  

char distanceStr[8];
double distance;
double verticalDist;
double lateralDist;
short pitch;
byte rollL;
byte rollH;
byte pitchL;
byte pitchH;
byte yawL;
byte yawH;
byte command[] = {0x80, 0x06, 0x03, 0x77};
float pitchAngle;

void setup() {
  // Arduino Serial Monitor Setup
    Serial.begin(57600);
  // Laser Serial Setup
    laserSerial.begin(9600);
  // Accelerometer Serial Setup
    angleSerial.begin(115200);
  // LCD Setup
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
  // Send the command to start continuous measurement
    laserSerial.write(command, sizeof(command));
    laserSerial.flush();
    Serial.println("Setup Complete");
  }

void loop() {
    // Set the listening port to the accelerometer
      angleSerial.listen();
      delay(50);
    // Clear Buffer
      while(angleSerial.available()){
        angleSerial.read();
        }
      delay(125);
    // Read the incoming angle data
      while (angleSerial.available()) {
        byte incomingByte = angleSerial.read();
      
      // Look for the angle output header 0x55 0x53
        if (incomingByte == 0x55 && angleSerial.peek() == 0x53) {
          angleSerial.read(); // Read the 0x53 byte
      
        // Read angle data
          rollL = angleSerial.read();
          rollH = angleSerial.read();
          pitchL = angleSerial.read();
          pitchH = angleSerial.read();
          yawL = angleSerial.read();
          yawH = angleSerial.read();
          break;
          }
        }
      
  
  // Set the listening port to the laser
    laserSerial.listen();
    delay(50);
  // Clear Buffer
    while(laserSerial.available()) {
      laserSerial.read();
      }
    delay(125);
  // Wait for the sensor to take the measurement and send the data
    while(laserSerial.available()) {
      if (laserSerial.read() == 0x80) {
      // Read the incoming data
        byte data[10];
        for (int i = 0; i < 10; i++) {
          data[i] = laserSerial.read();
          }

      // Convert the distance data from ASCII to a string
        for (int i = 0; i < 7; i++) {
          distanceStr[i] = char(data[i + 2]);
          }
        distanceStr[8] = '\0';
        break;
  
        }
      }
  
    // CALCULATIONS
    // Convert the string to a float
      distance = atof(distanceStr);
      distance=distance*3.28084;
    // Convert data to angle
      short pitch = (short)((pitchH << 8) | pitchL);
    // Calculate actual angle
      pitchAngle = pitch / 32768.0 * 180.0;
    // Calculate Vertical Distance
      verticalDist = distance*sin((2*3.1415/360)*pitchAngle);
    // Calculate Lateral Distance
      lateralDist = sqrt((distance*distance)-(verticalDist*verticalDist));
     
    // RESULTS
      lcd.clear();
    // Display the distance on LCD
      lcd.setCursor(5,1);
      lcd.print(distance);
      lcd.printstr(" feet");
    // Display the lateral distance on LCD
      lcd.setCursor(5,2);
      lcd.print(lateralDist);
      lcd.printstr(" feet");
    // Display the vertical on LCD
      lcd.setCursor(3,3);
      lcd.print(verticalDist);
      lcd.printstr(" feet");
    // Print angle to serial monitor
      Serial.print(" Pitch: ");
      Serial.print(pitchAngle);
      Serial.println();
      Serial.flush();

  // Delay for 50ms before next loop iteration
  delay(50);
  }

An accelerometer does not measure angles!

Software Serial can work, but it's generally not a good solution. Doesn't look like you're using anything unusual library wise, so try an Arduino Nano Every - up to 4 serial ports, though not well documented on the Arduino site, the information can be found in the back trail of this forum.

I found this topic useful to get up to speed.

1 Like

In a strict definition of accelerometer, yeah, but this is what I'm using: Witmotion WT61C. I just refer to it as such because that's what they called it. My problem is not measuring the angle, as I said, it all works fine in isolation.

Not sure you can run a software serial at 115200 baud.
As suggested use a board with hardware serials.

Integrating acceleration to speed, then again to distance involves a lot of mathematical hazard. As long as You're satisfied, go on.

Nope. Highest I've seen reported was 38400, and that's beyond notes in the actual library. 9600, 19200, sure.
But even then. Lots of ifs, ands, and buts.

1 Like

True. Yiu can't. The maximum speed working safely is 38400 but that's on the limit and is affected by other use of the controller resources..

Will look into it, how difficult is this to do? If I'm reading it correctly, you install the MegaCoreX onto the Nano Every, then I'll need to use the Uno R3 to program it? Then it should be as simple as plug it in and change the code to use Serial1, Serial2?

It definitely runs at 115200, but only with just the accelerometer plugged in. It does print out the correct angle to the serial monitor. This is me slowly rotating it, and the serial monitor displaying the angle:

image_2024-08-08_162857016

Was hoping there was something obvious in my code that was causing the issues, but it looks like I'll be trying a board with more hardware serials.

No doubt I believe you, I was only saing it is not safe/reliable running a software serial at such high speed ( did't even know it could work ).
An hardware serial is the way to go.
If you have ( for example ) at hand an esp32 board you can test it with little modification ( only consider it operates at 3.3V and is not 5V tolerant, so your sensors/serials should work at this voltage )

Software serial is nice but it only works in Simplex or Half Duplex mode (It can transmit or receive but not concurrently) It tends to have problems above 9600 baud. If your project is not cost sensitive use a MEGA or similar with several hardware serial channels. If you are sending anything to the console it is a good idea to have its baud at least 2X the baud rate of the incoming data. These are not fixed rules but learned via experience over the years. And YES there are cases where this will be wrong something will work but how reliable will that be.

Simplex mode is a uni-directional communication. Half Duplex mode is a two-way directional communication but one at a time. Full Duplex mode is a two-way directional communication simultaneously. Sender and Receiver. In simplex mode, Sender can send the data but that sender can't receive the data.

This link will help: https://www.youtube.com/watch?v=07pFHyOrN_k

Thanks everyone for the help, was not expecting so many responses this fast. I'll report back once I've gotten the Nano Every as was suggested.

Took me about 15 minutes, once I had the Every in hand. PM me if you have trouble, I'll look at it.

You don't need a Uno to program a Nano Every, with or without MegaCoreX. Program through the USB connection as usual.