Guide: Arduino based LED controller for Current Satellite LED+ - Page 10
Planted Tank Forums
Your Tanks Image Hosting *Tank Tracker * Plant Profiles Fish Profiles Planted Tank Guide Photo Gallery Articles

Go Back   The Planted Tank Forum > Specific Aspects of a Planted Tank > DIY


Reply
 
Thread Tools Display Modes
Old 08-03-2013, 11:27 PM   #136
Caver
Algae Grower
 
PTrader: (0/0%)
Join Date: Jun 2013
Location: Austin TX
Posts: 56
Default

YAY!!! It seems to be working!

Once I figured out I had extremely short range with my LED setup, I kludged an adapter together and turned it loose on the tank light. It's cycled through a couple of my alarms and looks to be working.

I set up a full 24 hour cycle and will let that run through and see how it looks.

I went out and picked up a second UNO. Since the one I started with will be dedicated to the tank light, I needed one to play with...

Looking forward to see how this develops. Great work all !
__________________
--
Tom
Caver is offline   Reply With Quote
Sponsored Links
Advertisement
 
Old 08-05-2013, 02:12 AM   #137
Indychus
Planted Tank Enthusiast
 
Indychus's Avatar
 
PTrader: (8/100%)
Join Date: Feb 2013
Location: Irmo, SC
Posts: 645
Default

Congrats man, hopefully we'll get the range issues figured out.

I have ordered a few different wavelength IR leds to play with.

Here's version 2.2, with some fixes and improvements from Dahammer. I also changed the thunderstorm code some to try to prevent the float errors I was getting. It still does a random duration from 0-3 hours, but now it does it in hours and minutes instead of msecs, allowing all values to be stored as integers.

This compiles fine but I am not able to load it onto my board until Tuesday, so it has not been tested.

Version 2.2

Code:
 See post 144
__________________
The Fraternity of Dirt
Check out my open-source Arduino-Powered Light Controller Guide for Current LED+ and other IR switchable lights.

Last edited by Indychus; 08-05-2013 at 05:32 PM.. Reason: edit
Indychus is offline   Reply With Quote
Old 08-05-2013, 04:44 AM   #138
Dahammer
Algae Grower
 
PTrader: (0/0%)
Join Date: Oct 2010
Location: Mississippi
Posts: 118
Default

You could use byte now instead of int. Byte is unsigned with a max value of 0xFF or 255. Thanks for the updates, hopefully those solve the issues with the storms.

Which wavelength LEDs did you order? I was just looking at them on Jameco's website and they have these:
  • 830
  • 850
  • 875
  • 880
  • 890
  • 935
  • 940

Any idea how many different ones there are? I wander if Current would sell us some. haha.

I came across this info on Ken Shirriff's blog:
Quote:
For output, connect an IR LED and appropriate resistor to PWM output pin 3. Make sure the polarity of the LED is correct, or it won't illuminate - the long lead is positive. I used a NTE 3027 LED (because that's what was handy) and 100 ohm resistor; the range is about 15 feet. For additional range, you can amplify the output with a transistor.
The forward voltage on that LED is about 1.3, so with a 100ohm resistor the current is around 37mA. If he can get 15 feet with 37mA, we must have other issues.

Speaking of Ken Shirriff, his IR library uses a different approach in Rx/Tx of the IR codes. It uses one of the PWM pins on the Uno. I may play with that also, when I get a chance.
Dahammer is offline   Reply With Quote
Old 08-05-2013, 05:07 AM   #139
Indychus
Planted Tank Enthusiast
 
Indychus's Avatar
 
PTrader: (8/100%)
Join Date: Feb 2013
Location: Irmo, SC
Posts: 645
Default

I posted the hex codes for all of the remote functions earlier in the thread somewhere if that helps at all... I had initially tried to use a pwm pin as well but could not get the light to respond at all.

I have an 850 nm and 980 nm led on the way. I also found some 940 nm labeled as "high output"... Their specs seemed just like any other emitters I've seen, but I figured I'd give them a shot so they're on the way too.

I was able to get a range of around 5 feet by cutting the end off of a pen cap, lining the inside with aluminum foil, and sticking the led inside to focus the beam. 5 feet still isn't acceptable though, and there has to be a better solution.

Sent from my HTC One X
__________________
The Fraternity of Dirt
Check out my open-source Arduino-Powered Light Controller Guide for Current LED+ and other IR switchable lights.
Indychus is offline   Reply With Quote
Old 08-05-2013, 01:37 PM   #140
mistergreen
No more Bow ties
 
mistergreen's Avatar
 
PTrader: (13/100%)
Join Date: Dec 2006
Location: Cincinnati
Posts: 14,086
Default

Can't you ask the light manufacturer what wavelength IR they use?
mistergreen is online now   Reply With Quote
Old 08-05-2013, 04:49 PM   #141
Caver
Algae Grower
 
