Jump to content


Photo
- - - - -

Microcontroller Mechanical Speedo Project - Can Anyone Help


  • Please log in to reply
40 replies to this topic

#16 Evil Twin

Evil Twin

    Just On Tickover

  • Noobies
  • Pip
  • 9 posts
  • Location: Swansea

Posted 05 November 2015 - 02:34 PM

I might be able to help, just posted a few minutes ago in mini chat http://www.theminifo...ni-speedometer/

 

 

have you seen this https://twitter.com/...033967962771457

 

 

it will be on stand CV39 @ the nec Classic car show

 

https://twitter.com/...714585694838784


Edited by Evil Twin, 09 November 2015 - 03:51 PM.


#17 LukeH

LukeH

    One Carb Or Two?

  • TMF+ Member
  • PipPipPipPipPipPipPip
  • 1,004 posts
  • Location: Norwich, Norfolk

Posted 10 November 2015 - 04:05 PM

I'd go with different tactics,

 

A mechanical speedo is an odometer first, so I'd look to match the rpm of the motor by comparing a digital sensor on it with your R1 setup.

 

If you're not bothered about the odometer, gut the speedo and use a stepper motor, as I-jonez suggests

 

 

I agree that driving the standard odometer makes more sense than gutting one and using a stepper and separate digital odometer however I'm now leaning more towards the latter. The DC motor route has it's own problems;

 

1. Noise of motor

2. Requires high torque certainly more than the DC motor I purchased can produce. Even the slightest bend in the drive cable stalled the motor.

3. Requires small'ish supply voltage 10 - 18v seems to be the range for required RPM rating

4. Installation is quite bulky when the DC housing, speedo cable etc.. is factored in.

 

The stepper motor route is fairly straightforward and I've now got a mostly working digital odometer using an OLED and EEPROM for storing the count whilst powered down.



#18 LukeH

LukeH

    One Carb Or Two?

  • TMF+ Member
  • PipPipPipPipPipPipPip
  • 1,004 posts
  • Location: Norwich, Norfolk

Posted 10 November 2015 - 04:07 PM

I might be able to help, just posted a few minutes ago in mini chat http://www.theminifo...ni-speedometer/

 

 

have you seen this https://twitter.com/...033967962771457

 

 

it will be on stand CV39 @ the nec Classic car show

 

https://twitter.com/...714585694838784

 

Looks good - What sort of price is this going to retail at?

 

I'm still pushing ahead with my own build. Coming up with a solution is half the fun and has proven to be a huge learning experience for somehting I wouldn't have bothered with normally.



#19 LukeH

LukeH

    One Carb Or Two?

  • TMF+ Member
  • PipPipPipPipPipPipPip
  • 1,004 posts
  • Location: Norwich, Norfolk

Posted 10 November 2015 - 04:25 PM

So here is the sketch I am working on. It's work in progress and has only been tested on the bench so far.

 

I am using a 555 based frequency generator to simulate the input pulse train. I do not know the R1 pulses per mile yet so I have set it at 4000 to make calculations and checking easy.

 

I have a gauge specific stepper motor on order and I am using the Switec library that was written specifically for that motor.

 

A few notes about the sketch;

 

1. My mph calculations might be off and I will continue to test once I have the stepper motor.

2. I am converting mph into feet per second and counting over a 1 second sample period to update the odometer function. There might be a better way to do this?

3. The odometer reading will be written to EEPROM when the car speed equals zero. A better method is using a power failure comparator to trigger write to EEPROM using a capacitor to hold the power on. - Anyone know how to do this or better still have a circuit diagram?

 

To test I have set the input frequency to simulate 60mph. Converting this value to seconds is therefore easy and allows me to check all the forumlas. For example, at 60mph the odometer should update the tenths of a mile every 6 seconds - it does!

/*
Stepper Motor Speedometer and OLED Odometer
Luke Hurst Nov 2015
http://retromini.co.uk

Credits - Thanks must go to the following from whom I have taken code and modified to my requirements.

Kevin Gale - For writing the main stepper motor speedometer sketch - https://github.com/Walterclark1/Stepper_Speedometer

Walterclark for the excellent write-up on how to use the base sketch written by Kevin Gale - http://www.hillclimb.org/forum/viewtopic.php?f=16&t=1133&sid=260e267564c31b08855a0e21ea57cbac

Guy Carpenter - Switec library author - https://github.com/clearwater/SwitecX25

PJRC for the FreqMeasure library - https://www.pjrc.com/teensy/td_libs_FreqMeasure.html

Trewjohn2001 for the Odometer code - http://www.mgexp.com/phorum/read.php?40,2761694

*/

