// simplest possible sketch, using only loops and IO, no PWM hardware or libraries.
// copy and paste this into a new Arduino sketch, modify the indicated parameters and upload.
// (v2 some corrections and comment mods)
#define LED_PIN A0 // which pin is the LED on
// CHANGE THIS ^^ FOR DIFFERENT PIN
#define LED_GAMMA 4.4 // gamma correct the brightness curve
// CHANGE THIS ^^^ FOR DIFFERENT BREATH CURVE
// larger values make it "pop" more at the end
#define LED_OFF_STATE LOW // in theory the arduino can sink more current than it can source,
#define LED_ON_STATE HIGH // so swap these if you're wiring the other side of the LED to VCC rather than GND
#define PWM_MIN 0 // LED brightness minimum (0..255)
#define PWM_MAX 255 // LED brightness maximum (0..255)
// there is no need to use a series resistor for the LED as long as you manage the maximum on time. PWM is More efficient
#define DELTA_RATE 0.001 // LED brightness change per delta step (rate of change)
// CHANGE THIS ^^^ TO TUNE RATE
#define DELTA_LOOPS 2 // how long to spend in the PWM loop per delta step (major divider)
// the rate of the "breathing" is going to be a slightly complication multiplication of
// the processor clock speed, some overheads, and the DELTA_RATE divided by DELTA_LOOPS
//
// Code is written so the MIN and MAX values can be tweaked later without altering timings.
// There is also potential for "gamma correction" if the log brightness curve isn't sophisticated
// enough
//
// update: Changing the DELTA_RATE is now the best way to fine-tune the breathing rate.
// It scales better and with finer control than the LOOPS, since it's a floating point number.
void setup() {
Serial.begin(57600); // needed on some boards
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LED_OFF_STATE);
}
int direction_up = true;
float linear = 0.0;
void loop() {
// update our linear value
if(direction_up) {
// going up
if( (linear += DELTA_RATE) >= 1.0 ) {
// we hit max
linear = 1.0; direction_up = false;
}
} else {
// going down
if( (linear -= DELTA_RATE) <= 0.0 ) {
// we hit max
linear = 0.0; direction_up = true;
}
}
// turn the linear value into an absolute PWM brightness via the gamma curve
float gamma = pow(linear, LED_GAMMA);
gamma = gamma * (float)(PWM_MAX - PWM_MIN) + (float)PWM_MIN;
int pwm = gamma;
//Serial.println(pwm);
// if we have PWM hardware available, this next bit would be just a call to set it's value and a wait(),
// but we're not going to assume any is available on the pin you want, so we just use raw loops to do
// rough-and-ready PWM to the LED for a few turns.
for(int j = DELTA_LOOPS; j>0; j--) {
int i;
// spend some time on
for(i = pwm; i>0; i--) {
digitalWrite(LED_PIN, LED_ON_STATE);
}
// spend some time off
for(i = (256-pwm); i>0; i--) {
digitalWrite(LED_PIN, LED_OFF_STATE);
}
}
}