Circles, min/max pde

Requests for new functions or software apps
User avatar
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis
PostPosted: Wed Jan 18, 2012 9:00 pm
I made this menu screen because I liked the view of the outlets to look like the outlet box (so I could label them and remember which was which) and I thought circles would be more appealing. This pde also has the min/max functions to show when the temp and pH peaks. Turns out it's kind of a memory hog, but I thought folks might want to use the circles if they have the space. Can you add the function to the LCD library?
(the temp probes for the room and sump weren't hooked up when I took the picture)

Thanks,
Jon

Here's the pde...
Code: Select all
#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.h>
//Actinic and Daylight PMW are on the LED moonlights
byte ActinicPWMValue=0;
byte DaylightPWMValue=0;
int maxTemp=0;
int minTemp=2000;
int maxPH=0;
int minPH=1000;

time_t tsmax=now();
time_t tsmin=now();
time_t PHmax=now();
time_t PHmin=now();

byte wmport=Port5;
boolean wmdelay=false;
byte wmpulse=0;

#include <avr/pgmspace.h>
// Labels for the web banner
prog_char id_label[] PROGMEM = "jsclownfish";
prog_char probe1_label[] PROGMEM = "Tank";
prog_char probe2_label[] PROGMEM = "Room";
prog_char probe3_label[] PROGMEM = "Sump";
prog_char relay1_label[] PROGMEM = "Heater1";
prog_char relay2_label[] PROGMEM = "Heater2";
prog_char relay3_label[] PROGMEM = "MHalide";
prog_char relay4_label[] PROGMEM = "Actinic";
prog_char relay5_label[] PROGMEM = "WM1";
prog_char relay6_label[] PROGMEM = "WM2";
prog_char relay7_label[] PROGMEM = "Main";
prog_char relay8_label[] PROGMEM = "Fan";
PROGMEM const char *webbanner_items[] = {
    id_label, probe1_label, probe2_label, probe3_label, relay1_label, relay2_label,
   relay3_label, relay4_label, relay5_label, relay6_label, relay7_label, relay8_label};
   
void DrawTime(byte x, byte y, byte FGcolor, byte BGcolor, time_t ts)
{
//byte iTimeHourOffset=0;
    char text[13];
    char temp[]="  ";
    strcpy(text,"");
    //if (iTimeHour>12) iTimeHourOffset=12;
    itoa(hourFormat12(ts),temp,10);
    if (temp[1]==0) strcat(text,"0");
    strcat(text,temp);
    strcat(text,":");
    itoa(minute(ts),temp,10);
    if (temp[1]==0) strcat(text,"0");
    strcat(text,temp);
    strcat(text,":");
    itoa(second(ts),temp,10);
    if (temp[1]==0) strcat(text,"0");
    strcat(text,temp);
    if (isAM(ts))
    {
        strcat(text," AM");
    }
    else
    {
        strcat(text," PM");
    }
    ReefAngel.LCD.DrawText(FGcolor, BGcolor, x, y, text);
}
void DrawCircle(int a, int b, int r, byte color)
//void ReefAngel_NokiaLCD::PutPixel(byte color, byte x, byte y)
{
  int f = 1 - r; 
  int ddF_x = 1; 
  int ddF_y = -2 * r; 
  int x = 0; 
  int y = r;
 
 ReefAngel.LCD.PutPixel(color, a, b+r); 
 ReefAngel.LCD.PutPixel(color ,a, b-r); 
 ReefAngel.LCD.PutPixel(color, a+r, b); 
 ReefAngel.LCD.PutPixel(color, a-r, b);
 while (x<y)
 {   
 if (f >= 0)
 {      y--;
       ddF_y += 2;     
       f += ddF_y;   
   }   
   x++;   
   ddF_x += 2;   
   f += ddF_x;
   
   ReefAngel.LCD.PutPixel(color, a + x, b + y);
   ReefAngel.LCD.PutPixel(color, a - x, b + y);
   ReefAngel.LCD.PutPixel(color, a + x, b - y);
   ReefAngel.LCD.PutPixel(color, a - x, b - y);
   ReefAngel.LCD.PutPixel(color, a + y, b + x);
   ReefAngel.LCD.PutPixel(color, a - y, b + x);
   ReefAngel.LCD.PutPixel(color, a + y, b - x);
   ReefAngel.LCD.PutPixel(color, a - y, b - x);
   }
}
void FillCircle(int a, int b, int r, byte color)

   int f = 1 - r; 
   int ddF_x = 1; 
   int ddF_y = -2 * r; 
   int x = 0; 
   int y = r; 
for (int i=b-r; i<=b+r; i++)
{   
  ReefAngel.LCD.PutPixel(color, a, i); 

while (x<y)
{   
if (f >= 0)
{     
   y--;     
   ddF_y += 2;     
   f += ddF_y;   
}   
   x++;   
   ddF_x += 2;   
   f += ddF_x;     
   for (int i=b-y; i<=b+y; i++)
{     
ReefAngel.LCD.PutPixel(color, a+x, i);     
ReefAngel.LCD.PutPixel(color, a-x, i);   
}     
for (int i=b-x; i<=b+x; i++)
{     
ReefAngel.LCD.PutPixel(color,a+y, i);     
ReefAngel.LCD.PutPixel(color,a-y, i);   
}     
}
}
//circle matched outletbox
void DrawCircleBox (byte x, byte y, byte RelayData)
{
 byte b = 0;
 byte c = 0;
 byte d = 0;
    for (byte a=0;a<2;a++)
      {
        DrawCircle ((a*10)+x,y,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle((a*10)+x,y,3,OutletOnBGColor);
        }
        else
        {
          FillCircle((a*10)+x,y,3,OutletOffBGColor);
        }
      }
   for (byte a=2;a<4;a++)
      {
        b=(a-2)*10;
       DrawCircle (b+x,y+10,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle(b+x,y+10,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(b+x,y+10,3,OutletOffBGColor);
        }
      }
    for (byte a=4;a<6;a++)
      {
        c=(a-4)*10;
       DrawCircle (c+x,y+20,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle(c+x,y+20,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(c+x,y+20,3,OutletOffBGColor);
        }
      }
    for (byte a=6;a<8;a++)
      {
        d=(a-6)*10;
       DrawCircle (d+x,y+30,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle(d+x,y+30,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(d+x,y+30,3,OutletOffBGColor);
        }
      }
}
void DrawCustomMain()
{
// update the min and max temps
if (now()%86400==0)
{
  minTemp=ReefAngel.Params.Temp1;
  maxTemp=ReefAngel.Params.Temp1;
}
if (ReefAngel.Params.Temp1<minTemp)
{
  minTemp=ReefAngel.Params.Temp1;
  tsmin=now();
//  DrawTime(60,33);
}
if (ReefAngel.Params.Temp1>maxTemp)
{
  maxTemp=ReefAngel.Params.Temp1;
  tsmax=now();
//  DrawTime(60,23);
}
DrawTime(60,23,0, COLOR_WHITE,tsmax);
DrawTime(60,33,0,COLOR_WHITE, tsmin);
// update the min and max temps
if (now()%86400==0)
{
  minPH=ReefAngel.Params.PH;
  maxPH=ReefAngel.Params.PH;
}
if (ReefAngel.Params.PH<minPH)
{
  minPH=ReefAngel.Params.PH;
  PHmin=now();
//  DrawTime(60,33);
}
if (ReefAngel.Params.PH>maxPH)
{
  maxPH=ReefAngel.Params.PH;
  PHmax=now();
//  DrawTime(60,23);
}
DrawTime(60,23,0, COLOR_WHITE,tsmax);
DrawTime(60,33,0,COLOR_WHITE, tsmin);
DrawTime(60,55,0, COLOR_WHITE,PHmax);
DrawTime(60,65,0,COLOR_WHITE, PHmin);
// the graph is drawn/updated when we exit the main menu &
// when the parameters are saved
// Display the Tank temperature with color sensors
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,13,"TANK:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp1, COLOR_BLACK, 36, 13, 10);
// Display the Room temperature
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor, 70 ,120,"R00M:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp2, COLOR_BLACK, 100, 120, 10);
// Display the Room temperature
ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor,63,13,"SUMP:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, COLOR_BLACK, 91, 13, 10);
// Display the Room temperature
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,23,"HI:");
ReefAngel.LCD.DrawSingleMonitor(maxTemp, 0, 23, 23, 10);
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,23,"at");
// Display the Sump temperature
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,33,"LO:");
ReefAngel.LCD.DrawSingleMonitor(minTemp, 0, 23, 33, 10);
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,33,"at");
//Display the pH
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 44,"PH:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, 0, 23, 44, 100);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5, 54,"HI:");
ReefAngel.LCD.DrawSingleMonitor(maxPH, 0, 23, 54, 100);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 48, 54,"at");
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 64,"LO:");
ReefAngel.LCD.DrawSingleMonitor(minPH, 0, 23, 64, 100);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 48, 64,"at");
pingSerial();
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,10,78,"Heat1");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,10,88,"MH LT");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,10,98,"WM LT");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,10,108,"MainP");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,80,78,"Heat2");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,80,88,"ActLT");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,80,98,"WM RT");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,80,108,"Fan");
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
DrawCircleBox (55,80,TempRelay);
// ReefAngel.LCD.DrawOutletBox(12, 100, TempRelay);
// the graph is drawn/updated when we exit the main menu &
// when the parameters are saved
ReefAngel.LCD.DrawDate(6, 2);
ReefAngel.LCD.Clear(0, 1, 11, 132, 11);
pingSerial();
}
void DrawCustomGraph()
{
}
void setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  ReefAngel.LoadWebBanner(pgm_read_word(&(webbanner_items[0])), SIZE(webbanner_items));
  ReefAngel.Timer[4].SetInterval(180);  // set interval to 180 seconds
  ReefAngel.Timer[4].Start();
 
  ReefAngel.FeedingModePorts = B00110000;
  ReefAngel.WaterChangePorts = B10110000;
