Auxilliary LCD monitor

rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

Yes, just 4 lines.
The pinout of the HDDB15 is:
1-Relay1
2-Relay3
3-Relay5
4-Relay7
5-Relay8
6-Relay2
7-Relay4
8-Relay6
9-Not Connected
10-GND
11-Actinic PWM
12-Daylight PWM
13-SDA
14-SCL
15-+5VDC
So, all you need is make a cable and connect the SDA to D- and SCL to D+ and the power lines (VCC and GND)
Check D- and D+ pinout here:
http://pinouts.ru/Slots/USB_pinout.shtml
Roberto.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Thanks Roberto. I used the same USB pinouts on the sound board I made to link as a module, but the HDDB15 pinout is helpful. Thanks. When I was asking about 4 lines, I was thinking you could upload code into the temp port connector, but I think that is just for power you still have to connect the TTL serial cable to load code right?

-Jon
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

Correct. Just power.
You still need the USB-TTL cable to upload the code.
Roberto.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Roberto,

Your suggestion seems to work great. :D I made a cable last night and gave it a try. Curiously, the auxillary monitor doesn't seem to sleep, but the main does. I thought it was the Refresh function, but if that is removed the auxillary keeps resetting over and over again.
2screen.JPG
2screen.JPG (124.6 KiB) Viewed 5300 times
-Jon
Deckoz2302
Posts: 149
Joined: Tue Nov 01, 2011 11:05 am

Re: Auxilliary LCD monitor

Post by Deckoz2302 »

I got second screen envy....
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

That's so cool!!! :D
Roberto.
Deckoz2302
Posts: 149
Joined: Tue Nov 01, 2011 11:05 am

Re: Auxilliary LCD monitor

Post by Deckoz2302 »

indeed....so roberto how much for that prototype hahaha
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

He actually has one of the RA+ boards :)
RA+ has an ATMega2560 chip, which has 256K of flash memory and 8K of RAM.
Plenty of memory to load all features and not have to worry about code size.
I have 2 more. PM me if you are interested :)
Roberto.
Deckoz2302
Posts: 149
Joined: Tue Nov 01, 2011 11:05 am

Re: Auxilliary LCD monitor

Post by Deckoz2302 »

Oh I know that's a ra & ra+ ...I'm talking about your project on hold prototype hahaha...really though jsclownfish this is an awesome breakthrough using a 2nd arduino board(ra)
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Thanks! :D It doesn't really require an RA+ but it will require either a second main board or a second LCD connected to an Arduino controller.

I had an idea today. Since the joystick is there and the auxLCD is only for display purposes, I might be able to toggle between two screen formats to show more data. My hope was to use the joystick to trigger it, but a simple delay between screens would be OK. The problem is that using any delay or this code...

Code: Select all

bool bDone = false;
do
{
// wait indefinitely for a button press
delay(200);
if ( ReefAngel.Joystick.IsButtonPressed() )
{
bDone = true;
}
} while ( ! bDone );
  // Tell the controller to cleanup and return to the main screen
  //ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
// To return to the menu instead, comment out the above line and use
// this line instead
Soundsend (11,100);
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
causes the screen to reset and the alert light to blink. At best I could change a little bit temporarily on the joystick button press function alone. Any ideas why it is resetting? I tried the clearscreen function and the refresh function as well. Same issue.

Thanks for your help,
Jon
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

It's the WDT that is kicking in.
You need this:

Code: Select all

wdt_reset();
The WDT needs to receive a reset within 1 second. If it doesn't receive the signal, it will assume that something is wrong and will reset to prevent lockup.
Roberto.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

yep, that did the trick. :) (I just removed that from the features file) The screens switch over nicely now on the press of the button. I still however can't get the data to refresh once I've entered the loop. I have a similar issue with the custom data screens. http://forum.reefangel.com/viewtopic.php?f=12&t=645 I tried to simply copy the void receiveEvent function in the loop, but couldn't get that to work. :?

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>
//#include <avr/wdt.h>

int maintemp=800;
int roomtemp=780;
int sumptemp=780;
int ph=700;
byte TempRelay =15;
byte TempRelay2=15;

void DrawCircle(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;
  
 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);    
}      
}
}
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 setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  Wire.begin(10); // I2C address 8
  Wire.onReceive(receiveEvent);
}
void loop()
{
  ReefAngel.Refresh();
  ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
  ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
  // Display Temp Text
  ReefAngel.LCD.DrawLargeText(0,255,30,15,"Tank Temp", Font8x8);
  
  // Display the T1 temp value 10,22 
   char text[7];
   ConvertNumToString(text, maintemp, 10);
   ReefAngel.LCD.Clear(255, 0, 25, 50, 60);
  if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
  else if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
  else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
  //pingSerial();
  
  // Display pH Text
  ReefAngel.LCD.DrawLargeText(0,255,85,85,"pH", Font8x8);
  
  // Display pH Value
  ConvertNumToString(text, ph, 100);
  ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (ph>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (ph>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
 
  // Display Sump Temp
  ReefAngel.LCD.DrawLargeText(0,255,8,50,"Sump Temp", Font8x8);
  ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
  ConvertNumToString(text, sumptemp, 10);
  ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);

 
  // Display Daylight Percentage Text
  ReefAngel.LCD.DrawLargeText(0,255,8,60,"Room Temp", Font8x8);
  ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
  ConvertNumToString(text, roomtemp, 10);
  ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8);

TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;  
DrawCircleBox (10,90,TempRelay);
DrawCircleBox (40,90,TempRelay2);
//****************************************************************************************
if ( ReefAngel.Joystick.IsButtonPressed() )
{  
  ReefAngel.Refresh();
  ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
  ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
  // Display Temp Text
  ReefAngel.LCD.DrawLargeText(0,255,30,15,"Tank Temp", Font8x8);
  
  // Display the T1 temp value 10,22 
   char text[7];
   ConvertNumToString(text, ph, 10);
   ReefAngel.LCD.Clear(255, 0, 25, 50, 60);
  if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
  else if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
  else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
  //pingSerial();
  
  // Display pH Text
  ReefAngel.LCD.DrawLargeText(0,255,85,85,"pH", Font8x8);
  
  // Display pH Value
  ConvertNumToString(text, maintemp, 100);
  ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (maintemp>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (maintemp>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
 
  // Display Sump Temp
  ReefAngel.LCD.DrawLargeText(0,255,8,50,"Pump Flow", Font8x8);
  ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
  ConvertNumToString(text, sumptemp, 10);
  ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);

 
  // Display Daylight Percentage Text
  ReefAngel.LCD.DrawLargeText(0,255,8,60,"Lux Level", Font8x8);
  ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
  ConvertNumToString(text, roomtemp, 10);
  ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8);

TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;  
DrawCircleBox (10,90,TempRelay);
DrawCircleBox (40,90,TempRelay2);
}
bool bDone = false;
do
{
// wait indefinitely for a button press
delay(200);
if ( ReefAngel.Joystick.IsButtonPressed() )
{
bDone = true;
}
} while ( ! bDone );
}
void receiveEvent(int howMany) 
{
  if (howMany==13)  // Our custom protocol is 13 bytes
  {
    byte cmd1, cmd2, cmd3, cmd4, cmd5, cmd6, cmd7, cmd8, cmd9, cmd10, cmd11,cmd12,cmd13;
      cmd1=Wire.receive();
      cmd2=Wire.receive();
      cmd3=Wire.receive();
      cmd4=Wire.receive();
      cmd5=Wire.receive();
      cmd6=Wire.receive();
      cmd7=Wire.receive();
      cmd8=Wire.receive();
      cmd9=Wire.receive();
      cmd10=Wire.receive();
      cmd11=Wire.receive();
      cmd12=Wire.receive();
      cmd13=Wire.receive();
    if (cmd1=='$' && cmd2=='$' && cmd3=='$') // the first 3 bytes of the custom protocol are $$$ to ensure it's coming from RA
    {

    maintemp=(cmd4<<8)+cmd5;
    sumptemp=(cmd6<<8)+cmd7;
    roomtemp=(cmd8<<8)+cmd9;
    ph=(cmd10<<8)+cmd11;
    TempRelay=cmd12;
    TempRelay2=cmd13;
    }
  }
  else
    for (int a=0;a<howMany;a++)
      Wire.receive(); // if the number of bytes is not 13, discard everything
}
Thanks for your help,
Jon
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

I think you are entering into a loop that doesn't do anything:

Code: Select all

while ( ! bDone );
This will do nothing until you press the joystick.
My suggestion is instead of use the button press, use the navigation up and down or left and right to increment or decrement a global variable.
Then all you have to do is draw the screen for whatever value this variable is holding. This way you can have as many screen as you want.
Something like this:

Code: Select all

#define NumScreens 2
int ScreenID=0;

void setup()
{
}

void loop()
{
  if (ReefAngel.Joystick.IsLeft() || ReefAngel.Joystick.IsDown()) ScreenID--;
  if (ReefAngel.Joystick.IsRight() || ReefAngel.Joystick.IsUp()) ScreenID++;
  if (ScreenID<0) ScreenID=NumScreens;
  if (ScreenID>=NumScreens) ScreenID=0;
  switch (ScreenID)
  {
    case 0:
    {
      // Draw Screen 0
      break;
    }
    case 1:
    {
      // Draw Screen 1
      break;
    }
  }
}
Roberto.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Thanks, I'll given that a try. The loop was something I borrowed from the custom menus so I push the button to switch screens and it stays there until I push it again to go back. The problem then is that it waits on the second screen but isn't receiving data until it exits back to the first screen once the button is pushed again. I was trying to find a way to keep receiving data while in the loop. I was thinking that switch case functions with the wire receive in each case (screen) could work.

I'll let you know how it goes. :)

