Skip to content

USART feedback #175

Description

@goosst

Hello,

Thank you for all the nice work, I'm able to control the hoverboard motors through UART2 using an ESP32. So that's a good start :). Also nice to see simulink / matlab models related to FOC ;).

However the feedback signals I'm receiving don't seem to come through reliably.
I've tried running the Send and Receive functions from the .ino example at different task rates (copied my esp32 code below). It just varies from a lot of rubbish "Non-valid data skipped" to having strange reported values if they come true once.

Additional information in case it would help:

  • to keep it simple when starting, I've used the default settings from the repository and just enabled default_envs = VARIANT_USART in platformio.ini
  • processor is a GD32F103
  • If results are reported, the rpm doesn't seem to match the commanded rpm. But I can imagine this is because the default is voltage mode and not speed mode. Not sure yet what this speed/steer command actually represents in voltage mode

Any advice how to debug or which firmware variants are recommended for debugging is appreciated, seeing quite some issues were opened related to USART, I might want to avoid reinventing known remedies.

thanks!

#include <Arduino.h>

#define HOVER_SERIAL_BAUD 115200 // [-] Baud rate for Serial2 (used to communicate with the hoverboard)
#define SERIAL_BAUD 115200       // [-] Baud rate for built-in Serial (used for the Serial Monitor)
#define START_FRAME 0xABCD       // [-] Start frme definition for reliable serial communication
#define DEBUG_RX                 // [-] Debug received data. Prints all bytes to serial (comment-out to disable)

//only pick one taskrate for this simple test
#define TASK_1000MS 0 //simple task scheduling of 1 second
#define TASK_500MS 0
#define TASK_200MS 1 //simple task scheduling of 200ms
#define TASK_10MS 0

// Global variables
uint8_t idx = 0;        // Index for new data pointer
uint16_t bufStartFrame; // Buffer Start Frame
byte *p;                // Pointer declaration for the new received data
byte incomingByte;
byte incomingBytePrev;

typedef struct
{
  uint16_t start;
  int16_t steer;
  int16_t speed;
  uint16_t checksum;
} SerialCommand;
SerialCommand Command;

typedef struct
{
  uint16_t start;
  int16_t cmd1;
  int16_t cmd2;
  int16_t speedR_meas;
  int16_t speedL_meas;
  int16_t batVoltage;
  int16_t boardTemp;
  uint16_t cmdLed;
  uint16_t checksum;
} SerialFeedback;
SerialFeedback Feedback;
SerialFeedback NewFeedback;

// #define RXD2 16
// #define TXD2 17
void setup()
{
  // put your setup code here, to run once:

  pinMode(BUILTIN_LED, OUTPUT);
  Serial.begin(SERIAL_BAUD); //this is printed to monitor through computer
  Serial.println("Hoverboard Serial test");
  Serial2.begin(HOVER_SERIAL_BAUD); //used to communicate with hoverboard
}

// ########################## SEND ##########################
void Send(int16_t uSteer, int16_t uSpeed)
{
  // Create command
  Command.start = (uint16_t)START_FRAME;
  Command.steer = (int16_t)uSteer;
  Command.speed = (int16_t)uSpeed;
  Command.checksum = (uint16_t)(Command.start ^ Command.steer ^ Command.speed);

  // Write to Serial
  Serial2.write((uint8_t *)&Command, sizeof(Command));
}

// ########################## RECEIVE ##########################
void Receive()
{
  // Check for new data availability in the Serial buffer
  if (Serial2.available())
  {
    incomingByte = Serial2.read();                                      // Read the incoming byte
    bufStartFrame = ((uint16_t)(incomingByte) << 8) | incomingBytePrev; // Construct the start frame
  }
  else
  {
    return;
  }

// If DEBUG_RX is defined print all incoming bytes
#ifdef DEBUG_RX
  Serial.print(incomingByte);
  Serial.println("bytes read");
  return;
#endif

  // Copy received data
  if (bufStartFrame == START_FRAME)
  { // Initialize if new data is detected
    p = (byte *)&NewFeedback;
    *p++ = incomingBytePrev;
    *p++ = incomingByte;
    idx = 2;
  }
  else if (idx >= 2 && idx < sizeof(SerialFeedback))
  { // Save the new received data
    *p++ = incomingByte;
    idx++;
  }

  // Check if we reached the end of the package
  if (idx == sizeof(SerialFeedback))
  {
    uint16_t checksum;
    checksum = (uint16_t)(NewFeedback.start ^ NewFeedback.cmd1 ^ NewFeedback.cmd2 ^ NewFeedback.speedR_meas ^ NewFeedback.speedL_meas ^ NewFeedback.batVoltage ^ NewFeedback.boardTemp ^ NewFeedback.cmdLed);

    // Check validity of the new data
    if (NewFeedback.start == START_FRAME && checksum == NewFeedback.checksum)
    {
      // Copy the new data
      memcpy(&Feedback, &NewFeedback, sizeof(SerialFeedback));

      // Print data to built-in Serial
      Serial.print("1: ");
      Serial.print(Feedback.cmd1);
      Serial.print(" 2: ");
      Serial.print(Feedback.cmd2);
      Serial.print(" 3: ");
      Serial.print(Feedback.speedR_meas);
      Serial.print(" 4: ");
      Serial.print(Feedback.speedL_meas);
      Serial.print(" 5: ");
      Serial.print(Feedback.batVoltage);
      Serial.print(" 6: ");
      Serial.print(Feedback.boardTemp);
      Serial.print(" 7: ");
      Serial.println(Feedback.cmdLed);
    }
    else
    {
      Serial.println("Non-valid data skipped");
    }
    idx = 0; // Reset the index (it prevents to enter in this if condition in the next cycle)
  }

  // Update previous states
  incomingBytePrev = incomingByte;
}

// ########################## LOOP ##########################

void loop(void)
{

#if TASK_10MS
  static long unsigned int a = micros();
  if (micros() >= (a + 10000))
  { //10 ms tasks
    a = micros();
    /* Tasklist: 10 ms */
    Receive();    // Check for new received data
    Send(0, 100); //Send(int16_t uSteer, int16_t uSpeed)
  }
  else if (micros() < a)
    a = 0;
#endif

#if TASK_200MS
  static long unsigned int f = micros();
  if (micros() >= (f + 200000))
  { //200 ms tasks
    f = micros();
    Receive();    // Check for new received data
    Send(0, 100); //Send(int16_t uSteer, int16_t uSpeed)
  }
  else if (micros() < f)
    f = 0;
#endif

#if TASK_500MS
  static long unsigned int f = micros();
  if (micros() >= (f + 500000))
  { //500 ms tasks
    f = micros();
    /* Tasklist: 500 ms */
    Receive();    // Check for new received data
    Send(0, 100); //Send(int16_t uSteer, int16_t uSpeed)
  }
  else if (micros() < f)
    f = 0;
#endif

#if TASK_1000MS
  static long unsigned int g = micros();
  if (micros() >= (g + 1000000))
  { //1000 ms tasks
    g = micros();
    /* Tasklist: 1000 ms */
    Receive();    // Check for new received data
    Send(0, 100); //Send(int16_t uSteer, int16_t uSpeed)
  }

  else if (micros() < g)
    g = 0;
#endif
} 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions