Forum: Mikrocontroller und Digitale Elektronik AVR ADC auswerten klappt nicht


von Loginus (Gast)


Angehängte Dateien:

Lesenswert?

Guten Tag,

um das Ätzmittel in meiner Keramikschale auf richtiger Temperatur zu 
halten, habe ich die angehängte Schaltung geplant und geätzt sowie mit 
Codevision die Programme für die beiden Mikrocontroller in C 
geschrieben.

Ich möchte mit dem LM335 (Beinchen sind in Schrumpfschlauch eingepackt 
und verklebt) die Temperatur der Ätzflüssigkeit messen und bei Erreichen 
einer bestimmten Temperatur die Lastwiderstände auf der Unterseite der 
Keramikschale ein- bzw. ausschalten. Später sollen die Heizwiderstände 
statt nur ein- und ausgeschaltet zu werden mit PWM mit niedriger 
Frequenz angesteuert werden.

Mein Problem ist nun, dass mir die 7-Segment-Anzeigen immer den Wert 29 
ausgeben, unabhängig davon, ob der LM335 erwärmt oder gekühlt wird. Die 
Übertragung zwischen den Mikrocontrollern selbst funktioniert. Wenn ich 
die Temperatureinlesung auskommentiere und die Bits direkt festlege, 
werden diese auch angezeigt.

Könnt Ihr mir sagen, wo mein Fehler liegt?

Vielen Dank im Voraus für Eure Zeit.


Hier der Code von dem Attiny25:
1
 
2
/*******************************************************
3
Projekt:        Aetzwanne
4
5
Version :        ATTiny25 - 1
6
Erstellt:        20.09.2016
7
Letze Aenderung: 25.09.2016
8
9
Chip: Attiny25 mit internen 8.0 MHz
10
*******************************************************/
11
12
/// Header-Dateien///
13
#include <io.h>
14
#include <delay.h>
15
16
/// Definierungen ///
17
#define Lastwiderstaende    PORTB.0
18
#define DataOut             PORTB.1
19
#define InterruptOut        PORTB.2   
20
#define Target_low          40          //Minimale Temperatur
21
#define Target_high         45          //Maximale Temperatur
22
23
// Bandgap Voltage Reference: Off
24
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))
25
26
//// Prototypen ////
27
int read_adc ();
28
29
/// Globale Variablen ///
30
char temp = 0;
31
char temp_part = 0;
32
33
char temp_einer_bit0 = 1;
34
char temp_einer_bit1 = 0;
35
char temp_einer_bit2 = 0;
36
char temp_einer_bit3 = 0;
37
38
char temp_zehner_bit0 = 0;
39
char temp_zehner_bit1 = 1;
40
char temp_zehner_bit2 = 0;
41
char temp_zehner_bit3 = 0;
42
43
void main(void)
44
{
45
    // Crystal Oscillator division factor: 1
46
    #pragma optsize-
47
    CLKPR=(1<<CLKPCE);
48
    CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) |   
49
    (0<<CLKPS0);
50
    #ifdef _OPTIMIZE_SIZE_
51
    #pragma optsize+
52
    #endif
53
54
    // Port Initialisierung
55
    // Port B -  Bit5 = Out, Bit4 = Out, Bit3 = Out, Bit2 = Out, Bit1 = Out, Bit0 = In   
56
    DDRB=(1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
57
    PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); 
58
    
59
    //ADC Initialisierung
60
    ADMUX |= (1 << MUX0);  //ADC3 (PB3), Output vom LM335
61
    ADMUX |= (1 << MUX1); 
62
    ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);    //Frequenz: 62.5 kHz  
63
                   
64
    delay_ms(100);   //Sicherstellen, dass Attiny2313 empfangsbereit ist
65
    
66
    while (1)
