Millis Problem

Hello,

We are running the arduino on a weather balloon to take pictues, and send a the GPS coords to the ground.

The issue I am having is we need to vary not only the rapidity of the photos taken (ie at low altitude we want to take only a few photo’s, say every 5 minutes, while at its highest altitude we want to take a photo every 15 seconds, WHY? because the camera has a 1GB SD card limit and we want hi res pictures of the Earths curvature the card would be full before reaching the higher altitudes should it be taken every 15 seconds for the full 3 hour flight) at the same time we also need to vary the GPS output times as well, this time to save battery power, so in mid flight we do not care about knowing exactly where the balloon is, but at its zenith and on coming into land the GPS coord are very important as you can imagine.

Most libraries I have looked at cannot vary once the program begins execution, which is what we need to do.

My code below does not work, can anyone help, say with a very simple example. Show me where I am going wrong, as you can tell I new to Arduino and programming…

cheers

#include <NewSoftSerial.h>
#include <TinyGPS.h>
#include <AikoEvents.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

TinyGPS gps;
NewSoftSerial nss(2, 3);

using namespace Aiko;

struct      gpsdata {
  int            altitudeInt;
  int           sectorNUM; 
};
int sector = 10;
int shutterPin = 6;               // Shutter release

void gpsdump(TinyGPS &gps);
bool feedgps();
void printFloat(double f, int digits = 2);
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;

void setup()
{
  Events.addHandler(SectorDetermine, 5000);
  
  Serial.begin(9600);
  nss.begin(9600);
  digitalWrite(shutterPin, LOW);
  
}

gpsdata data;
void loop()
{
  bool newdata = false;
//  if (feedgps()){
//      newdata = true;
//    }
  unsigned long currentMillis = millis();
   
  if( (currentMillis - previousMillis >= (sector*3000)) ) {
    
    previousMillis = currentMillis;   
    Serial.print('in GPS Loop');
//    if (newdata){
    feedgps();
    gpsdump(gps);
//    }
  }
  
  if( (currentMillis - previousMillis2 >= (sector*5000)) ) {
    
   takePhoto();
   Serial.print('took a photo');
  }
  
  Serial.println('main');
   Events.loop();
}


void printFloat(double number, int digits)
{
  // Handle negative numbers
  if (number < 0.0)
  {
     Serial.print('-');
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
  
  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  Serial.print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0)
    Serial.print("."); 

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    Serial.print(toPrint);
    remainder -= toPrint; 
  } 
}

void gpsdump(TinyGPS &gps)
{
  long lat, lon;
  float flat, flon;
  unsigned long age, date, time, chars;
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned short sentences, failed;

//  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
//  Serial.print("Date: "); Serial.print(static_cast<int>(month)); Serial.print("/"); Serial.print(static_cast<int>(day)); Serial.print("/"); Serial.print(year);
//  Serial.print("  Time: "); Serial.print(static_cast<int>(hour)); Serial.print(":"); Serial.print(static_cast<int>(minute)); Serial.print(":"); Serial.print(static_cast<int>(second)); Serial.print("."); Serial.print(static_cast<int>(hundredths));
  feedgps();
  gps.f_get_position(&flat, &flon, &age);
//  Serial.print(" Lat/Long(float): "); printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5);
//  feedgps();
//  Serial.print("Alt(float): "); printFloat(gps.f_altitude()); Serial.println();
  (data.altitudeInt) =  (int)gps.f_altitude();
  printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5);Serial.print(", ");printFloat(gps.f_altitude());Serial.println();
//  Serial.print("Data Struct contents: "); Serial.print(data.altitudeInt); Serial.println();  // Sector Determine Data debug
Serial.print("Sector : ");Serial.print(sector);Serial.println();
} 
bool feedgps()
{
  while (nss.available())
  {
    if (gps.encode(nss.read()))
      return true;
  }
  return false;
}

static void SectorDetermine(){

  if (data.altitudeInt < 100){
    (data.sectorNUM) = 1;
  }
    if (data.altitudeInt >= 101 && data.altitudeInt <= 1500){
      (data.sectorNUM) = 10;
    }
  sector = data.sectorNUM;
}

