Projekt
Ich bin noch nicht sehr erfahren mit Elektronik und Mikrocontroller-Programmierung. Ich habe kürzlich (aus Versehen) ein paar ATTiny13A-Mikrocontroller gekauft, vorausgesetzt, ich könnte sie mit der Arduino IDE programmieren.
Aufgrund des geringen Speicherplatzes auf diesen Dingen entschied ich mich für ein einfaches Projekt: ein Leselicht, das sich automatisch ausschaltet. Und ich habe mich entschieden, AVR Studio (6.0) anstelle der Arduino IDE zu verwenden.
Die Schaltung ist ziemlich einfach, denke ich. Zwei Knöpfe, um eine halbe Stunde Licht hinzuzufügen, und ein weiterer, um das Licht sofort auszuschalten. Alles wird von einer USB-Steckdose mit Strom versorgt, die etwa 5 V liefert (5,2, habe ich gemessen).
Ich habe die LED vereinfacht. Tatsächlich gibt es 2 LEDs (ich hatte zuerst 3 geplant) und die entsprechenden Widerstände, weshalb ich auch den Widerstand hinzugefügt habe. Auch die Verbindungen zum AVR-Programmer habe ich weggelassen, da sie für die Schaltung selbst nicht relevant sind.
Simulieren Sie diese Schaltung – Mit CircuitLab erstellter Schaltplan
Das Licht funktioniert wie es soll. Es brennt 3 Sekunden lang, wenn ich es einstecke. Ich kann es ein- und ausschalten. Und wenn ich es einschalte, brennt es ungefähr eine halbe Stunde, bevor es sich von selbst ausschaltet. Wenn ich vorher weiß, dass ich mehr als eine halbe Stunde Licht haben möchte, kann ich den Knopf mehrmals drücken, um N mal eine halbe Stunde zu bekommen.
So weit, ist es gut.
Problem: unerwünschte Resets
Jetzt ist das Problem, dass es ziemlich empfindlich auf Spitzen oder Einbrüche zu reagieren scheint. Ich habe eine Wandwarze mit zwei Anschlüssen. Wenn das Nachtlicht in einen von ihnen eingesteckt wird und ich mein Telefon in den anderen einstecke, wird das Nachtlicht zurückgesetzt, leuchtet drei Sekunden lang und schaltet sich dann aus. Dies passiert auch meistens, wenn ich das Telefon ausstecke. Dabei spielt es keine Rolle, ob bei mir das Licht an- oder ausgeschaltet war.
Meine Hauptfrage ist also, wie löse ich diese Resets ? Für andere Ratschläge bin ich auch offen.
Ich werde das Programm hier auch als Referenz einfügen. Ich denke, es ist nicht relevant, aber ich habe versucht, Interrupts zu verwenden und den Controller die meiste Zeit im Schlafmodus zu haben, also werde ich es trotzdem posten, nur für den Fall, dass es wichtige Informationen enthält.
/*
* 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...
}
}
Höchstwahrscheinlich haben Sie einen Spannungsabfall, wenn Sie das Telefon anschließen oder trennen. Sie sollten immer etwas Kapazität zwischen VCC und GND hinzufügen, um die Schaltung weniger anfällig für Spannungsabfälle zu machen. Versuchen Sie, zwei Kondensatoren parallel hinzuzufügen: 10 uF (Elektrolyt) und 100 nF (Keramik oder Folie). Beachten Sie die Polarität des Elektrolyten! Wenn dies nicht hilft, versuchen Sie, weitere Kappen parallel hinzuzufügen.
Und ja, der Transistor sollte mindestens einen Basiswiderstand von 10 Ohm haben.
Bearbeiten: Für Atmel-MCUs finden Sie die korrekten Kondensatorwerte im Datenblatt oder in den Referenzdesigns.
Aber: Vielleicht noch wichtiger sind die Parasiten (ESR, Equivalent Series Resistance). Achten Sie darauf, eine untere ESR-Kappe (Keramik) so nah wie möglich an den Versorgungsstiften der MCU zu platzieren. Im Allgemeinen gilt: Je größer eine Kappe, desto mehr ESR wird sie haben. 100 nF ist ein Wert, der üblicherweise in der Nähe der Versorgungspins (Chipebene) verwendet wird, während 10 uF oder 4,7 uF üblicherweise verwendet werden, um ganze Schaltungsteile zu puffern (Unterschaltungsebene).
Für Ihre Schaltung reicht es sicherlich aus, zwei 100nF parallel zu den Power-Pins hinzuzufügen.
Ich würde mit einer 100-nF-Keramikkappe so nah wie möglich an den Vcc- und GND-Pins beginnen. Dies ist eine allgemeine Empfehlung für Atmel uC, um mit kleineren Spannungsabfällen und -spitzen fertig zu werden.
Fügen Sie als zweiten Schritt diesen Elektrolyten irgendwo auf der Stromversorgungsleitung hinzu (muss nicht sehr nahe am Chip sein). Sie können mit etwas im Bereich von 10-100 uF beginnen und eines auswählen, das für die Qualität Ihres Netzteils geeignet ist. Das ist rein experimentell.
Im Allgemeinen gilt: Je größer die Kappe, die Sie hinzufügen, desto widerstandsfähiger wird Ihre Schaltung gegen Leistungsverluste, aber länger wird die Abschaltzeit sein, wenn Sie den Stecker ziehen.
Tipp: 100uF, 47uF und ähnliche Kappen können kostenlos von PC-Mainboards, Fernsehgeräten und anderer Desktop-Elektronik gespült werden.
Bitte informieren Sie sich über POR (Power On Reset)-Schaltungen für Atmel-basierte CPUs, Seite 6
http://www.atmel.com/Images/Atmel-2521-AVR-Hardware-Design-Considerations_ApplicationNote_AVR042.pdf
Um die RESET-Leitung vor weiterem Rauschen zu schützen, schließen Sie einen Kondensator vom RESET-Pin an Masse an. Dies ist nicht direkt erforderlich, da der AVR intern über einen Tiefpassfilter verfügt, um Spitzen und Rauschen zu eliminieren, die einen Reset verursachen könnten. Die Verwendung eines zusätzlichen Kondensators ist ein zusätzlicher Schutz. Ein solcher zusätzlicher Kondensator kann jedoch nicht verwendet werden, wenn DebugWIRE oder PDI verwendet werden.
Ignacio Vazquez-Abrams
Ricardo
Majenko
Ricardo
GolezTrol
GolezTrol
Majenko
Chris Stratton
Jake Robinson
GolezTrol
Majenko
davidcary