-Jon
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Wow, that works great! :D I can switch data screens and the data keeps updating nicely. Now I'm dreaming about all the different screens I could display. 8-) I need to work out how to update between screens though. As long as the format is the same and writes over the last screen it works. But if it is a different format and I try to clear the screen, the loop causes the screen to look like it is flashing.

-Jon
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

Use this instead:

Code: Select all

  if (ReefAngel.Joystick.IsLeft() || ReefAngel.Joystick.IsDown())
  {
    ReefAngel.LCD.ClearScreen(DefaultBGColor);
    ScreenID--;
  }
  if (ReefAngel.Joystick.IsRight() || ReefAngel.Joystick.IsUp())
  {
    ReefAngel.LCD.ClearScreen(DefaultBGColor);
    ScreenID--;
  }
That will only clear the screen when you move the joystick .
Roberto.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Outstanding! :D

This is so cool! I hadn't really envisioned this aspect of having an auxillary monitor that doesn't bear the weight of the other controller functions. I was messing around with it today and put this group of screens together. It easily moves from one to the next and keeps the data updating. (since I don't have all the sensors hooked up on these there are some of the 0's or Errors on the display)
Check it out....
Screens.jpg
Screens.jpg (44.36 KiB) Viewed 4846 times
Now I'm looking forward to really thinking about what each screen should look like and how to display the data. That should keep me busy for awhile. :twisted:

Thanks for all the help!
-Jon

