Help Starting with Millis

Hi all,

I am doing a project which involves a cellular chip with GPS. I have it set that when a pair of wires disconnect from one another, it is supposed to start a timer. When that timer surpasses 30 seconds, then I want it to call and text. But while it is counting, I still need it to detect a cancel button to cancel all operations and return back to its resting state.

With that said, I have no idea how to continue from here, or even know if the stuff I have already is correct or not. Can someone help me in figuring this out?

My email is shenangostem@gmail.com if you want to contact me.

I look forward to hearing from you! Here is my code:

#include "Adafruit_FONA.h"

#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4

#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;

Adafruit_FONA fona = Adafruit_FONA(FONA_RST);       //define fona


// constants
const int buttonPin = 5 ;                   // button for auto emergency distress
const int cancelPin = 6;
const int ledPin =  13;                     // LED for distress will be called
const int recordPin = 11;

// variables
int buttonState = 0;                       //start with harness connected
int cancelState = 0;

unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 1000;  //the value is a number of milliseconds

//strings
char gps_string[ 140 ];                    //define the GPS information as a string

void setup() {
  Serial.begin(4800);                      //start serial monitor at 4800 baud
  Serial.println("Beginning Setup");
  fonaSerial->begin(4800);                  //begin software serial at 4800 baud
  fona.begin(*fonaSerial);                  //fona begins to utilize software serial
  fona.enableGPS(true);                     //enable GPS function
  fona.getGPS( 0, gps_string, 140 );        //get the GPS location as a reference
  pinMode(ledPin, OUTPUT);                  // initialize the LED pin as an output
  pinMode(buttonPin, INPUT);                // initialize the pushbutton pin as an input
  pinMode(cancelPin, INPUT);
  pinMode(recordPin, OUTPUT);               //set the digital record pin as an output

}

void loop() {
  currentMillis = millis();
  buttonState = digitalRead(buttonPin);     //read for button push every loop
  cancelState = digitalRead(cancelPin);
  fona.getGPS( 0, gps_string, 140 );        //update GPS info every loop 
  Serial.println("Pin State:" + buttonState);             //
  
if (buttonState = 0) {
  startMillis = millis();
}

if (startMillis < 30 && cancelState = 1) {  //if pin is high (harness still connected) keep everything off
    digitalWrite(ledPin, LOW);
    digitalWrite(recordPin, LOW);
    fona.hangUp();}
else {                                      //if pin is low (harness tripped) turn everything on
    digitalWrite(ledPin, 1);
    fona.sendSMS("555-555-5555", "help...i've fallen and I can't get up!");
      Serial.println("Text Message Sent");
     delay(2500);
     fona.sendSMS("555-555-5555", gps_string );
      Serial.println("GPS Coordinates Sent");
     delay(5000);
    fona.callPhone("555-555-5555");
    Serial.println("Calling");
      delay(7500);
    digitalWrite(recordPin, HIGH);
      delay(500);
    digitalWrite(recordPin, LOW);
      Serial.println("Recording Started");
  }
}

It is a very bad idea to post your email address in public - it will be harvested by spammers. I suggest you edit your Original Post and delete the email address ASAP. Forum people will not be emailing you in any case - they will respond to you in the Forum.

You have not said what your program actually does and what you want it to do that is different.

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

Welcome to the forums. Congratulations for using code tags on your first post! Excellent.

As for your code, there are several issues

  Serial.println("Pin State:" + buttonState);             //

C/C++ doesn’t allow you to concatinate string literals with other variables.

  Serial.print("Pin State:"); Serial.println(buttonState);
  if (buttonState = 0) {
    startMillis = millis();
  }

This is an assignment. You want to test for equality which is ‘==’

And you don’t want to assign to startMillis every time the button is pressed. You want to detect the change from button not pressed to button pressed. Look at the StateChangeDetection example to see how to do this properly (File->Examples->02.Digital->StateChangeDetection)

blh64:
Welcome to the forums. Congratulations for using code tags on your first post! Excellent.

As for your code, there are several issues

  Serial.println("Pin State:" + buttonState);             //

C/C++ doesn't allow you to concatinate string literals with other variables.

  Serial.print("Pin State:"); Serial.println(buttonState);
  if (buttonState = 0) {

startMillis = millis();
  }



This is an assignment. You want to test for equality which is '=='

And you don't want to assign to startMillis every time the button is pressed. You want to detect the change from button not pressed to button pressed. Look at the StateChangeDetection example to see how to do this properly (File->Examples->02.Digital->StateChangeDetection)

