Forum: Mikrocontroller und Digitale Elektronik While Funktion in einer Switch Case Anweisung


von Kevin (Gast)


Angehängte Dateien:

Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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!

von Falk B. (falk)


Lesenswert?

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);

von Kevin (Gast)


Lesenswert?

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

von franzose (Gast)


Lesenswert?

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...

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

@ 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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Wolfgang A. (Gast)


Lesenswert?

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.

von Kevin (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.