The Planted Tank Forum banner

Guide: Arduino based LED controller for Current Satellite LED+

174K views 715 replies 69 participants last post by  Dahammer 
#1 · (Edited)
So I made an off-hand comment in one of Current USA's threads last night about an Arduino controller for their LED+ freshwater fixture. In the 12 or so hours since posting that, I have probably received a dozen PM's requesting code, IR protocol, sketches, or other information. Instead of responding to each request for information separately, it became obvious that I just needed to put together a thread for my project. This is that thread.

First, a disclaimer. While I'm not your average DIY tinkerer, I'm also not an electronics expert. I'm a mechanical engineer by day, and like to think of myself as a modern mad scientist by night. If you decide to build your own controller based on this thread, be aware that you're on your own. That's not to say I won't help... I think open source is the way of the future and love to pass knowledge on. I just mean that if you burn up your Arduino, yourself, or your house, that it's on you.

I'm putting together a guide to follow along, but none of the steps should be considered the last step. The nice thing about Arduino is how easy it is to constantly modify your code and add features. Throughout this thread, I will periodically post my newest code so that you can upload it and get the newer features. If you're experienced with Arduino, feel free to hack my code apart and have your way with it.

This process should work for any light fixture with some tweaking!

I'm writing this step-by-step so hopefully anyone can follow along. The more Arduino users we have in the world, the better life can be for everyone! If you're new to Arduino, don't be overwhelmed... it's not as difficult as it seems at first glance. And if you're an old hand please don't bash my primitive coding too much!



Everything in this post should be considered open source and public domain. Feel free to use my code, distribute it, hack it up, whatever.
 
See less See more
#299 ·
Thanks for the info.

I read a little on the millis function.

I'm going to have to sleep on that one and try again later. My brain doesn't want to wrap around that tonight.

It was a busy day...building up the display, testing sensors and playing with the code.

I also installed connectors on the sensors and the IR LED to facilitate tearing the unit apart for mods.

I think it's time to kick back, watch the fish and turn my brain off. :sleep:
 
#300 ·
something like this

Code:
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

void setup() {
    // print initially so we don't have to wait around 
    // for a minute for the temperature to show up
    temperaturePrint();
}

void loop() {
//some code

  currentMillis = millis();
 //every minute
 if(currentMillis - previousMillis > 60000) {
    // save the last time
    previousMillis = currentMillis;
    temperaturePrint();
  }

}

void temperaturePrint() {
    //temperature stuff   
    sensors.requestTemperatures();
    lcd.setCursor(0,2);
    lcd.print("Tank 1: ");
    printTemperature(insideThermometer);
    lcd.setCursor(0,3);
    lcd.print("Tank 2: ");
    printTemperature(outsideThermometer);
}
 
#301 · (Edited)
How often are you wanting to update the temperature readings? I noticed that you have 2 calls to lcd.begin() in setup, only one is needed. You can also call sensors.getTempF instead of sensors.getTempC if you want the temp in Fahrenheit. But getTempF just calls toFahrenheit which is what you are doing as well. Haha!

You can also add the special character degree symbol using createChar function, which is part of the LiquidCrystal library.

Edit:
Actually, it may already be included, try this or check the datasheet for your LCD:

lcd.print((char)223));
 
#304 ·
Actually, it may already be included, try this or check the datasheet for your LCD:

lcd.print((char)223));
Your above trick works to print the degree symbol, but I had to remove one of the close parenthesis to get it to compile.

Thanks for all the ideas. I'm going to have to study to figure out how to implement them.

This was my very clumsy beginner attempt at programming the Arduino for my specific application. I haven't done any programming in literally decades...so I'm going to make a lot of very basic mistakes.

For this sketch I literally copied pieces of a tutorial sketch for an indoor/outdoor thermometer and pasted the pieces into v4 where I thought they needed to go. I'm sure there's all kinds of 'wrong' stuff!

Some things I've noticed with my controller running on the bench tonight...Every so often, right after a code is sent, the temperature goes to 3 decimal places. I thought I had it set for 2 by setting the sensors to 9 bit resolution. Obviously I'm missing something. Actually, I'd be satisfied with 1 decimal place for the temp.

Oh well...almost bedtime. Maybe some of this coding stuff will make more sense to me after I get some sleep and a couple of cups of coffee in the morning.
 
