Blinking LEDS at preset times?

Hi, I don't know much from Arduino programming. I am trying a project from three LEDS, blinking for 2000 m/s each on a pre set time, over a period from 100000 m/s. led1 = ledPin 8 led2 = ledPin 9 led3 = ledPin10 sequence is: led1: low 40000 high 2000 low 20000 high 2000 low 36000 ---- total 100000 m/s led2: low 20000 high 2000 low 20000 high 2000 low 56000 ---- total 100000 m/s led3: low 10000 high 2000 low 15000 high 2000 low 71000 ---- total 100000 m/s All times starting at same time 0 m/s I am trying this because a have a trainset which I want to run with Arduino, comprising of a total of 52 signals and points. I have a Arduino 2560 board, with 54 pins, each point or signal needs a relay, or one pin. Is this possible. If yes could some one give me a sketch code for the three Leds please, than I can probably work the rest out my self. Regards Martinus.

martinus:
Hi, I don’t know much from Arduino programming. I am trying a project from three LEDS, blinking for 2000 m/s each on a pre set time, over a period from 100000 m/s.
led1 = ledPin 8
led2 = ledPin 9
led3 = ledPin10
All times starting at same time 0 m/s
I am trying this because a have a trainset which I want to run with Arduino, comprising of a total of 52 signals and points. I have a Arduino 2560 board, with 54 pins, each point or signal needs a relay, or one pin. Is this possible. If yes could some one give me a sketch code for the three Leds please, than I can probably work the rest out my self. Regards Martinus.

Tell me what grade you get when you turn this in

/*
*  Pin Sequencer V0.1.0
*  Chuck Todd <ctodd@cableone.net>
*/

#define LED1 8
#define LED2 9
#define LED3 10
#define LED4 13
#define LED5 6
#define LEDCount 5 // count of LEDs, Arrays 

// #define DEBUG  // uncomment this line to enable Debug display on Serial Monitor

/* each entry in this list must have Arduino Pin Number in first position,
*       at least one positive or negative value in the sequence, 
*       ending with a zero '0' to mark the end of the sequence
* these PROGMEM arrays exist in Program memory, they do not take up any DATA memory
* they are a little tough to work with, but worth it. because of the RAM savings.
*/
const int16_t L1[] PROGMEM ={LED1,-40,2,-20,2,-36,0}; // negative means Low, count in seconds
const int16_t L2[] PROGMEM ={LED2,-20,2,-20,2,-56,0}; // pattern for each LED
const int16_t L3[] PROGMEM ={LED3,-10,2,-15,2,-71,0}; // zero is end/ repeat again marker
const int16_t L4[] PROGMEM ={LED4,10,-10,5,-2,0};        
const int16_t L5[] PROGMEM ={LED5,1000,-10,0};        // this led will be on for 1,000 second, off for 10

const int16_t* const LTable[] PROGMEM ={L1,L2,L3,L4,L5}; // for each LED create a Ln[] and add it here

/* Each LED pin only consumes 4 bytes of ram, irrespective of how many sequence events is requires
*/
uint16_t L_index[LEDCount][2]; // two elements for each LED
                        // [0] is index for current element
                       // [1] is next trip point in seconds                       

void initIndex(){ // setup the Arduio pins for output, High or Low as controlled by the Ln[] arrays.
#ifdef DEBUG
char ch[50];
#endif
for(uint8_t i = 0;i<LEDCount;i++){
  L_index[i][0] = 1;                              // first entry in sequence
  uint16_t base = pgm_read_word_near(&LTable[i]); // base address for sequence table for this LED
  int16_t pin =pgm_read_word_near(base);          // Actual pin to change
  pinMode(pin,OUTPUT);
  int16_t n = pgm_read_word_near(base+2);         // time in seconds for the first state
                                                  // added 2 because each element is 2 bytes 
  L_index[i][1]=abs(n);                           // duration in seconds for this state  
  if(n<0) digitalWrite(pin,LOW);                  // negative for low
  if(n>0) digitalWrite(pin,HIGH);                 // positive for high
#ifdef DEBUG
  sprintf(ch,"base=%04X LED%d =%d LI[%d][0]=%d LI[%d][1]=%d\n",base,i,pin,i,L_index[i][0],i,L_index[i][1]);
  Serial.print(ch);
#endif
  }
}

