New computer -> issues...

Do you have a question on how to do something.
Ask in here.

Posts: 89
Joined: Thu Mar 08, 2012 5:11 pm
Location: Redwood City, California
PostPosted: Mon Oct 12, 2020 9:24 am
Ahh, thanks for the update.

I saw a lot of references to the web wizard, but I've been out of the loop for over a year... I'll have to give the web wizard a try.

Thanks again for your help!

Best,
Gabe

Posts: 89
Joined: Thu Mar 08, 2012 5:11 pm
Location: Redwood City, California
PostPosted: Wed Oct 14, 2020 10:54 pm
New problem: the custom menu shows a jumbled overlapping combination of all menu options on one line of the RA+ screen. I would upload an image to illustrate the point, but for some reason every time I try it just erases whatever I type here...

I tried reviewing the RA Custom Menus guide made by binder, but to no avail. It seems that must be out of date, and changing my code to match the examples in that guide resulted in failures to compile.

One thing I find suspicious is that my ReefAngel_Features.h file contains the following two lines:
Code: Select all
#define CUSTOM_MENU_ENTRIES 6
#define CUSTOM_MENU_ENTRIES 7

My code actually has 7 menu entries.
If I delete the line with "6" and compile the code again, the line with "6" reappears in my ReefAngel_Features.h file.
If I delete the line with "7" and compile the code again, it does not reappear. However, If I run the CB ReefAngel Process Sketch plugin and then compile, the line with "7" reappears in my features file.
As far as I can tell though, none of this fixes my problem, I just find it strange.

I tried using the webwizard, but it seems that doesn't provide support for custom menus. Also, I was unable to install the webwizard plugin on my computer (at the very end of the process it just says installation failed).

So I'm back to throwing myself upon the mercy of those who understand more about the RA programming and libraries.
My code is below:
Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <ReefAngel.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <RA_CustomLabels.h>
#include <RA_CustomSettings.h>
#include <PH.h>
#include <avr/pgmspace.h>

//Ports assignment:
//First relay box is for the reef system.
//Port1 - Metal Halide Daylights.
#define lights Port1
//Port2 - AWC drain pump.
#define AWCdrain Port2
//Port3 - AWC fill pump.
#define AWCfill Port3
//Port4 - Chiller, feed pump, & exhaust fans.
#define chiller Port4
//Port5 - Clockwise circulation pumps.
#define clockCirc Port5
//Port6 - Counterclockwise circulation pumps.
#define countCirc Port6
//Port7 - ATO pump.
#define ATOPump Port7
//Port8 - Return pump & skimmer pump.
#define returnPump Port8

//Change these values as needed. They are the threshold values for the low and high temperatures, respectively.
int lowTempWarning = 750; //low temp warning below 75F.
int highTempWarning = 800; //high temp warning above 80F.

//These vairable are used to control the ATO system.
static time_t ATOTimer;
int ATOTimeOut = 100;

//The following variables control when automatic water changes occur.
int AWCHour = 12;
int AWCMinute = 0;
char AWCChar[] = "AWC Scheduled: 1200"; //This string will be printed to the display until an AWC is attempted each day.

//These variables will be used to keep track of the progress of an AWC.
int AWCCheck = 0;
boolean AWCFail = false;
boolean drained = false;

//This variable will trigger an AWC().
boolean AWC = false;

//This variable will be set to true if a water change has been done since the last midnight and will be set to false at midnight.
boolean AWCToday = false;

//This vairable will store the current time for comparisons on when to initialize an AWC.
time_t AWCt;

//This variable will be a backup timer for AWC.
static time_t AWCTimer;

//These variables will control how long the AWC pumps should be on (in seconds) in case of float switch failure.
int AWCDrainSecs = 30;
int AWCFillSecs = 30;

//This function will check to make sure the water level in the sump is at the high float before initiating an AWC.
int AWCATOCheck()
{
  if (!ReefAngel.Relay.Status(returnPump))  //If the return pump is not on, don't run an AWC and return 0 (false).
    return 0; //Returning zero here is the only way for AWCCheck to equal 0 while AWC equals true. This will cause the AWC process to pause until the return pump is on again.
 
  if (!ReefAngel.HighATO.IsActive()) //If the water level is not at the maximum normal level, run the ATO.
  {
    ATOTimer = now();
    ReefAngel.Relay.On(ATOPump);  //Fill the return section to the high float with RODI.
    AWCToday = true;
    return 2;
  }
  else
  {
    AWCToday = true;
    return 1;
  }
}

//Custom Menu Code
const unsigned PROGMEM char menu1_label[] = "Feed for 5 Mins";
const unsigned PROGMEM char menu2_label[] = "Start AWC";
const unsigned PROGMEM char menu3_label[] = "Clear Alerts & Vars";
const unsigned PROGMEM char menu4_label[] = "pH Calibration";
const unsigned PROGMEM char menu5_label[] = "Set Date & Time";
const unsigned PROGMEM char menu6_label[] = "Return & Skimmer";
const unsigned PROGMEM char menu7_label[] = "Version";
const unsigned char *menu_items[] = {
menu1_label, menu2_label, menu3_label, menu4_label, menu5_label, menu6_label, menu7_label
};
void MenuEntry1()
{
  ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
  AWCToday = false;
  AWC = true;
}
void MenuEntry3()
{
  //Clear portal variables.
  //ReefAngel.CustomVar[Var_AWCCountTotal] = 0;
  //ReefAngel.CustomVar[Var_AWCCountToday] = 0;
  //ReefAngel.CustomVar[Var_AWCDrainFail] = 0;
  //ReefAngel.CustomVar[Var_AWCFillFail] = 0;
  //ReefAngel.CustomVar[Var_AWCATOFail] = 0;
 
  //Clear AWC control variables.
  AWC = false;
  AWCToday = false;
  AWCFail = false;
  AWCCheck = 0;
 
  //Clear ATO timeout.
  ReefAngel.ATOClear();
  ReefAngel.DisplayMenuEntry("ATO & AWC Variables Cleared");
}
void MenuEntry4()
{
  ReefAngel.StartSetupCalibrateChoicePH();
  ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry5()
{
  ReefAngel.SetupDateTime();
  ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry6()
{
  ReefAngel.WaterChangeModeStart();
}
void MenuEntry7()
{
ReefAngel.DisplayVersion();
}

void DrawCustomMain()
{
  // the graph is drawn/updated when we exit the main menu & when the parameters are saved
  ReefAngel.LCD.DrawDate(6, 120);

  pingSerial();

  byte mainTempColor;
  //To make changes for each temp sensor, change the value of tempColor to be the appropriate color
  if ( ReefAngel.Params.Temp[T1_PROBE] < lowTempWarning ) { mainTempColor = COLOR_CYAN; }
  else if ( ReefAngel.Params.Temp[T1_PROBE] > highTempWarning ) { mainTempColor = COLOR_RED; }
  else { mainTempColor = COLOR_SEAGREEN; }
  //Display the T1 Main System temperature
  int T1y = 66; //Y-position of T1 probe reading.
  ReefAngel.LCD.DrawText(mainTempColor, DefaultBGColor, 5, T1y, "Tank Temp: ");
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T1_PROBE], mainTempColor, 65, T1y, 10);
 
  //Display the T2 Room temperature
  int T2y = 75; //Y-position of T2 probe reading.
  ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 5, T2y, "Room Temp: ");
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T2_PROBE], COLOR_BLACK, 65, T2y, 10);

  /*byte pHColor;
  //Depending upon the pH, change the value of pHColor to be the appropriate color
  if ( ReefAngel.Params.PH < 790 ) { pHColor = COLOR_YELLOW; }
  else if ( ReefAngel.Params.PH > 810 ) { pHColor = COLOR_MAGENTA; }
  else { pHColor = COLOR_SEAGREEN; }
  //Display the pH starting at 88, 74
  ReefAngel.LCD.DrawText(pHColor, DefaultBGColor, 5, 80, "pH: ");
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, pHColor, 30, 80, 100);*/
 
  //Display whether the ATO high float switch is active (float away from wires) or inactive (float close to wires)
  byte floatColor; //Text color for ATO reading.
  int ATOy = 84; //Y-position for ATO reading.
  ReefAngel.LCD.Clear(DefaultBGColor, 0,ATOy, 128,ATOy+7); //Default font size is 5 pixels wide by 8 pixels high.
  if (ReefAngel.HighATO.IsActive() && !ReefAngel.isATOTimeOut())
  {
    floatColor = COLOR_MEDIUMORCHID;
    ReefAngel.LCD.DrawText(floatColor, DefaultBGColor, 5, ATOy, "Water Level Low");
  }
  else if (!ReefAngel.HighATO.IsActive() && !ReefAngel.isATOTimeOut())
  {
    floatColor = COLOR_SEAGREEN;
    ReefAngel.LCD.DrawText(floatColor, DefaultBGColor, 5, ATOy, "Water Level Normal");
  }
  else {ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_RED, 5, ATOy, "ATO Failure");}

  //Display whether an AWC has occurred today, or when today's AWC is scheduled,
  //or that an AWC is in progress, or that an AWC failure has occurred:
  //byte AWCColor; //Text color for AWC info.
  int AWCy = 95; //Y-position for AWC info.
  ReefAngel.LCD.Clear(DefaultBGColor, 0,AWCy, 128,AWCy+7); //Default font size is 5 pixels wide by 8 pixels high.
  if (AWCFail)
  {
    ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_RED, 2, AWCy, "AWC Failure");
  }
  else
  {
    if (AWC)
    {
      ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_YELLOW, 2, AWCy, "AWC In Progress");
    }
    else if (AWCToday)
    {
      ReefAngel.LCD.DrawText(COLOR_GREEN, COLOR_WHITE, 2, AWCy, "AWC Completed Today");
    }
    else {ReefAngel.LCD.DrawText(COLOR_BLUE, COLOR_WHITE, 2, AWCy, AWCChar);}
  }

  //Display relay box 1 ports with status at 12,94
  byte TempRelay = ReefAngel.Relay.RelayData;
  TempRelay &= ReefAngel.Relay.RelayMaskOff;
  TempRelay |= ReefAngel.Relay.RelayMaskOn;
  ReefAngel.LCD.DrawOutletBox(12, 105, TempRelay);
}