#305 · (Edited)
Oops, sorry. Yeah, 1 too many parenthesis.

What sensor do you have? Check out the calculateTemperature function in DallasTemperature.cpp. Looking at the datasheet, I'm guessing you have a DS18S20 based sensor, since it allows for more than 1 sensor on the same wire. For that sensor, the code in calculateTemperature function calculates an extended resolution regardless of what you set it too.
 
#308 ·
Yeah,

The temp reading to 2 decimal places is a pretty minor thing.

I'm studying the coding for reading the sensors so I can understand the delays and your suggestions for using millis. If I'm understanding what I'm reading correctly...the sensors need approx. 750 mS to complete a read and transfer data.

I just want to clean up the code so the system doesn't barf on me after running a few hours/days...:eek:

Of course if someone on here wants to do the thermometer thing and knows how to clean it up, I have no qualms with riding coat tails...:icon_mrgr
 
#312 ·
I'm not sure how to even begin mistergreen...

Basically I'm trying to clean up my sketch from post #296, where I patched in code for two DS18B20 thermometers to the light controller.

There were some comments that the 1 second delay in the loop function for the sensors would cause problems, so I'm trying to do something other than the standard delay that stops the whole device. From what I've read on the sensors, they need a delay in polling or they'll get errors.

You and DaHammer suggested the Alarm.timerRepeat and moving the print code...etc. I've tried multiple iterations based on the tutorials I've read and get many different errors.

I suspect it has to do with the passing of the sensor device addresses and I'm probably messing up moving the print and sensor address code.

I'm so new at this coding process, I'm probably overlooking something very basic. I can build hardware all day long, but software is much more difficult for me.
 
#314 · (Edited)
Try this:

