Hallöchen, ich bin sehr neu in diesem Forum und generell wenn es um C
Programmierung und Mikrocontroller geht.
Ich bin seit 2014 im ersten Ausbildungsjahr als Ssyteminformatiker, habe
vorher noch nie Programmiert, und soll eine kleine "Alarmanlage bauen",
da die Raucher in unserem Gebäude (mehrere Firmen) ständig die Türen
offen lassen obwohl dies untersagt ist.
Grundaufbau: Ich hab einen Magnetschalter, einen Summer, eine LED, und
einen ATMEGA8L, Stromzufuhr sind 3* AA Batterien.
Prinzip ist die Tür ist geschlossen, der Magnetkontakt liegt an und der
Controller soll in den PWR_DOWN Modus versetzt werden.
Wird die Tür geöffnet, beginnt ein Timer(zum überprüfen habe ich immer
mal die Zeitabstände verändert), und wenn die Tür nicht rechtzeitig
schließt dann werden der Summer und die LED für eine bestimmte Zeit
angeschalten.
Damit der Stromverbrauch nicht zu hoch ist sollen diese nach einer Zeit,
auch wenn die Tür noch offen steht, abgeschaltet werden und der
Controller in PWR_DOWN versetzt werden.
Das eigentliche Programm steht, aber die Sleep-Modi machen mir zu
schaffen-.-
Nachdem der Summer und die LED abgeschaltet werden fährt der Controller
in PWR_DOWN, jedoch nicht wenn die Tür geschlossen wird.
Dass bereitet mir alles Kopfzerbrechen und ich soll eigentlich nächste
Woche fertig sein...
Mein Ausbilder sagt ständig,obwohl er auch nur grundlegende Kenntnis in
diese Richtung hat, es muss funktionieren und wenn es nicht geht, hast
du einen Fehler eingebaut. Er schaut aber nichtmal drüber...
Könnt ihr mir helfen?
Hier mein Code:
1
#define F_CPU 1000000
2
3
#include<avr/io.h>
4
#include<avr/sleep.h>
5
#include<avr/interrupt.h>
6
#include<util/delay.h>
7
8
// lange, variable Wartezeit, Einheit in Millisekunden
So chaotisch, wie dein Code eingerückt und formatiert ist, wundert es
mich nicht, dass du die implementierte Logik nicht mehr im Blick hast.
Wenn du Informatik als Lehrberuf hast, dann solltest du das schleunigst
abstellen. Codeformatierung ist kein Selbstzweck. Wenn
Hobbyprogrammierer das lernen, dann wirst du das als hauptberuflicher
Programmierer auch lernen müssen.
Ich weiss nicht, wei lang du schon in der Ausbildung bist. Wenn du bei
mir länger als ein halbes Jahr in der Ausbildung gewesen wärst und du
präsentierst mir so ein Machwerk, dann drucke ich das aus und hau es dir
so lange um die Ohren, bis nur noch Konfetti übrig ist! (Bildlich
gesprochen, Gewalt ist ja keine Lösung und auch zu recht verboten)
Sebastian Fiedler schrieb:> es muss funktionieren und wenn es nicht geht, hast> du einen Fehler eingebaut.
Tja, was hast du überhaupt programmiert ?
Soll die Schaltung nur 1 Tür überwachen oder mehrere ?
(derzeit ja wohl nur 1, aber vielleicht sind die Kontakte in Reihe
geschaltet).
Geht der PIN auf HIGH oder LOW wenn die Tür geöffnet wird ?
Sicherlich ist
1
while(1)
2
{
3
GICR|=(1<<INT0);// externen Interrupt freigeben
4
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
5
sleep_mode();// in den Schlafmodus wechseln
6
// hier wachen wir wieder auf
7
GICR&=~(1<<INT0);// externen Interrupt sperren
der Kern deines Programms, allerdings würde ich auf
1 01 The rising edge of INTx generates an interrupt request
reagiaren (wenn der Eingang auf HIGH geht wenn die Tür geöffnet wird)
Dann ist das weitere Vorgehen einfach:
1
long_delay(5000);// oder wie lange die Tür offen sein darf
2
if(PIND&(1<<PD2))// immer noch Tür offen ?
3
{
4
PORTD|=(1<<PD4)|(1<<PD1);// LED und Summmer
5
long_delay(1000);// für eine Sekunde anschalten
6
PORTD&=~((1<<PD4)|(1<<PD1));// ausschalten
7
}
8
// Schleife läuft rum und uC schläft wieder bis Tür aufgeht
9
}
Die Logikprobleem mit quasi-gleichzeitigen Abläufen in der Realität
(warten und währenddessen schliesst sich die Tür) haben viele Leute.
Es gäbe einen EEffekt, wenn die Tür 2 Sekunden aufgeht, 2 Sekunde zu
geht, wieder 2 Sekunden auf geht, dann glaubt die Schaltung, sie wäre
über 5 Sekunden offen gewesen. Das kann man auch noch verbessern.
Irgendwas stimmt da nicht.
Hier
> MCUCR &= ~0x3; // levelgesteuerter Interrupt an INT0
setzt du den Interrupt so, dass du bei Low Level am PD2 Interrupts
bekommst.
Low-Level an diesem Pin bedeutet was?
Offenbar ist der Schalter an der Tür so verschaltet ...
1
...
2
while(1){
3
4
if(PIND&(1<<PD2)){
... das
* 1 eine geöffnete Tür darstellt
* 0 eine geschlossene Tür darstellt
Wenn aber 0 eine geschlossene Tür darstellt, dann ist klar, dass dir die
geschlossene Tür den µC (wegen der Level Einstellung) ständig aus dem
Sleep herausholen wird. D.h. der Teil hier
1
....
2
else{
3
GICR|=(1<<INT0);// externen Interrupt freigeben
4
5
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
6
sleep_mode();// in den Schlafmodus wechseln
7
8
// hier wachen wir wieder auf
9
GICR&=~(1<<INT0);// externen Interrupt sperren
10
// WICHTIG! falls der externe LOW Puls an INT0
11
_delay_ms(10);
12
}
ist völlig sinnlos, denn der µC wird da nicht im Sleep bleiben, sondern
sofort wieder rauskommen. Dies deshalb, weil die Tür ja geschlossen ist,
damit hast du einen Input-Pegel von 0, der aber einen Interrupt auslöst
und den µC sofort wieder aus dem sleep erweckt.
Da du Power-Down nur mit einem externen Level-Interrupt beenden kannst,
wirst du den so legen müssen, dass der Normalfall (und der wird wohl Tür
geschlossen sein) eben KEINEN Interrupt auslöst, sondern nur der
Abnormfall (nämlich wenn die Tür geöffnet ist).
Karl Heinz schrieb:> Da du Power-Down nur mit einem externen Level-Interrupt beenden kannst,> wirst du den so legen müssen, dass der Normalfall (und der wird wohl Tür> geschlossen sein) eben KEINEN Interrupt auslöst, sondern nur der> Abnormfall (nämlich wenn die Tür geöffnet ist).
D.h. aber auch, wenn eine dauergeöffnete Tür nach der Meldung den µC
nicht länger blockieren soll, dann wird man den Interrupt
umkonfigurieren müssen.
Im Normalfall, Tür geschlossen, löst ein High-Pegel Interrupts aus.
Ist die Tür aber zu lange geöffnet, dann muss sich alles umdrehen. Damit
der µC die Wartezeit bis zum Schliessen der Tür schlafen kann, dürfen
dann nur noch Low-Pegel einen Interrupt auslösen, so lange bis jemand
die Tür schliesst. Das ganze so lange, bis dann tatsächlich die Tür
geschlossen wird, woraufhin die Interrupts umkonfiguriert werden, so
dass wieder der Normalfall gilt: High Pegel (also geöffnete Tür) löst
einen Interrupt aus.
Erst mal als Ablaufdiagramm (ohne Beachtung der Details welches Bit wo
zu setzen ist) formulieren!
Sebastian Fiedler schrieb:> Mein Ausbilder sagt ständig,obwohl er auch nur grundlegende Kenntnis in> diese Richtung hat, es muss funktionieren und wenn es nicht geht, hast> du einen Fehler eingebaut. Er schaut aber nichtmal drüber...
O.T.
Wenn das Programm dann funktioniert, gib den Quelltext NUR mit dem
Fehler raus, sonst gibt es der Ausbilder eventuell noch als sein Werk
aus. Flashe die funktionierende .hex-Datei und gib ihm einen alten
Quelltext.
Ich habe solche Schweinereien selbst erlebt und konnte auf diese Weise
ein Großmaul und Alleskönner vor versammelter Mannschaft vorführen.
DER macht so Etwas nie wieder...
VEB Kraftverkehr Acapulco schrieb:> Sebastian Fiedler schrieb:>> Mein Ausbilder sagt ständig,obwohl er auch nur grundlegende Kenntnis in>> diese Richtung hat, es muss funktionieren und wenn es nicht geht, hast>> du einen Fehler eingebaut. Er schaut aber nichtmal drüber...>> O.T.> Wenn das Programm dann funktioniert, gib den Quelltext NUR mit dem> Fehler raus, sonst gibt es der Ausbilder eventuell noch als sein Werk> aus. Flashe die funktionierende .hex-Datei und gib ihm einen alten> Quelltext.>> Ich habe solche Schweinereien selbst erlebt und konnte auf diese Weise> ein Großmaul und Alleskönner vor versammelter Mannschaft vorführen.> DER macht so Etwas nie wieder...
Dann empfiehlt es sich aber auch die Lock-Fuse setzen :-)