Tuesday, January 29, 2013

Bit Angle Modulation using Arduino

So I always wanted to replace my fluorescent lighting with RGB LED strips for those friday night parties because that would make waking up a bit more pleasant. You can wake up to some light instead of jarring noise... (Right now I use my computer to play some Pandora Radio dubstep at 7:20 am, but I digress.)

Anyway, I want my lighting to follow f.lux's principles, too (f.lux. Highly recommend this): nice, cool blue in the morning/afternoon, and a warm white in the night.

So yeah, color temperatures to RGB. BUT HAO 2 GET VALUES?
Don't worry, hex codes here.

Now, all I need are the actual RGB strips, and some CODE to use with a MICROCONTROLLER.
And some MOSFETs... and a 12v power supply... 
Oh, and RF links, since I want to use multiple strips in my room.
And some way to connect the microcontroller to my router, since I want to be able to change my lighting through a website.
Don't steal mah idea D:< .. actually I encourage you to do it! Send me a link if you do!

But before I buy hundreds of dollars worth of RGB LED strips, I've decided to make the code.

I was planning to use some Attiny85s, and those only have 2 PWM outputs. HOW 2 GET 3?
Well that's where software comes in. But software PWM takes a toll on the microprocessor.

Solution? Use bit angle modulation.
This thread explains it very nicely.

Or this picture. Either works I suppose.

So yeah, pretty much like that.

Next, I'll try to figure out how to make a function for this that supports multiple outputs, making them ride on the same modulation.
Also maybe I could make the microcontroller calculate stuff during Bit 7 using millis(), reducing overhead.

I'm not 100% sure if the Attiny85 will work, but WHATEVER. I have a couple of Attiny44s. :D

No extra hardware needed if you're using Arduino Uno or something.

Henry Choi
BAM LED dimmin'

Moar Info:

const int R_pin = 13;
const int period = 10;    //in microseconds - 20 is a 195.3125Hz period

//***Starting Stuffs*** 

//unsigned long time;
byte R_brightness = 0;

void setup() {

  pinMode(R_pin, OUTPUT);


void loop() {

  R_brightness = (pow(2, cos(millis() / 500.) ) - 0.5) *  (255) / (2 - 0.5);

  //a cosine function for fading (shamelessly stolen from my PSU project)
  //exponential to compensate for LED logarithmic brightness

  for (int multiplier = 0; multiplier <= 7; multiplier++) {
    if (R_brightness & 1 << multiplier)

      // Here, I use '<<' so that the bitwise operator '&' can be used. I use '&' as a mask.
      digitalWrite(R_pin, HIGH);
    delayMicroseconds(period << multiplier);
    // '<<' simply means to multiply by 2^[whatever on the right side]
    digitalWrite(R_pin, LOW);

/* If you want to do that mirroring thing that's addressed in the forums linked above, uncomment this part. Although, I personally don't see the blinking...
  for (int multiplier = 7; multiplier >= 0; multiplier--) {
    if (R_brightness & 1 << multiplier)

      digitalWrite(R_pin, HIGH);
    delayMicroseconds(period << multiplier);
    digitalWrite(R_pin, LOW);

Oh internet you so smart.

No comments:

Post a Comment