Middelen code voor analoge ingang

blackdog

Golden Member

Hi,

Voor de Reisreferentie wil ik een hoge resolutie temperatuur meting hebbem.
Dit heb ik uiteindelijk voor elkaar door een TMP37 sensor welke 20mV/C als output geeft en een bepaalde instelling van mijn microcontroler.
Deze microcontroler welke een Adafruit Adalogger M0 en deze bevat een SAM21 chip.

De 1V interne referentie maakt wel dat ik niet verder dan 50C kan meten, wat verder niet van belang is omdat de oven rond de 42C staat ingesteld.

Eert even mijn vraag en de code waar het nu over gaat.
Om voldoende ruisonderdrukking te krijgen wordt hier een waarde van 1024 gebruikt.
Dit werkt verder goed.

Als de Referentie in werking is en dus de processor uit de slaapstand is gehaald, dan is middelen over 1000 metingen geen enkel probleem.
Maar wat gebeurd er als de processor in de slaapstand gaat en zeg 1x per 10 minuten een batterij meting doen en een temperatuur meting dit naar de micro SD gecopieerd wordt.
Blijft de waarde van de "filteraccumulator" behouden?
Als deze opnieuw moet worden opgebouwd kan dit 15 a 20 seconde duren voor hij weer stabiel is.
En dat is wat lang en kost daardoor te veel energie uit de batterijen.

c code:


// https://www.felixdonkers.nl/2012/07/smart-sensor-filtering/
//
// Code voor het uitlezen van een TMP37 temperatuur sensor met een hoge resolutie en lage ruis

const int N = 1024;                           // aantal te middelen meetwaardes
int meetwaardes[N];                           // opslag van individuele meetwaardes
int filteraccumulator = 0;                    // optelsom van alle individuele meetwaardes
int i = 0;                                    // meetwaardeteller
int filterwaarde = 0;

unsigned long tempReading;
float adcTemp;
float uref = 1;
float tempA;
float temp;


void setup() {
  
Serial.begin(9600);                           // open a serial connection

analogReference(AR_INTERNAL1V0);              // Gebruik de interne 1V ADC referentie 
analogReadResolution(16);                     // Gebruik de 16 Bit resolutie
}


void loop(){
  
  filteraccumulator -= meetwaardes[i];           // vergeet oudste meetwaarde
  meetwaardes[i] = analogRead(7);                // Bewaar nieuwe meetwaarde
  filteraccumulator += meetwaardes[i];           // Accumuleer nieuwste meetwaarde
  i++; i %= N;                                   // Teller loopt van 0 tot N-1

  filterwaarde = filteraccumulator/N;            // bereken de gemmiddelde waarde

  tempA = filterwaarde * (uref/65534.0);         // Tussenwaarde berekening met Uref en de 16 bit waarde 
  temp = tempA / 0.02;                           // Laatste stap berekening, 0.02 is het aantal mV/C van de TMP37 sensor

  Serial.println(filterwaarde);
  Serial.println(temp, 3);

  delay(10); 
}

Dit is een stukje output van de serial monitor.
http://www.bramcam.nl/TMP37-Middelen-01.png

De loop code wordt naturulijk een stuk complexer en daardoor slomer wat resulteerd in een nog lagere tijd om een stabiel waarde te krijgen.
Maar ik kan ook alleen de omgevings temperatuur loggen en de oventemperatuur niet wegschrijven tijdens het reizen.

Dan nog dit om wat duidelijker te maken.
Ik ben niet in precies de temperatuur te weten van de oven.

Deze wordt ondermeer bepaald door deze onderdelen.
De nauwkeurigheid van de gebruikte TMP37.
De drift van de gebruikte TMP sensor.
De stabiliteit van de Interne referentie van de SAM21 controler.
De drift van de interne referentie of externe referentie.
De stabiliteit en lineairietijd van de SAM21 ADC.

Ik wil dus een mogelijkheid hebben eventueel de drift van de oven kunnen zien met een resolutie die hoog genoeg is.
Op het ogenblik ben ik bezig uit te zoeken hoe goed de SAM21 controler is bij temperatuur variaties.
Een andere optie is een ADS1115 te gebruiken dan heb ik zeker een 15 Bit ADC met al een lage ruis.
Maar goed de vraag is dus blijft dit dus behouden als er naar de slaapstand wordt gegaan en weer wakker wordt => Blijft de waarde van de "filteraccumulator" behouden?

Dank en groet,
Bram

You have your way. I have my way. As for the right way, the correct way, and the only way, it does not exist.
blackdog

Golden Member

Hi,

Hoeben, de processor gaat in slaapstand als de referentie niet gebruikt wordt.
Maar deze wordt b.v. 4 tot 6x per uur even gewekt voor een aantal metingen en deze op te slaat op een SD caard.
Alles draait op twee accu's.

Groet,
Bram

You have your way. I have my way. As for the right way, the correct way, and the only way, it does not exist.