PTrader: (0/0%)
Join Date: Jun 2013
Location: Austin TX
Posts: 56
Default

I have version 2.2 up & running. I'll let you know if I see anything of note.

Along those lines...I find that on my fixture, the delay and resend of the IR code causes an issue with the PowerButton function. It's a toggle, rather than a discrete on/off signal, so the delay & resend ends up where it started. I commented the delay out on that function and it seems to work.

Keep it up guys...
__________________
--
Tom
Caver is offline   Reply With Quote
Old 08-05-2013, 05:26 PM   #142
Indychus
Planted Tank Enthusiast
 
Indychus's Avatar
 
PTrader: (8/100%)
Join Date: Feb 2013
Location: Irmo, SC
Posts: 645
Default

Quote:
Originally Posted by mistergreen View Post
Can't you ask the light manufacturer what wavelength IR they use?
I've been in touch with Current several times trying to get details on the IR system. They don't want the liability that comes with helping consumers hack their products. The guy I talked to was very nice and interested in what I was doing, but also very firm about not releasing any details.
__________________
The Fraternity of Dirt
Check out my open-source Arduino-Powered Light Controller Guide for Current LED+ and other IR switchable lights.
Indychus is offline   Reply With Quote
Old 08-05-2013, 05:29 PM   #143
Indychus
Planted Tank Enthusiast
 
Indychus's Avatar
 
PTrader: (8/100%)
Join Date: Feb 2013
Location: Irmo, SC
Posts: 645
Default

Quote:
Originally Posted by Caver View Post
the delay and resend of the IR code causes an issue with the PowerButton function. It's a toggle, rather than a discrete on/off signal, so the delay & resend ends up where it started.
Keep it up guys...


I was hesitant to program any alarms based on the power toggle for this very reason, and I completely forgot about it when adding the delays. Fixed below, I'll delete the one above.
__________________
The Fraternity of Dirt
Check out my open-source Arduino-Powered Light Controller Guide for Current LED+ and other IR switchable lights.
Indychus is offline   Reply With Quote
Old 08-05-2013, 05:31 PM   #144
Indychus
Planted Tank Enthusiast
 
Indychus's Avatar
 
PTrader: (8/100%)
Join Date: Feb 2013
Location: Irmo, SC
Posts: 645
Default

Version 2.2

Code:
///////////////////////////////////////////////////////////////////
// Current Satellite LED+ Controller  V2.2                       //
//   Indychus...Dahammer...mistergreen @ plantedtank.net         //
//   This code is public domain.  Pass it on.                    //
//   Confirmed on Arduino UNO 1.0.5                              //
//   Req. Time, TimeAlarms, RTClib                               //
///////////////////////////////////////////////////////////////////

////////////SETUP//////////////////////////////////////////////////

#include <Wire.h>
#include <RTClib.h>
#include <Time.h>
#include <TimeAlarms.h>

RTC_DS1307 RTC;

int IRledPin =  13;                  // Pin location for IR output

void setup()               
 { Serial.begin(9600);  
   Wire.begin();
   
   RTC.begin();
  
   if (! RTC.isrunning()) { 
    Serial.println("RTC is NOT running!");
    RTC.adjust(DateTime(__DATE__, __TIME__));  //Adjust to compile time
    }
    setSyncProvider(syncProvider);     //reference our syncProvider function instead of RTC_DS1307::get()

 
  
  pinMode(IRledPin, OUTPUT);         // Designate IRledPin as Output

  ////////////ALARM FUNCTIONS/////////////////////////////////////////
 
 // Note: TimeAlarms.h must be edited to allow for 24 alarms.  By default it is set to 6.
 
  ThunderStorm ();              // Schedule intitial storm
 
  Alarm.alarmRepeat(7,00,0, DawnDusk);
  Alarm.alarmRepeat(9,00,0, Cloud2);     // (HR,MIN,SEC,FUNCTION)
  Alarm.alarmRepeat(13,00,0, FullSpec);
  Alarm.alarmRepeat(15,00,0, Cloud2);
  Alarm.alarmRepeat(19,00,0, DawnDusk);
  Alarm.alarmRepeat(21,00,0, Night2);
  Alarm.alarmRepeat(12,00,00, ThunderStorm); 
}   
////////////THUNDERSTORMS///////////////////////////////////////////// 
void ThunderStorm ()
{ // Called everyday at noon & randomly schedules a storm between 1 & 9 in the evening
  byte RH = random(0,23);                   // Randomizer for thunderstorm
  byte RM = random(0,59);
  byte RS = random(0,59);
  byte TSDurationH = random(0,2); 
  byte TSDurationM = random(0,59);  

  
  if (RH <= 12)
      Serial.print("No storm scheduled today");
      
  if (RH > 12)                             // If random value is after 1 pm, allow storm
      {Alarm.alarmOnce(RH,RM,RS,Storm2);
       Serial.print("Next storm = ");
   Serial.print(RH);
  printDigits(RM);
  printDigits(RS);
  Serial.print("   ");
  Serial.print("Storm duration = ");
   Serial.print(TSDurationH);
  printDigits(TSDurationM);
  
  Serial.println();
      
      if ((RH + TSDurationH) < 19)   // Return to Cloud2 if storm ends between 1-7pm
        {Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,Cloud2);}
      
      else if ((RH + TSDurationH) < 21)  // Return to DawnDusk if storm ends between 7-9pm
        {Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,DawnDusk);}
      
      else                                       // Return to Night2 if storm ends after 9pm
        {Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,Night2);}}}   