For anyone interested, here is the pde as well...

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>
//#include <avr/wdt.h>
//screen set-up
#define NumScreens 5
int ScreenID=0;
//define for data over I2C
int maxTemp=0;
int minTemp=2000;
int maintemp=800;
int roomtemp=780;
int sumptemp=780;
int ph=700;
byte TempRelay =15;
byte TempRelay2=15;
//time stamp
time_t tsmax=now();
time_t tsmin=now();
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)
{
  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);    
}      
}
}
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 setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  Wire.begin(10); // I2C address 10
  Wire.onReceive(receiveEvent);
  ReefAngel.Timer[LCD_TIMER].SetInterval(120);
  ReefAngel.Timer[LCD_TIMER].Start();  // start timer
}
void loop()
{
  if ( ReefAngel.Timer[LCD_TIMER].IsTriggered() )  // process screensaver timeout
	{// Screensaver timeout expired
	ReefAngel.LCD.BacklightOff();
	}
  if ( ReefAngel.Joystick.IsButtonPressed())
	{// turn the backlight on
	ReefAngel.LCD.BacklightOn();
        }
  // TODO check Timer[LCD_TIMER] code
  if ( ReefAngel.Timer[LCD_TIMER].Trigger == 0 )
	{
	ReefAngel.Timer[LCD_TIMER].Start();
	return;
	}// update the min and max temps
  if (now()%86400==0)
  {
    minTemp=maintemp;
    maxTemp=maintemp;
  }
  if (maintemp<minTemp) 
  {
    minTemp=maintemp;
    tsmin=now();
  //  DrawTime(60,33);
  }
  if (maintemp>maxTemp) 
  {
    maxTemp=maintemp;
    tsmax=now();
  }
  if (ReefAngel.Joystick.IsLeft() || ReefAngel.Joystick.IsDown()) 
  {
    ReefAngel.ClearScreen(DefaultBGColor);
    ScreenID--;
  }
  if (ReefAngel.Joystick.IsRight() || ReefAngel.Joystick.IsUp()) 
    {
    ReefAngel.ClearScreen(DefaultBGColor);
    ScreenID++;
    }
  if (ScreenID<0) ScreenID=NumScreens;
  if (ScreenID>=NumScreens) ScreenID=0;
  switch (ScreenID)
  {
  case 0:  //Initial first screen
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#1", Font8x8);
    // Display Temp Text
    ReefAngel.LCD.DrawLargeText(0,255,30,15,"Tank Temp", Font8x8);
    // Display the T1 temp  
    char text[7];
    ConvertNumToString(text, maintemp, 10);
    ReefAngel.LCD.Clear(255, 35, 25, 50, 60);
    if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
    else if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
    // Display pH Text
    ReefAngel.LCD.DrawLargeText(0,255,82,85,"  pH  ", Font8x8);
    // Display pH Value
    ConvertNumToString(text, ph, 100);
    ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (ph>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (ph>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
    // Display Sump Temp
    ReefAngel.LCD.DrawLargeText(0,255,8,50,"Sump Temp", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
    ConvertNumToString(text, sumptemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);
    // Display Room Temp
    ReefAngel.LCD.DrawLargeText(0,255,8,60,"Room Temp", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
    ConvertNumToString(text, roomtemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (10,90,TempRelay);
    DrawCircleBox (40,90,TempRelay2);
    break;
  case 1:  //same as first screen with position changes
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#2", Font8x8);
    // Display Temp Text
    ReefAngel.LCD.DrawLargeText(0,255,30,15,"   pH    ", Font8x8);
    // Display the T1 temp 
    ConvertNumToString(text, ph, 100);
    ReefAngel.LCD.Clear(255, 35, 25, 50, 60);
    if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
    else if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
    // Display pH Text
    ReefAngel.LCD.DrawLargeText(0,255,82,85,"Tank", Font8x8);  
    // Display pH Value
    ConvertNumToString(text, maintemp, 10);
    ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (maintemp>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (maintemp>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
    // Display Flow
    ReefAngel.LCD.DrawLargeText(0,255,8,50,"Pump Flow", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
    ConvertNumToString(text, sumptemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);
    // Display light level 
    ReefAngel.LCD.DrawLargeText(0,255,8,60,"Lux Level", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
    ConvertNumToString(text, roomtemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (10,90,TempRelay);
    DrawCircleBox (40,90,TempRelay2);
    break;
  case 2:  //Temperature detail screen with sump and room temp, 24 hr. max/min, time stamps, and graph
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#3", Font8x8);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,33,"TANK:");
    ReefAngel.LCD.DrawSingleMonitor(maintemp, COLOR_BLACK, 36, 33, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,43,"HI:");
    ReefAngel.LCD.DrawSingleMonitor(maxTemp, 0, 23, 43, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,43,"at");
    DrawTime(60,43,0, COLOR_WHITE,tsmax);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,53,"LO:");
    ReefAngel.LCD.DrawSingleMonitor(minTemp, 0, 23, 53, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,53,"at");
    DrawTime(60,53,0,COLOR_WHITE, tsmin);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,63,"Range:");
    ReefAngel.LCD.DrawSingleMonitor((maxTemp-minTemp), COLOR_BLACK, 46, 63, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,66,63,"degreesF");
    ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor, 5 ,73,"R00M:");
    ReefAngel.LCD.DrawSingleMonitor(roomtemp, COLOR_BLACK, 36, 73, 10);
    ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor, 5, 83,"SUMP:");
    ReefAngel.LCD.DrawSingleMonitor(sumptemp, COLOR_BLACK, 36, 83, 10);
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#3", Font8x8);
    break;
 case 3:  //relay box key
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#4", Font8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (56,46,TempRelay);
    ReefAngel.LCD.DrawLargeText(0,255,27,20,"RelayBox 1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44,"Heat1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"MH LT", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"WaveR", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,74,"MainP", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,44,"Heat2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,54,"StdLT", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,64,"WaveL", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,74,"Fans", Font8x8);
    break;
  case 4:  //relay box key
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#5", Font8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (56,46,TempRelay2);
    ReefAngel.LCD.DrawLargeText(0,255,27,20,"RelayBox 2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44,"Dose1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"Dose2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"WaveA", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,74,"  PO4", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,44,"OPEN1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,54,"OPEN2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,64,"Wave2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,74,"OPEN3", Font8x8);
    break;
}
}
void receiveEvent(int howMany) 
{
  if (howMany==13)  // Our custom protocol is 13 bytes
  {
    byte cmd1, cmd2, cmd3, cmd4, cmd5, cmd6, cmd7, cmd8, cmd9, cmd10, cmd11,cmd12,cmd13;
      cmd1=Wire.receive();
      cmd2=Wire.receive();
      cmd3=Wire.receive();
      cmd4=Wire.receive();
      cmd5=Wire.receive();
      cmd6=Wire.receive();
      cmd7=Wire.receive();
      cmd8=Wire.receive();
      cmd9=Wire.receive();
      cmd10=Wire.receive();
      cmd11=Wire.receive();
      cmd12=Wire.receive();
      cmd13=Wire.receive();
    if (cmd1=='$' && cmd2=='$' && cmd3=='$') // the first 3 bytes of the custom protocol are $$$ to ensure it's coming from RA
    {

    maintemp=(cmd4<<8)+cmd5;
    sumptemp=(cmd6<<8)+cmd7;
    roomtemp=(cmd8<<8)+cmd9;
    ph=(cmd10<<8)+cmd11;
    TempRelay=cmd12;
    TempRelay2=cmd13;
    }
  }
  else
    for (int a=0;a<howMany;a++)
      Wire.receive(); // if the number of bytes is not 13, discard everything
}
psyrob
Posts: 247
Joined: Thu Sep 01, 2011 8:44 pm

Re: Auxilliary LCD monitor

Post by psyrob »

I am assuming that you can only do this with an second aurdino board and second lcd screen? Or can you use the multiple screens if you only have one controller?
Image
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Yep, you are correct. The second LCD needs another processor to receive and display the information.
-Jon
rossbryant1956
Posts: 471
Joined: Sat Jan 14, 2012 2:08 pm
Location: Montgomery Village, MD

Re: Auxilliary LCD monitor

Post by rossbryant1956 »

jsclownfish wrote:I also have trouble with the temp connectors getting them off and on without messing them up. -Jon
I do as well. I killed a temp extension cable this weekend doing this. Roberto, is there some secret to this problem? Thx in advance.

Ross
Roscoe's Reefs - Starting Over Again:

Building new 29g Nano after landlord went berserk over my 4 75 gallon tanks, Multiple RA's, Water mixing stations, etc. Your help welcomed in remembering all I've forgotten.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

You can try filing the connector so it doesn't get caught so tight or pull the connector and not the cable.
Roberto.
User avatar
Xender
Posts: 105
Joined: Sun Mar 20, 2011 12:38 am
Location: France

Re: Auxilliary LCD monitor

Post by Xender »

Can we have more pictures of your multiple display? I mean how do you connect everythings? ;-)
Thx and good work !
I hope We will have touch screen in the future ^^ !
Fresh Water Aquarium 180*60*80
Salt Water Aquarium 60*60*60
Click Here to see the Video of my Fresh Water Aquarium
Image
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: Auxilliary LCD monitor

Post by TanksNStuff »

Sorry for minor derail, but seems a few people here are having a problem with this...

For removing the temp connectors without damaging the wires, I've been using a pair of needle nose pliers to grab the plastic connector on the top and bottom edges... then remove it by wiggling up and down (carefully). This seems to have been working for me.

As for the multi-screen display on auxilliary monitor... wow, that's brilliant. Since I replaced my board with the RA+, I have a spare that I could consider toying with this idea. I'd love to see some pics of how you connected them too, and a list of any parts you used to do this.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

I'll post some pics soon, the only 'extra' hardware is a main head unit RA+ connected to the original RA (same enclosure and all). The one piece of DIY, is the cable. I spliced an old serial cable and USB cable together according to the pinout Roberto advised here, http://forum.reefangel.com/viewtopic.ph ... 2&start=10. You only need 4 of the wires from the serial connection (on the auxillary) to connect to a USB line for I2C communication.

The serial HDDB15 pins needed are:
10-GND
13-SDA
14-SCL
15-+5VDC

These then connect to the USB locations here: http://pinouts.ru/Slots/USB_pinout.shtml

I needed a conductivity meter to make sure I had the right pins and wires.

-Jon


I too use a needle nose pliers but have had mixed results and damaged a few cables in the process :( . I've since learned to be very careful with these.
psyrob
Posts: 247
Joined: Thu Sep 01, 2011 8:44 pm

Re: Auxilliary LCD monitor

Post by psyrob »

Jon: Did you ever post pics on your set up somewhere on the forums? I just ordered a RA+ upgrade board and now of course I am interested in using the old board like you have here....Seeing your connections would help me figure if I have enough "tech potential" to pull it off! thanks
Rob
Image
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

I'm not sure what your looking for in the way of pictures. The only thing I had to set up to make it work was the DIY cable above. Let me know and I can try to take a picture.

Jon
psyrob
Posts: 247
Joined: Thu Sep 01, 2011 8:44 pm

Re: Auxilliary LCD monitor

Post by psyrob »

Well, just a pic of the controllers connected together, so we can see what is connected to what, and how you have this all mounted and placed in your system...

Oh, and was it hard in making the pde to ido file switch? Did you have to change any code in the switch over, or is what you have posted in this thread still working?


Thanks
Image
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

You can see pictures of the code and the set-up here http://forum.reefangel.com/viewtopic.php?f=11&t=923, and here it is on the tank.
Picture1.jpg
Picture1.jpg (99.37 KiB) Viewed 5533 times

Not terribly exciting, but you can see I use one of those car mobile phone holders for the main controller in the stand and I have the 2nd unit attached with velcro to the outside of the stand. That let's me pull it off and look at the different screens a bit more easily. You can't see the expansion unit in the picture, but it is next to the one you can see on the side wall of the stand. Lastly, you'll also notice the back-up power supply to notify me if the power goes out. I used this method http://forum.reefangel.com/viewtopic.php?f=2&t=1239and it seems to work well.

-Jon
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

Here are my latest ino files:

Here is the latest code for the main.

Code: Select all

/* Main ReefAngelPlus controller with communication for sound,
auxillary monitor, I/O expansion, and extra relaybox, send master time,
flow, buzzer, overflow and reservoir alarms on the I/O

The following features are enabled for this File: 
#define DisplayImages
#define SetupExtras 
#define DateTimeSetup
#define VersionMenu
#define DisplayLEDPWM
#define wifi
#define RelayExp
#define WDT
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 9
#define CUSTOM_MAIN
#define COLORS_PDE
#define FONT_8x8
#define NUMBERS_8x8
#define CUSTOM_VARIABLES
*/


#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 <IO.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <avr/pgmspace.h>

//Actinic and Daylight PMW are on the LED moonlights
byte ActinicPWMValue=0;
byte DaylightPWMValue=0;
byte MoonPWMValue;
byte Sound;
int maxTemp=0;
int minTemp=2000;
int maxPH=0;
int minPH=1000;
int flow =0;
int maxflow=0;
int minflow=1000;

//timestamp
time_t mastertime=now();
time_t tsmax=now();
time_t tsmin=now();
time_t PHmax=now();
time_t PHmin=now();
time_t flowmax=now();
time_t flowmin=now();

// Moon Global Variables - Thanks Deckoz2302!
byte ThisPhase;
double AG;
double IP;
long YY, MM, K1, K2, K3, JD;

//wire.write variable number
byte param[2];

//wavemaker dalay variables
byte wmport=Port5;
boolean wmdelay=false;
byte wmpulse=0;

//time variables for time between sounds
long previousMillis = 0;    
long interval = 5000;      // interval at which a sound can play (milliseconds)

//varibles for input module data
byte IOIn[10];
int Flow0;
int Flow1;
int Flow2;
byte buzz = 1;
byte Overflow = 0;
byte Reservoir = 0;
byte HATO = 0;
byte LATO = 0;
byte wm = 0;
byte level = 0;
byte atos = 0;
byte powerOut;

static int swidth = 90; // change these
static int sheight = 60; // change these

static const prog_int16_t header_data[] PROGMEM = { // add data here
};

void DrawBitmap(int xpos, int ypos) {
int count = 0;
for (int j = 0; j < sheight; j++) {
for (int i = 0; i < swidth; i++) {
ReefAngel.LCD.PutPixel(pgm_read_word_near(header_data + count),xpos+i,ypos+j);
count++;
}
}
}
// Custom Menu Code
prog_char menu1_label[] PROGMEM = "Feeding";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "pH Calibration";
prog_char menu4_label[] PROGMEM = "pH Detail";
prog_char menu5_label[] PROGMEM = "Temp Detail";
prog_char menu6_label[] PROGMEM = "Date / Time";
prog_char menu7_label[] PROGMEM = "Flow Cells";
prog_char menu8_label[] PROGMEM = "Version";
prog_char menu9_label[] PROGMEM = "Sound Bytes";
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label, menu6_label,
menu7_label, menu8_label, menu9_label
};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry4()
{
//pH detail screen with 24 hr. max/min, time stamps, and graph
ReefAngel.ClearScreen(DefaultBGColor);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 13,"PH:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, 0, 36, 13, 100);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5, 23,"HI:");
ReefAngel.LCD.DrawSingleMonitor(maxPH, 0, 23, 23, 100);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 48, 23,"at");
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 33,"LO:"); 
ReefAngel.LCD.DrawSingleMonitor(minPH, 0, 23, 33, 100);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 48, 33,"at");
DrawTime(60,23,0, COLOR_WHITE,PHmax);
DrawTime(60,33,0,COLOR_WHITE, PHmin);
    ReefAngel.LCD.Clear(DefaultBGColor,0,75,131,125);
    ReefAngel.LCD.Clear(DefaultFGColor,1,75,1,125);
    for (byte i=6; i<=131; i+=3)
    {
        ReefAngel.LCD.PutPixel(GraphDotLineColor, i, 100);
    }
ReefAngel.LCD.DrawSingleGraph(PHColor,1,75,InternalMemory.T1Pointer_read()+360);
pingSerial();
bool bDone = false;
do
{
// wait indefinitely for a button press
delay(200);
if ( ReefAngel.Joystick.IsButtonPressed() )
{
bDone = true;
}
} while ( ! bDone );
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry5()
{
//Temperature detail screen with sump and room temp, 24 hr. max/min, time stamps, and graph
ReefAngel.ClearScreen(DefaultBGColor);
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,13,"TANK:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T1_PROBE], COLOR_BLACK, 36, 13, 10);
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,23,"HI:");
ReefAngel.LCD.DrawSingleMonitor(maxTemp, 0, 23, 23, 10);
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,23,"at");
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,33,"LO:");
ReefAngel.LCD.DrawSingleMonitor(minTemp, 0, 23, 33, 10);
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,33,"at");
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor, 5 ,43,"R00M:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T2_PROBE], COLOR_BLACK, 36, 43, 10);
ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor, 5, 53,"SUMP:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T3_PROBE], COLOR_BLACK, 36, 53, 10);
DrawTime(60,23,0, COLOR_WHITE,tsmax);
DrawTime(60,33,0,COLOR_WHITE, tsmin);
    ReefAngel.LCD.Clear(DefaultBGColor,0,75,131,125);
    ReefAngel.LCD.Clear(DefaultFGColor,1,75,1,125);
    for (byte i=6; i<=131; i+=3)
    {
        ReefAngel.LCD.PutPixel(GraphDotLineColor, i, 100);
    }
ReefAngel.LCD.DrawSingleGraph(T1TempColor,1,75,InternalMemory.T1Pointer_read());
ReefAngel.LCD.DrawSingleGraph(T2TempColor,1,75,InternalMemory.T1Pointer_read()+120);
ReefAngel.LCD.DrawSingleGraph(T3TempColor,1,75,InternalMemory.T1Pointer_read()+240);
pingSerial();
bool bDone = false;
do
{
// wait indefinitely for a button press
delay(200);
if ( ReefAngel.Joystick.IsButtonPressed() )
{
bDone = true;
}
} while ( ! bDone );
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry6()
{
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry7()
{
//Flow detail screen with 24 hr. max/min, & time stamps
ReefAngel.ClearScreen(DefaultBGColor);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 13,"FLOW0:");
ReefAngel.LCD.DrawSingleMonitor(Flow1, 0,46,13, 1);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 66, 13,"gal/hr");
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5, 23,"HI:");
ReefAngel.LCD.DrawSingleMonitor(maxflow, 0, 23, 23, 1);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 48, 23,"at");
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 33,"LO:"); 
ReefAngel.LCD.DrawSingleMonitor(minflow, 0, 23, 33, 1);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 48, 33,"at");
DrawTime(60,23,0, COLOR_WHITE,flowmax);
DrawTime(60,33,0,COLOR_WHITE, flowmin);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 43,"FLOW1:");
ReefAngel.LCD.DrawSingleMonitor(Flow2, 0,46,43, 1);
pingSerial();
bool bDone = false;
do
{
// wait indefinitely for a button press
delay(200);
if ( ReefAngel.Joystick.IsButtonPressed() )
{
bDone = true;
}
} while ( ! bDone );
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8()
{
ReefAngel.DisplayVersion();
DrawBitmap(5,60);
}
void MenuEntry9()
{
   Sound++;
   if ( Sound > 9 ) Sound = 1;
//  Sound=random(0,8);
Soundsend(Sound,1);
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 5, 13,"Playing Sound #");
ReefAngel.LCD.DrawSingleMonitor(Sound, 0,90,13, 1);
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 23,"just keep swimming");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 33,"Under the sea");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 43,"anemone");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 53,"H20 intolerant");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 63,"fronds like these");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 73,"Sharkbait");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 83,"Seabirds");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 93,"fish are friends");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor, 5, 103,"Aquascum");
if (Sound==0) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 23,"just keep swimming");
else if (Sound==1) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 33,"Under the sea");
else if (Sound==2) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 43,"anemone");
else if (Sound==3) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 53,"H20 intolerant");
else if (Sound==4) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 63,"fronds like these");
else if (Sound==5) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 73,"Sharkbait");
else if (Sound==6) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 83,"Seabirds");
else if (Sound==7) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 93,"fish are friends");
else if (Sound==8) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor, 5, 103,"Aquascum");
}
void DrawTime(byte x, byte y, byte FGcolor, byte BGcolor, time_t ts)
{
    char text[13];
    char temp[]="  ";
    strcpy(text,"");
    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);
}
//function to backage int into bytes for parameters temp, pH, timers, actinic%)
void paramsend(int a)
{
  param[0]=(byte)(a>>8);
  param[1]=(byte)(a);
  Wire.write(param,2);
}
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);    
}      
}
}
void DrawCustomGraph()
{
}
void DrawCustomMain()
{
  // update the min and max temps
if (now()%86400==0)
{
  minTemp=ReefAngel.Params.Temp[T1_PROBE];
  maxTemp=ReefAngel.Params.Temp[T1_PROBE];
}
if (ReefAngel.Params.Temp[T1_PROBE]<minTemp) 
{
  minTemp=ReefAngel.Params.Temp[T1_PROBE];
  tsmin=now();
}
if (ReefAngel.Params.Temp[T1_PROBE]>maxTemp) 
{
  maxTemp=ReefAngel.Params.Temp[T1_PROBE];
  tsmax=now();
}
// update the min and max pH
if (now()%86400==0)
{
  minPH=ReefAngel.Params.PH;
  maxPH=ReefAngel.Params.PH;
}
if (ReefAngel.Params.PH<minPH) 
{
  minPH=ReefAngel.Params.PH;
  PHmin=now();
}
if (ReefAngel.Params.PH>maxPH) 
{
  maxPH=ReefAngel.Params.PH;
  PHmax=now();
}
if (now()%86400==0)
{
  minflow=flow;
  maxflow=flow;
}
if (flow<minflow) 
{
  minflow=flow;
  flowmin=now();
}
if (flow>maxflow) 
{
  maxflow=flow;
  flowmax=now();
}
// 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();
GetFlow();
// Display the Tank temperature with color sensors
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,13,"TK:");
  if (ReefAngel.Params.Temp[T1_PROBE]>830) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T1_PROBE], COLOR_RED, 23, 13, 10); 
  else if (ReefAngel.Params.Temp[T1_PROBE]>810) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T1_PROBE], COLOR_ORANGE, 23, 13, 10); 
  else ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T1_PROBE], COLOR_BLACK, 23, 13, 10);
  // Display the PH with color sensors
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 64, 13,"PH:");
  if (ReefAngel.Params.PH>840 || ReefAngel.Params.PH<790) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_RED, 82, 13, 100);
  else if (ReefAngel.Params.PH>830 || ReefAngel.Params.PH<800) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_ORANGE, 82, 13, 100);
  else ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, 0, 82, 13, 100);
