Pages: 1 2 [3]   Go Down
Author Topic: What is the best type of sensor for motorcycle ODOMETER..??  (Read 4877 times)
0 Members and 1 Guest are viewing this topic.
INDIA
Offline Offline
Sr. Member
****
Karma: 0
Posts: 382
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

After connecting the A0 to 5v+ and some changes made the code working correctly.. smiley

Now another challenge is to add trip meter extracted from the odometer..
I will connect a push button on A1 of arduino and the GND
which will shift the trip meter from TRIP A, TRIP B, TRIP C.
And a long press on any A, B or C will reset the trip meter to 0Km..

Will I have to store every trip on separate position on the EEPROM...??

Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Will I have to store every trip on separate position on the EEPROM...??

Yes, if you want the trip meters to be preserved when you power off and on again. You could maybe use less than 4 bytes per trip meter, but you've got loads of EEPROM space left, so I wouldn't bother trying to reduce the amount of data stored, unless keeping the mcu powered while you write all the data becomes a problem.
Logged

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.

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I didnt get this part  " unless keeping the mcu powered while you write all the data becomes a problem. "

Did you mean that the more data I want to write the more longer I t wil take to write and hence I will have to use much bigger Capacitor to keep the MCU powered that long...??

Yes. Each byte you write to EEPROM takes 3.3ms according to the EEPROM library documentation, so you have to make sure that the capacitor is big enough to power the mcu for the length of time it takes to recognise the power loss plus the length of time it takes to write all the bytes.
Logged

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.

INDIA
Offline Offline
Sr. Member
****
Karma: 0
Posts: 382
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is the best way to calculate for the TRIP meters..??

Freshly use odometer interrupts and calculate for the TRIP Meter..??

OR

just display the difference between the odometer reading when the TRIP Meter was reset and and odometer reading present..??
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What is the best way to calculate for the TRIP meters..??

Freshly use odometer interrupts and calculate for the TRIP Meter..??

OR

just display the difference between the odometer reading when the TRIP Meter was reset and and odometer reading present..??

Either, but the second is probably simpler. Store the value of wheelRevs at which each trip meter was last reset, then subtract it from savedWheelRevs and convert the result to km as usual for display. This also means you don't need to write the trip counters to EEPROM when the power goes down - instead, whenever you reset a trip counter, write its wheelRevs to EEPROM immediately.
« Last Edit: September 26, 2011, 11:11:35 am by dc42 » Logged

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.

INDIA
Offline Offline
Sr. Member
****
Karma: 0
Posts: 382
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I wrote this code, but it is not working..

Code:
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 9, 8);
const int rstPin = 7;
int rstState = 0;
int Trip;
const int odometerPin = 3;
const int odometerInterrupt = 1;
const int odometerEepromLocation = 0;  // address of the first of 4 bytes in which the total wheel revs is stored
const int powerPin = A0;               // analog pin used to sense impending loss of power

const float wheelCircumference =  0.5;            //0.002035;  // wheel circumference in km
const int minPowerOkReading = 700;          // minimum reading on the power sense analog input that indicates good power
const int minPowerRestoredReading = 750;    // minimum reading on the power sense analog input that indicates we have powered back up

volatile unsigned long wheelRevs;       // total wheel revolutions counted, will overflow after 85 million km
unsigned long lastDisplayedMs = 0UL;    // time when we last refreshed the display

void setup()
{
  lcd.begin(16,2);
  // Initialise wheel revs from value stored in EEPROM
  wheelRevs = 0UL;
  for (int i = odometerEepromLocation + 3; i >= odometerEepromLocation; --i)
  {
    wheelRevs <<= 8;
    wheelRevs |= (unsigned long)EEPROM.read(i);
  }
 
  if (wheelRevs == 0xFFFFFFFFUL)
  {
    // must be the first time we have run
    wheelRevs = 0UL;
  }
 
  // Set up the odometer sensor pin and interrupt
  pinMode(odometerPin, INPUT);
  attachInterrupt(odometerInterrupt, odometerIsr, FALLING); 
 
 
 
}

void odometerIsr()
{
  ++wheelRevs;
}

