The Planted Tank Forum - View Single Post - Guide: Arduino based LED controller for Current Satellite LED+
View Single Post
Old 08-06-2013, 09:27 AM   #148
Dahammer
Algae Grower
 
PTrader: (0/0%)
Join Date: Oct 2010
Location: Mississippi
Posts: 119
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 04:02 AM.. Reason: Updated code
Dahammer is offline   Reply With Quote