// Display status of ato's
if (Reservoir == 0)
{
FillCircle(15,26,5,COLOR_RED);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_RED,14,22,"R");
}
else if (Reservoir == 1)
{
FillCircle(15,26,5,COLOR_GREEN);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_GREEN,14,22,"R");
}
if (Overflow == 0)
{
FillCircle(26,26,5,COLOR_GREEN);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_GREEN,23,22,"O");
}
else if (Overflow == 1)
{
FillCircle(26,26,5,COLOR_RED);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_RED,23,22,"O");
}
if (ReefAngel.HighATO.IsActive())
{
HATO = 1;
FillCircle(36,26,5,COLOR_GREEN);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_GREEN,34,22,"H");
}
else
{
HATO = 0;
FillCircle(36,26,5,COLOR_RED);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_RED,34,22,"H");
}
if (ReefAngel.LowATO.IsActive())
{
LATO = 1;
FillCircle(46,26,5,COLOR_RED);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_RED,44,22,"L");
}
else
{
LATO = 0;
FillCircle(46,26,5,COLOR_GREEN);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_GREEN,44,22,"L");
}
// Display the % Moonlight
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 23,"MN:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(), COLOR_BLACK, 82, 23, 1);
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 100, 23,"%");
// Display the Flow 1
ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor,5,33,"FL0:");
ReefAngel.LCD.DrawSingleMonitor(Flow1, COLOR_BLACK, 33, 33, 1);
// Display the Flow 0
ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor,64,33,"FL1:");
ReefAngel.LCD.DrawSingleMonitor(Flow2, COLOR_BLACK, 92, 33, 1);
// moonphase------------------------------------------------------------   
  YY = (year()) - floor((12 - (month())) / 10); 
  MM = (month()) + 9;
  if (MM >= 12)
  {
    MM = MM - 12;
  }
  K1 = floor(365.25 * (YY + 4712));
  K2 = floor(30.6 * MM + 0.5);
  K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;
  JD = K1 + K2 + (day()) + 59;
  if (JD > 2299160)
  {
    JD = JD - K3;
  }
  IP = (JD - 2451550.1) / 29.530588853;
  IP = IP - floor(IP);
  if (IP < 0)
  {
    IP = IP + 1;
  }
  AG = IP*29.53;
  
  if (AG < 1.84) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"New");
  else if (AG < 5.53) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"Waxing Crescent");
  else if (AG < 9.92) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"First Quarter");
  else if (AG < 12.91) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"Waxing Gibbous");   
  else if (AG < 16.61) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"Full");    
  else if (AG < 20.30) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"Waning gibbous");    
  else if (AG < 23.99) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"Last Quarter");    
  else if (AG < 27.68) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"Waning Crescent");    
  else  ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 43,"New") ;  
//temperature room
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,5,53,"RM:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T2_PROBE], COLOR_BLACK, 23, 53, 10);
//temperature sump
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,64,53,"SP:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T3_PROBE], COLOR_BLACK, 82, 53, 10);
// Display arrows for Wavemaker
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 5, 63,"WV:");
  if (bitRead(ReefAngel.Relay.RelayData,Port5-1)==1) ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 23, 63,"-->"); //port 5 on
  else if (bitRead(ReefAngel.Relay.RelayData,Port6-1)==1) ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 23, 63,"<--");  //port 6 on
  else ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 43, 63," O "); //port5 and port 6 off, wavemaker delay
//Timer and trigger to keep wavemaker timing correct after setting date/time
    int t=ReefAngel.Timer[1].Trigger-now();
    if (t>=0)
    {
      ReefAngel.LCD.Clear(255,23,73,53,83);
      ReefAngel.LCD.DrawText(0, DefaultBGColor,23,73,t);
    }
    if (t>300) ReefAngel.Timer[1].ForceTrigger();  
    //wavemakers extra
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 63,"WV:");
  if (bitRead(ReefAngel.Relay.RelayDataE[0],Port5-1)==1) ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 82, 63,"v  "); //port 5 on
  else if (bitRead(ReefAngel.Relay.RelayDataE[0],Port6-1)==1)  ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 82, 63,"  v");  //port 6 on
  else ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 82, 63," O "); //port5 and port 6 off, wavemaker delay
//Timer and trigger to keep wavemaker timing correct after setting date/time
    int u=ReefAngel.Timer[2].Trigger-now();
    if (u>=0)
    {
      ReefAngel.LCD.Clear(255,82,73,112,83);
      if (bitRead(ReefAngel.Relay.RelayDataE[0],Box1_Port5-1)==1 || bitRead(ReefAngel.Relay.RelayDataE[0],Box1_Port6-1)==1)
      {
      ReefAngel.LCD.DrawText(0, DefaultBGColor,82,73,u);
      }
    }
    if (u>300) ReefAngel.Timer[2].ForceTrigger();
