Speedometer not displaying values.

Hello,
I have a coding related issue with my project. It is a speedometer using a reed switch, converting measured blinks from a driveshaft on a tractor to MPH at the wheels. The issue is is that when i go to serial monitor to display information during testing, I get values of 0.00. Here is the code:

#define reed A0

int reedVal;
long timer;
float mph;
float radius = 12;
float circumference;
float gearing = 3.83;

int maxReedCounter = 100;
int reedCounter;

void setup(){

reedCounter = maxReedCounter;
circumference = 23.14radius;
pinMode(reed, INPUT);

//Setup Timer, allows for precise timed readings of the reed switch
cli();//breaks interrupt

//set interrupt to 1kHz
//TCCR variables are to set up timers, Google them.
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 1999; // = (1/1000)/((1/(16*10^6))*8)-1
//CTC mode TURN ON
TCCR1B |= (1 << WGM12);
//timer compare interrupt
TIMSK1 |= (1 << OCIE1A);

sei();//interruption allowance
//END TIMER

Serial.begin(9600);//bauds
}

ISR(TIMER1_COMPA_vect){//interrupt @ freq of 1kHz to measure reed
reedVal = digitalRead(reed);//obtain val from pin A0
if (reedVal){//when reed closed
if(reedCounter == 0){
mph = (56.8*float(circumference))/(float(timer)*float(gearing));
timer =0;//timer reset
reedCounter = maxReedCounter;
}
else{
if(reedCounter > 0){
reedCounter -= 1;
}
}
}
else{
if(reedCounter > 0){
reedCounter -= 1;
}
}
if(timer > 2000){
mph =0;
}
else{
timer += 1;
}
}

void displayMPH(){
Serial.println(mph);
}

void loop(){
//once a second mph display, can be adjusted
displayMPH();
delay(333);//milliseconds
}

I know it’s not a mechanical issue because i used this for test and it displays ‘1023’ when a magnet is near the reed switch:

#define reed A0

int reedVal;

void setup() {
Serial.begin(9600); //enabling 9600 baud for serial monitoring
}

void loop() {
reedVal=analogRead(reed);
Serial.println(reedVal);
delay(10); //assign refresh rate to 10ms
}

I am a newer programmer and self educated, so help with this issue and advice is greatly appreciated. This is a modified version of the famous arduino bike speedometer.

Can you provide the circuit that is used with this sketch? How fast is your shaft turning? None of the variables used in the main program and the interrupt handler are declared volatile as they should be.

Using a timer interrupt to read the reed switch once a millisecond is quite a bit extraordinary. There are more efficient ways to get that information and doing such a lot of calculations inside the interrupt handler should be avoided.

Please use code and not quote tags next time you post code (do you see the smiley in the code, that and worse things happen when you don't use code tags).

It spins about 860 RPMs at its fastest, but will average spinning in the 400-500 rpm range. I can not upload a sketch right now but will be able to later.

Have you tried declaring the variables volatile?

Using an external interrupt with the reed switch is a better way to go. There are so many complications with polling. If you want to troubleshoot the polling scheme... There are two ways mph could be 0, either this line never gets executed...

mph = (56.8*float(circumference))/(float(timer)*float(gearing));

or this line gets executed...

 mph =0;

Next step is to find out which one.

DavidOConnor: Using an external interrupt with the reed switch is a better way to go. There are so many complications with polling.

My opinion is exactly the opposite. Using interrupts introduces a lot of design issues and complexities and should be avoided as far as possible, and if necessary only used reluctantly and to the minimum extent necessary. I don't see any need for them here. Using a polling based approach will be perfectly adequate in performance terms, and will make it easy to debounce the signal (which you're quite likely to need, with a reed switch).

Debouncing the switch is easy at such low RPM. The shaft rotational period at full speed is about 70 ms, so just ignore the switch for about 35 ms after the first close. If you want to go faster, measure the bounce time of the switch with a scope.

Here is the interrupt based solution…

volatile unsigned long lastSwitchTime=0;
volatile int rpm;

void setup() {
  Serial.begin(9600);
  attachInterrupt(0,reedSwitchInterrupt,RISING);
}

void loop() {
  delay(1000);
  Serial.println(calcMph(rpm));
  rpm = 0;
}

void reedSwitchInterrupt() {
  unsigned long now = millis();  
  int elapsedTime = now - lastSwitchTime;
  
  if (elapsedTime < 35)
    return;
  if (elapsedTime > 2000)
    rpm = 0;
  else
    rpm = 60.0/(elapsedTime/1000.0);
  lastSwitchTime = now;
}

int calcMph(int rpm) {
  // convert rpm to mph
}

Thank you thank you thank you DavidOConnor!!!! I borrowed a couple things from your code and got it working.

My opinion is exactly the opposite. Using interrupts introduces a lot of design issues and complexities and should be avoided as far as possible,

I'd agree with you, except that OP is using interrupts - timer based ones. David's suggestion, as I read it, was to junk the timer based polling, and trigger an interrupt when the sensor is activated.

On the other hand, if the pulses are slow enough, neither interrupt scenario is needed.