_Leo
May 20, 2012, 6:14pm
1
Everyone,
I’m in need of your programming expertize.
As basis I’m using a UNO R3 with 16MHz, eeprom 512 and a MS5611 barometric pressure sensor.
At a later date I will be using a 328 with 8 MHz (3.3v) and my ultimate goal is to use the Attiny85.
Essentially I have everything working however due to my lack of knowledge with Timer/Interrupt programming I am unable to find a good solution in putting everything together.
Here is what I want to do:
The program is for a model rocket that records the altitude to eeprom and sets off 2 deployments.
-> Get pressure from sensor and save in array (50 / sec)
-> Calculate average pressure from array (10 / sec)
-> Calculate the altitude (10 / sec)
-> Write altitude to eeprom ( 10 / sec)
-> Check to see if lift-off has occurred (10 /sec)
-> Check if max altitude has been reached –> deploy parachute (10 / sec)
-> Check if preset altitude has been reached –> deploy parachute (10 / sec)
-> Check if touchdown occurred –> exit loop to read out the altitude via led flash
Now my first questions are:
What would be the best way to go about this?
Do I use a timer interrupt and if so how should I implement it?
Thanks!
Do I use a timer interrupt
I don't really see any reason for this, based on the low sample rates.
YMMV.
What would be the best way to go about this?
you should read the blink without delay example that should help you
a quick dump of your list into code with functions that need to be elaborated.
unsigned long T1 = 20;
unsigned long T2 = 100;
long p = 0;
void loop()
{
// 50 / sec items
if (millis() - T1 > lastPressureTime)
{
lastPressureTime += T1;
p += readPressure();
}
// 10/sec items
if (millis() - T2 > lastAverageTime)
{
lastAverageTime+= T1;
pressure = p/5;
p = 0; // reset
altitude = calcAltitude(pressure);
writeEEprom(altitude); // wears out if written too often ... consider an external eeprom that can be replaced)
flag = checkLiftOffOccured();
if ((altitude < highest && parachuteClosed() ) || (altitude >= presetAltitude))
{
doParachute();
}
highest = max(altitude, highest);
if (touchDown())
{
exit();
}
}
this is incomplete code but it gives you an idea how it is done. The functions must be written still or can be replaced by the actual code .
Succes!
_Leo
May 20, 2012, 6:44pm
4
Thanks AWOL. I'll try it without using timer interrupts.
Thank you Rob.
I am using an external eeprom for that very reason.
I had the program written in a manner that you have posted but was not happy with it.
I'll give it another try and report here with my concerns, if any.
Please post your unhappy code so we can see if we can fix it (we is the forum)
_Leo
May 21, 2012, 10:32am
6
Rob,
I thought I'd give your millis loop example a try:
unsigned long T1;
unsigned long lastPressureTime;
int loopCounter;
void setup()
{
Serial.begin(115200);
T1 = 1000;
lastPressureTime = 0;
loopCounter = 0;
}
void loop()
{
if (millis() - T1 > lastPressureTime)
{
lastPressureTime += T1;
Serial.println(loopCounter); // print every second
loopCounter++;
}
}
It doesn't seem to be working correctly.
_Leo
May 21, 2012, 4:40pm
9
Rob,
I took another look at your code and made slight modifications.
Now it is working correctly.
unsigned long T1;
unsigned long lastPressureTime;
int loopCounter;
void setup()
{
Serial.begin(115200);
T1 = 1000;
lastPressureTime = T1;
loopCounter = 0;
}
void loop()
{
if (millis() + T1 >= lastPressureTime)
{
lastPressureTime += T1;
Serial.println(loopCounter); // print every second
loopCounter++;
}
}
Sorry to say but you should not use + addition with millis() compares , it is explained here - http://www.faludi.com/2007/12/18/arduino-millis-rollover-handling/ -
a retry which includes the value of millis(), give it a try
unsigned long T1=1000;
unsigned long T2=250;
unsigned long lastPressureTime=0;
unsigned long lastCalcTime=0;
int counter1=0;
int counter2=0;
void setup()
{
Serial.begin(115200);
}
void loop()
{
unsinged long now = millis();
if (now - T1 >= lastPressureTime)
{
lastPressureTime += T1;
Serial.print(now);
Serial.print("\t ");
Serial.println(counter1); // print every second
counter1++;
}
if (now - T2 >= lastCalcTime)
{
lastCalcTime += T2;
Serial.print("\t\t ");
Serial.print(now);
Serial.print("\t ");
Serial.println(counter2); // 4x /second
counter2++;
}
}
_Leo
May 21, 2012, 6:38pm
11
Under normal circumstances rollover occurs after 50 days.
My hardware would be used for no more than 1 hour at the max.
Sorry Rob. Your second example doesn't work either.
_Leo
May 21, 2012, 6:45pm
12
Ok, I was able to find an easy fix with the rollover issue using the working code I posted earlier:
unsigned long T1, T2;
unsigned long lastPressureTime, lastPrintTime;
int loopCounter;
void setup()
{
Serial.begin(115200);
T1 = 20;
T2 = 1000;
lastPressureTime = 0;
lastPrintTime = 0;
loopCounter = 0;
}
void loop()
{
if (millis() >= lastPressureTime + T1) // loop 50 times per second
{
lastPressureTime += T1;
loopCounter++;
}
if (millis() >= lastPrintTime + T2) // print every second
{
lastPrintTime += T2;
Serial.println(loopCounter);
loopCounter = 0;
}
}
The output for every second I get is this:
50
49
51
50
49
51
50
49
50
51
50
49
51
50
49
51
50
It should output a constant 50 but it doesn't. Any idea why that is?
you still are using the addition
You have two different calls to millis() and expect they return an identical value.
try this variation
unsigned long T1, T2;
unsigned long lastPressureTime, lastPrintTime;
int loopCounter;
void setup()
{
Serial.begin(115200);
T1 = 20;
T2 = 1000;
lastPressureTime = 0;
lastPrintTime = 0;
loopCounter = 0;
}
void loop()
{
unsigned long now = millis();
if (now >= lastPressureTime + T1) // loop 50 times per second
{
lastPressureTime += T1;
loopCounter++;
}
if (now >= lastPrintTime + T2) // print every second
{
lastPrintTime += T2;
Serial.println(loopCounter);
loopCounter = 0;
}
}
_Leo
May 21, 2012, 7:14pm
14
You are correct. The 2 millis were the issue. With only one millis I'm getting a constant 50 printout now.
_Leo
May 21, 2012, 7:39pm
15
I have corrected the code to be overflow conform:
unsigned long T1, T2;
unsigned long lastPressureTime, lastPrintTime;
int loopCounter;
void setup()
{
Serial.begin(115200);
T1 = 20;
T2 = 1000;
lastPressureTime = 0;
lastPrintTime = 0;
loopCounter = 0;
}
void loop()
{
unsigned long now = millis();
if (now - lastPressureTime >= T1) // loop 50 times per second
{
lastPressureTime = now;
loopCounter++;
}
if (now - lastPrintTime >= T2) // print every second
{
lastPrintTime = now;
Serial.println(loopCounter);
loopCounter = 0;
}
}
system
May 21, 2012, 7:58pm
16
You can simplify; all the global variables are zeroed before setup runs, and T1 and T2 could be initialised when declared.