//  power status on LCD
if (powerOut)
    {
    ReefAngel.LCD.Clear(255,1,92,102,102);
    ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor,1,92,"BACKUP Power ON");
    }
    else
    {
    ReefAngel.LCD.Clear(255,1,92,102,102);
    ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor,1,92,"Main Power ON");
    }
pingSerial();
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 110, TempRelay);
// draw 1st expansion relay
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 120, TempRelay);
}
void Soundsend(byte x, long y)  //function to play sound and delay before it plays again.
{
  interval = y*100;
  unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > interval) 
      {
      // save the last time you played a sound 
      previousMillis = currentMillis;   
      // if longer than 100 sec than play a sound
         Wire.beginTransmission(9);      // transmit to device #9
         Wire.write('$');         // send the $$$
         Wire.write('$');
         Wire.write('$');
         Wire.write(x);         // send the command
         Wire.endTransmission();      // stop transmitting
        }
}
void setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
  ReefAngel.PHMin=546;
  ReefAngel.PHMax=868;
// Set the ports that get toggled on & off during the following modes
// To enable a port to be toggled, place a 1 in the appropriate position
// Uncomment and update as needed
// Port 87654321
  ReefAngel.FeedingModePorts = B00110000;
  ReefAngel.FeedingModePortsE[1] = B00110100;
  ReefAngel.WaterChangePorts = B10110000;
  ReefAngel.WaterChangePortsE[1] = B11111111;
  // Ports that are always on
  ReefAngel.Relay.On(Port7);  //main pump
  ReefAngel.Relay.On(Box1_Port1); //chiller
  ReefAngel.Relay.On(Box1_Port2); //chiller pump
  ReefAngel.Relay.On(Box1_Port4); //phosban pumpo
// Top smaller pumps once an hour for 5 minutes
  ReefAngel.Relay.On(Box1_Port5);
  ReefAngel.Timer[2].SetInterval(30); 
  ReefAngel.Timer[2].Start();
//Side to side Wavemaker Pumps
  ReefAngel.Relay.On(Port5);
  ReefAngel.Timer[1].SetInterval(200);
  ReefAngel.Timer[1].Start();
}
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);
  ReefAngel.DosingPumpRepeat(Box1_Port7,0,60,4); // Dose for 4 seconds every 60 minutes with 0 minutes offset
  ReefAngel.DosingPumpRepeat(Box1_Port8,5,60,4); // Dose for 4 seconds every 60 minutes with 5 minutes offset
  ReefAngel.CustomVar[1]=Flow0;
  ReefAngel.CustomVar[2]=Flow1;
  ReefAngel.CustomVar[3]=Flow2;
  ReefAngel.CustomVar[6]=buzz;
//Sump refill, check reservoir level first, then standard ATO
  if (Reservoir == 1)
  {
   ReefAngel.StandardATO(Box1_Port3,60);  //Setup relay unit Port3 as Auto Top-Off function with 60s timeout 
  }
 //Alarm state
  if (ReefAngel.Params.Temp[T1_PROBE]>830) 
  {
  buzz = 1;
  }
  else
  {
  buzz = 0;
  }
  GetFlow();
   // 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(200);
      ReefAngel.Timer[1].Start();
      ReefAngel.Relay.Toggle(Port5);
      ReefAngel.Relay.Set(Port6,!ReefAngel.Relay.Status(Port5));
    }
  }
//extra small powerheads to increase circulation once an hour 
//for 5 min during the day
if (hour()>=8 && hour()<=21)
{
    if (minute()<5)
     {
       if (ReefAngel.Timer[2].IsTriggered())
         {
          ReefAngel.Timer[2].SetInterval(30);
          ReefAngel.Timer[2].Start(); 
          ReefAngel.Relay.Toggle(Box1_Port5);
          ReefAngel.Relay.Set(Box1_Port6,!ReefAngel.Relay.Status(Box1_Port5));
         }        
     }
    else
     {
       ReefAngel.Relay.Off(Box1_Port5);
       ReefAngel.Relay.Off(Box1_Port6);
     }
}
else
{
   ReefAngel.Relay.Off(Box1_Port5);
   ReefAngel.Relay.Off(Box1_Port6);
}
//Moonlight
 MoonPWMValue=MoonPhase();
  if (hour()==21 || hour()==8)
     MoonPWMValue=PWMSlope(21,00,9,00,0,MoonPhase(),60,0);
  if (ReefAngel.Relay.Status(Port4)) MoonPWMValue=0;
  ReefAngel.PWM.SetActinic(MoonPWMValue);
  ReefAngel.PWM.SetDaylight(MoonPWMValue);

//I/O module communication
  Wire.beginTransmission(7);      // transmit to device #7
  Wire.write('$');         // send the $$$
  Wire.write('$');
  Wire.write('$');
  Wire.write(buzz);
  Wire.endTransmission();      // stop transmitting  

//Overflow blocked alarm & main pump shut-off, Reservoir alarm
  // Overflow blocked, Reservoir Full
  if (Overflow == 1  && Reservoir == 0) 
   {
     ReefAngel.Relay.Off(Port7);
     ReefAngel.CustomVar[4]=1;  // overflow: 0 good, 1 bad
     ReefAngel.CustomVar[5]=0;  // reservoir: 0 good, 1 bad
     level = 0;
   }
  // Overflow open, Reservoir Full
  else if (Overflow == 0  && Reservoir == 0) 
   {
     ReefAngel.Relay.On(Port7);
     ReefAngel.CustomVar[4]=0;
     ReefAngel.CustomVar[5]=0;
     level = 1;
   }
       // Overflow blocked, Reservoir Empty
  else if (Overflow == 1  && Reservoir == 1) 
   {
     ReefAngel.Relay.Off(Port7);
     ReefAngel.CustomVar[4]=1;
     ReefAngel.CustomVar[5]=1;
     level = 2;
   }
       // Overflow open, Reservoir Empty
  else if (Overflow == 0  && Reservoir == 1) 
   {
     ReefAngel.Relay.On(Port7);
     ReefAngel.CustomVar[4]=0;
     ReefAngel.CustomVar[5]=1;
     level = 3;
   }
//ATO status  
  if (HATO == 1 && LATO == 1) 
   {
     atos = 0;
   }
  else if (HATO == 1 && LATO == 0) 
   {
     atos = 1;
   }
  else if (HATO == 0 && LATO == 1) 
   {
     atos = 2;
   }
  else if (HATO == 0 && LATO == 0) 
   {
     atos = 3;
   } 
 // power sensor with scanner
    powerOut = !ReefAngel.Relay.IsRelayPresent(0);
    // turn off power hogs if the power is out    
    if (powerOut)
    {
    ReefAngel.Relay.Off(Port1);
    ReefAngel.Relay.Off(Port2);
    ReefAngel.Relay.Off(Port3);
    ReefAngel.Relay.Off(Port4);
    ReefAngel.Relay.On(Port5);
    ReefAngel.Relay.Off(Port6);
    ReefAngel.Relay.Off(Port7);
    ReefAngel.Relay.Off(Port8);
    ReefAngel.CustomVar[7]=1;
  }  
  else 
  {
    ReefAngel.CustomVar[7]=0;
  }
//send sound requests
      if (ReefAngel.DisplayedMenu==FEEDING_MODE) Soundsend(7,100);     //feeding time
      if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) Soundsend(8,100);     //feeding time
         
//send data parameter package to the auxillary monitor
         Wire.beginTransmission(10);      // transmit to device #10
         Wire.write('$');         // send the $$$
         Wire.write('$');
         Wire.write('$');
         paramsend(ReefAngel.Params.Temp[T1_PROBE]);
         paramsend(ReefAngel.Params.Temp[T2_PROBE]);
         paramsend(ReefAngel.Params.Temp[T3_PROBE]);
         paramsend(ReefAngel.Params.PH);
         paramsend(ReefAngel.Timer[1].Trigger-now());
         paramsend(ReefAngel.PWM.GetActinicValue());
         Wire.write(level);
         Wire.write(atos);
         Wire.write(ReefAngel.Relay.RelayData);
         Wire.write(ReefAngel.Relay.RelayDataE[0]);
         paramsend(Flow0);
         paramsend(Flow1);
         paramsend(Flow2);
         Wire.write(hour());
         Wire.write(minute());
         Wire.write(second());
         Wire.write(day());
         Wire.write(month());
         paramsend(year());
         Wire.endTransmission();      // stop transmitting
   ReefAngel.Portal("jsclownfish");
   ReefAngel.ShowInterface();
}
void GetFlow()
{
  Wire.requestFrom(7,9);
  if(Wire.available())
  {
    for (int a=0;a<10;a++)
      IOIn[a]=Wire.read();
  }
  Flow0=(IOIn[1]<<8)+IOIn[2];
  Flow1=(IOIn[3]<<8)+IOIn[4];
  Flow2=(IOIn[5]<<8)+IOIn[6];
  Overflow=IOIn[7];
  Reservoir=IOIn[8];
}


I hope this helps. Please let mw know if you need more info as you go.
-Jon
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

and the 2nd RA monitor

Code: Select all

/* Auxillary LCD monitor connected to the ReefAngel Controller (328)
requires a custom cable to connect from I2C main to the serial port

The following features are enabled for this File: 
#define DisplayLEDPWM
#define RelayExp
#define InstalledRelayExpansionModules 1
#define CUSTOM_MAIN
#define COLORS_PDE
#define FONT_8x8
#define NUMBERS_8x8
#define NUMBERS_16x16
*/