void takePhoto(){
  digitalWrite(shutterPin, HIGH);
  delay(500);
  digitalWrite(shutterPin, LOW);
}

It doesn't work.. Normally I'd ignore such a comment, look at what you want to do, and delve through the code to figure out what is not behaving the way you want it to. Alas, it is a bit late, and I know somebody else will post before I'd get a chance to do the above, so I'll ask the question they'd undoubtedly ask (admittedly, it is a decent sized script.. so I'd appreciate the answer aswell, if I do end up being the one to help you out =P )

It doesn't work... What in particular doesn't work? how should it work? Do you have some debug info you could post?

Does changing sector to a larger datatype help...

[glow]unsigned long[/glow] sector = 10;

Firstly thank you for the replies, I'll try changing sector into unsigned long when I get home from workand could i ask why you think that will help?

Second sorry not to make clear the problem, look at the section of code below, what I am trying to achieve is two functions to be called every int*3000 ms and int*5000, when I say its not working, I can't give a screenshot as I am at work and don't have the arduino with me so I'll post the output later. At the moment though it seems that the camera shot (which is an LED at the minute for test purposes) flashes every 1000 ms (it should be every 1x3000ms) and the GPS function should be called every 1x5000ms this does not seem to work at all...

The main question is, is the structure of what I am doing correct to achieve this? can someone show me where I am going wrong with the loop structure.

I hope this makes more sense : )

if( (currentMillis - previousMillis >= (sector*3000)) ) {

previousMillis = currentMillis; Serial.print('in GPS Loop'); // if (newdata){ feedgps(); gpsdump(gps); // } }

if( (currentMillis - previousMillis2 >= (sector*5000)) ) {

takePhoto(); Serial.print('took a photo'); }

I looked through and couldn’t see anything glaringly wrong, but I don’t have an Arduino with me to test (also at work atm…)

This is what I would do though, so you can take what you want from it (no real need for the event library, but you can keep it if you want):

// keep track of the time
unsigned long time, lastTime, lastTimeGPS;

// update the GPS every 5 seconds
#define GPS_DELAY (5000)

// keep track of where we are and what delay we want
// 0-100: 300s (5 min)
// 100-1500: 30s
// 1500+: 5s
int sectorAlts[] = { 0, 100, 1500 };
unsigned long sectorDelays[] = { 300, 30, 5 }; // (in seconds)
// the sector that we start in
int sector = 0;

void setup()
{
  // setup initial things..
  lastTime = lastTimeGPS = millis();
}

void loop()
{
  // update the time
  time = millis();
  
  // take a photo every
  if((time - lastTime) >= sectorDelays[sector])
  {
    TakePhoto();
    lastTime = time;
  }
  
  // update the gps according to how fast we've set it
  if((time - lastTimeGPS) >= GPS_DELAY)
  {
    // grab GPS data and figure out which sector we're in
    UpdateGPS();
    UpdateSector();
    lastTimeGPS = time;
  }
}

void UpdateSector()
{
  // find out which sector we're in
  // starting at the first one
  // (step through it slowly if you don't
  // immediately see what's going on)
  for(int i = 0; i < sizeof(sectorAlts); i++)
    if(GPS.altitudeInt >= sectorAlts[i])
      sector = i;
}

Hi,

Just to let you know the structure is OK. the problem is with these two lines (below) as they only used single qoutes '' . If you have one char with single Quotes ie 'H' thats ok but if you have more characters ie 'hello' you get very odd results, hence my confusion as I was get very odd numbers printed to the screen instead of the text I was expecting.

So always use double Qoute ie "Hello" in c++ that is, its ok in pure C I am told

cheers

Nathan :-)

Serial.print('in GPS Loop');

Serial.print('took a photo');

I was get very odd numbers printed to the screen

I've just had a quick scan of this thread, and nowhere except the last post did I see that the problem was due to "very odd numbers". Why didn't you say that earlier?

Hi,

because I thought the strange number output was millis() outputting to the screen, hence I thought a problem existed with my structure.

It turns out the structure was fine and output was as i said from the Quotes issue.

Don't forget I am very green on coding...in future I'll post the output as well.