C Temperaturanzeige (DS1621) auf 4 - Digit 7-Segmentanzeige

Währe das eine "gute" Möglichkeit den Wert ruhiger zu bekommen?
 
Hmm... wenn der Sensor bei -40°C im Eisfach liegt (gültiger Wert), Du den jetzt kochst, und gerade bei 100°C das nächste Sample-Fenster ist (gültiger Wert). Du legst den wieder zurück ins Eisfach, er hat beim nächsten sample wieder -40°C, und bleibt da stabil...

Da der Wert aber ungültig bleibt (vorletzter angezeigter Wert), wirst Du auf Deiner 100°C-Anzeige sitzenbleiben.

Hin und her schwankende Werte werden ignoriert - egal wie groß Amplitude und Frequenz sind.

Hast Du den Sensor inzwischen mal gegen Zugluft und Licht isoliert, und die Sample- und Anzeigefrequenz erhöht (waren ja vorher 6s oder so)?
Ändert sich dann was?

(wegen Licht: in irgend'nem Datenblatt stand mal der Heinweis, daß die Auflösung des ADCs (oder so) ausreichen würde, in einen Raum eintretende Personen über einen schwarz angemalten PT1000 zu detektieren (oder so ähnlich). Ok, das ist jetzt nicht Dein Sensor, aber Wind und Sonne können bei 'nem frei liegenden Sensor erheblich was ausmachen...)

Datenblatt LTC2400 schrieb:
Variation in the self-heating of the RTD element due to air currents is the most difficult challenge. If the RTD is mounted in a sealed glass enclosure and painted black, the LTC2400 can detect the arrival of a person in the room. This is also true of infrared thermocouple sensors (thermopiles) that can also be used directly with the LTC2400.
Quelle
 
In meiner Timer ISR erhöhe ich jetzt jede "10 mS" den Wert einer Variable. Hat die Variable den Wert "x" erreicht, führe ich die Messung aus.
Das sind ca. jede 2 Minuten. Das klappt jetzt. Der Sensor ist halt sehr empfindlich.

