Use of arrays

Hi
I am trying to make a dosing sketch for my aquarium. My issue is as follows:

Choose a set programme. I have a 2dose/day, 4dose/day, 8dose/day, 16dose/day and a 24dose/day. An allocated time has been set for each dose so it corresponds with time.
In order to not write thousands of lines of code I have tried to use arrays.
The first part of the code is to create my 5 arrays of the ON times of the dosing pump.

unsigned long 2Dose[2] = {0, 43200000};
unsigned long 4Dose[4] = {0, 21600000, 43200000, 64800000};
unsigned long 8Dose[8] = {0, 10800000, 21600000, 32400000, 43200000, 54000000, 64800000, 75600000};
unsigned long 16Dose[16] = {0, 5400000, 10800000, 16200000, 21600000, 27000000, 32400000, 37800000, 
                          43200000, 48600000, 54000000, 59400000, 64800000, 70200000, 75600000, 81000000};
unsigned long 24Dose[24] = {0, 3600000, 7200000, 10800000, 14400000, 18000000, 21600000, 25200000, 28800000, 
                          32400000, 36000000, 39600000, 43200000, 46800000, 50400000, 54000000, 57600000, 
                          61200000, 64800000, 68400000, 72000000, 75600000, 79200000, 82800000};

unsigned long OffSet = 300000; //5MINUTE OFFSET

The second part was to create a generic function for the dosing pump

void Run2Dose (int pin,
               unsigned long time,       //Current time in millis
               unsigned long offset,     //Offset time in millis avoid clashing of dosing
              unsigned long start[],     //Start time in millis
               unsigned long period)     //On period time in millis
{
  for (int x = 0; x < 2; x++)
  {
    if ((time + offset) + start[x] <= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, HIGH);
    }
    else if ((time + offset) + start[x] >= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, LOW);
    }
  }
}
      
void Run4Dose (int pin,
               unsigned long time,       //Current time in millis
               unsigned long offset,     //Offset time in millis avoid clashing of dosing
              unsigned long start[],     //Start time in millis
               unsigned long period)     //On period time in millis
{
  for (int x = 0; x < 4; x++)
  {
    if ((time + offset) + start[x] <= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, HIGH);
    }
    else if ((time + offset) + start[x] >= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, LOW);
    }
  }
}   

void Run8Dose (int pin,
               unsigned long time,       //Current time in millis
               unsigned long offset,     //Offset time in millis avoid clashing of dosing
               unsigned long start[],    //Start time in millis
               unsigned long period)     //On period time in millis
{
  for (int x = 0; x < 8; x++)
  {
    if ((time + offset) + start[x] <= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, HIGH);
    }
    else if ((time + offset) + start[x] >= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, LOW);
    }
  }
}

void Run16Dose (int pin,
               unsigned long time,       //Current time in millis
               unsigned long offset,     //Offset time in millis avoid clashing of dosing
               unsigned long start[],    //Start time in millis
               unsigned long period)     //On period time in millis
{
  for (int x = 0; x < 16; x++)
  {
    if ((time + offset) + start[x] <= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, HIGH);
    }
    else if ((time + offset) + start[x] >= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, LOW);
    }
  }
}

void Run24Dose (int pin,
               unsigned long time,       //Current time in millis
               unsigned long offset,     //Offset time in millis avoid clashing of dosing
               unsigned long start[],    //Start time in millis
               unsigned long period)     //On period time in millis
{
  for (int x = 0; x < 24; x++)
  {
    if ((time + offset) + start[x] <= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, HIGH);
    }
    else if ((time + offset) + start[x] >= (time + offset) + start[x] + period)
    {
      digitalWrite(pin, LOW);
    }
  }
}

And the last part is the actual function

void RunDosers()
{
  ActualTime = (((hour()*3600) + (minute()*60) + second()) * 1000);
  if (Doser1Prog == 4)
  {
    for (int x = 0; x < 2; x++)
    Run2Dose(DOS1, ActualTime, 0, 2Dose[x], D1P2);  //pin/time/ offset/start[]/period
    if (DOS1 == HIGH)
    {
      LEDDOSER1.setColor(Blue);
      LEDDOSER1.on();
    }
    else if (DOS1 == LOW)
    {
      LEDDOSER1.setColor(Green);
      LEDDOSER1.on();
    }
  }
  else if (Doser1Prog == 5)
  {
    for (int x = 0; x < 4; x++)
    Run4Dose(DOS1, ActualTime, OffSet, 4Dose[x], D1P4);  //pin/time/ offset/start[]/period
    if (DOS1 == HIGH)
    {
      LEDDOSER1.setColor(Blue);
      LEDDOSER1.on();
    }
    else if (DOS1 == LOW)
    {
      LEDDOSER1.setColor(Green);
      LEDDOSER1.on();
    }
  }
  else if (Doser1Prog == 6)
  {
    for (int x = 0; x < 8; x++)
    Run8Dose(DOS1, ActualTime, (OffSet * 2), 8Dose[x], D1P8);  //pin/time/ offset/start[]/period
    if (DOS1 == HIGH)
    {
      LEDDOSER1.setColor(Blue);
      LEDDOSER1.on();
    }
    else if (DOS1 == LOW)
    {
      LEDDOSER1.setColor(Green);
      LEDDOSER1.on();
    }
  }
  else if (Doser1Prog == 7)
  {
    for (int x = 0; x < 16; x++)
    Run16Dose(DOS1, ActualTime, (OffSet * 3), 16Dose[x], D1P16);  //pin/time/ offset/start[]/period
    if (DOS1 == HIGH)
    {
      LEDDOSER1.setColor(Blue);
      LEDDOSER1.on();
    }
    else if (DOS1 == LOW)
    {
      LEDDOSER1.setColor(Green);
      LEDDOSER1.on();
    }
  }
  else if (Doser1Prog == 8)
  {
    for (int x = 0; x < 24; x++)
    Run24Dose(DOS1, ActualTime, (OffSet * 4), 24Dose[x], D1P24);  //pin/time/ offset/start[]/period
    if (DOS1 == HIGH)
    {
      LEDDOSER1.setColor(Blue);
      LEDDOSER1.on();
    }
    else if (DOS1 == LOW)
    {
      LEDDOSER1.setColor(Green);
      LEDDOSER1.on();
    }
  }
}

