Issue storing QR in EEPROM and transmitting over RS485

I'm building a master/slave project using RS485. This all worked at one point in the past as intended but my gut tells me I likely have some older code saved on my computer that is not up to date with what once worked.

I can confirm the slave correctly communicates to the master because it's able to transmit the string "New feeder detected with UUID:" followed by what is supposed to be a unique identifier number like 85AE4826-F9B8-42A1-A2A4-DE9446317FCD but instead the UUID is garbage: �������������������������������

I'm using this Waveshare barcode scanner to scan a QR code and store it in the slave's EEPROM. I can confirm the waveshare scanner works as intended when I hook it up to an Arduino and directly output to serial monitor.

I'm hoping someone can take a look at the slave code attached (made up of a few files - I omitted ones that I believe are irrelevant like NeoPixel control files) and let me know what's wrong in my code that's causing this to read out garbage when I connect a slave to the master's serial monitor. I've tried setting my serial monitor on my master at both 57600 baud and 9600, no luck. Also have Both NL & CR enabled if it matters (I assume not since the first part of the string gets sent successfully).

I've also attached the master code in the first code block. Any help appreciated!

Master Code

  pinMode(EnRS485,INPUT);
  Serial1.begin(9602);
  Serial.begin(57600);
  while(Serial.available()>0);
  Serial.print("S");
}
void loop(){
  updateData();
}
void updateData(){
  if(Serial1.available()>5){
    String e=Serial1.readStringUntil('\r');
    Serial.println(e);
  }
  if(Serial.available()>1){
    String t=Serial.readStringUntil('\r');
    const char* c=t.c_str();
    if(strstr(c,"M602")){
      t=t.substring(4,t.length()-2);
      FeederUUID=t.substring(1,t.indexOf(' ')-1);
      int d=t.substring(t.indexOf(' ')).toInt();
      int dir=2;
      digitalWrite(EnRS485,LOW);
      Serial1.print("<"+FeederUUID+","+String(d)+","+String(dir)+">\r");
      delay(5);
    } else if(strstr(c,"M603")){
      t=t.substring(4);

Slave Code files from here on

Main file:

#include <SoftwareSerial.h>

int RequestedDistance = 0;         //Holds target distance information for feeder motor
boolean CoverSensorValue;          //true if cover is open
boolean TensionSensorValue;        //true if no tension is sensed
boolean isRSCommand=false;         //true when last received move motor command is RS command
boolean isFeederActive=true;       //True if feeder motor is moving right now
boolean LockPeelingMotor=true;     //Makes sure peeling motor is locked once operation is done, so error messages "halted" isnt shown

String FeederUUID;
String EEPROMUUID;

//UUID
int ee_address = 0;
const byte numChars = 37;
char uuid[numChars];   // an array to store the received data
char default_uuid[numChars] = "00000000-0000-0000-0000-000000000000\0";
//edcfeb27-de3c-46bb-9b83-cea63a52c36b
struct UUID {
  char is_uuid;
  char _uuid[numChars];
};
struct UUID eeprom_uuid;
boolean newData = false;

void setup() {
  initNeoPixel(); // Initialize LED
  setLedState(LED_READY);
  pinMode(ENCA,INPUT);
  pinMode(CoverSensor,INPUT);
  pinMode(TensionSensor,INPUT);
  pinMode(MotorFeedPINA,OUTPUT);
  pinMode(MotorFeedPINB,OUTPUT);
  pinMode(MotorPeelPINA,OUTPUT);
  pinMode(MotorPeelPINB,OUTPUT);
  pinMode(EnRS485, OUTPUT);               //DE/RE Controling pin of RS-485
  pinMode(ForwardButton,INPUT_PULLUP);
  delay(5);
  readStringFromEEPROM(0, &EEPROMUUID);
  EEPROMUUID.remove(EEPROMUUID.length()-1);
  delay(5);
  // send “EEPROM: <uuid>” in one RS-485 transaction:
  {
    String banner = "New feeder dete

void readButtons(){
  if(digitalRead(ForwardButton)==LOW){
    if(MotorReverseDir==1){MotorFeedDirection=0;}
    while(digitalRead(ForwardButton)==LOW){
      MoveMotor(0,FeederSpeed,MotorFeedDirection);//Feed motor, speed, direction
      HandlePeeling();
    }
    RequestedDistance = 1;
    MotorPosition = 0;

    
    while(digitalRead(ReverseButton)==LOW){
      MoveMotor(0,FeederSpeed,MotorFeedDirection);//Feed motor, speed, direction
    }
    RequestedDistance = 1;
    MotorPosition = 0;
    isRSCommand=false;
  }
}

SerialFunctions.ino



        RequestedDistance=RequestedDistance/DistanceDivider;

        isRSCommand=true;
        LockPeelingMotor=false;
        MotorPosition = 0;
        PeelingTimer=millis();
      }
    }
    Serial.flush();
  }
}

void sendserial(String dat){
  digitalWrite(EnRS485 , HIGH);
  delay(1);
  Serial.print(dat);
  delay(20);
  digitalWrite(EnRS485 , LOW);
}

UUID.ino


        // terminate and flag
        uuid[ndx] = '\0';
        ndx = 0;
        newData = true;
      }
    }

    if (newData) {
      newData = false;
      // echo and save
      sendserial("Feeder address: " + String(uuid) + "\n");
      writeStringToEEPROM(0, String(uuid));
    }
  }
}


