Call a function problem

I am trying to replace the delay(1000) in the following code to millis.

This works:

    int z = 1;
    while (z <= totToolZones) {
    Serial.print("z = ");
    Serial.println(z);
    z++;
    delay(1000);
  }

This does not:

 currentMillis = millis();
unsigned long currentMillis = millis();
if ((unsigned long)(currentMillis - previousMillis) >= PollInterval) {
  previousMillis = currentMillis;
    int z = 1;
    while (z <= totToolZones) {
    Serial.print("z = ");
    Serial.println(z);
    z++;
  }
    }

In the setup(), I have:

int totToolZones = 12;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
const long PollInterval = 1000;

What I need to accomplish is to print the Serial.println(z); every PollInterval ( 1 second).
Print z=1 wait 1 second print z=2 wait 1 second Print z=3 etc. etc.

The above code prints all 12 (totToolZones ) every 1 second
The top code with the delay(1000) works correctly and prints z=1 wait 1 second prints z=2 wait 1 second prints z=3 etc. etc.

I cannot understand what I am doing incorrectly.

The example I used was from Blink without Delay example.

Play with this:

unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= PollInterval and z<= totToolZones) {
  previousMillis = currentMillis;
    Serial.print("z = ");
    Serial.println(z);
    z++;
    }

int totToolZones = 12;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
const long PollInterval = 1000;

If this is in setup these go out of scope when loop is run.

hi

first of all you have 2 x "usigned long currentMillis" in your skecth a Local and global one.
local is more then enough.

you dont need the While loop, thats the reason why it print 1 to 12 every 1 sec.

make "z" Global varaible and not local.

and "(unsigned long)currentMillis" you dont need to point out its a unsigned long beacuse you allready declarde that.

Declare z as a global variable then

currentMillis = millis();
if (currentMillis - previousMillis >= PollInterval)
{
  previousMillis = currentMillis;
  Serial.print("z = ");
  Serial.println(z % totToolZones);
  z++;
}

UKHeliBob:
Declare z as a global variable then

currentMillis = millis();

if (currentMillis - previousMillis >= PollInterval)
{
  previousMillis = currentMillis;
  Serial.print("z = ");
  Serial.println(z % totToolZones);
  z++;
}

What stops z from incrementing forever?

This code, thanks UKHeliBob, works to some degree in that I do get the delay between each print.

currentMillis = millis();
if (currentMillis - previousMillis >= PollInterval)
{
  previousMillis = currentMillis;
  Serial.print("z = ");
  Serial.println(z % totToolZones);
  z++;
}

However, if I set the totToolZones=6, then I get the following print:

z = 1
z = 2
z = 3
z = 4
z = 5
z = 0
z = 1
z = 2
z = 3
z = 4
z = 5
z = 0

I do not get the last numeral (6).
This "loops" forever and it should stop print once it has reached totToolZones:

z = 1
z = 2
z = 3
z = 4
z = 5
z = 6

Then stop.

What I ideally require is to be able set an additional delay as follows:

z = 1
delay 1 second
z = 2
delay 1 second
z = 3
delay 1 second
z = 4
delay 1 second
z = 5
delay 1 second
z = 6

NOW DELAY 10 seconds

z = 1
delay 1 second
z = 2
delay 1 second
z = 3
delay 1 second
z = 4
delay 1 second
z = 5
delay 1 second
z = 6

REPEAT

Once I have this running, I will replace the "Serial.print" with a "Wire.write as each zone is an UNO that is connected via I2C.

The demo Several Things at a Time illustrates the use of millis() to manage timing.

…R

@aarg:
Many thanks, works well:

unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= PollInterval and z<= totToolZones) {
  previousMillis = currentMillis;
    Serial.print("z = ");
    Serial.println(z);
    z++;
    }

How do I put this in an additional “loop” that will call the above every XXX seconds?

What stops z from incrementing forever?

Nothing, but the

 Serial.println(z % totToolZones);

prevents the actual value of z being printed.

NOTE : z should be declared as an unsigned int to prevent it going negative.

it should stop print once it has reached totToolZones:

I don't believe that was clear in your original requirement.

I have a BT device connected to an UNO using SoftwareSerial.
When a string is received that StartsWith “P”, I need to call a function “pollZones()”
This function must “loop” through the number of “zones” and Serial.print “z = n”, where n == zones 1 through “totToolZones”.
The problems I have are:
1). The pollZones() Serial.print only prints 1 “zone” (z = 1) each time a “P” is received.
The pollZones() should print all zones each time a “P” is received.
As an example of how pollZones() should work with totToolZones==4:

Rx Android: >P,4,#<
GOT P
Total Zones: 4
z = 1  // now wait PollInterval = 100;
z = 2  // now wait PollInterval = 100;
z = 3  // now wait PollInterval = 100;
z = 4  // now wait PollInterval = 100;

