Program with interrupt only, no "loop" code

No questions here, I though it might be useful for someone to look over.

Goal:
LED driver. I have 14 stairs where I am installing LED strips under the step overhang.

  • The LED strips are so bright I have to reduce the dutycycle to < 1%.
  • Don't want to see flicker so the base frequency > 200 Hz.
  • To reduce power supply load I want to power two strips at a time.
  • I want to use timer1 because I like to use the timers when I can.
  • Reduced power of µP needed if run at 24Vdc input. I don't to use a buck converter.

Just an example where everything is performed in a interrupt where normally a good goal it to keep the interrupt as short as possible.

Graphically this is what I want (and this program does):

/*
Front Stairs (livingroom to Foyer)  LED Driver

2022-07-12 v001

- control 7 strips (one on each step) independently (or 14 strips 2 at a time)
- On time is approx 1/2 %
- Frequency approx 230 Hz
- Strips are only on one at a time.
- undecided if one right after another or spread across the period.


Target:
	Arduino Pro Mini 16Mhz 5V
	the 5v output is needed to drive the output MosFet's (logic level)
	Period controlled by Interrupt on timer1
*/

#include <avr/power.h>
#define period 0x0F0A //259.7 
#define OnTime 20                   // OnTime 20 meas 24µs with scope (at LED strip)
#define interPulseDelay 5

// ---------------------------------------------------------------------------------
void setup(){

       cli();      //stop interrupts
       DDRD = 0b11111110; // set PORTD (digital 7~0) to outputs
       PORTD = 0;
       TIMSK0 &= ~_BV(TOIE0); // disable timer0 overflow interrupt
// 
    
  //set timer1 interrupt period (freq)
  	TCCR1A = 0;  // set entire TCCR1A register to 0
  	TCCR1B = 0;  // same for TCCR1B
  	TCNT1  = 0;  //initialize counter value to 0
  // set compare match register
  	OCR1A = period;

    // turn on CTC mode
  	TCCR1B |= (1 << WGM12);

  // Set CS11 for ÷8 prescaler
  	TCCR1B |= (1 << CS11);	// | (1 << CS10);
  
  // enable timer compare interrupt
  	TIMSK1 |= (1 << OCIE1A);

// to save power disable unused functions in µP
    ADCSRA = 0;                 // turn off the ADC converter
    power_adc_disable();        // ADC converter (need the above and this line to fully disable the ADC)
    power_spi_disable();        // SPI
    power_usart0_disable();     // Serial (USART)
    power_timer0_disable();     // Timer 0
    //power_timer1_disable();   // Timer 1
    power_timer2_disable();     // Timer 2
    power_twi_disable();        // TWI (I2C)

	sei();      //enable interrupts
}       //end setup

// ---------------------------------------------------------------------------------
ISR(TIMER1_COMPA_vect){		//timer1 interrupt
     // toggle LED is only used during development to trigger the logic analyzer.
    asm ("sbi %0, %1 \n": : "I" (_SFR_IO_ADDR(PINB)), "I" (PINB5)); // Toggle LED
	
    for (int i =1; i < 8; i++){
        PORTD |= (1 << i);
 	    delayMicroseconds(OnTime);
 	    PORTD = 0x00;
        delayMicroseconds(interPulseDelay);
    }
}

// ---------------------------------------------------------------------------------
void loop(){}

// -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

/*
Output Pins: (Board markings)
Tx
2
3
4
5
6
7
*/


2 Likes

But my wife wants an elevator.

:aerial_tramway:

I never argue with success. But I do prefer to avoid interrupts and timers and just write plain code to do the thing.

In this case it seems like an easy enough process to accomplish with just plain code anyone could figure out without the datasheet and some motivation I will cheerfully admit to having run of some time ago, never mind precisely how long.

So, cool! You do you.

BTW I have enjoyed seeing LEDs get brighter and brighter, more colors too, yeah.

a7

This was exactly why I posted this code, to show interrupts can work without being super short. I'm not throwing down the gauntlet but when I first looked at this requirement I started with "loop" code. However I realized that all could be done in an interrupt since there is no "loop" code to have timing issues with.

I don't think this can be accomplished with 3 lines of working code in a "loop" structure.

I would love an "L" shaped ranch :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.