67
    {      
68
        /// Temperatur einlesen ///
69
      //Temperatur in Celsius errechnen (10mV/K)
70
        temp = read_adc() * 0.00488759 * 100 - 273.15; 
71
        
72
        /// Temperatur auswerten ///
73
  //Temperatur zu niedrig? Lastwiderstaende ein
74
        if (temp < Target_low)                             
75
            Lastwiderstaende = 1;
76
                              
77
  //Temperatur zu hoch? Lastwiderstaende aus
78
        else if (temp > Target_high)                    
79
            Lastwiderstaende = 0; 
80
                         
81
        /// Temperatur zerlegen ///
82
        //Einerstelle in BCD zerlegen 
83
        temp_part = temp % 10;                        
84
        
85
        switch (temp_part)
86
        {     
87
            case 0:
88
                temp_einer_bit0 = 0;
89
                temp_einer_bit1 = 0;
90
                temp_einer_bit2 = 0;
91
                temp_einer_bit3 = 0;
92
                break; 
93
                    
94
            case 1:
95
                temp_einer_bit0 = 1;
96
                temp_einer_bit1 = 0;
97
                temp_einer_bit2 = 0;
98
                temp_einer_bit3 = 0;
99
                break;
100
                    
101
            case 2:
102
                temp_einer_bit0 = 0;
103
                temp_einer_bit1 = 1;
104
                temp_einer_bit2 = 0;
105
                temp_einer_bit3 = 0;
106
                break;   
107
                    
108
            case 3:
109
                temp_einer_bit0 = 1;
110
                temp_einer_bit1 = 1;
111
                temp_einer_bit2 = 0;
112
                temp_einer_bit3 = 0;
113
                break;
114
                    
115
            case 4:
116
                temp_einer_bit0 = 0;
117
                temp_einer_bit1 = 0;
118
                temp_einer_bit2 = 1;
119
                temp_einer_bit3 = 0;
120
                break;
121
                    
122
            case 5:
123
                temp_einer_bit0 = 1;
124
                temp_einer_bit1 = 0;
125
                temp_einer_bit2 = 1;
126
                temp_einer_bit3 = 0;
127
                break;
128
                    
129
            case 6:
130
                temp_einer_bit0 = 0;
131
                temp_einer_bit1 = 1;
132
                temp_einer_bit2 = 1;
133
                temp_einer_bit3 = 0;
134
                break;
135
                    
136
            case 7:
137
                temp_einer_bit0 = 1;
138
                temp_einer_bit1 = 1;
139
                temp_einer_bit2 = 1;
140
                temp_einer_bit3 = 0;
141
                break;
142
                    
143
            case 8:
144
                temp_einer_bit0 = 0;
145
                temp_einer_bit1 = 0;
146
                temp_einer_bit2 = 0;
147
                temp_einer_bit3 = 1;
148
                break;
149
                    
150
            case 9:
151
                temp_einer_bit0 = 1;
152
                temp_einer_bit1 = 0;
153
                temp_einer_bit2 = 0;
154
                temp_einer_bit3 = 1;
155
                break;
156
        }         
157
        
158
        //Zehnerstelle in BCD zerlegen 
159
        temp_part = (temp - temp_part) / 10;
160
        
161
        switch (temp_part)
162
        {     
163
            case 0:
164
                temp_zehner_bit0 = 0;
165
                temp_zehner_bit1 = 0;
166
                temp_zehner_bit2 = 0;
167
                temp_zehner_bit3 = 0;
168
                break; 
169
                    
170
            case 1:
171
                temp_zehner_bit0 = 1;
172
                temp_zehner_bit1 = 0;
173
                temp_zehner_bit2 = 0;
174
                temp_zehner_bit3 = 0;
175
                break;
176
                    
177
            case 2:
178
                temp_zehner_bit0 = 0;
179
                temp_zehner_bit1 = 1;
180
                temp_zehner_bit2 = 0;
181
                temp_zehner_bit3 = 0;
182
                break;   
183
                    
184
            case 3:
185
                temp_zehner_bit0 = 1;
186
                temp_zehner_bit1 = 1;
187
                temp_zehner_bit2 = 0;
188
                temp_zehner_bit3 = 0;
189
                break;
190
                    
191
            case 4:
192
                temp_zehner_bit0 = 0;
193
                temp_zehner_bit1 = 0;
194
                temp_zehner_bit2 = 1;
195
                temp_zehner_bit3 = 0;
196
                break;
197
                    
198
            case 5:
199
                temp_zehner_bit0 = 1;
200
                temp_zehner_bit1 = 0;
201
                temp_zehner_bit2 = 1;
202
                temp_zehner_bit3 = 0;
203
                break;
204
                    
205
            case 6:
206
                temp_zehner_bit0 = 0;
207
                temp_zehner_bit1 = 1;
208
                temp_zehner_bit2 = 1;
209
                temp_zehner_bit3 = 0;
210
                break;
211
                    
212
            case 7:
213
                temp_zehner_bit0 = 1;
214
                temp_zehner_bit1 = 1;
215
                temp_zehner_bit2 = 1;
216
                temp_zehner_bit3 = 0;
217
                break;
218
                    
219
            case 8:
220
                temp_zehner_bit0 = 0;
221
                temp_zehner_bit1 = 0;
222
                temp_zehner_bit2 = 0;
223
                temp_zehner_bit3 = 1;
224
                break;
225
                    
226
            case 9:
227
                temp_zehner_bit0 = 1;
228
                temp_zehner_bit1 = 0;
229
                temp_zehner_bit2 = 0;
230
                temp_zehner_bit3 = 1;
231
                break;
232
        }   
233
        
234
        /// Temperaturwert uebertragen ///
235
        //Einerstelle uebertragen
236
        DataOut = temp_einer_bit0;   //Zu uebertragendes Bit anlegen
237
        InterruptOut = 1;            //Signalisieren, dass Bit angelegt ist
238
        delay_ms(1);                 //Warten, bis Bit uebernommen ist
239
        InterruptOut = 0;
240
        delay_ms(1);       
241
        
242
        DataOut = temp_einer_bit1;  
243
        InterruptOut = 1;            
244
        delay_ms(1);                 
245
        InterruptOut = 0;
246
        delay_ms(1);
247
        
248
        DataOut = temp_einer_bit2;   
249
        InterruptOut = 1;            
250
        delay_ms(1);                
251
        InterruptOut = 0;
252
        delay_ms(1);
253
        
254
        DataOut = temp_einer_bit3;   
255
        InterruptOut = 1;            
256
        delay_ms(1);                 
257
        InterruptOut = 0;
258
        delay_ms(1);
259
                
260
        //Zehnerstelle
261
        DataOut = temp_zehner_bit0;   
262
        InterruptOut = 1;            
263
        delay_ms(1);                 
264
        InterruptOut = 0;
265
        delay_ms(1);
266
        
267
        DataOut = temp_zehner_bit1;   
268
        InterruptOut = 1;            
269
        delay_ms(1);                 
270
        InterruptOut = 0;
271
        delay_ms(1);
272
        
273
        DataOut = temp_zehner_bit2;   
274
        InterruptOut = 1;            
275
        delay_ms(1);                 
276
        InterruptOut = 0;
277
        delay_ms(1);
278
        
279
        DataOut = temp_zehner_bit3;   
280
        InterruptOut = 1;           
281
        delay_ms(1);                 
282
        InterruptOut = 0;
283
        delay_ms(1);    
284
        
285
        //Warten bis zur naechten Messung
286
        delay_ms(1000);     
287
     }  