void DrawCustomGraph()
{
  //Print "Pringle Lab Reef" at the top of the screen
  ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 18, 2, "Pringle Lab Reef");
  ReefAngel.LCD.DrawGraph(5,13);
}
////// Place global variable code above here


void setup()
{
  InternalMemory.LCDID_write(1);
  ReefAngel.Init();
  ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])), SIZE(menu_items));
  ReefAngel.UseFlexiblePhCalibration();
  ReefAngel.FeedingModePorts = Port5Bit | Port6Bit; // Turn off Ports 5 & 6 (circulation pumps) when Feeding Mode is activated.
  ReefAngel.WaterChangePorts = Port8Bit;  // Turn off port 8 (return & skimmer pumps) when Water Change Mode is activated
  ReefAngel.Relay.On(returnPump); // Turn on return & skimmer pumps.
  //Initialize portal variables.
  //ReefAngel.CustomVar[Var_AWCCountTotal] = 0;
  //ReefAngel.CustomVar[Var_AWCCountToday] = 0;
  //ReefAngel.CustomVar[Var_AWCFillFail] = 0;
  //ReefAngel.CustomVar[Var_AWCDrainFail] = 0;
  //ReefAngel.CustomVar[Var_AWCATOFail] = 0;
  //startupTimer = now();
}

