LED Sequencer and an apparent timing issue (delays appear to solve the problem)
all-
so i'm working on led sequencer firmware lilypad clone on-board tlc5940. idea user creates "banks" of 1 (or more) leds , interval each bank. @ desired time, bank turn on (or off) needed.
these banks have been defined in eeprom (this stripped-down version of code; actual software supports "program mode" allow user configure eeprom serially via visual basic .net program) , read in @ run-time.
i setup pattern defined 6 banks of 2 leds, each firing @ 1/2, 1, 2, 4, 8, , 16 seconds (a 6bit binary counter). interval defined in 1/10 seconds, max of 9999 (16 minutes , change).
the problem: first bank turns on, doesn't turn off after 1/2 second. blinks 1/2 second every 10 seconds or (if that). other 5 banks work fine.
the (apparent) solution: added debugging statements figure out why didn't work , guess - problem disappeared!
finally messed around various combinations discover "delay(2)" in addevent method seems easiest , solution less impact (adding debugging code throws off animation).
so uncommenting define effin_buggy_code or debug_check cause problem disappear.
also if change delay @ bottom of loop() 25 millis or more problem doesn't appear either (but animation isn't smooth).
basically adding sufficient debug code see going on causes problem disappear.
so i'm assuming sort of timing issue buggy code, hence reason post.
first up, main program
here included "events" class.
ideas? things can better? far, thing i've thought of improve code's speed keep current led state in event structure (since i'm sure it's faster pull out boolean , flip query tlc5940 on spi).
thanks in advance,
brad (kf7fer)
ps oh yeah, i've tried faster animations (1/10, 1/5, 2/5, 4/5, 1.6, , 3.2 seconds) slower (1,2, 4, 8, 16, , 32 seconds) , problem persists.
so i'm working on led sequencer firmware lilypad clone on-board tlc5940. idea user creates "banks" of 1 (or more) leds , interval each bank. @ desired time, bank turn on (or off) needed.
these banks have been defined in eeprom (this stripped-down version of code; actual software supports "program mode" allow user configure eeprom serially via visual basic .net program) , read in @ run-time.
i setup pattern defined 6 banks of 2 leds, each firing @ 1/2, 1, 2, 4, 8, , 16 seconds (a 6bit binary counter). interval defined in 1/10 seconds, max of 9999 (16 minutes , change).
the problem: first bank turns on, doesn't turn off after 1/2 second. blinks 1/2 second every 10 seconds or (if that). other 5 banks work fine.
the (apparent) solution: added debugging statements figure out why didn't work , guess - problem disappeared!
finally messed around various combinations discover "delay(2)" in addevent method seems easiest , solution less impact (adding debugging code throws off animation).
so uncommenting define effin_buggy_code or debug_check cause problem disappear.
also if change delay @ bottom of loop() 25 millis or more problem doesn't appear either (but animation isn't smooth).
basically adding sufficient debug code see going on causes problem disappear.
so i'm assuming sort of timing issue buggy code, hence reason post.
first up, main program
code: [select]
// simple led sequencer code
#include "events.h"
#include <tlc5940.h>
#include <eeprom.h>
#define max_brightness 40 // max led brightness
#define eeprom_base 100 // start of bank data
#define size_of_eeprom 4 // size of bank data in eeprom
events sequencelist; // event queue
void setup() {
int bankoffset = 0;
serial.begin(9600);
sequencelist.init(); // initialize event list
// fetch data eeprom. start w/ number of banks
int numberbanks = eeprom.read(eeprom_base);
// each bank, pull sequence info
(int indx=0; indx < numberbanks; indx++) {
// pull data each bank eeprom
// first determine offset eeprom
int spot = eeprom_base + 1 + (size_of_eeprom * indx);
int bankno = eeprom.read(spot);
int numberleds = eeprom.read(spot + 1);
// handle interval bit differently since it's integer
int interval = eeprom.read(spot + 2) << 8; // high byte
interval += eeprom.read(spot + 3); // low byte
// add these entries event list , let's go!
sequencelist.addevent( interval, bankno, bankoffset, numberleds );
// adjust bank offset
bankoffset += numberleds;
}
// initialize tlc5940 , turn channels off
tlc.init(0);
}
// main program loop
void loop() {
// pretty idle here waiting next event expire. toggle
// led state, delete event, , re-add new eventtime.
if (sequencelist.checkevent()) {
// timer expired! extract details
int banknumber = sequencelist.getbanknumber();
int bankoffset = sequencelist.getbankoffset();
int interval = sequencelist.getinterval();
int numberleds = sequencelist.getnumberleds();
boolean lights = false;
// delete , re-add event can keep things on schedule
sequencelist.deleteevent();
sequencelist.addevent(interval, banknumber, bankoffset, numberleds);
// check first led in bank see if need turn off or on
if (tlc.get(bankoffset) == 0)
lights = true;
// update bank needed
(int indx = bankoffset; indx < (bankoffset + numberleds); indx++) {
if (lights)
tlc.set(indx, max_brightness);
else
tlc.set(indx, 0);
}
// update display
tlc.update();
}
else {
// let's kill time here
delay(2);
}
}here included "events" class.
code: [select]
// events
// simple event handler led sequencer
#include <wprogram.h>
// total number of events possible
#define max_events 16
class events {
private:
// event structure
typedef struct {
unsigned long eventtime; // event deadline
int interval; // actual event time period
int banknumber; // bank number
int bankoffset; // bank offset (0-16)
int numberleds; // total number of leds in bank
} event;
event eventlist[max_events]; // current event list
int numberevents; // number events in list
public:
void init(void); // initialize object
// add event list
boolean addevent(int interval,
int banknumber,
int bankoffset,
int numberleds);
// check see if current event has expired
boolean checkevent(void);
// fetch event details
int getinterval(void) { return eventlist[0].interval;}
int getbanknumber(void) { return eventlist[0].banknumber;}
int getbankoffset(void) { return eventlist[0].bankoffset;}
int getnumberleds(void) { return eventlist[0].numberleds;}
// how many events in queue?
int getnumberevents(void) { return numberevents;}
// delete current event
boolean deleteevent(void);
void dumpevents(void);
};
//
// class implementation follows
//
// initialize object
void events::init(void) {
numberevents = 0;
}
// add event queue (ok, it's array). note insert items
// in chronological order of expiration
boolean events::addevent(int interval, int banknumber, int bankoffset, int numberleds) {
int indx = 0;
boolean found = false;
boolean done = false;
unsigned long eventtime = millis() + (unsigned long)interval * 100ul;
// make sure there room @ inn
if (numberevents == max_events)
return false;
#define effin_buggy_code 1
#ifdef effin_buggy_code
// can't figure out how make work consistently without small delay
// here.
delay(2);
#endif
// locate position in array
(indx = 0; (indx < numberevents) && !found; indx++) {
found = (eventtime < eventlist[indx].eventtime);
}
if (found) {
// found spot in array. move existing events 1 spot
// first adjust indx (since off one)
indx--;
// move items 1 leave spot
(int spot=numberevents; spot > indx; spot--) {
eventlist[spot] = eventlist[spot - 1];
}
// insert new event
eventlist[indx].interval = interval;
eventlist[indx].eventtime = eventtime;
eventlist[indx].banknumber = banknumber;
eventlist[indx].bankoffset = bankoffset;
eventlist[indx].numberleds = numberleds;
}
else {
// didn't find it. add end of list
eventlist[numberevents].interval = interval;
eventlist[numberevents].eventtime = eventtime;
eventlist[numberevents].banknumber = banknumber;
eventlist[numberevents].bankoffset = bankoffset;
eventlist[numberevents].numberleds = numberleds;
}
// bump event counter
numberevents++;
return true;
}
// check see if current event has expired
boolean events::checkevent(void) {
if (numberevents == 0)
return false;
//#define debug_check 1
#ifdef debug_check
if (millis() >= eventlist[0].eventtime) {
if (eventlist[0].banknumber == 1) {
serial.print("expired @ ");
serial.println(millis());
}
}
#endif
return (millis() >= eventlist[0].eventtime);
}
// delete current event
boolean events::deleteevent(void) {
// make sure list populated
if (numberevents == 0)
return false;
// if there 1 done here
if (--numberevents == 0)
return true;
// move rest down bit
(int indx=1; indx <= numberevents; indx++) {
eventlist[indx - 1] = eventlist[indx];
}
return true;
}ideas? things can better? far, thing i've thought of improve code's speed keep current led state in event structure (since i'm sure it's faster pull out boolean , flip query tlc5940 on spi).
thanks in advance,
brad (kf7fer)
ps oh yeah, i've tried faster animations (1/10, 1/5, 2/5, 4/5, 1.6, , 3.2 seconds) slower (1,2, 4, 8, 16, , 32 seconds) , problem persists.
i'd suggest of names misleading:
my eeprom larger that. size_of_bank might better name.
spot? how startaddress?
your class should have constructor calls init(), can assured init() gets called.
you deleteevent() method removes last event. don't design. should able remove nth event.
your checkevents() method returns true if event occurred. should return -1 no event, , n nth event.
your other methods assume first event in list event fired.
really, think problem in events class. need know event occurred, can data event. deleting event, , re-adding it, silly. add method reset nth event's eventtime value.
code: [select]
#define size_of_eeprom 4 // size of bank data in eeprommy eeprom larger that. size_of_bank might better name.
code: [select]
int spot = eeprom_base + 1 + (size_of_eeprom * indx);spot? how startaddress?
your class should have constructor calls init(), can assured init() gets called.
you deleteevent() method removes last event. don't design. should able remove nth event.
your checkevents() method returns true if event occurred. should return -1 no event, , n nth event.
your other methods assume first event in list event fired.
really, think problem in events class. need know event occurred, can data event. deleting event, , re-adding it, silly. add method reset nth event's eventtime value.
Arduino Forum > Using Arduino > Programming Questions > LED Sequencer and an apparent timing issue (delays appear to solve the problem)
arduino
Comments
Post a Comment