#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 <IO.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <avr/wdt.h>
//screen set-up
#define NumScreens 9
int ScreenID=0;
//define for data over I2C
int maxTemp=0;
int minTemp=2000;
int maintemp=800;
int roomtemp=780;
int sumptemp=780;
int ph=700;
int maxPH=600;
int minPH=900;
int moonlight=0;
byte TempRelay =15;
byte TempRelay2=15;
int wavetime=0;
int wavetime2=0;
int flow0=0;
int flow1=0;
int flow2=0;
int wmaker2;
byte mhour;
byte mminute;
byte msecond;
byte mday;
byte mmonth;
int myear;
byte Overflow;
byte Reservoir;
byte LATO;
byte HATO;
byte level;
byte atos;
//Analog Clock constants
    const float pi = 3.141592653;
    byte clock_center_x = 65;
    byte clock_center_y = 65;
    byte clock_radius = 55;
    byte secondhand_radius = 33;
    float secondangle;
    byte secondend_x;
    byte secondend_y;
    float minuteangle;
    float hourangle;
   // Analog Clock Structure
       int minutebase_radius = 3;
       int minutehand_radius = 33;
       int hourbase_radius = 3;
       int hourhand_radius = 25;   
       int seconds_hand_x, seconds_hand_y, minutes_hand_x, minutes_hand_y, hours_hand_x, hours_hand_y;
       int hours_hand_base_x, hours_hand_base_y, hours_hand_base_x1, hours_hand_base_y1;
       int minutes_hand_base_x, minutes_hand_base_y, minutes_hand_base_x1, minutes_hand_base_y1; 
       int minutebase_x, minutebase_y, minutebase_x1, minutebase_y1; 
       int minuteend_x, minuteend_y; 
       int hourbase_x, hourbase_y, hourbase_x1, hourbase_y1; 
       int hourend_x, hourend_y; 
       float minfloat;

//time stamp
time_t tsmax=now();
time_t tsmin=now();
time_t PHmax=now();
time_t PHmin=now();
int mastertime;

// Moon Global Variables - Thanks Deckoz2302!
byte ThisPhase;
double AG;
double IP;
byte MoonPWMValue;
long YY, MM, K1, K2, K3, JD;

// Draw Minutes Hand
void draw_minute(int color)
{
  Drawline(minutebase_x, minutebase_y, minutebase_x1, minutebase_y1, color); 
  Drawline(minutebase_x, minutebase_y, minuteend_x, minuteend_y, color); 
  Drawline(minutebase_x1, minutebase_y1, minuteend_x, minuteend_y, color); 
}
// Draw Hour Hand
void draw_hour(int color)
{
   Drawline(hourbase_x, hourbase_y, hourbase_x1, hourbase_y1, color); 
   Drawline(hourbase_x, hourbase_y, hourend_x, hourend_y, color); 
   Drawline(hourbase_x1, hourbase_y1, hourend_x, hourend_y, color); 
}
void Drawline (int x0, int y0, int x1, int y1, int color) 
{
  int dy = y1 - y0;
  int dx = x1 - x0;
  int stepx, stepy;
  if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
  if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
  dy <<= 1; // dy is now 2*dy
  dx <<= 1; // dx is now 2*dx
  ReefAngel.LCD.PutPixel(color, x0, y0);
  if (dx > dy) {
    int fraction = dy - (dx >> 1); // same as 2*dy - dx
    while (x0 != x1) {
      if (fraction >= 0) {
        y0 += stepy;
        fraction -= dx; // same as fraction -= 2*dx
        }
      x0 += stepx;
      fraction += dy; // same as fraction -= 2*dy
      ReefAngel.LCD.PutPixel(color, x0, y0);
    }
  } else {
  int fraction = dx - (dy >> 1);
  while (y0 != y1) {
  if (fraction >= 0) {
    x0 += stepx;
    fraction -= dy;
    }
  y0 += stepy;
  fraction += dx;
  ReefAngel.LCD.PutPixel(color, x0, y0);
  }
  }}