////////////CLOCK///////////////////////////////////////////////////
void  loop(){                       
  digitalClockDisplay();
  Alarm.delay(900000);               // Clock display update frequency (msec)
}

time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{return RTC.now().unixtime();}

void digitalClockDisplay()          // Digital clock
{ Serial.print("Current Time = ");
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); }

void printDigits(int digits)        // Add :
{Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);}


////////////SIGNAL///////////////////////////////////////////////////
// Create Frequency (38khz/26msec)
void pulseIR(long microsecs) 
{  cli();                           // kill interupts
  while (microsecs > 0)
  { digitalWrite(IRledPin, HIGH);    // ~3 msec
    delayMicroseconds(7);            // ~delay
    digitalWrite(IRledPin, LOW);     // ~3 msec
    delayMicroseconds(7);            // ~delay
    microsecs -= 26;  }
  sei();  }                           // zombie interupts


////////////FIXTURE FUNCTIONS////////////////////////////////////////
void DeviceID ()
{
  int codes[17][2] = { 
    {8840,4320}, 
    {620,480}, 
    {600,500}, 
    {540,1660}, 
    {580,520}, 
    {520,560}, 
    {600,480},
    {620,480}, 
    {540,540}, 
    {620,1600}, 
    {520,1660}, 
    {580,520},
    {520,1660}, 
    {600,1580}, 
    {620,1580}, 
    {540,1660}, 
    {600,1580}};

  for( int i = 0 ; i < 17; i++) {
    pulseIR(codes[i][0]);
    delayMicroseconds(codes[i][1]);}}

void Footer ()
{int codes[3][2] = { 
    {580,1620},
    {540,38980},
    {8860,2120}};

  for( int i = 0 ; i < 3; i++) {
    pulseIR(codes[i][0]);
    delayMicroseconds(codes[i][1]);}
  pulseIR(620);}

void IR(int codes[15][2]) 
{DeviceID();

  for( int i = 0 ; i < 15; i++) {
    pulseIR(codes[i][0]);
    delayMicroseconds(codes[i][1]);}  
  Footer(); }

void PowerButton()                             //Fixture power on/off toggle
{int codes[15][2] = { 
    {600,500},
    {600,500},
    {520,560},
    {600,500},
    {600,500},
    {520,560},
    {580,1620},
    {540,540},
    {600,1600},
    {520,1660},
    {580,1620},
    {580,1620},
    {520,1660},
    {580,1600},
    {580,520}}; 
  IR(codes);
   Serial.println("Power Toggle");}

void Night2()                                   //Fixture Initialize Night2 Mode
{int codes[15][2] = { 
    {600,1640},
    {600,500},
    {520,560},
    {600,1620},
    {600,1640},
    {520,560},
    {580,540},
    {540,540},
    {600,480},
    {520,1660},
    {580,1620},
    {580,500},
    {520,500},
    {580,1600},
    {580,1560}}; 
  IR(codes);
  Alarm.delay(1000); // Wait 1 second & resend
  IR(codes);
  Serial.println("Night 2 Mode Initialized");}

void Cloud2()                                         //Fixture Initialize Cloud2 Mode
{int codes[15][2] = { 
    {600,1580},
    {600,500},
    {520,1620},
    {600,500},
    {600,1600},
    {520,560},
    {580,480},
    {540,540},
    {600,560},
    {520,1660},
    {580,560},
    {580,1620},
    {520,560},
    {580,1600},
    {580,1640}};
  IR(codes);
  Alarm.delay(1000); // Wait 1 second & resend
  IR(codes);
  Serial.println("Cloud Cover 2 Mode Initialized");}

void FullSpec()                                  //Fixture Initialize Full Spectrum Mode
{int codes[15][2] = { 
    {600,1580},
    {600,500},
    {520,480},
    {600,1580},
    {600,1600},
    {520,560},
    {580,1600},
    {540,540},
    {600,560},
    {520,1660},
    {580,1580},
    {580,540},
    {520,560},
    {580,1600},
    {580,480}};
  IR(codes);
  Alarm.delay(1000); // Wait 1 second & resend
  IR(codes);
  Serial.println("Full Spectrum Mode Initialized");}

void DawnDusk()                         // Fixture Initialize Dawn/Dusk Mode
{int codes[15][2] = { 
    {600,1660},
    {600,1560},
    {520,480},
    {600,1580},
    {600,1600},
    {520,560},
    {580,500},
    {540,540},
    {600,560},
    {520,500},
    {580,1580},
    {580,540},
    {520,560},
    {580,1660},
    {580,1580}};
  IR(codes);
  Alarm.delay(1000); // Wait 1 second & resend
  IR(codes);
  Serial.println("Dawn/Dusk Mode Initialized");}

void Storm2()                         //Fixture Initialize Storm2 Mode
{  int codes[15][2] = { 
    {600,1660},
    {600,540},
    {520,480},
    {600,500}, 
    {600,1600},
    {520,560},
    {580,500},
    {540,540},
    {600,560},
    {520,1660},
    {580,1580},
    {580,1620},
    {520,560},
    {580,1660},
    {580,1580}};
  IR(codes);
  Alarm.delay(1000); // Wait 1 second & resend
  IR(codes);
  Serial.println("Storm2 Mode Initialized");}
__________________
The Fraternity of Dirt
Check out my open-source Arduino-Powered Light Controller Guide for Current LED+ and other IR switchable lights.
Indychus is offline   Reply With Quote
Old 08-05-2013, 07:27 PM   #145
Caver
Algae Grower
 
PTrader: (0/0%)
Join Date: Jun 2013
Location: Austin TX
Posts: 56
Default

No biggie Indychus.

Having done some coding in Basic back in the day...I remember how easy it is to overlook something like that, especially if your mind is occupied with another function that is giving you problems...

It just so happened I wanted to use the PowerButton function to turn the light completely off at bedtime and back on the next day, so I noticed it when turn-on time came up.

Also...I originally wanted to turn the light off at midnight, but it didn't like 00:00:00...(nothing happened). I didn't try 24:00:00...but 23:59:00 works and is close enough...

Looking forward to seeing your progress on this project, especially a resolution the the IR wavelength question. I think that will help range issues some of us are seeing.

I'm really enjoying this controller project, so much so, I ordered another LED+ for my 6 gal tank so both my aquariums will be running off this controller. I'm also collecting the parts to make an Arduino dual channel digital thermometer to monitor both tanks.

I haven't gotten this enthused over a home DIY electronics project in many years!
__________________
--
Tom
Caver is offline   Reply With Quote
Old 08-05-2013, 07:37 PM   #146
Indychus
Planted Tank Enthusiast
 
Indychus's Avatar
 
PTrader: (8/100%)
Join Date: Feb 2013
Location: Irmo, SC
Posts: 645
Default

I'm not sure what the issue with 00:00:00 is... I had originally scheduled the t-storm reset to be at midnight, but it never fired so I changed it to noon.

Arduino is addictive once you realize what it is capable of. There are a lot of other microcontrollers aimed towards DIY tinkerers (I particularly like raspberry pi), but Arduino's IDE is so easy to use and the community is so vast that for me it's hard to justify using anything else for most projects.
__________________
The Fraternity of Dirt
Check out my open-source Arduino-Powered Light Controller Guide for Current LED+ and other IR switchable lights.
Indychus is offline   Reply With Quote
Old 08-06-2013, 01:22 AM   #147
Dahammer
Algae Grower
 
PTrader: (0/0%)
Join Date: Oct 2010
Location: Mississippi
Posts: 118
Default

When I got home this afternoon I had every intention of trying to measure the current going through the LED in my test board. But wouldn’t you know it, my cheap DMM won’t measure more than 200mA! So confident I was pushing more than that through the LED, I went in a different direction. I'm going to have to get better tools to work with.

I decided to test Ken Shirriff’s IRremote library. I’m having rather good luck with it. I can operate the fixture from around 10 feet pretty reliably using it. After I get beyond 10 feet, it is hit or miss. That’s better than it was though.

Here is my test code, if any of you want to play with it. Just download & install the library. You use the serial monitor to send in numbers for the commands that you want to test. The numbering follows the remote left to right, top to bottom. All of the ones I tested work with my fixture but I didn’t test them all.

Please note that the pin configuration is different than it is in IndyChus's code. You'll need your IR LED circuit connected to PIN 3 on the Arduino instead of PIN 13.

Code:
// IR tests for Current Satellite+ fixtures
// This codes uses Ken Shirriff's IR library
// http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
//
// You'll need Ken's library to use this code
// You'll need to connect your IR LED circuit to PIN 3 on the Arduino
//
// Use the serial monitor in the Arduino software to send numbers to the Arduino Uno
// The code accepts 1 - 32. See below

#include <IRremote.h>

IRsend irsend;

int cmd = 0;

void setup()
{
  Serial.begin(9600);
}

void loop() {
  
  if (Serial.available() > 0) { // wait for something to be sent
    
    delay(5); //Wait for transmission to finish
    cmd = SerialReadInt();
    Serial.print("You entered: ");
    Serial.println(cmd);
    CurrentCMDs();
  }
}

int SerialReadInt()
{
  int i, numAva;
  char inBytes[3];                  // Array to hold the bytes
  char * inBytesPtr = &inBytes[0];  // Pointer to the first element of the array
      
    numAva = Serial.available();  // Read number of input bytes
    if (numAva > 2)
      numAva = 2; // Only allow 2 characters to prevent overflow
      
    for (i=0; i<numAva; i++)       // Load input bytes into array
      inBytes[i] = Serial.read();
    inBytes[i] =  '\0';             // Put NULL character at the end
    return atoi(inBytesPtr);
}

void CurrentCMDs() {
    //Serial.println(cmd);
    
    switch (cmd) {
      case 1:
        irsend.sendNEC(0x20DF3AC5,32); // Orange
        break;
      case 2:
        irsend.sendNEC(0x20DFBA45,32); // Blue
        break;
      case 3:
        irsend.sendNEC(0x20DF827D,32); // Rose
        break;
      case 4:
        irsend.sendNEC(0x20DF02FD,32); // Power On/Off
        break;
      case 5:
        irsend.sendNEC(0x20DF1AE5,32); // White
        break;
      case 6:
        irsend.sendNEC(0x20DF9A65,32); // FullSpec
        break;
      case 7:
        irsend.sendNEC(0x20DFA25D,32); // Purple
        break;
      case 8:
        irsend.sendNEC(0x20DF22DD,32); // Play/Pause
        break;
      case 9:
        irsend.sendNEC(0x20DF2AD5,32); // Red Up
        break;
      case 10:
        irsend.sendNEC(0x20DFAA55,32); // Green Up
        break;
      case 11:
        irsend.sendNEC(0x20DF926D,32); // Blue Up
        break;
      case 12:
        irsend.sendNEC(0x20DF12ED,32); // White Up
        break;
      case 13:
        irsend.sendNEC(0x20DF0AF5,32); // Red Down
        break;
      case 14:
        irsend.sendNEC(0x20DF8A75,32); // Green Down
        break;
      case 15:
        irsend.sendNEC(0x20DFB24D,32); // Blue Down
        break;
      case 16:
        irsend.sendNEC(0x20DF32CD,32); // White Down
        break;
      case 17:
        irsend.sendNEC(0x20DF38C7,32); // M1 Custom
        break;
      case 18:
        irsend.sendNEC(0x20DFB847,32); // M2 Custom
        break;
      case 19:
        irsend.sendNEC(0x20DF7887,32); // M3 Custom
        break;
      case 20:
        irsend.sendNEC(0x20DFF807,32); // M4 Custom
        break;
      case 21: // 1
        irsend.sendNEC(0x20DF18E7,32); // Moon1
        break;
      case 22:
        irsend.sendNEC(0x20DF9867,32); // Moon2
        break;
      case 23:
        irsend.sendNEC(0x20DF58A7,32); // Moon3
        break;
      case 24:
        irsend.sendNEC(0x20DFD827,32); // DawnDusk
        break;
      case 25:
        irsend.sendNEC(0x20DF28D7,32); // Cloud1
        break;
      case 26:
        irsend.sendNEC(0x20DFA857,32); // Cloud2
        break;
      case 27:
        irsend.sendNEC(0x20DF6897,32); // Cloud3
        break;
      case 28:
        irsend.sendNEC(0x20DFE817,32); // Cloud4
        break;
      case 29:
        irsend.sendNEC(0x20DF08F7,32); // Storm1
        break;
      case 30:
        irsend.sendNEC(0x20DF8877,32); // Storm2
        break;
      case 31:
        irsend.sendNEC(0x20DF48B7,32); // Storm3
        break;
      case 32:
        irsend.sendNEC(0x20DFC837,32); // Storm 4
        break;
      default:
        irsend.sendNEC(0x20DF9A65,32); // FullSpec
      }
      delay(40);
}
Dahammer is offline   Reply With Quote
Old 08-06-2013, 08:27 AM   #148
Dahammer
Algae Grower
 
PTrader: (0/0%)
Join Date: Oct 2010
Location: Mississippi
Posts: 118
Default

I went ahead and added IndyChus' code to the code I was testing using the IRremote library. It seems to be working for me, but it needs testing.

It uses Ken Shirriff's IRremote library, which means it uses Pin 3 on the Uno versus Pin 13.

I've built in the ability to send in commands via the serial monitor for testing each code. There are of course 32 of them, 1 for each button on the remote. They start with the top left button (Orange) being 1 and go left to right, top to bottom, ending with the bottom right button (Storm4) being 32. If you comment out the "#define DEBUG_IR" at the top, this option won't be included, saving a little space.

