Auxilliary LCD monitor

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

Auxilliary LCD monitor

Post by jsclownfish »

I've been working on a project to make a 2nd LCD module that I could mount on the tank with no extra wires or probes. I've got it working as I want it to look with a 2nd LCD board and an Arduino. The info for the parameters and relay boxes are sending appropriately. :) It looks like this.....
sync'd LCDs
sync'd LCDs
photo.JPG (27.41 KiB) Viewed 6207 times
2nd screen
2nd screen
photo2.jpg (22.57 KiB) Viewed 6207 times
I still have a few bugs to work out before I find a little box to mount it in and make a small Arduino board for it to connect. The 2nd LCD needs to be reset if the power turns off on the main controller or if the USB line is disconnected. :? I actually have to reconnect it so it has power and then remove the 5V line for a couple seconds and reconnect it. If I can't figure it out, I'll have to add a reset switch somewhere on the module. I also haven't figured out if and how to sleep the 2nd LCD and wake it if needed. I don't want to do it from the main, but I'm guessing it's not a good idea to leave it on all the time.

Comments or ideas are always welcome. :)

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

Re: Auxilliary LCD monitor

Post by rimai »

Here is the ideas I have for you.
I know you have some goodies under your hood :twisted:
Why not use the RA+ as the main head unit and your standard RA as remote head unit?
You could use a USB cable and crimp a HDDB15 on the other end.
Something like this:
http://i761.photobucket.com/albums/xx25 ... 213411.jpg
The sleep in the main head unit is actually not a real sleep. It's only the backlight that goes off.
The backlight is on pin#2 of Arduino board, so if you do digitalWrite(2,LOW); it should turn off the backlight of your remote unit.
Now to the connection lost handling.
Why is that you need to remove power? What is happening when connection is lost?
Are you pushing data from the main unit or pulling from the remote?
I love the work you've done so far!!! Very impressed!! :shock:
Good job!
Roberto.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

hmmm. That could work. It might be a bit bulkier than I originally planned, but it would have the joystick to turn on the backlight without opening the cabinet and going to the main. I'd need another enclosure though. ;)

On the power issue, I get power appropriately to a LED connected to the power line, but the LCD stays dark. If I disconnect the USB(I2C) from the controller and plug in the board with a wall wart it comes back, or if I just remove the 5V line from the USB(I2C) for a couple seconds and reconnect it comes back. Same thing happens if I use the USB from my PC.

-Jon
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Auxilliary LCD monitor

Post by binder »

That's pretty sweet. Are you using the web server or serial line to send the data to the slave? Is it done automatically by the slave or is the slave listening for the host to push the data?
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 pushing the data from the main to the slave Arduino/LCD. It is connected using the same USB line the modules use (redirecting the 4 lines to tx/rx/gnd/5V with a couple 1K resistors) for the I2C communication.

Here is the main (master) controller pde...
(there is some 'extra' code in here as I am getting ready to add the second relay box)

Code: Select all

#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.h>
//Actinic and Daylight PMW are on the LED moonlights
byte ActinicPWMValue=0;
byte DaylightPWMValue=0;
byte param[8];

#define photodiode 8    //i2C for flow/light sensors
byte wmport=Port5;
boolean wmdelay=false;
byte wmpulse=0;
byte brightness=0;
byte flow=0;
long previousMillis = 0;        // will store last time LED was updated
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
// atleast 5 sec inteval before the next sound plays
long interval = 5000;           // interval at which to blink (milliseconds)

#include <avr/pgmspace.h>
// Labels for the web banner
prog_char id_label[] PROGMEM = "jsclownfish";
prog_char probe1_label[] PROGMEM = "Tank";
prog_char probe2_label[] PROGMEM = "Room";
prog_char probe3_label[] PROGMEM = "Sump";
prog_char relay1_label[] PROGMEM = "Heater1";
prog_char relay2_label[] PROGMEM = "Heater2";
prog_char relay3_label[] PROGMEM = "MHalide";
prog_char relay4_label[] PROGMEM = "Actinic";
prog_char relay5_label[] PROGMEM = "WM1";
prog_char relay6_label[] PROGMEM = "WM2";
prog_char relay7_label[] PROGMEM = "Main";
prog_char relay8_label[] PROGMEM = "Fan";
prog_char relay11_label[] PROGMEM = "Dose#1";
prog_char relay12_label[] PROGMEM = "Dose#2";
prog_char relay13_label[] PROGMEM = "Top-off#3";
prog_char relay14_label[] PROGMEM = "ATF Flow";
prog_char relay15_label[] PROGMEM = "Relay#5";
prog_char relay16_label[] PROGMEM = "Relay#6";
prog_char relay17_label[] PROGMEM = "Relay#7";
prog_char relay18_label[] PROGMEM = "Relay#8";
PROGMEM const char *webbanner_items[] = {
    id_label, probe1_label, probe2_label, probe3_label, relay1_label, relay2_label,
   relay3_label, relay4_label, relay5_label, relay6_label, relay7_label, relay8_label, 
   relay11_label, relay12_label, relay13_label, relay14_label,relay15_label, relay16_label, 
   relay17_label, relay18_label};