Up at the top, redefine your sensor addresses to this (makes more sense since you're not really doing inside & outside):

Code:
DeviceAddress thermometer_1 = { 0x28, 0x98, 0x82, 0xA8, 0x04, 0x00, 0x00, 0x6D }; //Red
DeviceAddress thermometer_2 = { 0x28, 0xA6, 0x33, 0xA8, 0x04, 0x00, 0x00, 0x11 }; //blue
Changing the names will also require changing the setResolution calls in Setup():
Code:
  sensors.setResolution(thermometer_1, 9);
  sensors.setResolution(thermometer_2, 9);
Then add this following code to the SetAlarms() function, doesn't matter where you add it. You can also change the alarm frequency if you like. It's second based, but alarming every second would probably cause problems.
Code:
  Alarm.timerRepeat(1800, PrintTemp);  // Print temps every 30 minutes
  PrintTemp(); // Display initial temps
Then add the following function somewhere:
Code:
void PrintTemp()
{
  float tempC = sensors.getTempC(thermometer_1);
  lcd.setCursor(0,2);
  lcd.print("Tank: 1 ");
  lcd.print(DallasTemperature::toFahrenheit(tempC), 1);
  lcd.print((char)223);
  
  tempC = sensors.getTempC(thermometer_2);
  lcd.setCursor(0,3);
  lcd.print("Tank 2: ");
  lcd.print(DallasTemperature::toFahrenheit(tempC), 1);
  lcd.print((char)223);
}
Then remove the code you put in the loop() function, as well the printTemperature function that you added. You could also add code to the TestCodes() function so that you could initiate a test from the serial terminal.

Code:
void TestCodes (int cmd)
{
  // Handles commands sent in from the serial monitor
  if (cmd >= 1 && cmd <= 32)
    { 
      // cmd must be 1 - 32
      SendCode(cmd-1, 1);
    }
    else if (cmd == 33)
    {
    	PrintTemp();  // Send 33 to test temp sensors
    }
    else { printf_P(PSTR("Invalid Choice\n")); }
}
 
#315 · (Edited)
Let me play with it for a bit and when I get my best guess I'll post something.

Right now I've tried 5-6 variations and I don't have any idea which is closer and I get different and complex error messages each time.

One specific question...the example sketch in the TimeAlarms library shows the "Alarm.timerRepeat(15, Repeats);" statement going in "void setup()".

I'm assuming I should be able to add the same statement to the setup section of the controller code as in the above example and pull the section of code dealing with polling and printing the sensors currently in "void loop()" and creating another function (for the sake of simplicity) called "void Repeats()".

Also as I understand it, I can change the 15 to any value down to 1. Can 'Repeats' be changed to another function name?

The section of code I'm pulling out of the loop is

delay(1000) // Supposedly this is what needs to be pulled out of the loop
sensors.requestTemperatures();
lcd.setCursor(0,2);
lcd.print("Tank 1: ");
printTemperature(insideThermometer);
lcd.print((char)223);
lcd.setCursor(0,3);
lcd.print("Tank 2: ");
printTemperature(outsideThermometer);
lcd.print((char)223);

I'm adding it back in outside the loop as...

void Repeats();
{
sensors.requestTemperatures();
lcd.setCursor(0,2);
lcd.print("Tank 1: ");
printTemperature(insideThermometer);
lcd.print((char)223);
lcd.setCursor(0,3);
lcd.print("Tank 2: ");
printTemperature(outsideThermometer);
lcd.print((char)223);
}

I'm thinking there's something in there that the Alarm.timerRepeat can't process. It doesn't seem to matter where I put it. I get different error messages every time.

That's basically what I've been trying.

As for polling frequency...I'd like something at least every few seconds so it would react quickly to changing conditions. Sure...most of the time it wouldn't be necessary, but the nerd in me wants 'realtime' data...:icon_mrgr

I see DaHammer has responded with some code for me to try. I just tried it, but I got some errors. I probably made a typo or something. I'm going to get something to eat and play with it some more.

Thanks for all the help. I don't mean to distract from the original direction of the thread for my customizations. If we get too far out in left field, just say so. This is a really cool gadget even without the thermometers...:proud:
 
#316 ·
I corrected a typo or 2, so you may want to retry the code above if you copied it after I first posted it.

Consider the following call:
Code:
Alarm.alarmRepeat(1800, PrintTemp);
1800 is number of seconds to wait. PrintTemp is the function that will be called after 1800 seconds. You can change 1800 to any value you like, up to 24 hours best I recall, but I wouldn't do it every second. If you did, then you'll likely run into problems with the sensors not being able to keep up with the demand. Besides the temperature should be rather stable, so it's really not necessary to poll them so frequently. PrintTemp is just a name of a function. It can be changed to the name of any valid function in the program that you want to call with the timer.
 
#318 · (Edited)
Hi Guys,

It works ! :bounce:
I input DaHammers suggestions. I corrected a couple of typos. In the printTemp routine I changed a Serial.print call to lcd.print to get the temps to display.

I changed the Alarm.alarmRepeat to Alarm.timerRepeat and put it in with the rest of the alarms. Otherwise the temps apparently weren't updating, even if I reduced the time for testing. And the temps are displaying to one decimal point.

Now to let it run for a few days and see what happens.

I'll quit bothering you guys now so we can get back to the original topic of the thread.

Here's my code as it stands tonight. Feel free to use/ignore as you see fit.

Thanks again to all for your help and comments! :proud:


Code:
///////////////////////////////////////////////////////////////////
//   Current Satellite LED+ Controller  V4.1c                    //
//   Indychus...Dahammer...mistergreen @ plantedtank.net         //
//   Clumsy mod to include dual channel thermometer by           //
//   Caver @ plantedtank.net with lots of help from the above.   //
//   This code is public domain.  Pass it on.                    //
//   Confirmed on Arduino UNO 1.0.5                              //
///////////////////////////////////////////////////////////////////
//
// 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.
//
// You can test the IR commands via the Arduino software's serial monitor
// by sending in a value from 1 - 32. Values follow the remote control, 
// left to right, top to bottom (e.g 1 = Orange, 2 = Blue, 21 = Moon1, etc)
//
// Install LCD per instructions at http://learn.adafruit.com/character-lcds/overview
//
#include <Wire.h>
#include <RTClib.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <IRremote.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>

RTC_DS1307 RTC;
IRsend irsend;

byte randAnalogPin = 0;   // This needs to be set to an unused Analog pin, Used by RandomStorm()
#define LCD_COLS 20      // Number of columns on the LCD (e.g. 16, 20, etc)
#define LCD_ROWS 4       // Number of rows on the LCD (e.g. 2, 4, etc)
LiquidCrystal lcd(10, 8, 7, 6, 5, 4);

// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

DeviceAddress thermometer_1 = { 0x28, 0x98, 0x82, 0xA8, 0x04, 0x00, 0x00, 0x6D }; //Red
DeviceAddress thermometer_2 = { 0x28, 0xA6, 0x33, 0xA8, 0x04, 0x00, 0x00, 0x11 }; //blue

// Current Satellite+ IR Codes (NEC Protocol)
unsigned long codeHeader = 0x20DF; // Always the same
// Remote buttons listed left to right, top to bottom
PROGMEM unsigned int arrCodes[32] = {0x3AC5,  // 1 -  Orange
                                     0xBA45,  // 2 -  Blue
                                     0x827D,  // 3 -  Rose
                                     0x02FD,  // 4 -  Power On/Off
                                     0x1AE5,  // 5 -  White
                                     0x9A65,  // 6 -  FullSpec
                                     0xA25D,  // 7 -  Purple
                                     0x22DD,  // 8 -  Play/Pause
                                     0x2AD5,  // 9 -  Red Up
                                     0xAA55,  // 10 - Green Up
                                     0x926D,  // 11 - Blue Up
                                     0x12ED,  // 12 - White Up
                                     0x0AF5,  // 13 - Red Down
                                     0x8A75,  // 14 - Green Down
                                     0xB24D,  // 15 - Blue Down
                                     0x32CD,  // 16 - White Down
                                     0x38C7,  // 17 - M1 Custom
                                     0xB847,  // 18 - M2 Custom
                                     0x7887,  // 19 - M3 Custom
                                     0xF807,  // 20 - M4 Custom
                                     0x18E7,  // 21 - Moon 1
                                     0x9867,  // 22 - Moon 2
                                     0x58A7,  // 23 - Moon 3
                                     0xD827,  // 24 - Dawn/Dusk
                                     0x28D7,  // 25 - Cloud 1
                                     0xA857,  // 26 - Cloud 2
                                     0x6897,  // 27 - Cloud 3
                                     0xE817,  // 28 - Cloud 4
                                     0x08F7,  // 29 - Storm 1
                                     0x8877,  // 30 - Storm 2
                                     0x48B7,  // 31 - Storm 3
                                     0xC837}; // 32 - Storm 4

// These are the messages that print on the serial monitor & lcd when each IR code is sent
#define MAX_MSG_LEN 13  // Maximum length of the arrMSG messages
prog_char PROGMEM arrMSG[][MAX_MSG_LEN+1] = {"Orange",        "Blue",          "Rose",          "Power On/Off",
                                             "White",         "Full Spectrum", "Purple",        "Play/Pause",
                                             "Red Up",        "Green Up",      "Blue Up",       "White Up",
                                             "Red Down",      "Green Down",    "Blue Down",     "White Down",
                                             "Custom Mix 1",  "Custom Mix 2",  "Custom Mix 3",  "Custom Mix 4",
                                             "Moonlight 1",   "Moonlight 2",   "Moonlight 3",   "Dawn/Dusk",
                                             "Cloud Cover 1", "Cloud Cover 2", "Cloud Cover 3", "Cloud Cover 4",
                                             "Storm 1",       "Storm 2",       "Storm 3",       "Storm 4"};

void SetAlarms()
{
  // Set up your desired alarms here
  // The default value of dtNBR_ALARMS is 6 in TimeAlarms.h.
  // This code sets 9 alarms by default, so you'll need to change dtNBR_ALARMS to 9 or more
  // Changes the times to suit yourself. Add as many alarms as you like, just stay within dtNBR_ALARMS
  Alarm.alarmRepeat(13,00,0, PowerOnOff);
  Alarm.alarmRepeat(13,02,0, Moon1);
  Alarm.alarmRepeat(13,45,0, DawnDusk);
  Alarm.alarmRepeat(14,00,0, Cloud2);     // (HR,MIN,SEC,FUNCTION)
  Alarm.alarmRepeat(15,00,0, Cloud1);
  Alarm.alarmRepeat(17,00,0, FullSpec);
  Alarm.alarmRepeat(19,00,0, Cloud1);
  Alarm.alarmRepeat(20,00,0, Cloud2);
  Alarm.alarmRepeat(21,45,0, Moon3);
  Alarm.alarmRepeat(22,00,0, Moon1);
  Alarm.alarmRepeat(23,00,0, Moon2);
  Alarm.alarmRepeat(23,59,0, PowerOnOff);
  Alarm.timerRepeat(2, PrintTemp);
  PrintTemp(); // Display initial temps
   
  // Comment these out if you don't want the chance of a random storm each day
  // Alarm.alarmRepeat(12,00,00, RandomStorm);
  // RandomStorm();  // Sets up intial storm so we don't have wait until alarm time
}

// Setup file structure & output function for stdout redirect
static FILE uartout = {0}; // create a FILE structure to reference our UART output function
static int uart_putchar (char c, FILE *stream)
{
  // Serial write fumction
  Serial.write(c);
  return 0;
}

// File structure & output function for lcd output
static FILE lcdout = {0} ;      // lcd FILE structure
static int lcd_putchar(char ch, FILE* stream)
{
  // lcd write function
  lcd.write(ch);
  return (0);
}

void setup()
{
  Wire.begin();
  RTC.begin();
  Serial.begin(9600);
  lcd.begin(LCD_COLS, LCD_ROWS);
  
  // Start up the library
sensors.begin();
// set the resolution to 10 bit (good enough?)

  sensors.setResolution(thermometer_1, 9);
  sensors.setResolution(thermometer_2, 9);

lcd.clear(); // start with a blank screen
  
  // fill in the UART file descriptor with pointer to writer.
  fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
  stdout = &uartout;  // Output stdout to UART
   
  // fill in lcd file descriptor (we'll use fprintf to output to it)
  fdev_setup_stream (&lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE);
  
  if (! RTC.isrunning()) {
    // If no RTC is installed, set time to compile time at each reset
    printf_P(PSTR("RTC is NOT running!\n"));  // Store this string in PROGMEM
    RTC.adjust(DateTime(__DATE__, __TIME__));
    }
  
  setSyncProvider(syncProvider);     // reference our syncProvider function instead of RTC_DS1307::get()
  
  printf_P(PSTR("Time: %02d:%02d:%02d\n"), hour(), minute(), second());  // Print the time
  SetAlarms();  // Set up above alarms
  
  // Print available SRAM for debugging, comment out if you want
  printf_P(PSTR("SRAM: %d\n"), freeRam());
  
  printf_P(PSTR("To test IR codes, send 1 - 32\n"));
}

void loop()
{
    
  if (Serial.available() > 0) {
    delay(5); //Wait for transmission to finish
    TestCodes(SerialReadInt());  // Go grab IR code and send it
  }
  Alarm.delay(100);   // Service alarms & wait (msec)
  lcd.setCursor(7,0);
  fprintf(&lcdout, "%02d:%02d", hour(), minute());  // Print the time HH:MM to the lcd
}
time_t syncProvider()
{
  //this does the same thing as RTC_DS1307::get()
  return RTC.now().unixtime();
}

void RandomStorm ()
{ 
  // Schedules a storm between 1 & 8 in the evening
  // It sets Storm2, followed by Cloud2 or DawnDusk or Moon2, depending on when the storm is over
  randomSeed(analogRead(randAnalogPin));  // Generate random seed on unused pin
  byte RH = random(23);                   // Randomizer for RandomStorm
  byte RM = random(59);
  byte RS = random(59);
  byte TSDurationH = random(2);
  byte TSDurationM = random(59);
  
  lcd.setCursor(0,1);
  if (RH >= 13 && RH <= 21)
    { // If 1:00PM - 8:00PM schedule a storm
      Alarm.alarmOnce(RH,RM,RS,Storm2);
      
      // Store strings in PROGMEM
      printf_P(PSTR("Scheduled Storm: %02d:%02d:%02d Duration: %02d:%02d\n"), RH, RM, RS, TSDurationH, TSDurationM);
      fprintf_P(&lcdout, PSTR("Sch Storm: %02d:%02d"), RH, RM);
          
      if ((RH + TSDurationH) < 19)   // Switch to Cloud2 if storm ends between 1:00-6:59pm
        {
          Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,Cloud2);
        }
      else if ((RH + TSDurationH) < 21)  // Switch to DawnDusk if storm ends between 7:00-8:59pm
        {
          Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,DawnDusk);
        }
      else                               // Otherwise, switch to Night2
        {
          Alarm.alarmOnce((RH + TSDurationH),(RM + TSDurationM),RS,Moon2);
        }
    }
    else
    { // Don't really need this, but it can stay till we need the space
      printf_P(PSTR("No storm today\n"));
      fprintf_P(&lcdout, PSTR("No storm today\n"));
    }
}
int SerialReadInt()
{
  // Reads first 2 bytes from serial monitor; anything more is tossed
  byte i;
  char inBytes[3];
  char * inBytesPtr = &inBytes[0];  // Pointer to first element
    
    for (i=0; i<2; i++)             // Only want first 2 bytes
      inBytes[i] = Serial.read();
    inBytes[i] =  '\0';             // Put NULL character at the end
    while (Serial.read() >= 0)      // If anything else is there, throw it away
      ; // do nothing      
    return atoi(inBytesPtr);        // Convert to decimal
}