I "think" I fixed a bug in the ThunderStorm() routine where it wasn't generating real random numbers. Most of the time I was getting my storms scheduled at 17:05:36 for 46 minutes or something like that. Now I get a different time every time. It does require an unused analog pin. I've set that to analog pin 0, if that isn't open on yours then change it to something else.

If the alarmRepeat() function would allow you to pass an argument to the function it sets the alarm on, this code could be made smaller. We could modify the TimeAlarms library to make it happen, if we need the space.

Code:
///////////////////////////////////////////////////////////////////
// Current Satellite LED+ Controller  V3.2                       //
//   Indychus...Dahammer...mistergreen @ plantedtank.net         //
//   This code is public domain.  Pass it on.                    //
//   Confirmed on Arduino UNO 1.0.5                              //
//   Req. Time, TimeAlarms, RTClib, IRremote                     //
///////////////////////////////////////////////////////////////////
//
// This version uses Ken Shirriff's IRremote library to Rx/Tx the IR codes
// http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
// 
// This code does NOT use PIN 13 on the Uno, as do previous versions
// Instead PIN 3, which is a PWM pin, is used. So you'll need to connect
// your LED to PIN 3 instead of PIN 13 for it to work.

#include <Wire.h>
#include <RTClib.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <IRremote.h>

RTC_DS1307 RTC;
IRsend irsend;

/*********** BEGIN USER DEFINED VARIABLES ***********/
// DEBUG_IR adds the option to test the IR commands via the Arduino software's serial monitor
// You can send any value from 1 to 32 and it send the corresponding IR code
// The codes follow the remote controller, left to right, top to bottom
// e.g 1 = Orange, 2 = Blue, 21 = Moon1, etc
#define DEBUG_IR

int postDelay = 100;         // Delay after codes are sent
int randAnalogPin = 0;       // This needs to be set to an unused Analog pin, Used by ThunderStorm()

// Current Satellite+ IR Codes (NEC Protocol)
unsigned long codeHeader = 0x20DF; // Always the same

// Remote buttons listed left to right, top to bottom
unsigned int codeOrange = 0x3AC5;
unsigned int codeBlue = 0xBA45;
unsigned int codeRose = 0x827D;
unsigned int codePowerOnOff = 0x02FD;
unsigned int codeWhite = 0x1AE5;
unsigned int codeFullSpec = 0x9A65;
unsigned int codePurple = 0xA25D;
unsigned int codePlay = 0x22DD;
unsigned int codeRedUp = 0x2AD5;
unsigned int codeGreenUp = 0xAA55;
unsigned int codeBlueUp = 0x926D;
unsigned int codeWhiteUp = 0x12ED;
unsigned int codeRedDown = 0x0AF5;
unsigned int codeGreenDown = 0x8A75;
unsigned int codeBlueDown = 0xB24D;
unsigned int codeWhiteDown = 0x32CD;
unsigned int codeM1Custom = 0x38C7;
unsigned int codeM2Custom = 0xB847;
unsigned int codeM3Custom = 0x7887;
unsigned int codeM4Custom = 0xF807;
unsigned int codeMoon1 = 0x18E7;
unsigned int codeMoon2 = 0x9867;
unsigned int codeMoon3 = 0x58A7;
unsigned int codeDawnDusk = 0xD827;
unsigned int codeCloud1 = 0x28D7;
unsigned int codeCloud2 = 0xA857;
unsigned int codeCloud3 = 0x6897;
unsigned int codeCloud4 = 0xE817;
unsigned int codeStorm1 = 0x08F7;
unsigned int codeStorm2 = 0x8877;
unsigned int codeStorm3 = 0x48B7;
unsigned int codeStorm4 = 0xC837;

void SetAlarms()
{
  // Set up your desired alarms here
  // The default value of dtNBR_ALARMS is 6 in Alarms.h.
  // This code sets 12 alarms by default, so you'll need to change dtNBR_ALARMS to 12 or more
  Alarm.alarmRepeat(7,00,0, DawnDusk);
  Alarm.alarmRepeat(9,00,0, Cloud2);     // (HR,MIN,SEC,FUNCTION)
  Alarm.alarmRepeat(11,00,0, FullSpec);
  Alarm.alarmRepeat(15,00,0, Cloud2);
  Alarm.alarmRepeat(19,00,0, DawnDusk);
  Alarm.alarmRepeat(21,00,0, Moon2);
  
  ThunderStorm(); // Sets up intial storm; Comment out if you don't want storms; Adds 4 additional Alarms  
}
/************* END USER DEFINED VARIABLES *************/

void setup()
{
  Wire.begin();
  RTC.begin();
  Serial.begin(9600);
  
  if (! RTC.isrunning()) { 
    Serial.println("RTC is NOT running!");
    RTC.adjust(DateTime(__DATE__, __TIME__));  //Adjust to compile time
    }
  
  setSyncProvider(syncProvider);     //reference our syncProvider function instead of RTC_DS1307::get()
  
  Alarm.timerRepeat(900, digitalClockDisplay);  // Display the time every 15 minutes
  digitalClockDisplay();
  SetAlarms();
}

