Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atom Serial TX is full of errors when it simultaneously receives Serial data #86

Open
2 tasks done
thomasfredericks opened this issue Nov 12, 2024 · 0 comments
Open
2 tasks done

Comments

@thomasfredericks
Copy link

Describe the bug

When the Atom Lite is NOT receiving data, it transmits data to the computer without an error.
serial-receive

When the Atom Lite IS simultaneously receiving data, many errors appear in the data sent to the computer.
serial-send-receive

To reproduce

Here is an Arduino sketch. Serial is configured at baud 115200. It simply puts any received data in a array and it sends out the values 0 to 255 in a loop constantly.

//#include <M5Atom.h>

unsigned long monChronoMessages;

int inBuffer[256];
int inBufferIndex;
int outBufferIndex;

void setup() {
  // put your setup code here, to run once:
 // M5.begin(false, false, false);

  Serial.begin(115200);

  delay(5000);
}



void loop() {
  // put your main code here, to run repeatedly:

  // À CHAQUE 20 MS I.E. 50x PAR SECONDE
  if (millis() - monChronoMessages >= 20) {
    monChronoMessages = millis();

    for (int i = 0; i < 33; i++) {
      Serial.write(outBufferIndex);
      Serial.flush();
      outBufferIndex = (outBufferIndex + 1) % 256;
    }
  }

  while (Serial.available()) {
    inBuffer[inBufferIndex] = Serial.read();
    inBufferIndex = (inBufferIndex + 1) % 256;
  }
}

Here is a Python test program that checks that all incoming data is the sequence of numbers 0 to 255. If a number falls out of sequence it means that there is was an error while transmitting the data.

Install Serial for Python first:
pip install pyserial

import serial
import time
import threading
import sys
import select

def send_sequence(ser, batch_size=33, delay=0.1, stop_event=None):
    try:
        while not stop_event.is_set():
            for start in range(0, 256, batch_size):
                # Generate the batch of 33 numbers (or fewer if at the end of the sequence)
                batch = list(range(start, min(start + batch_size, 256)))
                ser.write(bytes(batch))
                #print(f"Sent batch: {batch}")
                time.sleep(delay)
                if stop_event.is_set():
                    break

    except serial.SerialException as e:
        print(f"Serial error in sender: {e}")
    except KeyboardInterrupt:
        print("Stopping sender...")

def check_sequence(ser, stop_event=None):
    try:
        expected_value = 0  # Start expecting from 0
        ignore_first = True
        while not stop_event.is_set():
            if ser.in_waiting > 0:
                byte = ser.read(1)
                received_value = int.from_bytes(byte, byteorder='big')
                if ignore_first == True:
                    expected_value = (received_value + 1) % 256
                    ignore_first = False
                else:
                    if received_value == expected_value:
                        #print(f"Received correct value: {received_value}")
                        expected_value = (expected_value + 1) % 256
                    else:
                        print(f"Sequence error! Expected {expected_value} but got {received_value}")
                        expected_value = (received_value + 1) % 256

    except serial.SerialException as e:
        print(f"Serial error in receiver: {e}")
    except KeyboardInterrupt:
        print("Stopping receiver...")

def main():
    serial_port = 'COM3'  # Replace with your actual serial port
    baud_rate = 115200
    stop_event = threading.Event()  # Create an event to control stopping the threads

    try:
        # Instantiate the serial connection once
        ser = serial.Serial(serial_port, baud_rate)
        print(f"Connected to {serial_port} at {baud_rate} baud.")

        # Create and start the sending and receiving threads with the shared ser instance
        send_thread = threading.Thread(target=send_sequence, args=(ser, 63, 0.1, stop_event))
        receive_thread = threading.Thread(target=check_sequence, args=(ser, stop_event))

        send_thread.start()
        receive_thread.start()

        # Wait for any key press to stop the threads
        print("Press ctrl+C to stop...")
        input()  # Wait for user input

        # Set the stop event to signal both threads to exit
        stop_event.set()

        # Join threads to wait for them to finish
        send_thread.join()
        receive_thread.join()

    except serial.SerialException as e:
        print(f"Could not open serial port {serial_port}: {e}")
    except KeyboardInterrupt:
        print("Exiting program...")
    finally:
        ser.close()
        print("Serial port closed.")

if __name__ == "__main__":
    main()

Expected behavior

Replace COM3 with your serial port in the Python code:

serial_port = 'COM3'  # Replace with your actual serial port`

The expected behavior is that the Python code should receive all the values 0 to 255 in a loop sequentially. If you run the Python code you will see that some values received are out of sequence.
serial-send-receive

What is strange is that if you disable the sending of values from Python (by commenting the following lines) THERE ARE NO MORE ERRORS IN THE VALUES RECEIVED:

#send_thread = threading.Thread(target=send_sequence, args=(ser, 63, 0.1, stop_event))
#send_thread.start()
#send_thread.join()

serial-receive

Screenshots

No response

Environment

  • OS: Tested on Windows an Mac OS
  • IDE &IDE Version: 2.3.3
  • Repository Version: Latest

Additional context

No response

Issue checklist

  • I searched for previous reports in the issue tracker
  • My report contains all necessary details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant