Go Down

Topic: PWM dimming problem (Read 383 times) previous topic - next topic

Mr_Stian

Hello everyone. I am working on my own LED light for nye aquarium, and are now finished with the hardware and are working on the code. I have a arduino Leonardo controlling 6 LED channels with PMW signal via 6 LED LDD drivers from Meanwell.

I have checked that all the channels work using analogWrite commands so they all work.

I found a sketch somwhere online (can not find were at the moment) and adapted this to have 6 channels. The original one only had 2. That is the only modifications i have done. I have the DS1307 RTC and a I2C controlled LCD panel (connected, but not in use yet)

The problems i am having is that it always seems to be night mode. That there are some problems with getting the time from the RTC. I used this code to set the time on the RTC:

Code: [Select]
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>

int rtc[7];

void setup()
{
  Serial.begin(9600);
/*
  RTC.stop();
  RTC.set(DS1307_SEC,1);
  RTC.set(DS1307_MIN,57);
  RTC.set(DS1307_HR,17);
  RTC.set(DS1307_DOW,4);
  RTC.set(DS1307_DATE,18);
  RTC.set(DS1307_MTH,2);
  RTC.set(DS1307_YR,9);
  RTC.start();
*/
}

void loop()
{
  RTC.get(rtc,true);

  for(int i=0; i<7; i++)
  {
    Serial.print(rtc[i]);
    Serial.print(" ");
  }
  Serial.println();

  delay(1000);

}


When i adapted the serial monitor code to the light script the RTC showed the correct time.

Can anyone see if there is a problem with my light controller script? Here is the code:

Code: [Select]
/*
Arduino LED controller for reef aquariums

// paramterized LED lighting control for reef aquariums
// use a DS1307 RTC to kick off lighting schedules
//   fade up on a given slope
//         delay a set amount
//         fade back down
//   such that the photoperiod lasts the correct amount of time


//  Circuit
//
// PWM pins described below connected to dimming circuits on drivers
// ledMaster pin below connected to a 120V AC relay to turn the LED drivers on and off (optional)
// grounds from drivers connected to arduino ground
// DS1307 RTC connected via I2C
//
//
//

*/

// Pins to control LEDs. Change these if you're using different pins.
int actinic1Led = 5;    // LED PMW channel for actinic. Channel 1 Lumina 5.2 LED
int blueLed = 6;        // LED PWM channel for blues. Channel 2 Lumina 5.2 LED
int whiteLed = 9;      // LED PWM channel for whites. Channel 3 Lumina 5.2 LED
int colorLed = 10;      // LED PMW channel for enhanced color spectrum. Channel 4 Lumina 5.2 LED
int actinic2Led = 11;   // LED PMW channel for actinic. Channel 5 Lumina 5.2 LED
int moonlightLed = 13;  // LED PMW channel for moonlight.


// Set up RTC
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year;

// Other variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0;            // counter that resets at midnight. Don't change this.
int blueStartMins = 480;       // minute to start blues. Change this to the number of minutes past
                               //    midnight you want the blues to start.
int whiteStartMins = 480;      // minute to start whites. Same as above.
int actinicStartMins = 480;    // minute to start actinic. Same as above.
int colorStartMins = 480;       // minute to start color channel. Same as above.
int moonlightStartMins = 0;    // minute to start moonlight. Same as above.
int bluePhotoPeriod = 510;     // photoperiod in minutes, blues. Change this to alter the total
                               //    photoperiod for blues.
int whitePhotoPeriod = 510;    // photoperiod in minutes, whites. Same as above.
int actinicPhotoPeriod = 510;  // photoperiod in minutes, actinic. Same as above.
int colorPhotoPeriod = 510;    // photoperiod in minutes, color. Same as above.
int moonlightPhotoPeriod = 510;     // photoperiod in minutes, monlight. Same as above.

int fadeDuration = 60;      // duration of the fade on and off for sunrise and sunset. Change
                            //    this to alter how long the fade lasts.
int blueMax = 255;          // max intensity for blues. Change if you want to limit max intensity. channel 2
int whiteMax = 255;         // max intensity for whites. Same as above. Channel 3
int actinicMax = 255;       // maxintensety for actinic channel 1 and 5
int moonlightMax = 255;     // max intensety for moonlight
int colorMax = 255;         // max intensety for color channel 4


/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins,    // current time in minutes
            int ledPin,  // pin for this channel of LEDs
            int start,   // start time for this channel of LEDs
            int period,  // photoperiod for this channel of LEDs
            int fade,    // fade duration for this channel of LEDs
            int ledMax   // max value for this channel
            )  {
  if (mins > start && mins <= start + fade)  {
    analogWrite(ledPin, map(mins - start, 0, fade, 0, ledMax));
  }
    if (mins > start + period && mins <= start + period - fade)  {
    analogWrite(ledPin, ledMax);
  }
    if (mins > start + period - fade && mins <= start + period)  {
    analogWrite(ledPin, map(mins - start + period - fade, 0, fade, ledMax, 0));
  }
}

/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 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.
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.write(0);
   Wire.write(decToBcd(second));
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

void setup()  {
 
// init I2C 
  Wire.begin();
}

/***** Main Loop ***********/
/***************************/
void loop()  {
  // get time from RTC and put in hrs and mins variables
  getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
  minCounter = rtcHrs * 60 + rtcMins;

  // determine if it is day or night, and act accordingly
  if ((minCounter > blueStartMins || minCounter > whiteStartMins || minCounter > actinicStartMins || minCounter > colorStartMins)
           && (minCounter < blueStartMins + bluePhotoPeriod || minCounter < whiteStartMins + whitePhotoPeriod
           || minCounter < actinicStartMins + actinicPhotoPeriod || minCounter < colorStartMins + colorPhotoPeriod))  {   //day
    // set LED states
    setLed(minCounter, blueLed, blueStartMins, bluePhotoPeriod, fadeDuration, blueMax);
    setLed(minCounter, whiteLed, whiteStartMins, whitePhotoPeriod, fadeDuration, whiteMax);
    setLed(minCounter, colorLed, colorStartMins, colorPhotoPeriod, fadeDuration, colorMax);
    setLed(minCounter, actinic1Led, actinicStartMins, actinicPhotoPeriod, fadeDuration, actinicMax);
    setLed(minCounter, actinic2Led, actinicStartMins, actinicPhotoPeriod, fadeDuration, actinicMax);
    analogWrite(moonlightLed, 50);
  }
  else  {   //night
    analogWrite(blueLed, 0);
    analogWrite(whiteLed, 0);
    analogWrite(actinic1Led, 0);
    analogWrite(actinic2Led, 0);
    analogWrite(colorLed, 0);
    analogWrite(moonlightLed, 100);
  }
   
  // Get ready for next iteration of loop
  delay(1000);
}


I see from the basic sketch that i used to set the RTC do not use the address of the RTC. Can this cause this? Do i have to set the time with another sketch, or is it possible from the main sketch?

Thank you for taking the time to help me! :)

luisilva

My first advice is that you may use the library at your main code. If yo don't do that how you want to find the error?

megaBlocks

#2
Aug 04, 2014, 10:32 pm Last Edit: Aug 04, 2014, 10:37 pm by megaBlocks Reason: 1
Do you ever set pinMode(pin, OUTPUT)?? I didnt see that being called in your setup() function.
"""please help me , i don't  know how stop my motor"""

Mr_Stian

Could you elaborate? I do not understand your reply. Which library?

I am very new to programming Arduino so sorry if this is a stupid question.

megaBlocks

try replacing you setup function with this:

Code: [Select]

void setup()  {
  pinMode(actinic1Led,OUTPUT);
  pinMode(blueLed,OUTPUT);
  pinMode(whiteLed,OUTPUT);
  pinMode(colorLed,OUTPUT);
  pinMode(actinic2Led,OUTPUT);
  pinMode(moonlightLed,OUTPUT);
 
// init I2C 
  Wire.begin();
}


Also to save on variable space try replacing your "int" decorations with "const int" instead, like this:
Code: [Select]

const int actinic1Led = 5;    // LED PMW channel for actinic. Channel 1 Lumina 5.2 LED
const int blueLed = 6;        // LED PWM channel for blues. Channel 2 Lumina 5.2 LED
const int whiteLed = 9;      // LED PWM channel for whites. Channel 3 Lumina 5.2 LED
const int colorLed = 10;      // LED PMW channel for enhanced color spectrum. Channel 4 Lumina 5.2 LED
const int actinic2Led = 11;   // LED PMW channel for actinic. Channel 5 Lumina 5.2 LED
const int moonlightLed = 13;  // LED PMW channel for moonlight.
"""please help me , i don't  know how stop my motor"""

luisilva


Could you elaborate? I do not understand your reply. Which library?

I am very new to programming Arduino so sorry if this is a stupid question.


If this reply is for me, I referring to the library DS1307.h. In the sketch of the serial line you have it:
Code: [Select]
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>   // <--- This is the library that I referring

int rtc[7];

void setup()
{
  Serial.begin(9600);
/*
  RTC.stop();
  RTC.set(DS1307_SEC,1);
  RTC.set(DS1307_MIN,57);
  RTC.set(DS1307_HR,17);
  RTC.set(DS1307_DOW,4);
  RTC.set(DS1307_DATE,18);
  RTC.set(DS1307_MTH,2);
  RTC.set(DS1307_YR,9);
  RTC.start();
*/
}

void loop()
{
  RTC.get(rtc,true);

  for(int i=0; i<7; i++)
  {
    Serial.print(rtc[i]);
    Serial.print(" ");
  }
  Serial.println();

  delay(1000);

}


I don't know that library and I don't here you get it. My advice is, try to download this other library:
https://github.com/adafruit/RTClib
I use it and I like it. Install it and try to use the examples, and to adapt it for what you are trying to do.

Mr_Stian

I found the page that had the source code, and no one of the guys using it use the library DS1307.h

I can also add the OUTPUT to the sketch, but not sure if this helps as the moonlights are on, as if the time is in the middle of the night.

I have some questions about this part of the code:

Code: [Select]
// 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.
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99


Is this to set the time on the RTC? Can i just add the time and date behind each byte, uploade and then remove the time and date and upload again?

Mr_Stian

I managed to figure out why it did not work. There were an error in the if statement when the LED´s were supposed to be at max.

This is the fixed state:

Code: [Select]
/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins,    // current time in minutes
            int ledPin,  // pin for this channel of LEDs
            int start,   // start time for this channel of LEDs
            int period,  // photoperiod for this channel of LEDs
            int fade,    // fade duration for this channel of LEDs
            int ledMax   // max value for this channel
            )  {
  if (mins > start && mins <= start + fade)  {
    analogWrite(ledPin, map(mins - start, 0, fade, 0, ledMax));
  }
    if (mins > start + fade && mins <= start + period - fade)  {
    analogWrite(ledPin, ledMax);
  }
    if (mins > start + period - fade && mins <= start + period)  {
    analogWrite(ledPin, map(mins - start + period - fade, 0, fade, ledMax, 0));
  }
}


The second if statement originally said if mins > start + photoperiod. This is wrong. This phase starts after mins > start + fade

So now it works as it is supposed to work....

TomGeorge

Hi,

Quote
LED LDD drivers from Meanwell.


Can you tell us the specifications or part number of the driver please.

Tom..... :)
Everything runs on smoke, let the smoke out, it stops running......VK3DMK

MarkT

You have a function that's a great candidate for using references rather than pointers:

Code: [Select]
// Gets the date and time from the ds1307
void getDateDs1307(byte & second,
          byte & minute,
          byte & hour,
          byte & dayOfWeek,
          byte & dayOfMonth,
          byte & month,
          byte & year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  second     = bcdToDec(Wire.read() & 0x7f);
  minute     = bcdToDec(Wire.read());
  hour       = bcdToDec(Wire.read() & 0x3f);
  dayOfWeek  = bcdToDec(Wire.read());
  dayOfMonth = bcdToDec(Wire.read());
  month      = bcdToDec(Wire.read());
  year       = bcdToDec(Wire.read());
}


And then the call would be:
Code: [Select]
  getDateDs1307(second, rtcMins, rtcHrs, dayOfWeek, dayOfMonth, month, year);

instead of
Code: [Select]
  getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
[ I won't respond to messages, use the forum please ]

Go Up