Hallo Leute... Ich habe testweise ein Programm geschrieben welches mir die Zeit anzeigt wie lange eine Taste gedrückt ist. Hintergrund ist, ich möchte die Durchflussmenge einer Pumpe messen. Drücke ich den Starttaster rennt die Pumpe und mein Timer los. Lasse ich die Taste los stoppt der Timer und die Zeit wird im Display angezeigt. Die Pumpe wird über nen Zweiten Timer im FastPWM-Modus angesteuert. Was ich aber nicht verstehe, ich kann dem LCD zusehen wie es Zeichen für Zeichen schreibt. Ist also extremst lahm das ganze. Mein Controller läuft mit 16Mhz und ist ein ATmega32. Bevor die Displayausgabe erfolgt, wird der Timer für die Zeitmessung angehalten, der PWM Timer läuft zu dieser Zeit aber noch. Mir ist aufgefallen, wenn ich den PWM-Timer erst garnicht initialisieren und dann meine Zeit messe, erfolgt die Ausgabe minimal schneller. Aber das kann doch eig. garnicht damit zusammenhängen oder? Der Timer läuft ja hardwareseitig? Hat da jemand eine Idee zu? Achso... Programm in C geschrieben. Danke schonmal.
Rush. schrieb:
> Programm in C geschrieben
Schau mal in Zeile 42.
Da scheint etwas nicht zu stimmen.
A.L.U.
Hi
>Achso... Programm in C geschrieben.
Entschuldige. Aber das ist die einzige nachvollziehbare Information.
MfG Spess
haha wie geil is das denn... 1+1=2 aber nicht für jeden! denke auch 42 is der fehler
Was die geschäzten Vorposter auszudrücken versuchen ist, dass ohne deinen Quellcode mit Hilfe nicht zu rechnen ist.
> Hat da jemand eine Idee zu? > Achso... Programm in C geschrieben. Am C wird es vermutlich nicht liegen, man soll damit auch funktioniertende Programme schreiben können. Mit anderen Worten: Man wird Dir besser helfen können, wenn Du Deinen Quelltext zeigst. ;-) ...
Rush. schrieb:
> Ich habe testweise ein Programm geschrieben
Hallo Rush.
wenn du den Inhalt von diesem Programm für dich
behältst, kann dir hier niemand wirklich helfen.
Als lüfte dieses Geheimnis für uns alle.
A.L.U.
Ist ja gut ist ja gut :-D
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include "lcd-routines.h" |
4 | #include <stdlib.h> |
5 | |
6 | extern void lcd_data(unsigned char temp1); |
7 | extern void lcd_command(unsigned char temp1); |
8 | extern void lcd_enable(void); |
9 | extern void lcd_init(void); |
10 | extern void lcd_home(void); |
11 | extern void lcd_clear(void); |
12 | extern void set_cursor(uint8_t x, uint8_t y); |
13 | extern void lcd_string(char *data); |
14 | |
15 | volatile int i=0; |
16 | volatile float ms=0; |
17 | |
18 | void init_io(void) |
19 | {
|
20 | DDRD = 0b00010010; //PD4 Ausgang |
21 | PORTD &=~ (1<<PB1); |
22 | DDRB = 0; |
23 | PORTB = 255; |
24 | |
25 | }
|
26 | |
27 | void init_pwm(void) |
28 | {
|
29 | /* TCCR1B-Registeraufbau ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
|
30 |
|
31 | CS12 CS11 CS10 Description
|
32 | 0 0 0 No clock source (Timer/Counter stopped).
|
33 | 0 0 1 clkI/O/1 (No prescaling)
|
34 | 0 1 0 clkI/O/8 (From prescaler)
|
35 | 0 1 1 clkI/O/64 (From prescaler)
|
36 | 1 0 0 clkI/O/256 (From prescaler)
|
37 | 1 0 1 clkI/O/1024 (From prescaler)
|
38 | |
39 | TCCR1A-Registeraufbau COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
|
40 | |
41 | COM1A1/COM1B1 COM1A0/COM1B0 Description
|
42 | 0 0 Normal port operation, OC1A/OC1B disconnected.
|
43 | 0 1 WGM13:0 = 15: Toggle OC1A on Compare Match, OC1B disconnected (normal port operation).
|
44 | For all other WGM13:0 settings, normal port operation, OC1A/OC1B disconnected.
|
45 | 1 0 Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM, (non-inverting mode)
|
46 | 1 1 Set OC1A/OC1B on compare match, clear OC1A/OC1B at BOTTOM, (inverting mode)
|
47 | */
|
48 | |
49 | TCCR1A |= (1<<COM1B1) | (1<<COM1B0) | (1<<WGM11) | (1<<WGM10); // 10 Bit FastPWM - clear at bottom, set on compare match invertiert |
50 | TCCR1B |= (1<<WGM12) | (1<<CS11) | (1<<CS10); |
51 | }
|
52 | |
53 | void init_timer0(void) |
54 | {
|
55 | OCR0 = 63; // ((16000000Hz/256)/1000Hz) = 62,5 für 1ms |
56 | TIMSK = (1<<OCIE0); // enable interrupts on compare match |
57 | }
|
58 | |
59 | void activate_timer0(void) |
60 | {
|
61 | TCCR0 = (1<<WGM01) | (1<<CS02); //prescaler 256; CTC-Mode |
62 | sei(); |
63 | }
|
64 | |
65 | void deactivate_timer0(void) |
66 | {
|
67 | cli(); |
68 | TCCR0 = (0<<CS02) | (0<<CS01) | (0<<CS00); //prescaler 1024; CTC-Mode |
69 | }
|
70 | |
71 | void rst_timer0(void) |
72 | {
|
73 | ms = 0; |
74 | i = 0; |
75 | }
|
76 | |
77 | void ShowTime(void) |
78 | {
|
79 | unsigned char milliseconds[6]; |
80 | lcd_clear(); |
81 | set_cursor(0,0); |
82 | ms = ms / 1000; |
83 | dtostrf(ms, 3,3, milliseconds); |
84 | lcd_string(milliseconds); |
85 | }
|
86 | |
87 | ISR(TIMER0_COMP_vect) |
88 | {
|
89 | cli(); |
90 | if (i < 50) |
91 | {
|
92 | i++; |
93 | }
|
94 | else
|
95 | {
|
96 | ms++; |
97 | }
|
98 | sei(); |
99 | }
|
100 | |
101 | int main(void) |
102 | {
|
103 | init_io(); |
104 | init_pwm(); |
105 | lcd_init(); |
106 | init_timer0(); |
107 | lcd_clear(); |
108 | set_cursor(0,0); |
109 | sei(); |
110 | |
111 | while (1) |
112 | {
|
113 | if ( !(PINB & (1<<PINB0)) ) |
114 | {
|
115 | activate_timer0(); // Timer aktivieren |
116 | while (i < 50) {} // warten bis Taster vollständig gedrückt - Prellen unterdrücken |
117 | OCR1B = 1023; // DC 1,0 13,8 V |
118 | while ( !(PINB & (1<<PINB0)) ) {} |
119 | deactivate_timer0(); |
120 | OCR1B = 0; |
121 | ShowTime(); |
122 | rst_timer0(); |
123 | }
|
124 | |
125 | while ( !(PINB & (1<<PINB2)) ) |
126 | {
|
127 | activate_timer0(); // Timer aktivieren |
128 | while (i < 50) {} // warten bis Taster vollständig gedrückt - Prellen unterdrücken |
129 | OCR1B = 819; // DC ~0,8 11,03 V |
130 | while ( !(PINB & (1<<PINB0)) ) {} |
131 | deactivate_timer0(); |
132 | ShowTime(); |
133 | rst_timer0(); |
134 | }
|
135 | |
136 | while ( !(PINB & (1<<PINB4)) ) |
137 | {
|
138 | activate_timer0(); // Timer aktivieren |
139 | while (i < 50) {} // warten bis Taster vollständig gedrückt - Prellen unterdrücken |
140 | OCR1B = 615; // DC ~0,6 8,29 V |
141 | while ( !(PINB & (1<<PINB0)) ) {} |
142 | deactivate_timer0(); |
143 | ShowTime(); |
144 | rst_timer0(); |
145 | }
|
146 | |
147 | while ( !(PINB & (1<<PINB6)) ) |
148 | {
|
149 | activate_timer0(); // Timer aktivieren |
150 | while (i < 50) {} // warten bis Taster vollständig gedrückt - Prellen unterdrücken |
151 | OCR1B = 411; // DC ~0,4 5,54 V |
152 | while ( !(PINB & (1<<PINB0)) ) {} |
153 | deactivate_timer0(); |
154 | ShowTime(); |
155 | rst_timer0(); |
156 | }
|
157 | |
158 | while ( !(PINB & (1<<PINB1)) ) |
159 | {
|
160 | activate_timer0(); // Timer aktivieren |
161 | while (i < 50) {} // warten bis Taster vollständig gedrückt - Prellen unterdrücken |
162 | OCR1B = 207; // DC ~0,2 2,79 V |
163 | while ( !(PINB & (1<<PINB0)) ) {} |
164 | deactivate_timer0(); |
165 | ShowTime(); |
166 | rst_timer0(); |
167 | }
|
168 | |
169 | OCR1B = 0; |
170 | }
|
171 | return 0; |
172 | }
|
gibts irgend einen bestimmten Grund für ms float zu verwenden? Die float-Berechnungen werden dich ordentlich Prozessorzeit kosten.
Hi Nur auf den ersten Blick: Den exzessiven Gebrauch von 'sei()' und 'cli()' solltest du tunlichst vermeiden. MfG Spess
Rush. schrieb: > ISR(TIMER0_COMP_vect) > { > cli(); > if (i < 50) > { > i++; > } > else > { > ms++; > } > sei(); > } unnötig in der ISR cli/sei zu verwenden. evtl kostest das ewige ein/ausgeschalte cpu-zeit.
vergesst das sei/cli. Ohne hatte ich das selbe Problem, deshalb hab ich es testweise mit reingeschrieben. @Gleicher Tag Was meinst du mit blockierend? Klär mich mal bitte auf, stehe sogesehen noch im Anfangsstadium der uC-Programmierung.
@Flo Bezüglich des Float. Will die Zeit gerne mit Nachkommastellen haben. Aber wenn du schon fragst dann gibts sicherlich elegantere Möglichkeiten.
Hi >vergesst das sei/cli. Ohne hatte ich das selbe Problem, deshalb hab ich >es testweise mit reingeschrieben. Du schaltest aber bei einem >void deactivate_timerXY(void) auch alle Interrupts ab. Ist das gewollt? MfG Spess
16MHz Quarz angeschlossen, 1MHz interner takt ist noch aktiv !? Joe
@spess53 Ja das ist gewollt mit den Interrupts. Benutze ja nur einen einzigen zum Zählen der Millisekunden. Und den brauche ich ja nicht mehr wenn der Taster losgelassen wurde. @Joe Ne, der Takt ist auf externen Quarz eingestellt.
@ rush. ist das display nur lahm wenn du deine starttaste drückst? wenn das so ist blockiert evtl deine entrellschleife?. dann vielleicht den tasterzusatnd über die ISR mit abwicklen? bin auch erst neu dabei, von daher ne vermutung? (hab mal zum test mehrer tasten über die timer ISR "mit" abgefragt. klappt wunderbar, inkl timerausgabe LCD)
Als Erstz für float lässt sich mit Festkommaarithmetik arbeiten: http://www.mikrocontroller.net/articles/Festkommaarithmetik ;-) Schont die Rechenzeit
schalt mal um lcd_string(milliseconds); die interrupts ab, wenns dann funktioniert ist ein interrupt ständig am werkeln. Ansonsten ists eher in der funktion zu suchen.
Als Anfaenger schreibt man ein Programm gewoehnlich blockierend. Das bedeutet, das Programm steht immer an einer definierten Stelle und wartet auf genau ein Ereignis, und tut waehrend dieser (Warte-)Zeit nichts. Der Zeitablauf ist genau vorgegeben. Als Fortgeschrittener schreibt man nicht mehr blockierend. Man reagiert auf ein Ereignis wenn es auftritt, und wartet nicht mehr. Der Zeitablauf ist nicht mehr genau vorgegeben. Falls ein Ablauf eingehalten werden muss, so bedient man sich einer Statusmaschine. Toent etwas theoretisch. ja.
@swen ne, das display ist auch lahm wenn ich einen string direkt in der while(1) schreibe ohne eine taste zu drücken.
swen schrieb:
> ist das timing in der lcd-routine.h für 16mhz angepasst?
icht meinte in der lcd-routines.h ;)
kann sein das in der #include "lcd-routines.h" auch die Taktfrequenz eingetragen werden muss ?
Die Taktfrequenz kann entweder in der lcd-routines.h eingetragen werden ober aber im Avr-Studio unter den Projektoptionen. Dort stehen die 16Mhz drin. Dieser Eintrag bezieht sich ja auf das komplette Projekt. Schreibe ich es zusätzlich in die lcd-routines.h kommt erstens ne warnmeldung vom compiler "F_CPU redefined in...." und zweitens ändert es an meinem Problem trotzdem nichts.
dann mach mal stück für stück dein programm "kleiner" und beobachte das display. trial & error :)
Was will ich denn da groß kleiner machen? Schmeisse die initialisierung fürs pwm raus und mehr geht sogesehen garnicht. sind doch nur tasterabfragen.
Wenn ein Programm nicht debug-bar ist, sollte man's wegschmeissen und neu beginnen.
So, eben einfach mal das hier geschrieben:
1 | #include <avr/io.h> |
2 | #include "lcd-routines.h" |
3 | |
4 | extern void lcd_data(unsigned char temp1); |
5 | extern void lcd_command(unsigned char temp1); |
6 | extern void lcd_enable(void); |
7 | extern void lcd_init(void); |
8 | extern void lcd_home(void); |
9 | extern void lcd_clear(void); |
10 | extern void set_cursor(uint8_t x, uint8_t y); |
11 | extern void lcd_string(char *data); |
12 | extern void lcd_led(uint8_t a); |
13 | |
14 | |
15 | |
16 | int main(void) |
17 | {
|
18 | lcd_init(); |
19 | |
20 | lcd_string("alsdjadsf"); |
21 | }
|
und es ist immer noch so lahm. Einen anderen Port habe ich eben auch mal versucht, das selbe :-(
na selbst die festellung ist ne amtliche aussage! da steckt der fehler wohl nicht im programmteil/ISR teil. schalt mal bitte auf int rcosc um. evtl hat dein quarz probleme (kontakt, kapazitäten...)
jl schrieb: > schalt mal um > lcd_string(milliseconds); > die interrupts ab, > > wenns dann funktioniert ist ein interrupt ständig am werkeln. > Ansonsten ists eher in der funktion zu suchen. hast du das probiert? wär doch die erste Einschränkung der Fehlerquelle!
Rush. schrieb: > extern void lcd_data(unsigned char temp1); > extern void lcd_command(unsigned char temp1); > extern void lcd_enable(void); > extern void lcd_init(void); > extern void lcd_home(void); > extern void lcd_clear(void); > extern void set_cursor(uint8_t x, uint8_t y); > extern void lcd_string(char *data); > extern void lcd_led(uint8_t a); ich weiss eigentlich garnicht warum das alles da rein muss... wenn ich lcd routines verlinke brauch ich garnichts davon
Zaphod Beeblebrox schrieb:
> geht mir zu schnell hier -.-
da haste wohl nen schnelles LCD :D
wer weiß, meins liegt noch jungfräulich unverzinnt im Keller...
Hab den Takt mal auf den default von 1Mhz gestellt und die Projektoptionen angepasst. Das selbe! @swen Gute Frage ob ich das brauche oder nicht. In früheren Verisonen vom avr-gcc hat er mir immer ne Fehlermeldung ausgespuckt. Ein Freund hat mir dann geraten das extern immer mit reinzunehmen damit der Compiler von vorn herein weiss das die Funktionen eben extern liegen. Habs jetzt rausgenommen und das LCD geht trotzdem, aber langsam eben :-(
hat das lcd jemals "schnell" angezeigt? nich das hier der "wurm liegt". evtl haste ja noch nen zweiten controller zum probieren. nur um das unvorstellbare auszuschließen. weil dann wäre ich auch mit meinem latein am ende
Ja das hat die ganze Zeit normal funktioniert. Aber ich werds nochmal auf einem anderen Controller probieren. Hab nur gerade keinen anderen parat. Aber werde dann meine Erkenntnisse posten. Danke schonmal für eure Bemühungen.
Was mir noch einfällt... Kann mein Problem auch vom Programmer abhängen? Habe das Evertool Teil mal nachgebaut, da ist aber noch eine uralte Firmware drauf.
@ Rush. (Gast) Kleiner Tip: Netiquette. Lange Quelltexte gehören in den Anhang. Und es wäre sinnvoll, den AVR-Typ zu nennen. Wenn dein AVR so schnarchlangsam ist, kann es sein dass er mit dem Watchdogtimer mit 128 kHz läuft, das geht bei einigen AVRs. Oder du hast das define F_CPU in Makefile oder den Projektoptionen im AVR-Studio falsch eingestellt. Hast du jeweils neu compiliert und auch neu programmiert? Zum Thema nichtblockierende Programmierung siehe Multitasking. MfG Falk
Rush. schrieb:
> In den Optionen sind die 16Mhz übrigens auch eingetragen.
welche Optionen meinst Du?
Wie sind die Fusesettings für den Takt programmiert?
Wie ist CKDIV8-Fuse programmiert?
Am besten gibts Du uns mal den Prozessortyp und die 3 Fusebytes an.
Bye
Andi
@ Falk Falk Brunner schrieb: > Kleiner Tip: Netiquette. Lange Quelltexte gehören in den Anhang. Und > es wäre sinnvoll, den AVR-Typ zu nennen. Wenn du schon von Netiquette sprichst solltes du dich selber dran halten und wenigstens das erste Posting überfliegen: Rush. schrieb: > Mein Controller > läuft mit 16Mhz und ist ein ATmega32. Wie wenn ATmega32 nichts aussagen würde...
@ Michael (Gast)
>Wie wenn ATmega32 nichts aussagen würde...
Das hab ich dann wohl übersehen. Entschuldigung.
@Rush
Ob die Takteinstellung passt kann man leicht mit folgendem Programm
prüfen.
1 | #include <avr/io.h> |
2 | #define F_CPU 16000000
|
3 | #include <util/delay.h> |
4 | |
5 | int main(void) { |
6 | int i; |
7 | |
8 | DDRA = 1; // ein Port mit ner LED dran |
9 | |
10 | while (1) { |
11 | for (i=0; i<1000; i++) _delay_ms(1); |
12 | PORTA ^= 1; |
13 | }
|
14 | }
|
Du musst natürlich das Programm an deine Pinbelegung anpasssen. Wenn die LED im Sekundentakt blinkt ist deine Oszillatoreinstellung OK. MFG Falk
@Michael Das Timing meines Programms passt da ich ja wie schon am Anfang geschrieben die Dauer des gedrückten Tasters messe und diese auch korrekt am display angezeigt wird. Im Anhang meine Fuses und die Optionen aus dem AVR-Studio als Screenshot. @ Falk Brunner Ich habe den Watchdog doch im Code nirgends initialisiert, also läuft er doch garnicht oder?
@ Rush. (Gast) >Im Anhang meine Fuses und die Optionen aus dem AVR-Studio als >Screenshot. Das passt alles. >Ich habe den Watchdog doch im Code nirgends initialisiert, also läuft er >doch garnicht oder? Das ist was anderes. Bei einigen AVRs kann man den Watchdogoszillator als Taktquelle auswählen, aber nicht beim Mega32. MfG Falk
Habe das ganze eben nochmal mit einem anderen Controller versucht und die Ausgabe ist immer noch so langsam. Ob evtl. mein Display einen Schlag hat ?! Wobei, es lief eig. immer ganz zuverlässig.
>Ob evtl. mein Display einen Schlag hat ?! Wobei, es lief eig. immer ganz >zuverlässig. Nö, eher deine LCD Routinen oder der uC Takt. Da steckt doch der Wurm drin. Zeig die LCD Routinen mal.
Wäre abeer schon seltsam. Ich habe die libs von Peter Fleury. Diese ist soweit unverändert bis auf eine Routine zum Einschalten der Hintergrundbeleuchtun und lief immer einwandfrei. Aber schau mal drüber. Routine hängt dran.
Da haben wirs ja schon;) // erzeugt den Enable-Puls void lcd_enable(void) { // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen // Beitrag "Re: Bitte helft mir. Schon wieder AtMega16" LCD_PORT |= (1<<LCD_EN); _delay_ms(90); // kurze Pause // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern // Beitrag "LCD -> Probleme mit Optimierungsgrad" LCD_PORT &= ~(1<<LCD_EN); } 90ms für Enable ist schon etwas viel.
Na eeeeeeeeeeeeeeeeeeeeeendlich :-D Danke dir vielmals 10us fürs enable tuns auch :-D Vielen Dank für eure Bemühungen. Jetzt gehts :-)
} // erzeugt den Enable-Puls void lcd_enable(void) { // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen // Beitrag "Re: Bitte helft mir. Schon wieder AtMega16" LCD_PORT |= (1<<LCD_EN); _delay_us(1); // kurze Pause // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern // Beitrag "LCD -> Probleme mit Optimierungsgrad" LCD_PORT &= ~(1<<LCD_EN); } bei ihr isses 1us! check ma!
upps zu spät...:) na siehste geht doch nichts über ne community ;)
Jup 1us tuts bei mir auch. Ich kann mich grob erinnern dass ich mit dem Wert mal rumgespielt hatte weil ich mal ein LCD hatte wo es mit 1us nicht lief. So gehts einem wenn man die libs von projekt zu projekt kopiert ;-) Demnächst weiss ich bescheid.... Und ja, in dieser Community gehts vorwärts. Hier schreiben die leute schneller zurück als Freunde aus dem ICQ :-D
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.