Go Down

Topic: Need help with loop time/interrupt programming (Read 1 time) previous topic - next topic

_Leo_

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!
Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

AWOL

Quote
Do I use a timer interrupt

I don't really see any reason for this, based on the low sample rates.
YMMV.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

robtillaart

Quote
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.
Code: [Select]


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!
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

_Leo_

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.

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

robtillaart

Please post your unhappy code so we can see if we can fix it  (we is the forum)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

_Leo_

Rob,

I thought I'd give your millis loop example a try:

Code: [Select]
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

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

AWOL

Quote
It doesn't seem to be working correctly

Grrrr.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

_Leo_

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

_Leo_

Rob,

I took another look at your code and made slight modifications.

Now it is working correctly.

Code: [Select]
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++;
  } 
}
Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

robtillaart


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

Code: [Select]

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++;
  } 
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

_Leo_

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

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

_Leo_

Ok, I was able to find an easy fix with the rollover issue using the working code I posted earlier:

Code: [Select]
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?


Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

robtillaart

you still are using the addition :(

You have two different calls to millis() and expect they return an identical value.

try this variation
Code: [Select]

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;
  } 
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

_Leo_

You are correct. The 2 millis were the issue. With only one millis I'm getting a constant 50 printout now.
Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

_Leo_

I have corrected the code to be overflow conform:

Code: [Select]
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;
  } 
}
Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

Go Up