Zou geen enkel probleem moeten zijn. Zolang de processor spanning heeft blijft de data behouden. Ook als de processor in slaapstand gaat.

Maar bij een reset niet. Dan begint het programma weer helemaal opnieuw van bovenaf, in dit geval met de initialisatie instrukties die nog voor de Setup() funktie staan.

Bij een slaapstand heb je daar geen last van. Als de processor uit de slaap wordt gewekt dan gaat die verder waar die gebleven was, met behoud van alle variabelen.

Ook een reset is te overleven. Maar dan moet je niet bij opstarten alles wissen. Doe dat slechts eenmaal bijvoorbeeld dmv een wis-drukknop en laat dan het geheugen staan.

Verder heb je een SD-card. Daar kun je de data ook opslaan.

Klopt, je kunt een reset wel overleven. Maar dan moet je toch al wel speciale initialisatie code gaan schrijven. Zo een standaard arduino programma heeft dat niet dus die raakt bij een reset alles kwijt.

Veel processoren hebben diverse "slaap" mogelijkheden. Degene met het allerlaagste verbruik is die waarbij de CPU eigenlijk gewoon UIT gaat. Daar kom je uit met een RESET en dan is normaliter ook je RAM niet meer betrouwbaar. Er zijn ook minder heftige "sleep" modes waarbij dus RAM wel behouden blijft en soms ook nog bepaalde peripherals blijven draaien. Dit soort dingen moet je opzoeken in het datasheet van de chip of evt in de handleiding van de "sleep" functie die je gebruikt.

Sommige CPUs hebben een stuk "backup RAM" wat behouden blijft met een sleep-mode waarbij de CPU WEL compleet uit gaat, maar dus dat ene stukje RAM blijft bewaard. Op de STM32F072 is dat geloof ik 4k dat bewaard blijft.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Toeternietoe

Dubbelgeïsoleerd

Als je ontwaakt na een slaapstand moet je natuurlijk eerst weer 1000 nieuwe metingen doen om het gemiddelde eruit te kunnen bepalen. Je oude waarden MOETEN dus weg als je uit de slaapstand komt (of overschreden worden)

Dus als het lang duurt voordat de temp.uitlezing stabiel is moet je na ontwaken
Eerst wachten (je geeft aan 20 sec)
Dan een aantal metingen doen,
dan het gemiddelde bepalen, en dan wegschrijven.

Moeten dat 1000 metingen worden voor een goed gemiddelde?

Daar waar een schakeling rookt, vloeit de meeste stroom (1e hoofdwet van Toeternietoe)

Op 16 juli 2019 09:28:57 schreef Toeternietoe:
Je oude waarden MOETEN dus weg als je uit de slaapstand komt (of overschreden worden)

Dat is een "strategische keuze" die ik blackdog wel toevertrouw. Als je ieder kwartier een meting neemt en dan 1000 metingen gaat middelen, zit je anderhalve week te middelen. Zo stom zal ie wel niet zijn. Dus na het wakkerworden valt er wat voor te zeggen om zeg 100 metingen te doen en die allemaal mee te nemen in een gemiddelde wat dan over enkele uren verspreid is.

Anderzijds, in zo'n geval zou ik het liefst simpelweg het totaal van die 100 samples opslaan. Als je dan wilt middelen over 10 van dat soort metingen kan dat altijd nog.

Let op met Atmel (ik weet niet of die SAM vergelijkbaar is met de AVR), maar: De bij de AVR kan interne referentie kan wel SOURCEN naar de AREF pin, maar niet sinken. In het datasheet staat dat je 1 sample moet weggooien na het switchen van de AREF bron, nou dat is ruimschoots niet waar als je de referentie omlaag switched. Idem zou ik na een sleep de eerste paar samples niet direct vertrouwen. Om je nauwkeurigheid te controleren, zou ik het eerste sample naast het 10e sample houden (plotten) en dan kijken of je een verschil ziet. Zoja, dan kan je hem beter weggooien.

Ohja, nog 1 dingetje: In de AVR (wederom: ik weet niet of dat toepasbaar is op de SAM) is de interne referentie +/- 10% : zo goed als onbruikbaar.

Update: vrefint, nominaal 1.0V is... nominaal 1.0V, bij de SAM geven ze niet eens de +/- 10% op. Je hebt de garantie dat ze geprobeerd hebben er 1V van te maken, maar als het 2V blijkt te zijn, sorry, jammer dan. En als ie 1% lager zit dan 1.0V, dan zit de ADC buiten z'n werkbereik. Bere handig zo'n datasheet.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
blackdog

Golden Member

Hi,

Voor een hoge resolutie heb ik veel samples nodig om te middelen om ruis uit de TMP37 en de ADC ruis en referentie te onderdrukken.
Mischien kan ik met minder toe, als het geheel ingebouwd is en de ruis dan minder is door de nettere opbouw.

