2023-08-24 05:22 AM - edited 2023-08-24 05:24 AM
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:
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! :)
Solved! Go to Solution.
2023-08-28 05:27 PM
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!
2023-08-24 07:43 PM
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
2023-08-28 05:27 PM
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!