Auxilliary LCD monitor
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Auxilliary LCD monitor
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.....
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
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
Re: Auxilliary LCD monitor
Here is the ideas I have for you.
I know you have some goodies under your hood
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!!
Good job!
I know you have some goodies under your hood
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!!
Good job!
Roberto.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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
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
Re: Auxilliary LCD monitor
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?
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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)
and here is the Arduinio/LCD (slave) pde....
-Jon
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
}
Re: Auxilliary LCD monitor
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?
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.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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
-Jon
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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
-Jon
Re: Auxilliary LCD monitor
Yeah, it is initialized on setup, but you can override it.
In the loop(), either this:
Or this:
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
In the loop(), either this:
Code: Select all
ReefAngel.LCD.BacklightOn();
Code: Select all
ReefAngel.Timer[LCD_TIMER].Start();
http://www.reefangel.com/Products.USB-Power-Cable.ashx
Roberto.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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
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
Re: Auxilliary LCD monitor
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
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.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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
-Jon
Re: Auxilliary LCD monitor
Correct. Just power.
You still need the USB-TTL cable to upload the code.
You still need the USB-TTL cable to upload the code.
Roberto.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
Roberto,
Your suggestion seems to work great. 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.
-Jon
Your suggestion seems to work great. 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.
-Jon
-
- Posts: 149
- Joined: Tue Nov 01, 2011 11:05 am
Re: Auxilliary LCD monitor
I got second screen envy....
-
- Posts: 149
- Joined: Tue Nov 01, 2011 11:05 am
Re: Auxilliary LCD monitor
indeed....so roberto how much for that prototype hahaha
Re: Auxilliary LCD monitor
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
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.
-
- Posts: 149
- Joined: Tue Nov 01, 2011 11:05 am
Re: Auxilliary LCD monitor
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)
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
Thanks! 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...
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
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;
Thanks for your help,
Jon
Re: Auxilliary LCD monitor
It's the WDT that is kicking in.
You need this:
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.
You need this:
Code: Select all
wdt_reset();
Roberto.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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.
Thanks for your help,
Jon
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
}
Jon
Re: Auxilliary LCD monitor
I think you are entering into a loop that doesn't do anything:
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
while ( ! bDone );
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.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
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
I'll let you know how it goes.
-Jon
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
Wow, that works great! I can switch data screens and the data keeps updating nicely. Now I'm dreaming about all the different screens I could display. 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
-Jon
Re: Auxilliary LCD monitor
Use this instead:
That will only clear the screen when you move the joystick .
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--;
}
Roberto.
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
Outstanding!
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.... 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.
Thanks for all the help!
-Jon
For anyone interested, here is the pde as well...
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.... 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.
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
}
Re: Auxilliary LCD monitor
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?
- jsclownfish
- Posts: 378
- Joined: Mon Oct 24, 2011 7:52 pm
- Location: Saint Louis
Re: Auxilliary LCD monitor
Yep, you are correct. The second LCD needs another processor to receive and display the information.
-Jon
-Jon
-
- Posts: 471
- Joined: Sat Jan 14, 2012 2:08 pm
- Location: Montgomery Village, MD
Re: Auxilliary LCD monitor
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.jsclownfish wrote:I also have trouble with the temp connectors getting them off and on without messing them up. -Jon
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.
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.