void loop()
{
#ifdef DEBUG_IR 
  if (Serial.available() > 0) {
    delay(5); //Wait for transmission to finish
    CurrentCMDs(SerialReadInt());
  }
#endif
  Alarm.delay(100);               // Service alarms & wait (msec)
}

time_t syncProvider()
{
  //this does the same thing as RTC_DS1307::get()
  return RTC.now().unixtime();
}

void ThunderStorm ()
{ 
  // Schedules a storm between 1 & 9 in the evening
  randomSeed(analogRead(randAnalogPin));  // Generate random seed on unused pin
  byte RH = random(23);                   // Randomizer for thunderstorm
  byte RM = random(59);
  byte RS = random(59);
  byte TSDurationH = random(2);
  byte TSDurationM = random(59);
  
  Alarm.alarmRepeat(12,00,00, ThunderStorm); // Sets an alarm to call this code every day

  if (RH <= 12)
    {
      Serial.println("No storm scheduled today");
      return;
    }
      
  if (RH > 12)                             // If random value is after 1 pm, allow storm
    {
      Alarm.alarmOnce(RH,RM,RS,Storm2);
      Serial.print("Next storm = ");
      Serial.print(RH);
      printDigits(RM);
      printDigits(RS);
      Serial.print("   ");
      Serial.print("Storm duration = ");
      Serial.print(TSDurationH);
      printDigits(TSDurationM);
      Serial.println();
      
      if ((RH + TSDurationH) < 19)   // Return to Cloud2 if storm ends between 1-7pm
        {
          Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,Cloud2);
        }
      else if ((RH + TSDurationH) < 21)  // Return to DawnDusk if storm ends between 7-9pm
        {
          Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,DawnDusk);
        }
      else                                       // Return to Night2 if storm ends after 9pm
        {
          Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,Moon2);
        }
    }
}

void digitalClockDisplay()          // Digital clock
{ 
  Serial.print("Current Time = ");
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)        // Add :
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

#ifdef DEBUG_IR
int SerialReadInt()
{
  int i, numAva;
  char inBytes[3];                  // Array to hold the bytes
  char * inBytesPtr = &inBytes[0];  // Pointer to the first element of the array
      
    numAva = Serial.available();    // Read number of input bytes
    if (numAva > 2)
      numAva = 2;                   // Only allow 2 characters to prevent overflow
      
    for (i=0; i<numAva; i++)        // Load input bytes into array
      inBytes[i] = Serial.read();
    inBytes[i] =  '\0';             // Put NULL character at the end
    return atoi(inBytesPtr);        // Call atoi function and return result
}

void CurrentCMDs (int cmd)
{
  switch (cmd)
  {
    case 1:
      Orange();
      break;
    case 2:
      Blue();
      break;
    case 3:
      Rose();
      break;
    case 4:
      PowerOnOff();
      break;
    case 5:
      White();
      break;
    case 6:
      FullSpec();
      break;
    case 7:
      Purple();
      break;
    case 8:
      Play();
      break;
    case 9:
      RedUp();
      break;
    case 10:
      GreenUp();
      break;
    case 11:
      BlueUp();
      break;
    case 12:
      WhiteUp();
      break;
    case 13:
      RedDown();
      break;
    case 14:
      GreenDown();
      break;
    case 15:
      BlueDown();
      break;
    case 16:
      WhiteDown();
      break;
    case 17:
      M1Custom();
      break;
    case 18:
      M2Custom();
      break;
    case 19:
      M3Custom();
      break;
    case 20:
      M4Custom();
      break;
    case 21:
      Moon1();
      break;
    case 22:
      Moon2();
      break;
    case 23:
      Moon3();
      break;
    case 24:
      DawnDusk();
      break;
    case 25:
      Cloud1();
      break;
    case 26:
      Cloud2();
      break;
    case 27:
      Cloud3();
      break;
    case 28:
      Cloud4();
      break;
    case 29:
      Storm1();
      break;
    case 30:
      Storm2();
      break;
    case 31:
      Storm3();
      break;
    case 32:
      Storm4();
      break;
    default:
      Serial.println("Invalid Choice");
    }
}
#endif

void SendCode (unsigned int code, byte numTimes, const char *sMessage)
{
  unsigned long irCode = (codeHeader << 16) + code; // Header is 2 bytes, shift all the way to left & add code to it
  
  for( int i = 0; i < numTimes; i++)
  {
    irsend.sendNEC(irCode,32); // Send code
    Alarm.delay(postDelay);
  }
  Serial.print(sMessage);  // Print message
  digitalClockDisplay();
}

void Orange()
{ 
  SendCode(codeOrange, 2, "Orange: "); 
}

void Blue()
{ 
  SendCode(codeBlue, 2, "Blue: "); 
}

void Rose()
{ 
  SendCode(codeRose, 2, "Rose: "); 
}

void PowerOnOff()
{ 
  SendCode(codePowerOnOff, 1, "Power On/Off: ");
}

void White()
{ 
  SendCode(codeWhite, 2, "White: "); 
}

void FullSpec()
{
  SendCode(codeFullSpec, 2, "FullSpec: ");
}

void Purple()
{
  SendCode(codePurple, 2, "Purple: ");
}

void Play()
{ 
  SendCode(codePlay, 1, "Play/Pause: ");
}

void RedUp()
{
  SendCode(codeRedUp, 1, "RedUp: ");
}

void GreenUp()
{
  SendCode(codeGreenUp, 1, "GreenUp: ");
}

void BlueUp()
{
  SendCode(codeBlueUp, 1, "BlueUp: ");
}

void WhiteUp()
{
  SendCode(codeWhiteUp, 1, "WhiteUp: ");
}

void RedDown()
{
  SendCode(codeRedDown, 1, "RedDown: ");
}

void GreenDown()
{
  SendCode(codeGreenDown, 1, "GreenDown: ");}

void BlueDown()
{
  SendCode(codeBlueDown, 1, "BlueDown: ");
}

void WhiteDown()
{
  SendCode(codeWhite, 1, "WhiteDown: ");
}

void M1Custom()
{
  SendCode(codeM1Custom, 2, "M1Custom: ");
}

void M2Custom()
{
  SendCode(codeM2Custom, 2, "M2Custom: ");
}

void M3Custom()
{
  SendCode(codeM3Custom, 2, "M3Custom: ");
}

void M4Custom()
{
  SendCode(codeM4Custom, 2, "M4Custom: ");
}

void Moon1()
{
  SendCode(codeMoon1, 2, "Moon1: ");
}

void Moon2()
{
  SendCode(codeMoon2, 2, "Moon2: ");
}

void Moon3()
{
  SendCode(codeMoon3, 2, "Moon3: ");
}

void DawnDusk()
{
  SendCode(codeDawnDusk, 2, "DawnDusk: ");
}

void Cloud1()
{
  SendCode(codeCloud1, 2, "Cloud1: ");
}

void Cloud2()
{
  SendCode(codeCloud2, 2, "Cloud2: ");
}
  
void Cloud3()
{
  SendCode(codeCloud3, 2, "Cloud3: ");
}

void Cloud4()
{
  SendCode(codeCloud4, 2, "Cloud4: ");
}

void Storm1()
{
  SendCode(codeStorm1, 2, "Storm1: ");
}

void Storm2()
{
  SendCode(codeStorm2, 2, "Storm2: ");
}

void Storm3()
{
  SendCode(codeStorm3, 2, "Storm3: ");
}

void Storm4()
{
  SendCode(codeStorm4, 2, "Storm4: ");
}

Last edited by Dahammer; 08-08-2013 at 03:02 AM.. Reason: Updated code
Dahammer is offline   Reply With Quote
Old 08-06-2013, 08:24 PM   #149
Indychus
Planted Tank Enthusiast
 
Indychus's Avatar
 
PTrader: (8/100%)
Join Date: Feb 2013
Location: Irmo, SC
Posts: 645
Default

Looks good! Can't wait to get back to the house and try it out. I was supposed to be on the way home now, but we had some delays on the project I'm working on currently and probably won't be home until Friday.

Are you still using the transistor amplifier circuit, or is that 10 ft range with just the LED and resistor?

Sent from my HTC One X
__________________
The Fraternity of Dirt
Check out my open-source Arduino-Powered Light Controller Guide for Current LED+ and other IR switchable lights.
Indychus is offline   Reply With Quote
Old 08-06-2013, 09:17 PM   #150
Dahammer
Algae Grower
 
PTrader: (0/0%)
Join Date: Oct 2010
Location: Mississippi
Posts: 118
Default

Quote:
Originally Posted by Indychus View Post
Looks good! Can't wait to get back to the house and try it out. I was supposed to be on the way home now, but we had some delays on the project I'm working on currently and probably won't be home until Friday.

Are you still using the transistor amplifier circuit, or is that 10 ft range with just the LED and resistor?

Sent from my HTC One X
The 10' is with a transistor, a 2N2222. The only resistor is a 133ohm between the transistor base and pin 3. I'm going to drop that to 120ohm though when I pick one up. I have enough range for my purposes as is but I'd still like to extend it. I'll probably experiment with some other LEDs and possibly a MOSFET when I get time.
Dahammer is offline   Reply With Quote
Reply

Tags
arduino, automation, current led+, diy, light controller

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 02:06 AM.


Powered by vBulletin®
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Copyright Planted Tank LLC 2012