Go Down

Topic: Measuring speed of a motorbike wheel (Read 1 time) previous topic - next topic

Markosec

Oh, sorry, i was trying to simplify, since the original code contains more stuff outside the part shown.
The variables inside the loop are:
Code: [Select]
  long int cuantos  = 0;
  long velocidad  = 0;
  long contador = 0;
  long ultima_vez = 0;
  unsigned long  promedio = 0;
  boolean igual = true;
  unsigned long verificacion[3];
  int i = 0;


And the ISR variables are declared like:
Code: [Select]
volatile unsigned long ultimo = 0;
volatile unsigned long tiempos[3];
volatile int  puntero = 0;
volatile float m_totales   = 0;


I read somewhere (tutorial maybe) that ISR variables should be volatile, not sure why, but i did it, just in case.
The ISR routine is not too long? Not sure if that's ok....
Also, could it be that an interrupt calls just when the arduino is writing to the LCD, and some random lines appear? Once in a while this happens, a few green or white lines are drawed, but behaviour remains the same....
Another thing i don't understand, is that if i should enable the internal pull-up resistors or not, in this case it's enabled:
Code: [Select]
  pinMode(18, INPUT);  //Velocimetro  (PIN 18 para el interrupt)
  pinMode(18,HIGH);   // Internal pull up resistor(?)

The (presumed) hall sensor goes to arduinos +5v and pin 18, wich should be interrupt 5, and the pin 18 input is tied to ground via a resistor (3.9 Kohms )
Any suspects?  :~
I'll do it, just because i can do it

Far-seeker

If a input pin has a pull-up resistor enabled the voltage at that pin sits around 5V or HIGH unless and until it is pulled LOW by whatever is attached to the pin.  You have your ISR set to detect a rising edge, i.e. when the pin goes from LOW to HIGH.  Theoretically, this should only mean a delay as the input pin goes from HIGH to LOW then back to HIGH, but only if the sensor attached to the pin is reliably pulling that pin LOW each revolution of the wheel.

Depending on how what's attached to pin 18 behaves, you may want to try changing the ISR to be falling or disable the pull-up resistor.

dc42

You have declared your arrays with 3 elements each, but they should be declared with 4 elements each instead. You will be overrunning them when you store the 4th element, which probably accounts for the problem.

Regarding the correct wiring of the sensor, if it is a Hall sensor then it should have 3 terminals, not 2. Do you have a datasheet for it? If it has only 2 terminals, maybe it is a reed switch.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

JavaMan

Hi again Markosec,

You've made progress, but it still seems more complicated than it needs to be.  4 magnets? arrays? interrupts?  Maybe it would help if you saw an example of a simpler way.  One measurement per rotation.  See if you can work through the logic in loop() on the sketch below. The code is tested and works.  You can ignore the lines having to do with the lcd display if you want, and you will need to change the rollout to 1880 and convert from miles per hour to kilometers per hour.

Code: [Select]
// Written by Tom Fangrow, July 15, 2012
// reed switch on pin 4, LED on pin 13

#include <LiquidCrystal.h>

LiquidCrystal lcd(3, 5, 9, 10, 11, 12);
unsigned long newTime, oldTime=0;
float newPeriod, oldPeriod=0.0, velocity;
float rollout = 2085.0;      // tire circumference in mm

void setup() {
  pinMode(4, INPUT_PULLUP);  // other side of switch to ground
  pinMode(13, OUTPUT);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Bike Computer");              // welcome screen
  lcd.setCursor(0, 1);
  lcd.print("version 1.0");
  delay(3000);
}

void loop() {
  if(digitalRead(4) == LOW) {              // switch is closed
    newTime = millis();                    // note the time
    digitalWrite(13, HIGH);                // turn on LED
    newPeriod = float(newTime-oldTime);    // rotation period
    velocity = rollout*60*60/(newPeriod*1609.34);     // mph
    updateScreen();
    oldTime = newTime;                     // update oldTime
    oldPeriod = newPeriod;                 // update oldPeriod
    delay(60);           // allow time for switch to open again
  }
  else {                                   // switch is open
    digitalWrite(13, LOW);                 // turn off LED
    if(millis()-oldTime > 3000) {          // if bike stopped
      velocity = 0.0;                      // zero out display
      updateScreen();
      oldTime = millis();    // this will refresh every 3 seconds
    }
  }
}

void updateScreen() {
  lcd.clear();
  lcd.setCursor(0, 0);                    // first line
  lcd.print("Current Speed");
  lcd.setCursor(0, 1);                    // second ine
  lcd.print(velocity);
  lcd.print(" mph   ");     // extra spaces erase previous data
}

Markosec

hi everyone, thanks for the examples and guidance, i've finally managed to make it work!  :) I started from scratch, with another approach as suggested.
But being a noob, a loose wire apparently fried up my mega, sending current through an output pin , it's now unable to communicate with a pc, so i can't upload new sketches, it keeps being detected as an unknown device.   =(  (tried different usb cables and computers)
I'm now trying to design a pcb to protect the inputs and outputs via optocouplers (and placing wires really really away from the arduino)while a new mega arrives.
Thanks to everyone for the support, i'll open a new post (with pictures!) when i get the new board, to show what's done  ;)
I'll do it, just because i can do it

Go Up