//  ReefAngel.OverheatShutoffPorts = B00000111;
//  ReefAngel.LightsOnPorts = B00001100;
  ReefAngel.Relay.On(Port5);
  ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
  ReefAngel.Timer[1].Start();
  // Ports that are always on
  ReefAngel.Relay.On(Port7);
}
void loop()
{
  // Specific functions
  //1st Heater at 78.8, 2nd Heater at 77.0, MH on at 10AM off at 8PM, Actinics on at 9AM off at 9PM, Fan kicks on at 82.0
  ReefAngel.StandardHeater(Port1,788,792);
  ReefAngel.StandardHeater(Port2,770,792);
  ReefAngel.MHLights(Port3,10,0,20,0,5);
  ReefAngel.StandardLights(Port4,9,0,21,0);
  ReefAngel.StandardFan(Port8,792,820);
  // Wavemaker Code with night option
  if (ReefAngel.Timer[1].IsTriggered() )
  {
    if ((hour() >= 21) || (hour() <= 8)) //from 9p-Midnight
    {  //PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM,
       // byte endPWM, byte Duration, byte oldValue)
      wmpulse=PWMSlope(21,0,8,0,5,30,179,30);
      if (wmdelay)
      {
        ReefAngel.Timer[1].SetInterval(wmpulse);  // WM delay function from 30-170 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.Off(Port5);
        ReefAngel.Relay.Off(Port6);
        if (wmport==Port5) wmport=Port6; else wmport=Port5;
        wmdelay=false;
      }
      else
      {
        ReefAngel.Timer[1].SetInterval(200-wmpulse);  // WM bursts timing from 170-30 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.On(wmport);
        wmdelay=true;
      }
    }
    else
    {
      //8a-10p normal wave settings
      ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
      ReefAngel.Timer[1].Start();
      ReefAngel.Relay.Toggle(Port5);
      ReefAngel.Relay.Toggle(Port6);
    }
  }
  //Using Daylight ATO high signal piezo buzzer when temp exceeds 83F
  //other options are lowATOpin or the LED pins as ReefAngel.PWM.SetDaylight(100); else ReefAngel.PWM.SetDaylight(0);
if (ReefAngel.Params.Temp1>830)
  {
  pinMode(highATOPin,OUTPUT);
  digitalWrite(highATOPin,HIGH);
  }
  else
  {pinMode(highATOPin,OUTPUT);
  digitalWrite(highATOPin,LOW);
  }
    //Moonlight=byte PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, byte endPWM, byte Duration, byte oldValue)
   ReefAngel.PWM.SetActinic(ActinicPWMValue);
   ActinicPWMValue=PWMSlope(7,00,22,0,0,100,60,ActinicPWMValue);
   ReefAngel.PWM.SetDaylight(DaylightPWMValue);
   DaylightPWMValue=PWMSlope(7,00,22,0,0,100,60,DaylightPWMValue);
// Web Banner stuff
    if(ReefAngel.Timer[4].IsTriggered())
    {
        ReefAngel.Timer[4].Start();
        ReefAngel.WebBanner();
    }
    {
  ReefAngel.ShowInterface();
}
}


menu.JPG
menu.JPG (47.37 KiB) Viewed 2981 times

Posts: 12288
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Wed Jan 18, 2012 9:06 pm
That's so cool!! :)
I'm sure we can add circles to the libraries.
Roberto.

Posts: 243
Joined: Thu Sep 01, 2011 8:44 pm
PostPosted: Fri Feb 10, 2012 10:05 pm
Hey, this is great and I am trying to mod your code to fit my outlet box and I am stumped...The way I have my outlet box mounted, the outlets are all the reverse of yours....where in the code would I switch to have all the left hand side outlets be on the right and vice versa? I can figure out how to switch the text, but I can't figure out how to switch the circles...
Thanks
Image
User avatar
Posts: 2747
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Sat Feb 11, 2012 6:54 am
It's in this function:
Code: Select all
//circle matched outletbox
void DrawCircleBox (byte x, byte y, byte RelayData)
{
byte b = 0;
byte c = 0;
byte d = 0;
    for (byte a=0;a<2;a++)
      {
        DrawCircle ((a*10)+x,y,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle((a*10)+x,y,3,OutletOnBGColor);
        }
        else
        {
          FillCircle((a*10)+x,y,3,OutletOffBGColor);
        }
      }
   for (byte a=2;a<4;a++)
      {
        b=(a-2)*10;
       DrawCircle (b+x,y+10,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle(b+x,y+10,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(b+x,y+10,3,OutletOffBGColor);
        }
      }
    for (byte a=4;a<6;a++)
      {
        c=(a-4)*10;
       DrawCircle (c+x,y+20,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle(c+x,y+20,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(c+x,y+20,3,OutletOffBGColor);
        }
      }
    for (byte a=6;a<8;a++)
      {
        d=(a-6)*10;
       DrawCircle (d+x,y+30,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a)
        {
          FillCircle(d+x,y+30,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(d+x,y+30,3,OutletOffBGColor);
        }
      }
}

He draws each row at a time. Draws top row (ports 1 & 2), then 3 & 4, and so forth.

So it sounds like you are wanting to have the ports display like this:
2 1
4 3
6 5
8 7
Instead of:
1 2
3 4
5 6
7 8

Is that correct?
User avatar
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis
PostPosted: Sat Feb 11, 2012 8:13 am
Curt will know better, but I think you just need to change the a++ to a-- so it counts down instead of up at each line of the relay box. You'll also need to add the draw and fill circle functions the draw circle box calls.
-Jon

Posts: 243
Joined: Thu Sep 01, 2011 8:44 pm
PostPosted: Sat Feb 11, 2012 10:16 am
Curt, your right about how I want to have the outlets line up...thanks guys, I will try it later
Image
User avatar
Posts: 2747
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Sat Feb 11, 2012 10:21 am
I'm gonna work up an example code change for you later today when I get home.

Posts: 243
Joined: Thu Sep 01, 2011 8:44 pm
PostPosted: Sun Feb 12, 2012 12:08 pm
Jon,
I tried changing the ++ to -- , but the the code won't upload...it started to the process, then froze...didn't get an error message. I will tinker some more, and in the meantime, I will hold a mirror up to the screen to make the ports be in reverse! LOL
Image
User avatar
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis
PostPosted: Sun Feb 12, 2012 4:33 pm
After I thought about it a bit, that was too simple. I'll try to change the code a bit to see if I can switch it over. I think I was using the outlet number to direct position and relay status on the display. I'll think on it a bit if Curt doesn't already have a solution.

-Jon
User avatar
Posts: 2747
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Sun Feb 12, 2012 4:42 pm
I haven't coded a solution yet. I thought I was going to get to it yesterday but didn't. It's not just as simple as using -- instead of ++. You still have to keep the same order of logic for displaying them because of the spacing and alignment. The main thing you have to focus on is flipping the bitwise comparison.

Here's a quick flipping of things. It "should" work but I have not tested it out. I trimmed down the number of variables used and cleaned up a couple things.
Code: Select all
//circle matched outletbox
void DrawCircleBox (byte x, byte y, byte RelayData)
{
byte a = 0;
byte b = 0;
byte c = 0;
    for (a=0,c=1;a<2;a++,c--)
      {
// 0 & 1
        DrawCircle ((a*10)+x,y,5,COLOR_BLACK);
        if ((RelayData&(1<<c))==1<<c)
        {
          FillCircle((a*10)+x,y,3,OutletOnBGColor);
        }
        else
        {
          FillCircle((a*10)+x,y,3,OutletOffBGColor);
        }
      }
   for (a=2,c=3;a<4;a++,c--)
      {
// 2 & 3
        b=(a-2)*10;
       DrawCircle (b+x,y+10,5,COLOR_BLACK);
        if ((RelayData&(1<<c))==1<<c)
        {
          FillCircle(b+x,y+10,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(b+x,y+10,3,OutletOffBGColor);
        }
      }
    for (a=4,c=5;a<6;a++,c--)
      {
// 4 & 5
        b=(a-4)*10;
       DrawCircle (b+x,y+20,5,COLOR_BLACK);
        if ((RelayData&(1<<c))==1<<c)
        {
          FillCircle(b+x,y+20,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(b+x,y+20,3,OutletOffBGColor);
        }
      }
    for (a=6,c=7;a<8;a++,c--)
      {
// 6 & 7
        b=(a-6)*10;
       DrawCircle (b+x,y+30,5,COLOR_BLACK);
        if ((RelayData&(1<<c))==1<<c)
        {
          FillCircle(b+x,y+30,3,OutletOnBGColor);
        }
        else
        {
          FillCircle(b+x,y+30,3,OutletOffBGColor);
        }
      }
}

You are still drawing things in the same order but the only difference is you are checking the status of the last port first and updating the first circle with that, then proceeding onward.
Next

Return to Requests

Who is online

Users browsing this forum: No registered users and 1 guest

cron