# Reed sensor to calculate speed

**URL:** <https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501>\
**Category:** Programming\
**Created:** [January 10, 2022, 3:35pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501 "2022-01-10T15:35:04Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 3:35pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/1 "2022-01-10T15:35:04Z")

</div>

Hello all

I am trying to make speedometer for my bike. I've got a reed sensor and a hc05 bluetooth module.

I want to calculate the speed im going.

The problem i'm having is that 'timer' stays 0 at all times. It's the first time im working with these interrupts so i might be doing something wrong.

Can anyone help? I have added prints for all variables and commented their output next to it

```cpp
int reedSwitch =7;
int circumference;   
int totaltime;      
int Speed;           
int timer;          
int radius = 311; // radius in mm
int reed_status;

void isr()           
 {   
      timer++;                    
      delayMicroseconds(9600);  
 }
 
void setup(){
  Serial.begin(9600);                                        
  attachInterrupt(digitalPinToInterrupt(reedSwitch), isr, RISING);   
   pinMode(reedSwitch, INPUT_PULLUP);                        
   timer = 0;                                                
   Speed= 0;                                                 
   totaltime = 0;                                             
   circumference = 6.28 * radius;                             
}

void loop() {
    //reed_status = digitalRead(reedSwitch); // this code prints 0 when magnet is close and 1 when no magnet is close so the reed sensor is working 
    //Serial.println(reed_status);                                                  
    delay(5);
   if (millis() - totaltime >= 1000) {                                      
                                                                            
        detachInterrupt(digitalPinToInterrupt(reedSwitch));                          

        Speed= ((0.0036*circumference)/(millis() - totaltime)*timer); // Calculates the speed of the bike. mm/s -> km/u

        Serial.print("Speed ");                                               
        Serial.println(Speed); //prints 0

        Serial.print("circum ");                                               
        Serial.println(circumference); // prints 1953

        Serial.print("totaltime ");                                               
        Serial.println(totaltime); // this prints 1000 + 1000 every loop until about 32000. Then it prints -32000 and the prints start coming way faster
        
        Serial.print("timer ");                                               
        Serial.println(timer); //prints 0

        timer = 0;                                                          
        totaltime = millis();                                               
        attachInterrupt(digitalPinToInterrupt(reedSwitch), isr, RISING);             
   }
}

```

---

<div class="post-metadata">

**Author:** ![sherzaad](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/sherzaad/32/226173_2.png) [@sherzaad](https://forum.arduino.cc/u/sherzaad)\
**Post date:** [January 10, 2022, 3:42pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/2 "2022-01-10T15:42:27Z")

</div>

> [@jasper-bot](#):
>
> `int Speed;`

> [@jasper-bot](#):
>
> `Speed= ((0.0036*circumference)/(millis() - totaltime)*timer);`

'Speed' is an int but your are calculating a floating point value. try changing any variables that you are using that ARE not **integer** values to **float**

also for your 'timer' variable, I would suggest you use **_volatile_ int timer**

hope that helps....

---

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 3:49pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/3 "2022-01-10T15:49:35Z")

</div>

Thank you for your reply and help.

I changed Speed to float but it did not change anything. Just to be sure i also changed totaltime to float, timer to volatile float timer and circumference to float as a second test.

This also did not change anything.

I think the main problem is that timer is always 0 (that causes the equation to always be 0)

---

<div class="post-metadata">

**Author:** ![SteveThackery](https://avatars.discourse-cdn.com/v4/letter/s/96bed5/32.png) [@SteveThackery](https://forum.arduino.cc/u/SteveThackery)\
**Post date:** [January 10, 2022, 4:05pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/4 "2022-01-10T16:05:16Z")

</div>

Still trying to decipher your code. 'totaltime' needs to be an unsigned long integer, by the way.

I've never seen anyone put a delay() in an ISR. It doesn't work, does it?

---

<div class="post-metadata">

**Author:** ![sherzaad](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/sherzaad/32/226173_2.png) [@sherzaad](https://forum.arduino.cc/u/sherzaad)\
**Post date:** [January 10, 2022, 4:06pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/5 "2022-01-10T16:06:13Z")

</div>

> [@jasper-bot](#):
>
> I think the main problem is that timer is always 0 (that causes the equation to always be 0)

if that is the case then it seems that the ISR is never triggered then...

please know a schematic of your circuit connections of the reed relay to the arduino. hopefully that may shed some light on this issue...

btw why the delay within the ISR?? sort of a bad practice to put one within an ISR...

---

<div class="post-metadata">

**Author:** ![SteveThackery](https://avatars.discourse-cdn.com/v4/letter/s/96bed5/32.png) [@SteveThackery](https://forum.arduino.cc/u/SteveThackery)\
**Post date:** [January 10, 2022, 4:09pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/6 "2022-01-10T16:09:20Z")

</div>

So what is that delayMicroseconds(9600) in the ISR for anyway?

By the way, you don't need to detach and attach the interrupt every time. Use interrupts() and noInterrupts() instead.

---

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 4:21pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/7 "2022-01-10T16:21:05Z")

</div>

I have tried with and without the delay. I have deleted it now.

How do i use interrupts() and noInterrupts()?

Do i just replace detach with noInterrupts();  
and attach with interrupts()?

Working on a DIY scheme of my setup btw

```cpp
int reedSwitch =7;
float circumference;   
float totaltime;      
float speedt;           
volatile float timer;          
int radius = 311; // radius in mm
int reed_status;

void isr()           
 {   
      timer++; // Begin the timer and start counting
 }
 
void setup(){
  Serial.begin(9600);                                        
  //attachInterrupt(digitalPinToInterrupt(reedSwitch), isr, RISING);   
   pinMode(reedSwitch, INPUT_PULLUP);                        
   timer = 0;                                                
   speedt = 0;                                                 
   totaltime = 0;                                             
   circumference = 6.28 * radius;                             
}

void loop() {
    //reed_status = digitalRead(reedSwitch); 
    //Serial.println(reed_status); // prints 0 when magnet is close and 1 when no magnet is close
    delay(5);
   if (millis() - totaltime >= 1000) {                                      
                                                                            
        //detachInterrupt(digitalPinToInterrupt(reedSwitch));                          
        noInterrupts();
        speedt = ((0.0036*circumference)/(millis() - totaltime)*timer); // Calculates the speed of the bike. mm/s -> km/u

        Serial.print("Speed ");                                               
        Serial.println(speedt);

        Serial.print("circum ");                                               
        Serial.println(circumference);

        Serial.print("totaltime ");                                               
        Serial.println(totaltime);
        
        Serial.print("timer ");                                               
        Serial.println(timer);

        timer = 0;                                                          
        totaltime = millis();     
        interrupts();                                          
       // attachInterrupt(digitalPinToInterrupt(reedSwitch), isr, RISING);             

        
   }
}

```

---

<div class="post-metadata">

**Author:** ![SteveThackery](https://avatars.discourse-cdn.com/v4/letter/s/96bed5/32.png) [@SteveThackery](https://forum.arduino.cc/u/SteveThackery)\
**Post date:** [January 10, 2022, 4:26pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/8 "2022-01-10T16:26:43Z")

</div>

> [@jasper-bot](#):
>
> How do i use interrupts() and noInterrupts()?

It's better for you to refer to the official documentation:

> **[Arduino Reference - Arduino Reference](https://www.arduino.cc/reference/en/)**
>
> The Arduino programming language Reference, organized into Functions, Variable and Constant, and Structure keywords.

Look in the Functions section.

---

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 4:33pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/9 "2022-01-10T16:33:00Z")

</div>

This is probably the worst schematic you have ever seen, but i think it shows everything necessary and i dont have software for making schemes...

the reed module has a 10k pullup resistor ([VMA308: ARDUINO® COMPATIBLE MINI MAGNETIC REED MODULE (2 pcs) – Velleman – Wholesaler and developer of electronics](https://www.velleman.eu/products/view/?id=435530))

I have tried with and without a 10k ohm resistor between + and - of the reed switch

 ![scheme.PNG](https://europe1.discourse-cdn.com/arduino/original/4X/4/d/a/4da56d4c9a4e7c147da0cd033c16fdcd1fcc52e0.jpeg)

Picture: the hc05 module is disconnect because you cant upload sketches when the 0 and 1 ports are connected.

 ![270572521_472612524298014_3896586336465738287_n](https://europe1.discourse-cdn.com/arduino/original/4X/4/e/1/4e1e9276f4b9faaf56513a2dd609cf1d8c0413f6.jpeg)

---

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 5:06pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/10 "2022-01-10T17:06:01Z")

</div>

I have changed my code to millis() - totaltime is in milliseconds, my formula was for seconds.

I have divided millis() - totaltime by 1000. I think this should work now. I havent testen on a wheel but by playing with a magnet, the values are kinda believable.

```cpp
int reedSwitch =2;
float circumference;   
float totaltime;      
float speedt;           
volatile float timer;          
int radius = 311; // radius in mm
int reed_status;

void isr()           
 {   
      timer++; // Begin the timer and start counting
 }
 
void setup(){
  Serial.begin(9600);                                        
  attachInterrupt(digitalPinToInterrupt(reedSwitch), isr, RISING);   
   pinMode(reedSwitch, INPUT_PULLUP);                        
   timer = 0;                                                
   speedt = 0;                                                 
   totaltime = 0;                                             
   circumference = 6.28 * radius;                             
}

void loop() {
   if (millis() - totaltime >= 1000) {                                      
                                                                      
        detachInterrupt(digitalPinToInterrupt(reedSwitch));                          

        speedt = ((0.0036*circumference)/((millis() - totaltime) / 1000 )*timer); // Calculates the speed of the bike. mm/ms -> km/u
       
        timer = 0;                                                          
        totaltime = millis();     
                                                 
       attachInterrupt(digitalPinToInterrupt(reedSwitch), isr, RISING);             

        
   }
}

```

---

<div class="post-metadata">

**Author:** ![Paul\_KD7HB](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/paul_kd7hb/32/1127958_2.png) [@Paul\_KD7HB](https://forum.arduino.cc/u/Paul_KD7HB)\
**Post date:** [January 10, 2022, 5:33pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/11 "2022-01-10T17:33:35Z")

</div>

Perhaps the major problem is you are using a module with an active IC device that just happens to have a reed switch. But your program is written as if it is actually directly connected to a real reed switch. Nothing in the link you gave for the module has any information about the module or how to use it. I see a pot on the board, so that is likely a sensitivity control, but perhaps some other use. Who knows. But until you get that actually defined, there is no hope for you program.

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [January 10, 2022, 5:41pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/12 "2022-01-10T17:41:32Z")

</div>

There is no reason to use interrupts for an application like this. They introduce more problems (for a beginner) than they solve.

Do the timing in loop().

---

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 5:43pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/13 "2022-01-10T17:43:59Z")

</div>

I know that if i hold a magnet next to it the digitalRead value is 0 and when no magnet is close, the digitalRead value is 1.

But my program definitly doesnt work as intended yet... The values for Speed in the program above are something like:

```cpp
speed49.22
speed7.03
speed0.00
speed0.00
speed21.09
speed14.06
speed14.06
speed7.03
speed49.22
speed28.12
speed21.09
speed49.22
speed35.16
speed63.28
speed49.22
speed28.12
speed0.00
speed7.03
speed0.00
speed14.06

```

---

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 7:14pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/14 "2022-01-10T19:14:14Z")

</div>

Yea, i reworked my sketch to this. It is definitly not perfectly accurate but an estimate is good enough for the time being.

```cpp
unsigned long day = 86400000;
unsigned long hour = 3600000; // 3600000 milliseconds in an hour
unsigned long minute = 60000; // 60000 milliseconds in a minute
unsigned long second = 1000; // 1000 milliseconds in a second

unsigned long startMillis;  
unsigned long elapsedTimeCircumference;
unsigned long previousTimeCircumference;
const unsigned long period = 250; 

unsigned long Speed;

int reed_sensor = 2;
int reed_status;

float elapsedDistance;
//in mm
unsigned int radius = 311;
float circumference;  

void setup()
{
  Serial.begin(9600);
  pinMode(reed_sensor, INPUT_PULLUP);   
  startMillis = millis();
  elapsedTimeCircumference = millis();
  // in mm
  circumference = 6.28 * radius; 
}

void loop()
{
   reed_status = digitalRead(reed_sensor);
   startMillis = millis();
  
  if (reed_status == 0)
  {
      readValues();
  }
}

void readValues() {
        // tijd sinds vorige rotatie in ms
        elapsedTimeCircumference = startMillis - previousTimeCircumference;
        
        // snelheid in km/uur
        Speed = (( 3.6 * circumference)/(elapsedTimeCircumference)); 

        // afgelegde afstand in mm
        elapsedDistance += circumference ; 
        
        previousTimeCircumference = millis();
        Serial.println("speed: ");
        Serial.println(Speed);
        distance(elapsedDistance);
        Serial.println("Totale tijd: ");
        time(millis());
        delay(100);
 }

 void distance(float distancemm) {
  if (distancemm <= 500000) {
      float meter = distancemm / 1000;
      Serial.print("afgelegde afstand in meter:");
      Serial.println(meter);
    } else {
      float km = distancemm / 1000000;
      Serial.print("afgelegde afstand in km:");
      Serial.println(km);
      }
  }

void time(long timeNow){
 int days = timeNow / day ;                                
 int hours = (timeNow % day) / hour;                      
 int minutes = ((timeNow % day) % hour) / minute ;       
 int seconds = (((timeNow % day) % hour) % minute) / second;
 
  Serial.print(days,DEC);  
  printDigits(hours);  
  printDigits(minutes);
  printDigits(seconds);
  Serial.println();  
}

void printDigits(byte digits){
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits,DEC);   
}

```

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [January 10, 2022, 7:20pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/15 "2022-01-10T19:20:45Z")

</div>

The way I solve timing problems like this is:

1. wait until the sensor first detects the magnet and closes,
2. wait for the sensor to open, then record start\_milliseconds.
3. wait for sensor to close
4. wait for sensor to open, calculate total time and report speed.

For more stable reports, keep a running average of speeds (say, the last three values, and report the average).

---

<div class="post-metadata">

**Author:** ![jasper-bot](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@jasper-bot](https://forum.arduino.cc/u/jasper-bot)\
**Post date:** [January 10, 2022, 7:31pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/16 "2022-01-10T19:31:45Z")

</div>

Would that be with a do while? Something like this:

```cpp
if(read_status == 0) {
do {
  delay(50);          
  read_status = digitalRead(reed_sensor);
} while (read_status == 0);
//continu code
}

```

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [January 10, 2022, 7:48pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/17 "2022-01-10T19:48:42Z")

</div>

Assuming 0 or LOW means magnet detected, here is what I have done.

```cpp
void loop() {
while (digitalRead(sensor) == HIGH) ; //wait until magnet detected.
while (digitalRead(sensor) == LOW); //wait until it passes
unsigned long start = millis();
while (digitalRead(sensor) == HIGH); //wait until detected again
while (digitalRead(sensor) == LOW); //wait until it passes again
unsigned long total_time = millis() - start;
report_speed(total_time);
}

```

NOTE: This skips one revolution of the wheel and starts over, which with a little more work, can be fixed. And, of course, the code is blocking. The Arduino can't do anything else.

---

<div class="post-metadata">

**Author:** ![JohnRob](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/johnrob/32/253560_2.png) [@JohnRob](https://forum.arduino.cc/u/JohnRob)\
**Post date:** [January 10, 2022, 9:20pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/18 "2022-01-10T21:20:51Z")

</div>

While troubleshooting I would print out the raw timer reading. When that works the way you want the worry about the conversion to Speed.

And to get a feel for how fast the pulses are coming you should calculate the time between pulses at your max desired sensing speed.

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [July 9, 2022, 9:21pm UTC](https://forum.arduino.cc/t/reed-sensor-to-calculate-speed/945501/19 "2022-07-09T21:21:32Z")

</div>

Closed on July 9, 2022, 9:21pm UTC

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
