Program flashing output on power up

I have a program that creates 7 output pulses, in sequence, during every interrupt.

My issue is the outputs (PortD 1,2,3,4,5,6,7) come on full during powerup causing the LED's to come on bright for a second or 2. After which everything works as expected (duty cycle is about 1% so the LEDs are relatively dim.

Int he 4th line in setup() I think I'm setting all PORTD pins to 0 am I incorrect? If this does set all PortD pins to 0 then what might be setting them to 1's?

Thanks
John

Note; as to why I'm manipulating registers. I didn't know how to setup timer1 with Arduino macros and I just kept on with registers.

/*
- control 7 strips (one on each step) independently
- Frequency approx 237 Hz
- Strips are only on one at a time.

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 0x2100 //259.7  for 16Mhz 
#define interPulseDelay 50   // µs
#define minOnTime 10
#define maxOnTime 500   // at 300 OnTime the unused portion of the cycle is 12µs.

uint16_t OnTime = 1;

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

    cli();      //stop interrupts
    DDRB = 0b00111100; // set PORTB (digital ???) to outputs
    DDRD = 0b11111110; // set PORTD (digital 7~0) to outputs
    PORTD = 0;

  //set timer1 interrupt parameters:
        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 to keep power low in applications with 24V input (as regulator is linear)
    //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)

// Read pot - define OnTime

    // Read A0 - one time  -   accept default conversion clock
    ADMUX = _BV(REFS0);// | _BV(MUX0);      // 5V ref and MUX0 = A1 input.....
    ADCSRA = _BV(ADEN) |_BV(ADSC) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);  // divide by 128
    delayMicroseconds(500);     // must be > 410 else we read 0 because the conversion is still being performed
    uint16_t PotValue = (ADCL | ADCH<<8);

    if (PotValue < 99) {
        OnTime = minOnTime;
    }
    else if (PotValue > 901){
        OnTime = maxOnTime;  // test and change this to the Max possible with ckt.
    }
    else OnTime = map(PotValue, 100, 900, minOnTime, maxOnTime);

    ADCSRA = 0;                 // turn off the ADC converter
    power_adc_disable();        // disable ADC converter (need the above and this line to fully disable the ADC)

    sei();      //allow interrupts 

}   //end setup
    

// ---------------------------------------------------------------------------------
ISR(TIMER1_COMPA_vect){     //timer1 interrupt
    asm ("sbi %0, %1 \n": : "I" (_SFR_IO_ADDR(PINB)), "I" (PINB3)); // Toggle Board Pin 12
    
    for (int i =1; i < 8; i++){
        PORTD |= (1 << i);
        delayMicroseconds(OnTime);
        PORTD = 0x00;
        delayMicroseconds(interPulseDelay);
    }
}

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

// -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
// --- eof ---

Try placing this as the very first instruction in your setup (). Yes, before setting the port direction.

1 Like

Are we talking about Atmega328?

There is a simple solution for that, you need to add a resistor to each port. Assuming a high is on, you use a pull down resistor, maybe 10K, the value is not critical. That keeps the output off until you get through setup() and get them initialized.

Yes. A Pro mini 16 MHz

The ISR presumably, since you did not clear any pending TIMER1 interrupt bits in setup().

See the TIFR1 register description in the data sheet. Write 1 to the bit to clear it.

Incidentally, using any sort of delay in an ISR is regarded as a Bad Idea. The millisecond delay() is entirely ignored when the interrupts are off on AVR-based Arduinos, but on other MCUs, it will hang or crash the processor. Likewise with serial I/O.

I'll change the TIFR1 register initialization, mostly because its good form. Unfortunately it isn't the cause of my current issue.

I measured the signal on startup. It goes high about 60 ms after power comes on. The power has a clean startup (no ramp). The output of the µP is driven high for 1.5 seconds before the pulses start. I say driven because a 4k from the output pin to ground makes no measurable difference.

I'll have to start removing parts of the program and see where it happens.

I understand, in a typical program you are absolute correct. However in this program, there is no code in the loop() (aka main). And I've disabled the milli's timer.

I've written a program using a similar approach for an earlier application. That one has been running 24/7 for about 3 years. The only time it gets a rest is if we loose power.

Unfortunately this did not make a difference. But thanks for the suggestion though, I'll keep it in mind for further down the road.

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