Hallo zusammen,
vorweg... ich bin blutiger Anfänger... habe auch schon viel gesucht,
aber finde einfach nicht so richtig die Hilfe die ich brauche.
Folgendes, ich möchte mir gerne eine Individuelle Lichtsteuerung bauen
mit einem Attiny13A
Was soll er können?
Verschiende Programme ablaufen lassen
Programme durch schalten mittels Taster
Das aktuelle Programm speichern. Damit er mit dem Programm wieder
startet, wenn man Ihn wieder einschaltet...
Das habe ich bisher als minimal-version mir zusammen gebastelt.
1
#define F_CPU 4800000UL //4,8MHz
2
#include<avr/io.h>
3
#include<util/delay.h>
4
#include<avr/eeprom.h>
5
6
uint8_teeFooByteEEMEM;//Variable eeFooByte im EEPROM anlegen.
7
uint8_tSetting_Write;//Variable myWByte anlegen und den Wert 1 laden. (Wird später in EEPROM geschrieben)
8
uint8_tSetting_Read;//Variable für den Wert der dann aus EEPROM gelesen wird.
9
10
intmain(void)
11
{
12
#define EEPROM_DEF 0xFF
13
intx;
14
15
16
17
Setting_Read=eeprom_read_byte(&eeFooByte);
18
x=Setting_Read;
19
if(x<1){x=1;}
20
21
//int x = 1;
22
intk=0;
23
inti=0;
24
25
DDRB=0b00000001;//PB0 als Ausgang deklarieren
26
PORTB=0b00000010;
27
28
while(1)
29
{
30
k++;
31
i++;
32
33
if(!(PINB&(1<<1))){x++;Setting_Write=x;eeprom_write_byte(&eeFooByte,Setting_Write);_delay_ms(500);}// Invertiert mit (!...) Taster abfragen! Wert aus Variable Setting_Write in eeFooByte (EEPROM) schreiben
34
35
if(x==1)
36
{
37
if(k==10){PORTB|=(1<<PB0);}
38
if(k==20){PORTB&=~(1<<PB0);}
39
if(k==30){PORTB|=(1<<PB0);}
40
if(k==40){PORTB&=~(1<<PB0);}
41
42
if(k==80){PORTB|=(1<<PB0);}
43
if(k==90){PORTB&=~(1<<PB0);}
44
if(k==100){PORTB|=(1<<PB0);}
45
if(k==110){PORTB&=~(1<<PB0);}
46
47
if(k==150){k=0;}
48
49
}
50
if(x==2)
51
{
52
if(k==1){PORTB|=(1<<PB0);}
53
if(k==6){PORTB&=~(1<<PB0);}
54
if(k==11){PORTB|=(1<<PB0);}
55
if(k==16){PORTB&=~(1<<PB0);}
56
57
if(k==26){PORTB|=(1<<PB0);}
58
if(k==31){PORTB&=~(1<<PB0);}
59
if(k==36){PORTB|=(1<<PB0);}
60
if(k==41){PORTB&=~(1<<PB0);}
61
62
if(k==51){k=0;}
63
}
64
if(x>=3){x=1;}
65
66
67
if(i==1000){i=0;}
68
_delay_ms(25);
69
}
70
71
}
Probleme: Er schaltet nicht zuverlässig die Programme durch, er bleibt
hängen, so das eine LED konstant an bleibt oder gar nicht erst leuchtet.
Das Byte in den eeprom schreiben funktioniert wohl auch nicht so
zuverlässig.
Könnt ihr mit bitte helfen??
Vielen lieben Dank
Tobias
k, x, i sind nicht gerade aussagekräftige Dateinamen. Nutze den Platz
für längere Namen.
Auch die Port-Zugriffe kann man mit Hilfe von Definitionen und
Funktionen lesbarer machen. Beispiele:
1
#define BEREITSCHAFTS_LED PB3
2
PORTB|=(1<<BEREITSCHAFTS_LED);// ein schalten
3
PORTB&=~(1<<BEREITSCHAFTS_LED);// aus schalten
4
5
#define Bereitschafts_LED_Ein PORTB |= (1<<PB3);
6
#define Bereitschafts_LED_Aus PORTB &= ~(1<<PB3);
7
Bereitschafts_LED_Ein;
8
Bereitschafts_LED_Aus;
9
10
staticinlinevoidBereitschafts_LED_Ein()
11
{
12
PORTB|=(1<<PB3);
13
}
14
15
staticinlinevoidBereitschafts_LED_Aus()
16
{
17
PORTB|=&=~(1<<PB3);
18
}
19
20
Bereitschafts_LED_Ein();
21
Bereitschafts_LED_Aus();
Anstelle dieser langen "if"-Ketten halte ich "switch" für eleganter.
Bist du sicher dass die Stromversorgung Ok ist? Hast du
Abblock-Kondensatoren? Zeige mal den Schaltplan und Fotos.
Wozu dient die Variable i?
Da mir der letzte Spannungsteiler hops gegangen ist versorge ich den
AtTiny13 nun über den ISP6 Anschluss,
Normal hab ich aber einen Spannungsteiler 5V, 1 100µF und 0,1µF
Kondensator mit drinnen.
Ich sehe da ein Problem:
Wenn k zum Beispiel gerade 14 ist und due dann von Programm X=1 nach x=2
umschaltest, wird es ziemlich lange dauern, bis der Zähler k überläuft
und bei 0 beginnt. Ich würde entweder bei jedem Umschalten des Programms
k auf 0 setzen oder den letzten if Ausruck ändern.
anstatt: if (k==51) {k = 0;}
besser: if (k>=51) {k = 0;}
oder noch besser mit switch:
Tobias B. schrieb:> Da mir der letzte Spannungsteiler hops gegangen ist
Stromversorgung über einen Spannungsteiler ist schon mal ein riesen
Fehler. Verwende entweder einen aktiven Spannungsregler (wie den LM7805)
oder schließe den Mikrocontroller direkt ans Netzteil/Batterie an, falls
die Spannung passt.
Und nie vergessen: 100nF direkt an jedem IC von VCC nach GND.
Zeige mal den Schaltplan und Fotos.
Vielen Dank schonmal,
jetzt hab ich das etwas angepasst.
Mit dem Case blieb auf einmal die LED Konstant an... komisch,
Das Programme umschalten funktioniert nun reibungslos (vorerst :-)) aber
irgendwo hab ich noch den Wurm drinnen mit dem Abspeichern und Auslesen
des "aktiven" Programms? Wenn ich die Spannung unterbreche, dann fängt
er wieder mit "1" an.
D.h. entweder speichert oder liest den Wert nicht, das immer mein
1
if(x<1){x=1;}
greift.
Spannungsregler ist notiert, suche mir da die passenden SMD Bauteile
raus, 0,1µF hab ich drangehangen an VCC/GND.
Was meint ihr? Ist der 100µF übertrieben? Der ist als SMD Bauteil doch
recht groß.
Grüße
Tobias
1
#define F_CPU 4800000UL //4,8MHz
2
#include<avr/io.h>
3
#include<util/delay.h>
4
#include<avr/eeprom.h>
5
6
uint8_teeFooByteEEMEM;//Variable eeFooByte im EEPROM anlegen.
7
uint8_tSetting_Write;//Variable myWByte anlegen und den Wert 1 laden. (Wird später in EEPROM geschrieben)
8
uint8_tSetting_Read;//Variable für den Wert der dann aus EEPROM gelesen wird.
9
10
intmain(void)
11
{
12
#define EEPROM_DEF 0xFF
13
intx;
14
15
16
17
Setting_Read=eeprom_read_byte(&eeFooByte);
18
x=Setting_Read;
19
if(x<1){x=1;}
20
21
//int x = 1;
22
intk=0;
23
inti=0;
24
25
DDRB=0b00000001;//PB0 als Ausgang deklarieren
26
PORTB=0b00000010;
27
28
while(1)
29
{
30
k++;
31
i++;
32
33
if(!(PINB&(1<<1))){x++;Setting_Write=x;eeprom_write_byte(&eeFooByte,Setting_Write);k=0;i=0;_delay_ms(500);}// Invertiert mit (!...) Taster abfragen! Wert aus Variable myWriteByte in eeFooByte (EEPROM) schreiben
Tobias B. schrieb:> Was meint ihr? Ist der 100µF übertrieben? Der ist als SMD Bauteil doch> recht groß.
Schau ins Datenblatt des Spannungsregler. Da wird immer ein konkreter
Wert empfohlen und manchmal ein maximale erlaubter Wert angegeben.
Ich glaube, dass Schlüsselwort EEMEM soll vor dem Namen der Variable
stehen.
Warum benutzt du für x eine 16 Bit (int) Variable, kopierst sie aber zum
Speichern von und zu 8 Bit um? Vermutlich ist das jetzt nicht die
Problemursache, aber es ist zumindest merkwürdig.
Wenn du diese EEprom Zelle aufgrund vorheriger falscher Versuche schon
tausende male beschrieben hast, ist sie vielleicht einfach schon
verschlissen. Probiere mal einen anderen Speicherplatz. Anstelle der
EEMEM Variable kannst du bei eeprom_write_byte() und eeprom_read_byte()
einfach die Nummer (=Adresse) der Speicherzelle angeben.
Zeige den Quelltext mit switch/case.
Benutze längere Variablen Namen.
Benutze #define und/oder Funktionen um den Code besser lesbar zu machen.
Ich habe keine Lust, diese Wirrwarr noch öfter analysieren zu müssen.
> Da immer das if (x < 1) {x = 1;} greift.
Woher weißt du, dass genau diese Zeile greift? Hast du einen Debugger
verwendet, oder wie analysierst du das? Ich würde das gerne wissen, weil
man die weitere Vorgehensweise darauf aufsetzen kann.
Noch ein möglicher Fehler:
Beim Programmstart aktivierst du den internen Pull-Up Widerstand vom
Taster und fragst in ohne nennenswerte Verzögerung danach ab.
Je nachdem, wie hoch die parasitäre Kapazität vom Steckbrett, Leitungen
und Taster sind, ist der pin dann noch dabei, von Low nach High hoch zu
kommen.
Benutze einen externen Pull-Up Widerstand mit 1 bis 4,7k Ohm und baue
eine kleine Warteschleife ein, bevor du den Taster zum ersten mal
abfragst.
Hallo,
nein ich habe kein Debugger, live zu sehen was der Attiny macht wäre
schon schön...
So ich hab jetzt das EEMEM davor gesetzt, das Beispiel hatte ich von
http://avr-programmieren-rh.de/
Desweiteren habe ich das
1
_delay_ms(25);
nach oben geholt, um ein wenig verweilzeit zu haben um den Taster ab zu
fragen.
desweiteren hab ich "int" durch "uint8_t" ersetzt.
Jetzt klappt alles! VIELEN DANK EUCH! :-)
Wie meint ihr das, den Code lesbarer zu machen? Sorry für diese Frage..
Grüße
Tobias
Hab doch noch mal eine Frage,
wenn ich PB5 als Ausgang einstelle und dort eine LED Anschließe, macht
der Attiny nichts mehr und die LED schimmert..
Ist ja auch der Reset Pin, muss ich da irgendwie was anders machen?
Tobias B. schrieb:> nein ich habe kein Debugger, live zu sehen was der Attiny macht wäre> schon schön...
Also hast du das nur vermutet. Das solltest du auch deutlich
hinschreiben, sonst führt deine (Fehl-)Diagnose die Helfer in die Irre.
Es ist immer Hilfreich, solche Vermutungen durch zusätzliche LED
Anzeigen oder serielle Ausgaben zu verifizieren. Dafür brauchst du nur
einen freien Pin. Siehe http://stefanfrings.de/avr_hello_world/> Wie meint ihr das, den Code lesbarer zu machen? Sorry für diese Frage..
Habe ich doch geschrieben. Versuche es mal so (ungetesteter Code):
1
#define F_CPU 4800000UL //4,8MHz
2
#include<avr/io.h>
3
#include<util/delay.h>
4
#include<avr/eeprom.h>
5
6
// Die LED ist an PB0 und GND angeschlossen
7
#define LED_EIN { PORTB |= (1 << PB0); }
8
#define LED_AUS { PORTB &= ~(1 << PB0); }
9
10
// Der Taster ist an PB1 und GND angeschlossen (erfordert Pull-Up)
11
#define TASTER_GEDRUECKT (!(PINB & (1<<PB1)))
12
13
uint8_teeBlinkMusterNrEEMEM;// Um das Blinkmuster im EEprom zu speichern
14
uint8_tblinkMusterNr;// Aktuell laufendes Blinkmuster (1 oder 2)
15
uint8_tstep=0;// Schrittzähler für die Blinkmuster
16
17
18
voidsetup()
19
{
20
// I/O Pins initialisieren
21
DDRB=0b00000001;// PB0=Ausgang für die LED
22
PORTB=0b00000010;// PB1=Eingang mit Pull-Up für den Taster
Du solltest deiner LED dringend einen Vorwiderstand spendieren, wenn du
sie nicht killen willst. Wenn du das mit vielen LEDs so (ohne
Widerstand) machst, brennt dir sogar der Mikrocontroller durch.
Stefanus, vielen Dank.
Vorwiderstand hab ich dran, 220Ohm.
Hmm woran liegt das mit PB5?
Deine code ist sehr übersichtlich, ich werde mir das wohl auch so
angewöhnen, danke :-)
Tobias schrieb:> Hmm woran liegt das mit PB5?
PB5 ist der Reset Eingang.
Versuche nicht, die entsprechende Fuse zu ändern, denn ohne Reset
funktioniert die ganze ISP Schnittstelle danach nicht mehr!
Das Programm hat eine unschöne Stelle:
Wenn blinkMusterNr=2 aktiv ist und du dann die Taste drückst, wird die
Variable auf 3 erhöht und das dann auch so im EEprom gespeichert.
3 ist ungültig, deswegen wird das direkt danach von den default case auf
1 geändert.
Letztendlich wird im EEprom immer 2 oder 3 stehen, obwohl in
Wirklichkeit die Blinkmuster 2 oder 1 aktiv sind. Ist egal, oder?
Ich glaub, ich würde die Blinksignale in dem Format Start/Länge in
Arrays schreiben und dann mit ner Schleife drüber gehen, um zu schauen,
wo ich bin? Langsamer, aber schöner... find ich...