Hello,
I have another question. The main objective of the sketch above is to realize a speedometer computing vehicle velocity, travel distance and wheel rpm. It is based on ABS sensor measures.
I would like acquire hall effect sensor data every 10 ms (for sure your now my project) and plot them of a small OLED screen (SSD1906). Regarding watching confort and the constraints on screen refresh rate 300ms seems to be a good compromise.
The following sketch works but it takes a little bit more than 10ms to initialize the screen with the command:
display.begin(SSD1306_SWITCHCAPVCC);
// Program to compute rotational wheel speed, vehicle velocity and travel distance from the measure of a hall effect sensor
// The program used a fixed period to count the number of rising edge and compute the wheel speed in rpm
// Libraries:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <NeoHWSerial.h>
// Serial communication:
#define DEBUG_PORT_TYPE NeoHWSerial
#define DEBUG_PORT NeoSerial
// Display SSD1906 settings:
#define OLED_MOSI 9
#define OLED_CLK 10
#define OLED_DC 11
#define OLED_CS 12
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
// Variables:
volatile byte rpmCounter=0; // pulse counter
unsigned long counter=0; // total number of counting pulses since begining only for debugging
unsigned int rpm=0; // rotational wheel speed in rpm
unsigned long previousTimeSensor=0; // end time of the last sensor period in micros
unsigned long previousTimeScreen=0; // end time of the last screen period in micros
unsigned long currentTime=0; // actual time in micros
unsigned long deltaTimeSensor=0;
const long periodSensor=10000; // time period for pulse counting in micros
const long periodScreen=300000; // time period for refresch the screen in micros
const int ppr=40; // pulse per revolution
const float radiusRearWheell=0.2758; // radius of the wheel in m
const float pi = 3.14159; // pi constant
float Speed=0; // vehicle speed in km/h
float distance=0; // travel distance in m
//------------------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------//
void disp(float SpeedToDisp, int rpmToDisp, float DistanceToDisp, int counterToDisp) // display function for SSD1906
{
// vehicle speed displaying:
display.setTextSize(1);
display.setCursor(0,3);
display.print("Speed");
display.setCursor(38,0);
display.setTextSize(2);
display.print(SpeedToDisp);
display.setCursor(95,3);
display.setTextSize(1);
display.print(" km/h");
// wheel rpm displaying:
display.setTextSize(1);
display.setCursor(0,18);
display.print("RPM");
display.setCursor(38,15);
display.setTextSize(2);
display.print(rpmToDisp);
display.setCursor(98,18);
display.setTextSize(1);
display.print(" rpm");
// travel distance displaying:
display.setTextSize(1);
display.setCursor(0,33);
display.print("Dist.");
display.setCursor(38,30);
display.setTextSize(2);
display.print(DistanceToDisp,1);
display.setCursor(110,33);
display.setTextSize(1);
display.print(" m");
// global pulse counter displaying:
display.setTextSize(1);
display.setCursor(0,48);
display.print("Coun.");
display.setCursor(38,45);
display.setTextSize(2);
display.print(counterToDisp);
display.display();
display.clearDisplay();
}
//------------------------------------------------------------------------------------------------//
void rpmCountFun() // function for attachInterrupt
{
rpmCounter++ ; // Update rpm counter
counter++; // Update global counter just for debugging
}
//------------------------------------------------------------------------------------------------//
void updateSensor() // function for attachInterrupt
{
deltaTimeSensor = currentTime - previousTimeSensor;
if (deltaTimeSensor >= periodSensor){
detachInterrupt(0); // disable interrupt when calculating
rpm = rpmCounter*6000000/(ppr*deltaTimeSensor ); // convert frecuency to RPM be carefull period is in micros and need to be multiplied by 6000000 to be converted in min
Speed = 3.6*radiusRearWheell*rpm*2*pi/ 60; // speed calculation v=3.6*r*w with w in rad/s
distance = distance + rpmCounter*2*pi*radiusRearWheell/ppr; // distance calculation
rpmCounter = 0; // restart the RPM counter
DEBUG_PORT.print(currentTime);
DEBUG_PORT.print("\t \t \t ");
DEBUG_PORT.print(rpm);
DEBUG_PORT.print("\t \t ");
DEBUG_PORT.print(Speed);
DEBUG_PORT.print("\t \t ");
DEBUG_PORT.print(distance);
DEBUG_PORT.print("\t \t \t ");
DEBUG_PORT.println(counter);
previousTimeSensor += periodSensor; // uptade previousTimeSensor
attachInterrupt(0, rpmCountFun, RISING); //enable interrupt
}
}
//------------------------------------------------------------------------------------------------//
void updateScreen() // function for attachInterrupt
{
if (currentTime - previousTimeScreen >= periodScreen){
disp(Speed, rpm, distance, counter ); // display results on the screen
previousTimeScreen += periodScreen; // uptade previousTimeScreen
}
}
//------------------------------------------------------------------------------------------------//
void setup() {
DEBUG_PORT.begin(115200);
//init SSD1906 display:
display.clearDisplay();
display.begin(SSD1306_SWITCHCAPVCC);
display.clearDisplay();
display.setTextColor(WHITE);
attachInterrupt(0, rpmCountFun, RISING);
DEBUG_PORT.print("currentTime\t");
DEBUG_PORT.print("\t RPM \t");
DEBUG_PORT.print("\t speed\t");
DEBUG_PORT.print("\t distance\t");
DEBUG_PORT.println("\t global counter\t");
}
//------------------------------------------------------------------------------------------------//
void loop() {
currentTime = micros();
updateSensor();
updateScreen();
}
So the first currentTime value is 13032 microsecond.
currentTime RPM speed distance global counter
13032 11 1.14 0.04 1
20000 0 0.00 0.04 1
30004 74 7.69 0.26 6
40000 15 1.56 0.30 7
50000 30 3.12 0.39 9
60004 29 3.02 0.48 11
70004 14 1.46 0.52 12
80004 44 4.57 0.65 15
90000 15 1.56 0.69 16
100004 59 6.13 0.87 20
110004 14 1.46 0.91 21
120000 60 6.24 1.08 25
130004 14 1.46 1.13 26
140004 89 9.25 1.39 32
150000 15 1.56 1.43 33
160000 105 10.92 1.73 40
170004 14 1.46 1.78 41
180004 29 3.02 1.86 43
190004 14 1.46 1.91 44
Is there another way to do screen initialisation or a tip to avoid the first little delay?
Thanks,
Pm