288
}
289
290
/// Funktionen ///
291
int read_adc ()
292
{    
293
    // ADC starten
294
    ADCSRA |= (1 << ADSC);
295
296
    // Auf Ende des Messvorgangs warten
297
    while (ADCSRA & (1 << ADSC));
298
          
299
    // 10-Bit-Ergebnis zurueckgeben
300
    return (ADCH<<8 | ADCL);
301
}

Hier der Code von dem Attiny2313A:
1
/*******************************************************
2
Projekt:        Aetzwanne
3
4
Version :        ATTiny2313A - 1
5
Erstellt:        22.09.2016
6
Letze Aenderung: 25.09.2016
7
8
Chip: Attiny2313A mit internen 8.0 MHz
9
*******************************************************/
10
11
/// Header-Dateien ///
12
#include <io.h>
13
#include <delay.h>
14
15
/// Definierungen ///
16
#define InterruptIn PIND.2
17
#define DataIn      PIND.3
18
19
#define SegmentA    PORTB.7
20
#define SegmentB    PORTB.6
21
#define SegmentC    PORTB.5
22
#define SegmentD    PORTB.4
23
#define SegmentE    PORTB.3
24
#define SegmentF    PORTB.2
25
#define SegmentG    PORTB.1
26
27
#define Digit1      PORTB.0
28
#define Digit2      PORTD.6
29
30
/// Prototypen ///
31
void write_bitmuster (char temp_part);
32
 
