Proyecto
Todavía no tengo mucha experiencia con la electrónica y la programación de microcontroladores. Recientemente (accidentalmente) compré un par de microcontroladores ATTiny13A, asumiendo que podría programarlos usando el IDE de Arduino.
Debido a la pequeña cantidad de memoria en estas cosas, decidí hacer un proyecto simple: una luz de lectura que se apaga automáticamente. Y decidí usar AVR Studio (6.0) en lugar del IDE de Arduino.
El circuito es bastante simple, creo. Dos botones para agregar media hora de luz y otro para apagar las luces inmediatamente. Todo funciona con una verruga de pared USB, que suministra alrededor de 5V (5.2, lo medí).
Simplifiqué el led. De hecho, hay 2 leds (planifiqué 3 al principio) y las resistencias apropiadas, que es también la razón por la que agregué la resistencia. También dejé de lado las conexiones con el programador AVR, ya que no son relevantes para el circuito en sí.
La luz funciona como debe ser. Se enciende durante 3 segundos cuando lo enchufo. Puedo encenderlo y apagarlo. Y cuando lo enciendo, se quema durante aproximadamente media hora antes de apagarse solo. Si sé de antemano que quiero tener más de media hora de luz, puedo presionar el botón varias veces, para obtener N veces media hora.
Hasta ahora todo bien.
Problema: reinicios no deseados
Ahora el problema es que parece ser bastante sensible a los picos o caídas. Tengo una verruga de pared con dos conexiones. Cuando la luz de la noche está enchufada en una de ellas, y conecto mi teléfono a la otra, la luz de la noche se reinicia, se quema durante tres segundos y luego se apaga. Esto también sucede la mayor parte del tiempo cuando desconecto el teléfono. No importa si la luz estaba encendida o apagada cuando lo hago.
Entonces, mi pregunta principal es, ¿cómo resuelvo estos reinicios ? También estoy abierto a otros consejos.
También pegaré el programa aquí como referencia. Creo que no es relevante, pero intenté usar interrupciones y tener el controlador en modo de suspensión la mayor parte del tiempo, así que lo publicaré de todas formas, en caso de que contenga información vital.
/*
* 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...
}
}