The Talking Reef

Request new hardware or ideas for the controller
User avatar
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis
PostPosted: Thu Jan 12, 2012 2:09 pm
I didn't know really where to post this, but I thought you would all get a laugh out of it and it does speak to the amazing flexibility of this system.

I had an idea to make my reef tank talk when folks walked by or when the RA had something to say. I purchased this sheild (http://www.spikenzielabs.com/SpikenzieLabs/VoiceShield.html) for an arduino Uno and a motion sensor (http://www.adafruit.com/products/189) and put it all together. My 'sounds' are various ocean noises, Little Mermaid, and Nemo clips that make me laugh. I also found a few that respond nicely to feeding time and water change modes. Thanks to all the tutelage from folks here, I used the I2C to send requests to the system to make various sounds on queue.

I'm finishing up the box and all, but it already is fun for those walking past the tank to hear "just keep swimming, just keep swimming", etc. or "It's feeding time" when the Feed mode is triggered. :lol:

I thought some of you who are in to the LED lighting system might enjoy a little thunder with your lighting if you want to give it a try. :D

-Jon

Posts: 12225
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Thu Jan 12, 2012 2:27 pm
Nice :)
Roberto.
User avatar
Posts: 2737
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Thu Jan 12, 2012 3:32 pm
Where's the video of this?? :)
User avatar
Posts: 149
Joined: Tue Nov 01, 2011 11:05 am
PostPosted: Fri Jan 13, 2012 5:23 am
I want thunder with my lightning! This is gnarly haha

I'd also do motion sensed warnings such as

If motiontriggered==true && atolow==true. "Warning. Auto Top off Resovoir Low"

Or

If motion triggered== true && atohigh ==true "overflow Prevented Please clear error to reactivate return pump"

Or

If motion && cloud
If cloudstart < hour(12) "todays forcast: cloudy in the morning with the sun come out later in the day"
If cloudstart > hour(12 " todays forcast: well be having clouds in the after noon ect ect

Or for t storms "thunderstorms throughout the afternoon with heavy winds" (vortech mode storm)


Where do we get a usb > io module...
Haha obviously not code but you get the idea.....
User avatar
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis
PostPosted: Sat Jan 14, 2012 10:54 am
OK, here it is in testing. :)
http://www.youtube.com/watch?v=XIX5sQFBMLA&feature=g-upl&context=G2056f10AUAAAAAAAAAA

It seems to work pretty well. I get a little background buzz when the halides are on that I need to work out, but it is fun! The demo shows a couple sounds playing in response to motion and a sound byte for feeding and water change from the RA. I use my son's I home for a speaker since it is amplified and has volume controls when I don't want it turned on.

Please keep in mind this is my first ever electronics project and I would have never been able to even try this without everything I've picked up on this forum. Thanks!

-Jon
(If anyone is interested, I'd be happy to share the pde's or more of the actual unit as well, although it may reveal my amateur electronics skills. ;) )

Posts: 12225
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Sat Jan 14, 2012 11:30 am
That's so awesome!!
Roberto.
User avatar
Posts: 2737
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Sat Jan 14, 2012 2:47 pm
Nice. :)

Posts: 243
Joined: Thu Sep 01, 2011 8:44 pm
PostPosted: Sat Jan 14, 2012 5:32 pm
I would like to see your PDE and the pics of the actual unit and how it is connected to the RA controller. This is really cool!!!
Image
User avatar
Posts: 378
Joined: Mon Oct 24, 2011 7:52 pm
Location: Saint Louis
PostPosted: Sun Jan 15, 2012 10:34 am
OK, here are the pde codes I am currently testing. Please keep in mind this also has a few other things I am still evaluating (relay box, I/O device) that is hanging around in this code as well. The Arduino/VoiceShield code also requires the VoiceSheild library. I'll try to post some pics/video of the box itself soon.

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;

#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 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
  ReefAngel.ShowInterface();
}
}


and the Arduino/VoliceShield pde...

Code: Select all
#include <Wire.h>
#include <VoiceShield.h>

VoiceShield vs(9);

byte soundnum=255;
int LED = 13;    //red LED for activated PIR
int LEDG = 12;     //power on LED, 220 resistor on POS.
int inputPin = 10;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
byte randNumber;                // randomize sound bytes
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.
long interval = 30000;           // interval at which to blink (milliseconds)

void setup()
{
  pinMode(LED, OUTPUT);      // declare LED as output
  pinMode(LEDG,OUTPUT);
  pinMode(inputPin, INPUT);     // declare sensor as input
  Wire.begin(9); // I2C address 9
  Wire.onReceive(receiveEvent); 
}

void loop()
{
  digitalWrite (LEDG,HIGH);
  val = digitalRead(inputPin);  // read input value
  randNumber = random(0,6);   //random number from 5 to 20. The first 5 are for specific calls from Master
  if (val == HIGH)
  {            // check if the input is HIGH
    digitalWrite(LED, HIGH);
    // limits the sound to play after a set break so it doesn't just keep repeating.
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > interval)
    {
       previousMillis = currentMillis; 
       vs.ISDPLAY_to_EOM(randNumber); }      //play sound
    else vs.ISDSTOP();
    if (pirState == LOW)
    {
      pirState = HIGH;
    }
  }
  else
  {
    digitalWrite(LED, LOW); // turn LED OFF
    if (pirState == HIGH)
    {
      pirState = LOW;
    }
  }
//start pde for recieve requests from RA
  if (soundnum!=255)   
  {
    ProcessCMD(soundnum);   
    soundnum=255;
  }
}

void receiveEvent(int howMany) {
  if (howMany==4)  // Our custom protocol is 5 bytes
  {
    byte cmd1, cmd2, cmd3, cmd4;
    cmd1=Wire.receive();
    cmd2=Wire.receive();
    cmd3=Wire.receive();
    cmd4=Wire.receive();
    if (cmd1=='$' && cmd2=='$' && cmd3=='$') // the first 3 bytes of the custom protocol are $$$ to ensure it's coming from RA
    {
      soundnum=cmd4; // 4th byte is the sound
    }
  }
  else
    for (int a=0;a<howMany;a++)
      Wire.receive(); // if the number of bytes is not 5, discard everything
}

void ProcessCMD(byte cmd)
{
  if (cmd>=0 && cmd<=4)
    vs.ISDSTOP();
    vs.ISDPLAY_to_EOM(cmd);
}


Enjoy :) ,
Jon

Posts: 25
Joined: Sun Mar 04, 2012 9:47 pm
PostPosted: Fri Mar 09, 2012 2:05 pm
WOW that is so cool! once I get my RA and learn how to use it I would like to play around with this idea, be great for ATO res. Low warring. over /under heating warning.
Next

Return to Requests

Who is online

Users browsing this forum: No registered users and 3 guests

cron