Hello all,
I have been trying to create a diy RPM gauge for a 2 stroke motorcycle. I am not a very good at electricity so I just followed a guide. Bellow are the circuit I used:
My problem is once I start the motor the gauge "works" for a few seconds, then it goes to 0 and stops moving. Occasionally it moves to a few thousand RPM and stops once again. Also the arduino sometimes just freezes. Can anyone please help me?
I have written a few tests, so that I could verify the workings of the gauge and it does work correctly. I have also attached a LED that toggles on a interrupt which works, but freezes for a second sometimes.
Any help would be much appreciated!
The code:
// PIN SETUP
const uint8_t TACHO_OUTPUT_PIN = 9;
const uint8_t SENSOR_INPUT_PIN = 2; // available pins: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
const uint8_t TEST_LED = 10;
// SIGNAL INPUT SETTINGS
const int NUM_OF_CYLINDERS = 1;
const int STROKE = 2;
const int SIGNALS_PER_RPM = (NUM_OF_CYLINDERS * STROKE) / 2;
// TACHOMETER SETTINGS
const int NUM_OF_TACHO_CYLINDERS = 8;
const int MAX_RPM = 8000;
const float GAUGE_OFFSET = 0.03; // in percent, the offset of the needle
const int TACH_UPDATE_INTERVAL = 1000;
// GLOBAL VARIABLES
volatile int sparkFireCount = 0;
int lastRpmValue = 0;
unsigned long lastUpdateTime = 0;
//int rpmTone;
void setup() {
//Serial.begin(9600);
pinMode(TACHO_OUTPUT_PIN, OUTPUT);
pinMode(TEST_LED, OUTPUT);
//pinMode(SENSOR_INPUT_PIN, INPUT_PULLUP)
attachInterrupt(digitalPinToInterrupt(SENSOR_INPUT_PIN), onSensorInterupted, FALLING);
test2();
//digitalWrite(TEST_LED, HIGH);
}
void loop() {
//test2();
//test1();
unsigned long elapsedTime = millis() - lastUpdateTime;
if (elapsedTime <= TACH_UPDATE_INTERVAL)
return;
//int rpm = sparkFireCount * SIGNALS_PER_RPM;
// rpm = number of fires * type of engine * elapsed time since last update * to minutes
int rpm = sparkFireCount * ((1000 / TACH_UPDATE_INTERVAL) * 60) * SIGNALS_PER_RPM;
// we smooth out the rpm value, so it looks more stable
// rpm = (rpm + lastRpmValue) / 2;
noInterrupts();
sparkFireCount = 0;
//interrupts();
lastUpdateTime = millis();
lastRpmValue = rpm;
setTachometer(rpm);
interrupts();
}
void setTachometer(int rpm) {
rpm = constrain(rpm, 0, MAX_RPM);
//Serial.println(rpm);
int rpmTone = (double)rpm / 60.0 * NUM_OF_TACHO_CYLINDERS / 2.0;
rpmTone = rpmTone - rpmTone * GAUGE_OFFSET;
// we set the RPM output
// because the signal is downward limited to 30hz, we will disable it if its half of that
if (rpmTone < 16)
noTone(TACHO_OUTPUT_PIN);
else {
rpmTone = constrain(rpmTone, 30, 100000);
tone(TACHO_OUTPUT_PIN, rpmTone);
}
}
void onSensorInterupted() {
digitalWrite(TEST_LED, !digitalRead(TEST_LED));
++sparkFireCount;
}
void test1() {
setTachometer(0);
delay(2000);
setTachometer(1000);
delay(1000);
setTachometer(2000);
delay(1000);
setTachometer(3000);
delay(1000);
setTachometer(4000);
delay(1000);
setTachometer(5000);
delay(1000);
setTachometer(6000);
delay(1000);
setTachometer(7000);
delay(1000);
setTachometer(8000);
delay(3000);
}
void test2() {
delay(1000);
for(int i = 0; i<MAX_RPM; ++i) {
setTachometer(i);
//delay(1);
}
setTachometer(0);
//delay(5000);
}


