loading

Can anyone please give me code to detect speed and display on LCD using I2C interface?

   I have a speed sensor which gives 8 pulse per revolution of wheel. I want to calculate the speed of the wheel and display it on an LCD using I2C interface. The LCD interface works fine and I can print anything on it. But I do not know the code to calculate the speed and display it on LCD.
  Please help me and share with me a code that will calculate the speed based on 8 pulses/rev and display the speed on my LCD.


sort by: active | newest | oldest
frollard4 years ago
The best way to do this is using interrupts. An interrupt service routine, ISR is a function that can halt everything else, call a chunk of code, then return to the spot where it jumped from. The interrupt can be caused by a timer, or external pin transitioning, or going high, or going low.
http://arduino.cc/en/Reference/AttachInterrupt
^^must read.

(important concepts)
  • Speed is distance divided by time. Meters/second or miles per hour for examples.
  • Frequency likewise, is a count of incidents divided by time. revolutions per minute or Hertz (what we want here)
  • The period is the amount of time spent on each count. (similar to wavelength)
Example interrupt code:

int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
}

void loop()
{
  digitalWrite(pin, state);
}

void blink()
{
  state = !state;
}

In this example, the attachinterrupt() calls blink() whenever interrupt 0 (pin 2) changes.  blink() sets state to whatever it wasn't before, and loop() just sets the output to whatever 'state' is constantly.  It will never miss noticing whether the input changed, so state will always change, so blink should always work.

You'll also need to keep track of time.  You will need to look up millis() and micros() to understand how you can time various things

Now there are 2 options, you can count the number of pulses in a second, or count the number of micro/milli-seconds per pulse, then extrapolate the speed (inverse of period)
For the first option, you need to listen for whenever you get a pulse (rising will be easiest to detect) - and increment a counter (in the isr).  You can add up the number of pulses over an amount of time (say 1000 milliseconds (1 second)) and extrapolate from there.  By keeping a trailing average of the last few calculations you can average and smooth the number so it doesn't jump all over the place.  You can also keep track of total pulses (distance).  Lastly, knowing the circumference of your wheel, dividing by 8, you can apply a REAL distance to the count.
edifiedsprit (author)  frollard4 years ago
Hi,
Will the below code work???

#include // header file for AVR mC interrupts

int pulse_Pin = 2; // declaring digital pin2 as pulse pin and its data type would be integer
volatile int pulse_count; // create a volatile variable that counts the number of pulses in a given time which can be used inside the ISR
volatile int pulse_rate; // create a volatile variable to get number of pulse per second inside ISR
volatile float bike_speed; // get the final bike speed
volatile int time;
volatile int previous_time = 0; // declaring a variable to keep track of time start time;
volatile int current_time = millis(); // declaring a variable to keep track of current time;

void setup()
{
Serial.begin(9600); // enable serial monitor with a baud rate of 9600 bits/sec
pinMode(pulse_Pin, INPUT); // setting pulse_pin as an iput pin
sei(); // Enable global interrupts alternatively we can also write "interrupts() to enable interrupts"
attachInterrupt(0, ISR_function, RISING); // attaching hardware interrupt on INT0, for triggering on rising pulse
}

void ISR_function()
{

current_time= millis(); // taking the current millis reading as the current time
time= current_time-previous_time; // getting the time between two pulses


for(time=0; time<1000; time++); // keeping track of time till 1000 ms
pulse_count++;

pulse_rate=pulse_count/1000; // divide pulse count by 1000 ms gives number of pulses per second
bike_speed=pulse_rate*9.1998; // the factor 9.1998 was determined by experiments and then making a plot of the data between speed of bike V/S number of pulses
previous_time= current_time; // resetting the previous_time variable for the next count
}


void loop()
{
Serial.println("------------");
Serial.println(pulse_count);
Serial.println(pulse_rate);
Serial.println(bike_speed);
Serial.println("-------end--------------");

}
sort-of. You want to do the ABSOLUTE MINIMUM stuff in your isr, like increment a single counter...that's it. Do the rest in your main loop, like I said, set a flag and if the flag is set, do your calculation then clear the flag.
edifiedsprit (author)  frollard4 years ago
what you said translates to something like this..
void ISR_function()
{
pulse_count++;
}

void someOtherFunction()
{
... do the calculation here and get the speed///
}

