![]() | Enter Your Electronics & Design Project for a chance to win a $100 Shopping Cart! | Project14 Home |
| Monthly Themes | ||
| Monthly Theme Poll |
/* ESP32_TOF_VL5130_USRF
This code is based on the four ""SingleRanging" examples in the VL53L0X API.
The range readings are in units of mm and the Pololu library example
Written By:
Cameron Rodriguez
cameron@notimpossiblelabs.com
Last Modified:
May 2nd, 2018
*/
// ###################################
// ############ Libraries ############
// ###################################
#include <Wire.h>
#include <VL53L0X.h>
// Math Library
#include <math.h>
// ###################################
// ######### Program Options #########
// ###################################
// #define DEBUG // Enable debug prints
// #define MotorsDisabled // Kill the PWM Motors
#define USEnable // Enable US readings
//
#ifdef DEBUG
boolean debug = true;
#else
boolean debug = false;
#endif
#ifdef USEnable
boolean usenable = true;
#else
boolean usenable = false;
#endif
#ifdef MotorsDisabled
boolean RunMotors = false;
#else
boolean RunMotors = true;
#endif
// Uncomment this line to use long range mode. This
// increases the sensitivity of the sensor and extends its
// potential range, but increases the likelihood of getting
// an inaccurate reading because of reflections from objects
// other than the intended target. It works best in dark
// conditions.
// #define LONG_RANGE
// Uncomment ONE of these two lines to get
// - higher speed at the cost of lower accuracy OR
// - higher accuracy at the cost of lower speed
#define HIGH_SPEED
//#define HIGH_ACCURACY
// ###################################
// ####### GPIO DECLARATIONS #########
// ###################################
#define PWMPin1 10
#define PWMPin2 11
#define USpw 5
#define USa A0
#define LuxPin A1
#define LEDC_CHANNEL_0 0
#define LEDC_CHANNEL_1 1
#define LEDC_TIMER_13_BIT 13 // use 13 bit precission for LEDC timer
#define LEDC_BASE_FREQ 5000 // use 5000 Hz as a LEDC base frequency
// ###################################
// ############# GLOBALS #############
// ###################################
// ***** PWM Setup *****
unsigned int pwmrange = 511; // 32u4 Huzzah boards
//Normalizing Scale Factor Calculations for Log Scale Mapping
int count = 0; int NumAvg = 1;
#ifdef LONG_RANGE
double TOF_RangeMax = 2000.0;
#else
double TOF_RangeMax = 1200.0;
#endif
double TOF_RangeMin = 50.0;
double US_RangeMax = 5000.0;
double US_RangeMin = 300.0;
int PWMmap1 = 0;
int PWMmap2 = 0;
double TOF_MAPSF = 1 / -log(1 / (double(TOF_RangeMax) - double(TOF_RangeMin) + 1.0)); // 255 * 1/-LOG(1/(RANGEMAX-RANGEMIN+1)) OR 255/MAX LOG VALUE GIVEN THE RANGE
double US_MAPSF = 1 / -log(1 / (double(US_RangeMax) - double(US_RangeMin) + 1.0)); // 255 * 1/-LOG(1/(RANGEMAX-RANGEMIN+1)) OR 255/MAX LOG VALUE GIVEN THE RANGE
// *********************
// ***** Measurement Setup *****
const int HistSz = 5;
long MI = 0; // Measurement Index
#if defined HIGH_SPEED
const int USMeasInt = 1;
#else
const int USMeasInt = 3;
#endif
// *********************
// ***** Lux *****
int LuxVal = 0;
// *********************
// ***** TOF Setup *****
float lux = 0.0;
int TOFrange = 0;
int TOFstatus = 1;
int TOF_Hist[HistSz]; // the Hist of the Status of the TOF
int TOF_Hist_Ind; // Index of Hist Array
int TOF_HistV = 0;
//
// ***** US Setup *****
long USpulse, USrange;
int USstatus = 0;
int US_Hist[HistSz]; // the Hist of the Status of the US
int US_Hist_Ind; // Index of Hist Array
int US_HistV = 0;
//
// ***** COMM Setup *****
const int serialSpeed = 115200; // USB serial port speed
VL53L0X sensor;
// ###################################
// ############ BASE FXNS ############
// ###################################
void AnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = pwmrange) {
// calculate duty, 8191 from 2 ^ 13 - 1
uint32_t duty = (8191 / valueMax) * min(value, valueMax);
// write duty to LEDC
ledcWrite(channel, duty);
}
// ###################################
// ############## SETUP ##############
// ###################################
void setup()
{
if(debug){
Serial.begin(serialSpeed);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println( F( "UART Communication Established" ) );
}
// Initialize I2C
Wire.begin();
// Initialize the GPIO
//pinMode(PWMPin1, OUTPUT); digitalWrite(PWMPin1, LOW);
//pinMode(PWMPin2, OUTPUT); digitalWrite(PWMPin2, LOW);
ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcAttachPin(PWMPin1, LEDC_CHANNEL_0);
ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcAttachPin(PWMPin2, LEDC_CHANNEL_1);
pinMode(USpw, INPUT);
pinMode(USa, INPUT);
pinMode(LuxPin, INPUT);
if(debug){ Serial.println( F( "Looking 4 Sensor") );}
sensor.init();
sensor.setTimeout(500);
if(debug){ Serial.println(F( "Sensor Starting") );}
#if defined LONG_RANGE
// lower the return signal rate limit (default is 0.25 MCPS)
sensor.setSignalRateLimit(0.1);
// increase laser pulse periods (defaults are 14 and 10 PCLKs)
sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif
#if defined HIGH_SPEED
// reduce timing budget to 20 ms (default is about 33 ms)
sensor.setMeasurementTimingBudget(20000);
#elif defined HIGH_ACCURACY
// increase timing budget to 200 ms
sensor.setMeasurementTimingBudget(200000);
#else // default is about 33 ms
sensor.setMeasurementTimingBudget(33000);
#endif
//Initialize the status histories for the TOF and US to 80% good
for (int TOF_Hist_Ind = 0; TOF_Hist_Ind < HistSz; TOF_Hist_Ind++) {
TOF_Hist[TOF_Hist_Ind] = 0;
}
TOF_Hist_Ind = 0;
for (int US_Hist_Ind = 0; US_Hist_Ind < HistSz; US_Hist_Ind++) {
US_Hist[US_Hist_Ind] = 0;
}
US_Hist_Ind = 0;
}
// ###################################
// ############# MAIN LOOP ###########
// ###################################
void loop(){
LuxVal = analogRead(LuxPin);
if(LuxVal >= 950){
//if((LuxVal >= 900)||(TOF_HistV <=3)){
#ifdef USEnable
usenable = true;
#endif
}
else{usenable = false;}
if(MI%USMeasInt == 0){
if(usenable){
read_US();
if( (USrange <= US_RangeMax) && (USrange > US_RangeMin) ){
USstatus = 1; US_Tracker();}
else{USstatus = 0; US_Tracker();}
}
else{USstatus = 0; USrange = 0; US_HistV = 0;}
}
TOFrange = sensor.readRangeSingleMillimeters();
if( (!sensor.timeoutOccurred()) && (TOFrange <= TOF_RangeMax) && (TOFrange > 0) ){
TOFstatus = 1; TOF_Tracker();}
else{TOFstatus = 0; TOF_Tracker();}
if(( TOFstatus == 1 )||(USstatus == 1 )){ // At least 1 channel of good data
if((TOFstatus == 1) && (USstatus == 0)){// TOF GOOD, US BAD
if (TOFrange < TOF_RangeMin) {PWMmap1 = pwmrange;}
else { PWMmap1 = LogMapTOF(double(TOFrange));}
}
else if((TOFstatus == 0) && (USstatus == 1)){ // TOF BAD, US GOOD
if (USrange > TOF_RangeMax) {PWMmap1 = 0;}
else { PWMmap1 = LogMapTOF(double(USrange));}
}
else{ // BOTH GOOD
if(TOF_HistV < US_HistV){ // Choose TOF over US if its history equal is better
if (USrange > TOF_RangeMax) {PWMmap1 = 0;}
else { PWMmap1 = LogMapTOF(double(USrange));}
}
else{
if (TOFrange < TOF_RangeMin) {PWMmap1 = pwmrange;}
else { PWMmap1 = LogMapTOF(double(TOFrange));}
}
}
if(RunMotors){
AnalogWrite(PWMPin1, PWMmap1);
AnalogWrite(PWMPin2, PWMmap1);
}
if(debug){
if(( TOFstatus == 1 )&&(USstatus == 1 )){
Serial.print("Lux Value: = "); Serial.print( LuxVal ); Serial.print( ", ");
Serial.print("PWM: = "); Serial.print( PWMmap1 ); Serial.print( ", ");
Serial.print("TOF: Status = "); Serial.print( TOF_HistV ); Serial.print(", Range = "); Serial.print( TOFrange ); Serial.print( "mm, ");
Serial.print("US: Status = " ); Serial.print( US_HistV ); Serial.print(", Range = ");Serial.print( USrange ); Serial.println( "mm" );}
else if(( TOFstatus == 0 )&&(USstatus == 1 )){
Serial.print("Lux Value: = "); Serial.print( LuxVal ); Serial.print( ", ");
Serial.print("PWM: = "); Serial.print( PWMmap1 ); Serial.print( ", ");
Serial.print("TOF: Status = "); Serial.print( TOF_HistV ); Serial.print(", Range = "); Serial.print( "----- " ); Serial.print( "mm, ");
Serial.print("US: Status = " ); Serial.print( US_HistV ); Serial.print(", Range = ");Serial.print( USrange ); Serial.println( "mm" );}
else{
Serial.print("Lux Value: = "); Serial.print( LuxVal ); Serial.print( ", ");
Serial.print("PWM: = "); Serial.print( PWMmap1 ); Serial.print( ", ");
Serial.print("TOF: Status = "); Serial.print( TOF_HistV ); Serial.print(", Range = "); Serial.print( TOFrange ); Serial.print( "mm, ");
Serial.print("US: Status = " ); Serial.print( US_HistV ); Serial.print(", Range = ");Serial.print( "----- "); Serial.println( "mm" );}
}
}
else{
if(RunMotors){
digitalWrite(PWMPin1, LOW);
digitalWrite(PWMPin2, LOW);
}
if(debug){
Serial.print("Lux Value: = "); Serial.print( LuxVal ); Serial.print( ", ");
Serial.print("PWM: = 0, ");
Serial.print("TOF: Status = "); Serial.print( TOF_HistV ); Serial.print(", Range = "); Serial.print( "----- " ); Serial.print( "mm, ");
Serial.print("US: Status = " ); Serial.print( US_HistV ); Serial.print(", Range = ");Serial.print( "----- "); Serial.println( "mm" );
}
}
MI++;
}
// ###################################
// ########### SUBFUNCTIONS ##########
// ###################################
void US_Tracker(){
US_HistV = US_HistV - US_Hist[US_Hist_Ind]; // Remove old value from the running total
US_Hist[US_Hist_Ind] = USstatus; // add new val to index
US_HistV = US_HistV + US_Hist[US_Hist_Ind]; // Add new value to the running total
US_Hist_Ind ++;
if (US_Hist_Ind >= HistSz) {US_Hist_Ind = 0;} // if we're at the end of the array, then wrap around to the beginning
}
void TOF_Tracker(){
TOF_HistV = TOF_HistV - TOF_Hist[TOF_Hist_Ind];
TOF_Hist[TOF_Hist_Ind] = TOFstatus;
TOF_HistV = TOF_HistV + TOF_Hist[TOF_Hist_Ind];
TOF_Hist_Ind ++;
if (TOF_Hist_Ind >= HistSz) {TOF_Hist_Ind = 0;} // if we're at the end of the array, then wrap around to the beginning
}
void read_US(){
#if defined HIGH_SPEED
USrange = analogRead(USa)*5;
#else
USrange = pulseIn(USpw, HIGH);
#endif
}
int LogMapTOF(double val) {
double MAPval = (val - TOF_RangeMin + 1);
MAPval = TOF_MAPSF * pwmrange * ( -log( MAPval / (TOF_RangeMax - TOF_RangeMin + 1) ));
return int(MAPval);
} // END LogMap
int LogMapUS(double val) {
double MAPval = (val - TOF_RangeMin + 1);
MAPval = US_MAPSF * pwmrange * ( -log( MAPval / (US_RangeMax - US_RangeMin + 1) ));
return int(MAPval);
} // END LogMapParts from:
| Product Name | Manufacturer Part Number | Quantity | Part Link |
|---|---|---|---|
| Transistor NPN T092 | 2n2222a | 1 | Buy NowBuy Now |
| Diode | 1N4001 | 1 | Buy NowBuy Now |
| Resistor 180Ω | 180Ω | 1 | Buy NowBuy Now |
Parts From:
| Product Name | Manufacturer Part Number | Quantity |
|---|---|---|
| TOF Sensor | 3317 | 1 |
| US Sensor | 984 | 1 |
| ESP32 Feather | 3404 | 1 |
| Female Header Pin | 2886 | 1 |
| 2000mah LiPo | 2011 | 1 |
Additional Parts:
| Product Name | Manufacturer Part Number | Quantity |
|---|---|---|
| Haptic Motor | JinLong Machinery Z7AL2B1692082 | 4 |
| Custom PCB | OSH Park | 1 |
| Wrist Brace | Mueller 74676862729 | 1 |
| Velcro | 3M B00006IC2T | 1 |
Design for a Cause | Project C.O.D.I: Help Build a Superhero Costume for Cody!
Project C.O.D.I. | Overview, Current Proof of Concept, and Next Steps