Ok so my project has one digital pin that is always pulled high. It is supposed to detect when there is a break in that wire that is pulling a digital pin high. If that pin goes low, I want it to start counting to 30 so that it gives me 30 seconds to press a button to cancel it. If that 30 seconds does surpass without the pressing of that cancel button, then I want it to proceed to call me/text me. It is a one-time program. Once it calls/texts, i want it to stop until it is reset after a new wire is in place. I just don't know how to go about reading a button while counting...

Robin2:
It is a very bad idea to post your email address in public - it will be harvested by spammers. I suggest you edit your Original Post and delete the email address ASAP. Forum people will not be emailing you in any case - they will respond to you in the Forum.

That's an urban legend. I post my email in a lot of forums and I've never seen an increase in spam as a result. Timewise, scraping sites for email addresses is very inefficient and the email addresses gleaned are of limited use.

The main reason to not post an email is that you want to encourage discussions on the forum.

Josephm3502:
Ok so my project has one digital pin that is always pulled high. It is supposed to detect when there is a break in that wire that is pulling a digital pin high. If that pin goes low, I want it to start counting to 30 so that it gives me 30 seconds to press a button to cancel it. If that 30 seconds does surpass without the pressing of that cancel button, then I want it to proceed to call me/text me. It is a one-time program. Once it calls/texts, i want it to stop until it is reset after a new wire is in place. I just don't know how to go about reading a button while counting...

You already stated what your project requirements are. YOU need to write some code. I suggested you look at the StateChangeDetection example. You should also look at the BlinkWithoutDelay example to see how to keep track of elapsed time without blocking your code from doing other things (like reading your button).

Give it a try. Figure some things out. If you get stuck, post your code, any errors and a description of the problem and people will help.

blh64:
You already stated what your project requirements are. YOU need to write some code. I suggested you look at the StateChangeDetection example. You should also look at the BlinkWithoutDelay example to see how to keep track of elapsed time without blocking your code from doing other things (like reading your button).

Give it a try. Figure some things out. If you get stuck, post your code, any errors and a description of the problem and people will help.

Ok. So I decided to take a step back and try to apply what I want to do to a simple task like lighting up an LED and writing in the serial monitor.

Here is what I came up with. I just have no idea if a nested if statement inside of another if statement is the right way to go...

const byte buttonPin = 11;
const byte cancelPin = 12;
const byte ledPin = 13;

int ledState = 0;
int buttonState = 0;
int cancelState = 0;

const unsigned long tripTime = 100;
const unsigned long cancelTime = 100;

unsigned long previousTime_1 = 0;
unsigned long previousTime_2 = 0;


void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(cancelPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.print("Ready...");

}

void loop() {
  unsigned long currentTime = millis();
  cancelState = digitalRead(cancelPin);

 if(currentTime - previousTime_1 >= tripTime){
    buttonState = digitalRead(buttonPin);
   if (buttonState = 0){
      Serial.print("You have 30 seconds to cancel!");
      digital.write(ledPin, HIGH);
 }
}

 if( currentTime - previousTime_2 >= cancelTime){
    cancelState = digitalRead(cancelPin);
   if (buttonState = 1) {
    Serial.print("operation cancelled...");
    digitalWrite(ledPin, LOW);
   }
 }

SteveMann:
That's an urban legend. I post my email in a lot of forums and I've never seen an increase in spam as a result. Timewise, scraping sites for email addresses is very inefficient and the email addresses gleaned are of limited use.

The main reason to not post an email is that you want to encourage discussions on the forum.

It's because big email host companies spend lots of money on infrastructure to filter out spammed emails.

arduino_new:
It's because big email host companies spend lots of money on infrastructure to filter out spammed emails.

I host my own mail server, so this doesn't apply to me.

Josephm3502:
Ok. So I decided to take a step back and try to apply what I want to do to a simple task like lighting up an LED and writing in the serial monitor.

Here is what I came up with. I just have no idea if a nested if statement inside of another if statement is the right way to go...

   if (buttonState = 0){

}
...
  if (buttonState = 1) {
  }
}

Those are assignment statements ('='). You want to a comparison ('==') in your if() statements.

As for the code in general, you need to detect a button state change and then start the timing. Look at the StateChangeDetection example. Your current code does not start counting your 30 second interval.

Do the 'start' and 'cancel' switches operate momentarily?

//version 1.00

//assumes the start button closes MOMENTARILY to start the timing
//assumes the cancel switch closes MOMENTARILY to cancel timing

#define switchClosed LOW


const byte startPin  = 11;
const byte cancelPin = 12;
const byte ledPin    = 13;