int readStringFromEEPROM(int addrOffset, String *strToRead) {
  int newStrLen = EEPROM.read(addrOffset);

  }
  data[newStrLen] = '\0';             // ← correct null terminator!
  *strToRead = String(data);
  return addrOffset + 1 + newStrLen;
}

What boards are you using, exactly?

I'm using custom boards that worked before for sure. The slave is Atmega328P and the master is Atmega32u4.

String (capital S) concatenation in the way you do (in both applications) chews memory due to the creation of temporary String objects. Rather use += or concat().
There is also no need to concatenate; you can simply use a few print statements, it will achieve the same.

I do not know if this is the cause of the issue.

It seems that the if and else branches has swapped here:

So I changed the previous to this new version, but now everything is garbage, no legible text outputs. Did I do it wrong?

  // send “EEPROM: <uuid>” in one RS-485 transaction:
  {
    String banner = "New feeder detected with UUID: " + EEPROMUUID + "\n\n";
    digitalWrite(EnRS485, HIGH);
    Serial.print(banner);
    Serial.flush();
    digitalWrite(EnRS485, LOW);
  }

changed to this new version:

  sendserial("EEPROM: ");
  sendserial(EEPROMUUID);
  sendserial("\n\n");

Also when I send for example M603 85AE4826-F9B8-42A1-A2A4-DE9446317FCD 4 command to move a small motor on the slave, nothing happens on the slave, whereas before that used to work.

Exactly how do you combine these files (.ino)?
Right now your main file does not compile.

It compiles just fine, I just excluded the neopixel stuff.

@shai Did you fixed the error, mentioned in post #5?

Please publish the code as message text using code tags rather than force the others to download your archives.

@b707 I even purchased a new Waveshare barcode scanner, still same problem. I think if the "Slave EEPROM:" string is sent from the slave to master via RS485, then the RS485 communication is fine? It seems to boil down to something related to the UUID either not being saved in EEPROM or not being transferred properly via RS485.

@shai
You did over-complicate the program. Don't put everything together.
Why do you need motors and Neopixel if you are debugging the transfer via Serial? Write small programs that each do only one thing. For example, get the ID from the scanner and send it to the monitor. And another writes a line with the ID to EEPROM. And until you debug them separately, don't add anything.

Unfortunately this code is above my level of understanding so I wouldn't even know where to begin. I already tested the scanner output directly via serial monitor, so that part at least works fine using Waveshare's recommended test code:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 12);  //Rx=11, Tx=12

void setup() {
  Serial.begin(115200);
  mySerial.begin(9600);
}

void loop() {
  if (mySerial.available()) {
    String receivedData = mySerial.readStringUntil('\n'); // Read entire data until newline character
    Serial.println(receivedData); // Print the data to Serial Monitor
  }
}

in this case I don't see any option for you but learning. Your actual code became too big to debug, especially for someone who don't understand it.

At least that's how I would do it myself in your situation - break the code into parts and debug one piece at a time.

That is the problem with copying someone else's monstrosity. The chances of it working "out of the box" for a beginner is close to zero, because there are too many ways to make fatal mistakes.

To learn this material, start with simple examples from the device libraries and get them working, one at a time. Once you understand each one reasonably well, then start adding the pieces together.

Didn't you had almost the same line in your last code?

const modificator changes nothing in your case.

Put in Serial.print statements to see what the functions readStringFromEEPROM and scanUUID, etc. are doing internally.

For example in scanUUID:

  if (newData) {
  Serial.print("scanUUID: ");  //debug
  Serial.println(uuid);
    FeederUUID = String(uuid);

In readStringFromEEPROM:

  int len = EEPROM.read(addrOffset);
  Serial.print("EEPROM returned len ");
  Serial.println(len);