Hello
So. That worked. Kind of. I worked out that speed is 50000 / revDuration * 4.
However, to maintain a more accurate speed, I made the Arduino actually calculate (500000000 / revDuraction * 4) / 1000
The code still hangs now and then, and sometimes misses interrupts. I'm quite sure that I am doing something fundamentally simple wrong.
The setup is simple, a circular magnet from a speedometer with a hall effect sensor close to it.
An LED on the sensor pulses with each polarity change of the magnet, so I know it is receiving pulses and sending this to the arduino.
The magnet is connected to a drill with a flexible shaft.
Spinning the drill spins the magnet. If I take the revDuration from the serial monitor, that corresponds with the speed I calculate.
So, this is the code:
unsigned long revMicros;
unsigned long prevRevMicros;
unsigned long revDuration;
unsigned long revCount;
unsigned long SpeedMPH;
unsigned long prevDisplayMillis;
int displayInterval = 1000;
// variables for the ISR
volatile unsigned long isrMicros;
volatile unsigned long isrCount;
volatile bool newIsrMicros = false;
void setup() {
Serial.begin(115200);
Serial.println("SimpleISRdemo.ino");
isrCount = 0;
attachInterrupt(0, revDetectorISR, RISING);
}
//==========
void loop() {
getIsrData();
if (millis() - prevDisplayMillis >= displayInterval) {
prevDisplayMillis += displayInterval;
showData();
}
}
//===========
void getIsrData() {
if (newIsrMicros == true) {
prevRevMicros = revMicros; // save the previous value
noInterrupts();
revMicros = isrMicros;
revCount = isrCount;
newIsrMicros = false;
interrupts();
revDuration = revMicros - prevRevMicros;
SpeedMPH = (500000000 / revDuration * 4) / 1000;
}
}
//===========
void showData() {
Serial.println();
Serial.println("===============");
Serial.print(" Rev Count ");
Serial.print(revCount);
Serial.println();
Serial.print(" Speed ");
Serial.print(SpeedMPH);
Serial.println();
Serial.print(" revDuration ");
Serial.print(revDuration);
}
//===========
void revDetectorISR() {
isrMicros = micros();
isrCount ++;
newIsrMicros = true;
}
I then took the code, and added in the driver for the nixie tubes. This kind of works, but hangs really badly...
unsigned long revMicros;
unsigned long prevRevMicros;
unsigned long revDuration;
unsigned long revCount;
unsigned long SpeedMPH;
unsigned long prevDisplayMillis;
int displayInterval = 1000;
int NixieA;
int NixieB;
// variables for the ISR
volatile unsigned long isrMicros;
volatile unsigned long isrCount;
volatile unsigned long timeoutMicros;
volatile bool newIsrMicros = false;
#define DIN_PIN 7 // Nixie driver (shift register) serial data input pin
#define CLK_PIN 6 // Nixie driver clock input pin
#define EN_PIN 5 // Nixie driver enable input pin
void setup() {
Serial.begin(115200);
Serial.println("SimpleISRdemo.ino");
pinMode(DIN_PIN, OUTPUT);
digitalWrite(DIN_PIN, LOW);
pinMode(CLK_PIN, OUTPUT);
digitalWrite(CLK_PIN, LOW);
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW);
isrCount = 0;
attachInterrupt(0, revDetectorISR, RISING);
}
//==========
void loop() {
getIsrData();
if (millis() - prevDisplayMillis >= displayInterval) {
prevDisplayMillis += displayInterval;
showData();
}
}
//===========
void getIsrData() {
if (newIsrMicros == true) {
prevRevMicros = revMicros; // save the previous value
noInterrupts();
revMicros = isrMicros;
revCount = isrCount;
newIsrMicros = false;
interrupts();
revDuration = revMicros - prevRevMicros;
SpeedMPH = (500000000 / revDuration * 4) / 1000;
}
}
void NixieDisplay(byte digit1, byte digit2)
{
StartShiftOutData();
if (digit2 != 10) ShiftOutData(digit2);
if (digit1 != 10) ShiftOutData(digit1);
EndShiftOutData();
}
void StartShiftOutData()
{
// Ground EN pin and hold low for as long as you are transmitting
digitalWrite(EN_PIN, 0);
// Clear everything out just in case to
// prepare shift register for bit shifting
digitalWrite(DIN_PIN, 0);
digitalWrite(CLK_PIN, 0);
}
void ShiftOutData(byte digit)
{
// Send data to the nixie drivers
for (int i = 15; i >= 0; i--)
{
// Set high only the bit that corresponds to the current nixie digit
if(i == digit) digitalWrite(DIN_PIN, 1);
else digitalWrite(DIN_PIN, 0);
// Register shifts bits on upstroke of CLK pin
digitalWrite(CLK_PIN, 1);
// Set low the data pin after shift to prevent bleed through
digitalWrite(CLK_PIN, 0);
}
}
void EndShiftOutData()
{
// Return the EN pin high to signal chip that it
// no longer needs to listen for data
digitalWrite(EN_PIN, 1);
// Stop shifting
digitalWrite(CLK_PIN, 0);
}
//===========
void showData() {
Serial.println();
Serial.println("===============");
Serial.print(" Rev Count ");
Serial.print(revCount);
Serial.println();
Serial.print(" Speed ");
Serial.print(SpeedMPH);
Serial.println();
Serial.print(" revDuration ");
Serial.print(revDuration);
Serial.println();
Serial.print(" Nixie Display ");
Serial.print(NixieA);
Serial.print(NixieB);
NixieB = (SpeedMPH % 10); // Assign second digit of the speed to NixieB
NixieA = (SpeedMPH / 10) % 10; // Assign first digit of the speed to NixieA
NixieDisplay(NixieB, NixieA); // Write these values to the tubes with the NixieDisplay function
}
//===========
void revDetectorISR() {
isrMicros = micros();
isrCount ++;
newIsrMicros = true;
}
I'm close, but I just can't figure out why the code hangs so terribly.
Can anyone help?
Edit I have a plan B now, using a frequency to analogue converter and simply read the input voltage, apply a value in MPH to a given voltabe, and output that. I've ordered three LM2907 chips to try out.
Thanks