Forum: Mikrocontroller und Digitale Elektronik Mittelwertbildung von Temperatur


von Dieter B. (Gast)


Lesenswert?

Moin Moin ^^

Ich bin dabei eine Temperaturanzeige zu programmieren. Das klappt soweit 
auch alles. Was mir nicht gefällt, ist das der Wert sich viel zu oft im 
Display ( 7- Segment) ändert. Dies habe ich versuch mit hilfe einer 
"Mittelwertbildung" zu unterdrücken. Der Sensor braucht ca. eine Sekunde 
bis er ein neues Ergebniss liefern kann. In meine ISR (wo ich den Wert 
abfrage vom DS1621 & umrechne) springe ich ca. jede 2 Sekunden rein. 
Wenn ich den Wert jetzt 16 x auf summiere, müsste es doch eigentlich "32 
Sekunden" dauern bis ich meinen neuen Wert auf dem Display sehen kann 
oder ?
Aktuell ändert sich der Wert aber fast jede 5 Sekunden.

Hat jemand eine Idee, sieht was ich falsch mache ?
1
#define F_CPU 8000000
2
3
#define DS1621_Write  0x9E
4
#define DS1621_Read   0x9F
5
6
#define Segment_1_AN PORTB &= ~(1<<PB3)
7
#define Segment_1_AUS PORTB |= (1<<PB3)
8
9
#define Segment_2_AN PORTB &= ~(1<<PB2)
10
#define Segment_2_AUS PORTB |= (1<<PB2)
11
12
#define Segment_3_AN PORTB &= ~(1<<PB1)
13
#define Segment_3_AUS PORTB |= (1<<PB1)
14
15
#define Segment_4_AN PORTB &= ~(1<<PB0)
16
#define Segment_4_AUS PORTB |= (1<<PB0)
17
18
#define Mittelwert 16
19
20
int Zahlen[13]= {
21
          0b00111111, // 0
22
          0b00000110, // 1
23
          0b01011011, // 2
24
          0b01001111, // 3
25
          0b01100110, // 4
26
          0b01101101, // 5
27
          0b01111101, // 6
28
          0b00100111, // 7
29
          0b01111111, // 8
30
          0b01101111, // 9
31
            0b01100011, // *
32
            0b01000000, // Minus
33
          0b00000000  // alle Aus
34
        };
35
36
#include <avr/io.h>
37
#include <util/delay.h>
38
#include "i2cmaster.h"
39
#include <avr/interrupt.h>
40
41
volatile unsigned char  TempH, TempL = 0;
42
volatile int16_t    Wert, Summe, Ergebnis;
43
volatile int8_t      TempAbs = 0;
44
volatile uint8_t    IsNegative, I, Done;
45
 
46
47
int main(void)
48
{
49
  DDRB |= ((1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3));
50
  DDRD |= ((1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6));
51
  
52
    OCR1A   = 15624;            // Legt den Wert ZUM Überlaufes fest ( ca. jede 2 Sec. )
53
  TCCR1A |= (1<<WGM11);          // CTC Modus
54
    TIMSK  |= (1<<OCIE1A);          // Compare Match Interrupt enable
55
    TCCR1B |= ((1<<CS12) | (1<<CS10));    // Prescaler auf 1024 setzen (F_CPU/1024)
56
  sei();
57
  
58
59
  i2c_init();
60
  
61
  i2c_start(DS1621_Write); // Starten der Umwandlung (Messung)
62
  i2c_write(0xEE);
63
  i2c_stop();
64
       
65
  i2c_start(DS1621_Write); // Starten der Auslesung (Temperaturregister)
66
  i2c_write(0xAA);
67
  i2c_stop();
68
69
  Segment_1_AUS; Segment_2_AUS; Segment_3_AUS; Segment_4_AUS;
70
  
71
while (1)
72
{
73
  
74
  Segment_1_AN;
75
  PORTD = Zahlen[Wert & 0x000F];
76
  _delay_ms(4);
77
  Segment_1_AUS;
78
79
  Segment_2_AN;
80
  PORTD = Zahlen[(Wert & 0x00F0) >> 4];
81
  _delay_ms(4);
82
  Segment_2_AUS;
83
  
84
  Segment_3_AN;
85
  PORTD = Zahlen[(Wert & 0x0F00) >> 8];
86
  _delay_ms(4);
87
  Segment_3_AUS;
88
  
89
  Segment_4_AN;
90
  PORTD = Zahlen[(Wert & 0xF000) >> 12];
91
  _delay_ms(4);
92
  Segment_4_AUS;
93
94
} // Ende While
95
} // Ende Main
96
97
ISR (TIMER1_COMPA_vect)
98
{
99
100
  if (I <= Mittelwert)
101
  {  
102
    I++;  
103
    i2c_start(DS1621_Read);
104
    TempH = i2c_readAck();
105
    TempL = i2c_readNak();
106
    i2c_stop();
107
108
/*    if ((TempL & 0b10000000) == (0b10000000))
109
    {
110
      TempH++;
111
    }
112
*/      
113
      Summe += TempH;
114
    
115
  }
116
117
118
  if (I == Mittelwert)
119
  {
120
    Ergebnis = Summe / Mittelwert;
121
    
122
    I = 0;
123
    Summe = 0;
124
    
125
    
126
      if (Ergebnis < 0)
127
      {
128
        IsNegative = 1;
129
        TempAbs = ~(Ergebnis) + 1;
130
      }
131
      else
132
      {
133
        IsNegative = 0;
134
        TempAbs = Ergebnis;
135
      }
136
137
      Wert = ((((TempAbs / 10) % 10) << 8) | ((TempAbs % 10) << 4) | (0x0A)); // Wert entspricht dem "Wert" aus dem Array (Zahlen)
138
139
      if (TempAbs == 0)
140
      {
141
        Wert = 0xCC0A;
142
      }
143
      else if (TempAbs >= 100)
144
      {
145
        Wert = (Wert | 0x1000);
146
      }
147
      else if (TempAbs < 10)
148
      {
149
        Wert = (Wert | 0xCC00);
150
      }
151
      else if (TempAbs < 100)
152
      {
153
        Wert = (Wert | 0xC000);
154
      }
155
156
      if (IsNegative == 1)
157
      {
158
        Wert = (Wert & 0x0FFF) | (0xB000);
159
      }
160
    
161
    
162
  }
163
  
164
165
  
166
  
167
}// Ende ISR