void TestCodes (int cmd)
{
  // Handles commands sent in from the serial monitor
  if (cmd >= 1 && cmd <= 32)
    { 
      // cmd must be 1 - 32
      SendCode(cmd-1, 1);
    }
    else { printf_P(PSTR("Invalid Choice\n")); }
}

void SendCode ( int cmd, byte numTimes )
{ // cmd = the element of the arrCode[] array that holds the IR code to be sent
  // numTimes = number of times to emmit the command
  // Shift header 16 bits to left, fetch code from PROGMEM & add it
  unsigned long irCode = (codeHeader << 16) + pgm_read_word_near(arrCodes + cmd);
  for( byte i = 0; i < numTimes; i++)
  {
    irsend.sendNEC(irCode,32); // Send/emmit code
    delay(100);
  }
  // Print the string associated with the IR code & the time
  //printf("%S: 0x%lx %02d:%02d:%02d\n", arrMSG[cmd], irCode, hour(), minute(), second());
  printf("%S: %02d:%02d:%02d\n", arrMSG[cmd], hour(), minute(), second());
  if (LCD_COLS == 16)
    {
      lcd.setCursor(0,1);
      fprintf(&lcdout, "%-16S", arrMSG[cmd]);
    }
  else
    {
      lcd.setCursor(0,1);
      // lcd.setCursor(6,0);
      fprintf(&lcdout, "%-14S", arrMSG[cmd]);
    }
}