Ik zou dus graag de trent zien van de oven temperatuur en deze ook tijdens het reizen of al de referentie "uit staat" op de werkbank.
Omdat ik ook een BME280 gebruik kan ik makkelijk daar ook de temperatuur van de omgeving uit halen en die gebruiken om op te slaan.

Ik ben met deelstukjes bezich van wat ik wil en sommige stukjes code kosten veel looptijd, zoals b.v. het ophalen van de gegevens uit de BME280 of andere sensoren.

Er zijn vele afwegingen te maken en zal ook wat moeten loslaten van wat ik leuk vind om te meten.
Ik kan er b.v. voor kiezen de processor gewoon in slaap tijdens de reis of standby stand te houden en in het kastje zo'n USB datalogger te bouwen die los van alles staat voor de temperatuur en andere eenheden.
Dan doe ik het loggen naar SD card alleen als de Reisferentie normaal aan staat, ik denk hier steeds meer hier aan om de ontwikkeltijd te beperken en de oven zo lang mogelijk te laten werken op een accu lading.

Voor de indruk, de oven zal niet meer als een paar honderste van een C veranderen, dat is ruim voldoende om binnen de dan dominante 1/F ruis te blijven van de twee LT1021 referenties.

rew
Misschien kan je jezelf herinneren dat ik een Nano en en Teensy microcontroler heb opgevoerd met een goede referentie en koelplaatje op de CPU.
Dat is zondermeer nodig om meer stabiliteit uit de ADC in de controler te persen.
Maar ik zij gisteren ook al dat ik ook een ADS1115 kan gaan gebruiken, dan heb ik een "echte" 15 bit ADC met een goede ruisonderdrukking en
dan kan het middelen in de arduino code volgens mij en stuk lager worden voor een goed resultaat.
Ik wil vandaag proberen wat testjes met de ADS1115 doen.

Voor de gene die het nog niet weten, temperatuur uitlezen met een resolutie van 0,001C met lage ruis is zeer moeilijk.
Er is bijna geen sensor te vinden waarbij dit mogelijk is, ik heb er hier een paar die in de buurt komen.
Ondermeer de Smartec SMT172 die ik hier ik een paar uitvoeringen heb zoals de TO18 en de HEC chip versie.
De code voor het uitlezen is nogal "specific" deze sloopt de i2c en dan blijft mijn display leeg als ik de sensor aansluit.

Voor de werking van de Reisreferentie is dit allemaal niet nodig, maar ik wil graag met hoge resolutie zo stabiel mogelijk ovengedrag kunnen uitlezen uitlezen.
Ik combineer vaak, zodat ik wat ik hier nu van leer wat de temperatur sensor betreft weer toepas in andere projecten.

Het mooie is dat de code voor een hoge resolutie de loop bijna niet vertraagt wordt!
Met mijn huidige opset(TMP37 en de gebruikte microcontroler en ADC config) is dus de waarde rond de 1000x middelen voor een redelijk stabiele uitlezing tot op 0,001C.

Groet,
Bram

You have your way. I have my way. As for the right way, the correct way, and the only way, it does not exist.

Op 15 juli 2019 23:46:03 schreef deKees:
Klopt, je kunt een reset wel overleven. Maar dan moet je toch al wel speciale initialisatie code gaan schrijven. Zo een standaard arduino programma heeft dat niet dus die raakt bij een reset alles kwijt.

Wist die bij reset het volledige geheugen? Dan is, denk ik, de oplossing ergens een geheugenblok bezet maken (getmem of zo) en er met pointers doorheen lopen. Dan wel even iets slims maken waarin je de laatste pointer ook opslaat.

Wissen wordt gedaan door de initialisatie code die door de compiler wordt meegebouwd. Als je niet wilt wissen bij reset dan moet je je variabelen aan een speciaal memory segment toekennen. Dat gaat met attributen, Iets als:

code:


int MyVariable __attribute__ ((section (".noinit")));

En nee, niet het hele geheugen wordt gewist, alleen dat stuk waar je variabelen staan. De rest wordt gebruikt voor de stack en wordt niet gewist.

[Bericht gewijzigd door deKees op dinsdag 16 juli 2019 22:48:05 (20%)

Handleiding SAM D21, tabel 15-4: In standby is ram in LOW-power mode. Ik kon zo snel niet vinden wat dat betekent, maar ik denk dat dit betekent dat je RAM behouden blijft.

Verder lijkt het er op dat de deep-sleep modes die diverse andere MCUs hebben hier niet bestaan. De ESP8266 en STM32 hebben een sleep mode waar je alleen met een reset uitkomt. Dan is ie echt HEEL zuinig en moet je moeite doen om te merken: wachteffe, we waren al bezig en zijn niet zojuist aangezet. De SAM heeft een WFI instructie waarbij afhankelijk van een sleep register eea uitgezet wordt. Maar hij gaat gewoon bij een interrupt op de volgende instructie verder, met behoud van RAM.... (Denk ik).

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/