Bike cadence sensor help

hello, how are you doing?, I have a question, I want to build a cadence sensor with the magnetic sensor and an oled screen by I2C, I have a code made, which was with the help of a friend and the internet but it measures the RPM incorrectly, someone could you help me with the code? (the project is for a racing bike)

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSerif9pt7b.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

const int REED_PIN = 0; // Pin connected to reed switch
const int LED_PIN = 13; // LED pin - active-high

const int REVS_PER_PEDAL = 4;     // Flywheel revolves 4x per pedal revolution
const int DISPLAY_REFRESH = 1000; // Refresh speed in milliseconds of OLED Display


float rev = 0;
float rpm[2];
int period_start = 0;
int period_duration;

void isr()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 30 ms, assume it's a bounce and ignore
  // 31ms is the time of a Reed spike at 30 RPM (assuming the magnet triggers on approxiamtively 1/16 of the wheel)
  // It's also >2x faster than the frequency of 200 RPM (pedals) - Shannon resolution
  // RPM values beween 30 and 200 should be reasonably good
  if (interrupt_time - last_interrupt_time > 30)
  {
    rev++;
  }
  last_interrupt_time = interrupt_time;
}

void setup() {
  pinMode(REED_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println("SSD1306 allocation failed");
    for(;;);
  }
  delay(2000);

  display.setFont(&FreeSerif9pt7b);
  display.clearDisplay();
  display.setTextSize(3);             
  display.setTextColor(WHITE);
    
  attachInterrupt(digitalPinToInterrupt (REED_PIN), isr, RISING); //interrupt pin
}

void loop() {
  delay(DISPLAY_REFRESH);
  detachInterrupt(digitalPinToInterrupt(REED_PIN));

  display.clearDisplay();
        
  period_duration = millis() - period_start;                  //duration since we started last IRQ
  rpm[1] = (rev / period_duration) * 60000 / REVS_PER_PEDAL;  //average RPM in current period
  rpm[0] = (2 * rpm[1] + rpm[0]) / 3;                         //weighted smoothing with previous measure         
  rev = 0;

  display.setCursor(25,50);             
  display.println((int)rpm[0]);
  display.display();

  period_start = millis();                                  //start a new period
  attachInterrupt(digitalPinToInterrupt (REED_PIN), isr, RISING);
}

I did the code with my friend (I don't know much about programming, I'm learning), he told me part of the code is from a cadence sensor project but for a stationary bike.
I would really appreciate a help

In what way does it measure RPM incorrectly?

Which Arduino?

1 Like

for example to have a 90rpm pedaling I have to pedal like crazy when in reality it is not like that

pro mini 5v (atmega 328)

Sounds like a calibration problem. Maybe fiddle with this line:

const int REVS_PER_PEDAL = 4;     // Flywheel revolves 4x per pedal revolution
const int REED_PIN = 0; // Pin connected to reed switch

Pin 0 is the Serial RX pin, NOT an interrupt pin, use pin 2 or 3 for REED_PIN.

Hi,
Can you please post a schematic diagram, showing your power supply, how you have the reed switch wired and include component names and pin labels.

Thanks... Tom... :grinning: :+1: :coffee: :australia:

1 Like

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