Jabberwoky
New member
Hi all I would really appreciate some help with my code.
First of all a bit about the hardware: I am using a Teensy 3.5 with an adafruit VL53L0X and adafruit 128x32 OLED LCD (I2C). My objective is to data-log the sensor data onto a microSD card that is built into the Teensy.
I have tested my hardware connections using several different examples from both the Adafruit and pololu libraries and they all seem to indicate my hardware is functional and connected properly.
My code starts ok and makes it through setup but goes on the fritz shortly after starting the main loop. More specifically the serial monitor stops outputting any data and the OLED display starts to fill up with white. My hunch is that this has something to do with the IntervalTimer but I can't explain why it works initially then stops. My other thought is that something is messing up my i2c bus but again I can't explain why that would work initially and be fine with the other sample sketches.
Any help is much appreciated, below is a sample of the serial output and the code:
SERIAL OUT SAMPLE:
Initializing SD card...card initialized.
Logging to: Log_05.csv
Time [ms], Distance [mm], Marker
End Setup!
0, 0, 0
0, 0, 0
3145, 47, 0
3228, 47, 0
3265, 43, 0
3347, 51, 0
3385, 51, 0
3467, 48, 0
3508, 48, 0
3588, 53, 0
3628, 49, 0
3665, 52, 0
3748, 51, 0
3787, 50, 0
First of all a bit about the hardware: I am using a Teensy 3.5 with an adafruit VL53L0X and adafruit 128x32 OLED LCD (I2C). My objective is to data-log the sensor data onto a microSD card that is built into the Teensy.
I have tested my hardware connections using several different examples from both the Adafruit and pololu libraries and they all seem to indicate my hardware is functional and connected properly.
My code starts ok and makes it through setup but goes on the fritz shortly after starting the main loop. More specifically the serial monitor stops outputting any data and the OLED display starts to fill up with white. My hunch is that this has something to do with the IntervalTimer but I can't explain why it works initially then stops. My other thought is that something is messing up my i2c bus but again I can't explain why that would work initially and be fine with the other sample sketches.
Any help is much appreciated, below is a sample of the serial output and the code:
SERIAL OUT SAMPLE:
Initializing SD card...card initialized.
Logging to: Log_05.csv
Time [ms], Distance [mm], Marker
End Setup!
0, 0, 0
0, 0, 0
3145, 47, 0
3228, 47, 0
3265, 43, 0
3347, 51, 0
3385, 51, 0
3467, 48, 0
3508, 48, 0
3588, 53, 0
3628, 49, 0
3665, 52, 0
3748, 51, 0
3787, 50, 0
Code:
/**************************************************************************
HARDWARE for this Project:
-> https://www.pjrc.com/store/teensy35.html
-> https://www.adafruit.com/product/3317
-> https://www.adafruit.com/product/931
-> http://www.migamotors.com/index.php?main_page=product_info&products_id=40
**************************************************************************/
//**********************************************************************************
//* Libraries Used
//**********************************************************************************
#include <Wire.h>
#include <VL53L0X.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SD.h>
#include <SPI.h>
//*****************************************************************
// DECLARATIONS
//*****************************************************************
//----------------For Logging to SD Card -----------------------------
#define ECHO_TO_SERIAL 1 //Echo data to serial port 1 = Turned ON
#define SYNC_INTERVAL 50 // How often to push data to SD after main event.
//for teensy 3.x data logging, set chipSelect = BUILTIN_SDCARD
const int chipSelect = BUILTIN_SDCARD;
//The logging file
File logfile;
//Logging Millis
volatile unsigned long currentTime = 0;
unsigned long currentTime_copy = 0;
//Create an IntervalTimer Object
IntervalTimer myTimer;
//-----------------For Display----------------------------------------
// Declaration for an SSD1306 connected to I2C (SDA,SCL pins)
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//----------------For Sensor------------------------------------------
// Declaration for an VL53L0X connected to I2C (SDA, SCL pins)
VL53L0X sensor;
//---------------Global Variables and Constants -------------------
char filename[] = "Log_00.csv";
unsigned int marker = 0;
volatile unsigned int distance = 0;
unsigned int distance_copy = 0;
//For button Interrupts
volatile bool startFlag = false;
const uint8_t STARTPOINT = 2; // Pin 2
volatile bool stopFlag = false;
const uint8_t STOPPOINT = 6; // Pin 6
// ---------------States for state machine------------------------
enum operatingState {WAITING = 0, ACTIVE};
volatile operatingState opState = WAITING;
//****************************************************************
// FUNCTION PROTOTYPES
//****************************************************************
void Waiting_State();
void Active_State();
void LogValues(unsigned int marker);
void displayMeasurement(unsigned int measurement, int opState);
void getDistance();
void StopISR();
void StartISR();
//****************************************************************
// SETUP
//****************************************************************
void setup() {
noInterrupts();
// Start up the serial line//////////////////////
#if ECHO_TO_SERIAL
Serial.begin(9600);
delay(2000);
#endif
//Start up the I2C lines//////////////////////////
Wire.begin();
//Start Up SD card/////////////////////////////
#if ECHO_TO_SERIAL
Serial.print("Initializing SD card...");
#endif
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
#if ECHO_TO_SERIAL
Serial.println("Card failed, or not present");
#endif
return;
}
#if ECHO_TO_SERIAL
Serial.println("card initialized.");
#endif
// Setup Log File
for (int i =0; i < 100; i++){
filename[4] = i / 10 + '0';
filename[5] = i % 10 + '0';
if (! SD.exists(filename)){
logfile = SD.open(filename, FILE_WRITE); // Only open a new file if it doesn't exist
break;
}
}
if (! logfile){
#if ECHO_TO_SERIAL
Serial.println("could not create file!");
#endif
}
#if ECHO_TO_SERIAL
Serial.print("Logging to: ");
Serial.println(filename);
#endif
// Write the Headers
logfile.println("Time [ms], Distance [mm], Marker");
#if ECHO_TO_SERIAL
Serial.println("Time [ms], Distance [mm], Marker");
#endif
// Setup OLED Display /////////////////////////////////////////////////////
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
#if ECHO_TO_SERIAL
Serial.println(F("SSD1306 allocation failed"));
#endif
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
display.display();
delay(500); // Pause for 1 second
// Clear the buffer
display.clearDisplay();
// Setup Sensor //////////////////////////////////////////////////////////
sensor.setTimeout(500);
if (!sensor.init())
{
Serial.println("Failed to detect and initialize sensor!");
while (1) {}
}
// reduce timing budget to 20 ms (default is about 33 ms)
sensor.setMeasurementTimingBudget(20000);
//Setup Start Switch, attach to ISR////////////////////////////////////////
pinMode(STARTPOINT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(STARTPOINT), StartISR, FALLING);
//Setup Stop Switch, attach to ISR
pinMode(STOPPOINT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(STOPPOINT), StopISR, FALLING);
//Setup Interval timer object used to get regular distance measurements from sensor.
myTimer.begin(getDistance, 40000); // timer.begin (ISR name, call interval in microseconds)
interrupts();
#if ECHO_TO_SERIAL
Serial.println("End Setup!");
#endif
}
//*****************************************************************
// BEGIN MAIN LOOP
//*****************************************************************
void loop() {
display.clearDisplay();
switch (opState){
case WAITING:
Waiting_State();
break;
case ACTIVE:
Active_State();
break;
}
}// END MAIN
//******************************************************************
// STATE FUNCTIONS
//******************************************************************
// **************************************************
// Waiting State - (Initial State)
// press Start Button to switch to Active State
// **************************************************
void Waiting_State(){
while(!startFlag){
distance_copy = 0;
LogValues(marker);
displayMeasurement(distance_copy, WAITING);
}
startFlag = false;
opState = ACTIVE;
return;
}
// ********************************************************************
// Active State -
// press Stop Button to return to waiting state
// ********************************************************************
void Active_State(){
marker = 1; // indicating START point of inflation event.
LogValues(marker); // single call with marker set to 1.
marker = 0; // Restore marker to default state
while(!stopFlag){
distance_copy = 0;
LogValues(marker);
displayMeasurement(distance_copy, ACTIVE);
}
marker = 2; // indicating Stop point of inflation event.
LogValues(marker); // single call with marker set to 2.
marker = 0;
stopFlag = false;
opState = WAITING;
return;
}
//******************************************************************
// SUPPORT FUNCTIONS
//******************************************************************
void displayMeasurement(unsigned int measurement,int opState) {
display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.println(filename);
display.setCursor(0,16);
display.print("mm: ");
display.print(measurement);
if (opState == ACTIVE){
display.print('*');
}
display.display();
return;
}
//------------------------------------------------------------------------------
void LogValues(unsigned int marker){
noInterrupts();
distance_copy = distance;
currentTime_copy = currentTime;
interrupts();
logfile.print(currentTime_copy);
logfile.print(", ");
logfile.print(distance_copy);
logfile.print(", ");
logfile.println(marker);
logfile.flush();
#if ECHO_TO_SERIAL
Serial.print(currentTime_copy);
Serial.print(", ");
Serial.print(distance_copy);
Serial.print(", ");
Serial.println(marker);
Serial.flush();
#endif
return;
}
//------------------------------------------------------------------------------
// ***********************************************************
// ISRs
// ***********************************************************
void getDistance()
{
distance = sensor.readRangeSingleMillimeters();
currentTime = millis();
}
// For Start Switch
//-----------------------------------------------------------
void StartISR()
{
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
// If interrupts come faster than 100ms, assume it's a bounce and ignore
if (interrupt_time - last_interrupt_time > 100)
{
startFlag = true;
}
last_interrupt_time = interrupt_time;
}
// For Stop Switch
//-----------------------------------------------------------
void StopISR()
{
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
// If interrupts come faster than 100ms, assume it's a bounce and ignore
if (interrupt_time - last_interrupt_time > 100)
{
stopFlag = true;
}
last_interrupt_time = interrupt_time;
}