Improved Arduino LED lighting code - Page 11
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 04-10-2013, 12:07 AM   #151
sink
Algae Grower
 
PTrader: (2/100%)
Join Date: Jun 2011
Location: Boston, MA
Posts: 148
Default

Quote:
Originally Posted by shrimper23 View Post
Any idea on the I2C capability guys? Also, Sink, a quick question on your code, I see you name the channels with a "k". Such as kChan0Pin, is there a reason for this? Just wondering as I haven't seen this before.
It is a convention in C to name constants starting with a lowercase k. It helps distinguish later on things that should be constant from things that can be safely reassigned. It is not a requirement though, merely a suggested style.

I would think you will have no issues with multiple devices on I2C.

Cheers.
sink is offline   Reply With Quote Quick reply to this message
Sponsored Links
Advertisement
 
Old 09-21-2013, 01:00 AM   #152
willflyfood
Newbie
 
PTrader: (0/0%)
Join Date: Sep 2013
Location: Fort Worth TX
Posts: 2
Default

Sink I am driving my self nuts here.... what pins did you use for the RTC?
willflyfood is offline   Reply With Quote Quick reply to this message
Old 09-21-2013, 04:20 AM   #153
willflyfood
Newbie
 
PTrader: (0/0%)
Join Date: Sep 2013
Location: Fort Worth TX
Posts: 2
Default Pins

I am using pin 4 and 5 but when I run the serial monitor I see nothing...
willflyfood is offline   Reply With Quote Quick reply to this message
Old 10-05-2013, 10:04 PM   #154
sink
Algae Grower
 
PTrader: (2/100%)
Join Date: Jun 2011
Location: Boston, MA
Posts: 148
Default

Quote:
Originally Posted by willflyfood View Post
Sink I am driving my self nuts here.... what pins did you use for the RTC?
Sorry for the delay in replying!

The RTC communicates over I2C, so you just use whatever pins those are on your board. On the Duemilanove that I have those are A4 and A5. It might be different on the Uno. There isn't anything special about my code in this respect, you hook up I2C the same way you would for any Arduino device. For just one I2C device (the RTC) you'd connect the SDA on the RTC to the SDA on the Arduino, and same for the SCL ports.
sink is offline   Reply With Quote Quick reply to this message
Old 10-05-2013, 10:13 PM   #155
sink
Algae Grower
 
PTrader: (2/100%)
Join Date: Jun 2011
Location: Boston, MA
Posts: 148
Default

Quote:
Originally Posted by willflyfood View Post
I am using pin 4 and 5 but when I run the serial monitor I see nothing...
The serial doesn't really send anything unless you "talk" to it with the client.py script I supplied in the code.

If you run the client.py script and enter "time" at the prompt, you get no response? Is there an error?
sink is offline   Reply With Quote Quick reply to this message
Old 10-06-2013, 05:15 AM   #156
HunterX
Planted Tank Obsessed
 
HunterX's Avatar
 
PTrader: (22/100%)
Join Date: May 2012
Location: Springfield MO
Posts: 388
Default

Hello everyone. I want to thank you all for taking the time to put this information on the forum. I do have a question. Has anyone used the arduino to control LED fixtures made by build my led.com? From what I understand, they are built with LED Drivers built into the fixture. Further more, they can ship with a prefab APEX dimming cable. It appears to be a standard RJ45 connection on the end that would plug into the controller. Would it be possible do use the Arduino with that setup to control the LEDs? if so what would I need?

Thank you in advance for your response.
HunterX is offline   Reply With Quote Quick reply to this message
Old 10-06-2013, 10:28 PM   #157
O2surplus
Planted Tank Enthusiast
 
O2surplus's Avatar
 
PTrader: (4/100%)
Join Date: Jan 2010
Location: "Out West, in the Land of Fruits & Nuts"
Posts: 804
Default

Quote:
Originally Posted by HunterX View Post
Hello everyone. I want to thank you all for taking the time to put this information on the forum. I do have a question. Has anyone used the arduino to control LED fixtures made by build my led.com? From what I understand, they are built with LED Drivers built into the fixture. Further more, they can ship with a prefab APEX dimming cable. It appears to be a standard RJ45 connection on the end that would plug into the controller. Would it be possible do use the Arduino with that setup to control the LEDs? if so what would I need?

Thank you in advance for your response.

The Apex controller outputs a 0-10V analog signal to dim the leds. So chances are good that the dimmable drivers in the BuildMyLed fixture are designed to accept that type of dimming control signal. The Arduino outputs a 5V PWM signal, so it won't be directly compatible with the drivers in the BML fixture.
If you have your heart set on using the arduino as your controller, just purchase LED drivers that accept a 5V PWM signal directly, and you'll be set.Checkout the Meanwell LDD-L & LDD-H series of drivers. They will work well for your application, and they're cheap too. Here's a link-LDD-1000H | Mean-Well LDD-1000H | USA Warehouse
__________________
225 Gal, Glass "Reef Ready" w/ twin Iwaki Pumps & 2 Ocean Clear inline filters.Lighting- Custom built DIY 600 watt LED system, BlueFish "mini" Led Controller,iAqua Aquarium Controller , and a 20lb CO2 system w/ Milwaukee Ph Controller.
O2surplus is offline   Reply With Quote Quick reply to this message
Old 10-07-2013, 03:50 PM   #158
HunterX
Planted Tank Obsessed
 
HunterX's Avatar
 
PTrader: (22/100%)
Join Date: May 2012
Location: Springfield MO
Posts: 388
Default

Quote:
Originally Posted by O2surplus View Post
The Apex controller outputs a 0-10V analog signal to dim the leds. So chances are good that the dimmable drivers in the BuildMyLed fixture are designed to accept that type of dimming control signal. The Arduino outputs a 5V PWM signal, so it won't be directly compatible with the drivers in the BML fixture.
If you have your heart set on using the arduino as your controller, just purchase LED drivers that accept a 5V PWM signal directly, and you'll be set.Checkout the Meanwell LDD-L & LDD-H series of drivers. They will work well for your application, and they're cheap too. Here's a link-LDD-1000H | Mean-Well LDD-1000H | USA Warehouse
Thanks for your reply. I'm sending you a PM.
HunterX is offline   Reply With Quote Quick reply to this message
Old 10-08-2013, 05:46 PM   #159
estill
Algae Grower
 
PTrader: (3/100%)
Join Date: Jan 2007
Location: Tacoma, Washington
Posts: 25
Default

To address the 0-10V "signal", could you use the Arduino PWM output to control a transistor or MOSFET? I know you can do this to drive a DC motor, and it will fool most multimeters into seeing a lower voltage.
estill is offline   Reply With Quote Quick reply to this message
Old 12-01-2013, 03:07 PM   #160
Gisimo
Algae Grower
 
PTrader: (0/0%)
Join Date: Apr 2012
Location: Denmark
Posts: 19
Default

Hello everyone i am considering to make a new light for at nano tank and i was wondering if i could use a Arduino Micro or mini instead of an uno ??

Last edited by Gisimo; 12-01-2013 at 03:33 PM.. Reason: Mistake
Gisimo is offline   Reply With Quote Quick reply to this message
Old 12-01-2013, 05:05 PM   #161
shrimper23
Algae Grower
 
PTrader: (0/0%)
Join Date: Oct 2011
Location: Franktown,CO
Posts: 5
Default I2C freezing

Hey Sink, wanted to see if you might be able to advise me on my project here. I have your code working beautifully with the Adafruit 16-channel 12-bit pwm driver. However, after integrating it into my full control code i'm having an issue. The code will perform as expected right up to the dimming stage, when it hits my LCD goes blank, LED's flash, and the whole I2C bus stops dead. It seems to me I may have to much going on with the I2C. I'm using an UNO R3 with a DS1307, the Adafruit PWM controller, and their I2C 16x2 LCD on the bus. Please let me know if you have any idea how I might fix this issue. Thank you.


#include <Wire.h>
#include "RTClib.h"
#include <SoftwareSerial.h>
#include <OneWire.h>
#include <Adafruit_PWMServoDriver.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

#define OFF 0x0
#define WHITE 0x7
#define rxpin 3
#define txpin 2

RTC_DS1307 RTC;
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

const long kTurnOn = 39000; // 37800time dawn begins - 0900hrs
const long kTurnOff = 59000; // 70200 time sunset begins - 2100hrs
const int kDayState[] = { 3000, 4000, 4000, 4000, 0, 0, 2000, 3000 }; // daytime LED state
const int kNightState[] = { 0, 4, 45, 4, 2000, 0, 0, 4 }; // nighttime LED stat
const long kFadeDuration = 0;
long ctr;
int state_chan1, state_chan2, state_chan3, state_chan4, state_chan5, state_chan6, state_chan7, state_chan8;

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
SoftwareSerial myserial(rxpin, txpin);
int DS18S20_Pin = 4;
OneWire ds(DS18S20_Pin);

int floatstate = 0;

long phReadInterval = 10000;
long previousMillisPH = 0;
int PHState = HIGH;
float PH_Val;

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;
float per_second_delta_2 = (float) (end_state[2]-start_state[2])/kFadeDuration;
float per_second_delta_3 = (float) (end_state[3]-start_state[3])/kFadeDuration;
float per_second_delta_4 = (float) (end_state[4]-start_state[4])/kFadeDuration;
float per_second_delta_5 = (float) (end_state[5]-start_state[5])/kFadeDuration;
float per_second_delta_6 = (float) (end_state[6]-start_state[6])/kFadeDuration;
float per_second_delta_7 = (float) (end_state[7]-start_state[7])/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;
out[2] = start_state[2] + per_second_delta_2 * elapsed;
out[3] = start_state[3] + per_second_delta_3 * elapsed;
out[4] = start_state[4] + per_second_delta_4 * elapsed;
out[5] = start_state[5] + per_second_delta_5 * elapsed;
out[6] = start_state[6] + per_second_delta_6 * elapsed;
out[7] = start_state[7] + per_second_delta_7 * elapsed;
}

long seconds_since_midnight() {
DateTime now = RTC.now();
long hr = now.hour();
long min = now.minute();
long sec = now.second();
long total = hr * 3600 + min * 60 + sec;
return total;
}

void set_state(const int state[]) {
if (state[0] >= 0 && state[0] <= 4096) {
pwm.setPWM(0, 0, state[0]);
state_chan1 = state[0]; }
if (state[1] >= 0 && state[1] <= 4096) {
pwm.setPWM(1, 0, state[1]);
state_chan2 = state[1]; }
if (state[2] >= 0 && state[2] <= 4096) {
pwm.setPWM(2, 0, state[2]);
state_chan3 = state[2]; }
if (state[3] >= 0 && state[3] <= 4096) {
pwm.setPWM(3, 0, state[3]);
state_chan4 = state[3]; }
if (state[4] >= 0 && state[4] <= 4096) {
pwm.setPWM(4, 0, state[4]);
state_chan5 = state[4]; }
if (state[5] >= 0 && state[5] <= 4096) {
pwm.setPWM(5, 0, state[5]);
state_chan6 = state[5]; }
if (state[6] >= 0 && state[6] <= 4096) {
pwm.setPWM(6, 0, state[6]);
state_chan7 = state[6]; }
if (state[7] >= 0 && state[7] <= 4096) {
pwm.setPWM(7, 0, state[7]);
state_chan8 = state[7]; }
}

void determine_state() {
if ( ctr >= 0 && ctr < kTurnOn ) { // night
set_state(kNightState);
} else if ( ctr >= kTurnOn && ctr <= (kTurnOn+kFadeDuration) ) { // sunrise
int foo[2];
fader(kTurnOn, kNightState, kDayState, foo);
set_state(foo);
} else if ( ctr > (kTurnOn+kFadeDuration) && ctr < kTurnOff ) { // day
set_state(kDayState);
} else if ( ctr >= kTurnOff && ctr <= (kTurnOff+kFadeDuration) ) { // sunset
int foo[2];
fader(kTurnOff, kDayState, kNightState, foo);
set_state(foo);
} else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ) { // night
set_state(kNightState);
}
}

float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius

byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return -1000;
}

if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}

ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end

byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad


for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}

ds.reset_search();

byte MSB = data[1];
byte LSB = data[0];

float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;

return TemperatureSum;

}

void getPHvalue(){
unsigned long currentMillisPH = millis();

if(currentMillisPH - previousMillisPH > phReadInterval){
previousMillisPH = currentMillisPH;
if(PHState == HIGH){
PHState = LOW;
}
else {
PHState = HIGH;
myserial.print("r\r");
while(myserial.available() > 0){
PH_Val = myserial.parseFloat();
if(myserial.read() == '\r');
}
}
}
}

void setup() {
myserial.begin(38400);
RTC.begin();
lcd.begin(16,2);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, INPUT);
pwm.begin();
pwm.setPWMFreq(800);
ctr = seconds_since_midnight();
Serial.print(ctr);
}

void loop(){
ctr = seconds_since_midnight();
determine_state();
floatstate = digitalRead(7);
if (floatstate == HIGH) {
digitalWrite(6, HIGH);
delay(10000);
digitalWrite(6, LOW);
}
else {
digitalWrite(6, LOW);
}

if ( ctr >= 0 && ctr < 26000 ) {
lcd.setBacklight(OFF);
} if ( ctr >= 0 && ctr < kTurnOn ) {
digitalWrite(5, LOW);
} else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ){
lcd.setBacklight(OFF);
digitalWrite(5, LOW);
}
else {
lcd.setBacklight(WHITE);
digitalWrite(5, HIGH);
}


DateTime now = RTC.now();
lcd.setCursor(0, 1);
lcd.print(now.hour(), DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);

getPHvalue();
lcd.setCursor(0,0);
lcd.print("PH:");
lcd.print(PH_Val);

float temperature = getTemp();
lcd.setCursor(8,0);
lcd.print(temperature);
lcd.print("C");

delay(5000); //just here to slow down the output so it is easier to read

}

My apologies for the post length.
shrimper23 is offline   Reply With Quote Quick reply to this message
Old 12-01-2013, 09:23 PM   #162
Pady
Newbie
 
PTrader: (0/0%)
Join Date: Dec 2013
Location: Sweden
Posts: 2
Default

Hello all of you
First of all I would like to say big thanks to Sink and O2surplus and all you other guys :-)
You all helped me getting started with my LED controller Arduino.
I'll have to read it all again to understand how it really works...
I need to fix up 4 channels with different 100% brightness and sunrise/down and moon light. Also putting in and reading everything to my laptop.
Pady is offline   Reply With Quote Quick reply to this message
Old 12-03-2013, 06:07 PM   #163
TomLS
Newbie
 
PTrader: (0/0%)
Join Date: Dec 2013
Location: Portsmouth, UK
Posts: 4
Default

Hi all,

I have been avidly reading this thread, and having no experience of Arduino before this (but a little experience with the Pi, Python, and Linux) I am having some problems.
Firstly, I know this code doesn't compile well with IDE v1.X+, but it seems to have exactly the same problems when I attempt compiling on IDE 0022 on another machine.
For this reason, I am attempting to get it to compile on v1.0.1 for linux, in the hope that I can give something back to the community when I finally have it working!

I have already been through the issues with the time library compatibility, and fixed the libraries on my machine, but I'm now having trouble with DS1307RTC libraries, and the errors mean nothing to me, so I'm hoping someone may be able to help.

It's also worth noting that my original aim was to use this code to take advantage of 4 PWM channels on the arduino, but due to a change in design of my lighting rig, I now only need 3 channels. I have left the fourth channel code in place, but have remmed it out to save myself work if I add extra strings in the future.

My modified version of the code is:

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, DS3231RTC.
 * A bundle of the required libraries (except for Wire, which you should
 * already have) is located in the downloads section of the URL above.  You can
 * always find the latest copy of the code at that location.
 */

/*
 * 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.  
 */

#include <Wire.h>
//#include <RTClib.h>
#include <TimerOne.h>
#include <Time.h>
#include <DS1307RTC.h>
//#include <DS3231RTC.h>

/*
 * 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
const int kChan2Pin = 11; // Channel 2 Pin
//const int kChan3Pin = 6; // Channel 3 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[] = { 600, 800, 800/*, 600*/ }; // daytime LED state
const int kNightState[] = { 0, 0/*, 0*/, 100 }; // nighttime LED state

/*
 * Duration (in seconds) of fade.  At the moment the only fades are sunrise and
 * sunset but this value will apply to any other fades you came up with
 */
const long kFadeDuration = 7200; // 2 hrs

long ctr;

/* hold state info */
int state_chan1, state_chan2, state_chan3/*, state_chan4*/;

/*
 * 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() {
  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]);
    state_chan1 = state[0]; }
  if (state[1] >= 0 && state[1] <= 1023) {
    Timer1.setPwmDuty(kChan1Pin, state[1]);
    state_chan2 = state[1]; }
  if (state[2] >= 0 && state[2] <= 1023) {
    Timer1.setPwmDuty(kChan2Pin, state[2]);
    state_chan3 = state[2]; }
  /*if (state[3] >= 0 && state[3] <= 1023) {
    Timer1.setPwmDuty(kChan3Pin, state[1]);
    state_chan4 = state[3]; }*/
}

/*
 * 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);
  } else if ( ctr >= kTurnOn && ctr <= (kTurnOn+kFadeDuration) ) { // sunrise
    int foo[2];
    fader(kTurnOn, kNightState, kDayState, foo);
    set_state(foo);
  } else if ( ctr > (kTurnOn+kFadeDuration) && ctr < kTurnOff ) { // day
    set_state(kDayState);
  } else if ( ctr >= kTurnOff && ctr <= (kTurnOff+kFadeDuration) ) { // sunset
    int foo[2];
    fader(kTurnOff, kDayState, kNightState, foo);
    set_state(foo);
  } else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ) { // night
    set_state(kNightState);
  }
}

/*
 * 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);
}

/*
 * 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 setup() {
  Serial.begin(115200); // Max for Arduino Uno
  setSyncProvider(RTC.get);
  Timer1.initialize(6666); // 150Hz PWM
  pinMode(kChan0Pin, OUTPUT);     
  Timer1.pwm(kChan0Pin, 0);
  pinMode(kChan1Pin, OUTPUT);     
  Timer1.pwm(kChan1Pin, 0);
  pinMode(kChan2Pin, OUTPUT);     
  Timer1.pwm(kChan2Pin, 0);
/*  pinMode(kChan3Pin, OUTPUT);     
  Timer1.pwm(kChan3Pin, 0);*/
}

void loop () {
  ctr = seconds_since_midnight();
  determine_state();

  if (Serial.available() >= 5) {
    char data[4];
    for (int i=0; i<5; i++) {
      data[i] = Serial.read();
    }

    Serial.flush(); // ensure we never have more than 5 bytes buffered

    if (data[0] == 'A') { // send current time
      time_t longInt = now();
      unsigned char byteArray[4];
                
      // convert from an unsigned long int to a 4-byte array
      byteArray[0] = (int)((longInt >> 24) & 0xFF);
      byteArray[1] = (int)((longInt >> 16) & 0xFF);
      byteArray[2] = (int)((longInt >> 8) & 0XFF);
      byteArray[3] = (int)((longInt & 0XFF));
      // send time
      Serial.print("Z");
      Serial.print(byteArray[0]);
      Serial.print(byteArray[1]);
      Serial.print(byteArray[2]);
      Serial.print(byteArray[3]);
    }
    else if (data[0] == 'B') { // set time
      union u_tag {
        byte b[4];
        unsigned long ulval;
      } u;

      u.b[0] = data[4];
      u.b[1] = data[3];
      u.b[2] = data[2];
      u.b[3] = data[1];

      RTC.set(u.ulval);
      setTime(u.ulval);
      Serial.print("Z0000");
    }
    else {
      Serial.print("X0000");
    }
  }

 delay(250);


  Serial.print("ctr: ");
  Serial.print(ctr); // display counter
  Serial.println(); 
  Serial.print("channel 1, 2: "); 
  Serial.print(state_chan1); 
  Serial.print(", "); 
  Serial.print(state_chan2); 
  Serial.println(); 
  digitalClockDisplay(); //display time
  Serial.println(); 

}

And the resultant errors are:

Code:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp: In static member function ‘static time_t DS1307RTC::get()’:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:39:19: error: invalid operands of types ‘void’ and ‘bool’ to binary ‘operator==’
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp: At global scope:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:54:6: error: prototype for ‘bool DS1307RTC::read(tmElements_t&)’ does not match any in class ‘DS1307RTC’
In file included from /home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:26:0:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.h:19:14: error: candidate is: static void DS1307RTC::read(tmElements_t&)
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:95:6: error: prototype for ‘bool DS1307RTC::write(tmElements_t&)’ does not match any in class ‘DS1307RTC’
In file included from /home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:26:0:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.h:20:14: error: candidate is: static void DS1307RTC::write(tmElements_t&)
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:139:17: error: variable or field ‘exists’ declared void

Any help anyone can give me would be greatly appreciated.

I have also purchased a 20x4 LCD display that I hope to use to display PWM value for each channel, and water, heatsink, and air temperatures using the DS18B20 chip. But for now... baby steps!!

Many thanks,
Tom.
TomLS is offline   Reply With Quote Quick reply to this message
Old 12-03-2013, 06:17 PM   #164
TomLS
Newbie
 
PTrader: (0/0%)
Join Date: Dec 2013
Location: Portsmouth, UK
Posts: 4
Default

Oh, and its probably worth noting that I'm using the Nano V3 ATMega328 board, but from what I can tell it's functionally identical to the uno...

This is related to a post which is still apparently being moderated!...

Last edited by TomLS; 12-03-2013 at 07:37 PM.. Reason: related post in moderation
TomLS is offline   Reply With Quote Quick reply to this message
Old 12-03-2013, 07:36 PM   #165
TomLS
Newbie
 
PTrader: (0/0%)
Join Date: Dec 2013
Location: Portsmouth, UK
Posts: 4
Default

Hi Sink et al.,

I have been avidly reading this thread, and having no experience of Arduino before this (but a little experience with the Pi, Python, and Linux) I am having some problems.
Firstly, I know this code doesn't compile well with IDE v1.X+, but it seems to have exactly the same problems when I attempt compiling on IDE 0022 on another machine.
For this reason, I am attempting to get it to compile on v1.0.1 for linux, in the hope that I can give something back to the community when I finally have it working!

I have already been through the issues with the time library compatibility, and fixed the libraries on my machine, but I'm now having trouble with DS1307RTC libraries, and the errors mean nothing to me, so I'm hoping someone may be able to help.

It's also worth noting that my original aim was to use this code to take advantage of 4 PWM channels on the arduino, but due to a change in design of my lighting rig, I now only need 3 channels. I have left the fourth channel code in place, but have remmed it out to save myself work if I add extra strings in the future.

My modified version of the code is:

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, DS3231RTC.
 * A bundle of the required libraries (except for Wire, which you should
 * already have) is located in the downloads section of the URL above.  You can
 * always find the latest copy of the code at that location.
 */

/*
 * 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.  
 */

#include <Wire.h>
//#include <RTClib.h>
#include <TimerOne.h>
#include <Time.h>
#include <DS1307RTC.h>
//#include <DS3231RTC.h>

/*
 * 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
const int kChan2Pin = 11; // Channel 2 Pin
//const int kChan3Pin = 6; // Channel 3 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[] = { 600, 800, 800/*, 600*/ }; // daytime LED state
const int kNightState[] = { 0, 0/*, 0*/, 100 }; // nighttime LED state

/*
 * Duration (in seconds) of fade.  At the moment the only fades are sunrise and
 * sunset but this value will apply to any other fades you came up with
 */
const long kFadeDuration = 7200; // 2 hrs

long ctr;

/* hold state info */
int state_chan1, state_chan2, state_chan3/*, state_chan4*/;

/*
 * 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() {
  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]);
    state_chan1 = state[0]; }
  if (state[1] >= 0 && state[1] <= 1023) {
    Timer1.setPwmDuty(kChan1Pin, state[1]);
    state_chan2 = state[1]; }
  if (state[2] >= 0 && state[2] <= 1023) {
    Timer1.setPwmDuty(kChan2Pin, state[2]);
    state_chan3 = state[2]; }
  /*if (state[3] >= 0 && state[3] <= 1023) {
    Timer1.setPwmDuty(kChan3Pin, state[1]);
    state_chan4 = state[3]; }*/
}

/*
 * 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);
  } else if ( ctr >= kTurnOn && ctr <= (kTurnOn+kFadeDuration) ) { // sunrise
    int foo[2];
    fader(kTurnOn, kNightState, kDayState, foo);
    set_state(foo);
  } else if ( ctr > (kTurnOn+kFadeDuration) && ctr < kTurnOff ) { // day
    set_state(kDayState);
  } else if ( ctr >= kTurnOff && ctr <= (kTurnOff+kFadeDuration) ) { // sunset
    int foo[2];
    fader(kTurnOff, kDayState, kNightState, foo);
    set_state(foo);
  } else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ) { // night
    set_state(kNightState);
  }
}

/*
 * 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);
}

/*
 * 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 setup() {
  Serial.begin(115200); // Max for Arduino Uno
  setSyncProvider(RTC.get);
  Timer1.initialize(6666); // 150Hz PWM
  pinMode(kChan0Pin, OUTPUT);     
  Timer1.pwm(kChan0Pin, 0);
  pinMode(kChan1Pin, OUTPUT);     
  Timer1.pwm(kChan1Pin, 0);
  pinMode(kChan2Pin, OUTPUT);     
  Timer1.pwm(kChan2Pin, 0);
/*  pinMode(kChan3Pin, OUTPUT);     
  Timer1.pwm(kChan3Pin, 0);*/
}

void loop () {
  ctr = seconds_since_midnight();
  determine_state();

  if (Serial.available() >= 5) {
    char data[4];
    for (int i=0; i<5; i++) {
      data[i] = Serial.read();
    }

    Serial.flush(); // ensure we never have more than 5 bytes buffered

    if (data[0] == 'A') { // send current time
      time_t longInt = now();
      unsigned char byteArray[4];
                
      // convert from an unsigned long int to a 4-byte array
      byteArray[0] = (int)((longInt >> 24) & 0xFF);
      byteArray[1] = (int)((longInt >> 16) & 0xFF);
      byteArray[2] = (int)((longInt >> 8) & 0XFF);
      byteArray[3] = (int)((longInt & 0XFF));
      // send time
      Serial.print("Z");
      Serial.print(byteArray[0]);
      Serial.print(byteArray[1]);
      Serial.print(byteArray[2]);
      Serial.print(byteArray[3]);
    }
    else if (data[0] == 'B') { // set time
      union u_tag {
        byte b[4];
        unsigned long ulval;
      } u;

      u.b[0] = data[4];
      u.b[1] = data[3];
      u.b[2] = data[2];
      u.b[3] = data[1];

      RTC.set(u.ulval);
      setTime(u.ulval);
      Serial.print("Z0000");
    }
    else {
      Serial.print("X0000");
    }
  }

 delay(250);


  Serial.print("ctr: ");
  Serial.print(ctr); // display counter
  Serial.println(); 
  Serial.print("channel 1, 2: "); 
  Serial.print(state_chan1); 
  Serial.print(", "); 
  Serial.print(state_chan2); 
  Serial.println(); 
  digitalClockDisplay(); //display time
  Serial.println(); 

}

And the resultant errors are:

/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp: In static member function ‘static time_t DS1307RTC::get()’:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:39:19: error: invalid operands of types ‘void’ and ‘bool’ to binary ‘operator==’
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp: At global scope:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:54:6: error: prototype for ‘bool DS1307RTC::read(tmElements_t&)’ does not match any in class ‘DS1307RTC’
In file included from /home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:26:0:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.h:19:14: error: candidate is: static void DS1307RTC::read(tmElements_t&)
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:95:6: error: prototype for ‘bool DS1307RTC::write(tmElements_t&)’ does not match any in class ‘DS1307RTC’
In file included from /home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:26:0:
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.h:20:14: error: candidate is: static void DS1307RTC::write(tmElements_t&)
/home/tom/sketchbook/libraries/DS1307RTC/DS1307RTC.cpp:139:17: error: variable or field ‘exists’ declared void


Any help anyone can give me would be greatly appreciated.

I have also purchased a 20x4 LCD display that I hope to use to display PWM value for each channel, and water, heatsink, and air temperatures using the DS18B20 chip. But for now... baby steps!!

Many thanks,
Tom.
TomLS is offline   Reply With Quote Quick reply to this message
Reply

Quick Reply
Message:
Options

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.



Thread Tools
Display Modes

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

Forum Jump


All times are GMT. The time now is 07:07 AM.


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