Skip to main content
Explorer II
August 24, 2023
Solved

UART communication between Nucleo F401RE and Teensy 4.1

  • August 24, 2023
  • 1 reply
  • 3760 views

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! :)

    This topic has been closed for replies.
    Best answer by alyssaForum

    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!

    1 reply

    ST Employee
    August 25, 2023

    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

    alyssaForumAuthorAnswer
    Explorer II
    August 29, 2023

    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!