33
/// Globale Variablen ///
34
char interruptzaehler = 0;
35
36
char temp_einer_bit0;
37
char temp_einer_bit1;
38
char temp_einer_bit2;
39
char temp_einer_bit3;
40
41
char temp_zehner_bit0;
42
char temp_zehner_bit1;
43
char temp_zehner_bit2;
44
char temp_zehner_bit3;
45
46
// External Interrupt 0 service routine
47
interrupt [EXT_INT0] void ext_int0_isr(void)
48
{
49
    switch (interruptzaehler)
50
    {
51
        case 0: 
52
            temp_einer_bit0 = DataIn;
53
            break;
54
        
55
        case 1: 
56
            temp_einer_bit1 = DataIn;
57
            break;
58
            
59
        case 2: 
60
            temp_einer_bit2 = DataIn;
61
            break;
62
        
63
        case 3: 
64
            temp_einer_bit3 = DataIn;
65
            break; 
66
            
67
        case 4: 
68
            temp_zehner_bit0 = DataIn;
69
            break; 
70
            
71
        case 5: 
72
            temp_zehner_bit1 = DataIn;
73
            break; 
74
            
75
        case 6: 
76
            temp_zehner_bit2 = DataIn;
77
            break; 
78
        
79
        case 7: 
80
            temp_zehner_bit3 = DataIn;
81
            break;   
82
    }
83
            
84
    interruptzaehler++;
85
        
86
    if (interruptzaehler == 8)
87
        interruptzaehler = 0;  
88
}
89
90
void main(void)
91
{
92
    //Lokale Varibalen
93
    char temp_part = 0;  
94
    
95
    // Crystal Oscillator division factor: 1
96
    #pragma optsize-
97
    CLKPR=(1<<CLKPCE);
98
    CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
99
    #ifdef _OPTIMIZE_SIZE_
100
    #pragma optsize+
101
    #endif
102
103
    /// Port Initialisierung ///
104
    // Port A: Bit2=Out Bit1=Out Bit0=Out 
105
    DDRA=(1<<DDA2) | (1<<DDA1) | (1<<DDA0);
106
    PORTA=(0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
107
108
    // Port B: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out 
109
    DDRB=(1<<DDB7) | (1<<DDB6) | (1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
110
    PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
111
112
    // Port D: Bit6=Out Bit5=Out Bit4=Out Bit3=In Bit2=In Bit1=Out Bit0=Out 
113
    DDRD=(1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (0<<DDD3) | (0<<DDD2) | (1<<DDD1) | (1<<DDD0);
114
    PORTD=(0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); 
115
    
116
    // Externe Interrupts Initialisierung: INT0: ein
117
    MCUCR=(0<<ISC11) | (0<<ISC10) | (1<<ISC01) | (1<<ISC00);
118
    GIMSK=(0<<INT1) | (1<<INT0) | (0<<PCIE0) | (0<<PCIE2) | (0<<PCIE1);
119
    GIFR=(0<<INTF1) | (1<<INTF0) | (0<<PCIF0) | (0<<PCIF2) | (0<<PCIF1);
120
121
    #asm("sei")
122
    
123
    while (1)
124
    {            
125
        //Einerstelle ausrechnen und Multiplexen 
126
        temp_part = temp_einer_bit0 + temp_einer_bit1 * 2 + temp_einer_bit2 * 4 + temp_einer_bit3 * 8;
127
        write_bitmuster (temp_part); 
128
        Digit2 = 1;
129
        delay_ms (1); 
130
        Digit2 = 0;
131
        
132
        temp_part = temp_zehner_bit0 + temp_zehner_bit1 * 2 + temp_zehner_bit2 * 4 + temp_zehner_bit3 * 8;
133
        write_bitmuster (temp_part);  
134
        Digit1 = 1;
135
        delay_ms (1); 
136
        Digit1 = 0;
137
    }
138
}
139
140
void write_bitmuster (char temp_part)
141
{
142
    switch (temp_part)
143
    { 
144
        case 0:     
145
            SegmentA = 1;
146
            SegmentB = 1;
147
            SegmentC = 1;
148
            SegmentD = 1;
149
            SegmentE = 1;
150
            SegmentF = 1;
151
            SegmentG = 0;   
152
            break;   
153
                
154
        case 1:     
155
            SegmentA = 0;
156
            SegmentB = 1;
157
            SegmentC = 1;
158
            SegmentD = 0;
159
            SegmentE = 0;
160
            SegmentF = 0;
161
            SegmentG = 0; 
162
            break;
163
                
164
        case 2:     
165
            SegmentA = 1;
166
            SegmentB = 1;
167
            SegmentC = 0;
168
            SegmentD = 1;
169
            SegmentE = 1;
170
            SegmentF = 0;
171
            SegmentG = 1; 
172
            break;
173
                
174
        case 3:     
175
            SegmentA = 1;
176
            SegmentB = 1;
177
            SegmentC = 1;
178
            SegmentD = 1;
179
            SegmentE = 0;
180
            SegmentF = 0;
181
            SegmentG = 1;
182
            break;
183
                
184
        case 4:     
185
            SegmentA = 0;
186
            SegmentB = 1;
187
            SegmentC = 1;
188
            SegmentD = 0;
189
            SegmentE = 0;
190
            SegmentF = 1;
191
            SegmentG = 1;
192
            break;
193
                
194
        case 5:     
195
            SegmentA = 1;
196
            SegmentB = 0;
197
            SegmentC = 1;
198
            SegmentD = 1;
199
            SegmentE = 0;
200
            SegmentF = 1;
201
            SegmentG = 1;
202
            break;
203
                
204
        case 6:     
205
            SegmentA = 1;
206
            SegmentB = 0;
207
            SegmentC = 1;
208
            SegmentD = 1;
209
            SegmentE = 1;
210
            SegmentF = 1;
211
            SegmentG = 1;
212
            break;
213
                
214
        case 7:     
215
            SegmentA = 1;
216
            SegmentB = 1;
217
            SegmentC = 1;
218
            SegmentD = 0;
219
            SegmentE = 0;
220
            SegmentF = 0;
221
            SegmentG = 0; 
222
            break;
223
                
224
        case 8:     
225
            SegmentA = 1;
226
            SegmentB = 1;
227
            SegmentC = 1;
228
            SegmentD = 1;
229
            SegmentE = 1;
230
            SegmentF = 1;
231
            SegmentG = 1;   
232
            break;
233
                
234
        case 9:     
235
            SegmentA = 1;
236
            SegmentB = 1;
237
            SegmentC = 1;
238
            SegmentD = 1;
239
            SegmentE = 0;
240
            SegmentF = 1;
241
            SegmentG = 1;   
242
            break;
243
    }
244
}

von Arduinoquäler (Gast)


Lesenswert?

>>Wichtige Regeln - erst lesen, dann posten!
>>
>>    Groß- und Kleinschreibung verwenden
>>    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

-------------------------^^^^^^^^^^^^^^^^^^^^^^^^

von Karl M. (Gast)


Lesenswert?

Hallo,

zur Schönheit, das Ergebnis ohne Vorzeichen ist:

uint16_t read_adc(void);

Dann schaue dir bitte im Datenblatt die Auflistung unter:
17.13.2 ADCSRA – ADC Control and Status Register A
an.

Speziell:
Bits 2:0 – ADPS[2:0]: ADC Prescaler Select Bits
Table 17-5. ADC Prescaler Selections

Bei 8MHz würde ich einen 1/64 ADC-Vorteiler wählen und bei der Messung 
immer auch eine Mittelwertbildung in betracht ziehen.

Z.B. über 4 Messwerte.

Dann gibt es noch das schöne Register:
DIDR0 – Digital Input Disable Register 0

Dies verwende ich bei Nutzung des ADC immer.

Dann setze ich noch im:
ACSR – Analog Comparator Control and Status Register
ACSR.ACD = 1;

von Loginus (Gast)


Angehängte Dateien:

Lesenswert?

Wäre sinnvoll gewesen :/ Hier der Code als Textdatei. Vielleicht kann 
ein netter Mod ja den Code im ersten Post löschen.

von Arduinoquäler (Gast)


Lesenswert?

Loginus schrieb:
> Hier der Code als Textdatei.

Ja aber der Automatismus zum korrekten Anzeigen von Dateien
möchte gerne  *.c haben.

von Thomas E. (thomase)


Lesenswert?

Loginus schrieb:
> return (ADCH<<8 | ADCL);

ADCL muß vor ADCH ausgelesen werden. Kannst du das hier gewährleisten?

Also überlasse es dem Compiler, dafür zu sorgen, daß es richtig gemacht 
wird.
1
return ADC;

: Bearbeitet durch User
von Loginus (Gast)


Angehängte Dateien:

Lesenswert?

Danke für Eure Antworten. Der neue Code ist angehängt.

Wenn ich mit einem Netzteil Spannung an X6 anlege, zeigt die 
7-Segment-Anzeige etwa 10 Grad weniger an, als ich erwarte. Lege ich 
beispielsweise 3,5V an, erwarte ich 86 Grad, angezeigt werden aber 76 
Grad. Da die Differenz aber immer gleich bleibt, kann ich das durch die 
Software ausgleichen.

Nun aber zum Problem: Wenn ich den LM335 anschließe (X5 und X6 
verbinden, Plus an X6, Masse an X7, ADJ-Pin bleibt frei), messe ich über 
dem Widerstand R2 5V und habe dann logischerweise 0V am ADC Pin 
anliegen.

Ich habe dann erneut das Netzteil angeschlossen und die Stromaufnahme 
gemessen: 80mA fließen, wenn ich das Netzteil an X6 und X7 anschließen.
Nur warum?

von Jakob (Gast)


Lesenswert?

Wenn 80 mA von (+) in einen Port-Pin fließen, ist er wohl als
Ausgang (Low) geschaltet.

Dafür sind die DDR-Bits zuständig, falls der Port-Pin nicht schon
durch vorherige missglückte Versuche einen Schluss nach Masse hat...

Der ADC misst dann den Spannungsabfall am Low-Side-Transistor.

von Loginus (Gast)


Lesenswert?

Jap, das war es. Nun läuft alles. Hatte beim Schaltplan den Portpin 
geändert und es auch in den Definierungen geändert aber die Änderung bei 
der Port Initialisierung vergessen. Mein armer Attiny. Nochmals danke an 
alle!

von Duden (Gast)


Lesenswert?

Loginus schrieb:
> Definierungen

herrlich ...

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.