Hallo,
bin grad dabei meinem ComingHome Modul paar weitere Funktionen zu geben.
Dabei hab ich auch einen DIP Schalter, der je nach zustand das licht
entweder gar nicht dimmen soll 00 ,
auf und abdimmen aber licht bei 60% halten 01 ,
auf und abdimmen aber licht bei 80% halten 10 ,
auf und abdimmen aber licht bei 100% halten 11 ,
Nun: 00 10 11 funktionieren.
Wenn ich aber 01 mache, dann dimmt er auf, scheint sich dann aber iwie
aufzuhängen und steckt in der zeit schleife fest und kommt so nie zum
runter dimmen.
Das ganze ist noch nicht fertig, da ich noch nen Lichtsensor abfragen
werde und INT0 und INT1 Interrupt routinen einbauen werde.
Bloß ich hänge hier grad bei der Sache und weis nicht worans liegen
könnte. Im grunde sind ja nur paar variabeln die geändert werden.
Selbst, wenn ich den Code von 80% da reinlege, funktioniert es nicht.
Woran liegt es also?
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<avr/interrupt.h>
4
#include<avr/sleep.h>
5
6
volatileintsekunde=0;//wird vom Timer immer um 1 erhöht.
7
//1 = 0,01sekunden
8
intdutycycle=0;//aktueller Dutycycle
9
intmaxdutycycle=153;//maximaler Dutycycle
10
intdutycycleoff=1;//Auf- und abdimmen deaktivieren
11
intlichtsensor=0;//ADC-wert des Lichtsensors
12
intlichtschwelle=0;//unterhalb dieses wertes wird der Lichtwert als dunkel erkannt
13
intabdimmen=0;//wird auf 1 gesetzt. wenn die Hauptzeit läuft
14
intanbleibzeit=1;//Zeit in sekunden in der das Licht aktiv bleiben soll
15
intdimmzeit=17;//Zeit pro PWM änderung
16
intstop=0;//wenn 1, dann aus
17
18
intmain(void)
19
{
20
ACSR|=1<<ACD;//Analog Comparator ausschalten um Strom zu sparen
21
22
//Konfiguration ADC
23
24
//PWM
25
DDRB|=1<<DDB3;//PWM Ausgang auf PINB3
26
27
PORTD|=1<<PIND5|1<<PIND6|1<<PIND7;//Pull up
28
PORTB|=1<<PINB0;
29
PORTC|=1<<PINC2|1<<PINC3|1<<PINC4|1<<PINC5;
30
31
32
sei();//Interrup zulassen
33
while(1)
34
{
35
//Timer für Sekunde definieren
36
TCCR1B|=1<<WGM12|1<<CS11|1<<CS10;//Taktgeber für genau eine Sekunde
Bist du soweit ein paar Tips anzunehmen, mit denen du dein Programm
einfacher machen kannst?
Da ist zb. die komplette If-Orgie mit der du die Pins PD5, PD6 und PD7
auswertest.
Grundsätzlich ist da (fast) nichts falsches drann. Aber so
ist es dann doch einfacher ausgedrückt als diese komplette if-Orgie, die
mit ihren "! oder nicht !" dann doch eher fehleranfällig zu lesen und zu
schreiben sind.
Das benutzt natürlich, dass deine 3 Schalter an aufeinanderfolgenden
Pins liegen. Der komplette Port wird geholt, die 3 Bits mit dem &
freigestellt (alle anderen Bits auf 0), dann um entsprechend viele
Stellen nach rechts geschoben, so dass sich aus den 3 Bits eine Zahl
zwischen 0 und 7 ergibt und damit kann man dann aus dem Array den zu
benutzenden Wert holen.
PINC1 benutz ich nicht. Der schalter liegt auf PIN 28,27,26,25 beim
Atmega 8
Belegt somit an PORTC PINC5 PINC4 PINC3 PINC2.
Der zweite DIP Schalter ist an den PINS 11,12,13 und 14 angeschlossen.
Beide Schalter schalten gegen GND. Ich benutze die internen Pull Ups.
Ja, man kanns bestimmt schöner machen. Aber es müsste doch trotzdem
gehen.
Weil er erkennt ja die Stellungen für Off, 80% und 100%
Hab bereits die Dip schalter durchgemessen und auch schon nen anderen
Atmega genommen, aber das Problem bleibt bestehen. Er schaltet nach der
Anbleibzeit nicht mehr aus.
Oh, da hab ich mich da wohl vertan...PINC1 ist aber offen auf der
Platine.
Man bin ich blöd -.-
werds direkt mal testen
Danke schonmal, werde gleich berichten
Sascha712 schrieb:> Ja, man kanns bestimmt schöner machen. Aber es müsste doch trotzdem> gehen.
Das interessante ist, das Code welcher übermässig komplex und 'nicht
schön' ist, auch oft Code ist, in dem die tollsten Fehler schlummern.
Daher ist die Aussage "erst muss es funktionieren, dann mach ich es
schön" nur die halbe Miete. Denn wenn man Code von vorne herein gleich
(in vernünftigem Masse) einfach bzw. schön schreibt, spart man sich
viele Fehler, die man dann auch nicht suchen muss.
Deine Dimm-Routine. Noch durchblicke ich die noch nicht in allen
Einzelheiten aber aus dem Bauch raus müsste das funktionieren. D.h. wenn
da nicht noch irgendwo ein kleiner fieser Fehler steckt.
Und nimm der Grundaufsatz für den Timer am Anfang der while Schleife aus
dieser raus. Solche Dinge werden einmalig gemacht und danach lässt man
die Bits in Ruhe.
Ich hab per Dipschalter auch die möglichkeit das auf und abdimmen
wegzulassen. Also quasi nur an und aus.
Darum sind die Bits für den Timer dort.
Im grunde ist es ganz simpel. Immer nach ablauf von delay-Dimmzeit wird
Dutycycle entweder um eins erhöht oder um eins verringert, dadurch auch
das "Faden"
Gibts irgendwo paar informationen, wie man "schön" schreibt?
gruß
Sascha712 schrieb:> Ich hab per Dipschalter auch die möglichkeit das auf und abdimmen> wegzulassen. Also quasi nur an und aus.> Darum sind die Bits für den Timer dort.
Schon.
Aber was bringt dir ein
1
while(1)
2
{
3
//Timer für Sekunde definieren
4
TCCR1B|=1<<WGM12|1<<CS11|1<<CS10;//Taktgeber für genau eine Sekunde
5
TIMSK|=1<<OCIE1A;
6
OCR1A=15624;
am ANfang der Schleife?
Die Bits verändern sich nie.
Du schaltest einzig und alleine den Vorteiler zu oder weg. Aber der Rest
bleibt immer gleich.
> Gibts irgendwo paar informationen, wie man "schön" schreibt?
Zum Beispiel das angesprochene.
Zum Beispiel, indem man sowas
> if((PINB & (1<<PINB0))&&( !(PINC & (1<<PINC1)) ))
in einem realen Programm mit Makrohilfe ein wenig aufpeppt.
1
if(IS_CLOSED(DIMM_DIP_1)&&IS_OPEN(DIMM_DIP_0))
ist schon wesentlich einfacher zu lesen.
Noch einfacher ist es aber, wenn man die beiden Bits als das auffasst,
was sie sind. Beide zusammen bilden eine Zahl zwischen 0 und 3 und davon
abhängig werden dann Parameter ausgewählt. Daher ist es auch verünftig
genau das zu tun: aus den beiden Bits eine Zahl zusammenzubauen und dann
von dieser Zahl ausgehend den Brückenschlag zu den Parametern zu
schaffen, wie immer der dann auch aussieht, zb mit einem Array.
was ist leichter zu verstehen. Deine Version, oder die hier
1
structdimmPreset_
2
{
3
uint8_tdutyCycleOff;
4
uint16_tdimmZeit;
5
uint16_tmaxDutyCycle;
6
};
7
8
structdimmPreset_[]=
9
{
10
// PINB0 PINC1
11
{1,0,0},// 0 0 Off
12
{0,12,204},// 0 1 60%
13
{0,12,204},// 1 0 80%
14
{0,10,255}// 1 1 100%
15
};
16
17
....
18
19
DimmLevel=0;
20
if(PINB&(1<<PINB0))
21
DimmLevel+=2;
22
if(PINC&(1<<PINC1))
23
DimmLevel+=1;
24
25
dutycycleoff=dimmPreset[DimmLevel].dutyCycleOff;
26
dimmzeit=dimmPreset[DimmLevel].dimmZeit;
27
maxdutycycle=dimmPreset[DimmLevel].maxDutyCycle;
28
....
welche ist kürzer? Welche ist leichter an andere Zahlenwerte anzupassen?
Welche ist leichter an andere Pinnummern anzupassen?
Anstatt PINB, PINC, PINB0, PINC1 wäre es auch vernünftig mittels #define
ein paar sprechende Namen zu definieren, so dass man die tatsächliche
Belegung nicht quer durch das ganze Programm verstreut hat, sondern am
Anfang ganz oben.
denn beispielsweise
1
#define LED_PORT PORTD
2
#define ERROR_LED PD5
3
4
5
...
6
7
8
LED_PORT|=(1<<ERROR_LED);
erzählt mir im Programmtext als Leser schon wesentlich mehr als es ein
1
PORTD|=(1<<PD5);
jemals könnte. Und wenn ich da noch einen Kommentar dazu mache
1
PORTD|=(1<<PD5);// Error LED einschalten
dann binn ich schon fast in der besseren Variante, hab aber den Vorteil,
dass die nicht falsch sein kann ...
1
PORTD|=(1<<PD6);// Error LED einschalten
weil an PD6 in Wirklichkeit gar nicht die Error LED sitzt, sondern die
Busy LED :-)
1
#define LED_PORT PORTD
2
#define ERROR_LED PD5
3
#define BUSY_LED PD6
4
5
...
6
7
8
LED_PORT|=(1<<ERROR_LED);
9
LED_PORT&=~(1<<BUSY_LED);
Noch ein bischen Makro Magie darüber gestreut
1
#define LED_PORT PORTD
2
#define ERROR_LED PD5
3
4
#define TURN_ON(b) LED_PORT |= ( 1 << b )
5
#define TURN_OFF(b) LED_PORT &= ~( 1 << b )
6
7
...
8
9
10
TURN_ON(ERROR_LED);
11
TURN_OFF(BUSY_LED);
und dann liest sich der Programmtext schon fast wie englische Prosa,
obwohl nach all den Ersetzungen da auch nichts anderes steht als
1
PORTD|=(1<<PD5);
2
PORTD&=~(1<<PD6);
Aber die Information, die mir ein
1
TURN_ON(ERROR_LED);
2
TURN_OFF(BUSY_LED);
ganz automatisch beim Lesen vermittelt, ist eine ungleich höhere und
höherwertige. Hier geht es nicht mehr um Ports und Bits. Hier geht es
darum, was das Programm an dieser Stelle aus einer logischen Sicht der
Dinge macht.
Ja, ich find das ist gut erklärt. Dazu sollte es wirklich nen Wiki
geben!
Werd ich so machen.
Nach dem Compilieren nimmt die schönere Version aber genausoviel Platz
weg, wie die "meine"?
Danke übrigens für die guten Beispiel! :)