byte ledState;

byte startState;
byte lastStartState;

byte cancelState;
byte lastCancelState;

bool timingFlag      = false;

const unsigned long sendInterval   = 30 * 1000ul; //30 seconds

unsigned long timingMillis;
unsigned long sendMillis;
unsigned long switchMillis;


//******************************************************************************
void setup()
{
  Serial.begin(9600);
  pinMode(startPin, INPUT_PULLUP);
  pinMode(cancelPin, INPUT_PULLUP);

  pinMode(ledPin, OUTPUT);

  Serial.println("Ready...");

} //END of setup()


//******************************************************************************
void loop()
{
  //***********************************
  //if timing is enabled has the timer expired?
  if (timingFlag == true && millis() - sendMillis >= sendInterval)
  {
    //do something
    Serial.println("Blow up the world");
    digitalWrite(ledPin, HIGH);

    //cancel timing
    timingFlag = false;
  }

  //***********************************
  //every 50ms check the switches
  if ( millis() - switchMillis >= 50)
  {
    //restart timer
    switchMillis = millis();

    checkSwitches();
  }

}//END of loop()


//******************************************************************************
void checkSwitches()
{
  //***********************************
  startState = digitalRead(startPin);

  //did the switch change state?
  if (lastStartState != startState)
  {
    //update to the new state
    lastStartState = startState;

    //when we are not timing, was the switch pressed?
    if (timingFlag == false && startState == switchClosed)
    {
      Serial.println("You have 30 seconds to cancel!");

      //enable timing
      timingFlag = true;

      //start timer
      sendMillis = millis();

    }
  }

  //***********************************
  cancelState = digitalRead(cancelPin);

  //did the switch change state?
  if (lastCancelState != cancelState)
  {
    //update to the new state
    lastCancelState = cancelState;

    //was the switch pressed?
    if (cancelState == switchClosed)
    {
      Serial.println("Operation cancelled...");
      digitalWrite(ledPin, LOW);

      //disable timing
      timingFlag = false;
    }
  }

  //***********************************
  //other switches here
  //***********************************


} //END of checkSwitches()

larryd:
Do the 'start' and 'cancel' switches operate momentarily?

//version 1.00

//assumes the start button closes MOMENTARILY to start the timing
//assumes the cancel switch closes MOMENTARILY to cancel timing

#define switchClosed LOW

const byte startPin  = 11;
const byte cancelPin = 12;
const byte ledPin    = 13;

byte ledState;

byte startState;
byte lastStartState;

byte cancelState;
byte lastCancelState;

bool timingFlag      = false;

const unsigned long sendInterval  = 30 * 1000ul; //30 seconds

unsigned long timingMillis;
unsigned long sendMillis;
unsigned long switchMillis;

//******************************************************************************
void setup()
{
  Serial.begin(9600);
  pinMode(startPin, INPUT_PULLUP);
  pinMode(cancelPin, INPUT_PULLUP);

pinMode(ledPin, OUTPUT);

Serial.println("Ready...");

} //END of setup()

//******************************************************************************
void loop()
{
  //***********************************
  //if timing is enabled has the timer expired?
  if (timingFlag == true && millis() - sendMillis >= sendInterval)
  {
    //do something
    Serial.println("Blow up the world");
    digitalWrite(ledPin, HIGH);

//cancel timing
    timingFlag = false;
  }

//***********************************
  //every 50ms check the switches
  if ( millis() - switchMillis >= 50)
  {
    //restart timer
    switchMillis = millis();

checkSwitches();
  }

}//END of loop()

//******************************************************************************
void checkSwitches()
{
  //***********************************
  startState = digitalRead(startPin);

//did the switch change state?
  if (lastStartState != startState)
  {
    //update to the new state
    lastStartState = startState;

//when we are not timing, was the switch pressed?
    if (timingFlag == false && startState == switchClosed)
    {
      Serial.println("You have 30 seconds to cancel!");

//enable timing
      timingFlag = true;

//start timer
      sendMillis = millis();

}
  }

//***********************************
  cancelState = digitalRead(cancelPin);

//did the switch change state?
  if (lastCancelState != cancelState)
  {
    //update to the new state
    lastCancelState = cancelState;

//was the switch pressed?
    if (cancelState == switchClosed)
    {
      Serial.println("Operation cancelled...");
      digitalWrite(ledPin, LOW);

//disable timing
      timingFlag = false;
    }
  }

//***********************************
  //other switches here
  //***********************************

} //END of checkSwitches()

They do indeed operate momentarily.