void paramsend(int a, int b, int c, int d)
{
  param[0]=(byte)(a>>8);
  param[1]=(byte)(a);
  param[2]=(byte)(b>>8);
  param[3]=(byte)(b);
  param[4]=(byte)(c>>8);
  param[5]=(byte)(c);
  param[6]=(byte)(d>>8);
  param[7]=(byte)(d);
}
void DrawCustomMain()
{
// 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();
// Display the Tank temperature with color sensors
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,5,13,"TK:");
  if (ReefAngel.Params.Temp1>830) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp1, COLOR_RED, 23, 13, 10); 
  else if (ReefAngel.Params.Temp1>810) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp1, COLOR_ORANGE, 23, 13, 10); 
  else ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp1, COLOR_BLACK, 23, 13, 10);
// Display the Room temperature
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,5,23,"RM:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp2, 0, 23, 23, 10);
// Display the Sump temperature
ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor,5,33,"FL:");
ReefAngel.LCD.DrawSingleMonitor(flow, 0, 23, 33, 1);
// 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 the % Moonlight
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 23,"LT:");
ReefAngel.LCD.DrawSingleMonitor(brightness, 0, 82, 23, 1);
// Display arrows for Wavemaker
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 33,"WV:");
  if (bitRead(ReefAngel.Relay.RelayData,Port5-1)==1) ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 82, 33,"-->"); //port 5 on
  else if (bitRead(ReefAngel.Relay.RelayData,Port6-1)==1) ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 82, 33,"<--");  //port 6 on
  else ReefAngel.LCD.DrawText(APColor,DefaultBGColor, 82, 33," O "); //port5 and port 6 off, wavemaker delay
pingSerial();
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 45, TempRelay);
#ifdef RelayExp
// draw 1st expansion relay
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 55, TempRelay);
#endif
//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,105,33,135,43);
      ReefAngel.LCD.DrawText(0, DefaultBGColor,105,33,t);
    }
    if (t>300) ReefAngel.Timer[1].ForceTrigger();  
}
void DrawCustomGraph()
{
ReefAngel.LCD.DrawGraph(1, 75);
}
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 #8
         Wire.send('$');         // send the $$$
         Wire.send('$');
         Wire.send('$');
         Wire.send(x);         // send the command
         Wire.endTransmission();      // stop transmitting
        }
}
void setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  ReefAngel.LoadWebBanner(pgm_read_word(&(webbanner_items[0])), SIZE(webbanner_items));
  ReefAngel.Timer[4].SetInterval(180);  // set interval to 180 seconds
  ReefAngel.Timer[4].Start();
  
  ReefAngel.FeedingModePorts = B00110000;
  ReefAngel.WaterChangePorts = B10110000;
//  ReefAngel.OverheatShutoffPorts = B00000111;
//  ReefAngel.LightsOnPorts = B00001100;
  ReefAngel.Relay.On(Port5);
  ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
  ReefAngel.Timer[1].Start();
  // Ports that are always on
  ReefAngel.Relay.On(Port7);
