expanding arduino boards

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

expanding arduino boards

Post by jsclownfish »

I'm still very new to all this, but I was wondering if it is possible to set-up some Arduino sensors on a seperate system to save some memory and feed that data to the Reef Angel for display. It seems like there are lots of solutions to code new functionality, but memory is limiting.

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

Re: expanding arduino boards

Post by rimai »

Can be done.
The expansion port talks I2C, so anything you build externally that talks I2C will work.
Roberto.
User avatar
jsclownfish
Posts: 375
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: expanding arduino boards

Post by jsclownfish »

Great! I've decided to give it a whirl and started with trying to send a signal from my arduino with a photo resisitor (http://www.ladyada.net/learn/sensors/cds.html) to the main and then display the resulting light reading on the LCD. I set up the jumpers on the main (SDA&SCL) and wired the usb lines to the common 5V and gnd. I also used the 10K pull up resistors on the SDA and SCL lines to pin 4 and 5. Suprisingly it almost worked. :o

The readout definately was trying to respond, but I was only getting two of the three characters that show up on the serial print monitor and a lot of noise in between. I'll play with it again soon, but I thought it might be worth sharing now to see if it is something obvious I am missing or a bigger problem.

Master pde

Code: Select all

#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.h>
//Actinic and Daylight PMW are on the LED moonlights
byte ActinicPWMValue=0;
byte DaylightPWMValue=0;
int photodiode = 9;
byte wmport=Port5;
boolean wmdelay=false;
byte wmpulse=0;
#include <avr/pgmspace.h>
// Labels for the web banner
prog_char id_label[] PROGMEM = "jsclownfish";
prog_char probe1_label[] PROGMEM = "Tank";
prog_char probe2_label[] PROGMEM = "Room";
prog_char probe3_label[] PROGMEM = "Sump";
prog_char relay1_label[] PROGMEM = "Heater1";
prog_char relay2_label[] PROGMEM = "Heater2";
prog_char relay3_label[] PROGMEM = "MHalide";
prog_char relay4_label[] PROGMEM = "Actinic";
prog_char relay5_label[] PROGMEM = "WM1";
prog_char relay6_label[] PROGMEM = "WM2";
prog_char relay7_label[] PROGMEM = "Main";
prog_char relay8_label[] PROGMEM = "Fan";
PROGMEM const char *webbanner_items[] = {
    id_label, probe1_label, probe2_label, probe3_label, relay1_label, relay2_label,
	relay3_label, relay4_label, relay5_label, relay6_label, relay7_label, relay8_label};
void 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,"SP:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, 0, 23, 33, 10);
// Display the PH with color sensors
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 64, 13,"PH:");
  if (ReefAngel.Params.PH>840 || ReefAngel.Params.PH<790) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_RED, 82, 13, 100);
  else if (ReefAngel.Params.PH>830 || ReefAngel.Params.PH<800) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_ORANGE, 82, 13, 100);
  else ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, 0, 82, 13, 100);
// Display the % Moonlight
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 23,"LT:");
// 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 // RelayExp
    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 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.beginTransmission(photodiode);
    Wire.send(0);
    Wire.endTransmission();
    Wire.requestFrom(photodiode,1);
    while(Wire.available() == 0);
    ReefAngel.LCD.DrawSingleMonitor(Wire.receive(), 0, 82, 23, 1);
    delay(500);
    }
  ReefAngel.ShowInterface();
}
Slave (arduino Uno) pde:

Code: Select all

/* Photocell simple testing sketch. 
 
Connect one end of the photocell to 5V, the other end to Analog 0.
Then connect one end of a 10K resistor from Analog 0 to ground 
Connect LED from pin 11 through a resistor to ground 
For more information see www.ladyada.net/learn/sensors/cds.html */
#include <Wire.h>;        //IC2 communication

int photocellPin = 0;     // the cell and 10K pulldown are connected to a0
int photodiode;     // the analog reading from the sensor divider
int LEDpin = 11;          // connect Red LED to pin 11 (PWM pin)
int LEDbrightness;        // 
int i;
char reader[10];
void setup() {
  // We'll send debugging information via the Serial monitor
  Serial.begin(9600); 
  Wire.begin(9);                // join i2c bus with address #9
  Wire.onRequest(requestEvent); // register event
}
 void loop() {
  photodiode = analogRead(photocellPin);  
 
  Serial.print("Analog reading = ");
  Serial.println(photodiode);     // the raw analog reading
  // LED gets brighter the darker it is at the sensor
  // that means we have to -invert- the reading from 0-1023 back to 1023-0
  photodiode = 1023 - photodiode;
  //now we have to map 0-1023 to 0-255 since thats the range analogWrite uses
  LEDbrightness = map(photodiode, 0, 1023, 0, 255);
  analogWrite(LEDpin, LEDbrightness); 
  delay(100);
 }
  void requestEvent()
  {
    Wire.send(photodiode);   //send info on light reading
}
  
Thanks for reading and any comments/thoughts.
-Jon
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: expanding arduino boards

Post by rimai »

Awesome work Jon!!!
My observations:
1. Serial and Wire are already initialized on ReefAngel.Init(), so you don't need it on your RA pde.
2. Don't use delay in any of your code. It's not needed and will always cause problems.
3. On your RA pde, I don't think you need to send 0 before you request data from slave
4. this line is doing nothing to you because of the ";" at the end. It tells the controller to do whatever is before the ";", which is nothing at the moment.

Code: Select all

while(Wire.available() == 0);
With that said, try this:

Main 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>

#define photodiode 9

//Actinic and Daylight PMW are on the LED moonlights
byte ActinicPWMValue=0;
byte DaylightPWMValue=0;

byte wmport=Port5;
boolean wmdelay=false;
byte wmpulse=0;
#include <avr/pgmspace.h>
// Labels for the web banner
prog_char id_label[] PROGMEM = "jsclownfish";
prog_char probe1_label[] PROGMEM = "Tank";
prog_char probe2_label[] PROGMEM = "Room";
prog_char probe3_label[] PROGMEM = "Sump";
prog_char relay1_label[] PROGMEM = "Heater1";
prog_char relay2_label[] PROGMEM = "Heater2";
prog_char relay3_label[] PROGMEM = "MHalide";
prog_char relay4_label[] PROGMEM = "Actinic";
prog_char relay5_label[] PROGMEM = "WM1";
prog_char relay6_label[] PROGMEM = "WM2";
prog_char relay7_label[] PROGMEM = "Main";
prog_char relay8_label[] PROGMEM = "Fan";
PROGMEM const char *webbanner_items[] = {
  id_label, probe1_label, probe2_label, probe3_label, relay1_label, relay2_label,
  relay3_label, relay4_label, relay5_label, relay6_label, relay7_label, relay8_label};
void 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,"SP:");
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, 0, 23, 33, 10);
  // Display the PH with color sensors
  ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 64, 13,"PH:");
  if (ReefAngel.Params.PH>840 || ReefAngel.Params.PH<790) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_RED, 82, 13, 100);
  else if (ReefAngel.Params.PH>830 || ReefAngel.Params.PH<800) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_ORANGE, 82, 13, 100);
  else ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, 0, 82, 13, 100);
  // Display the % Moonlight
  ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 23,"LT:");
  // 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 // RelayExp
  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 setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  ReefAngel.LoadWebBanner(pgm_read_word(&(webbanner_items[0])), SIZE(webbanner_items));
  ReefAngel.Timer[4].SetInterval(180);  // set interval to 180 seconds
  ReefAngel.Timer[4].Start();

  ReefAngel.FeedingModePorts = B00110000;
  ReefAngel.WaterChangePorts = B10110000;
  //  ReefAngel.OverheatShutoffPorts = B00000111;
  //  ReefAngel.LightsOnPorts = B00001100;
  ReefAngel.Relay.On(Port5);
  ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
  ReefAngel.Timer[1].Start();
  // Ports that are always on
  ReefAngel.Relay.On(Port7);
}
void loop()
{
  // Specific functions
  //1st Heater at 78.8, 2nd Heater at 77.0, MH on at 10AM off at 8PM, Actinics on at 9AM off at 9PM, Fan kicks on at 82.0
  ReefAngel.StandardHeater(Port1,788,792);
  ReefAngel.StandardHeater(Port2,770,792);
  ReefAngel.MHLights(Port3,10,0,20,0,5);
  ReefAngel.StandardLights(Port4,9,0,21,0);
  ReefAngel.StandardFan(Port8,792,820);
  // Wavemaker Code with night option
  if (ReefAngel.Timer[1].IsTriggered() )
  {
    if ((hour() >= 21) || (hour() <= 8)) //from 9p-Midnight 
    {  //PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, 
      // byte endPWM, byte Duration, byte oldValue)
      wmpulse=PWMSlope(21,0,8,0,5,30,179,30);
      if (wmdelay)
      {
        ReefAngel.Timer[1].SetInterval(wmpulse);  // WM delay function from 30-170 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.Off(Port5);
        ReefAngel.Relay.Off(Port6);
        if (wmport==Port5) wmport=Port6; 
        else wmport=Port5;
        wmdelay=false;
      }
      else
      {
        ReefAngel.Timer[1].SetInterval(200-wmpulse);  // WM bursts timing from 170-30 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.On(wmport);
        wmdelay=true;
      }
    }
    else
    {
      //8a-10p normal wave settings
      ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
      ReefAngel.Timer[1].Start();
      ReefAngel.Relay.Toggle(Port5);
      ReefAngel.Relay.Toggle(Port6);
    }
  }
  //Using Daylight ATO high signal piezo buzzer when temp exceeds 83F
  //other options are lowATOpin or the LED pins as ReefAngel.PWM.SetDaylight(100); else ReefAngel.PWM.SetDaylight(0); 
  if (ReefAngel.Params.Temp1>830) 
  {
    pinMode(highATOPin,OUTPUT);
    digitalWrite(highATOPin,HIGH);
  }
  else
  {
    pinMode(highATOPin,OUTPUT);
    digitalWrite(highATOPin,LOW);
  }
  //Moonlight=byte PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, byte endPWM, byte Duration, byte oldValue)
  ReefAngel.PWM.SetActinic(ActinicPWMValue);
  ActinicPWMValue=PWMSlope(7,00,22,0,0,100,60,ActinicPWMValue); 
  ReefAngel.PWM.SetDaylight(DaylightPWMValue);
  DaylightPWMValue=PWMSlope(7,00,22,0,0,100,60,DaylightPWMValue);
  // Web Banner stuff
  if(ReefAngel.Timer[4].IsTriggered())
  {
    ReefAngel.Timer[4].Start();
    ReefAngel.WebBanner();
  }

  //receive Light readout
  Wire.requestFrom(photodiode,1);
  while(Wire.available() == 0)
  {
    ReefAngel.LCD.DrawSingleMonitor(Wire.receive(), 0, 82, 23, 1);
  }

  ReefAngel.ShowInterface();
}
And Uno PDE

Code: Select all

/* Photocell simple testing sketch. 
 
 Connect one end of the photocell to 5V, the other end to Analog 0.
 Then connect one end of a 10K resistor from Analog 0 to ground 
 Connect LED from pin 11 through a resistor to ground 
 For more information see www.ladyada.net/learn/sensors/cds.html */
#include <Wire.h>;        //IC2 communication

int photocellPin = 0;     // the cell and 10K pulldown are connected to a0
int photodiode;     // the analog reading from the sensor divider
int LEDpin = 11;          // connect Red LED to pin 11 (PWM pin)
int LEDbrightness;        // 
int i;
char reader[10];
void setup() {
  // We'll send debugging information via the Serial monitor
  Serial.begin(9600); 
  Wire.begin(9);                // join i2c bus with address #9
  Wire.onRequest(requestEvent); // register event
}
void loop() {
  photodiode = analogRead(photocellPin);  

  Serial.print("Analog reading = ");
  Serial.println(photodiode);     // the raw analog reading
  // LED gets brighter the darker it is at the sensor
  // that means we have to -invert- the reading from 0-1023 back to 1023-0
  photodiode = 1023 - photodiode;
  //now we have to map 0-1023 to 0-255 since thats the range analogWrite uses
  LEDbrightness = map(photodiode, 0, 1023, 0, 255);
  analogWrite(LEDpin, LEDbrightness); 
}
void requestEvent()
{
  Wire.send(photodiode);   //send info on light reading
}
Roberto.
User avatar
jsclownfish
Posts: 375
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: expanding arduino boards

Post by jsclownfish »

It works! :D

I made a few minor changes once I got it working.
1) Moved the LCD step to the beginning of the pde. Otherwise it showed on the other screens.
2) Changed the number reported to a byte (scaled 1-255).
3) Simplified the report to ON or OFF based on the number reported. (the number is useful, but it really jumps around alot and it might be easier to just confirm the lights are on or off)

Here's the Master:

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;

#define photodiode 9
byte wmport=Port5;
boolean wmdelay=false;
byte wmpulse=0;
#include <avr/pgmspace.h>
// Labels for the web banner
prog_char id_label[] PROGMEM = "jsclownfish";
prog_char probe1_label[] PROGMEM = "Tank";
prog_char probe2_label[] PROGMEM = "Room";
prog_char probe3_label[] PROGMEM = "Sump";
prog_char relay1_label[] PROGMEM = "Heater1";
prog_char relay2_label[] PROGMEM = "Heater2";
prog_char relay3_label[] PROGMEM = "MHalide";
prog_char relay4_label[] PROGMEM = "Actinic";
prog_char relay5_label[] PROGMEM = "WM1";
prog_char relay6_label[] PROGMEM = "WM2";
prog_char relay7_label[] PROGMEM = "Main";
prog_char relay8_label[] PROGMEM = "Fan";
PROGMEM const char *webbanner_items[] = {
    id_label, probe1_label, probe2_label, probe3_label, relay1_label, relay2_label,
	relay3_label, relay4_label, relay5_label, relay6_label, relay7_label, relay8_label};
void 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,"SP:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, 0, 23, 33, 10);
// Display the PH with color sensors
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor, 64, 13,"PH:");
  if (ReefAngel.Params.PH>840 || ReefAngel.Params.PH<790) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_RED, 82, 13, 100);
  else if (ReefAngel.Params.PH>830 || ReefAngel.Params.PH<800) ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, COLOR_ORANGE, 82, 13, 100);
  else ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, 0, 82, 13, 100);
// Display the % Moonlight
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 23,"LT:");
  if (Wire.receive()<100) ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 82, 23,"OFF");
  else ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 82, 23,"ON  ");
// 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 // RelayExp
    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 setup()
{
  ReefAngel.Init();  //Initialize controller and start web banner timer
  ReefAngel.LoadWebBanner(pgm_read_word(&(webbanner_items[0])), SIZE(webbanner_items));
  ReefAngel.Timer[4].SetInterval(180);  // set interval to 180 seconds
  ReefAngel.Timer[4].Start();
  
  ReefAngel.FeedingModePorts = B00110000;
  ReefAngel.WaterChangePorts = B10110000;
//  ReefAngel.OverheatShutoffPorts = B00000111;
//  ReefAngel.LightsOnPorts = B00001100;
  ReefAngel.Relay.On(Port5);
  ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
  ReefAngel.Timer[1].Start();
  // Ports that are always on
  ReefAngel.Relay.On(Port7);
}
void loop()
{
  // Specific functions
  //1st Heater at 78.8, 2nd Heater at 77.0, MH on at 10AM off at 8PM, Actinics on at 9AM off at 9PM, Fan kicks on at 82.0
  ReefAngel.StandardHeater(Port1,788,792);
  ReefAngel.StandardHeater(Port2,770,792);
  ReefAngel.MHLights(Port3,10,0,20,0,5);
  ReefAngel.StandardLights(Port4,9,0,21,0);
  ReefAngel.StandardFan(Port8,792,820);
  // Wavemaker Code with night option
  if (ReefAngel.Timer[1].IsTriggered() )
  {
    if ((hour() >= 21) || (hour() <= 8)) //from 9p-Midnight 
    {  //PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, 
       // byte endPWM, byte Duration, byte oldValue)
      wmpulse=PWMSlope(21,0,8,0,5,30,179,30);
      if (wmdelay)
      {
        ReefAngel.Timer[1].SetInterval(wmpulse);  // WM delay function from 30-170 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.Off(Port5);
        ReefAngel.Relay.Off(Port6);
        if (wmport==Port5) wmport=Port6; else wmport=Port5;
        wmdelay=false;
      }
      else
      {
        ReefAngel.Timer[1].SetInterval(200-wmpulse);  // WM bursts timing from 170-30 sec.
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.On(wmport);
        wmdelay=true;
      }
    }
    else
    {
      //8a-10p normal wave settings
      ReefAngel.Timer[1].SetInterval(InternalMemory.WM1Timer_read());
      ReefAngel.Timer[1].Start();
      ReefAngel.Relay.Toggle(Port5);
      ReefAngel.Relay.Toggle(Port6);
    }
  }
  //Using Daylight ATO high signal piezo buzzer when temp exceeds 83F
  //other options are lowATOpin or the LED pins as ReefAngel.PWM.SetDaylight(100); else ReefAngel.PWM.SetDaylight(0); 
if (ReefAngel.Params.Temp1>830) 
  {
  pinMode(highATOPin,OUTPUT);
  digitalWrite(highATOPin,HIGH);
  }
  else
  {pinMode(highATOPin,OUTPUT);
  digitalWrite(highATOPin,LOW);
  }
    //Moonlight=byte PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, byte endPWM, byte Duration, byte oldValue)
   ReefAngel.PWM.SetActinic(ActinicPWMValue);
   ActinicPWMValue=PWMSlope(7,00,22,0,0,100,60,ActinicPWMValue); 
   ReefAngel.PWM.SetDaylight(DaylightPWMValue);
   DaylightPWMValue=PWMSlope(7,00,22,0,0,100,60,DaylightPWMValue);
// Web Banner stuff
    if(ReefAngel.Timer[4].IsTriggered())
    {
        ReefAngel.Timer[4].Start();
        ReefAngel.WebBanner();
    }
    {
//receive Light readout
    Wire.requestFrom(photodiode,1);
    }
  ReefAngel.ShowInterface();
}


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