von Gerald G. (gerald_g)


Lesenswert?

Ocr1a hat normalerweise 8 bit. 15624 ist etwas mehr. Für Interrupts im 
Sekunden Bereich nehme ich normal einfach den watchdog

von Dieter B. (Gast)


Lesenswert?

Gerald G. schrieb:
> Ocr1a hat normalerweise 8 bit. 15624 ist etwas mehr. Für
> Interrupts im
> Sekunden Bereich nehme ich normal einfach den watchdog

Bei nem TINY2313 ist das doch nen 16 Bit Register ?!

von Timmo H. (masterfx)


Lesenswert?

Ich habe mir deinen Code jetzt nicht wirklich angesehen.
Aber ich würde da einfach so eine Art Tiefpass drüber machen...
1
#define FILTER_SHIFT  6
2
3
filtered_temp = filtered_temp - (filtered_temp >> FILTER_SHIFT) + aktuelle_temp;  
4
ausgabe_temp = filtered_temp >> FILTER_SHIFT;

von Gerald G. (gerald_g)


Lesenswert?

Dieter B. schrieb:
> Bei nem TINY2313 ist das doch nen 16 Bit Register ?!

Ja, da hast du recht

Dann toggle doch einfach bei jedem isr Aufruf eine deiner Segmente.

von Dieter B. (Gast)


Lesenswert?

Gerald G. schrieb:
> Dieter B. schrieb:
>> Bei nem TINY2313 ist das doch nen 16 Bit Register ?!
>
> Ja, da hast du recht
>
> Dann toggle doch einfach bei jedem isr Aufruf eine deiner Segmente.

What soll mir das bringen ?

von Gerald G. (gerald_g)


Lesenswert?

So debugge ich meinen code.
Du willst wissen warum die Aktualisierung nur 5 Sekunden dauert anstatt 
30? Schaue wie schnell die isr aufgerufen wird. Passt das? Dann pack das 
togglen in die if's rein. Passt das? ...
Das ist ne Sache von Minuten da so einen toggle Befehl an verschiedenen 
stellen nacheinander einzufügen.

von holger (Gast)


Lesenswert?

>  TCCR1A |= (1<<WGM11);          // CTC Modus

Der Kommentar ist falsch. WGM11 auf 1 ist kein CTC.

von Dieter B. (Gast)


Lesenswert?

holger schrieb:
>>  TCCR1A |= (1<<WGM11);          // CTC Modus
>
> Der Kommentar ist falsch. WGM11 auf 1 ist kein CTC.

Ahh,

Das müsste dann der WaveGeneratorMode sein oder ?
Welche Bits sind denn für den CTC zuständig ?! Finde die gerade nicht

von holger (Gast)


Lesenswert?

>Welche Bits sind denn für den CTC zuständig ?! Finde die gerade nicht

Die Tabelle im Datenblatt ist so gross wie ein LKW.
Die kann man nicht übersehen.

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.