The issue is it does not compile. The following is the compile error

C:\Users\proie\Dropbox\ARDUINO\arduino 1.8.9\AquArt_Blynk_DoserTest\DOSERS.ino: In function 'void RunDosers()':

DOSERS:218:35: error: unable to find numeric literal operator 'operator"" Dose'

     Run2Dose(DOS1, ActualTime, 0, 2Dose[x], D1P2);  //pin/time/ offset/start[]/period

                                   ^

DOSERS:233:40: error: unable to find numeric literal operator 'operator"" Dose'

     Run4Dose(DOS1, ActualTime, OffSet, 4Dose[x], D1P4);  //pin/time/ offset/start[]/period

                                        ^

DOSERS:248:46: error: unable to find numeric literal operator 'operator"" Dose'

     Run8Dose(DOS1, ActualTime, (OffSet * 2), 8Dose[x], D1P8);  //pin/time/ offset/start[]/period

                                              ^

DOSERS:263:47: error: unable to find numeric literal operator 'operator"" Dose'

     Run16Dose(DOS1, ActualTime, (OffSet * 3), 16Dose[x], D1P16);  //pin/time/ offset/start[]/period

                                               ^

DOSERS:278:47: error: unable to find numeric literal operator 'operator"" Dose'

     Run24Dose(DOS1, ActualTime, (OffSet * 4), 24Dose[x], D1P24);  //pin/time/ offset/start[]/period

                                               ^

exit status 1
expected unqualified-id before numeric constant

can somebody please point me as to where I am going wrong please.
Thanks

You cannot use numbers as the first letter in a variable name, rename "2Dose" to "Dose2" or "_2Dose" - this applies to the other array names as well.

Ok, I will change that, what about the way I have used the arrays? if you note I have put a for loop in both the void Run2/4/16/24Dose and the void RunDoser statements.. is this correct?

Proietti:
Ok, I will change that, what about the way I have used the arrays? if you note I have put a for loop in both the void Run2/4/16/24Dose and the void RunDoser statements.. is this correct?

If it works, yes - otherwise no.. :wink:

Your attempt at using arrays is laudable but not necessary because you do not need to store the of each dose, merely the period in milliseconds between doses, that is one period per dose scheme

Take a look at the BlinkWithoutDelay example. The blink period is equivalent to the period between doses and the changing of the state of the LED is when you would give a dose

As stated above there is no need for arrays.

Within the program you can directly calculate all the desired dose times or time intervals from a single constant: 86400 seconds per day.

N doses per day would be one dose every 86400/N seconds (multiply by 1000 for milliseconds), etc.

Here's an example of an aquarium doser that works with a pretty extensive menu to let you customize what you want to have happen.

Thanks I will have a look at that. With regards to adapting blink without delay I did look at that but it wont do for my application. I will end up with 6 dosers all individually controlled and most importantly none of them will coincide with each other when dosing in other words there will be a 5 min gap between any dose, hence the idea to tie the dosing into programmes which use time to activate as opposed to millis

I did look at that but it wont do for my application. I will end up with 6 dosers all individually controlled and most importantly none of them will coincide with each other when dosing in other words there will be a 5 min gap between any dose

So, what is the problem ?

At worst you use 6 "timers" as used by BWoD or if the 5 minute gap is fixed then one "timer" and adjust the period according to the required gap

Proietti:
Thanks I will have a look at that. With regards to adapting blink without delay I did look at that but it wont do for my application. I will end up with 6 dosers all individually controlled and most importantly none of them will coincide with each other when dosing in other words there will be a 5 min gap between any dose, hence the idea to tie the dosing into programmes which use time to activate as opposed to millis

You’ve misunderstood something. What you describe is perfect for the BWoD style timing. Definitely no reason to keep track of a bunch of times you could easily calculate.

The code I have works a little differently. It enforces a minimum time gap between doses but if a dose is missed for whatever reason (power goes out for a little while it something) then it will come back and catch back up on the next dose.

It also enforces a minimum set time between alkalinity and calcium dosing so you don’t dump them in on top of one another and get a precipitation.

Basically it tracks how much it has already dosed today, looks at the time and the interval to calculate how many doses it has left to make today, and then divides that total amount to dose into the total number of doses left to get how much to dose on this particular dose.

The next step was to make it so that all you had to do was put in your test results and it would calculate the dosing for you. But alas we moved and my tank came down.

This kind of thing easily handles 1, 2, 3... 44, 45, 46, 47, 48... feedings a day.

void loop()
{
  unsigned long interval =  (24UL * 60UL * 60UL * 1000UL) / FeedingsPerDay;
  static unsigned long lastFeedingTime;
  unsigned long currentTime = millis();
  if (currentTime - lastFeedingTime >= interval)
  {
    // Time for a feeding!

    // NOTE: This would normally be "lastFeedingTime += interval;" which works best when the
    // interval is fixed.  In this case if you were three hours into a long interval and change the feeding 
    // rate to 24 per day (one per hour) the feeder would feed three times immediately.  I think it is 
    // safer to feed once now and again in an hour.
    lastFeedingTime = currentTime;
  }
}