Bicycle speedometer

Hello everyone,

I am trying to build a speedometer for my bicycle. I have some issues with my current hardware. Let me go through of what i have done first. I have attached a magnet on my bicycle radius (not sure if there is a specific way to do that). Next i have attached a magnetic sensor with my arduino quite close to the magnet. When I spin the wheel (slowly) and the magnet passes from the sensor the arduino onboard led turns on. Else the led is turned off. The PROBLEM is when I turn the wheel fast (It is not very fast since I am doing this with my hands) it skips everything. I am not sure what I am doing wrong and if my hardware is not enough what should I buy? It seems that there is not enough time to catch the magnetic force.

thanks for your time.

regards Billy.

194 posts and you still haven't read the stickies?

In other words, you forgot to post: - schematics - part numbers - code

Sounds like your (unspecified) sensor is not responding fast enough. Perhaps choosing a faster sensor will help.

Or it could be your (unspecified) sketch. Do you have anything in your loop() that might be slowing down the response?

If you can verify that the hardware is capable of sensing at higher speeds it might be time to investigate interrupts.

Try a bare bones sketch whose only function is to blink the onboard LED (for a minimum time, say 500 milliseconds) when the sensor input goes active.

Hello sorry for the previous message. Here is the code that I am working with.

const int switchPin = 2;
const int ledPin = 13;
const int relay1=7;
const int relay2=8;
int times=0; // how many times the wheel turns

void setup() {
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(switchPin, HIGH);

  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);

  digitalWrite(relay1, HIGH);
  digitalWrite(relay2, HIGH);

void loop() {
  if(digitalRead(switchPin) == LOW){
    digitalWrite(ledPin, LOW);
    times = times + 1;
  }else {
    digitalWrite(ledPin, HIGH);

  /* Check the relay status */
  if(times==3) {
    digitalWrite(relay1, LOW);
  }else if(times==8) {
    digitalWrite(relay2, LOW);
  Serial.println("Whell turn times:");

Furthermore I have no schematics about my sensor. I just work with plug and play mode. The sensor is this:

I would suggest two things.

1) Switch the magnet polarity, and see if the sensor responds better. 2) Use a stronger external pull up (4.7K) instead of the internal pullup you enabled with

pinMode(switchPin, INPUT);
  digitalWrite(switchPin, HIGH);
//equivalent to pinMode(switchPin, INPUT_PULLUP);

Thank you for your response. Would your mind explaining what exactly that INPUT_PULLUP does? Any usefull link or something that is similar to what you are thinking?

thank you.

Sparkfun tutorial

You can buy these very cheaply from any cycle shop - why bother?


HI, What does the LED on the Hall Effect PCB do when the wheel turns.

You need to post a diagram, hand draw a diagram and post a picture of it.

Plug and Play just doesn't cut it if you are going to be experimenting/building with electronics.

What happens if you stop the wheel with the magnet continually activating the sensor? You need to detect the sensor output GOING HIGH not BEING HIGH.

Thanks.. Tom.. :)

Would your mind explaining what exactly that INPUT_PULLUP does?

At the top of the forum web page is a heading “LEARNING”. One of the menu items is “REFERENCE” and most of the basic syntax questions are answered there. There are listings for both pinMode() and INPUT_PULLUP.

The output of the hall sensor module is an npn transistor with open collector. It is basically a NO switch to ground, with a floating output when open (not switched to ground). In order for the Arduino input to read this properly, it needs a “pull up” resistor to a HIGH level voltage when open.
this pullup resistor can be either the internal resistor engaged with INPUT_PULLUP or an external resistor. The internal resistor is about 50K, and my not provide a strong enough pull up to HIGH. An external resistor can be of lower resistance 4.7K to 10K is frequently used.

Google will be your friend for any terms you don’t understand.

allanhurst: You can buy these very cheaply from any cycle shop - why bother?

Personal enrichment?

xmarkx: I am trying to build a speedometer for my bicycle.

You appear to be on the wrong tram. You appear to be counting wheel revolutions, and for a purpose that is incomprehensible. I guess this line of code sums it up quite well

  Serial.println("Whell turn times:")

If you really do want to build a bicycle speedometer, there are plenty of examples of fan speed, water flow, engine rpm, even bicycle speedometers, on this forum. They all work much the same way, using an interrupt counter, which is not the way you propose.

Reading reply#8 again would be a rather good idea as well. The speedo I use cost $2.

Buy a hall effect sensor that can be used with high speed dc motors. And implement it to your application. Do not use analog sensor if you can use digital, it would be much faster.

There’s a delay(100) in the loop. This means your sensor is checked only once every 100 ms. That’s plenty of time to miss a rotation. And indeed you need to detect the change as pointed out above.

Try this:

bool tick = false;
uint32_t detectedTime = 0;
uint16_t ledTime = 300;
void loop() {
  if(digitalRead(switchPin) == LOW && tick == false){
    times = times + 1;
    tick = true;
    detectedTime = millis();
    Serial.print("Wheel turn times: ");
  if (millis() - detectedTime < ledTime)
    ditigalWrite(ledPin, LOW)
  else {
    digitalWrite(ledPin, HIGH);

  /* Check the relay status */
  if(times==3) {
    digitalWrite(relay1, LOW);
  }else if(times==8) {
    digitalWrite(relay2, LOW);

Upon tick detection the flag is set, the number of rotations so far is printed, a timer is started, and the LED lights up for 300 ms.
No delay() in the loop() allows your sensor to be checked much much more frequent. That delay() is probably the killer, together with your Serial.print() statement which also takes time.

Ok thank you i will try to test this out and i hope it works.