The Planted Tank Forum - Reply to Topic
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 > Improved Arduino LED lighting code

Thread: Improved Arduino LED lighting code Reply to Thread
Title:
  
Message:
Post Icons
You may choose an icon for your message from the following list:
 

Register Now

In order to be able to post messages on the The Planted Tank Forum forums, you must first register.
Please enter your desired user name, your email address and other required details in the form below.
User Name:
Password
Please enter a password for your user account. Note that passwords are case-sensitive.
Password:
Confirm Password:
Email Address
Please enter a valid email address for yourself.
Email Address:
Location
Your Location. As precise as you feel comfortable with.
Security Question
While balancing on a piece of wood, two inches by four inches known as a 2x4, John and his friend Sally both spotted a dalmatian inside of a truck with sirens. The animal with John and Sally is a _ _ _?
Insurance
Please select your insurance company (Optional)

Log-in

Human Verification

In order to verify that you are a human and not a spam bot, please enter the answer into the following box below based on the instructions contained in the graphic.



Additional Options
Miscellaneous Options

Topic Review (Newest First)
05-31-2015 07:24 PM
MrSpiffy Any recommendations on cooling fans that will work with Arduino PWM? I noticed it's in the code, but it will not control the fans I purchased (Arctic F8 PWM). Looking for some suggestions.
04-26-2015 01:57 PM
Gisimo
help

i found the mistakes and now it is working
04-23-2015 06:52 PM
kman ^^ Arduino has updated their software from 1.0.6 to 1.6.3 or something like that, and there are a LOT of sketches that won't compile correctly until the new version without making changes. You might want to try the previous software version and see if that helps. The old versions are still available on the Arduino.cc website.
04-23-2015 12:20 PM
Gisimo
help

hi guys im trying to make lights for my aquarium but this time i am going to use a hc-05 eller 06 bluetooth. i have triet the code for arduino 1.0 but it dosent work(it wont compile) so i tried the origional one but i cant get it to work with 1.0!!! is there one of you here who have the original code but for 1.0??(without lcd,fan ect)
The resen is the Arduino 0022 dont se the bluetooth com port... if you no of a way to get the 0022 to find the com-port please tell
03-20-2015 04:02 AM
MrSpiffy Looks like the common ground was my problem. The dining works at night. Haven't gotten to test the sunrise portion, yet. Perhaps it's also the issue with the fans..?
03-18-2015 10:21 PM
MrSpiffy Those are all great to know. Thanks for sharing! However, it doesn't address the concern of joining the ground pin of the Arduino to the ground pin of the PSU for the LEDs.
03-18-2015 09:59 PM
kman http://www.ruggedcircuits.com/10-way...oy-an-arduino/
03-18-2015 09:56 PM
MrSpiffy I'm using a separate power supply for the Arduino via micro-USB. That should be a standard 5V supply.

I was referring to protecting the Arduino from connections to the 24V LED supply, even via ground. Sounds like some people had heard from a guy who heard from another guy that you can fry your Arduino by doing that. I'm guessing that's just mumbo jumbo.
03-18-2015 06:02 PM
O2surplus
Quote:
Originally Posted by MrSpiffy View Post
Yeah, there's definitely been a learning curve with the Arduino. But it's been interesting, despite the frustration.

I read somewhere that some people recommend a resistor or diode, or some other method, to protect the Arduino unit from the PSU power. Is that something you've found to be necessary, as well?
The Arduino's on board regulator tends to overheat, if it's forced to drop too much voltage. I don't recommend powering the Arduino with more than 12V. Using 7 to 9V is optimal.
03-18-2015 04:45 PM
MrSpiffy Yeah, there's definitely been a learning curve with the Arduino. But it's been interesting, despite the frustration.