void loop()
{
  // Capture the wheel revs with interrupts disabled in case it changes while we read it
  noInterrupts();
  unsigned long savedWheelRevs = wheelRevs;
  interrupts();
 
  if (analogRead(powerPin) < minPowerOkReading)
  {
    // Looks like power is going down, so write wheel revs to EEPROM (takes 13.2ms to write 4 bytes)
    for (int i = odometerEepromLocation; i < odometerEepromLocation + 4; ++i)
    {
      EEPROM.write(i, (unsigned char)savedWheelRevs);
      savedWheelRevs >>= 8;
    }
   
    // wait until either we die or the power comes back up
    while (analogRead(powerPin) < minPowerRestoredReading)
    {
      delay(200);
    }   
  }
  else
  { 
    unsigned long now = millis();
    if (now - lastDisplayedMs >= 200)    // update display every 200ms
    {
      lastDisplayedMs = now;
      float km = wheelCircumference * savedWheelRevs;
      lcd.setCursor(0, 0);
      lcd.print(km, 1);
      lcd.print("Km");
     
    }
    delay(5);    // repeat after 5ms so that we check for power down often enough
  }
 
  rstState = digitalRead(rstPin);
 
  if (rstState == HIGH){
    EEPROM.write(9, wheelRevs);
  }
 
  Trip = (savedWheelRevs - EEPROM.read (9)) * wheelCircumference; 
  lcd.setCursor(0, 1);
  lcd.print (Trip, 1);
  lcd.print(" ");
}

« Last Edit: September 28, 2011, 11:31:49 am by Joy » Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You need to save the wheel revs when the trip counter was started in 4 bytes of EEPROM, not one. First, let's write functions to read and write 4 bytes of EEPROM since you will be doing it in more than one place. Add this just before setup():

Code:
unsigned long readEepromLong(unsigned int address)
{
  unsigned long ret = 0UL;
  for (int i = address + 3; i >= address; --i)
  {
    ret <<= 8;
    ret |= (unsigned long)EEPROM.read(i);
  }
  return(ret);
}

void writeEepromLong(unsigned int address, unsigned long val)
{
    for (int i = odometerEepromLocation; i < odometerEepromLocation + 4; ++i)
    {
      EEPROM.write(i, (unsigned char)val);
      val >>= 8;
    }
}

Next, change my original setup() and loop() to make use of these:

Code:
void setup()
{
  // Initialise wheel revs from value stored in EEPROM
  wheelRevs = readEepromLong(odometerEepromLocation);
  if (wheelRevs == 0xFFFFFFFFUL)
  {
    // must be the first time we have run
    wheelRevs = 0UL;
  }
 
  // Set up the odometer sensor pin and interrupt
  pinMode(odometerPin, INPUT);
  attachInterrupt(odometerInterrupt, odometerIsr, RISING); 
}

void odometerIsr()
{
  ++wheelRevs;
}

void loop()
{
  // Capture the wheel revs with interrupts disabled in case it changes while we read it
  noInterrupts();
  unsigned long savedWheelRevs = wheelRevs;
  interrupts();
 
  if (analogRead(powerPin) < minPowerOkReading)
  {
    // Looks like power is going down, so write wheel revs to EEPROM (takes 13.2ms to write 4 bytes)
    writeEepromLong(odometerEepromLocation, savedWheelRevs);
   
    // Wait until either we die or the power comes back up
    while (analogRead(powerPin) < minPowerRestoredReading)
    {
      delay(200);
    }   
  }
  ...

Now change your trip meter code to use those functions:

Code:
    if (rstState == HIGH){
      writeEepromLong(TripMeterEepromLocation, wheelRevs);
    }
   
    Trip = (savedWheelRevs - readEepromLong(TripMeterEepromLocation)) * wheelCircumference; 

Also, I'd keep the trip meter wheel revs in a local variable to save reading it from the eeprom every time.

« Last Edit: September 28, 2011, 12:16:19 pm by dc42 » Logged

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.

INDIA
Offline Offline
Sr. Member
****
Karma: 0
Posts: 382
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Huh... smiley-sad

I am jumbling up things smiley-sad

Code:
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 9, 8);
int rstState = 0;
int Trip;
const int odometerPin = 3;
const int odometerInterrupt = 1;
const int odometerEepromLocation = 0;  // address of the first of 4 bytes in which the total wheel revs is stored
const int powerPin = A0;               // analog pin used to sense impending loss of power