void loop()
{
......use the speed here and proceed with the code

right???
exactly...

so,
(not in its entirety)
There is only one caveat and that's that IF the isr fires between doing a speed calculation and resetting the counter, there is a chance a pulse may be lost, but considering the speed of the processor and the time it takes to run that instruction, and that it will only fire once per second for a millionth of a second, you should be okay.

(there is again the other way to do it saying in loop 'if pulse count changes, set a time stamp and keep track of the current and last time stamp to calculate speed' - thay way you get an update every time the pulse comes in, which may be better than counting pulses.

volatile unsigned int pulse_count = 0;
unsigned long nextTime = 0;

void setup()
{
pulse_count = 0;
//attach ISR here,
nextTime = millis() + 1000; //when we did the calculation last. Should init to a number near zero, plus 1 second.
}

void ISRPinPulse()
{
pulse_count++
}

void loop()
{
if (millis() > nextTime) //its been 1000ms
{
//calculate speed here
pulse_count = 0; //reset the number of pulses.
nextTime = millis() + 1000; //set next time to fire
}//end if
} //end loop

edifiedsprit (author)  edifiedsprit4 years ago
also what is the difference between:

void someFunction()
{
....bla bla...

speed=(based on code logic and the calculation);
}

and

someFunction()
{
....bla bla...
speed=(based on code logic and the calculation);
return speed;
}
???
The difference between them is one you could say

variable = someFunction(); //return value of someFunction would be stored as 'variable'

the other, not having a return, means you have to store the value in a global variable, declared outside the functions.
//declared before setup
volatile int speed = 0;

void someFunction()
{
....bla bla...

speed=(based on code logic and the calculation); // sets the global variable
}

and

someFunction()
{
....bla bla...
someCalculatedNumber=(based on code logic and the calculation);
return someCalculatedNumber; //<<}
edifiedsprit (author)  frollard4 years ago
Dear Frollard,
Thank you so much your your code and the explaination. I will try to use it and see what I get. I am very novice to all this so, I guess even after your detailed efforts, I may encounter problems. ;-)
my goal is for you to learn :) If I just write the code for you, you won't learn.

I'll show you how I would do it (method) but you have to write it - I'll be happy to help if you have questions.
edifiedsprit (author)  frollard4 years ago
Sure thing!! cant thank you enough dear.
Yes even I want to learn..and I am taking this as your consent to have the liberty to ping you for help :-)
rickharris4 years ago
You have no idea how helpful it would be if you tell us which micro your using!
His other question was about the Arduino Uno...
frollard iceng4 years ago
I can smell Arduino questions from a mile away.
iceng frollard4 years ago
:)
frollard iceng4 years ago
aaaaaaaaaand author never to be seen again.
edifiedsprit (author)  frollard4 years ago
I the code you have mentioned about "blink()"
can you educate me on this? is it a function or what exactly is it?
each time you call a function it does whatever code is in the curly brackets.

You really need to check out some starter code for arduino with how to understand functions and how the programs run.

Quick recap:
program starts by declaring any global variables you'll need to store values later.
Then the arduino will run whatever code is in setup(). It will do this once (like setting pinmodes, setting variable values, etc.
Then it will run loop(), and like the name suggests, it will run loop forever. the ISR will interrupt loop and do its thing, in this case set 'state' to !state (not state).
edifiedsprit (author)  frollard4 years ago
Dear Frollard,
I am in the process of studying coding, however I have understood ISR, I believe so, however I want to know how to return a value from ISR. I read that codes(function) in ISR does not take or return any value. Is that true? cos if so then how will I be able to use the speed value that I get in my main code?
Yes, you cannot return an isr value, but you can set a global variable so long as it is declared as volatile, and set a boolean flag, so that the rest of your program knows the isr fired.

void somethingISR(){
flag = true;
sensorReading = analogRead(analogpin);
}

then the rest of your program can check
if (flag) then DoSomethingWithSensorReading.
edifiedsprit (author)  frollard4 years ago
We have a time difference of 12 hours to the least which explains my delay in checking it back..
I have a mission for 2013 to get people to stop thinking we are clairvoyant!
OK ... I don't think you are ... clairvoyant ;-D
It,s working already!
I knew you were going to say that.
edifiedsprit (author)  rickharris4 years ago
Dear Rickharris,
Thank you for showing interest and spending your precious time..yes it is an Arduino Uno. I presume it will be enough for you, however should you still need the uC, its Atmega328!