I read somewhere that some people recommend a resistor or diode, or some other method, to protect the Arduino unit from the PSU power. Is that something you've found to be necessary, as well?
03-18-2015 04:39 PM
O2surplus
Quote:
Originally Posted by MrSpiffy View Post
Ran across what may be a little detail that completely throws things off. It sounds like I should join the grounds for the Arduino and the LED PSU, otherwise the PWM may not function properly. I'll give that a shot and see how it goes.
LOL- Don't feel bad. Lots of people miss that "little detail". The Arduino and power supply do need to share a common ground.
03-18-2015 03:59 PM
MrSpiffy Ran across what may be a little detail that completely throws things off. It sounds like I should join the grounds for the Arduino and the LED PSU, otherwise the PWM may not function properly. I'll give that a shot and see how it goes.
03-15-2015 04:51 PM
MrSpiffy I'm not sure why, but my lights will not fade on or off during the sunrise or sunset periods. The period does appear to change, as the LCD does show the correct state at the proper times.

I have two rows of LEDs with the dimming input for each driver connected to pins 9 and 10, which is where I gathered they should be connected from evaluating the code.

My setup consists of a 24V PSU (trimmed down to 18V) running to a pair of MeanWell LDD drivers, each driving a set of 5 LEDs, 3W each. I also have a 4x20 LCD, DS18B20 temp probe, and the DS3231 RTC. Lastly, I'm using an Adafruit Trinket Pro 5V Arduino unit, so available pins may be a little different than for an Uno. Also, the 5V onboard output is only 150mA, not 800mA as the Uno would typically have.

The RTC was set and appears to be functioning correctly, as it's keeping time and date accurately. The temp probe also looks like it's working fine, as the temp updates regularly and shows an expected temp value for the ambient air. And the LCD is displaying fine, backlight and contrast working just fine.

Things that are NOT working are the fans and the PWM dimming. However, I believe the fans are due to the brand of fan I purchased. (Arctic F8 80mm PWM fans I guess use different frequencies for PWM. Although, even just using straight 12V and no PWM input, they wouldn't spin up at all.)

Pinouts:

LCD: 4,5,11,14,15,16,17 (RS,RW,E,D4-D7)
RTC: A4,A5 (analog pins)
PWM fans: 6
PWM dimming: 9,10
Temp probe: 12

I just moved all 5V power requirements for the temp probe, LCD, Backlight, and RTC over to the BUS pin to avoid using the onboard power regulation.

Pin 13 is used for an onboard LED, and pins 2 and 7 are only for onboard USB control, so I avoided using them.

Unused pins: 2,3,7,13,A6,A7

Is it possible I don't have the available onboard power required for all of these things in the Trinket Pro?

Any help troubleshooting this issue would be greatly appreciated.

Code:
/*
 * Name:    tank-control.pde
 * Author:    User "sink" at plantedtank.net forums
 * URL:        http://bitbucket.org/akl/tank-control
 *
 * This is control code for an aquarium lighting system.  It is intended to be
 * run on an Arduino microcontroller board.  It allows independant
 * high-resolution control of two PWM outputs (normally connected to LED
 * drivers) and complete flexibility with respect to intensity, timing
 * schedules, and sunrise/sunset.
 *
 * This code requires the following libraries: Wire, TimerOne, Time, DS1307RTC
 *
 * The latest version of this code can always be found at above url.
 */

/*
 * Copyright (c) 2011, User "sink" at plantedtank.net forums
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.

 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.  
 */
/* NOTICE: 4/2/2014- Addtional support for I2C LCD & Dallas OneWire Temperature readout added by O2Surplus.
              The original Libraries used in this version of the code were updated for use with Arduino 1.5-r2.
              Please make sure to use the proper version of said libraries. */
              
#include <TimerOne.h>
#include <Time.h>
#include <Wire.h>
#include <DS3231RTC.h>
#include <OneWire.h> // added to original code by O2Surplus 4/2/2014
#include <LiquidCrystal.h>// added to original code by O2Surplus 4/2/201401.

//LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display, not using I2C here
LiquidCrystal lcd(4,5,11,14,15,16,17);  // Set the LCD I2C address

//Temperature chip i/o
int DS18B20_Pin = 12; //DS18S20 Signal pin on digital 17

OneWire ds(DS18B20_Pin);  // on digital pin 17

int fanEnable = 6;// assigns cooling fan ON/OFF control to digital pin 6.

/*
 * IMPORTANT:  These *must* be the pins corresponding to the Timer1 timer on
 * the ATmega168/328.  These are digital pins 9 and 10 on the Uno/Duemilanove.
 */
const int kChan0Pin = 9; // Channel 0 Pin
const int kChan1Pin = 10; // Channel 1 Pin

// All times are in seconds since midnight (valid 0 - 86399)
const long kTurnOn = 32400; // time dawn begins - 0900hrs
const long kTurnOff = 75600; // time sunset begins - 2100hrs

/*
 * Light "state" represents the PWM duty cycle for each channel This normally
 * dictates light intensity. It is an array { duty_chan_1, duty_chan_2 }.
 * Possible values for duty cycle are 0 - 1023.
 */
const int kDayState[] = { 1023,1023 }; // daytime LED state
const int kNightState[] = { 0, 0 }; // nighttime LED state

// duration (in seconds) of sunrise/sunset fade
const long kFadeDuration = 3600; // 60 minutes

long ctr;

/*
 * fader -- Determine output state for a given time to provide smooth fade from
 * one state to another.
 *     Args:
 *     start_time  -- time (in seconds) of start of fade
 *     start_state -- beginning state
 *     end_state   -- ending state
 *     out         -- array to update with state
 */
void fader(long start_time, const int start_state[], const int end_state[], int out[2]) {

  float per_second_delta_0 = (float) (end_state[0]-start_state[0])/kFadeDuration;
  float per_second_delta_1 = (float) (end_state[1]-start_state[1])/kFadeDuration;

  long elapsed = ctr-start_time;

  out[0] = start_state[0] + per_second_delta_0 * elapsed;
  out[1] = start_state[1] + per_second_delta_1 * elapsed;
}

// return seconds elapsed since midnight
long seconds_since_midnight() {
//  setTime(21, 45, 00, 16, 2, 2015);
//set the system time to 21hrs 45min 00sec 16,Feb 2015...does not set RTC, will reset upon powerup
  
  time_t t = now();
  long hr = hour(t);
  long min = minute(t);
  long sec = second(t);
  long total = hr * 3600 + min * 60 + sec;
  return total;
}

// set output state
void set_state(const int state[]) {
  if (state[0] >= 0 && state[0] <= 1023) Timer1.setPwmDuty(kChan0Pin, state[0]);
  if (state[1] >= 0 && state[1] <= 1023) Timer1.setPwmDuty(kChan1Pin, state[1]);
}

/*
 * determine_state -- This is where the actual timing logic resides.  We
 * examine ctr (seconds since midnight) and then set output state accordingly.
 * Variable ctr rolls back to 0 at midnight so stages that cross midnight (ie:
 * nighttime) are broken up into two stages.
 */
void determine_state() {
  if ( ctr >= 0 && ctr < kTurnOn ) { // night
      set_state(kNightState);
      
      lcd.setCursor(0,2);
      //lcd.print("                   ");
      lcd.setCursor(5,2);
      lcd.print("NIGHT/MODE ");         // LCD coding added by O2Surplus 4/2/2014
      digitalWrite(fanEnable,LOW);
      lcd.setCursor(6,3);
      lcd.print("FANS-OFF");
      
  } else if ( ctr >= kTurnOn && ctr <= (kTurnOn+kFadeDuration) ) { // sunrise
    int foo[2];
    fader(kTurnOn, kNightState, kDayState, foo);
    set_state(foo);
      
      lcd.setCursor(0,2);
      //lcd.print("                   ");
      lcd.setCursor(3,2);
      lcd.print("SUNRISE/MODE");              // LCD coding added by O2Surplus 4/2/2014
      digitalWrite(fanEnable, HIGH);
      lcd.setCursor(7,3);
      lcd.print("FAN-ON");
  } else if ( ctr > (kTurnOn+kFadeDuration) && ctr < kTurnOff ) { // day
    set_state(kDayState);
      
      lcd.setCursor(0,2);
      //lcd.print("                   ");
      lcd.setCursor(5,2);             
      lcd.print("DAY/MODE");              // LCD coding added by O2Surplus 4/2/2014
      digitalWrite(fanEnable, HIGH);
      lcd.setCursor(7,3);
      lcd.print("FAN-ON");
  } else if ( ctr >= kTurnOff && ctr <= (kTurnOff+kFadeDuration) ) { // sunset
    int foo[2];
    fader(kTurnOff, kDayState, kNightState, foo);
    set_state(foo);
      lcd.setCursor(0,2);
      //lcd.print("                   ");
      lcd.setCursor(5,2);
      lcd.print("SUNSET/MODE");              // LCD coding added by O2Surplus 4/2/2014
      //lcd.setCursor(11,2);
      //lcd.print("  ");
      digitalWrite(fanEnable, HIGH);
      lcd.setCursor(7,3);
      lcd.print("FAN-ON");
  } else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ) { // night
    set_state(kNightState);
      lcd.setCursor(0,2);
      //lcd.print("                   ");
      lcd.setCursor(5,2);
      lcd.print("NIGHT/MODE");          // LCD coding added by O2Surplus 4/2/2014
      digitalWrite(fanEnable,LOW);
      lcd.setCursor(6,3);
      lcd.print("FANS-OFF");
  }
}

/*
 * Utility function for pretty digital clock time output
 * From example code in Time library -- author unknown
 */
void printDigits(int digits) {
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
 
}
void displayDigits(int digits) {
  lcd.print(":");
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits);
  
}

/*
 * Display time
 * Adapted from example code in Time library -- author unknown
 */
void digitalClockDisplay() {
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print("  ");
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year()); 
  Serial.println(); 
}
void lcdClockDisplay() {
  lcd.setCursor(0,0);
  lcd.print(hour());
  displayDigits(minute());
  displayDigits(second());
  lcd.print("   ");
  lcd.print(month());
  lcd.print("/");
  lcd.print(day());
  lcd.print("/");
  lcd.print(year()); 
   
}
void setup() {
  Serial.begin(115200);        // Max for Arduino Uno
  setSyncProvider(RTC.get);
  setSyncInterval(120);
  Wire.begin();
  lcd.begin(20,4);             // initialize the lcd for 20 chars 4 lines and turn on backlight
  Timer1.initialize(6666);     // 150Hz PWM
  pinMode(kChan0Pin, OUTPUT);     
  Timer1.pwm(kChan0Pin, 0);
  pinMode(kChan1Pin, OUTPUT);     
  Timer1.pwm(kChan1Pin, 0);
  pinMode(fanEnable,OUTPUT);   // Fan control coding added by O2Surplus 4/2/2014
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
    }
  
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
    }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
    }
  
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
    }  

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
    }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } 
  
  else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
  
  ctr = seconds_since_midnight(); // Original code
 
  lcd.setCursor(0,1);             // Temperature to I2C LCD added by O2Surplus 4/2/2014
  lcd.print("   Temp F = ");
  lcd.print(fahrenheit);
 
  determine_state();              // Original code
  Serial.print("ctr: ");
  Serial.print(ctr);              // display counter
  Serial.println();
  digitalClockDisplay();          //display time
  Serial.println();
  lcd.setCursor(0,0);             //Time/Date to I2C display added 4/2/2014 by O2Surplus
  lcd.println();
  lcdClockDisplay();
}
02-18-2015 06:09 PM
paronaram It's 12min forward.
I change it to 720, same result...

Thanks
02-18-2015 04:21 AM
O2surplus
Quote:
Originally Posted by paronaram View Post
Hi, thanks for reply.
Yes, I did.
It was not working at all, and I found that library was old, updated library and it works now.
but I get 12min off

Thanks
Aram-

Check line #57 your copy of the TimeSet code. This is what it looks like-
const int kAdjustment = 25;
The 25 stands for the number of seconds needed to compile & upload the code to your arduino (on average). You can change the 25 to any number you wish to skew the time forward or back. Since your clock is 12 minutes off (forward or back?) try changing the 25 to 720 or -720 to see if that corrects the time.
This thread has more than 15 replies. Click here to review the whole thread.

Posting Rules
You may post new threads
You may 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


All times are GMT. The time now is 09:15 PM.


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