What I am actually getting is:

Rx Android: >P,4,#<
GOT P
Total Zones: 4
z = 1
Rx Android: >P,4,#<
GOT P
Total Zones: 4
z = 2
Rx Android: >P,4,#<
GOT P
Total Zones: 4
z = 3
Rx Android: >P,4,#<
GOT P
Total Zones: 4
z = 4

2). In the void loop() function, pollZones() is only called on the first occurrence of “if (rxZoneT.startsWith(“P”))” and not every time “rxZoneT.startsWith(“P”)” is received.

My entire sketch is:

#include <SoftwareSerial.h>
SoftwareSerial portBT(13, 11);
int totToolZones = 0;
int z = 1;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
const long PollInterval = 100;

void setup() {
  Serial.begin(9600); //setup serial for input and output
  portBT.begin(9600);
}

void loop() {
  static char buffer[24];
  if (readBT(portBT.read(), buffer, 24) > 0) {
    String rxZoneT(buffer);
    Serial.print("Rx Android: >");  // For DEBUG
    Serial.print(rxZoneT);  // For DEBUG
    Serial.println("<");  // For DEBUG
 
      if (rxZoneT.startsWith("P")) { // Only action this routine if "P" is the first character in string "rxZoneT".
        Serial.println("GOT P");
            // Parse the string "rxZoneT" to obtain the totToolZones - string can be variable length and is not a statis length.
            int index1 = rxZoneT.indexOf(',');
            int index2 = rxZoneT.indexOf(',', index1+1);
            String zonesTotal = rxZoneT.substring(index1+1, index2);
            totToolZones = zonesTotal.toInt();
            Serial.print("Total Zones: ");  // For DEBUG
            Serial.println(totToolZones);  // For DEBUG

        pollZones();  // Start the polling of the zones - Call pollZones();
      }
  }
}

void pollZones(){
// poll zones from "1" until "totToolZones" reached at an interval of "PollInterval" between zone polls
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= PollInterval and z<= totToolZones) {
  previousMillis = currentMillis;
      Serial.print("z = ");
      Serial.println(z);
      z++;
      }
}

int readBT(int readch, char *buffer, int len)
{
  static int pos = 0;
  int rpos;
  if (readch > 0) {
    switch (readch) {
      case '\n': // Ignore new-lines
        break;
      case '\r': // Return on CR
        rpos = pos;
        pos = 0;  // Reset position index ready for next time
        return rpos;
      default:
        if (pos < len-1) {
          buffer[pos++] = readch;
          buffer[pos] = 0;
        }
    }
  }
  // No end of line has been found, so return -1.
  return -1;
}

Declan:
@aarg:
Many thanks, works well:

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= PollInterval and z<= totToolZones) {
  previousMillis = currentMillis;
    Serial.print("z = ");
    Serial.println(z);
    z++;
    }




How do I put this in an additional "loop" that will call the above every XXX seconds?

You just put it in loop() and it will run every time that loop() runs.

void setup()
{
// code that only runs once
}

void loop()
{
// code that runs over and over
}

NOT

void main()
{
// code that runs over and over has to have its own loop
}

You already have one thread on this sketch started.

Yip, but that related to replacing delay() with millis

Declan:
Yip, but that related to replacing delay() with millis

Make life easy for us.

Click Report to Moderator and ask to have your two Threads merged. Keep all the info about a project in one place.

...R

@Robin2, thanks for advise - Done

Could someone please point me in the right direction - this is driving me crazy :cry:

Declan:
Could someone please point me in the right direction - this is driving me crazy :cry:

See what you make of this

unsigned long longPeriod = 10000;
unsigned long shortPeriod = 1000;
unsigned long startTime;
unsigned long currentTime;
byte state = 0;
byte counter;
byte maxCount = 6;

void setup()
{
  Serial.begin(115200);
  startTime = millis();
}

void loop()
{
  switch (state)
  {
    case 0:  //wait for long period to elapse
      currentTime = millis();
      if (currentTime - startTime >= longPeriod)
      {
        counter = 0;
        startTime = millis();
        state = 1;
      }
      break;

    case 1:  //count up at short period intervals
      currentTime = millis();
      if (currentTime - startTime >= shortPeriod)
      {
        Serial.println(counter);
        counter++;
        if (counter >= maxCount)
        {
          state = 0;
        }
        else
        {
          startTime = millis();
        }
      }
  }
}

As written it waits 10 seconds then prints 0 to 5 at 1 second intervals, waits again then repeats. Please ask if you have any questions.

@ UKHeliBob - Thanks, That works great.
I will drop into my code and let you know how I progress.