Forum: Compiler & IDEs Anfängerfrage: Wert umwandeln


von Rocco (Gast)


Lesenswert?

Hallo,

ich bin nicht sehr erfahren beim programmieren also verzeiht mir bitte 
den Diletantismus.

Ich habe mal mit einem Bekannten etwas gebaut und programmiert das einen 
DS18S20 One Wire Temperatursensor ausließt und die Temperatur in einem 
2x8 LED Array anzeigt. Das Anzeigen funktioniert so, dass 4 LED für die 
Zahlen 1,2,4,8 stehen und je nachdem welche LED leuchten werden die 
Werte addiert.
Mit dem 10er Bereich ist es genau so.
1 [ ] [ ] 10
2 [x] [x] 20
4 [x] [ ] 40
8 [ ] [ ] 80

^^in dem Bsp leuchten die LED mit den Werten2, 4, 20  d.h. es sind 26°C

Jetzt muss ich mit einem weiteren Atmega diese LED's wieder auslesen und 
die ganze Sache wieder in einen Zahlenwert umwandeln so das der Atmega 2 
Werte miteinander vergleichen kann. Das Auslesen ist einfach, nur wie 
mache ich aus den Signalen von PIC und PIND etwas das ich mit < oder > 
vergleichen kann?

Das ist der Code der aus den Daten des DS18S20 die LED Hausnummer macht:
1
do
2
        {
3
4
                // Kommando an den Sensor (Messung starten)
5
                // >>Notiz>> Wir gehen einfach von einem Erfolg aus <<
6
                start_meas();
7
        
8
                // Temperatur vom Sensor holen
9
                t = read_meas_fast();
10
        t = t/8;
11
        u = t;
12
13
                // Temperatur in Grad Celsius:
14
                tC = (t >> 1) | (t & 0xFF00);
15
                if(tC < 0) tC = -tC; //Vorzeichen entfernen
16
                        
17
18
                //reset (alle LEDs aus)
19
                p = 0x00;
20
21
           //Konfiguration der Pins für LEDs setzen
22
                // (0 = LED an, 1 = LED aus)
23
                if(tC >= 80) { p |=(1<<7); tC -= 80; } //Pin7 für 80°C an
24
                if(tC >= 40) { p |=(1<<6); tC -= 40; } //Pin6 für 40°C an
25
                if(tC >= 20) { p |=(1<<5); tC -= 20; } //Pin5 für 20°C an
26
                if(tC >= 10) { p |=(1<<4); tC -= 10; } //Pin4 für 10°C an
27
                if(tC >= 8)  { p |=(1<<3); tC -= 8;  } //Pin3 für 8°C  an
28
                if(tC >= 4)  { p |=(1<<2); tC -= 4;  } //Pin2 für 4°C  an
29
                if(tC >= 2)  { p |=(1<<1); tC -= 2;  } //Pin1 für 2°C  an
30
                if(tC >= 1)  { p |=(1<<0); tC -= 1;  } //Pin0 für 1°C  an
31
32
           
33
        p = ~p;
34
        
35
        //Eichung des Thermometers
36
        LED_OUT = p;
37
        
38
                        
39
                // ein wenig warten verhindert,
40
                // dass der Sensor durch Selbsterw?rmung
41
                // falsche Ergebnisse liefert
42
                _delay_ms(1000);



Für das Auslesen und das Vergleichen habe ich bisher follgendes 
Auszugsweise:
1
#define WTEMP_IN   PINC        //Wärmebad abfragen
2
#define KTEMP_IN   PIND        //Kältebad abfragen  
3
4
//und die main:#########################
5
6
7
uint8_t w_temp = 0;          //Variable zum speichern der Zustände vom Wärmebad
8
uint8_t k_temp = 0;          //Variable zum speichern der Zustände vom Kältebad
9
10
KTEMP_DDR = 0x00;    //Eing?nge
11
WTEMP_DDR = 0x00;    //Eing?nge
12
13
        do
14
        {
15
      k_temp = KTEMP_IN;          //Temp vom Kältebad abholen
16
      w_temp = WTEMP_IN;          //Temp vom Wärmebad abholen
17
18
        if((p_temp <= k_temp + 1))   //fals Probentemp gleich Kältebadtemp ist
19
        {  Mache etwas }

Danke für die Hilfe

Gruß Rocco

von Karl H. (kbuchegg)


Lesenswert?

Rocco schrieb:

> Jetzt muss ich mit einem weiteren Atmega diese LED's wieder auslesen und
> die ganze Sache wieder in einen Zahlenwert umwandeln so das der Atmega 2
> Werte miteinander vergleichen kann. Das Auslesen ist einfach, nur wie
> mache ich aus den Signalen von PIC und PIND etwas das ich mit < oder >
> vergleichen kann?

Indem du in deinem Programm genau das gleiche machst, was du beim 
Ablesen der Temperatur als Mensch auch machst. Sprich: Du baust dir erst 
mal die durch die LED angezeigte Zahl zusammen.

 Zahl = 0
 wenn die Led mit der Wertigkeit 1 leuchtet, dann Zahl = Zahl + 1
 wenn die Led mit der Wertigkeit 2 leuchtet, dann Zahl = Zahl + 2
 wenn die Led mit der Wertigkeit 4 leuchtet, dann Zahl = Zahl + 4
 ...

jetzt hast du eine Zahl, die der LED-Anzeige entspricht und mit der 
kannst du in weiterer Folge machen was immer du willst.

von Karl H. (kbuchegg)


Lesenswert?

Allerdings erhebt sich die Frage: Warum willst du überhaupt einen 2.ten 
Prozessor verwenden. Ich bin mir ziemlich sicher, dass dein erster 
Prozessor das schalten bei bestimmten Temperaturen locker noch nebenbei 
erledigen kann.

von Rocco L. (kaufparkangucker)


Lesenswert?

das das so einfach ist...

Ich brauche einen zweiten weil alle anderen Füße bereits belegt sind.

vielen Dank

von Karl H. (kbuchegg)


Lesenswert?

Rocco L. schrieb:
> das das so einfach ist...

Nicht wahr :-)

Und dabei hast du es sogar die ganze Zeit gewusst! Ich zitiere
> anzeigt. Das Anzeigen funktioniert so, dass 4 LED für die
> Zahlen 1,2,4,8 stehen und je nachdem welche LED leuchten
> werden die Werte addiert.


> Ich brauche einen zweiten weil alle anderen Füße bereits belegt sind.

Ich glaub, ich wills gar nicht wissen. Genausowenig wie ich wissen will, 
warum jemand eine binäre Anzeige ein paar 7-Segment vorzieht.

von Rocco L. (kaufparkangucker)


Lesenswert?

ja, einfach zu doof sowas anzusteuern, noch nie gemacht und alles selber 
beigebracht-da mangelt es an allen Grundlagen.
Ich wünschte mir ja auch ich könnte so was.

Das persönliche Treffen und miteinander etwas machen, kann ein Forum 
leider nicht ganz ersetzen. :-(

von Rocco L. (kaufparkangucker)


Lesenswert?

Hallo,

ich habe das mal versucht umzusetzen. Könnten sie bitte nochmal drüber 
sehen?

Die Idee ist das ein Motor eine Probe in ein Kältebad fahren soll und 
später in ein Wärmebad. Dabei wird die Temperatur in den beiden Bädern 
und in der Probe gemessen. Wenn die Probentemperatur gleich der 
Temperatur des jeweiligen Bades ist, soll ins andere Bad gewächselt 
werden.
1
//B2 Taster K?ltebad
2
//B3 Taster W?rmebad
3
4
5
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#define F_CPU 2000000
9
#include <util/delay.h>
10
#include <inttypes.h>
11
#include <stdint.h>
12
13
#define TRUE 1
14
#define FALSE 0
15
16
// Anchlussbelegung:
17
18
#define KTEMP_DDR DDRD        //Temperatur Input vom Kältebad
19
#define WTEMP_DDR DDRC        //Temperatur Input vom Wärmebad
20
#define PTEMP_DDR DDRA        //Temperatur Input von Probe
21
22
#define MOTOR_DDR DDRB        //Datenrichtung zum Motor-Steuer-Atmega festlegen
23
#define MOTOR_OUT PORTB        //Ausgänge zum Motor-Steuer-Atmega
24
#define MOTOR_IN  PINB
25
26
//#define WTEMP_IN   PINC        //Wärmebad abfragen
27
//#define KTEMP_IN   PIND        //Kältebad abfragen      
28
//#define PTEMP_IN   PINA        //Probentemperatur abfragen
29
30
#define CW   PB0          //Motor cw richtung Kältebad
31
#define CCW  PB1          //Motor ccw richtung Wärmebad
32
#define KB   PB2          //Taster Kältebad abfragen 
33
#define WB   PB3          //Taster Wärmebad abfragen
34
35
36
37
38
39
40
41
42
int main(void)
43
{
44
    uint8_t w_temp = 0;          //Variable zum speichern der Zustände vom Wärmebad
45
    uint8_t k_temp = 0;          //Variable zum speichern der Zustände vom Kältebad
46
    uint8_t p_temp = 0;          //Variable zum speichern der Zustände von der Probe
47
         
48
        const uint16_t pause = 200;
49
    const uint16_t pause_2 =80;
50
    
51
    
52
    KTEMP_DDR = 0x00;    //Eing?nge D
53
        WTEMP_DDR = 0x00;    //Eing?nge C
54
    PTEMP_DDR = 0x00;    //Eing?nge A
55
    //B0 un B1 als Ausgänge, B2 und B3 als Eingänge:
56
    MOTOR_DDR = DDRB = (1 << DDB0) | (1 << DDB1) | (0 << DDB2) | (0 << DDB3);
57
        
58
59
60
    //Pause für 20 Sekunden damit alles andere initialisieren kann
61
    //for(int a=0; a<10; a++){_delay_ms( 1000 )};
62
63
    
64
65
        do
66
        {
67
      k_temp = 0;          
68
      p_temp = 0;          
69
      w_temp = 0;          
70
      //k_temp = KTEMP_IN;          //Temp vom Kältebad abholen
71
      //p_temp = PTEMP_IN;          //Temp der Probe abholen
72
      //w_temp = WTEMP_IN;          //Temp vom Wärmebad abholen
73
74
      if ( PINA & (1<<PINA0) ) {p_temp = p_temp + 1}
75
      if ( PINA & (1<<PINA1) ) {p_temp = p_temp + 2}
76
      if ( PINA & (1<<PINA2) ) {p_temp = p_temp + 4}
77
      if ( PINA & (1<<PINA3) ) {p_temp = p_temp + 8}
78
      if ( PINA & (1<<PINA4) ) {p_temp = p_temp + 10}
79
      if ( PINA & (1<<PINA5) ) {p_temp = p_temp + 20}
80
      if ( PINA & (1<<PINA6) ) {p_temp = p_temp + 40}
81
      if ( PINA & (1<<PINA6) ) {p_temp = p_temp + 80}
82
83
      if ( PINC & (1<<PINC0) ) {w_temp = w_temp + 1}
84
      if ( PINC & (1<<PINC1) ) {w_temp = w_temp + 2}
85
      if ( PINC & (1<<PINC2) ) {w_temp = w_temp + 4}
86
      if ( PINC & (1<<PINC3) ) {w_temp = w_temp + 8}
87
      if ( PINC & (1<<PINC4) ) {w_temp = w_temp + 10}
88
      if ( PINC & (1<<PINC5) ) {w_temp = w_temp + 20}
89
      if ( PINC & (1<<PINC6) ) {w_temp = w_temp + 40}
90
      if ( PINC & (1<<PINC6) ) {w_temp = w_temp + 80}
91
92
      if ( PIND & (1<<PIND0) ) {k_temp = k_temp + 1}
93
      if ( PIND & (1<<PIND1) ) {k_temp = k_temp + 2}
94
      if ( PIND & (1<<PIND2) ) {k_temp = k_temp + 4}
95
      if ( PIND & (1<<PIND3) ) {k_temp = k_temp + 8}
96
      if ( PIND & (1<<PIND4) ) {k_temp = k_temp + 10}
97
      if ( PIND & (1<<PIND5) ) {k_temp = k_temp + 20}
98
      if ( PIND & (1<<PIND6) ) {k_temp = k_temp + 40}
99
      if ( PIND & (1<<PIND6) ) {k_temp = k_temp + 80}
100
101
      //Wenn Taster vom K?ltebad an (d.h. Probe ist im Kältebad)
102
      if((PINB & (1<<KB)))
103
      {
104
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
105
      PORTB &= ~ (1<<CCW);  //Motor aus
106
      PORTB &= ~ (1<<CW);    //Motor aus
107
108
109
        if((p_temp <= k_temp + 1))   //fals Probentemp gleich Kältebadtemp ist
110
        {
111
         //Pause um damit Probe die Temp vom Kältebad vollständig annehmen kann
112
             //     for(int a=0; a<20; a++){_delay_ms( 1000 );}
113
114
         //ins Wärmebad fahren)
115
         PORTB &= ~ (1<<CCW);
116
         PORTB |= (1<<CW);
117
118
         //Pause für 20 Sekunden
119
               //for(int a=0; a<20; a++){_delay_ms( 1000 );} 
120
        }
121
      }
122
         
123
      //Wenn Taster vom Wärmebad an (d.h. Probe ist im Wärmebad)
124
      if((PINB & (1<<WB)))
125
      {
126
        //Motor erst mal grundlegend ausschalten, um einen definierten Startwert zu haben
127
      PORTB &= ~ (1<<CCW);  //Motor aus
128
      PORTB &= ~ (1<<CW);    //Motor aus
129
        
130
      
131
        if((p_temp >= w_temp - 1))// fals Probentemp gleich Wärmebadtemp ist
132
        {
133
         //Pause um damit Probe die Temp vom Wärmebad vollständig annehmen kann
134
         //for(int a=0; a<20; a++){_delay_ms( 1000 );}
135
136
         //ins Kältebad fahren
137
         PORTB &= ~ (1<<CW);
138
         PORTB |= (1<<CCW);
139
         
140
        }
141
      }
142
143
144
         
145
146
147
148
        } //ENDE do
149
    while(1);
150
151
} //ENDE main

Habe gerade nochmal genau gelesen, 7 Segment haben Sie geschrieben, ich 
weis nicht warum ich dabei an LCD gedacht habe. So eine 7 Segmentanzeige 
wäre natürlich gescheiter...
Beim nächsten mal ;)

von Karl H. (kbuchegg)


Lesenswert?

Wenn ich mir hier mal den Fehler PINA7 / PINA6
wegdenke
1
      if ( PINA & (1<<PINA0) ) {p_temp = p_temp + 1}
2
      if ( PINA & (1<<PINA1) ) {p_temp = p_temp + 2}
3
      if ( PINA & (1<<PINA2) ) {p_temp = p_temp + 4}
4
      if ( PINA & (1<<PINA3) ) {p_temp = p_temp + 8}
5
      if ( PINA & (1<<PINA4) ) {p_temp = p_temp + 10}
6
      if ( PINA & (1<<PINA5) ) {p_temp = p_temp + 20}
7
      if ( PINA & (1<<PINA6) ) {p_temp = p_temp + 40}
8
      if ( PINA & (1<<PINA6) ) {p_temp = p_temp + 80}

dann ist die Pinbelegung genau so, dass ein einfaches
1
      p_temp =  ((PINA & 0xF0) >> 4 ) * 10;
2
      p_temp +=  (PINA & 0x0F );

genau dasselbe macht.




> Beim nächsten mal ;)

