Trying to set up 2 different UART channels for BPM and Button data

This application consists of 2 arduino iot 33, 1 sender and one receiver. The issue involves sending BPM and Button data to the receiver from the sender. On the sender are 6 buttons with 1 acting as the tap tempo button and the other 5 acting as selection buttons.

I started working with 1 UART channel to send BPM data from my application (worked perfectly). I then realized I needed to send button presses from 5 different buttons over UART as well. Now I know I can fit the 3 chars of a bpm and the 5 button chars for a total of 8 chars but I need the buttons and the BPM to send at different timings: BPM data at a set time and the button data whenever they are pushed. When I added the second UART channel, things stopped working entirely on the sender arduino. I'm at a loss for what to do. Any help is very much appreciated.

Another thing: I've made sure that my new serial wiring is correct with sercom being set up on pins 5 and 6 on each of the 2 arduinos, making sure pin5(RX) on the sender connects to pin6(TX) on the receiver and pin6(TX) on the sender connected to pin5(RX) on the receiver.

Sender Code

#include <ArduinoTapTempo.h>
#include <Bounce2.h>

const int BUTTON_PIN = 9;
const int LED_PIN = A5;  // Pin for the LED
const int SERIAL_BAUD_RATE = 9600;
ArduinoTapTempo tapTempo;

const int ledPins[] = { 13, A1, A2, A3, A4 };  // Define an array of button pins
const int numLEDs = 5;                         // Number of LEDs
const int buttonPins[] = { 4, 2, 3, 7, 8 };    // Define an array of button pins
const int numButtons = 5;
int buttonChar[numButtons];

int bpmAdjust = 0;
int currentBPM = 120;  // Store the current BPM
int adjustedBPM = 120;
int persistantBPM = 120;
bool resetDownbeat = false;
unsigned long resetTime = 0;

unsigned long lastUpdateMillis = 0;
const unsigned long updateInterval = 10;

unsigned long previousMillis = 0;
unsigned long interval;

Bounce resetButton = Bounce();
Bounce buttons[5];  // Create an array of debounced buttons

bool ledState[5] = { false };     // Store the state of each LED
bool resetButtonPressed = false;  // Flag to track reset button press

unsigned long previousTimer = 0;       // Initialize a variable to store the last time the code ran
const unsigned long timerInter = 500;  // Interval in milliseconds (1 second)

Uart mySerial (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0); // <----- this is what was added that broke the tap tempo functionality.

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);

  Serial.begin(9600);
  Serial1.begin(9600); // BPM sent over Serial1
  mySerial.begin(9600); // Button data send over mySerial

  tapTempo.setTotalTapValues(4);
  tapTempo.setBeatsUntilChainReset(8);
  tapTempo.setMaxBPM(200);
  tapTempo.setMinBPM(40);

  for (int i = 0; i < 5; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);  // Set button pins as INPUT_PULLUP
    pinMode(ledPins[i], OUTPUT);           // Set LED pins as OUTPUT
    buttons[i].attach(buttonPins[i]);
    buttons[i].interval(50);  // Debounce interval in milliseconds
  }

  delay(1000);
}

void loop() {
  unsigned long currentTimer = millis();  // Get the current time
  for (int i = 0; i < 5; i++) {
    buttons[i].update();  // Update the button states

    if (buttons[i].fell()) {                  // Button pressed
      ledState[i] = !ledState[i];             // Toggle LED state
      digitalWrite(ledPins[i], ledState[i]);  // Update the LED state
    }
  }

  for (int i = 0; i < 5; i++) {
        bool buttonState = digitalRead(buttonPins[i]);
        mySerial.print("Button ");
        mySerial.print(i + 1);
        mySerial.print(": ");
        mySerial.println(buttonState);
    }

  bool buttonDown = digitalRead(BUTTON_PIN) == LOW;
  tapTempo.update(buttonDown);

  currentBPM = tapTempo.getBPM();
  adjustedBPM = currentBPM + bpmAdjust;
  unsigned long currentMillis = millis();

  interval = 60000 / adjustedBPM;
  // Serial.println(adjustedBPM);
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));  // Toggle the LED state
    Serial.println(adjustedBPM);
  }

  if (currentTimer - previousTimer >= timerInter) {
    previousTimer = currentTimer;  // Update the previous time
    // Serial.println(currentBPM);

    if (currentBPM >= 50 && currentBPM <= 250) {
      // send bytes
      transmitterBPM(currentBPM);
    }
  }
}

void transmitterBPM(int bpm) {
  // Serial.println(bpm);
  if (bpm >= 100 && bpm <= 999) {
    byte highByte = bpm / 100;
    byte middleByte = (bpm / 10) % 10;
    byte lowByte = bpm % 10;

    Serial1.write(highByte);
    Serial1.write(middleByte);
    Serial1.write(lowByte);
  }
}

Receiver Code

#include <Bounce2.h>

int bpmAdjust = 0;
int currentBPM;  // Store the current BPM
int adjustedBPM;
int persistantBPM;
int previousBPM;

// UART
int bitOne = 1;
int bitTwo = 1;
int bitThree = 0;
unsigned long previousTimer = 0;       // Initialize a variable to store the last time the code ran
const unsigned long timerInter = 500;  // Interval in milliseconds (1 second)
Uart mySerial(&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0);

enum ReceiverState {
  IDLE,
  WAIT_FOR_BUTTON,
  PROCESS_BUTTON_DATA
};

ReceiverState receiverState = IDLE;
String receivedDataBuffer = "";

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

void loop() {
  unsigned long currentTimer = millis();  // Get the current time

  if (currentTimer - previousTimer >= timerInter) {
    previousTimer = currentTimer;  // Update the previous time

    if (Serial1.available() >= 3) {
      bitOne = Serial1.read();
      bitTwo = Serial1.read();
      bitThree = Serial1.read();
    }

    String concatenatedString = String(bitOne) + String(bitTwo) + String(bitThree);
    currentBPM = concatenatedString.toInt();
  }


  receiver();
  if (currentBPM != previousBPM) {
    previousBPM = currentBPM;
  }
}


void receiver() {
  if (mySerial.available() > 0) {
    char receivedChar = mySerial.read();
    processReceivedChar(receivedChar);
  }
}

void processReceivedChar(char receivedChar) {
  switch (receiverState) {
    case IDLE:
      if (receivedChar == 'B') {
        receiverState = WAIT_FOR_BUTTON;
        receivedDataBuffer = "";
      }
      break;

    case WAIT_FOR_BUTTON:
      if (receivedChar == ':') {
        receiverState = PROCESS_BUTTON_DATA;
      } else {
        receivedDataBuffer += receivedChar;
      }
      break;

    case PROCESS_BUTTON_DATA:
      // Process the button data
      int buttonNumber = receivedDataBuffer.toInt();
      processReceivedData(buttonNumber);

      // Return to the IDLE state
      receiverState = IDLE;
      break;
  }
}

void processReceivedData(int buttonNumber) {
  Serial.print("Button Pressed: ");
  Serial.println(buttonNumber);
}

You seem to use Serial protocols for human reading, but send from one controller to another one.

In a machine readable protocol you could encode the BPM into 2 bytes and all the button states into 1 byte. Then mark the button state code different from the first BMP code, so that the receiver can distinguish a 1-byte button message from a 2-byte BMP message on the same Serial port.

Thank you for pointing me the right direction. However I'm still lost on how to do the encoding into bytes part.