My prototype code - evil and crufty as it is, is too big to post here! The most obscure thing about it is probably the interrupt handling. Each of the wheel and the tach interrupt routines adds an entry into a log of times. The main loop routine polls the log every 100 ms and runs the required logic. I've posted the tach and wheel routines below because that's where the bulk of the logic is. The reason for the two stage interrupt process is so I can put debugging into the logic without messing up interrupts. I've also posted the actual tach interrupt routine. the wheel routine is simpler because it posts every event where the tach bulks them up by 10.
void processwheel(unsigned long lmillis){ //input is time of interrupt from log
unsigned long wheeltime; //time for previous revolution
if (lastwheelint!=0){ //don't do calculations 1st time in
wheeltime=lmillis-lastwheelint; //track the exact rotation time
wheelrpm=60000/(float)wheeltime;
//Serial.print(" wheeltime="); Serial.print(wheeltime); Serial.print(" wheel rpm="); Serial.print(wheelrpm);
roadspeed=.123*wheelrpm; //condensed version of 2.05*60*wheelrpm/1000; where 205 is wheel circ. in metres
//Serial.print(" road speed kph="); Serial.print(roadspeed);
setgear(); //figure out what gear we're in
}
lastwheelint=lmillis;
}
void processtach(unsigned long lmillis){ // input is interrupt time in millis
unsigned long tachtime; //elapsed time for 10 tach events
if (lasttachint!=0) { //skip calculation on first time in
tachtime=lmillis-lasttachint; //time for last 10 events
if (tachtime>0){ //just avoid divide by 0
insttachrpm=60000/(float)tachtime*10; //rpm based on time in ms for 10 tach pulses
avgtachrpm=(avgtachrpm*2+insttachrpm)/3; //rolling average rpm
//Serial.print(" tachtime="); Serial.print(tachtime); Serial.print(" inst tach rpm="); Serial.print(insttachrpm); Serial.print(" avg tach rpm="); Serial.print(avgtachrpm);
}
}
lasttachint=lmillis;
}
void tachmonitor(){ //this is the actual interrupt routine
static int tachcount;
if (tachcount <9) { //bulking up tach interrupts by a factor of 10
tachcount++;
}
else { //every 10th tach pulse we spawn a log entry
if (ilog<=maxlog){
lflag[ilog]='T'; //pedal pass flag
lmillis[ilog]=millis();
ilog++;
}
else {
logoflo=true; //we've overrun the log table
}
tachcount=0;
}
}