//----Libraries to Include--------
#include <EEPROMex.h>
#include "SwitecX25.h"
#include "FreqMeasure.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//----End Libraries--------------

//----Define OLED Display Settings------
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
//-----End OLED Display Settings--------

//-----Variables-----------------------------------------------------------------------------------
const int UpdateInterval = 100;  // 100 milliseconds speedo update rate
const double StepsPerDegree = 3.0;  // Motor step is 1/3 of a degree of rotation
const unsigned int MaxMotorRotation = 315; // 315 max degrees of movement
const unsigned int MaxMotorSteps = MaxMotorRotation * StepsPerDegree;
const double PulsesPerMile = 4000.0; // Number of input pulses per mile
const double SecondsPerHour = 3600.0;
const int FeetPerMile = 5280; // Feet per mile conversion factor for Odometer update function 
const double SpeedoDegreesPerMPH = 180.0 / 100.0; // Speed on face of dial at 180 degrees is 100mph.
unsigned long PreviousMillis = 0;   // last time we updated the speedo
double MinMotorStep;  // lowest step that will be used - calculated from update interval
unsigned long distsubtotal; // Running total of feet covered for Odometer update function
unsigned long lastmillis; // Last time we updated the Odometer
unsigned long FeetTravelled; // mph converted into feet travelled for Odometer function
double sum=0;
int count=0;
double avgPulseLength=0;
unsigned int motorStep = 0;
int noInputCount = 0;
float mph=0;
//----End Variables---------------------------------------------------------------------------------

//----Define Stepper motor library variables and pin outs-------------------------------------------
SwitecX25 Motor(MaxMotorSteps, 4,5,6,7); // Create the motor object with the maximum steps allowed

//------READ Stored Odometer Values From EEPROM-----

/* - Commented out during testing to avoid reading from EEPROM resulting in strange number formatting.
int disttenthsm = EEPROM.readInt(0);
int distm = EEPROM.readInt(5);
int distenm = EEPROM.readInt(10);
int disthundredm = EEPROM.readInt(15);
int disthousandm = EEPROM.readInt(20);
int disttenthousandm = EEPROM.readInt(25);
int disthundredthousandm = EEPROM.readInt(30);
*/
int disttenthsm;
int distm;
int distenm;
int disthundredm;
int disthousandm;
int disttenthousandm;
int disthundredthousandm;
//------End EEPROM Read-----------------------------

//---------------Start-up code run once-------------------------------------------------------------------
void setup(void) 
{
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC); //Intialise OLED 

  pinMode(0, INPUT_PULLUP); //Define digital pinn 0 as pulse signal input
  
//-----Display SMITHS logo on start-up
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(28,30);
  display.println("SMITHS"); 
  display.display();
  delay(2000);
  display.clearDisplay();
  display.display();
//-----End Logo-----------------------

  Motor.zero(); //Initialize stepper at 0 location

  lastmillis = (0); //Reset Odometer update interval to zero

  MinMotorStep = PulseToStep(2 * (UpdateInterval / 1000.0) * F_CPU); //Force to zero when two intervals have passed with input

  FreqMeasure.begin(); // Start freqmeasure library

}
//------End Start-up code----------------------------------------------------------------------------------------------------------