Re: expanding arduino boards

Post by rimai »

Nice :)
You could smooth out the readings as you read them.
The best way is averaging X readings. Start with 10 readings. Should be plenty to average and give you a better number.
Roberto.
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: expanding arduino boards

Post by TanksNStuff »

I don't know much about any of this as I'm new to the Arduino / RA world, but just from reading the link to the photo resistor that jsclownfish gave, I noticed this comment:
They are very low cost, easy to get in many sizes and specifications, but are very innacurate. Each photocell sensor will act a little differently than the other, even if they are from the same batch. The variations can be really large, 50% or higher! For this reason, they shouldn't be used to try to determine precise light levels in lux or millicandela. Instead, you can expect to only be able to determine basic light changes
So, the decision to change to "ON or OFF" was probably a good idea. Even if you took Roberto's advice to smooth the reading by taking an average... it probably still would have issues (as far as having an accurate reading) due to the sensor being innacurate to begin with.

I'm curious as to what you will be doing with this data and if you happened to take a screenshot of the display showing the data? Were you planning to have another function dependant upon the results of this data? If so, what?

I can see this as not only being useful to some people, but also as a stepping stone to come up with other ideas for expansions. Good job jsclownfish!
User avatar
jsclownfish
Posts: 375
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis

Re: expanding arduino boards

Post by jsclownfish »

Thanks for the note. I agree that this isn't a method for accurately accessing lux or millicandela levels, but I like the idea of the system performing two potential tasks.
1) provide a direct output that the lighting is OFF or ON based on the sensor rather than on the outlet relay. When I have had lighting issues in the past it is seldom due to the power to the lamp, but more like the bulb or ballast going bad.
2) while the variation between photo resistors maybe be off, the variablity in any one sensor is reasonably good and with that I may be able to actually see a trend in the light output falling off or changing over time.

I have a few more of these around now and I just need to come up with a housing to mount them to the tank somehow so I can start gathering data. Hopefully then I can see how stable the measurements are over time.

-Jon
TanksNStuff
Posts: 188
Joined: Fri Dec 30, 2011 6:57 am

Re: expanding arduino boards

Post by TanksNStuff »

Two perfectly good reasons to have something like this. Especially the first one. I can see that as being an issue if the outlet is active but the equipment plugged into it not working... whether it be due to power failure or whatever reason.
Post Reply