Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //proper-larson.ino
- // macros for LED state
- #define ON true
- #define OFF false
- #define UP true
- #define DOWN false
- // variables for larson pattern timing
- unsigned long currentMillis = millis();
- unsigned long previousMillis = 0;
- unsigned long millisInterval = 5;
- // LED fading (recommended value)
- int fadeIncrement = 5;
- // tells which LED is the brightest
- // start at the far "right" (or left?)
- int larsonStatus = 0x80;
- // bit mask for maximum scan value
- // picture larsonMax in binary
- // 00001000 00000000
- // if you had 30 LEDs, you'd need an a long...
- int larsonMax = 0x80;
- // arbitrary starting direction
- bool direction = DOWN;
- // variables for software PWM
- // really have to play with pwmMax
- // and microInterval to get a smooth
- // fade effect
- unsigned long currentMicros = micros();
- unsigned long previousMicros = 0;
- unsigned long microInterval = 10;
- // instead of HW PWM's "255" levels, we get 100
- const byte pwmMax = 100;
- // typedef for properties of each sw pwm pin
- typedef struct pwmPins {
- int pin;
- int pwmValue;
- bool pinState;
- int pwmTickCount;
- } pwmPin;
- // create the sw pwm pins
- // these can be any I/O pin
- // that can be set to output!
- const int pinCount = 8;
- //const byte pins[pinCount] = {2,3,5,6,9,10,11,12};
- const byte pins[pinCount] = {2,3,4,5,6,7,8,9};
- // an array of Software PWM Pins
- pwmPin myPWMpins[pinCount];
- void setup() {
- // sets each element of myPWMpins to something
- setupPWMpins();
- }
- void loop() {
- // constantly ping handlePWM()
- handlePWM();
- // typical millis timer code
- // see what time it is.
- currentMillis = millis();
- if (currentMillis - previousMillis >= millisInterval) {
- if (direction == UP) {
- // going "left"
- // need a reference for which LED is the "bright" one
- int index = 0;
- for (index=pinCount; index >= 0; index--) {
- if (bitRead(larsonStatus, index))
- break;
- }
- // index is the bit set to "1"
- // see if we're the last pin
- if (index < (pinCount)) {
- // fade up the LED next to the "on" LED
- myPWMpins[index+1].pwmValue += fadeIncrement;
- // check if the fading LED is fully on yet
- if (myPWMpins[index+1].pwmValue >= pwmMax) {
- // okay, time to move to the next one!
- // "barrel shift" the "1", one bit over
- larsonStatus = larsonStatus << 1;
- // start fading the previous on
- myPWMpins[index].pwmValue = myPWMpins[index].pwmValue - fadeIncrement;
- // did we hit the end yet?
- if (larsonStatus == (larsonMax << 1)) {
- // okay, time to change direction
- larsonStatus = larsonMax;
- direction = DOWN;
- }
- }
- }
- // create the tails.
- createFadeTail((index-1),4,15);
- createFadeTail((index-2),2,5);
- createFadeTail((index-3),1,1);
- } else {
- // going right
- int index = 0;
- // need a reference for which LED is the "bright" one
- for (index=0; index < pinCount; index++) {
- if (bitRead(larsonStatus, index))
- break;
- }
- // index is the bit set to "1"
- if (index > 0) {
- // fade up the LED next to the "on" LED
- myPWMpins[index-1].pwmValue += fadeIncrement;
- if (myPWMpins[index-1].pwmValue >= pwmMax) {
- larsonStatus = larsonStatus >> 1;
- // start fading the previous on
- myPWMpins[index].pwmValue = myPWMpins[index].pwmValue - fadeIncrement;
- // didn't use a const here, because, it is probably 0
- if ((larsonStatus == 0x01)) {
- direction = UP;
- }
- }
- // very similar to opposite direction
- // except we are modifying pins "after" bright one
- createFadeTail((index+1),4,15);
- createFadeTail((index+2),2,5);
- createFadeTail((index+3),1,1);
- }
- }
- // setup clock for next tick
- previousMillis = currentMillis;
- }
- }
- void createFadeTail(int pinIndex, int fadeMultiplier, int pwmLimit) {
- // make sure we aren't modifying past the end of myPWMpins or pins array
- if ((pinIndex) < pinCount) {
- // change pwmValue to make our fade effect
- myPWMpins[pinIndex].pwmValue = myPWMpins[pinIndex].pwmValue - fadeIncrement*fadeMultiplier;
- // make sure the number doesn't go negative
- if (myPWMpins[pinIndex].pwmValue <= fadeIncrement)
- // limit the lowest brightness
- // found this looks better with "1-5" instead of 0
- myPWMpins[pinIndex].pwmValue = pwmLimit;
- }
- handlePWM();
- }
- void handlePWM() {
- currentMicros = micros();
- // check to see if we need to increment our PWM counters yet
- if (currentMicros - previousMicros >= microInterval) {
- // Increment each pin's counter
- for (int index=0; index < pinCount; index++) {
- // each pin has its own tickCounter
- myPWMpins[index].pwmTickCount++;
- // determine if we're counting on or off time
- if (myPWMpins[index].pinState == ON) {
- // see if we hit the desired on percentage
- // not as precise as 255 or 1024, but easier to do math
- if (myPWMpins[index].pwmTickCount >= myPWMpins[index].pwmValue) {
- myPWMpins[index].pinState = OFF;
- }
- } else {
- // if it isn't on, it is off
- if (myPWMpins[index].pwmTickCount >= pwmMax) {
- myPWMpins[index].pinState = ON;
- myPWMpins[index].pwmTickCount = 0;
- }
- }
- // for the LEDs on or off, for min and max values
- // similar to how Arduino library does PWM
- if (myPWMpins[index].pwmValue == pwmMax)
- myPWMpins[index].pinState = ON;
- if (myPWMpins[index].pwmValue == 0)
- myPWMpins[index].pinState = OFF;
- // could probably use some bitwise optimization here, digitalWrite()
- // really slows things down after 10 pins.
- digitalWrite(myPWMpins[index].pin, myPWMpins[index].pinState);
- }
- // reset the micros() tick counter.
- previousMicros = currentMicros;
- }
- }
- // function to "setup" the sw pwm pin states
- // modify to suit your needs
- void setupPWMpins() {
- for (int index=0; index < pinCount; index++) {
- // connect a myPWMpin to an actual pin
- myPWMpins[index].pin = pins[index];
- // start with all LEDs off
- myPWMpins[index].pwmValue = 0;
- // doesn't matter ON or OFF
- myPWMpins[index].pinState = ON;
- // set the counter to 0
- myPWMpins[index].pwmTickCount = 0;
- // make sure pin is set correctly
- pinMode(pins[index], OUTPUT);
- }
- // start with the "go-right" pattern, so
- // turn on "last" LED full
- myPWMpins[pinCount-1].pwmValue = 100;
- }
- // Code from james@baldengineer.com
- // email | twitter | www
- // See more at: https://www.baldengineer.com/larson
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement