Google RGB LED MR16 and you'll see you can pick these up for very reasonable price. But what can you do with them?As part of a larger home automation project, with a lot of web research and a little soldering I was able to integrate it with my digiSpark pretty easily.
First, I purchased this lamp with an IR remote.
While the remote is junk and doesn't work for home automation, the lamp and lense where great quality. So the first thing I did was hooking it to a 12v battery.
Then of course, I took it apart :)Inside, it looks like this...
The poka-dot white thing in the middle is the RGB LED. The black "storm trooper" thing in the upper right is the IR sensor. The IC that controls the LED is in the lower right under the metal capacitor.
I first wondered how I would command this. Would I tap into the RGB itself or hack the signal? Directly driving the RGB is compelling, I can give any color, brightness or pattern I want, but it would take finding all three transistors base and driving them correctly and at least three pins. That would be "messy".
Immediately the direction I took was to spoof the IR signal. I found this invaluable Instructable post.
Reverse Engineering: RGB LED Bulb with IR remote

But this wasn't enough. The author "Chr", setup and drove the internal PWM to do the carrier wave, but effectively "bit-banged" the signal by turning the PWM (carrier) on/off. Well, I removed the IR sensor (which filters the carrier) and drove P5 directly to the IR sense line using his bit-bang.
Oddly enough, it started doing something, but not what it was supposed to. So I hacked and fiddled and right about when I was about to build a scope, I realized his diagrams show the signal lines inverted. So I flipped the "high" and "lows" and pow! it worked!
Here's the code that directly drives P5 (I borrowed from Chr's code heavily, all of my success is his). I did some basic cleanup, I also translated his "picture of a spreadsheet of commands" into a helpful command array with comments.
int pin = 5;
#define LEAD_MS 550
#define ZERO_MS 550
#define ONE_MS 1620
#define INIT_HIGH_MS 8800
#define INIT_LOW_MS 4200
unsigned char _ctCommands = 24;
unsigned char _commands[] = {
0x08, // pale blue
0x10, // green
0x18, // aqua
0x20, // dimmer
0x28, // light blue
0x30, // light green
0x48, // violet
0x50, // blue
0x58, // purple
0x60, // off
0x68, // deep purple
0x70, // dark blue
0x88, // yellow
0x90, // red
0x98, // peach
0xA0, // brighter
0xA8, // salmon
0xB0, // orange
0xC8, // smooth
0xD0, // white
0xD8, // fade
0xE0, // on
0xE8, // strobe
0xF0}; // flash
void setup()
{
pinMode(pin, OUTPUT);
Serial.begin(9600);
Serial.println("start");
}
unsigned char idx = 0;
void loop()
{
digitalWrite(pin, HIGH);
unsigned char i;
send_command(_commands[idx]);
for (i=0;i<200;i++)
{
delayMicroseconds(2000);
}
idx++;
if (idx > _ctCommands)
idx = 0;
}
void send_command(unsigned char data)
{
unsigned char i;
command_init();
unsigned char address = 0x00;
send_ir_byte(address);
send_ir_byte(address ^ 0xff);
send_ir_byte(data);
send_ir_byte(data ^ 0xff);
send_bit(LEAD_MS, ZERO_MS); // stop-bit
}
int delays[] = {
ZERO_MS, ONE_MS}; // hi-low
void send_ir_byte(unsigned char data)
{
unsigned char i;
for (i=0;i<8;i++) // MSB first
{
if ((data<<i) & 0x80)
{
send_bit_high();
}
else
{
send_bit_low();
}
}
}
void send_bit_high()
{
send_bit(LEAD_MS, ONE_MS);
}
void send_bit_low()
{
send_bit(LEAD_MS, ZERO_MS);
}
void send_bit(int highMs, int lowMs)
{
// 1.65ms
digitalWrite(pin, LOW);
delayMicroseconds(highMs);
digitalWrite(pin, HIGH);
delayMicroseconds(lowMs);
}
void command_init()
{
send_bit(INIT_HIGH_MS, INIT_LOW_MS);
}
This used just one pin, so I have plenty of pins left to integrate the NRF24L01+
No comments:
Post a Comment