Aber nur weil die Hardware schon steht und wahrscheinlich irgendwo 
eingebaut ist.
Aber mal im Ernst: Wäre es nicht vernünftig die original untauglich 
Hardware durch eine neue zu ersetzen und jemand an den Editor zu lassen, 
der auch ein wenig programmieren kann?

Sorry. Aber ich kann da einfach nicht mehr widerstehen. Da werden von 
Leuten, die grade mal sinngemäss "krabbeln" gelernt haben, Lösungen 
gebaut und programmiert, wo du dir als interessierter Bastler (und noch 
nicht einmal Hardware-Profi) nur noch auf den Kopf greifst. Ein 
interessierter Bastler hat in längstens 3 Tagen eine Lösung (inkl. 
Hardwareaufbau) fertig, die um Welten besser ist. Für einen Profi ist 
die Programmierung eine Sache auf 2 Stunden, inkl. ausgiebigem Testen.
Ich will dir ja nicht dein Hobby vermiesen, aber ein gewisser Realismus 
sollte schon sein, dass das hinten und vorne nichts gescheites ist. Und 
ich rede von der Originalplatine!
Du sagst du brauchst einen 2.ten µC weil du keine Pins mehr frei hast. 
Junger Mann: Du hast 24 Pins nur mit LED verbraten!
D.h. den 2.ten µC brauchst du nur, weil du Altlasten mitschleppst. 
Denkst du nicht, das es besser wäre, diese Altlasten erst mal 
loszuwerden. Und schwupps, ist die Notwendigkeit für einen 2-ten 
Prozessor überhaupt nicht mehr vorhanden.

> Habe gerade nochmal genau gelesen, 7 Segment haben Sie geschrieben,
> ich weis nicht warum ich dabei an LCD gedacht habe. So eine 7
> Segmentanzeige wäre natürlich gescheiter...

Eigentlich nicht. Eigentlich wäre ein LCD gscheiter gewesen, wenn man 3 
Temperaturen anzeigen lassen will. Aber 3 Stück 2 stellige 7-Segment 
kann man auch so noch relativ problemlos mit nur 14 Stück µC Pins 
ansteuern. Bleiben immer noch 10 Anschlüsse gegenüber der Originallösung 
frei, die zum Schalten verwendet werden können.


Manchmal kann ich nicht anders als nur noch den Kopf zu schütteln.
Wenn ich keine Ahnung von Dieselmotoren hab, dann red ich doch nicht 
meinem Nachbar ein, ich könnte ihm einen neuen Motor in sein Auto 
einbauen und baue ihm dann einen Federmotor zum Aufziehen ein!

: Wiederhergestellt durch User
von Rocco L. (kaufparkangucker)


Lesenswert?

da ich mich gern weiter entwickeln möchte würde mich Ihr Code Schnipsel 
schon interessieren. Können Sie das kurz komentieren, vieleicht verstehe 
ich so wie man an Sachen ran gehen kann besser:
1
      p_temp =  ((PINA & 0xF0) >> 4 ) * 10;
2
      p_temp +=  (PINA & 0x0F );

ich kapier was F0 und 0F Binär ergibt. Aber was macht der 
Schiebeoperator und die 4?

von Karl H. (kbuchegg)


Lesenswert?

Einfach mal auf dem Papier durchspielen.

Der angezeigte Wert sei 46
d.h. von den LED kommt das Bitmuster

    0100 0110

und jetzt den Code durchgehen und nachvollziehen was passiert.

(dabei ist es hilfreich, die Bitmuster der Zahlen von 0 bis 9 zu kennen

   0  00000000           5 00000101
   1  00000001           6 00000110
   2  00000010           7 00000111
   3  00000011           8 00001000
   4  00000100           9 00001001

entscheidend ist, das das Bitmuster von jeweils 4 Bit (sowohl den oberen 
als auch den unteren 4 Bit) direkt den Zahlen 0 bis 9 entspricht.


PS: Ich entschuldige mich für das Pamphlet weiter oben. Ich lasse es 
trotzdem stehen, denn in der Sache an sich bin ich nach wie vor 
derselben Meinung würde es aber diplomatischer ausdrücken. Aber ich 
musste mir einfach mal Luft machen.

von Rocco L. (kaufparkangucker)


Lesenswert?

00101110  46
11110000 240
------------
00011110 286

so, habe das mal addiert, die linke 1 ist weg, wegen 8 bit Beschrenkung

jetzt schiebe ich das Ergebnis 4 Stellen nach rechts:

00000001

und multipliziere mit 10

00001010




ganz klar ist mir die Sache nicht...

von codehamster (Gast)


Lesenswert?

der & operator heisst nicht dass du addieren sollst.

wenn du das nachvollziehen willst.

1. PINA & 0xF0
2. 4 stellen nach rechts schieben
3. multipliziere mit 10

von Rocco L. (kaufparkangucker)


Lesenswert?

PINA & 0xF0 belendet also kein Bit aus, im Gegenteil zu
PINA & 0x01 wo nur das erste Beinchen abgefragt wird.

Dann wird der abgeholte Wert, z.B. 46 (00101110) vier stellen nach 
rechts geschoben und mit 10 multipliziert
00101110 jetzt wir geschoben:
00010111
00001011
00000101
00000010

mit 10 multiplizieren ergibt nun 20



der zweite Codeschnipsel macht das gleiche, nur mit den hinteren 4 Bit 
und addiert das zu der ersten Zahl, also

00000010 +        2+
----1110          14
----------       -----
   10000          16

da komm ich auf 16 :-( nicht auf 46

von DirkB (Gast)


Lesenswert?

1. Du hättest +20 rechnen (nicht+2) müssen. Aber das ist trotzdem noch 
verkehrt, denn

2. Rocco schrieb:
> 1 [ ] [ ] 10
> 2 [x] [x] 20
> 4 [x] [ ] 40
> 8 [ ] [ ] 80
>
> ^^in dem Bsp leuchten die LED mit den Werten2, 4, 20  d.h. es sind 26°C


46 ist bei deiner Darstellung demnach 01000110

01000110 & 0xf0 = 01000000
                  01000000 >> 4 = 0100 = 4
                                         4 * 10 = 40
01000110 & 0x0f = 00000110 =                       6
                                                 ----
                                                  46

von Volkmar D. (volkmar)


Lesenswert?

Wobei man sich die Und-Verknüpfung mit 0xF0 sparen kann denn durch das 
Rechts-Verschieben fallen die unteren 4 Bit sowieso weg.

Was das Einlesen der Bitmuster an PINA (und PINC sowie PIND) angeht: 
Hier sollte man die Ports zunächst in eine Variable mit einem einzigen 
Zugriff einlesen und die anschließende Auswertung anhand dieser 
Variablen durchführen. Andernfalls kann es passieren das sich der 
Eingangswert an den Ports während des sequentiellen Einlesens ändert und 
somit ein fehlerhafter Wert ermittelt wird.

von Rocco L. (kaufparkangucker)


Lesenswert?

ok, das ist nachvollziebar.
Danke für die Tips.

von Knut (Gast)


Lesenswert?

Oder:

Einer = 46%10
Zehner = 46/10

is noch einfacher (in C) als das Bitschieben zu Fuß, auch wenn das 
Verständis auf der Strecke bleibt.



Knut

von DirkB (Gast)


Lesenswert?

Aber nur, wenn du in BCD rechnest.

Beachte hier die spezielle Situation.

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.