uint16_t findNext(){ // returns next expiration second
uint8_t i=0;
uint16_t ns=L_index[i][1];  // pick first expiration
while(i<LEDCount){
  if(ns>L_index[i][1]) ns = L_index[i][1]; // is this one shorter?
  i++;
  }
#ifdef DEBUG
char ch[50];
sprintf(ch," next second =%d\n",ns);
Serial.print(ch);
#endif
return ns;
}

#ifdef DEBUG
void printTables(){
char ch[50];
for(uint8_t i = 0;i<LEDCount; i++){
  uint16_t base = pgm_read_word_near(&LTable[i]);
  sprintf(ch,"base%d=0x%04X ",i,base);
  Serial.print(ch);
  int16_t j;
  uint8_t k=0;
  do{
    j=pgm_read_word_near(base+k*2);
    Serial.print(j,DEC);Serial.print(' ');
    k++;
  }while(j!=0);
  Serial.println();
  }
}
#endif

void lightEmUp(uint16_t tick){
#ifdef DEBUG
char ch[50];
#endif
for(uint8_t i = 0;i<LEDCount;i++){
  uint16_t base =pgm_read_word_near(&LTable[i]);
  while(tick>=L_index[i][1]){
    L_index[i][0] += 1;                                      // next sequence value
    int16_t n = pgm_read_word_near(base+(L_index[i][0]*2));  // time,polarity or stop
                                                             // multipled by 2 because each element is 2 bytes. 
#ifdef DEBUG
    sprintf(ch,"\nbase=%04X LI[%d][0]=%d n=%d",base,i,L_index[i][0],n);
    Serial.print(ch);
#endif
    if(n==0){
      L_index[i][0]=1; // back to start of timing array, skip pin 
      n = pgm_read_word_near(base+(L_index[i][0]*2));
      }
    L_index[i][1] += abs(n);                    // tick value this new status is value for
    int16_t pin = pgm_read_word_near(base);     // actual Arduino pin to change
#ifdef DEBUG
    sprintf(ch," LI[%d][1]=%d n=%d pin=%d ",i,L_index[i][1],n,pin);
    Serial.print(ch);
#endif
    if(n<0){
      digitalWrite(pin,LOW);
#ifdef DEBUG
      Serial.print("L ");
#endif
      }
    if(n>0){
      digitalWrite(pin,HIGH);
#ifdef DEBUG
      Serial.print("H ");
#endif
      }
    }
  if(tick<L_index[i][1])
    L_index[i][1] -= tick;
  }
}

static uint16_t nextSec;           // how many seconds until the next change event
static unsigned long startTime=0;  // millisecond counter, continually adjusted after each event.

void setup(){
Serial.begin(19200);  //debug console
#ifdef DEBUG
printTables();    // just to verify I can access the PROGMEM correctly
#endif
startTime=millis();
initIndex();            // Set up the pins, Set their initial state, duration
nextSec = findNext();   // when the next change happens
}

void loop(){
unsigned long t=millis();
if((t-startTime)>=((unsigned long)nextSec*1000L)){ // is it time yet?
  uint16_t tick = (t-startTime)/1000;  //number of seconds since last event.
#ifdef DEBUG
  Serial.print("\n+");Serial.print(tick,DEC);Serial.print(' ');
#endif
  startTime += (unsigned long)tick*1000; // adjust startime to last event 
  lightEmUp(tick);                       // actuall change the pins, net the next event countdown timers
  nextSec=findNext();                    // when is the next event scheduled?
  }
}

Chuck.

If the times are in seconds, why are you giving it in milliseconds? It makes it less understandable when used in a specification of your requirements.

Weedpharma

Hello Chuck, thank you very much for you help, I got it working. Regards Martinus van Walsum.