int freeRam ()
{
  // Returns available SRAM
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

void PrintTemp()
{
  sensors.requestTemperatures();
  float tempC = sensors.getTempC(thermometer_1);
  lcd.setCursor(0,2);
  lcd.print("Tank 1: ");
  lcd.print(DallasTemperature::toFahrenheit(tempC), 1);
  lcd.print((char)223);
  
  tempC = sensors.getTempC(thermometer_2);
  lcd.setCursor(0,3);
  lcd.print("Tank 2: ");
  lcd.print(DallasTemperature::toFahrenheit(tempC), 1);
  lcd.print((char)223);
  
}

// IR Code functions, called by alarms
void Orange() {SendCode(0,2);}
void Blue() {SendCode(1,2);}
void Rose() {SendCode(2,2);}
void PowerOnOff() {SendCode(3,1);}
void White() {SendCode(4,2);}
void FullSpec() {SendCode(5,2);}
void Purple() {SendCode(6,2);}
void Play() {SendCode(7,1);}
void RedUp() {SendCode(8,1);}
void GreenUp() {SendCode(9,1);}
void BlueUp() {SendCode(10,1);}
void WhiteUp() {SendCode(11,1);}
void RedDown() {SendCode(12,1);}
void GreenDown() {SendCode(13,1);}
void BlueDown() {SendCode(14,1);}
void WhiteDown() {SendCode(15,1);}
void M1Custom() {SendCode(16,2);}
void M2Custom() {SendCode(17,2);}
void M3Custom() {SendCode(18,2);}
void M4Custom() {SendCode(19,2);}
void Moon1() {SendCode(20,2);}
void Moon2() {SendCode(21,2);}
void Moon3() {SendCode(22,2);}
void DawnDusk() {SendCode(23,2);}
void Cloud1() {SendCode(24,2);}
void Cloud2() {SendCode(25,2);}
void Cloud3() {SendCode(26,2);}
void Cloud4() {SendCode(27,2);}
void Storm1() {SendCode(28,2);}
void Storm2() {SendCode(29,2);}
void Storm3() {SendCode(30,2);}
void Storm4() {SendCode(31,2);}
 
#319 ·
Hi Guys,

It works ! :bounce:
I input DaHammers suggestions. I corrected a couple of typos. In the printTemp routine I changed a Serial.print call to lcd.print to get the temps to display.
It seems that no matter what I do, I always do something boneheaded like that.

I changed the Alarm.alarmRepeat to Alarm.timerRepeat and put it in with the rest of the alarms. Otherwise the temps apparently weren't updating, even if I reduced the time for testing. And the temps are displaying to one
decimal point.
Ha! Good find. Alarm.alarmRepeat actually triggers an alarm at the same time every day and not after every x seconds. timerRepeat is the one that repeats every x seconds. Another boneheaded mistake on my part. I went back to the previous post and fixed the mistakes you found.

Now to let it run for a few days and see what happens.

I'll quit bothering you guys now so we can get back to the original topic of the thread.

Here's my code as it stands tonight. Feel free to use/ignore as you see fit.

Thanks again to all for your help and comments! :proud:
You're not bothering me. Glad to help, the only downside is as you've found out I'm prone to boneheaded mistakes. Usually I find most of them through testing myself, but in the case of the LCD and thermometer, I have nothing to test yet. Glad you got it going. I was surprised at the overhead the thermometer libraries/code add, 5k, wow!
 
#322 ·
Nice! Mine has been running the older software (3.7) for several weeks now without any issues. I haven't been home to update it or tinker with it any in a while. Luckily the wife is pretty tech-savvy and can keep an eye on it for me.

Sent from my HTC One X
 
#323 ·
Yeah...

It's been kinda quiet here the last couple of weeks. I figured no news is good news...everyones controllers are perking along nicely.

Mine is. I'm running the last version of code I posted, controlling lights on a 20 gal Long and a 6 gal shrimp tank. The lights are working flawlessly. I get an occasional glitch with the temperature sensors...but I think that's because of the funky plug in wiring. I still haven't cleaned it up in a permanent way.

Another thing I've noticed is the RTC runs fast big time. I have to hook the controller up to a PC and reset the clock every couple of weeks...it gains almost 10 minutes in that time frame. Not a big deal in the overall scheme of things...but I'm kinda picky about clocks being accurate.
 
#329 ·
It's not the RTC that's fast, it's the time the arduino is keeping that's off, I assuming. In the code it's best to re-sync the arduino time with the RTC maybe every 24hours.
Code:
setSyncProvider(syncProvider);
The arduino/Time.h library uses millis() which isn't accurate.

The code already does:
Code:
  setSyncProvider(syncProvider);     // reference our syncProvider function instead of RTC_DS1307::get()
Code:
time_t syncProvider()
{
  //this does the same thing as RTC_DS1307::get()
  return RTC.now().unixtime();
}
 
#327 ·
OK.

After a VERY quick look at SyncProvider info...I'm at work and for some reason they keep asking me to do stuff...

To implement a resync to the RTC every 24 hours, I'd need to add a line...

setSyncInterval (86400); //RTC sync interval in seconds

Would that go right after the "setSyncProvider(syncProvider);" in void setup ()?
 
#332 ·
Ah, just found it... You can resync.

Code:
 setSyncInterval(interval);  // Set the number of
                               //  seconds between re-sync
so if you want to re-synce in a day

Code:
 setSyncInterval(60*60*24);  // Set the number of
                               //  seconds between re-sync
ps. put this in the setup() with syncProvider
 
#333 ·
Ah, just found it... You can resync.

Code:
 setSyncInterval(interval);  // Set the number of
                               //  seconds between re-sync
so if you want to re-synce in a day

Code:
 setSyncInterval(60*60*24);  // Set the number of
                               //  seconds between re-sync
Wouldn't this do the same thing?
Code:
setSyncInterval(86400); //RTC sync interval in seconds
Or is there a reason you used 60*60*24 in the parenthesis?
 
This is an older thread, you may not receive a response, and could be reviving an old thread. Please consider creating a new thread.
Top