void DrawTime(byte x, byte y, byte FGcolor, byte BGcolor, time_t ts)
{
    char text[13];
    char temp[]="  ";
    strcpy(text,"");
    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)
{
  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);    
}      
}
}
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+30,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle((a*10)+x,y+30,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle((a*10)+x,y+30,3,OutletOffBGColor);
        }
      }
   for (byte a=2;a<4;a++)
      {
        b=(a-2)*10;
       DrawCircle (b+x,y+20,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle(b+x,y+20,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle(b+x,y+20,3,OutletOffBGColor);
        }
      }
    for (byte a=4;a<6;a++)
      {
        c=(a-4)*10;
       DrawCircle (c+x,y+10,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle(c+x,y+10,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle(c+x,y+10,3,OutletOffBGColor);
        }
      }
    for (byte a=6;a<8;a++)
      {
        d=(a-6)*10;
       DrawCircle (d+x,y,5,COLOR_BLACK);
        if ((RelayData&(1<<a))==1<<a) 
        {
          FillCircle(d+x,y,3,OutletOnBGColor);
        }
        else 
        {
          FillCircle(d+x,y,3,OutletOffBGColor);
    
      }
      }
}
void DrawWeeklyAvg (byte hr, int sensor, byte color, byte x, byte y, byte z)
{
  const int numReadings = 7;
  int dailyread;
  int readings[numReadings];      // the readings from the analog input
  int index = 0;                  // the index of the current reading
  int total = 0;                  // the running total
  int average = 0;                // the average
  if (hour()==hr && minute()==0 && second()==0) 
  {
    dailyread=sensor;  
  total= total - readings[index];   // subtract the last reading:         
  readings[index] = dailyread;   // read from the sensor: 
  total= total + readings[index];   // add the reading to the total:       
     index = index + 1;  // advance to the next position in the array:                   
  if (index >= numReadings)     // if we're at the end of the array...           
    index = 0;       // ...wrap around to the beginning:                         
  average = total / numReadings;    // calculate the average:
  delay (1000);
  ReefAngel.LCD.DrawSingleMonitor(average, color, x, y, z);
  }
}
void DrawDailyAvg (int sensor, byte color, byte x, byte y, byte z)
{
  const int numReadings = 24;
  int dailyread;
  int readings[numReadings];      // the readings from the analog input
  int index = 0;                  // the index of the current reading
  int total = 0;                  // the running total
  int average = 0;                // the average
  if (minute()==0 && second()==0) 
  {
    dailyread=sensor;  
  total= total - readings[index];   // subtract the last reading:         
  readings[index] = dailyread;   // read from the sensor: 
  total= total + readings[index];   // add the reading to the total:       
     index = index + 1;  // advance to the next position in the array:                   
  if (index >= numReadings)     // if we're at the end of the array...           
    index = 0;       // ...wrap around to the beginning:                         
  average = total / numReadings;    // calculate the average:
  delay (1000);
  ReefAngel.LCD.DrawSingleMonitor(average, color, x, y, z);
  }
}
void setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  setTime(19,59,0,6,3,12);
  Wire.begin(10); // I2C address 10
  Wire.onReceive(receiveEvent);
  ReefAngel.Timer[LCD_TIMER].SetInterval(180);
  ReefAngel.Timer[LCD_TIMER].Start();  // start timer 
}
void loop()
{
  setTime(mhour,mminute,msecond,mday,mmonth,myear);
  if ( ReefAngel.Timer[LCD_TIMER].IsTriggered() )  // process screensaver timeout
	{// Screensaver timeout expired
	ReefAngel.LCD.BacklightOff();
	}
  if ( ReefAngel.Joystick.IsButtonPressed())
	{// turn the backlight on
	ReefAngel.LCD.BacklightOn();
        }
  // TODO check Timer[LCD_TIMER] code
  if ( ReefAngel.Timer[LCD_TIMER].Trigger == 0 )
	{
	ReefAngel.Timer[LCD_TIMER].Start();
	return;
	}// update the min and max temps
  if (now()%86400==0)
  {
    minTemp=maintemp;
    maxTemp=maintemp;
  }
  if (maintemp<minTemp) 
  {
    minTemp=maintemp;
    tsmin=now();
  }
  if (maintemp>maxTemp) 
  {
    maxTemp=maintemp;
    tsmax=now();
  }
  // update the min and max pH
if (now()%86400==0)
{
  minPH=ph;
  maxPH=ph;
}
if (ph<minPH) 
{
  minPH=ph;
  PHmin=now();
  
  
}
if (ph>maxPH) 
{
  maxPH=ph;
  PHmax=now();
}
  if (ReefAngel.Joystick.IsLeft() || ReefAngel.Joystick.IsDown()) 
  {
    ReefAngel.ClearScreen(DefaultBGColor);
    ScreenID--;
  }
  if (ReefAngel.Joystick.IsRight() || ReefAngel.Joystick.IsUp()) 
    {
    ReefAngel.ClearScreen(DefaultBGColor);
    ScreenID++;
    }
  if (ScreenID<0) ScreenID=NumScreens;
  if (ScreenID>=NumScreens) ScreenID=0;
  switch (ScreenID)
  {
  case 0:  //Initial first screen
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#1", Font8x8);
    // Display Temp Text
    ReefAngel.LCD.DrawLargeText(0,255,30,15,"Tank Temp", Font8x8);
    // Display the T1 temp  
    char text[7];
    ConvertNumToString(text, maintemp, 10);
    ReefAngel.LCD.Clear(255, 35, 25, 50, 60);
    if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
    else if (maintemp>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
    // Display pH Text
    ReefAngel.LCD.DrawLargeText(0,255,82,85,"  pH  ", Font8x8);
    // Display pH Value
    ConvertNumToString(text, ph, 100);
    ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (ph>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (ph>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
    // Display Sump Temp
    ReefAngel.LCD.DrawLargeText(0,255,8,50,"Sump Temp", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
    ConvertNumToString(text, sumptemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);
    // Display Room Temp
    ReefAngel.LCD.DrawLargeText(0,255,8,60,"Room Temp", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
    ConvertNumToString(text, roomtemp, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8); 
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (10,90,TempRelay);
    DrawCircleBox (40,90,TempRelay2);
    break;
  case 1:  //same as first screen with position changes
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#2", Font8x8);
    // Display Temp Text
    ReefAngel.LCD.DrawLargeText(0,255,30,15,"   pH    ", Font8x8);
    // Display the T1 temp 
    ConvertNumToString(text, ph, 100);
    ReefAngel.LCD.Clear(255, 35, 25, 50, 50);
    if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 35, 25, text);
    else if (ph>830) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 35, 25, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 35, 25, text);
    // Display pH Text
    ReefAngel.LCD.DrawLargeText(0,255,25,105,"Tank", Font8x8);  
    // Display pH Value
    ConvertNumToString(text, maintemp, 10);
    ReefAngel.LCD.Clear(255, 65, 95, 132, 115);
    if (maintemp>840 || ph<790) ReefAngel.LCD.DrawHugeNumbers(COLOR_RED, 255, 65, 95, text);
    else if (maintemp>830 || ph<800) ReefAngel.LCD.DrawHugeNumbers(COLOR_ORANGE, 255, 65, 95, text);
    else ReefAngel.LCD.DrawHugeNumbers(COLOR_MIDNIGHTBLUE, 255, 65, 95, text);
    // Display Flow0
    ReefAngel.LCD.DrawLargeText(0,255,8,50,"Pump1Flow", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 50, 132, 60);
    ConvertNumToString(text, flow0, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 50, text, Num8x8);
    // Display Flow1
    ReefAngel.LCD.DrawLargeText(0,255,8,60,"Pump2Flow", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 60, 132, 70);
    ConvertNumToString(text, flow1, 10);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 60, text, Num8x8);
    // Display light level 
    ReefAngel.LCD.DrawLargeText(0,255,8,70,"Moonlight", Font8x8);
    ReefAngel.LCD.Clear(255, 90, 70, 132, 90);
    ConvertNumToString(text, moonlight, 1);
    ReefAngel.LCD.DrawLargeText(COLOR_MIDNIGHTBLUE, 255, 90, 70, text, Num8x8); 
// moonphase------------------------------------------------------------   
  YY = (year()) - floor((12 - (month())) / 10); 
  MM = (month()) + 9;
  if (MM >= 12)
  {
    MM = MM - 12;
  }
  K1 = floor(365.25 * (YY + 4712));
  K2 = floor(30.6 * MM + 0.5);
  K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;
  JD = K1 + K2 + (day()) + 59;
  if (JD > 2299160)
  {
    JD = JD - K3;
  }
  IP = (JD - 2451550.1) / 29.530588853;
  IP = IP - floor(IP);
  if (IP < 0)
  {
    IP = IP + 1;
  }
  AG = IP*29.53;
  
  if (AG < 1.84) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"New", Font8x8);
  else if (AG < 5.53) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waxing Crescent", Font8x8);
  else if (AG < 9.92) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"First Quarter", Font8x8);
  else if (AG < 12.91) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waxing Gibbous", Font8x8);   
  else if (AG < 16.61) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Full", Font8x8);    
  else if (AG < 20.30) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waning gibbous", Font8x8);    
  else if (AG < 23.99) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Last Quarter", Font8x8);    
  else if (AG < 27.68) ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"Waning Crescent", Font8x8);    
  else  ReefAngel.LCD.DrawLargeText(DPColor,DefaultBGColor, 5, 80,"New") ;  
    break;
  case 2:  //Temperature detail screen with sump and room temp, 24 hr. max/min, time stamps, and graph
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#3", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,10,15,"Temp Details", Font8x8);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,33,"TANK:");
    ReefAngel.LCD.DrawSingleMonitor(maintemp, COLOR_BLACK, 36, 33, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,43,"HI:");
    ReefAngel.LCD.DrawSingleMonitor(maxTemp, 0, 23, 43, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,43,"at");
    DrawTime(60,43,0, COLOR_WHITE,tsmax);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,53,"LO:");
    ReefAngel.LCD.DrawSingleMonitor(minTemp, 0, 23, 53, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,48,53,"at");
    DrawTime(60,53,0,COLOR_WHITE, tsmin);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,63,"Range:");
    ReefAngel.LCD.DrawSingleMonitor((maxTemp-minTemp), COLOR_BLACK, 46, 63, 10);
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,69,63,"degreesF");
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,73,"Avg:");
    DrawDailyAvg(maintemp, COLOR_BLACK, 43, 73, 1);  
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,83,"WeeklyAvg:");
    DrawWeeklyAvg(12,maintemp, COLOR_BLACK, 66, 83, 1);  
    ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor, 86,83,"at noon");
    ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor, 5 ,93,"R00M:");
    ReefAngel.LCD.DrawSingleMonitor(roomtemp, COLOR_BLACK, 36, 93, 10);
    ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor, 5, 103,"SUMP:");
    ReefAngel.LCD.DrawSingleMonitor(sumptemp, COLOR_BLACK, 36, 103, 10);
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#3", Font8x8);
    break;
  case 3:  //pH details
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#4", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,20,15,"pH Details", Font8x8);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,33,"pH:");
    ReefAngel.LCD.DrawSingleMonitor(ph, COLOR_BLACK, 36, 33, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,43,"HI:");
    ReefAngel.LCD.DrawSingleMonitor(maxPH, 0, 23, 43, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,48,43,"at");
    DrawTime(60,43,0, COLOR_WHITE,PHmax);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,53,"LO:");
    ReefAngel.LCD.DrawSingleMonitor(minPH, 0, 23, 53, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,48,53,"at");
    DrawTime(60,53,0,COLOR_WHITE, PHmin);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,63,"Range:");
    ReefAngel.LCD.DrawSingleMonitor((maxPH-minPH), COLOR_BLACK, 46, 63, 100);
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,73,"Avg:");
    DrawDailyAvg(ph, COLOR_BLACK, 43, 73, 100);  
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,83,"WeeklyAvg:");
    DrawWeeklyAvg(12,ph, COLOR_BLACK, 66, 83, 100);  
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 86,83,"at noon");
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,5,93,"WeeklyAvg:");
    DrawWeeklyAvg(0,ph, COLOR_BLACK, 66, 93, 100);  
    ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 86,93,"at midnt");
    break;
 case 4:  //relay box key
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#5", Font8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (56,46,TempRelay);
    ReefAngel.LCD.DrawLargeText(0,255,27,20,"RelayBox 1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44,"MainP", Font8x8); //7
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"WaveL", Font8x8); //5
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"MH LT", Font8x8); //3
    ReefAngel.LCD.DrawLargeText(0,255,7,74,"Heat2", Font8x8); //1
    ReefAngel.LCD.DrawLargeText(0,255,75,44,"Fans", Font8x8);  //8
    ReefAngel.LCD.DrawLargeText(0,255,75,54,"WaveR", Font8x8);  //6
    ReefAngel.LCD.DrawLargeText(0,255,75,64,"StdLT", Font8x8); //4
    ReefAngel.LCD.DrawLargeText(0,255,75,74,"Heat1", Font8x8);  //2
    break;
  case 5:  //relay box key
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#6", Font8x8);
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;  
    DrawCircleBox (56,46,TempRelay2);
    ReefAngel.LCD.DrawLargeText(0,255,27,20,"RelayBox 2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44,"Dose1", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"Wave3", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"  ATO", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,74,"Chill", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,44,"Dose2", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,54,"Wave4", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,64,"PO4", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,75,74,"Chill", Font8x8);
    break;
  case 6:  //level sensors
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#7", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,20,20,"Level Sensors", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,44," Overflow", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,54,"Reservoir", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,64,"  Low ATO", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,7,74," High ATO", Font8x8);
    if (level == 0)
    {
      Overflow = 0;
      Reservoir = 0;
    }
    else if (level == 1)
    {
      Overflow = 1;
      Reservoir = 0;
    }
    else if (level == 2)
    {
      Overflow = 0;
      Reservoir = 1;
    }
    else if (level == 3)
    {
      Overflow = 1;
      Reservoir = 1;
    }
    if (atos == 0)
    {
      HATO = 1;
      LATO = 1;
    }
    else if (atos == 1)
    {
      HATO = 1;
      LATO = 0;
    }
    else if (atos == 2)
    {
      HATO = 0;
      LATO = 1;
    }
    else if (atos == 3)
    {
      HATO = 0;
      LATO = 0;
    }
    DrawCircle (90,48,5,COLOR_BLACK);
        if (Overflow == 1) 
        {
          FillCircle(90,48,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 44, 132, 54);

        }
        else if (Overflow == 0)
        {
          FillCircle(90,48,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,44,"HIGH", Font8x8);
        }
    DrawCircle (90,58,5,COLOR_BLACK);
        if (Reservoir == 1) 
        {
          FillCircle(90,58,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,54,"FILL", Font8x8);
        }
        else if (Reservoir == 0)
        {
          FillCircle(90,58,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 54, 132, 64);

        }
    DrawCircle (90,68,5,COLOR_BLACK);
        if (LATO == 1) 
        {
          FillCircle(90,68,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,64,"FILL", Font8x8);
        }
        else if (LATO == 0)
        {
          FillCircle(90,68,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 64, 132, 74);
        }
    DrawCircle (90,78,5,COLOR_BLACK);
        if (HATO == 1) 
        {
          FillCircle(90,78,3,OutletOnBGColor);
          ReefAngel.LCD.Clear(255, 100, 74, 132, 84);
        }
        else if (HATO == 0)
        {
          FillCircle(90,78,3,OutletOffBGColor);
          ReefAngel.LCD.DrawLargeText(OutletOffBGColor,255,100,74,"LOW", Font8x8);
        }        
       break;
  case 7:  //setclock
  // Analog clock is modified from the original source by Jeff Miller
  // Author: Jeff Miller   http://arduinofun.blogspot.com/
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    // Frame
    DrawCircle(clock_center_x, clock_center_y, clock_radius, COLOR_CORNFLOWERBLUE);
    DrawCircle(clock_center_x, clock_center_y, clock_radius - 1, COLOR_CORNFLOWERBLUE);        
    DrawCircle(clock_center_x, clock_center_y, clock_radius - 2, COLOR_CORNFLOWERBLUE);       
    // Face Tick Marks  (x = r cos theta, y = r sin theta)
    for (byte r=0; r < 12; r++) {
      float angle = (2 * pi / 12)*r;
      int tick_x_out = (clock_radius - 8) * cos (angle) + clock_center_x;
      int tick_y_out = (clock_radius - 8) * sin (angle) + clock_center_y;
      int tick_x_in = clock_radius *.72 * cos (angle) + clock_center_x;
      int tick_y_in = clock_radius * .72 * sin (angle) + clock_center_y;                
      Drawline(tick_x_in, tick_y_in, tick_x_out, tick_y_out, COLOR_CORNFLOWERBLUE);
      }
    // Face Characters
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x - 8,106," 6", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x - 8, 25,"12", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x + 34,clock_center_y," 3", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,clock_center_x - 50, clock_center_y - 4,"9 ", Font8x8);
   // Draw Seconds Hand
       secondangle = (2 * pi / 60) * second();
              if (second() > 15)
        {secondangle = secondangle -1.57;
        }
      else
        {secondangle = secondangle +4.71;
        }
       Drawline(clock_center_x, clock_center_y, secondend_x, secondend_y, WHITE);
       secondend_x = secondhand_radius * cos (secondangle) + clock_center_x;
       secondend_y = secondhand_radius * sin (secondangle) + clock_center_y;
       Drawline(clock_center_x, clock_center_y, secondend_x, secondend_y, BLACK);