const float wheelCircumference = 0.002035;  // wheel circumference in km
const int minPowerOkReading = 700;          // minimum reading on the power sense analog input that indicates good power
const int minPowerRestoredReading = 750;    // minimum reading on the power sense analog input that indicates we have powered back up

volatile unsigned long wheelRevs;       // total wheel revolutions counted, will overflow after 85 million km
unsigned long lastDisplayedMs = 0UL;    // time when we last refreshed the display


unsigned long readEepromLong(unsigned int address)
{
  unsigned long ret = 0UL;
  for (int i = address + 3; i >= address; --i)
  {
    ret <<= 8;
    ret |= (unsigned long)EEPROM.read(i);
  }
  return(ret);
}

void writeEepromLong(unsigned int address, unsigned long val)
{
    for (int i = odometerEepromLocation; i < odometerEepromLocation + 4; ++i)
    {
      EEPROM.write(i, (unsigned char)val);
      val >>= 8;
    }
}


void setup()
{
  lcd.begin(16,2);
    // Initialise wheel revs from value stored in EEPROM
  wheelRevs = readEepromLong(odometerEepromLocation);
  if (wheelRevs == 0xFFFFFFFFUL)
  {
    // must be the first time we have run
    wheelRevs = 0UL;
  }
 
  // Set up the odometer sensor pin and interrupt
  pinMode(odometerPin, INPUT);
  attachInterrupt(odometerInterrupt, odometerIsr, RISING); 
}

void odometerIsr()
{
  ++wheelRevs;
}

void loop()
{
  // Capture the wheel revs with interrupts disabled in case it changes while we read it
  noInterrupts();
  unsigned long savedWheelRevs = wheelRevs;
  interrupts();
 
  if (analogRead(powerPin) < minPowerOkReading)
  {
    // Looks like power is going down, so write wheel revs to EEPROM (takes 13.2ms to write 4 bytes)
    writeEepromLong(odometerEepromLocation, savedWheelRevs);
   
    // Wait until either we die or the power comes back up
    while (analogRead(powerPin) < minPowerRestoredReading)
    {
      delay(200);
    }   
  }
  else
  { 
    unsigned long now = millis();
    if (now - lastDisplayedMs >= 200)    // update display every 200ms
    {
      lastDisplayedMs = now;
      float km = wheelCircumference * savedWheelRevs;
      lcd.setCursor(0, 0);
      lcd.print(km, 1);
      lcd.print("Km");
     
    }
    delay(5);    // repeat after 5ms so that we check for power down often enough
  }
 
      if (rstState == HIGH){
      writeEepromLong(TripMeterEepromLocation, wheelRevs);
    }
   
    Trip = (savedWheelRevs - readEepromLong(TripMeterEepromLocation)) * wheelCircumference; 
}
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Huh... smiley-sad

I am jumbling up things smiley-sad

Meaning... ?

Your code to display the trip meter seems to have disappeared. It and the calculation of Trip should be inside the 'if' alongside the display of total km:

Code:
    if (now - lastDisplayedMs >= 200)    // update display every 200ms
    {
      lastDisplayedMs = now;
      float km = wheelCircumference * savedWheelRevs;
      lcd.setCursor(0, 0);
      lcd.print(km, 1);
      lcd.print("Km");

      Trip = (savedWheelRevs - readEepromLong(TripMeterEepromLocation)) * wheelCircumference;
      lcd.setCursor(...);
      lcd.print(trip, ...);
      
    }
Logged

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.

INDIA
Offline Offline
Sr. Member
****
Karma: 0
Posts: 382
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 9, 8);
int rstState = 0;
int Trip;
int TripMeterEepromLocation;
const int rstPin = 7;
const int odometerPin = 3;
const int odometerInterrupt = 1;
const int odometerEepromLocation = 0;  // address of the first of 4 bytes in which the total wheel revs is stored
const int powerPin = A0;               // analog pin used to sense impending loss of power

const float wheelCircumference = 0.002035;  // wheel circumference in km
const int minPowerOkReading = 700;          // minimum reading on the power sense analog input that indicates good power
const int minPowerRestoredReading = 750;    // minimum reading on the power sense analog input that indicates we have powered back up

volatile unsigned long wheelRevs;       // total wheel revolutions counted, will overflow after 85 million km
unsigned long lastDisplayedMs = 0UL;    // time when we last refreshed the display


