Hallo, Ich habe ein Entwicklerboard mit einem Atmega88. Wollte für den Betrieb in dem ich Arbeite eine kleine Schaltung aufbauen, mit der man 4-20mA Drucktransmitter messen kann. Die Schaltung beinhaltet ein 2x20 Display, 4 Taster, mitdem man den zu messenden Transmitter vorwählen kann. Zur Hardware gibts nicht viel zu sagen, versorgt wird der Microcontroller über einen Stepdown Regler, der 24V in 5V wandelt. Die 4-20mA lese ich über einen 250 Ohm Widerstand ein und scaliere diese später im Programm. Zum Problem: Ich habe 2 Dateien angehängt. In der Datei Transmitter.c habe ich den Analogeingang eingelesen und in einer while Schleife auf das Display ausgegeben. Funktioniert einwandfrei. In der Datei Transmitter_Solid_State.c habe ich diese Funktion in eine Switch Case Funktion gepackt. Hier wird aber der Analgogwert nur beim Menüpunktwechsel aktualisiert. Ich vermute das Problem liegt an dem am Ende des "case" stehenden Break. Kann mir jemand verraten wie ich den Analogwert ständig aktualisiert bekomme? Habe mich im Forum schon dämlich gesucht. Wäre für jeden Denkanstoß oder ein Lösungsweg sehr Dankbar. Mfg Kevin
@ Kevin (Gast) >In der Datei Transmitter.c habe ich den Analogeingang eingelesen und in >einer while Schleife auf das Display ausgegeben. >Funktioniert einwandfrei. Es gibt die schöne mathematische Operation Modulo. Damit kann man einfacher Vor- und Nachkommastellen berechnen ;-) Siehe Festkommaarithmetik >In der Datei Transmitter_Solid_State.c habe ich diese Funktion in eine >Switch Case Funktion gepackt. Wo soll das sein? Ausserdem ist ein switch() Konstrukt KEINE Funktion! Man kann nicht einfach beliebige Worte verwenden! Diese 2. VErsion ist ein Kauderwelsch! Was soll denn da rauskommen? >Kann mir jemand verraten wie ich den Analogwert ständig aktualisiert >bekomme? Indem man es richtig macht. >Habe mich im Forum schon dämlich gesucht. Die Antwort darauf liefert die Logik, nicht das Forum. >Wäre für jeden Denkanstoß oder ein Lösungsweg sehr Dankbar. Was soll denn rauskommen? Dein 1. Ansatz ist deutlich einfacher, übersichtlicher und er funktioniert!
Noch ein Tip. Nomen est Omen. Man sollte Variabeln sinnvoll benennen. x,y,z, ist was für Arrays und Indizes, nicht Druck, Strom, etc. Strukturierte Programmierung auf Mikrocontrollern Ausserdem ist es unsinning, wenn du schon mit Fließkomma rechnest, dann das wieder manuell zu zerlegen! Dann gleich konsequent Festkommaarithmetik. Ein C-Buch wäre hier sehr empfehlenswert (nicht als Türsopper, sondern als Lektüre)
1 | uint32_t pressure = (2000L*raw); |
2 | uint32_t current_inst = (15650L*raw); |
3 | uint32_t current_set = (25000L*raw); |
4 | |
5 | sprintf(messwertstring, "%ld.%02ld %02ld.%02ld %02ld.%02ld",pressure/1000,pressure%1000,current_inst/1000,current_inst%1000,current_set/1000,current_set%1000); |
Hallo Falk, Danke für deine Antwort. Okay ein Konstrukt! Habe mit der Mikrocontroller Programmierung erst angefangen. Die Modulo Funktion schau ich mir mal genauer an! In der Zweiten Version die ich geschickt habe sollte durch das Switch Case Konstrukt die Menüfuhrung durchgeswitch werden und der Analogwert in jedem case aktualisiert werden. (Bei Case 3 & 4 habe ich nur mal Case 3 & Case 4 auf das Display gegeben bis der Rest Funktioniert) Das durchschalten Funktioniert auch. Wie gesagt nur die Aktualisierung des Analogwertes soll immer aktuell ausgegeben werden. Es sollen 4 Transmittertypen auswählbar sein. 0-400mbar 0-4bar 0-6bar 0-10bar Für mein Vorhaben soll in jedem case muss der Analogwert aufbereitet und dauerhaft ausgegeben werden. oder sollte ich das ganze Komplett anders aufbauen? Mfg Kevin
Also ich steck auch erst knietief in der Programmierung mit c, aber ich würde mir mehrere Funktionen schreiben. z.B. INIT(), ReadADC(uint8_t), toDisplay(uint8_t) etc... in der Switch case springst Du dann da rein. In jedem Durchlauf der Main passiert das gleiche, solange Du keine taste drückst. Da gibt's ja schon eine while-schleife...
@ Kevin (Gast) >Es sollen 4 Transmittertypen auswählbar sein. >0-400mbar >0-4bar >0-6bar >0-10bar >oder sollte ich das ganze Komplett anders aufbauen? Ja. Vor allem übersichtlicher. Eben dazu braucht man wirklich sinnvolle Funtionen und natürlich auch einen switch(). _Lcd_Init(); wird nur EINMALIG ausgeführt. Vor der großen while(1) Schleife. Der Name _Lcd_Init() ist nicht sonderlich sinnvoll, Funktionen die mit _ anfangen sind für den Compiler reserviert. Das zentrale switch() Konstrukt soll klein und übersichtlich sein. Der Krümelkram wird in Funktionen ausgelagert. Ausserdem muss man die Funktionen zur Anzeige und zur Tasterauswertung sowie Messwerterfassung trennen. Das schafft Überblick und eine gescheite Struktur. Nach Möglichkeit schafft man universelle Funktionen, denen man passende Parameter übergibt. Etwa so. Siehe Anhang.
Kevin schrieb: > oder sollte ich das ganze Komplett anders aufbauen? Ja. Vor allen Dingen sollst nicht eine so dermassen lange Hauptschleife schreiben. Da verlierst du nämlich ganz schnell den Überblick. Ob man bei 4 Fällen einen switch-case macht, kann man natürlich diskutieren. Im Moment seh ich eigentlich keinen Vorteil da drinn. Noch was: Initialisierungen gehören aus der Hauptschleife im Normalfall raus. Es macht keinen Sinn, inneerhalb der Hauptschleife das LCD ständig neu zu initialisieren. Und gewöhn dir an, dass es genau EINE Endlosschleife gibt und nicht deren mehrere. Wenn du Code aus einem vorhergehenden Projekt übernimmst, dann nicht einfach ins neue Projekt reinklatschen sondern die Dinge müssen angepasst werden! Das spielt jetzt natürlich wieder in die Richtung, dass deine Hauptschleife viel zu unübersichtlicht lang ist. Das du da noch überhaupt irgendwas findest?
1 | void doKevinsTransmitterTest() |
2 | {
|
3 | _Lcd_Locate(1,1); |
4 | _LcdWriteString("Kevins"); |
5 | _Lcd_Locate(2,1); |
6 | _LcdWriteString("Transmittertest"); |
7 | }
|
8 | |
9 | void doStromMessung() |
10 | {
|
11 | raw = ADC_Read (7); |
12 | |
13 | x = (2.0*raw); |
14 | y = (15.65*raw); |
15 | z = (25*raw); |
16 | |
17 | pistvorkomma=(x/1000); |
18 | pistnachkomma=x-(pistvorkomma*1000); |
19 | pistnachkomma=pistnachkomma/10; |
20 | |
21 | iistvorkomma=(y/1000); |
22 | iistnachkomma=y-(iistvorkomma*1000); |
23 | iistnachkomma=iistnachkomma/10; |
24 | |
25 | isollvorkomma=(z/1000); |
26 | isollnachkomma=z-(isollvorkomma*1000); |
27 | isollnachkomma=isollnachkomma/10; |
28 | |
29 | _Lcd_Locate(1,1); |
30 | _LcdWriteString("Pist IIst ISoll"); |
31 | |
32 | sprintf(messwertstring, "%d.%02d %02d.%02d %02d.%02d", pistvorkomma+4, pistnachkomma, |
33 | iistvorkomma+4, iistnachkomma, |
34 | isollvorkomma+4, isollnachkomma); |
35 | _Lcd_Locate (2,1); |
36 | _LcdWriteString (messwertstring); |
37 | }
|
38 | |
39 | void doCase3() |
40 | {
|
41 | _Lcd_Locate(1,1); |
42 | _LcdWriteString("Case 3"); |
43 | _Lcd_Locate(2,1); |
44 | _LcdWriteString("Case 3"); |
45 | }
|
46 | |
47 | void doCase4() |
48 | {
|
49 | _Lcd_Locate(1,1); |
50 | _LcdWriteString("Case 4"); |
51 | _Lcd_Locate(2,1); |
52 | _LcdWriteString("Case 4"); |
53 | }
|
54 | |
55 | int main() |
56 | {
|
57 | |
58 | ....
|
59 | |
60 | _Lcd_Init(); |
61 | |
62 | State_cnt = 1; |
63 | |
64 | // Endlosschleife
|
65 | while(1) |
66 | {
|
67 | |
68 | if( State_cnt == 1 ) |
69 | {
|
70 | doKevinsTransmitterTest(); |
71 | }
|
72 | |
73 | else if( State_cnt == 2 ) |
74 | {
|
75 | doStromMessung(); |
76 | }
|
77 | |
78 | else if( State_cnt == 3 ) |
79 | {
|
80 | doCase3(); |
81 | }
|
82 | |
83 | else if( State_cnt == 4 ) |
84 | {
|
85 | doCase4(); |
86 | }
|
87 | |
88 | if(Check_SW1()) |
89 | {
|
90 | State_cnt++; |
91 | if( State_cnt == 4) |
92 | State_cnt = 1; |
93 | while(Check_SW1()); |
94 | }
|
95 | }
|
96 | }
|
achte auch ein wenig mehr auf die äussere Form des Codes. Es macht wenig Sinn, alle Buchstaben einfach nur Knirsch an Knirsch zu schreiben. So was ist sehr schwer zu lesen bzw. zu entziffern, weil du zuallererst mal die Wörter in dem Wust an Buchstaben finden musst. Im Gegenzug kannst du dir dafür die exzessiven Leerzeilen sparen. 1 Leerzeile reicht völlig aus, um anzuzeigen, dass hier ein neuer Gedankengank im Code beginnt. Es braucht da keine 25 aufeinanderfolgenden Leerzeilen.
Falk Brunner schrieb: > x,y,z, ist was für Arrays und Indizes Gewöhnlich verwendet man für Indices Buchstaben aus dem Bereich i bis k, wenn man dann nicht aussagekräftigere Namen verwenden möchte. x, y und z werden eher für Mess-/Prozessgrößenverwendet, egal ob Skalar oder Array.
Danke für all eure Antworten! Das Gerüst Falk gefällt mir sehr. Werde es gleich anpassen und testen! Wahnsinn wie schnell du den Code angepasst habt! @ Karl Heinz: Ich habe mich für das Switch Case Konstrukt entschieden, da wenn noch Speicher auf dem Mikrocontroller frei ist noch ein paar Drucktransmitter dazukommen dürften/könnten aber nicht unbedingt müssen. Natürlich gelobe ich auf Hinsicht des Programmcodes, der Leerzeichen und Kommentierung Besserung! :-) Danke nochmal an alle! Ihr habt mir sehr geholfen
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.