cancel
Showing results for 
Search instead for 
Did you mean: 

UART communication between Nucleo F401RE and Teensy 4.1

alyssaForum
Associate II

Hello everyone,

I am trying to establish a serial communication between a Teensy 4.1 and a Nucleo F401RE board. The Nucleo board reads data from some VL53L7CX ToF sensors (this part works) and send them via Serial to the Teensy (this one doesn't work).

Indeed, the Teensy never receives any data, except after the end of the initialization of the ToF sensors: it receives a 0 integer. However, at this moment of the code, no data are supposed to be sent by the Nucleo. So I don't understand where that could come from and why I can't receive the actual data written on the Serial port. Do you have any idea about that please?


I have made the following wiring:

  • Pin 0 of Teensy linked to pin PA_9 (D8) of the Nucleo
  • Pin 1 of the Teensy linked to pin PA_10 (D2) of the Nucleo
  • GND of the Teensy linked to the GND of Nucleo

Also, here are my two codes (both were developed with the Arduino platform). The 1st one is the Nucleo's code and the 2nd one is the Teensy's code:

NUCLEO

 

/**
 ******************************************************************************
 * @file    ToF_sensor_new.ino
 * @author  alyssa agnissan
 * @version V1.0.0
 * @date    17 August 2023
 * @brief   Read ranging data from several VL53L7CX sensor with a multiplexer
 ******************************************************************************

/************************** INCLUDES **************************/
#include <Arduino.h>
#include <Wire.h>
#include <vl53l7cx_class.h>
#include <stdio.h>

#ifdef ARDUINO_SAM_DUE
  #define DEV_I2C Wire1
#else
  #define DEV_I2C Wire
#endif
#define SerialPort Serial

#define LED_PIN PC13

#define multiplexer 0x70          // PCA9548A device I2C address 

#define TOF 4                     // number of ToF
          
#define LPN_PIN1 4                // sensor #1 wiring 
#define PWREN_PIN1 A0
#define I2C_RST_PIN1 9

#define LPN_PIN2 5                // sensor #2 wiring 
#define PWREN_PIN2 A2

#define LPN_PIN3 7                // sensor #3 wiring 
#define PWREN_PIN3 A4

#define LPN_PIN4 8                // sensor #4 wiring 
#define PWREN_PIN4 A5

// #define PRINT
// #define TIME
// #define MEAN_TIME
// #define INIT

/************************** PARAMETERS **************************/
// Components.
VL53L7CX sensor1(&DEV_I2C, LPN_PIN1);
VL53L7CX sensor2(&DEV_I2C, LPN_PIN2);
VL53L7CX sensor3(&DEV_I2C, LPN_PIN3);
VL53L7CX sensor4(&DEV_I2C, LPN_PIN4);
VL53L7CX* tab_sensor[] = {&sensor1, &sensor2, &sensor3, &sensor4};

// Tabs for wiring
int PWREN_PIN[] = {PWREN_PIN1, PWREN_PIN2, PWREN_PIN3, PWREN_PIN4};               // INUTILE POUR MINI PCB

// UART port Nucleo
HardwareSerial Serial1(PA10, PA9);

// Global param.
uint8_t res = VL53L7CX_RESOLUTION_4X4;
uint8_t ranging_mode = VL53L7CX_RANGING_MODE_CONTINUOUS;  // advised mode for fast ranging measurements or high performances
uint8_t address[] = {0x54, 0x56, 0x58, 0x60};             // sensors' I2C address 

char report[256];
int target_detected = 0;
int32_t sum = 0;
uint8_t status;
int time = 0; int k = 1;


/************************** FUNCTIONS **************************/
void tcaselect(byte i);
int tof_init();
void display_commands_banner(void);
void print_result(VL53L7CX_ResultsData *Result, int num_sensor);


/************************** MAIN **************************/
void setup()
{
  // Initialize serial for output.
  SerialPort.begin(115200);
  Serial1.begin(9600);
  SerialPort.println("------- BEGIN INITIALISATION -------\n");
  
  // Initialize I2C bus.
  DEV_I2C.begin();

  // ToF initialisation
  #ifdef INIT
  // unsigned long startTime = millis();   // init timer
  #endif

  if(tof_init() == -1)  return;

  #ifdef INIT
  unsigned long endTime = millis();
  unsigned long elapsedTime = endTime - startTime;
  SerialPort.print("TIME FOR INITIALISATION : "); SerialPort.print(elapsedTime); SerialPort.print(" ms\n\n");
  #endif

  // Indicate end of initialisation
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  Serial.println("------- INITIALISATION DONE -------\n\n");
}


void loop()
{
  VL53L7CX_ResultsData Results;
  uint8_t NewDataReady = 0;
  target_detected = 0;
  sum = 0;

  #ifdef MEAN_TIME
  unsigned long startTime = millis();   // init timer
  #endif

  // For each sensor
  for(size_t i = 0; i < TOF; i++) {
    #ifdef TIME
    unsigned long startTime = millis();   // init timer
    #endif

    // Select the MUX pin
    tcaselect(i);
    delay(100);

    // Check if data ready
    do {
      status = tab_sensor[i]->vl53l7cx_check_data_ready(&NewDataReady);
    } while (!NewDataReady);

    // If yes, read and print it
    if ((!status) && (NewDataReady != 0)) {
      status = tab_sensor[i]->vl53l7cx_get_ranging_data(&Results);
      delayMicroseconds((1000000 * 9) / 9600);
      print_result(&Results, i);
    }

    #ifdef TIME
    // Compute the measurement time for 1 sensor
    unsigned long endTime = millis();
    unsigned long elapsedTime = endTime - startTime;
    SerialPort.print("MEASUREMENT TIME FOR ONE SENSOR : "); SerialPort.print(elapsedTime); SerialPort.print(" ms\n\n");
    #endif

    // delay(3000);
  }
  #ifdef MEAN_TIME
  // Compute the measurement time for all sensors
  unsigned long endTime = millis();
  unsigned long elapsedTime = endTime - startTime;
  time += elapsedTime;

  if(k == 50){
    SerialPort.print("MEASUREMENT TIME FOR ALL THE SENSORS : "); SerialPort.print(time/50); SerialPort.print(" ms\n\n");
    time = 0; k = 1;
  }
  k++;
  #endif
}


/************************** FUNCTIONS **************************/
// Enable requested I2C channel (0..7)
void tcaselect(byte i) {
  if (i > 7) return;
  DEV_I2C.beginTransmission(multiplexer);
  DEV_I2C.write(1 << i);
  DEV_I2C.endTransmission();
}


// ToF initialisation
int tof_init(){
  // For each ToF sensor
  for(size_t i = 0; i < TOF; i++){
    // Enable PWREN pin if present
    if (PWREN_PIN[i] >= 0) {
      pinMode(PWREN_PIN[i], OUTPUT);
      digitalWrite(PWREN_PIN[i], HIGH);
      delay(10);
    }
  }

  for(size_t i = 0; i < TOF; i++){
    // Begin sensor
    tab_sensor[i]->begin();
    SerialPort.print("Begin sensor #"); SerialPort.print(i); SerialPort.print(" OK\n");

    // Select the MUX pin
    tcaselect(i);
    SerialPort.print("MUX pin #"); SerialPort.print(i); SerialPort.print(" selected\n");
    delay(100);

    // Init sensor
    status = tab_sensor[i]->init_sensor(address[i]);
    if(status == 0)         {SerialPort.print("Init sensor OK\n");}
    else                    {SerialPort.print("ERROR INIT SENSOR\n"); return -1;}

    // Ranging mode
    status = tab_sensor[i]->vl53l7cx_set_ranging_mode(ranging_mode);
    if(status == 0)         SerialPort.print("Ranging mode OK\n");
    else                    {SerialPort.print("ERROR RANGING MODE\n"); return -1;}

    // Resolution
    status = tab_sensor[i]->vl53l7cx_set_resolution(res);
    if(status == 0)         SerialPort.print("Resolution initialisation OK\n");
    else                    {SerialPort.print("ERROR RESOLUTION INITIALISATION\n"); return -1;}

    // Start Measurements
    status = tab_sensor[i]->vl53l7cx_start_ranging();
    if(status == 0)         SerialPort.print("Start ranging OK\n");
    else                    {SerialPort.print("ERROR START RANGING\n"); return -1;}

    SerialPort.print("Initialisation sensor #"); SerialPort.print(i); SerialPort.print(" done\n\n");
  }

  return 0;
}


// Compute and print mean distance in mm
void print_result(VL53L7CX_ResultsData *Result, int num_sensor)
{
  int8_t i, j, k, l;
  uint8_t zones_per_line;
  uint8_t number_of_zones = res;

  zones_per_line = (number_of_zones == 16) ? 4 : 8;

  #ifdef PRINT
  SerialPort.print("TABLE FOR SENSOR #"); SerialPort.print(num_sensor); SerialPort.print("\n\n");
  #endif

  // For each line of the ROI
  for (j = 0; j < number_of_zones; j += zones_per_line)
  {
    #ifdef PRINT
    for (i = 0; i < zones_per_line; i++) 
      SerialPort.print(" -------");
    SerialPort.print("\n");
    
    for (i = 0; i < zones_per_line; i++)
      SerialPort.print("|       ");
    SerialPort.print("|\n");
    #endif

    // For each target of the zone to study
    for (l = 0; l < VL53L7CX_NB_TARGET_PER_ZONE; l++) // VL53L7CX_NB_TARGET_PER_ZONE = 1 by default
    {
      // For each column of the studied line of the ROI
      for (k = (zones_per_line - 1); k >= 0; k--)
      {
        // If target is detected for zone positionned line j and column k
        if (Result->nb_target_detected[j+k]>0)
        {
          #ifdef PRINT
          // Print distance
          snprintf(report, sizeof(report),"| \033%5ld\033",
              (long)Result->distance_mm[(VL53L7CX_NB_TARGET_PER_ZONE * (j+k)) + l]);
              SerialPort.print(report);
          #endif

          // Add the current measured distance to all the previous ones
          sum += Result->distance_mm[(VL53L7CX_NB_TARGET_PER_ZONE * (j+k)) + l];
          target_detected ++;
        }
        #ifdef PRINT
        else
        {
          snprintf(report, sizeof(report),"| %5s ", "X");
          SerialPort.print(report);
        }
        #endif
      }
      #ifdef PRINT
      SerialPort.print("|\n");
      #endif
    }
  }
  #ifdef PRINT
  for (i = 0; i < zones_per_line; i++)
   SerialPort.print(" -------");
  SerialPort.print("\n\n");
  #endif

  // Compute and print mean distance for all the targets detected in the ROI 
  Serial1.write(sum/target_detected);
  Serial.print(sum/target_detected); Serial.print("\n");
  delay(100);
}

 

TEENSY

 

/**
 ******************************************************************************
 * @file    ToF_sensor_new.ino
 * @author  alyssa agnissan
 * @version V1.0.0
 * @date    17 August 2023
 * @brief   Read ranging data from several VL53L7CX sensor with a multiplexer
 ******************************************************************************

/************************** INCLUDES **************************/
#include <Arduino.h>
#include <Wire.h>

/************************** PARAMETERS **************************/
bool initialisation = false;

/************************** MAIN **************************/
void setup() {
  // Initialize serial for output.
  Serial1.begin(9600);
  Serial.begin(115200);
  
  Serial.println("------- INITIALISATION DONE -------\n\n");
}

void loop() {
  int data;

  if (Serial1.available() > 0) {
    data = Serial1.read();
    Serial.print("Donnée reçue : ");
    Serial.println(data, DEC);
  }

  delay(100);
}

 


PS: I tried to use different UART pins but the problem remains the same. Also, I have seen that a bad synchronisation between receiver and transmitter could cause wrong readings. So I tried to add the line

 

delayMicroseconds((1000000 * 9) / 9600);

 

, in the Nucleo's code, to create a "silence time" in the communication to synchronise it again. No results...


Thank you very much for your help! 🙂

1 ACCEPTED SOLUTION

Accepted Solutions

Hello, thanks for your answer! After a deeper look, it turned out I was sending uint8_t data via Serial, which the Teensy "didn’t like" and thus didn’t read correctly.. I changed it to int and everything works perfectly now!

View solution in original post

2 REPLIES 2
jiangfan
ST Employee

check and ensure both sides work at same baud rate first:

Nucleo F401RE board sends specific data, such as 0x55, at 115200 or any desired baud, verify with oscilloscope

- if possible, receiver side, Teensy for you, also sends specific data, at same baud rate, verify with oscilloscope

Hello, thanks for your answer! After a deeper look, it turned out I was sending uint8_t data via Serial, which the Teensy "didn’t like" and thus didn’t read correctly.. I changed it to int and everything works perfectly now!