Here's a simple way to drive a RGB LED with Arduino Uno. The microcontroller generates a multiplexed PWM signal in software. The PWM is generated in an interrupt routine so the main program and LED update frequency are completely independent. The only requirements is that main program does not use hardware timer 1.
Components required: one common cathode RGB LED, one 330 ohm resistor.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Multiplexed PWM RGB Led Demo | |
// By Petri Hakkinen | |
// 24th November 2014 | |
// | |
// Arduino Uno driving a single RGB led with only one resistor. | |
// | |
// Make the following connections: | |
// * Connect Arduino pins D2,D3,D3 to anodes of a RGB led. | |
// * Connect cathode of the RGB led to 330 ohm resistor. | |
// * Connect the other end of the resistor to ground. | |
// | |
// A multiplexed PWM signal is generated by a timer interrupt routine. | |
// | |
// Uses TimerOne library, download from here: | |
// http://playground.arduino.cc/Code/Timer1 | |
#include <TimerOne.h> | |
volatile uint8_t color[3]; // R,G,B led intensities in range [0,255] | |
volatile uint8_t phase = 0; // phase of the PWM signal, counts from 0 to 255 | |
volatile uint8_t led = 0; // which led to update, counts from 0 to 2 | |
// Look up table of sin values for mega demo effect. | |
uint8_t sintab[64]; | |
// The interrupt routine that updates the states of leds. | |
void interruptRoutine() | |
{ | |
// turn all leds off | |
PORTD &= B11100011; | |
// sample pwm and turn on one led | |
if(phase < color[led]) | |
PORTD |= 1<<(led+2); | |
led = (led + 1) & 3; | |
phase++; | |
} | |
void setup() | |
{ | |
pinMode(2, OUTPUT); | |
pinMode(3, OUTPUT); | |
pinMode(4, OUTPUT); | |
// attach interrupt routine | |
Timer1.initialize(50); | |
Timer1.attachInterrupt(interruptRoutine); | |
// init sin table for mega demo effect | |
for(uint8_t i = 0; i < 64; i++) | |
sintab[i] = (uint8_t)(sin(i * M_PI * 2 / 64) * 127.0f + 128.0f); | |
} | |
void loop() | |
{ | |
const uint8_t speed = 13; | |
color[0] = 0; | |
color[1] = 0; | |
color[2] = 0; | |
// fade red | |
for(int i = 0; i < 256; i++) { | |
color[0] = i; | |
delay(speed); | |
} | |
// fade green | |
for(int i = 0; i < 256; i++) { | |
color[1] = i; | |
delay(speed); | |
} | |
// fade blue | |
for(int i = 0; i < 256; i++) { | |
color[2] = i; | |
delay(speed); | |
} | |
// mega demo effect | |
for(int i = 0; i < 500; i++) { | |
color[0] = sintab[i & 63]; | |
color[1] = sintab[(i*2 + 123) & 63]; | |
color[2] = sintab[(i*2/3 + 35) & 63]; | |
delay(speed); | |
} | |
} |
No comments:
Post a Comment