Having an issue here with code i've been working on. I'm basically writing a bike computer, and i'm starting out with a sensor and some basic math. However, the output from the Arduino is what's confusing me.
As you can see, there's fairly simple math happening here, nothing too complex.
The issue i'm having is that the loop will properly dump the text out to the serial port, and my computer will display it.. However, after actuating the sensor a few times, all output stops, the loop stops running as far as i can tell. I've inserted a digitalwrite statement as well to blink an LED when the loop runs, and it suddenly stops blinking after a few actuations of the sensor. It's like the entire processor locks up.
I've looked around on the forums and haven't seen anything like this before, wondering if anyone might have some insight into something I'm doing totally wrong..
//Tire circumference in millimeters
const int circ = 2095;
byte SensorPin = 2;
volatile unsigned long time;
unsigned int milsecs;
unsigned long time2;
volatile int count;
unsigned long total;
float mph = 0.0;
int outspeed;
void setup()
{
pinMode (SensorPin,INPUT);
digitalWrite (SensorPin, HIGH);
Serial.begin(19200);
attachInterrupt(0,sense,LOW);
}
void loop()
{
delay (1000);
milsecs = time - time2;
time2 = time;
total = count * circ;
mph = (circ / milsecs) * 2.2369;
mph = mph * 100;
outspeed = int(mph);
Serial.print("Time: ");
Serial.print(milsecs);
Serial.print(" Count: ");
Serial.println(count);
Serial.print("Total mm: ");
Serial.print(total);
Serial.print(" MPH: ");
Serial.println(outspeed);
Serial.println(time);
}
void sense()
{
if ((millis() - time) > 20)
{
time = millis();
count = count + 1;
}
}
Alright, that seems to keep it from locking up. However, now it's only counting pulses one-per-second, it can't handle anything faster..
My dilemma here is that when an interrupt occurs, it seems to halt the code and perform the interrupt routine, then resume the other code, no matter where it is.. the issue i'm having is that i need it to always be able to increment a counter and record the timing, but at the same time, only output the calculated result once per second.
If the program is in a delay anywhere, and it gets interrupted, it returns to the same spot it stopped in, preventing the milliseconds from being recorded accurately if it resumes in the middle of a delay.
Reading millis() in a interrupt seems to lock up the micro, unless i was doing something else wrong...
Remove delay, and use the state variable to trigger not only the action of updating millis(), but also to print out data. This way, everything updates when an interrupt occurs, making it more event driven. No delay to hang things up.
Here's a modified version (untested, but compiles)
//Tire circumference in millimeters
const int circ = 2095;
byte SensorPin = 2;
volatile unsigned long time;
unsigned int milsecs;
unsigned long time2;
volatile int count;
unsigned long total;
float mph = 0.0;
int outspeed;
boolean state = false;
void setup()
{
pinMode (SensorPin,INPUT);
digitalWrite (SensorPin, HIGH);
Serial.begin(19200);
attachInterrupt(0,sense,LOW);
}
void loop()
{
if(state)
{
senseAct();
milsecs = time - time2;
time2 = time;
total = count * circ;
mph = (circ / milsecs) * 2.2369;
mph = mph * 100;
outspeed = int(mph);
Serial.print("Time: ");
Serial.print(milsecs);
Serial.print(" Count: ");
Serial.println(count);
Serial.print("Total mm: ");
Serial.print(total);
Serial.print(" MPH: ");
Serial.println(outspeed);
Serial.println(time);
state = false;
}
}
void sense()
{
state = true;
}
void senseAct()
{
if ((millis() - time) > 20)
{
time = millis();
count = count + 1;
}
}
Heh, actually it seems I came to the same conclusion (or mostly similar) at the same time.. I set the output portion into it's own function that is only called when more than 1000 ms have passed. This way the main loop can continue to run at speed, and be available to catch any state changes by the interrupt. Since the interrupt doesn't read millis(), it shouldn't lock up (Though still don't know why that happens).
I changed the boolean to a volatile boolean cause i guess you're supposed to do that if you write a variable within an interrupt. The display section doesn't take too long, and the entire setup seems to be accurately reporting counts now.
I'm going to mess around with some more things here and try to see what I can do to start displaying the calculations, but if all goes well I should have the hard part done!
Thanks again for the help!
(Here's the code I used)
//Tire circumference in millimeters
const int circ = 2095;
byte SensorPin = 2;
unsigned long time;
unsigned int milsecs;
unsigned long time2;
int count;
unsigned long total;
float mph = 0.0;
int outspeed;
volatile boolean state = false;
unsigned long del;
void setup()
{
pinMode (SensorPin,INPUT);
digitalWrite (SensorPin, HIGH);
Serial.begin(19200);
attachInterrupt(0,sense,LOW);
}
void loop()
{
if(state == true && (millis() - time) > 10)
{
time = millis();
count = count + 1;
}
if(state == true)
{
state = false;
}
if (millis() - del > 1000)
{
display();
del = millis();
}
}
void display()
{
milsecs = time - time2;
time2 = time;
total = count * circ;
mph = (circ / milsecs) * 2.2369;
mph = mph * 100;
outspeed = int(mph);
Serial.print("Time: ");
Serial.print(milsecs);
Serial.print(" Count: ");
Serial.println(count);
Serial.print("Total mm: ");
Serial.print(total);
Serial.print(" MPH: ");
Serial.println(outspeed);
Serial.println(time);
}
void sense()
{
state = true;
}