Was ich aber gerne noch mal wissen würde, wie ich den Mittelwert in meinem Programm ermitteln kann, ich tuh mir damit noch etwas schwer!?
Wie ich das ausrechen muss, weiß ich! Das um zu setzen im Programm ist mein Problem :(
 
Eigentlich solltest Du das Schwanken ebenso haben, Du nimmst es halt nur weniger wahr... außer wenn Du durch die gewählte verringerte Sample-Frequenz zufällig immer dann mißt, wenn der Wert dem letzten entspricht.

Zur Mittelwertbildung: das ist halt ein weites Feld

Du kannst den Mittelwert aus n Werten bilden, indem Du die aufaddierst, und anschließend das Ergebnis durch n teilst. Effektiv benötigst Du dann auch die nfache Zeit für jede Ausgabe und die Variable, die die Summe aufnehmen soll, muß entsprechend das n-fache eines Einzelwertes aufnehmen können.
Das mit der nfachen Zeit könnte man umgehen, indem man sich die letzten n Werte "merkt" und über diesen den Mittelwert bildet - also nach jeder neuen Messung den ältesten verwirft, und über alle gemerkten mittelt. Erfordert also ein zusätzlichen Speicher (Array) für n Werte, und eine Zeigervariable, die immer auf den, derzeit ältesten Wert zeigt. Die eigentliche Mittellung bleibt gleich.
Bleiben wir mal bei der ersten Methode:
Bereits der 2te Wert sprengt den 8bit-Raum, Du mußt also eh ein weiteres Byte breite vorsehen. Mit diesen 8 bits könntest Du theoretisch 256 Deiner Werte mitteln. Sinnigerweise sollte man das 9te bit (aus dem TempL) miteinbeziehen.
Du müßtest dazu also die 9 Bits, die der Sensor liefert in einer 16bit-Integer rechtsorientieren. Ob und wie das schnell in C geht, kann ich Dir nicht sagen. In ASM gibts hie ein paar elegante Tricks, die das mit wenig bit-Geschubse schaffen
(gelesenes lowByte linksschieben, das etwaige halbKelvinBit landet im Carry, gelesene HighByte wird als Ergebnis-lowByte abgelegt. Dann einmal nach links gerollt (Carry landet im LSB). Fällt dabei 'ne 1 ins Carry, war also vorher das MSB 'ne 1, war also die Zahl Negativ - dann wird das Ergebnis-HighByte mit 0xFF beschrieben (vorher war es 0). Kommt wie beim 7fachen rechtsschieben (Arithmetisch über 2 Register also 14mal schieben) mit 2 Registern aus, sollte aber etwa doppelt so schnell sein...).

Wenn Du Deine n Werte zusammenaddiert hast wertest Du das Vorzeichen wie gehabt aus - die Sache mit dem HalbKelvinBit entfällt, da das ja bereits in den 9bit-Zahlen mitintegriert wurde. Bei der Division wäre wegen dem 9ten Bit durch 2*n zu teilen. Bei geeignetter Wahl von n kann man hier auch wieder schieben statt teilen. Strenggenommen kann man hier sogar auf die Division verzichten, und das beim Dezimalstellenzerhacken miteinbeziehen - allerdings müßten die Divisionen dort dann dort jeweils 16 bit breit sein, was mehr Rechenaufwand sein sollte - Du merkst davon natürlich in C nichts - sieht da sogar eleganter aus...
klar kann man das da optimieren, aber dann paßt es weniger zur Hochsprache...
 
Das hört sich ja erstmal alles recht kompliziert an.
Wie würdest du denn eine Temperatur messen ? KTY ?! Digital ?!
 
Hi,

Wie würdest du denn eine Temperatur messen ? KTY ?! Digital ?!

ich würde ne Temperatur (wenn es irgendwie geht) mit nem DS18S20 messen.
Analog (also zB KTY) würde ich nur messen wenn die zu messende Temperatur außerhalb des "Überlebensbereiches" eines DS18S20 wäre. Dann kann nen KTY aber auch nix mehr ausrichten. Dann benötigt man nen PT100/PT1000/Ni1000 oder nen Thermoelement.

Gruß
Dino
 
Hi,



ich würde ne Temperatur (wenn es irgendwie geht) mit nem DS18S20 messen.
Analog (also zB KTY) würde ich nur messen wenn die zu messende Temperatur außerhalb des "Überlebensbereiches" eines DS18S20 wäre. Dann kann nen KTY aber auch nix mehr ausrichten. Dann benötigt man nen PT100/PT1000/Ni1000 oder nen Thermoelement.

Gruß
Dino

Hast du schon Erfahrung mit dem Sensor gemacht ? Das ist ein "1 Wire" Bus... Ist der komplizierter als der I2C Bus ?
Das Auswerden und umrechnen sollte ja annähernd gleich sein oder ?
 
Hmm... wenn der Sensor bei -40°C im Eisfach liegt (gültiger Wert), Du den jetzt kochst, und gerade bei 100°C das nächste Sample-Fenster ist (gültiger Wert). Du legst den wieder zurück ins Eisfach, er hat beim nächsten sample wieder -40°C, und bleibt da stabil...

Da der Wert aber ungültig bleibt (vorletzter angezeigter Wert), wirst Du auf Deiner 100°C-Anzeige sitzenbleiben.
:trytofly: Also das must Du mir mal vormachen, wie man die Temperatur innerhalb von Sekundenbruchteilen um 140°C hebt und sie anschließend wieder auf genau den selben Wert senkt.
 
Naja, war jetzt vielleicht etwas überspitzt dargestellt... andererseits sind Deine Bruchteile ja auch 6 Sekunden lang...

Hmm... soll ich mal recherchieren was für Rampen mein Bruder mit dem Nanokalorimeter so fährt, bei 'ner Messung?
 
Naja, war jetzt vielleicht etwas überspitzt dargestellt... andererseits sind Deine Bruchteile ja auch 6 Sekunden lang...
#55: 0,75s
Hmm... soll ich mal recherchieren was für Rampen mein Bruder mit dem Nanokalorimeter so fährt, bei 'ner Messung?
Das wäre sicher interessant. Dann erzähl uns aber auch in welchen Größenordungen da gearbeitet wird und wie man da noch Temperaturen mißt.
 
Hallo zusammen,

ich habe leider nicht so viel Zeit alles durchzulesen, das Thema ist ja inzwischen schon riesen groß. Wenn es aber einfach nur um den Mittelwert geht, ist das doch recht einfach zu lösen.

Nach #64 von LotadaC, könnte es in C so aussehen:

Code:
    uint16_t summe, ergebnis;
    uint8_t TempH, TempL;
    uint8_t i;
    
    summe = 0;
    for (i=0; i<16; i++)
    {
        [COLOR=#000080]// hier die Messung machen[/COLOR]
        summe += ((uint16_t)TempH<<1) | (TempL>>7);
    }
    ergebnis = summe>>4;
    // 9 Bits: TempH Bits 8..1 und TempL Bit 0

Ich nehme hier an, dass in TempH MSB ist und in TempL Bit7 für das niederwertigste Bit genutzt wird (ich hoffe ich habe es richtig verstanden).

Im Ergebnis befinden sich die gesamten 9 bit.

Es wurde irgendwo schon erwähnt, dass es günstiger ist 2^n Werte zu summieren, dann ist nämlich die Division einfach durch rechts schieben der Summe zu erledigen. Im oberen Beispiel summiere ich 16 Werte und schiebe 4 Bit nach rechts, teile also dadurch durch 16.

Wenn die Messung zu lange dauert, könnte man auch mit einem FiFo arbeiten, das hatte ja LotadaC auch schon vorgeschlagen.

Vielleicht hilft der obige Code ja schon etwas weiter.

Dirk :ciao:
 
LotadaC / Dirk / TommyB...

Vielen lieben dank für eure Zeitintensive Erklärung ;) Bei euch lernt man echt ne menge ;)! Danke
 
