Go Down

Topic: What is the best type of sensor for motorcycle ODOMETER..?? (Read 5396 times) previous topic - next topic

Joy

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

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...??


dc42


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.
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.

dc42


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.
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.

Joy

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..??

dc42

#34
Sep 26, 2011, 06:09 pm Last Edit: Sep 26, 2011, 06:11 pm by dc42 Reason: 1

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.
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.

Joy

#35
Sep 28, 2011, 06:09 pm Last Edit: Sep 28, 2011, 06:31 pm by Joy Reason: 1
I wrote this code, but it is not working..

Code: [Select]
#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(" ");
}


dc42

#36
Sep 28, 2011, 07:14 pm Last Edit: Sep 28, 2011, 07:16 pm by dc42 Reason: 1
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: [Select]

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: [Select]

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: [Select]

    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.

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.

Joy

Huh... :(

I am jumbling up things :(

Code: [Select]
#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; 
}

dc42


Huh... :(

I am jumbling up things :(


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: [Select]

    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, ...);
     
   }
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.

Joy

Code: [Select]
#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...??

dc42

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

Code: [Select]

#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: [Select]

  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: [Select]

  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
  } 
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.

Go Up