//------Start of Loop--------------------------------------------------------------------------------------------------------------
void loop() { 
 
  unsigned long currentMillis = millis();

  // Update the motor position every UpdateInterval milliseconds
  if (currentMillis - PreviousMillis >= UpdateInterval) {
    PreviousMillis = currentMillis;   
    count = 0;
    sum = 0;

    // Read all the pulses available so we can average them
    while (FreqMeasure.available()) {
      sum += FreqMeasure.read();
      count++;
    }

    if (count) {
      // Average all the readings we got over our fixed time interval. This helps
      // stabilize the speedo at higher speeds. The pulse length gets shorter and 
      // thus harder to measure accurately but we get more pulses to average.
      // It may be necessary to update the FreqMeasure library to change the buffer
      // length to hold the full number of pulses per update interval at the highest
      // speedo values.
      avgPulseLength = sum / count;
      motorStep = PulseToStep(avgPulseLength);
      noInputCount = 0;
    } 
    else if (++noInputCount == 2)  // force speed to zero after two missed intervals
      motorStep = 0;

    // Ignore speeds below the the two missed intervals speed so the motor doesn't jump
    if (motorStep <= MinMotorStep) 
      motorStep = 0;

    Motor.setPosition(motorStep);
    
  }

  // Always update the motor. It doesn't instantly go to the desired step so even if
  // we didn't call setPosition the motor may still be moving to position from the last
  // setPosition call.
  Motor.update();
 
//-----------------Update Odometer Counter and Display every second -----------------------------------
   mph = ((motorStep / 3)/SpeedoDegreesPerMPH); // Might be a better way of calculating mph based on input frequency
   Serial.println(mph); // Used for testing to output speed in serial monitor.
   if (millis() - lastmillis >= 1000){ //Uptade every  second. 
   FeetTravelled = ((mph * FeetPerMile) / SecondsPerHour); // Convert mph into feet per second for running subtotal count.
   distsubtotal += FeetTravelled;  // add feet traveled to running subtotal
   lastmillis = millis(); // Update lasmillis
   updateodometer(); // Adds distance travelled to odometer 
   }
   displayodometer(); // Calls displayodometer function
//---------------------------END ODOMETER------------------------------------------------------------- 

//---------------Start EEPROM update if vehicle is stopped------------------

  if (mph == 0){ // Write odomoter values to EEPROM when vehicle is at a stop. Consider replacing with power failure sense circuit to avoid excessive eeprom writes.
  updateeeprom();
} 
//--------------End EEPROM Update-------------------------------------------
  
  
}
//-------End of Loop--------------------------------------------------------------------------------------------------------

// The FreqMeasure gives us the pulse length in CPU cycles.  This formula converts this into a motor step.
// Basically we are converting the length of the pulse in CPU cycles into pulses per second and then
// converting that into MPH, Once we have MPH that number is converted into degrees and that is then
// converted into a number of steps.
unsigned int PulseToStep(double pulseLength)
{
  return (unsigned int)((F_CPU * SecondsPerHour * SpeedoDegreesPerMPH * StepsPerDegree) / (PulsesPerMile * pulseLength));
}

//-------Start of Functions-------------------------------------------------------------------------------------------------
void displayodometer() {
   
   display.setTextSize(2);
   display.setTextColor(WHITE);
   display.clearDisplay();
  
//----------------Display ten thousand m  units------------------------------------
  
  display.setCursor(10,20);
  display.println(disttenthousandm);
  
     
//----------------Display  thousand m units------------------------------------
  
  display.setCursor(25,20);
  display.println(disthousandm);

  
//----------------Display hundreds m units------------------------------------
  
  display.setCursor(40,20);
  display.println(disthundredm);
  
//----------------Display tens m units----------------------------------------

  display.setCursor(55,20);
  display.println(distenm);

  
//----------------Display miles units---------------------------------------------
  
  display.setCursor(70,20);
  display.println(distm);
  
//----------------Display tenths m units---------------------------------------------
  
  display.setCursor(85,20);
  display.println(disttenthsm);

  display.display();
}

//-------------------------Update Odomter Counts--------------------------------------------------------
  
void updateodometer(){
  
 while (distsubtotal >= 528){ 
   ++disttenthsm;
   distsubtotal = 0;
 }
 
 while (disttenthsm >9){
   ++distm;
   disttenthsm = 0;
 }
 
   while (distm >9){  
   ++distenm;
   distm = 0;
 }
 
     while (distenm >9){  
   ++disthundredm;
   distenm = 0;
 }
 
  while (disthundredm >9){
   ++disthousandm;
   disthundredm = 0;
 }

 while (disthousandm >9){
   ++disttenthousandm;
    disthousandm = 0;
 }

 while (disttenthousandm >9){   
   ++disthundredthousandm;
    disttenthousandm = 0;
 }
  }

void updateeeprom(){ // Called by routine in main loop when vehicle at a stop. Update function only writes changes to eeprom if a bit has changed to avoid excessive data writes.
    
  EEPROM.updateInt(0,disttenthsm);
  EEPROM.updateInt(5,distm);
  EEPROM.updateInt(10,distenm);
  EEPROM.updateInt(15,disthundredm);
  EEPROM.updateInt(20,disthousandm);
  EEPROM.updateInt(25,disttenthousandm);
  EEPROM.updateInt(30,disthundredthousandm);
}

Edited by LukeH, 10 November 2015 - 04:30 PM.


