justindost1
New member
i have used a basic pwm dimming code to make sure the driver is working and hooked up correctly but when i use this code the leds wont come on till the pwm value is at full. and if i try to change the max value from anything other than 100 it wont come on at all.
this is the full code
Code:
#define MAX_CHANNEL_PAIRS 4
_channelPair channels[MAX_CHANNEL_PAIRS] = {
{ 11, 7, 0 },
{ 10, 6, 0 },
{ 9, 5, 0 },
{ 8, 4, 0}
};
////////////////////////////////////////////////////////////
#define WHITE_MAX 100 // Maximum white level
#define BLUE_MAX 100 // Maximum blue level
#define DAWN_DUSK_OFFSET 45U // How sooner should blue lights come up before white, and how later should they go off after white
this is the full code
Code:
/**********************************************************************************
Aquarium LED controller with weather simulation
Copyright (C) 2010, 2011, Fabio Luis De Paoli
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as published
by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License v3
along with this program. If not, see
<http://www.gnu.org/licenses/gpl-3.0-standalone.html>.
// Definition of a light waypoint
struct _waypoint {
unsigned int time; // in 2 seconds, 1h=900 2secs, 24h = 43200 2secs
byte level;
};
// Definition of a segment
struct _segment {
unsigned int strTime; // Start
byte strLevel; // Start
unsigned int finTime; // Finish
byte finLevel; // Finish
};
/////////////////////////////////////////////////////////////
// Section where we define the white-blue channel pairs
struct _channelPair {
byte wPin;
byte bPin;
unsigned int channelDelay;
};
#define MAX_CHANNEL_PAIRS 4
_channelPair channels[MAX_CHANNEL_PAIRS] = {
{ 11, 7, 0 },
{ 10, 6, 0 },
{ 9, 5, 0 },
{ 8, 4, 0}
};
////////////////////////////////////////////////////////////
#define WHITE_MAX 100 // Maximum white level
#define BLUE_MAX 100 // Maximum blue level
#define DAWN_DUSK_OFFSET 45U // How sooner should blue lights come up before white, and how later should they go off after white
/******************************************************************************************
* BCD TO DEC
*
* Convert binary coded decimal to normal decimal
* numbers
**/
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
//////////////////////////////////////////////////////////////////
/******************************************************************************************
* DO LIGHTNING
*
* Do lightning, flashing all the LEDs at full intensity in a lightning like pattern.
*
* Inspired by lightning code posted by Numlock10@ReefCentral
* http://www.reefcentral.com/forums/showpost.php?p=17542851&postcount=206
**/
void doLightning(byte aWhiteLevel, byte aBlueLevel) {
byte numberOfFlashes = (byte) random(5) +1;
byte maxLightLevel;
if (aBlueLevel < 20) {
maxLightLevel = (aBlueLevel * 2) + 3;
} else {
maxLightLevel = WHITE_MAX;
}
byte var = 0;
while (var < numberOfFlashes) {
// LEDs on for 50ms
for (byte i=0; i<MAX_CHANNEL_PAIRS; i++) {
setLedPWMOutputs(i, maxLightLevel, maxLightLevel);
}
delay(50);
// LED off for 50ms
for (byte i=0; i<MAX_CHANNEL_PAIRS; i++) {
setLedPWMOutputs(i, 0, 0);
}
delay(50);
// LED on for 50ms to 250ms
for (byte i=0; i<MAX_CHANNEL_PAIRS; i++) {
setLedPWMOutputs(i, maxLightLevel, maxLightLevel);
}
delay(random(50,250));
// set the LED back to normal levels for 50ms to 1sec
for (byte i=0; i<MAX_CHANNEL_PAIRS; i++) {
setLedPWMOutputs(i, aWhiteLevel, aBlueLevel);
}
delay(random(50,1000));
var++;
}
Serial.print("##LIGHTNING x");
Serial.print(numberOfFlashes, DEC);
Serial.print(" @");
Serial.println(maxLightLevel,DEC);
}
///////////////////////////////////////////////////
/**************************************************************************
* PLAN BASIC CURVE
*
* Plan the basic light curve for the day, before clouds and other
* special effects are considered, just sunrise/sunset and the rest.
**/
void planBasicCurve(byte aMonth, byte aDay) {
unsigned int wSunriseStart, bSunriseStart;
unsigned int wSunsetFinish, bSunsetFinish;
unsigned int wFadeDuration, bFadeDuration;
unsigned int wFadeStep, bFadeStep;
//------------- BASIC CURVE -------------
wFadeDuration = (unsigned int) map((unsigned int) aDay, 1U, (unsigned int) daysInMonth[aMonth-1], (unsigned int) minFadeDuration[aMonth-1], (unsigned int) maxFadeDuration[aMonth-1]);
bFadeDuration = wFadeDuration + DAWN_DUSK_OFFSET/2U;
wFadeDuration = wFadeDuration - DAWN_DUSK_OFFSET/2U;
wSunriseStart = (unsigned int) map((unsigned int) aDay, 1U, (unsigned int) daysInMonth[aMonth-1], (unsigned int) minSunriseStart[aMonth-1], (unsigned int) maxSunriseStart[aMonth-1]);
bSunriseStart = wSunriseStart - DAWN_DUSK_OFFSET/2U;
wSunriseStart = wSunriseStart + DAWN_DUSK_OFFSET/2U;
wSunsetFinish = (unsigned int) map((unsigned int) aDay, 1U, (unsigned int) daysInMonth[aMonth-1], (unsigned int) minSunsetFinish[aMonth-1], (unsigned int) maxSunsetFinish[aMonth-1]);
bSunsetFinish = wSunsetFinish + DAWN_DUSK_OFFSET/2U;
wSunsetFinish = wSunsetFinish - DAWN_DUSK_OFFSET/2U;
// 30 transforms "1 min" in "2 secs":
wFadeDuration = wFadeDuration * 30U;
bFadeDuration = bFadeDuration * 30U;
wSunriseStart = wSunriseStart * 30U;
wSunsetFinish = wSunsetFinish * 30U;
bSunriseStart = bSunriseStart * 30U;
bSunsetFinish = bSunsetFinish * 30U;
wFadeStep = wFadeDuration / 5U;
bFadeStep = bFadeDuration / 5U;
dcwWhiteCurve[0].time = 0;
dcwWhiteCurve[0].level = 0;
dcwWhiteCurve[1].time = wSunriseStart;
dcwWhiteCurve[1].level = 0;
dcwWhiteCurve[2].time = wSunriseStart + wFadeStep;
dcwWhiteCurve[2].level = (WHITE_MAX * 10) / 100;
dcwWhiteCurve[3].time = wSunriseStart + 2U*wFadeStep;
dcwWhiteCurve[3].level = (WHITE_MAX * 30) / 100;
dcwWhiteCurve[4].time = wSunriseStart + 3U*wFadeStep;
dcwWhiteCurve[4].level = (WHITE_MAX * 70) / 100;
dcwWhiteCurve[5].time = wSunriseStart + 4U*wFadeStep;
dcwWhiteCurve[5].level = (WHITE_MAX * 90) / 100;
dcwWhiteCurve[6].time = wSunriseStart + 5U*wFadeStep;
dcwWhiteCurve[6].level = WHITE_MAX;
dcwWhiteCurve[7].time = wSunsetFinish - 5U*wFadeStep;
dcwWhiteCurve[7].level = WHITE_MAX;
dcwWhiteCurve[8].time = wSunsetFinish - 4U*wFadeStep;
dcwWhiteCurve[8].level = (WHITE_MAX * 90) / 100;
dcwWhiteCurve[9].time = wSunsetFinish - 3U*wFadeStep;
dcwWhiteCurve[9].level = (WHITE_MAX * 70) / 100;
dcwWhiteCurve[10].time = wSunsetFinish - 2U*wFadeStep;
dcwWhiteCurve[10].level = (WHITE_MAX * 30) / 100;
dcwWhiteCurve[11].time = wSunsetFinish - wFadeStep;
dcwWhiteCurve[11].level = (WHITE_MAX * 10) / 100;
dcwWhiteCurve[12].time = wSunsetFinish;
dcwWhiteCurve[12].level = 0;
dcwWhiteCurve[13].time = 1440U * 30U;
dcwWhiteCurve[13].level = 0;
dcwBlueCurve[0].time = 0;
dcwBlueCurve[0].level = 0;
dcwBlueCurve[1].time = bSunriseStart;
dcwBlueCurve[1].level = 0;
dcwBlueCurve[2].time = bSunriseStart + bFadeStep;
dcwBlueCurve[2].level = (BLUE_MAX * 10) / 100;
dcwBlueCurve[3].time = bSunriseStart + 2U*bFadeStep;
dcwBlueCurve[3].level = (BLUE_MAX * 30) / 100;
dcwBlueCurve[4].time = bSunriseStart + 3U*bFadeStep;
dcwBlueCurve[4].level = (BLUE_MAX * 70) / 100;
dcwBlueCurve[5].time = bSunriseStart + 4U*bFadeStep;
dcwBlueCurve[5].level = (BLUE_MAX * 90) / 100;
dcwBlueCurve[6].time = bSunriseStart + 5U*bFadeStep;
dcwBlueCurve[6].level = BLUE_MAX;
dcwBlueCurve[7].time = bSunsetFinish - 5U*bFadeStep;
dcwBlueCurve[7].level = BLUE_MAX;
dcwBlueCurve[8].time = bSunsetFinish - 4U*bFadeStep;
dcwBlueCurve[8].level = (BLUE_MAX * 90) / 100;
dcwBlueCurve[9].time = bSunsetFinish - 3U*bFadeStep;
dcwBlueCurve[9].level = (BLUE_MAX * 70) / 100;
dcwBlueCurve[10].time = bSunsetFinish - 2U*bFadeStep;
dcwBlueCurve[10].level = (BLUE_MAX * 30) / 100;
dcwBlueCurve[11].time = bSunsetFinish - bFadeStep;
dcwBlueCurve[11].level = (BLUE_MAX * 10) / 100;
dcwBlueCurve[12].time = bSunsetFinish;
dcwBlueCurve[12].level = 0;
dcwBlueCurve[13].time = 1440U * 30U;
dcwBlueCurve[13].level = 0;
}
/**************************************************************************
* PLAN NEW DAY
*
* This is the function that is called when we enter a new day, it calls
* planBasicCurve for the basic light with no clouds, then determines
* the oktas number for the day, which will determine how many clouds
* and at what spacing we will have
**/
void planNewDay(byte aMonth, byte aDay) {
planBasicCurve(aMonth, aDay);
if (!DEBUG_MODE) {
//------------- OKTA DETERMINATION -------------
byte randNumber;
randNumber = (byte) random(0,100);
if (randNumber > cloudyDays[aMonth]) {
// this is a mixed day, Okta 2 to 3
okta = (byte) random(2,4);
} else if (randNumber > clearDays[aMonth] ) {
// this is a cloudy day, Okta 4 to 8
okta = (byte) random(4,9);
} else {
// this is a clear day, Okta 0 to 1
okta = (byte) random(0,2);
}
}
Serial.print("Okta=");
Serial.print(okta, DEC);
setCloudSpacingAndTypes();
Serial.print(", type1=");
Serial.print(cloudType1, DEC);
Serial.print(", type2=");
Serial.print(cloudType2, DEC);
Serial.print(", spacing=");
Serial.println(cloudSpacing, DEC);
currCloudCoverFinish = 0;
}
void serialCommands()
{
int command = 0; // This is the command char, in ascii form, sent from the serial port
int i;
byte test;
if (Serial.available()) { // Look for char in serial que and process if found
command = Serial.read();
if (command == 73) { // "I" = Info
Serial.print("Okta: ");
Serial.println(okta,DEC);
dumpCurve();
}
if (command == 76) { // "L" = doLigthning based off zero
doLightning(prevWLevel, prevBLevel);
}
if (command == 79) { // "O" = Set okta and recalculate day
if (Serial.available()) {
command = Serial.read();
okta = command - 48;
setCloudSpacingAndTypes();
currCloudCoverFinish = 0;
Serial.print("Okta reset to: ");
Serial.println(okta,DEC);
}
}
if (command == 82) { //If command = "R" Read date and time
getDateDs1307();
printDateTime();
Serial.println(" ");
}
if (command == 84) { //If command = "T" Set Date
setDateDs1307();
getDateDs1307();
printDateTime();
Serial.println(" ");
}
else if (command == 81) { //If command = "Q" RTC1307 Memory Functions
delay(100);
if (Serial.available()) {
command = Serial.read();
if (command == 49) { //If command = "1" RTC1307 Initialize Memory - All Data will be set to 255 (0xff). Therefore 255 or 0 will be an invalid value.
Wire.beginTransmission(DS1307_I2C_ADDRESS); // 255 will be the init value and 0 will be considered an error that occurs when the RTC is in Battery mode.
Wire.send(0x08); // Set the register pointer to be just past the date/time registers.
for (i = 1; i <= 27; i++) {
Wire.send(0xff);
delay(100);
}
Wire.endTransmission();
getDateDs1307();
printDateTime();
Serial.println(": RTC1307 Initialized Memory");
}
else if (command == 50) { //If command = "2" RTC1307 Memory Dump
getDateDs1307();
printDateTime();
Serial.println(": RTC 1307 Dump Begin");
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0x00);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 64);
for (i = 1; i <= 64; i++) {
test = Wire.receive();
Serial.print(i);
Serial.print(":");
Serial.println(test, DEC);
}
Serial.println(" RTC1307 Dump end");
}
}
}
Serial.print("Command: ");
Serial.println(command); // Echo command CHAR in ascii that was sent
}
command = 0; // reset command
delay(100);
}
/****************************************************************
* SET LED PWM OUTPUTS
*
* Set all the LED channels we have connected to the Arduino
* with the right PWM light value
*
* For this function the bluePwmLevel and whitePwmLevel
* are expressed in percentage 0-100
*****************************************************************/
void setLedPWMOutputs(byte channel, byte whitePwmLevel, byte bluePwmLevel) {
byte level = 0;
level = (byte) ( ((unsigned int)whitePwmLevel *255U) /100U );
analogWrite(channels[channel].wPin, level);
level = (byte) ( ((unsigned int)bluePwmLevel *255U) /100U );
analogWrite(channels[channel].bPin, level);
}
/************************************************************
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers, Probably need to put in checks for valid numbers.
// Format: ssmmhhWDDMMYY (W=Day of the week, Sunday = 0)
*/
void setDateDs1307()
{
second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minute = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hour = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
dayOfWeek = (byte) (Serial.read() - 48);
dayOfMonth = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year= (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0x00);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
}
/**************************************************************************
* LOOP
*
**/
void loop() {
unsigned int now;
byte wLevel, bLevel;
boolean inThunder;
byte inCloud;
boolean minuteChanged = false;
serialCommands();
getDateDs1307();
if ((hour == 0) && (minute ==00) && (dayOfMonth == 0) && (year == 0)) {
// Communication with RTC failed, get out of loop before something
// bad happens
Serial.print("#");
heartbeat();
delay(200);
return;
}
//////////////IR REMOTE //////////////////
/////////////////////////////////////////
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
for (int z=0; z<2; z++) // ignore 2nd and 3rd signal repeat
{
irrecv.resume(); // receive the next value
}
}
/////////////////////////////////////////////////////////////////////
// If the day changed, plan the new day
if (prevDayOfMonth != dayOfMonth) {
Serial.println();
Serial.println();
printDateTime();
Serial.println(" ");
Serial.print("DofM:");
Serial.print(prevDayOfMonth, DEC);
Serial.print("->");
Serial.println(dayOfMonth, DEC);
prevDayOfMonth = dayOfMonth;
planNewDay(month, dayOfMonth);
dumpCurve();
}
if (!DEBUG_MODE) {
now = (hour*1800U + minute*30U + second/2U);
} else {
now = debug_now;
minute = now/60;
}
if (now != prevNow) {
heartbeat();
prevNow = now;
}
if (prevMinute != minute) {
Serial.print("++");
printDateTime();
Serial.println(" ");
prevMinute = minute;
minuteChanged = true;
dstemp();
}
// Loop through the LED channel pairs getting their light levels
for (byte i=0; i<MAX_CHANNEL_PAIRS; i++) {
boolean channelInThunder;
unsigned int chanDelay;
// Protection against unsigned int roll backwards
chanDelay = channels[i].channelDelay;
if (chanDelay > now) {
chanDelay = now;
}
getLevel(now - chanDelay, &channelInThunder, &wLevel, &bLevel);
setLedPWMOutputs(i, wLevel, bLevel);
if (channels[i].channelDelay == 0) {
inThunder = channelInThunder;
}
}
// In the future change this to LCD output
if ((prevWLevel != wLevel) || (prevBLevel != bLevel)) {
inCloud = insideCloud(now);
logLevel(now, wLevel, bLevel, inCloud, inThunder);
}
// If in Thunderstorm, 5% possible lighning every minute
#define LIGHTNING_CHANCE 5
if ((inThunder) && (minuteChanged)) {
byte randNumber = (byte) random(0, 100);
if (randNumber <= LIGHTNING_CHANCE) {
doLightning(wLevel, bLevel);
}
}
prevWLevel = wLevel;
prevBLevel = bLevel;
prevMinute = minute;
planNextCloudBatch(now);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**************************************************************************
* SETUP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
**/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Wire.begin();
Serial.begin(9600);
randomSeed(analogRead(0));
heartbeatLevel = LOW;
getDateDs1307();
// Zero the key variables
currCloudCoverStart = 0;
currCloudCoverFinish = 0;
prevWLevel = 0;
prevBLevel = 0;
prevDayOfMonth = 0;
dayOfMonth = 40; // Invalid number to force planNewDay in first loop
if (DEBUG_MODE) {
okta=0;
xTestRun();
prevDayOfMonth = 0;
okta=1;
xTestRun();
prevDayOfMonth = 0;
okta=2;
xTestRun();
prevDayOfMonth = 0;
okta=3;
xTestRun();
prevDayOfMonth = 0;
okta=4;
xTestRun();
prevDayOfMonth = 0;
okta=5;
xTestRun();
prevDayOfMonth = 0;
okta=6;
xTestRun();
prevDayOfMonth = 0;
okta=7;
xTestRun();
prevDayOfMonth = 0;
okta=8;
xTestRun();
}
//////////IR REMOTE//////////////////////
irrecv.enableIRIn(); // Start the receiver
}
/******************************************************************************
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers, Probably need to put in checks for valid numbers.
//
// Format: ssmmhhWDDMMYY (W=Day of the week, Sunday = 0)
void setDateDs1307() {
second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minute = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hour = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
dayOfWeek = (byte) (Serial.read() - 48);
dayOfMonth = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year= (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0x00);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
printDateTime();
}
*/
void logLevel(unsigned int tNow, byte wTLevel, byte bTLevel, byte tInCloud, boolean tInThunder)
{
Serial.print(tNow,DEC);
Serial.print(",");
Serial.print(wTLevel,DEC);
Serial.print(",");
Serial.print(bTLevel,DEC);
Serial.print(",");
Serial.print(tInCloud,DEC);
Serial.print(",");
Serial.print(tInThunder,DEC);
Serial.println();
}