Hallo zusammen,

ich habe leider nicht so viel Zeit alles durchzulesen, das Thema ist ja inzwischen schon riesen groß. Wenn es aber einfach nur um den Mittelwert geht, ist das doch recht einfach zu lösen.

Nach #64 von LotadaC, könnte es in C so aussehen:

Code:
    uint16_t summe, ergebnis;
    uint8_t TempH, TempL;
    uint8_t i;
    
    summe = 0;
    for (i=0; i<16; i++)
    {
        [COLOR=#000080]// hier die Messung machen[/COLOR]
       [COLOR=#ff0000][B] summe += ((uint16_t)TempH<<1) | (TempL>>7);[/B][/COLOR]
    }
    ergebnis = summe>>4;
    // 9 Bits: TempH Bits 8..1 und TempL Bit 0

Ich nehme hier an, dass in TempH MSB ist und in TempL Bit7 für das niederwertigste Bit genutzt wird (ich hoffe ich habe es richtig verstanden).

Im Ergebnis befinden sich die gesamten 9 bit.

Es wurde irgendwo schon erwähnt, dass es günstiger ist 2^n Werte zu summieren, dann ist nämlich die Division einfach durch rechts schieben der Summe zu erledigen. Im oberen Beispiel summiere ich 16 Werte und schiebe 4 Bit nach rechts, teile also dadurch durch 16.

Wenn die Messung zu lange dauert, könnte man auch mit einem FiFo arbeiten, das hatte ja LotadaC auch schon vorgeschlagen.

Vielleicht hilft der obige Code ja schon etwas weiter.

Dirk :ciao:


Dirk, Wieso wird da noch mal der Typ mit angegeben ?! Was bezweckt das ?
 
Aber jedes mal wenn ich die ISR aufrufe, wird der Wert doch aktualisiert oder ?

Code:
ISR (TIMER0_COMPA_vect)
{
        
        Summe = 0;
        
        for (I = 0 ; I < 16 ; I++)
        {
            i2c_start(DS1621_Read);
            TempH = i2c_readAck();
            TempL = i2c_readNak();
            i2c_stop();
            
            Summe += ((uint16_t)TempH << 1 | (TempL >> 7));
        }
        
            Ergebniss = Summe >> 4;

    
        Temp = Ergebniss;
    
        if (Temp < 0)
        {
            IsNegative = 1;
            TempAbs = ~(Temp) + 1;
        }
        else
        {
            IsNegative = 0;
            TempAbs = Temp;
        }
        
        if ((TempL & 0b10000000) == (0b10000000))
        {
            TempAbs = TempAbs + 1;
        }
            
        Wert = ((((TempAbs / 10) % 10) << 8) | ((TempAbs % 10) << 4) | (0x0A)); // Wert entspricht dem "Wert" aus dem Array (Zahlen)
    
        if (TempAbs == 0)
        {
            Wert = 0xCC0A;
        }
        else if (TempAbs >= 100)
        {
            Wert = (Wert | 0x1000);
        }
        else if (TempAbs < 10)
        {
            Wert = (Wert | 0xCC00);
        }
        else if (TempAbs < 100)
        {
            Wert = (Wert | 0xC000);
        }
            
        if (IsNegative == 1)
        {
            Wert = (Wert & 0x0FFF) | (0xB000);
        }
    

}
 
Dirk, Wieso wird da noch mal der Typ mit angegeben ?! Was bezweckt das ?

Wenn TempH uint8_t ist und ich den Ihnalt um ein Bit nach links schiebe, dann geht das höchstwertige Bit7 verloren. Mit (uint16_t)TempH teilst du dem Compiler mit, dass er TempH einfach als uint16_t behandeln soll, dann passiert das nicht. Bei TempL ist es nicht notwendig, da die Bits 6..0 eh egal sind und auch wegfallen sollen. (Das aber alles unter dem Vorbehalt, dass die Daten wirklich so in TempH und TempL vorhanden sind, wie ich in meinem Beitrag zuvor angenommen habe ;-)

Dirk, du bist echt der beste! Das du dir dafür immer Zeit nimmst und den "ahnunglosen" hilfst! Finde ich echt klasse.
Aber auch alle anderen vielen lieben dank für die große Hilfe :)
Ich denke hier hat vor allem LotadaC viel gehofen und Zeit investiert.

Dirk :ciao:
 
Aber jedes mal wenn ich die ISR aufrufe, wird der Wert doch aktualisiert oder ?
Es werden 16 Werte vom Sensor gelesen. Sowas würde ich nicht in einer TimerISR machen, ich würde es lieber ins Hauptprogramm setzen.

EDIT: An deinem Code sehe ich gerade, es gibt noch ein Vorzeichen. Dann darf man sicherlich nicht einfach summieren uint8_t summieren, das Vorzeichen muss berücksichtigt werden.

Um mir das näher anzusehen, habe ich allerdings im Moment leider keine Zeit. :-(
 
Es werden 16 Werte vom Sensor gelesen. Sowas würde ich nicht in einer TimerISR machen, ich würde es lieber ins Hauptprogramm setzen.

Das habe ich nur gemacht dabei meine Anzeige (Multilplex) ordentlich funktioniert.
So wie die ISR da jetzt steht... Würde doch jedes mal wenn er in die ISR läuft, den Wert auf dem Display aktualsieren oder nicht ? Dann währe doch der "Mittelwert" ohne Funktion oder ?
 
Beachte mein EDIT im Beitrag zuvor.

Ich sehe in der TimerISR keine Multiplexfunktion für ein Display. Ich würde es so machen, dass die Temperatur im Hauptprogramm ermittelt wird. Die TimerISR für das Displaymultiplex holt sich dann einfach nur das Ergebnis vom Hauptprogramm. Dann ist es auch nicht so schlimm, wenn die Messung etwas länger dauert. ;-)
 
Hi,

Hast du schon Erfahrung mit dem Sensor gemacht ? Das ist ein "1 Wire" Bus... Ist der komplizierter als der I2C Bus ?
Das Auswerden und umrechnen sollte ja annähernd gleich sein oder ?

ich setze den eigentlich recht gerne ein. Er ist relativ klein (SOT92-Gehäuse so wie nen BC547 oder andere Transistoren). Außerdem benötigt man nur einen Portpin für einen Bus mit mehreren Sensoren dran. Die Auswertung ist eigentlich recht einfach und es gibt überall genügend Beispiele wie man es umsetzen kann. Außerdem kann man die Sensoren über Phantomspeisung versorgen.

1Wire hat gegenüber I2C nur einen Nachteil. Das Busprotokoll wird nicht über nen Hardwareteil (TWI-Modul) im Atmel umgesetzt was auch noch Interruptfähig ist sondern muß komplett in Software umgesetzt werden. Dadurch verhagelt einem ein Interrupt (zB von nem Timer) das gesamte Busprotokoll und die Kommunikation bricht zusammen. Man muß also ein wenig nachdenken wie man das in ein Programm reinbaut das auch Timer benötigt.

Wo ich eher von 1Wire absehen würde ist zB bei ...
- Multiplexanzeigen (zB mit 7Segm-Displays)
- Software-PWM
- ...
... also bei allen Programmen die schnelle und oft auftretende Interrupts haben und es evtl dann auch noch auf exaktes Timing ankommt. Dann sollte man eher auf nen I2C-Sensor ausweichen. Es gibt aber auch I2C-1Wire-Bridges mit denen man vom Atmel mit I2C ansteuert und wo dann der 1Wire-Bus an der Bridge liegt. Hab ich zwar hier rumliegen (mal mitbestellt) aber noch nicht ausprobiert. Die würden dann das Softwareprotokoll wieder in Richtung Hardware verschieben was Timingprobleme verhindern sollte.

Gruß
Dino
 
Jetzt zeigt er mir einen viel zu hohen Wert an...
Raumtemperatur müssen 22°C sein und er zeigt mir jetzt nach dem schieben 34°C an
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)