wildbill:
Change the interrupt routine to just count pulses.
In loop, periodically calculate the speed from pulse count and millis.
When the bike stops there will be no pulses and next time you calc, speed falls to zero.
blh64:
The flicker comes from the fact that you blank the display prior to printing your information every time. It is best to just update the display. Combining that with reply #2 you get (untested)
#include <Wire.h> //
#include <LiquidCrystal_I2C.h> //
LiquidCrystal_I2C lcd(0x3F, 16, 2); //
unsigned long start;
volatile unsigned long tickCount;
unsigned long lastTickCount;
const unsigned long debounceTime = 100; // msecs of debounce for interrupts
const unsigned long updateTime = 5000; // msecs between updating speed and display
const float circMetric = 1.580; // wheel circumference (in meters)
// using 1 kilometer = 0.621371192 miles
const float circImperial = circMetric * .62137; // convert metric to imperial for MPH calculations
float speedk, speedm; // holds calculated speed vales in metric and imperial
void setup()
{
// the syntax with digitalPinToInterrupt should allow portability
//among different Arduino models - see attachInterrupt() - Arduino Reference
attachInterrupt(digitalPinToInterrupt(2), tickCalc, RISING); // interrupt called when sensors sends digital 2 high (every wheel rotation)
//attachInterrupt(0, speedCalc, RISING); // interrupt called when sensors sends digital 2 high (every wheel rotation)
//start now (it will be reset by the interrupt after calculating revolution time)
start = millis();
// set up the LCD's number of columns and rows:
lcd.init(); // инициализация LCD
lcd.backlight();
// Print a transitory message to the LCD.
lcd.print("CKOPOCTOMEP");
delay(2000); //just to allow you to read the initialization message
lcd.clear();
// top serial dialogue speed improves precision
Serial.begin(115200);
}
void tickCalc()
{
static unsigned long lastTickTime = 0;
if ( millis() - lastTickTime >= debounceTime ) {
// debounce time
tickCount++;
lastTickTime += debounceTime;
}
}
void speedCalc(unsigned long revolutions, unsigned long time)
{
float speed = 3600.0 * revolutions / time;
//calculate speed in km/h
speedk = speed * circMetric;
//calculate speed in mph
speedm = speed * circImperial;
}
void loop()
{
// The loop will be interrupted by the sensor each time the
// magnet passes near the sensor, in other words once per revolution
unsigned long elapsed;
unsigned long tempTickCount;
unsigned long now = millis();
if ( now - start >= updateTime ) {
noInterrupts(); // turn off interrupts while copying count
tempTickCount = tickCount;
interrupts();
elapsed = now - start;
speedCalc( tempTickCount - lastTickCount, elapsed );
start = now;
lastTickCount = tempTickCount;
// Top line in the 16 char, 2 lines display - speed data
lcd.setCursor(0, 0);
lcd.print(int(speedk));
lcd.print(" km/h ");
//bottom line the 16 char, 2 lines display - time data
lcd.setCursor(0, 1);
lcd.print(int(elapsed));
lcd.print(" ms/rev ");
}
}
gcjr:
i think it would be better if the code in the interrupt simply captures the time between interrupts and any calculations are performed in loop() just before updating the display
the following table indicates the time between revolutions for various speed in mph.
k 4819.49
msec mph k/msec
5000.0 1.0 1.0
4000.0 1.2 1.2
3200.0 1.5 1.5
2560.0 1.9 1.9
2048.0 2.4 2.4
1638.4 2.9 2.9
1310.7 3.7 3.7
1048.6 4.6 4.6
838.9 5.7 5.7
671.1 7.2 7.2
536.9 9.0 9.0
429.5 11.2 11.2
343.6 14.0 14.0
274.9 17.5 17.5
219.9 21.9 21.9
175.9 27.4 27.4
140.7 34.2 34.2
112.6 42.8 42.8
the actual speed calculation can be performed in loop(). besides capturing the time (msec) / revolution, the interrupt can set a flag indicating a new value is available.
"k" can be pre-calculated so that mph = k / dMsec -- k for 27 in. tire, 4819.49
k = (3600.0 / 5280) * PI * (tireDiaIn / 12.0) * 1000;
similarly conversion to another set of units (km) should only involve a single constant that can be precalculated.
leaky integration (averaging) can be used to smooth results if needed
mph += ((k / dMsec) - mph) / 10;
some code
#define butPin A1
byte butStateLst;
byte butState;
int tireDiaIn = 27;
float k;
float mph = 0;
// -----------------------------------------------------------------------------
void loop (void) {
static unsigned long msecLst = 0;
unsigned long msec = millis ();
unsigned long dMsec;
static byte flag = 0;
// check for event
butState = digitalRead (butPin);
if (butStateLst != butState) {
butStateLst = butState;
if (LOW == butState) {
dMsec = msec - msecLst;
msecLst = msec;
flag ++;
}
}
// process new event
if (flag) {
flag = 0;
mph += ((k / dMsec) - mph) / 10;
Serial.println (mph);
}
}
// -----------------------------------------------------------------------------
void setup (void) {
Serial.begin (115200);
pinMode (butPin, INPUT_PULLUP);
butStateLst = butState = digitalRead (butPin);
k = (3600.0 / 5280) * PI * (tireDiaIn / 12.0) * 1000;
// verify k
float circFt = 7.1;
float msec;
for (msec = 5000; msec > 100; msec *= 0.8) {
float fps = circFt * 1000 / msec;
float mph = fps * 3600 / 5280;
Serial.print (" ");
Serial.print (msec);
Serial.print (" ");
Serial.print (mph);
Serial.print (" ");
Serial.print (k);
Serial.print (" ");
Serial.print (k / msec);
Serial.println ("");
}
}
some results
5000.00 0.97 4819.49 0.96
4000.00 1.21 4819.49 1.20
3200.00 1.51 4819.49 1.51
2560.00 1.89 4819.49 1.88
2048.00 2.36 4819.49 2.35
1638.40 2.95 4819.49 2.94
1310.72 3.69 4819.49 3.68
1048.58 4.62 4819.49 4.60
838.86 5.77 4819.49 5.75
671.09 7.21 4819.49 7.18
536.87 9.02 4819.49 8.98
429.50 11.27 4819.49 11.22
343.60 14.09 4819.49 14.03
274.88 17.61 4819.49 17.53
219.90 22.01 4819.49 21.92
175.92 27.52 4819.49 27.40
140.74 34.40 4819.49 34.24
112.59 43.00 4819.49 42.81
0.41
2.17
4.28
5.90
7.82
9.21
10.63
11.74
12.79
13.71
14.58
15.33
16.01
16.59
17.06
17.53
17.93
18.22
18.51
18.57
18.86
18.96
20.64
22.59
22.35
22.36
22.47
22.27
22.21
21.99
21.90
21.80
23.17
25.40
24.94
24.47
24.01
23.54
23.24
22.97
22.61
22.20
21.53
23.09
26.59
26.16
25.64
25.09
24.50
23.96
23.56
23.04
22.72
23.17
28.51
27.65
26.79
26.00
25.34
24.84
Thank you so much!!! I'm new to arduino programming, so I need time to understand it and try it) Will revert back! Thank you once again!