//  Wire.begin();
//    Serial.begin(9600); // serial connection
}
void loop()
{
  // Specific functions
  //1st Heater at 78.8, 2nd Heater at 77.0, MH on at 10AM off at 8PM, Actinics on at 9AM off at 9PM, Fan kicks on at 82.0
  ReefAngel.StandardHeater(Port1,788,792);
  ReefAngel.StandardHeater(Port2,770,792);
  ReefAngel.MHLights(Port3,10,0,20,0,5);
  ReefAngel.StandardLights(Port4,9,0,21,0);
  ReefAngel.StandardFan(Port8,792,820);
  // Wavemaker Code with night option
  if (ReefAngel.Timer[1].IsTriggered() )
  {
    if ((hour() >= 21) || (hour() <= 8)) //from 9p-Midnight 
    {  //PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, 
       // byte endPWM, byte Duration, byte oldValue)
      wmpulse=PWMSlope(21,0,8,0,5,30,179,30);
      if (wmdelay)
      {
        ReefAngel.Timer[1].SetInterval(wmpulse);  // WM delay function from 30-170 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.Off(Port5);
        ReefAngel.Relay.Off(Port6);
        if (wmport==Port5) wmport=Port6; else wmport=Port5;
        wmdelay=false;
      }
      else
      {
        ReefAngel.Timer[1].SetInterval(200-wmpulse);  // WM bursts timing from 170-30 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.On(wmport);
        wmdelay=true;
      }
    }
    else
    {
      //8a-10p normal wave settings
      ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
      ReefAngel.Timer[1].Start();
      ReefAngel.Relay.Toggle(Port5);
      ReefAngel.Relay.Toggle(Port6);
    }
  }
  //Using Daylight ATO high signal piezo buzzer when temp exceeds 83F
  //other options are lowATOpin or the LED pins as ReefAngel.PWM.SetDaylight(100); else ReefAngel.PWM.SetDaylight(0); 
if (ReefAngel.Params.Temp1>830) 
  {
  pinMode(highATOPin,OUTPUT);
  digitalWrite(highATOPin,HIGH);
  }
  else
  {pinMode(highATOPin,OUTPUT);
  digitalWrite(highATOPin,LOW);
  }
    //Moonlight=byte PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, byte endPWM, byte Duration, byte oldValue)
   ReefAngel.PWM.SetActinic(ActinicPWMValue);
   ActinicPWMValue=PWMSlope(7,00,22,0,0,100,60,ActinicPWMValue); 
   ReefAngel.PWM.SetDaylight(DaylightPWMValue);
   DaylightPWMValue=PWMSlope(7,00,22,0,0,100,60,DaylightPWMValue);
// Web Banner stuff
    if(ReefAngel.Timer[4].IsTriggered())
    {
        ReefAngel.Timer[4].Start();
        ReefAngel.WebBanner();
    }
    {
//receive Light readout
    Wire.requestFrom(photodiode,2);
    if (Wire.available())
    {
      brightness=Wire.receive();
      flow=Wire.receive();
    }
//send sound requests
//      if (ReefAngel.Params.Temp1>830) Soundsend(9, 100);   //too hot
//      if (ReefAngel.Params.Temp1<770) Soundsend(10, 100);   //too cold
      if (ReefAngel.DisplayedMenu==FEEDING_MODE) Soundsend(7,100);     //feeding time
      if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) Soundsend(8,100);     //feeding time
//send data parameters
         Wire.beginTransmission(10);      // transmit to device #8
         Wire.send('$');         // send the $$$
         Wire.send('$');
         Wire.send('$');
         paramsend(ReefAngel.Params.Temp1,ReefAngel.Params.Temp2,ReefAngel.Params.Temp3,ReefAngel.Params.PH);
         Wire.send(param,8);
         Wire.send(ReefAngel.Relay.RelayData);
         Wire.endTransmission();      // stop transmitting
   ReefAngel.ShowInterface();
}
}

and here is the Arduinio/LCD (slave) pde....

Code: Select all

#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.h>
#include <avr/wdt.h>

int maintemp=800;
int roomtemp=780;
int sumptemp=780;
int ph=700;
byte TempRelay =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);
}
void receiveEvent(int howMany) {
  if (howMany==12)  // Our custom protocol is 11 bytes
  {
    byte cmd1, cmd2, cmd3, cmd4, cmd5, cmd6, cmd7, cmd8, cmd9, cmd10, cmd11,cmd12;
      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();
    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;
    }
  }
  else
    for (int a=0;a<howMany;a++)
      Wire.receive(); // if the number of bytes is not 11, discard everything
}
-Jon
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Auxilliary LCD monitor

Post by rimai »

I think the dark screen is related to the screen saver and not because there is anything going wrong with the communication, now that I'm looking at the code.
If you go with the idea I gave you with RA+ as master and standard RA as slave, you would be able to get out of screen saver. Otherwise, we can kill the screen saver and leave the LCD constantly on.
What would you prefer?
Roberto.
User avatar
jsclownfish
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: Auxilliary LCD monitor

Post by jsclownfish »

That could be the issue. Even without the main connected while I was working on the 2nd LCD display, I had to load the code to the Arduino with a dark screen, then disconnect the serial USB and reconnect the wall wart power after a few seconds and the LCD would come back. Is the screen saver part of the Initialization function?

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

Re: Auxilliary LCD monitor

Post by jsclownfish »

BTW, that cable from USB to serial HDDB15 would be nice to have anyway for programming the main control. As it is now I have to keep it connected to the relay to power and make sure everything looks good on the custom main, which means I am usually sitting on the floor with my laptop next to the tank. It would be nice to just take the main unit off and connect to the PC to test code.

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

Re: Auxilliary LCD monitor

Post by rimai »

Yeah, it is initialized on setup, but you can override it.
In the loop(), either this:

Code: Select all

ReefAngel.LCD.BacklightOn();
Or this:

Code: Select all

ReefAngel.Timer[LCD_TIMER].Start();
There is a USB power cable at the webstore that I added about a month or two ago.
http://www.reefangel.com/Products.USB-Power-Cable.ashx
Roberto.
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 try to turn off the screen saver to see if it works.
Thanks for the link. I hadn't seen it. Doesn't the communication require 4 lines? I'll probably still make a cable for a serial connection. That way I can give your idea a try and I also have trouble with the temp connectors getting them off and on without messing them up.

-Jon
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 5303 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 4849 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.
Post Reply