Hello everyone, I am currently debugging this speedometer setup on a friends vehicle. I did an engine swap on the rig and consequently the new transmission has an electronic output, the original was mechanical. My friend wanted to retain the factory gauge setup, so this project was born.
My basic plan was to take the Toyota VSS signal, convert that in an arduino nano, and output a signal that drives a small brushless motor mounted behind the gauge cluster. After much research and testing, I camp up with this code below. The brushless motor I am using is a Nidec 24H404H, it's a small bldc with built in drive circuitry and encoders. The motor requires a 15-25Khz PWM signal for speed control.
I used the PWM.h library for creating an 18Khz PWM signal for the motor, and the hardware counter Pin 5 for capturing the VSS signal. The setup seems to work quite well and is very accurate, with just a couple small issues.
The first problem is that the speedometer will quit working after about 15 minutes of highway driving at 65MPH. I believe this to be an issue with the "TCNT1" variable reaching its maximum value.
The Second Issue is that the speedometer only updates once a second, is there a better way to capture the VSS signal than the way I am doing it?
Thanks in advance
Code:
#include <SPI.h>
#include <Wire.h>
#include <PWM.h>
int led = 3; //Pin for PWM output
unsigned int range = 255;
int32_t frequency = 18000; //frequency (in Hz)
const int hardwareCounterPin = 5;
unsigned long count;
unsigned long pcount;
unsigned long ncount;
byte pwmval;
byte ulim = 125; //Adjust this variable to fine tune speedometer range
void setup(void) {
Serial.begin(9600);
Serial.println("Start");
InitTimersSafe();
SetPinFrequencySafe(led, frequency);
pwmval = 255;
}
void loop() {
bitSet(TCCR1B, CS12); // start counting pulses
bitSet(TCCR1B, CS11); // Clock on rising edge
count = TCNT1; //Store TCNT1 in variable
delay(1000); //Delay to count pulses
ncount = count - pcount; //Subtract previous count from current to get new count
Serial.println(ncount); //For testing
Serial.print("TCNT");
Serial.println(TCNT1);
if (ncount < 2){ //If new count or "MPH" is less than 2, set to 0
ncount = 0;
}
pwmval = constrain(map(ncount, 85, 0, ulim, 255), ulim, 255); //Convert ncount to proper range for PWM which happens to be 255-125. The range on the speedometer is 0-85, 255 being zero, and 125 being 88.
Serial.println(pwmval);
if (ncount != pcount){ //Only update PWM if the ncount variable changes
pwmWrite(led, pwmval);
}
pcount = count; //Set pcount for next loop
if(TCNT1 > 30000){ //If hardware counter exceeds 30000, then reset to 0
TCNT1 = 0;
bitSet(TCCR1B, CS12);
bitSet(TCCR1B, CS11);
}
}