Help with electric bike senior project

Hello I am a student and my college senior project is to build an electric bike. I wanted to use an arduino to make my project even better to add a speedometer and blinkers and while my program works it wont do both at the same time.

I found a program that uses a reed sensor on the fork and a magnet on the wheel and allows me to calculate the speed which. Depending on the speed one LED lights up for each mph up to 5 mph. (Ill add more later)

I also wrote a program so when a pushbutton is pressed an led will blink until the pushbutton is pressed again. I have two sets of one button and one led for two blinkers.

I am a mechanical engineering student so this isnt my strong suit by any means. That being said I realize I need to implement debounce and my code isnt beautiful, but I need a bit of help.

Why if both sections work correctly is it that when I run the program the speedometer takes over the blinker stops. I assume it is for the same reason that I cant turn on both blinkers at the same time even though I didnt intentionally program this to be a feature.

I have attached my code below and any help would be greatly appreciated

Thank you!

Ethan

const int reed = A0;    // pin that the sensor is attached to
const int ledPin13 = 13;       // pin that the LED13 is attached to
const int ledPin12 = 12;
const int ledPin11 = 11;
const int ledPin10 = 10;
const int ledPin9 = 9;
const int ledPin8 =  8;
const int ledPin7 =  7;
const int button1Pin = 6;
const int button2Pin = 5;

int reedVal;
long timer;// time between one full rotation (in ms)
float mph;
float radius = 8.5;// tire radius (in inches)
float circumference;

int state1 = HIGH;     
int reading1;           
int previous1 = LOW;

int state2 = HIGH;     
int reading2;           
int previous2 = LOW;

int maxReedCounter = 100;//min time (in ms) of one rotation (for debouncing)
int reedCounter;

void setup() {
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  
  reedCounter = maxReedCounter;
  circumference = 2*3.14*radius;
  pinMode(reed, INPUT);
  pinMode(ledPin13, OUTPUT);
  pinMode(ledPin12, OUTPUT);
  pinMode(ledPin11, OUTPUT);
  pinMode(ledPin10, OUTPUT);
  pinMode(ledPin9, OUTPUT);
  // TIMER SETUP- the timer interrupt allows precise timed measurements of the reed switch
  //for more info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  
  sei();//allow interrupts
  //END TIMER SETUP
  
  Serial.begin(9600);
}


ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
  reedVal = digitalRead(reed);//get val of A0
  if (reedVal){//if reed switch is closed
    if (reedCounter == 0){//min time between pulses has passed
      mph = (56.8*float(circumference))/float(timer);//calculate miles per hour
      timer = 0;//reset timer
      reedCounter = maxReedCounter;//reset reedCounter
    }
    else{
      if (reedCounter > 0){//don't let reedCounter go negative
        reedCounter -= 1;//decrement reedCounter
      }
    }
  }
  else{//if reed switch is open
    if (reedCounter > 0){//don't let reedCounter go negative
      reedCounter -= 1;//decrement reedCounter
    }
  }
  if (timer > 2000){
    mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
  }
  else{
    timer += 1;//increment timer
  } 
}

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

void loop() {               // the loop routine runs over and over again forever:
    
  reading1 = digitalRead(button1Pin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading1 == HIGH && previous1 == LOW) {
    if (state1 == HIGH)
      state1 = LOW;
    else
      state1 = HIGH;   
  }

  if (state1 == HIGH){
    digitalWrite(ledPin8, HIGH);
    delay(200);
    digitalWrite(ledPin8, LOW);
    delay(200);   
  }
 
  else if (state1 == LOW) {
    digitalWrite(ledPin8, LOW);
  }

  previous1 = reading1;
  
  reading2 = digitalRead(button2Pin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading2 == HIGH && previous2 == LOW) {
    if (state2 == HIGH)
      state2 = LOW;
    else
      state2 = HIGH;   
  }

  if (state2 == HIGH){
    digitalWrite(ledPin7, HIGH);
    delay(200);
    digitalWrite(ledPin7, LOW);
    delay(200);   
  }
 
  else if (state2 == LOW) {
    digitalWrite(ledPin7, LOW);
  }

  previous2 = reading2;
  
//print mph once a second
  displayMPH();
  delay(1000);
  
  if(mph > 1) {
    digitalWrite(ledPin9, HIGH);
  }
  else {
    digitalWrite(ledPin9, LOW);
  }
  
  if(mph > 2) {
    digitalWrite(ledPin10, HIGH);
  }
  else {
    digitalWrite(ledPin10, LOW);
  }
  
   if(mph > 3) {
    digitalWrite(ledPin11, HIGH);
  }
  else {
    digitalWrite(ledPin11, LOW);
  }
  
   if(mph > 4) {
    digitalWrite(ledPin12, HIGH);
  }
  else {
    digitalWrite(ledPin12, LOW);
  }
  
   if(mph > 5) {
    digitalWrite(ledPin13, HIGH);
  }
  else {
    digitalWrite(ledPin13, LOW);
  }
}

Why do you go through the pain of creating an interrupt to occur every 1/1000th of a second when there's a perfectly good counter being incremented every thousandth of a second available by reading millis();

A better approach would be to setup an interrupt to occur on each rising edge of your sensor. At this point you can read millis() and compare to the last time around. So if millis has advanced by 500 then your wheel is spinning at 2 rpm.

Store this in a global variable (perhaps called RPM) and then within your loop you can read it any time you fancy.

I can see two problems:

  • Your code is blocking because of the delay() function. It is impossible to do things simultaneously with blocking code
  • For the low speeds you are describing you will get a very slow update of the speedometer. At 1Mph one revolution will take about 3s. I suggest you mount more wheel magnets to increase the update rate