// Redraw minutes hand since the section closest to the center gets erased by the seconds hand
       draw_minute(BLACK);
// Redraw hour hand
       draw_hour(BLACK);
// Draw Minutes Hand
       minuteangle = (2 * pi / 60) * minute();
       if (minute() > 15)
        {minuteangle = minuteangle -1.57;
        }
      else
        {minuteangle = minuteangle +4.71;
        }
        // Erase old minutes Hand
       draw_minute(WHITE);
  // Calculate Minute Hand Base
      minutebase_x = minutebase_radius * cos (minuteangle - pi/2) + clock_center_x;
      minutebase_y = minutebase_radius * sin (minuteangle - pi/2) + clock_center_y;
      minutebase_x1 = minutebase_radius * cos (minuteangle + pi/2) + clock_center_x;
      minutebase_y1 = minutebase_radius * sin (minuteangle + pi/2) + clock_center_y;
// Calculate Minute Hand Point
      minuteend_x = minutehand_radius * cos (minuteangle) + clock_center_x;
      minuteend_y = minutehand_radius * sin (minuteangle) + clock_center_y;
// Draw new minutes Hand
      draw_minute(BLACK);                         
// Redraw hour hand
      draw_hour(BLACK);
// Draw Hour Hand   
      minfloat = minute(); // Convert minute short to float
      hourangle = (2 * pi / 12) * ((hourFormat12()) + (minfloat/60)); // Find angle for hour hand
      hourangle = hourangle -1.57;
// Erase old Hour Hand
      draw_hour(WHITE);
// Calculate hour Hand Base
      hourbase_x = hourbase_radius * cos (hourangle - pi/2) + clock_center_x;
      hourbase_y = hourbase_radius * sin (hourangle - pi/2) + clock_center_y;
      hourbase_x1 = hourbase_radius * cos (hourangle + pi/2) + clock_center_x;
      hourbase_y1 = hourbase_radius * sin (hourangle + pi/2) + clock_center_y;
// Calculate hour Hand Point
      hourend_x = hourhand_radius * cos (hourangle) + clock_center_x;
      hourend_y = hourhand_radius * sin (hourangle) + clock_center_y;
// Draw new hours Hand
      draw_hour(BLACK);
    ReefAngel.LCD.DrawLargeText(0,255,110,110,"#8", Font8x8);
    ReefAngel.LCD.DrawDate(5,121);
    break;
  case 8:  //menu
    ReefAngel.Refresh();
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 0, "                 ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(COLOR_WHITE, COLOR_CORNFLOWERBLUE, 0, 1, " Jon's Reef Tank ", Font8x8); //Top Banner
    ReefAngel.LCD.DrawLargeText(0,255,100,120,"#9", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,20,15,"Power Heads", Font8x8);
    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 8, 33,"Top wave:");
    ReefAngel.LCD.Clear(255,78,33,103,43);
    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 8, 108,"Side wave:");
    ReefAngel.LCD.Clear(255,78,108,103,120);
    ReefAngel.LCD.DrawText(0,DefaultBGColor, 78, 108, wavetime);
//    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 104, 113,TempRelay2);
    ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 104, 108,"sec");
  if ((TempRelay&(1<<5))==1<<5)
    {
    ReefAngel.LCD.Clear(255,5,75,90,105);
    ReefAngel.LCD.DrawLargeText(0,255,90,75,"<---", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,90,85,"<---", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,90,95,"<---", Font8x8);
    }
  else if ((TempRelay&(1<<6))==1<<6) 
    {
    ReefAngel.LCD.Clear(255,45,75,130,105);
    ReefAngel.LCD.DrawLargeText(0,255,5,75,"--->", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,5,85,"--->", Font8x8);
    ReefAngel.LCD.DrawLargeText(0,255,5,95,"--->", Font8x8);
    }
  else
    { 
    ReefAngel.LCD.Clear(255,5,75,45,105);
    ReefAngel.LCD.Clear(255,45,75,130,105);
    ReefAngel.LCD.DrawLargeText(0,255,45,85," ~~~", Font8x8);
    }
  if ((TempRelay2&(1<<5))==1<<5)
  {
   ReefAngel.LCD.Clear(255,80,45,100,65);
   ReefAngel.LCD.DrawLargeText(0,255,40,45,"|", Font8x8);
   ReefAngel.LCD.DrawLargeText(0,255,40,55,"v", Font8x8);
  }
  else if ((TempRelay2&(1<<6))==1<<6) 
    {
   ReefAngel.LCD.Clear(255,40,45,60,65);
   ReefAngel.LCD.DrawLargeText(0,255,80,45,"|", Font8x8);
   ReefAngel.LCD.DrawLargeText(0,255,80,55,"v", Font8x8);
    }  
  else
    { 
   ReefAngel.LCD.Clear(255,40,45,100,65);
    }    
    break;
}
}
void receiveEvent(int howMany) 
{
    if (howMany==32)  // Our custom protocol is 13 bytes
  {
    byte cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10;
    byte cmd11,cmd12,cmd13,cmd14,cmd15,cmd16,cmd17,cmd18,cmd19,cmd20;
    byte cmd21,cmd22,cmd23,cmd24,cmd25,cmd26,cmd27,cmd28,cmd29,cmd30;
    byte cmd31,cmd32;
    cmd1=Wire.read();
    cmd2=Wire.read();
    cmd3=Wire.read();
    cmd4=Wire.read();
    cmd5=Wire.read();
    cmd6=Wire.read();
    cmd7=Wire.read();
    cmd8=Wire.read();
    cmd9=Wire.read();
    cmd10=Wire.read();
    cmd11=Wire.read();
    cmd12=Wire.read();
    cmd13=Wire.read();
    cmd14=Wire.read();
    cmd15=Wire.read();
    cmd16=Wire.read();
    cmd17=Wire.read();
    cmd18=Wire.read();
    cmd19=Wire.read();
    cmd20=Wire.read();
    cmd21=Wire.read();
    cmd22=Wire.read();
    cmd23=Wire.read();
    cmd24=Wire.read();
    cmd25=Wire.read();
    cmd26=Wire.read();
    cmd27=Wire.read();
    cmd28=Wire.read();
    cmd29=Wire.read();
    cmd30=Wire.read();
    cmd31=Wire.read();
    cmd32=Wire.read();   
   if (cmd1=='$' && cmd2=='$' && cmd3=='$') // the first 3 bytes of the custom protocol are $$$ to ensure it's coming from RA
    {
    maintemp=(cmd4<<8)+cmd5;
    sumptemp=(cmd6<<8)+cmd7;
    roomtemp=(cmd8<<8)+cmd9;
    ph=(cmd10<<8)+cmd11;
    wavetime=(cmd12<<8)+cmd13;
    moonlight=(cmd14<<8)+cmd15;
    level=cmd16;
    atos=cmd17;
    TempRelay=cmd18;
    TempRelay2=cmd19;
    flow0=(cmd20<<8)+cmd21;
    flow1=(cmd22<<8)+cmd23;
    flow2=(cmd24<<8)+cmd25;
    mhour=cmd26;
    mminute=cmd27;
    msecond=cmd28;
    mday=cmd29;
    mmonth=cmd30;
    myear=(cmd31<<8)+cmd32;
    }
  }
  else
    for (int a=0;a<howMany;a++)
      Wire.read(); // if the number of bytes is not 32, discard everything
  }

Enjoy! :D
Jon
Post Reply