#20 l_jonez

l_jonez

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 1,453 posts
  • Local Club: south wales mini club

Posted 10 November 2015 - 05:12 PM

I started to write my sketch on Sunday. I'm using timer counter to calculate pulses per mile. Im going to give the map function a shot for the needle position. Just need the motor to turn up now and source a LCD display

#21 Ethel

Ethel

    ..is NOT a girl!

  • TMF Team
  • PipPipPipPipPipPipPipPipPipPipPip
  • 25,922 posts
  • Local Club: none

Posted 10 November 2015 - 06:07 PM

There are quite a few projects to drive salvaged car instrument pods for console games, you might some useful code there. Also Mpguino & Obduino.



#22 LukeH

LukeH

    One Carb Or Two?

  • TMF+ Member
  • PipPipPipPipPipPipPip
  • 1,004 posts
  • Location: Norwich, Norfolk

Posted 10 November 2015 - 06:08 PM

Check out this guys code. He's using a count with map function and LCD;

http://matthewcmcmil...ometer.html?m=1

I prefer the look of an OLED and they are relatively cheap ~ £10. 4 wires to control and easy with the adafruit libraries

#23 LukeH

LukeH

    One Carb Or Two?

  • TMF+ Member
  • PipPipPipPipPipPipPip
  • 1,004 posts
  • Location: Norwich, Norfolk

Posted 10 November 2015 - 06:13 PM

Sorry correction. The above link is not using map function but he is using an LCD and count.

#24 l_jonez

l_jonez

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 1,453 posts
  • Local Club: south wales mini club

Posted 10 November 2015 - 06:28 PM

Check out this guys code. He's using a count with map function and LCD;
http://matthewcmcmil...ometer.html?m=1
I prefer the look of an OLED and they are relatively cheap ~ £10. 4 wires to control and easy with the adafruit libraries


Yep I've seen his, mine is fairly similar. When I'm home next I'll get on with it and post it up.

#25 Evil Twin

Evil Twin

    Just On Tickover

  • Noobies
  • Pip
  • 9 posts
  • Location: Swansea

Posted 11 November 2015 - 01:02 PM

Sound like you guys are making progress, for you pulses per mile, for you to check I can possible help you where is you speed sensor picking up from.

#26 LukeH

LukeH

    One Carb Or Two?

  • TMF+ Member
  • PipPipPipPipPipPipPip
  • 1,004 posts
  • Location: Norwich, Norfolk

Posted 11 November 2015 - 01:31 PM

Sound like you guys are making progress, for you pulses per mile, for you to check I can possible help you where is you speed sensor picking up from.

 

On my R1 engine the sensor is mounted on the engine taking a reading from a trigger wheel in the gearbox. The problem is I have no idea how many teeth it has without taking things apart. I have been unable to find a definitive answer online. Some say 28 teeth others say 34.

 

I've calculated my gear ratio so I could figure out pulses per mile if I knew how many pulses per crank revolution.



#27 Evil Twin

Evil Twin

    Just On Tickover

  • Noobies
  • Pip
  • 9 posts
  • Location: Swansea

Posted 11 November 2015 - 02:05 PM

Does the sensor have a LED on it? If so we can work it out for 1 wheel revolution, every time the sensor create a magnetic field the led would light up, so for 1 wheel revolutions this would equal so many flashes of the led.

Otherwise we need the number of teeth, as it's could be 18% out.

#28 LukeH

LukeH

    One Carb Or Two?

  • TMF+ Member
  • PipPipPipPipPipPipPip
  • 1,004 posts
  • Location: Norwich, Norfolk

Posted 11 November 2015 - 03:47 PM

I don't believe it does have an LED but the service manual states it will go from 0.6v to 4.8v so it can easily be measured with a multimeter. I don't have a wiring harness connected to the engine yet and it will be a while before I do so I'll have to wait until I'm at that stage.



#29 Evil Twin

Evil Twin

    Just On Tickover

  • Noobies
  • Pip
  • 9 posts
  • Location: Swansea

Posted 11 November 2015 - 03:58 PM

I will keep an eye on your progress.

#30 l_jonez

l_jonez

    One Carb Or Two?

  • Members
  • PipPipPipPipPipPipPip
  • 1,453 posts
  • Local Club: south wales mini club

Posted 18 November 2015 - 07:29 PM

Well this happened today https://youtu.be/_0UZydztHSI

 






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users