Arduino Forum

Using Arduino => Programming Questions => Topic started by: Proietti on Sep 18, 2019, 01:03 pm

Title: Use of arrays
Post by: Proietti on Sep 18, 2019, 01:03 pm
Hi
I am trying to make a dosing sketch for my aquarium. My issue is as follows:

Code: [Select]

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


Code: [Select]

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);
    }
  }
}


Code: [Select]

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

Code: [Select]

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
Title: Re: Use of arrays
Post by: Danois90 on Sep 18, 2019, 01:07 pm
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.
Title: Re: Use of arrays
Post by: Proietti on Sep 18, 2019, 01:14 pm
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?
Title: Re: Use of arrays
Post by: Danois90 on Sep 18, 2019, 01:22 pm
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.. ;)
Title: Re: Use of arrays
Post by: UKHeliBob on Sep 18, 2019, 01:27 pm
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
Title: Re: Use of arrays
Post by: jremington on Sep 18, 2019, 03:34 pm
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.
Title: Re: Use of arrays
Post by: Delta_G on Sep 18, 2019, 07:03 pm
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. 

https://github.com/delta-G/Disco_Doser (https://github.com/delta-G/Disco_Doser)
Title: Re: Use of arrays
Post by: Proietti on Sep 18, 2019, 07:49 pm
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
Title: Re: Use of arrays
Post by: UKHeliBob on Sep 18, 2019, 07:55 pm
Quote
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
Title: Re: Use of arrays
Post by: Delta_G on Sep 18, 2019, 08:00 pm
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. 

Title: Re: Use of arrays
Post by: johnwasser on Sep 18, 2019, 11:51 pm
This kind of thing easily handles 1, 2, 3... 44, 45, 46, 47, 48... feedings a day.

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