void loop()
{
  //Start an AWC once per day at AWCHour:AWCMinute if an AWC hasn't happened since midnight and there hasn't been an ATO timeout.
  AWCt = now();
  if (!AWCFail && (hour(AWCt) == AWCHour) && (minute(AWCt) == AWCMinute) && !AWCToday && !AWC && !ReefAngel.isATOTimeOut())
  {
    AWC = true;  //Sets the AWC control variable to true.
  }
   
  //Reset the automatic water change variable and AWC and dosing counts every day at midnight.  Also add the day's AWC count to the total AWC count.
  if (hour(AWCt) == 0 && minute(AWCt) == 0 && AWCToday)
  {
    AWCToday = false;
    //ReefAngel.CustomVar[Var_AWCCountTotal] += ReefAngel.CustomVar[Var_AWCCountToday];
    //ReefAngel.CustomVar[Var_AWCCountToday] = 0;
  }
   
  //Start the chain of AWC functions.
  if (AWC && !AWCToday && AWCCheck == 0)
  {
    AWCCheck = AWCATOCheck(); //If AWCATOCheck returns non-zero, it will also set AWCToday to true.
  }
 
  if (AWCCheck == 2)
  {
    if (!ReefAngel.HighATO.IsActive())
    {
      ReefAngel.Relay.Off(ATOPump);
      AWCCheck = 1;
    }
   
    if ((now() - ATOTimer) >= ATOTimeOut)
    {
      ReefAngel.Relay.Off(ATOPump);
      bitSet(ReefAngel.AlertFlags,ATOTimeOutFlag);  //Trigger ATO timeout flag.
      AWCFail = true;
      //ReefAngel.CustomVar[Var_AWCATOFail] = 1;
      AWCCheck = 0;
      AWC = false;
    }
  }
 
  if (AWCCheck == 1 && !ReefAngel.Relay.Status(AWCdrain))
  {
    AWCTimer = now();
    ReefAngel.Relay.On(AWCdrain);
  }
   
  if (ReefAngel.Relay.Status(AWCdrain))
  {
    if (ReefAngel.HighATO.IsActive())
    {
      ReefAngel.Relay.Off(AWCdrain);
      drained = true;
    }
   
    if (now()-AWCTimer >= AWCDrainSecs)
    {
      ReefAngel.Relay.Off(AWCdrain);
      AWCFail = true;
      //ReefAngel.CustomVar[Var_AWCDrainFail] = 1;
      AWCCheck = 0;
      AWC = false;
    }
  }

  if (drained)
  {
    if (!ReefAngel.Relay.Status(AWCfill))
    {
      AWCTimer = now();
      ReefAngel.Relay.On(AWCfill);
    }

    if (ReefAngel.Relay.Status(AWCfill))
    {
      if (!ReefAngel.HighATO.IsActive())
      {
        ReefAngel.Relay.Off(AWCfill);
        drained = false;
        AWC = false;
        AWCCheck = 0;
        //ReefAngel.CustomVar[Var_AWCCountToday] += 1;
      }

      if (now()-AWCTimer >= AWCFillSecs)
      {
        ReefAngel.Relay.Off(AWCfill);
        drained = false;
        AWCFail = true;
        //ReefAngel.CustomVar[Var_AWCFillFail] = 1;
        AWCCheck = 0;
        AWC = false;
      }
    }
  }
 
  //Light Control
  if (ReefAngel.Params.Temp[T1_PROBE] < highTempWarning)
  {
    ReefAngel.StandardLights(lights, 8,00, 18,00); //Lights on at 8 am and off at 6 pm.
  }
 
  //Temp control is handled by the chiller, but it and the lights will be turned off if the temp gets too high.
  if (ReefAngel.Params.Temp[T1_PROBE] >= highTempWarning)
  {
    ReefAngel.Relay.Off(lights);
    ReefAngel.Relay.Off(chiller);
  }
   
  //Wavemaker control
  ReefAngel.WavemakerRandom(clockCirc,30,300); // Turn clockwise circulation pumps on/off random cycles that lasts from 30 to 300 secs.
  ReefAngel.Relay.Set(countCirc,!ReefAngel.Relay.Status(clockCirc)); // Turn counterclockwise circulation pumps on/off on opposite cycle from clockwise circulation pumps.
   
  //ATO
  if (!AWC) {ReefAngel.SingleATO(false, ATOPump, ATOTimeOut, 0);} //Use single high float switch (false = high) for reef ATO with 100 second timeout and no frequency limit.
 
  ReefAngel.ShowInterface();
}

Any help will be much appreciated!

Thank you,
Gabe

Posts: 12713
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Thu Oct 15, 2020 8:58 am
It is due to the changes Arduino updated PROGMEM.
Look at the changes for the IDE here: viewtopic.php?f=7&t=5993
I just tested your code and changed the PROGMEM stuff and it worked fine.
Roberto.

Posts: 89
Joined: Thu Mar 08, 2012 5:11 pm
Location: Redwood City, California
PostPosted: Thu Oct 15, 2020 1:57 pm
Thanks rimai!

It works now. I just needed to change the menu labels and initialization sections to:
Code: Select all
//Custom Menu Code
const unsigned char menu1_label[] PROGMEM = "Feed for 5 Mins";
const unsigned char menu2_label[] PROGMEM = "Start AWC";
const unsigned char menu3_label[] PROGMEM = "Clear Alerts & Vars";
const unsigned char menu4_label[] PROGMEM = "pH Calibration";
const unsigned char menu5_label[] PROGMEM = "Set Date & Time";
const unsigned char menu6_label[] PROGMEM = "Return & Skimmer";
const unsigned char menu7_label[] PROGMEM = "Version";
PROGMEM const char * const menu_items[] = {
menu1_label, menu2_label, menu3_label, menu4_label, menu5_label, menu6_label, menu7_label
};

Code: Select all
//Initialize menu in setup section
for (int a=0;a<SIZE(menu_items);a++)
  {
    ReefAngel.InitMenu(pgm_read_word(&(menu_items[a])),a);
  }


Thanks again,
Gabe
Previous

Return to How do I code ...

Who is online

Users browsing this forum: No registered users and 5 guests