unsigned long readEepromLong(unsigned int address)
{
  unsigned long ret = 0UL;
  for (int i = address + 3; i >= address; --i)
  {
    ret <<= 8;
    ret |= (unsigned long)EEPROM.read(i);
  }
  return(ret);
}

void writeEepromLong(unsigned int address, unsigned long val)
{
    for (int i = odometerEepromLocation; i < odometerEepromLocation + 4; ++i)
    {
      EEPROM.write(i, (unsigned char)val);
      val >>= 8;
    }
}


void setup()
{
  lcd.begin(16,2);
    // Initialise wheel revs from value stored in EEPROM
  wheelRevs = readEepromLong(odometerEepromLocation);
  if (wheelRevs == 0xFFFFFFFFUL)
  {
    // must be the first time we have run
    wheelRevs = 0UL;
  }
 
  // Set up the odometer sensor pin and interrupt
  pinMode(odometerPin, INPUT);
  attachInterrupt(odometerInterrupt, odometerIsr, RISING); 
}

void odometerIsr()
{
  ++wheelRevs;
}

void loop()
{
  // Capture the wheel revs with interrupts disabled in case it changes while we read it
  noInterrupts();
  unsigned long savedWheelRevs = wheelRevs;
  interrupts();
 
  if (analogRead(powerPin) < minPowerOkReading)
  {
    // Looks like power is going down, so write wheel revs to EEPROM (takes 13.2ms to write 4 bytes)
    writeEepromLong(odometerEepromLocation, savedWheelRevs);
   
    // Wait until either we die or the power comes back up
    while (analogRead(powerPin) < minPowerRestoredReading)
    {
      delay(200);
    }   
  }
  else
  { 
    unsigned long now = millis();
    if (now - lastDisplayedMs >= 200)    // update display every 200ms
    {
      lastDisplayedMs = now;
      float km = wheelCircumference * savedWheelRevs;
      lcd.setCursor(0, 0);
      lcd.print(km, 1);
      lcd.print("Km");
     
       Trip = (savedWheelRevs - readEepromLong(TripMeterEepromLocation)) * wheelCircumference;
      lcd.setCursor(0, 1);
      lcd.print(Trip, 1);
     
   
     
    }
    delay(5);    // repeat after 5ms so that we check for power down often enough
  }
 
      if (rstState == HIGH){
      writeEepromLong(TripMeterEepromLocation, wheelRevs);
    }
   
   
}


Is everything ok now...??
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I would change the start of your program to this (main change is that TripMeterEepromLocation is constant and initialised):

Code:
#include <EEPROM.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 9, 8);
const int rstPin = 7;
const int powerPin = A0;               // analog pin used to sense impending loss of power
const int odometerPin = 3;
const int odometerInterrupt = 1;

const int odometerEepromLocation = 0;   // address of the first of 4 bytes in which the total wheel revs is stored
const int TripMeterEepromLocation = 4;   // address of the first of 4 bytes where the trip meter wheel revs is stored

const float wheelCircumference = 0.002035;  // wheel circumference in km

I would add the following to setup(), assuming that your reset button is connected between pin 'rstPin' asnd ground with no external pullup or pulldown resistors:

Code:
  pinMode(rstPin, INPUT);
  digitalWrite(rstPin, HIGH);   // enable internal pullup resistor 

I would change the end of loop() to the following. Note that Trip is declared as float, and when the reset button is pressed we only write the wheel revs if it has changed.

Code:
  else
  { 
    if (digitalRead(rstPin) == LOW && readEepromLong(TripMeterEepromLocation) != savedWheelRevs)
    {
      writeEepromLong(TripMeterEepromLocation, savedWheelRevs);
    }
   
    unsigned long now = millis();
    if (now - lastDisplayedMs >= 200)    // update display every 200ms
    {
      lastDisplayedMs = now;
      float km = wheelCircumference * savedWheelRevs;
      lcd.setCursor(0, 0);
      lcd.print(km, 1);
      lcd.print("Km");
         
      float Trip = (savedWheelRevs - readEepromLong(TripMeterEepromLocation)) * wheelCircumference;
      lcd.setCursor(0, 1);
      lcd.print(Trip, 1);
    }
    delay(5);    // repeat after 5ms so that we check for power down often enough
  } 
Logged

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.

Pages: 1 2 [3]   Go Up
Jump to: