Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
I've got 3 of these lights on my 55G, a Klein m700 multimeter, an Arduino, and I'm on vacation... After going through this thread and spending a few hours playing with everything today, here's what I know.
If you have blues on, whites off, and you accidentally touch pins 1 and 2 with your meter probe at the same time the whites will flash and scare the heck out of you...
Connecting the gnd pin from an arduino to the G pin on the wire connector, and low pass filtered 1.25 VDC from an arduino PWM pin to either of 1 or 2 on the wire connector, will cause a brief flicker then darkness. The driver specs oreo posted mentions either PWM or DC voltage control, but that doesn't seem to be implemented/accessible via the 1 & 2 pins on the wire connector.
The mystery zero ohm R1 resistor is a simple bridge that allows 24VDC to jump over driver 2's DIM trace and make it over to the controller.
The frequency between G and pins 1 or 2 on the wire connector is 20.08 khz.
Arduino Uno PWM operates at about 489 hz, but it's possible to generate 20khz PWM via a generic loop and playing with counters. It will work with the stock Arduino PWM, but it buzzes horribly at that 489 hz.
To get control over dimming this light, I connected GND on the arduino to G on the wiring connector, then one of the 5V GPIO pins to each of the 1 & 2 pins on the wiring connector. From there, it's just a matter of varying the duty cycle on that GPIO at 20 khz to set the brightness. No other components needed.
Just to avoid going insane when you download the library at the link above you have to make a small alteration. I found that once the zip file is downloaded it will not install correctly following the advice on https://www.arduino.cc/en/Guide/Libraries. I eventually found out that it might be best to extract the zip file then transfer to the default folder usually Documents/Arduino/libraries . Now open the extracted file to find PWM folder/ open this and copy contents/ then return one step and paste the files in the same directory as the PWM folder.This should now show up in the include library option of the compiler
#include <PWM.h>
//#define DEBUG
/*
CONFIGURABLE
*/
// which Arduino PWM pins to use (do not use 5 or 6, doing so will literally cause a timewarp...)
const byte BLUES_PIN = 9;
const byte WHITES_PIN = 10;
// how bright the lights are allowed to get
const byte blue_max_level = 255; // 0-255
const byte white_max_level = 50; // 0-255
// cloudy weather
const bool clouds = true;
byte cloud_max_shade = 40; // 1-white_max_level (white_max_level is complete darkness) this is the maximum shadow clouds can cast
const unsigned long cloud_min_duration = 60000; // milliseconds, a cloud will last at least this long
const unsigned long cloud_max_duration = 300000; // milliseconds, this is how long a single cloud can last
const unsigned long cloud_min_between = 10000; // milliseconds, at least this long will pass between clouds
const unsigned long cloud_max_between = 60000; // milliseconds, this is how much time can pass between clouds
// start 7AM, rise until 10AM, peak until 8PM, fall until 9PM
const unsigned long blue_rise_duration = 10800000; // milliseconds
const unsigned long blue_peak_duration = 36000000; // milliseconds
const unsigned long blue_fall_duration = 3600000; // milliseconds
// start 8AM, rise untill 10AM, peak untill 4PM, fall until 5PM
const unsigned long white_rise_start = 3600000; // milliseconds
const unsigned long white_rise_duration = 7200000; // milliseconds
const unsigned long white_peak_duration = 21600000; // milliseconds
const unsigned long white_fall_duration = 3600000; // milliseconds
/*
END CONFIGURABLE
*/
unsigned long now;
unsigned long blue_peak_end, blue_fall_end, blue_duration;
unsigned long white_rise_end, white_peak_end, white_fall_end, white_duration;
unsigned long cloud_start, cloud_end, cloud_middle;
byte blue_level, last_blue_level;
byte white_level, last_white_level;
byte cloud_shade;
void setup()
{
InitTimersSafe();
randomSeed(analogRead(A0));
#ifdef DEBUG
Serial.begin(9600);
#endif
if(SetPinFrequency(BLUES_PIN, 20000) && SetPinFrequency(WHITES_PIN, 20000))
{
pwmWrite(BLUES_PIN, 0);
pwmWrite(WHITES_PIN, 0);
//SetPinFrequency(D3, 20000); SetPinFrequency(11, 20000);
//pwmWrite(3, 255); pwmWrite(11, 255);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}
blue_peak_end = blue_rise_duration + blue_peak_duration;
blue_fall_end = blue_peak_end + blue_fall_duration;
blue_duration = blue_fall_end; // convenience
white_rise_end = white_rise_start + white_rise_duration;
white_peak_end = white_rise_end + white_peak_duration;
white_fall_end = white_peak_end + white_fall_duration;
white_duration = white_fall_end - white_rise_start;
last_blue_level = 0;
last_white_level = 0;
cloud_shade = 0;
cloud_start = 0;
cloud_middle = 0;
cloud_end = 0;
cloud_max_shade = min(cloud_max_shade, white_max_level);
}
void loop()
{
now = millis();
if(now < blue_rise_duration)
{
blue_level = blue_max_level * (1.0 - (((float)blue_rise_duration - (float)now) / (float)blue_rise_duration));
}
else if(now < blue_peak_end)
{
blue_level = blue_max_level;
}
else if(now < blue_fall_end)
{
blue_level = blue_max_level * (float)(((float)blue_fall_end - (float)now) / (float)blue_fall_duration);
}
else
{
blue_level = 0;
}
if((now < white_rise_start) || (now > white_fall_end))
{
white_level = 0;
}
else if(now < white_rise_end)
{
white_level = white_max_level * (1.0 - (float)(((float)white_rise_duration - ((float)now - (float)white_rise_start)) / (float)white_rise_duration));
}
else if(now < white_peak_end)
{
if(clouds)
{
if((now > cloud_start) && (now < cloud_middle))
{
white_level = white_max_level - ((float)cloud_shade * (1.0 - ((float)(cloud_middle - now) / (float)(cloud_middle - cloud_start))));
}
else if((now > cloud_middle) && (now < cloud_end))
{
white_level = white_max_level - ((float)cloud_shade * ((float)(cloud_end - now) / (float)(cloud_end - cloud_middle)));
}
else if(now > cloud_end)
{
cloud_start = now + max(cloud_min_between, ((float)cloud_max_between * (float)((float)random(1, 100000) / 100000.0)));
cloud_end = cloud_start + max(cloud_min_duration, ((float)cloud_max_duration * (float)((float)random(1, 100000) / 100000.0)));
cloud_middle = cloud_start + ((cloud_end - cloud_start) / 2);
cloud_shade = random(1, cloud_max_shade);
}
}
else
{
white_level = white_max_level;
}
}
else if(now < white_fall_end)
{
white_level = white_max_level * (float)(((float)white_fall_duration - ((float)now - (float)white_peak_end)) / (float)white_peak_duration);
}
if(blue_level != last_blue_level)
{
pwmWrite(BLUES_PIN, blue_level);
last_blue_level = blue_level;
}
if(white_level != last_white_level)
{
pwmWrite(WHITES_PIN, white_level);
last_white_level = white_level;
}
#ifdef DEBUG
Serial.print("B"); Serial.println(blue_level);
Serial.print("W"); Serial.println(white_level);
#endif
}