5
\$\begingroup\$

Project

I'm not very experienced with electronics and microcontroller-programming yet. I recently (accidentally) bought a couple of ATTiny13A microcontrollers, assuming I could program them using the Arduino IDE.

Because of the small amount of memory on these things, I decided to make a simple project: a reading light that automatically switches off. And I decided to use AVR Studio (6.0) instead of the Arduino IDE.

The circuit is quite simple I think. Two buttons to add half an hour of light, and another one to switch off the lights immediately. Everything is powered by a USB wall wart, supplying around 5V (5.2, I measured).

I simplified the led. In fact there are 2 leds (I planned on 3 at first) and the appropriate resistors, which is also why I added the resistor. I also left out the connections to the AVR programmer, since they are not relevant to the circuit itself.

schematic

simulate this circuit – Schematic created using CircuitLab

The light works as it is supposed to. It burns for 3 seconds when I plug it in. I can turn it on and off. And when I turn it on, it burns for about half an hour before switching off by itself. If I know beforehand that I want to have more than half an hour of light, I can press the button multiple times, to get N times half an hour.

So far so good.

Problem: undesired resets

Now the problem is, it seems to be quite sensitive to peaks or drops. I got a wall wart with two connections. When the night light is plugged in in one of them, and I plug my phone into the other, the night light resets, burning for three seconds and then switching off. This also happens most of the time when I unplug the phone. It doesn't matter whether the light was switched on or off when I do.

So my main question is, how do I solve these resets? I'm open to other advice as well.

I'll paste the program here for reference as well. I think it's not relevant, but I tried to use interrupts and have the controller in sleep mode most of the time, so I'll post it anyway, just in case it contains vital information.

/*
 * NachtLampje.c
 *
 * Created: 22-10-2014 19:46:50
 *  Author: GolezTrol
 */ 

#define F_CPU 1200000UL // Sets up the default speed for delay.h 

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

volatile int seconds = 3;
int secondsInc = 1800;

void setupLed() {
    DDRB = 1<<DDB0;
}

void updateLed() {
    // Blink for a moment when we're at 15 seconds, so user might prolong.
    if (seconds > 0 && seconds != 15)
        PORTB |= 1<<PB0;
    else
        PORTB &= ~(1<<PB0);
}

void setTimer(int state) {
    if (state) {
        WDTCR |= (1<<WDP2) | (1<<WDP1); // 1sec
        WDTCR |= (1<<WDTIE); // Enable watchdog timer interrupts
    }       
    else {
        WDTCR &= ~(1<<WDTIE); // Disable watchdog timer interrupts
    }   
}

ISR(WDT_vect) {
    // Timer interrupt
    if (seconds == 0) 
      return;

    if (--seconds == 0) {
        setTimer(0);
    }   
    updateLed();
}

ISR(PCINT0_vect){
    // Button interrupt

    // Button 1 = PB3 = Add half an hour of light.
    if (~PINB & 0x08) {
        seconds += secondsInc;
    }

    // Button 2 = PB 4 = Turn off the lights
    if (~PINB & 0x10) {
        seconds = 0;
    }

    // Enable timer, if necessary
    setTimer(seconds > 0);

    // Update the led.
    updateLed();
}

int main(void) {
    setupLed();

    updateLed();

    setTimer(seconds > 0);

    GIMSK = 0b00100000;    // turns on pin change interrupts
    PCMSK = 0b00011000;    // turn on interrupts on pins PB3 and PB4

    sei(); // Enable global interrupts

    // Use the Power Down sleep mode
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    for (;;) {
        sleep_mode();   // go to sleep and wait for interrupt...
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ atmel.com/images/… \$\endgroup\$ – Ignacio Vazquez-Abrams Nov 2 '14 at 19:53
  • \$\begingroup\$ Not sure if it is related to the problem you are reporting, but your schematic is missing a current limiting resistor at the base of the transistor on the MCU pin 5. Is it there in the circuit and you missed it when you captured the schematic? \$\endgroup\$ – Ricardo Nov 2 '14 at 19:56
  • 6
    \$\begingroup\$ I notice the significant omission of any decoupling capacitors on that schematic. Did you leave them off on purpose, or do you actually not have any? \$\endgroup\$ – Majenko Nov 2 '14 at 19:56
  • \$\begingroup\$ The LED(s) also need(s) current limiting resistor(s). Are the LEDs in series or parallel? \$\endgroup\$ – Ricardo Nov 2 '14 at 19:58
  • 1
    \$\begingroup\$ @Majenko-notGoogle Thank you very much. I don't have those. I've built a breadboard-arduino which had those, but I guess I didn't fully understand what they were for, and I didn't know I needed them here as well. I'm reading the document that Ignacio Vazquez-Abrams linked to, and I think I understand the purpose of the decoupling capacitator now. Now only to find out what value it needs to have. :) \$\endgroup\$ – GolezTrol Nov 2 '14 at 20:03
3
\$\begingroup\$

Most proberbly you have a voltage drop when connecting or disconnecting the phone. You should always add some capacitance between VCC and GND to make the circuit less prone to voltage drops. Try to add two capacitors in parallel: 10uF (electrolytic) and 100nF (ceramic or foil). Mind the polarity of the electrolytic one! If this does not help, try to add more caps in parallel.

And, yes the transistor should have at least a 10 ohm base resistor.

Edit: For Atmel MCUs, the correct capacitor values can be found in the datasheet or reference designs.

But: Maybe even more important are the parasitics (ESR, equivalent series resistance). Make sure to place a lower-ESR cap (ceramic) as close as possible to the MCU's supply pins. In general, the larger a cap the more ESR it will have. 100nF is a value commonly used close to the supply pins (chip level), whereas 10uF or 4.7uF is commonly used to buffer entire circuit parts (subcircuit level).

For your circuit it is certainly sufficient to add two 100nF in parallel to the power pins.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer. It is appreciated. Your advice is what I understood from the comments as well. Can you tell me how I can find the proper values for those capacitors? Trial and error seems to be not a good way to get them. Also, can choosing the wrong value damage my circuit in any way? \$\endgroup\$ – GolezTrol Nov 20 '14 at 22:35
2
\$\begingroup\$

I'd start with 100nF ceramic cap as close to the Vcc and GND pins as possible. This is a general recommendation for Atmel uC to deal with smaller voltage drops and spikes.

As the second step, add that electrolytic one somewhere on the power supply line (don't have to be very close to the chip). You may start with something in 10-100uF range and choose one appropriate for the quality of your wall wart power supply. This is purely experimental.

Generally speaking, the bigger cap you add, the more resistant your circuit will be to power losses but longer will be the switching off time when you pull out the plug.

Tip: 100uF, 47uF and similar caps can be scavenged for free from PC mainboards, TV sets and other desktop electronics.

\$\endgroup\$
0
\$\begingroup\$

Please read up on POR (Power On Reset) circuits for Atmel based CPUs, page 6

http://www.atmel.com/Images/Atmel-2521-AVR-Hardware-Design-Considerations_ApplicationNote_AVR042.pdf

To protect the RESET line from further noise, connect a capacitor from the RESET pin to ground. This is not directly required since the AVR internally have a low-pass filter to eliminate spikes and noise that could cause reset. Using an extra capacitor is an additional protection. However, such extra capacitor cannot be used when DebugWIRE or PDI is used.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.