DS18B20 en TMP37 Kalibrator

blackdog

Golden Member

Hi,

Ja ik ben lekker productief ;-)

De door mij meest gebruikte temperatuur sensoren zijn de DS18B20 en de TMP37.
De eerste is een digitale sensor en de tweede is een analoge sensor.

Zoals mede CO gebruiker Gertjan ook al ondervonden heeft, kunnen er grote verschillen optreden tussen sensoren van het zelfde type.
Bij de DS18B20 kan dit tot 1C verschillen en bij de TMP37 zelfs 4C tussen twee IC's!
Over het algemeen is dit beter, maar Gertjan heeft ook al meegemaakt dat het voor een aantal sensoren net op het randje is en dat "typical" niet echt op ging...

Ik heb al een andere kalibrator opset maar ik wou een compakt kastje hebben met een Arduino, Nokia display, 5V voeding en ook direct het serie nummer van de gebruikte DS18B20 op het display hebben.
Het display kan ook twee sensoren te gelijk weergeven die gemeten moeten worden, één digitale sensor en één analoge sensor.

Ik heb ook nagedacht of de sensor die gebruikt om de oven op tempratuur te houden, hiervoor ook een DS18B20 of een TMP 37 te gebruiken.
Maar deze sensoren hebben niet een strak gespecificeerde drift voor langere tijd.

Dus ik ben uitgekomen bij één van de twee digitale sensoren die ik hier heb liggen en die gespecifiseert worden op <0,1C over een bepaald temperatuur gebied.
Het Micro Oventje dat ik hier laat zien die sensoren kan gaan kalibreren wordt opgestookt tot 40C.
De gebruikte sensor die de PID regeling aanstuurd is de: Tsic 506F.

Dit is de datasheet en wat info over deze sensor.
www.bramcam.nl/NA/DS18B20-TMP37-Kal/TSic50x.pdf

Hier heb ik net de kleine stukjes aluminium klaar, om het U profiel dicht te maken, het profiel is 15 x 15mm en 25mm hoog.
De draden die er uitsteken zijn van twee power transitoren in een totaal plastic behuizing.
Dan heb ik geen last van commonmode problemen en kan de aluminium behuizing aarden waar ik wil.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-01.png

Hier is het vierkante dekseltje te zien, het geheel zit klem tussen het U profiel.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-02.png

De transistoren zitten hier reeds vastgelijmd en de positie van de meetsensor is ongeveer aangegeven.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-03.png

De sensor is hier bedraad met de verplichte 0,1uF Cer. condensator
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-05.png

Ik ga eerst de sensor testen of hij goed is, daarna wordt de sensor vastgezet met wat 10 seconde lijm en daarna wordt het U profiel gevult met Thermische lijm.
Dit doe ik dan in twee stappen, dit om er voor te zorgen dat dit netjes gaat en de lijm goed de kans krijgt uit te harden.

Door het aluminium U profieldicht te maken met klem zittende vulstukjes krijg je een meer homogene verwarming van het U profiel.
Ook het volstorten met Thermische lijm gaat hierbij helpen.

Hier is te zien dat ik een stukje IC voet strip gebruik, waar je de te meten sensor in kan prikken.
Dit is met opset 5 pinnen, zodat ik meer oppervlakte heb om het goed vast te kunen lijmen, de twee buitenste busjes worden nog verwijderd.
De pennetjes die normaal in de print gaan worden er afgeknipt, de drie draden worden aan de bovenzijde van het dan nog uitstekende deel gesoldeerd.
Dit met het zelfde dunne draad, als waar de meetsensor in de oven mee bedraad is.
Deze opset dient er voor om het voetje op de zelfde temperatuur te krijgen/houden als het aluminium oventje.
Het voetje wordt uiteindelijk behalve met 10 seconde lijm ook met de Thermische lijm omgeven.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-04.png

Uitlezing Nokia display
*******************************************
Ingestelde temperatuur (40C)
Gemeten temperatuur oven

Adres van de geplaatste DS18B20 sensor
Temperatuur van de DS18B20 sensor

Temperatuur van de geplaatste TMP 37 sensor

Oven Ready status

Voor mijn gebruik is meestal rond de 40C, daarom gebruik ik maar één tempratuur instelling voor dit oventje.
*******************************************

Ik ga verder nog kijken of ik een kunstof klemmetje kan maken of wat kleine elastiekjes kan kopen om de sensor goed tegen de oven aan te houden.

Dit is een dopje dat ik kan gebruiken om het oventje een beetje af te schermen van de omgeving, zodat ik sneller een zinnige/stabiele waarde heb.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-06.png

Mooi, de rest komt wel weer, morgen eerst verder met mijn meetversterker daar de onderdelen zijn binnen gekomen.

Groet,
Blackdog

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,

Gisteren aan het lijmen geweest en testen van de sensor.

Hier is de sensor met wat 10 seconde lijm aan de onderwand vastgezet.
Er is nog een 5K meet NTC bijgekomen om te kijken hoe goed het oventje regeld.
Dit is zo'n gele NTC die ik meer gebruik en deze zit net bovende bovenste transistor tegen de wand geplakt.
Ben hiervan vergeten een foto te maken, maar op de andere foto's zijn de getwiste gele draden van deze sensor.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-07.png

De eerste laag thermische lijm aangebracht, dan nog even dit!
Deze lijm is echt giftig, dus iedereen die met dit soort lijm werkt, let goed op!
Het viel niet mee door de dikte van de lijm het in alle hoeken en gaten te krijgen.
Dit heb ik uiteindelijk zo goed mogelijk opgelost door in de lijm te prikken met een Saté prikker.
Voor het dekseltje er op ging is er nog een laag lijm aangebracht.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-08.png

Hier is het oventje dicht en je kan net omderaan het vierkante dekseltje zien dat de blauwe aarde draad hier klem zit.
Het viekante stukje is en met de waterpomptang in vastgezet, zo strak zit het.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-12.png

Op deze manier is de sensor uitgelezen, kan bijna niet simpeler, de data komt dan in de serieel terminal terrecht zoals hier:
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-10.png

De code is ook zeer simple voor deze sensor:

c code:

#include <TSIC506.h>

int error;  //1 = OK, 0 = parity error    return value of getTSicTemp()
int temptsic;  // "return" of temperature in degrees Celsius * 100
float tempt; // temperature in degrees Celsius

TSIC506 Sensor1(5, 4);  //firstValue = VCC-Pin, secondValue = Signal-Pin

void setup(){
  Serial.begin (115200);
  Serial.println("Starting...");
}
void loop(){ 
  error = Sensor1.getTSicTemp(&temptsic);  //turn the TSIC-Sensor ON -> messure -> OFF
  tempt=temptsic/100.0;
//    tempt=temptsic;
  Serial.println("C");
  Serial.print(tempt);
// Serial.println("Status: ");
//  Serial.print(error);
  delay(2);

}

De 5K NTC op de KeySight 34461A aangesloten zegt dan dit.
http://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-09.png

De verschillen zijn erg klein en dat pleit voor de 5K NTC, waarvan de spec 0,5% is.
Ik ga denk ik de temperatuurwaarde 4x middelen van de Tsic sensor en dit dan aan de PID software van de Arduino ga toevoeren.

Ik denk nog na over het display, hiervoor wou ik een Nokia display gebruiken, maar ik kan niet in één regel het adres van de te testen DS18B20 weergeven.
Het word dan denk ik een LCD display met een hogere resolutie om het netjes te kunnen weergegeven, het adres kosdt namelijk 46 karakters posities
en als je de comma's weg laat tussen de segmenten zit je altijd nog op 39 karakters.

Zoals altijd, laters meer hierover, nu eerst pecunias verdienen :-)

Groet,
Blackdog

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,

Al een redelijk aantal keren heb ik dit test apparaatje nodig gehad oee nsetje of meerdere temperatuur sensoren te kunnen controleren.
Ik liep drie jaar geleden een beetje vast op het mechanische probleem hoe het oventje te bevastigen in een soort van houder.

De laatste twee weken ben tussen andere projectjes door weer met deze temperatuur sensor kalibrator bezig geweest omdat ik weer een aantal sensoren nodig had
die redelijk dicht bij elkaar moesten zitten wat output betreft.

Deze versie van het oventje komt op rond de 45C uit als vaste temperatuur, verder ben ik met een Peltier module bezich, zodat ik redelijk snel temperatuur tussen zeg "0°C en 70°C kan instellen, maar dat wordt een ander topic.

Er zijn ondertusse neen paar andere sensoren bij gekomen die niet duur zijn en toch vrij goed.
Alle goedkopere analoge temperatuur sensoren zij tussen de +-2 en -+3 °C aan absolutie nauwkeurigheid.
Een goede NTC is vaak goedkoper maar verlangt een correctie voor als je over een wat groter temperatuur bereik wilt werken.
Echt goedkope analoge sensoren zijn ondermeer de TMP35, 36 en 37 van analog en de MCP9700A en de MCP9701A van Microchip.
Een nieuwe is de LMT86 waarbij in de datasheet een hele lijst is opgenomen met de verwachte waarden bij verschillende temperaturen.

Als deze sensoren hebben hun eigen manier om het maximale er uit te halen zodat ze uiteindelijk over een groot gebied een stuk nauwkeuriger worden.
Zowel voorde LMT86 alsook de MCP9700 series bestaan 2e orde corectie formules waarmee je de sensor over een flink bereik echt recht trekt.
Hierover ga ik jullie nog wat hulp vragen om deze 2e order formules te implimenteren in een van mijn Arduino Sketjes. ;)

Op deze foto is de onderzijde te zien waar de vele draden gemonteerd zitten.
Waar mogelijk is zo dun mogelijk draad gebruikt om het weglekken van energie zoveel mogelijk te beperken.
In het oventje zitten twee plastic power transitoren die strak tegen het aluminum zitten gelijmt, dit samen met twee temperatuur sensoren,
dit is goed te zien in de eerste foto's van dit oude topic.
Er zijn twee mini weerstanden gemonteerd aan de twee emittors,
deze zijn eigenlijk niet echt nodig omdat de hFE van de twee transistoren binnen een half procent gelijk zijn.
Maar dit helpt ook eventuele generatie verschijnselen de kop in te drukken.

De glastape om de module heen heb ik gebruikt voor de eerste testen betreffende de montage in een PG21 wartel zodat hij net klem zat.
De tweede rede is om een soort bakje te krijgen zodat ik een laagje conformal coating kon aanbrengen.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-13.png

.
Een close up van de verbindingen
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-14.png

.
Nu onder een andere hoek.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-15.png

.
Nu is het laagje conformal coating aangebracht, was even vergeten de module eerst even met een spuitbus lucht te bewerken, vandaar de stof die nog zichtbaar is...
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-17.png

.
Een vriend van mij kwam nadat ik het uitgelegt waar ik mee bezig was met de opmerking waarom ik voro het monteren van het oventje geen SUGRU zou gaan gebruiken...
SUGRU wat? zij ik... ja kneedbare lijm, is populair!
Ik tijdens het telefoongessprek zoeken en hij bood aan om het niet direct te bestellen maar omdat hij toch in de buurt zou zijn twee pakketjes in de bus zou werpen.
Na nog wat te hebben gelezen over de eigenschappen en filmpes te hebben bekeken heb ik één zo'm lijmpakketje opengetrokken en dit na wat kneden om het oventje heen gelegt.
Wel na eerst de glastape die nog om het overntje zat, te hebben verwijderd.
Het oventje met de SUGRU er omheen in de wartel geschroeft en daarna de SUGRU die niet wist waar het naar toe moest, naar beneden gedrukt de wartel in.
Ik het er voor gezorgt dat de voetjes waar ik de temperatuur sensoren in ga steken iets boven de wartelrand uitsteken.
Er is nu nog een klein laagje vrij en waarschijnlijk werk ik get mooi af met een heel dun laagje WURTH siliconen kit die ik normaal gebruik voor mijn installatie werkzaamheden.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-18.png

.
Bovenaanzicht.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-19.png

.
Er staat een A op de gele Kapton tape en ook de voetjes voor de temperatuur sensoren hebben een laagje Kapton tape, zodat ze schoon blijven tijdens de bewerkingen die ik aan het oventje doe.
Rechts zijn de groepjes draden goed te zien, allen getwist per groepje, de dikte van de draad en de kleur comby zorgt er voor dit ik ze uit elkaar kan houden.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-20.png

.
De onderzijde van de wartel, hier is zichtbaar dat hier nog wat ruimte beschikbaar is, de draden ga ik niet recht naar beneden laten lopen,
maar via een lusje.
Dit heeft twee redenen, één van de redenen is om het weglekken van de energie een beetje te beperken via de bedrading en ten tweede is om de draden niet strak uit de onderzijde te laten lopen met meer kant op breuk.
Als de draden in ee nlusje zitten in de wartel dan maak ik hem dicht met de WURTH kit waar ik het net ook al over had.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-21.png

De opset wordt wel iets anders dan dat ik eerst beschreven had, ik denk dat ik de Vishay 5K NTC ga gebruiken als sensor van de PID softare
en dit dan smamen met een ADS1115 ADC.
De Tsic 506F sensor die tot 45°C binnen 0,1C wordt gespecificeert wordt dan de referentie.
De temperatuur van beide Oven sensoren worden in beeld gebracht en de vrschillen in stabile stand wordt naar "0" gecorrigeert.
Daarna worden ze vergeleken met de waarden van de te testen temperatuur sensoren.
Dus dat zijn analoge sensoren met de zelfde pinning als b.v. de TMP35 Series van Analog en het andere voetje is voor de 18DS20 digitale sensor.

Het display gaat dan de afwijking aangeven bij mijn gekozen temperatuur en dat kan 42 of 45C zijn, mijn meest gebruikte temperatuur voor de oventjes die ik bouw.
De kalibrator met het Peltier element krijgt echter de mogelijkheid tot het instellen van een groot meetgebied.

Dit is een deel van het schema van de oven met de kleuren van de ovenbedrading.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-31.png

.
Ondertussen ben ik bezich met de software voor de Arduino, zoals het automatisch laten lezen van de 18DS20 adressen en de temperatuur.
Alsook wat onderzoek naar lineaire temperatuur sensoren wat de waarden zijn van hun uitgangs spanningen bij 25 en 45°C
Ik ben er al achter dat ik niet automatisch kan selecteren op de uitgangs spanning, dit daar een aantal sensoren te dicht bij elkaar zitten wat uitgangsspanning betreft.
Verder is het nog zo dat een aantal moderne sensoren een negatieve slope hebben, dus bij stijging van de temperatuur krijg je een lagere uitgangsspanning.
Het grijze balkje in dit stukje Excel geet de DC spanning aan bij 45°C. voor verschillende sensoren en is nog niet compleet gemaakt.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-30.png

.
Ik heb nog twee andere sensoren waarmee ik de temperatuur van dit oventje kan vergelijken die ook binnen 0,1% zijn en daarmee hoop ik dan de temperatuur
zo goed mogelijk te kunnen controleren.
Maar het belangrijkste is eigenlijk één of meerdere sensoren te kunnen groeperen, als er een microcontroler wordt gebruikt kan je altijd een kalibratie waarde gebruiken om als de Sensor er 1,545°C er naast zit op zeg 45C dit te corrigeren.

Het belangrijkste is hoe het oventje zich houd tijdens het meten, ik zet een klein kapje over het oventje, maar weet niet of dit voldoende zal zijn.
Ook weet ik niet wat de meet tijd zal worden onder het normale gebruikt, de testen zullen het gaan uitwijzen! :+

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,

Gisterenavond laat de kitspuit met de WURTH MS Instand kit opgehaald om een mooie rand kit aan te brengen
zodat het geheel er een beetje netjes gaat uitzien.
Met een scherp mesje heb ik op sommige plekken een klijn laagje SUGRU lijm weg gesneden zodat er voldoende plaatst was waar de witte kit
zou kunne vaszetten.
En daarna de wartel ingepakt met die hele mooi 3M Super 33+ isolatieband, kijk naar het randje, dat is de bovenzijde van de wartel,
de tape zit prachtig om het randje geen.
Op deze foto is ook nog wat heel licht blauw materiaal te zien, dat is de Thermische lijm die gebruikt isom het IC voetje vast te zetten.
Aan het begin van dit topic is ook te zien dat het aluminium buisje helemaal vol zit met deze lijm welke de Electrolube TBS20S is.
Dat ik de typen van de gebruikte materiaalen er bij zet is niet voor de reclame, maar één van de onderdelen voor het behalen van goede resultaten.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-32.png

.
En hier is te zien dat de witte kit er omheen is gekliederd. :+
Ik had de kitspuit het laatst gebruikt om K25 goot bij een klant vast te zetten, en de spuitmond was wat breed en ik had geen nieuw spuitmondje bij de hand.
Dus met mijn vingers en watte tipjes het verder netjes gemaakt.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-33.png

.
Hier is de zwarte 3M tape reeds verwijderd en de witte kit netjes afgestreken.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-34.png

.
En dit is de laatste foto voor vandaag, nu is ook de gel Kapton tape verwijderd en er zit een echte TO92 sensor in één van de voetjes en dat is een LMT86LP.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-35.png

De bovenzijde krijgt nog een laagje conformal coating omdat er wat kierjes zijn, en de twee zijkanten waar geen voetje zit waarschijnlijk een laagje isolatie.
Of dat dit nodig is, zal uit de eerste testen blijken.

Vanavond ga ik het oventje onder spanning zetten met een LAB voeding om te zien hoeveel vermogen er nu hij ingebouwd is, nodig is om 45°C te bereiken.
Aan de hand van die gegevens, kan ik dan de maximal stroom door de twee transistoren bepalen die nodig is om het oventje snel genoeg op te warmen.

SHOOT!

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.
benleentje

Golden Member

Ben je niet bang dat de temperatuurverdeling niet overal gelijk is. Je DUT (device under test) zit bijna bovenop de warmte transistor. Je regelsensor zit in het midden en dan heb je nog warmte verschillen tussen binnen en buiten.
Om heel nauwkeurig te meten zouden je naast je dut ook een nauwkeurige sensor moeten hebben. Ik zou denk ik als setup gekozen hebben voor een oven waarin je ook de dut kan onderbrengen.

Mensen zijn soms net als een gelijkrichter, ze willen graag hun gelijk hebben.
blackdog

Golden Member

Hi benleentje, :-)

Natuurlijk zijn er temperatuur verschillen, maar omdat het allemaal zo dicht bij elkaar zit zullen die klein zijn.
Als de PID controler draait dan kan ik met nog een derde sensor een extra contole doen.

Doordat het oventje volledig gevuld is met thermische lijm en het verder klein is, denk ik dat de verschillen niet groot zullen zijn.
Het oventje zal ook nog een kapje krijgen als ik metingen ga doen dat kan je onderstaande foto zien.
Een pillen bakje uit het ziekenhuis past heel mooi over de PG21 wartel die ik gebruik.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-36.png

Voor de duidlijkheid, dit oventje is niet bedoeld om de perfecte temperatuur te meten.
Er zijn twee sensoren in het oventje aanwezig die nauwkeurig zijn van rond 0.1°C.
Doordat oventje klein is zullen de temparatuur verschillen klein zijn in het alu buisje.

Grotendeels is het de bedoeling dat ik sensoren kan controleren die standaard rond de +-2°C zijn.
en metdit oventje kan ik de afwijking aflezen en een correctie waarde gaan gebruiken die dit oventje gaat aangeven.

Ja, een testopstelling die de sensoren in een oventje test zou nog beter kunnen zijn, maar dat is toch ook weer niet simpel.
Als ik een alu of koper oventje maak, dan kan ik de buitenkant mooi op temperatuur houden,
maar dat zegt niet dat de electronica in de oven ook precies die temperatuur heeft.

Ik heb nog een andere calibrator half afgemaakt, waarbij je de sensor in een alu blok drukt, maar dat zijn allemaal geen "snelle" en makkelijk in gebruik oplossingen.

1e test
De test die ik net heb gedaan geeft aan dat ik rond de 700-mWatt nodig heb voor 45°C oventemperatuur bij 23°C LAB temperatuur.
Dat is dan met het pillen potje over de kalibrator heen.

Laters meer.

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.
Shiptronic

Overleden

Tip, ipv een elastiekje zijn O-ringen er in alle soorten en maten te krijgen om je DUT-sensor tegen het aluminium te drukken.

Wie de vraag stelt, zal met het antwoord moeten leren leven.
blackdog

Golden Member

Hi Shiptronic,

Naar kleine elestiekjes had ik wel al gezocht maar O-ringen had ik nog niet aan gedacht!
Ga ik op mijn lijstje zetten.

Er komt natuurlijk ook wat pasta tussen de sensor en het oventje, het oventje is ook een beetje vlak gemaakt
aan de kant waar de sensoren tegenaan komen.

Net even ene uur gelopen en nog wat nagedacht over dit meetinstrumentje, ik denk dat ik het dopje van een laag isolatie materiaal ga voorzien en het geheel weer in een iets groter dopje ga zetten, zoals een dop van een scheerschuim spuitbus of slagroom, die hou ik meestal niet zo goed uit elkaar.. :+

Dank voor de tip!

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,

Ik heb in mijn topic i.v.m. millis in de PID software al aangegeven dat ik wil experimenteren met de "analoge uitgang" van de Arduino controler.
Daarvoor heb ik een filter en stroombron gemaakt en dit is de eerste versie.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-41.png

Uitleg
Ik heb gekozen voor een active filtering, dan een verzwakker(R3 en R4) en dan een stroombron voor max. 400mA.
De opamp is van een speciaal type en komt uit de MCP6000 series.
Deze opamp mag op maximaal +6V werken, dat is niet veel, maar in deze toepassing geen probleem, verder is hij zowel voor de ingangen als ook de uitgang Rail tot Rail.

De compensatie condensatorC4 is laag, en dat is met opset, omdat dit soort opamps wat lastiger capaciteiten kan aansturen.
Een ander groot voordeel van deze opamp is zijn zeer grote "Phase Margin" en de gebruikte snelle transistoren die de oven verwarmen zijn snel, dus ik denk dat C4 waarschijnlijk hier niet nodig is.
Toch nog even over de compensatie condensator C4 die zorgt er voor dat er een "shortcut" is voor de hogere frequenties die dan niet door de transistoren heen hoeven.
Het kantelpunt wordt bepaald door R6 en C4.

.
In het groene kader zijn de transitoren in het oventje aangegeven, het oventje heeft zelf al emittor weerstanden die opgebouwd is als 2x 3.3Ω
dit om de kleine verschillen in de transistoren weg te werken.
De transistors zijn geselecteerd en de verschillen waren al moeilijk te meten tussen de twee die ik had gekozen de emitter weerstanden laten de hele kleine verschillen alsnog verdwijnen.

.
Voor de berekeningen betreffende de aansturing van de van de basis van de oven transistoren door de opamp, moet de 1,65Ω emittorweerstand in de oven wel worden meegenomen,
dit vooral bij het opstarten als er 400mA gaat lopen.
Bij 400mA staat er over R7 van 3.3Ω 1.32V, dat betekend dat als op de +ingang van de opamp deze 1.32V wordt aangeboden de uitgang van de opamp net zoveel stroom in de basis van de power transistoren stuurd, zodat de -ingang vande opamp ook 1.32V is geworden en walla we hebben een stroombron.

De opamp uitgang zal voldoende sturing moeten kunnen leveren, dat is max 2mA(1,8mA gemeten) bij 400mA door de transistoren.
Dat is 1,32V over R7, 0,66V over de oven weerstand(R8), 0,6V van de BE overgang en als laatste 300mV over R5 de basis weerstand,
dit afgerond houd in dat de uitgang van de opamp op het niveau van +3V hangt bij 400mA uitgangsstroom.
Als de voeding van de opamp 5V is, dan is dit nooit een probleem, bij een voeding van 3,3V kan de opamp de aansturing net aan volgens de datasheet.

3V3 als opamp voeding...
Let dan wel op dat de opamp iets meer voeding krijgt dan b.v. je controler die de PWM genereerd, anders kom je buiten het werkings gebied van de +ingang van de eerste opamp.
De MCP6000 series mag een paar honderd mV buiten zijn voedings lijnen aangeboden krijgen, maar ik blijf daat altijd bij vandaan i.v.m. betrouwbaarheid.
Beter is het om de opamp uit zoals hier afgebeeld uit +5V te voeden, dan zijn er wat dat betreft geen problemen meer.

Filtering van het PWM signaal.
Ik heb hier gekozen voor actieve filtering van 2e orde wat voldoende moet zijn door ondermeer de traagheid van de oven.
Wel wil ik geen snel schakelende signalen aan de basis van de power transistoren toevoegen, dit i.v.m. het stoor niveau dat dit zou opleveren.
Aan de ingang zit geen weerstand naar massa, dit omdat ik er vanuit ga dat de uitgang 1 of 0 is, maar ik bedenk mij net dat ik ook rekening moet houden met fout situaties
en ik ga dus een 100K naar massa zetten.

Het filter heb ik berekend van de filter software van Analog Devices op hun website.
Het kantelpunt heb ik op 75Hz gelegt zodat bij de normale PWM frequnetie er ruim 30dB demping is van de grondgolf, er zijn dan geen snelle pulsen meer aanwezig aan de uitgang van het filter.
Dat de filterfrequentie hier op 75Hz ligt komt omdat ik niet te veel vertraging wel aanbrengen in het regelgedrag van de PID software..
Waarschijnlijk kan dit kantelpunt nog omlaag en daar gaan ondrmeer de testen voor dienen die ik nog moet doen.

Dit is een screenshot van de web applicatie van van de Analog Devices filter software.
Ik heb deze keer niet zoveel moeite gedaan de componenten waarden precies te bepalen daar het in deze toepassing niet nodig is.
Het kantelpunt kan verschoven worden door het aanpssen van C1 en C2 en/of R1 en R2.
Asl C1 en C2 allebij 2x zo groot worden genomen dus 66nF en 660nF dan wordt het kantelpunt de helft van de hier aangegeven waarde van 75Hz.
Maak je R1 en R2 2x zo hoog en laat je de condensatoren ongemoeid dan wordt het kantelpunt ook de helft van 75Hz.
De verhoudingen tussen C1, C2 en R1, R2 zijn zo gekozen dat ik makkelijk kan schalen zonder in de lage of hoge weerstandn waarden te komen.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-40.png

Er is nog een mogelijkheid om nog een kantelpunt voor filtering aan te brengen en dat is een condensator over de 10K weerstand R4, dan zou je hiermee dus een 3e order filter kune maken.
Het kantelpunt kan je dan berekenen an de hand van de vervangingswaarde van R3 en R4 samen met de extra gekozen condensator.
R3 is berekend voor twee microcontroler voedingspanningen, dat is 3,3V en voor 5V, R3 wordt voor 5V 27K en voor 3,3V 15K.

Voor de gene die denken, kan ik mooi dit schema gebruiken voro een stroombronschakeling voor zeg batterijen te ontladen, dat kan, maar hou rekening met de opamp eigenschappen.
De offset is niet super goed van de MCP6000 series en kan maximaal +-4,5mV zijn.
Voor deze schakeling geheel niet van belang, de commonmode van deze opamp, lage bias stroom, goede fase marge zijn in mijn schakeling van belang.
Oja, het prijsniveau van deze opamp is vrijwel gelijk aan die van een LM358, mooi he. :)

En dan nu de handel op een breadbord setten om te kijken of het werkt zoals bedoeld.

SHOOT!

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,

Ik heb wat metingen gedaan aan de "PWM To Current" omzetten en aan de hand van metingen nog wat veranderd aan het schema.
Verder werkte het niet in één keer, foutje in het schema? nop, ik had vergeten de doorverbinding te maken die wel in het schema stond,
maar die ik niet gedaan had op het breadboard met hele vreemde resultaten!
Deze muts had de doorverbinding tussen pin-6 en pin-7 vergeten, en een zwevende mosfet ingang is heel prettig om naar te zoeken... :+
Wijzen naar het onderdeel veranderd al de status, maar goed, ik heb de fout gevonden en daarna werkte het zoals het de bedoeling was.

Nog iets waarom ik dacht dat er nog meer aan de hand was met mijn eerste schema en ik schaam me een beetje dat ik er niet eerder aan gedacht had!
Beginners foutje namelijk, ik varieerde de duty cycle van mijn generator om te controleren of de stroom door de collector mooi lineair mee varieerde met de duty cycle.
Dat ging vooral minder lineair vanaf zo'n 300 mA en hoger, hoe kan dat nou...
Was dus even vergeten dat mijn hand DMM, de Agilent U1272A op het 400mA bereik een Ri heeft van ongeveer 1,7Ω.
Dit samen met wat Ri van de bekabeling en de Ri van het breadboard zorgte er voor dat de berekende 400mA niet gehaald werd.
De collector van de power transistor(niet die van oven wel zelfde type) had ik ook aan de +5V geknoopt, daarom ging het extra mis.

Goed, bij bij niet alleen de verhalen die allemaal zo goed gaan, ik heb geen last van asociale media gedrag :) van mijn fouten kan geleerd worden!
Hieronder het aangepaste schema met wat extra info er in.
De letters A t/m D geven de meetpunten aan van de scoop probes van het plaatje dat hierna komt.
Ook is er links op het schema een oranje krabbel te zien bij de weerstand R10 van 220Ω en condensator C7 van 4n7.
Deze zijn bedoeld om de scherpe flanken van het signaal te halen dat uit de micro controler komt.
Waarom vragen jullie je misschien af, dit omdat ik al een low pass filter heb op 75Hz...
Nu is de reeele wereld toch wat anders als een getekend schema of een Spice simulatie.

R1 van 5K6 en C2 van 330nF zouden de snelle flanken uit de controler makkelijk moeten kunnen onderdrukken.
Met een opamp die een grote bandbreedte zou hebben alsook een schakeling opgebouwd als een 435MHz zender gaat dat best goed komen.
Maar de situatie hier is natuurlijk heel anders(ja de flanken uit een microcontroler zijn zeer breedbandig!)
Ik zal er voor moeten zorgen dat die snele flanken niet in mijn opamp terrecht komen en ook niet te veel stralen(inductie en capacitief)
Daarom staan R10 en C7 getekend bij de microcontroler, en dan met zo kort mogelijke bedrading aangesloten.
Daarna zal de schakeling werken zoals bedoeld, de oranje pijl geeft aan in het schema hoe de HF stromen van de flanken lopen, die gaan dan niet meer richting de opamp als goed bedraad.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-50.png

.
Het zijn echt meer meetkabels dan testschakeling...
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-51.png

.
En dit is dan de scoop foto die de signale nop verschillende punten aangeeft, er is weer wat filtering gebruikt om de traces duieleijker te maken en niet om zaken te maskeren, juis in tegendeel.
Meer eerst dit:
Trace Geel = A op het schema en het is het PWM ingangs signaal.
Trace Groen = B op het schema en is de +ingang van de eerste opamp.
Trace Magenta = C op het schema en dat is de ingang van de tweede opamp
Trace Groen = D op het schema en dat is de spanning over R7, de emittor weerstadn van de power transistor.

Coor alle traces geld dat de "0" lijn de eerste divisie is vanaf de onderkant, zie de ingangs trace (Geel).
Alle kanalen zijn DC gekoppeld en de traces zijn zo in beeld gebracht dat ze elkaar niet overlappen en dat je toch de signaalform kan zien.

Let nu goed op de bovenste trace, dat is Magenta, daar kan je heel mooi de stijle flanken op zien als piekjes op het signaal ten tijde van de flanken.
Bij deze meting is het "flank Filter" dus niet toegepast om te laten zien dat na het 75Hz filter dit stoorsignaal nog aanwezig is.
Belangrijk voor mijn ovensturing? in het geheel niet, de energie in de nog aanwezige puls is erg laag dus de regelloop reageert daar niet op.
Jullie kunnen aan de gele trace zien dat ik wel goede probe techniek gebruik, er is geen over of ondershoot te zien van de blokgolf.
De gebruikte Duty Cycle is voor deze meting op 50% gezet, dit omdat dit de grootste fout geeft, bij de blauwe trace (Dits het residu van het PWM signaal)is de golfvorm het beste te zien.
Bij dus meer of minder dan 50% wordt dit signal kleiner.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-52.png

Vragen/opmerkingen SHOOT!

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.

Waarom niet gewoon ongeveer hetzelfde kantelpunt in de filtering dicht bij de arduino? Of bijvoorbeeld 4.7uF keramisch als C7 zodat je nog steeds goede HF eigenschappen hebt maar niet zo veel dat je een elco met (relatief) hoge ESR moet gaan nemen?

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

Golden Member

Hi rew, :-)

4,7uF met 470Ω heeft ook ongeveer 75Hz als kantelpunt, in ieder geval een goede vraag!
Maar dat is dan een 1e orde filter, als je kijkt naar mijn tweede schema, dan kan je zien dat ik er een 3e orde type van heb gemaakt door C6 van 330nF.
Hierdoor is de filtering nog beter geworden, wat verder weinig te meken heeft met de flank pulsjes, die komen op meerdere manieren de schakeling in.

Zwaar filteren aan de controler kant zoals jij voor steld, ben ik niet direct een voorstander van, dit i.v.m. de grote piekstromen(meer energie) in de uitgang van de controler
die als je b.v. de ADC gebruikt zeker het stoorniveau negatief zullen beinvloeden.

Voor mijn toepassing weer niet zo'n probleem, maar zoals ik mijn schema hier uitleg is voor een richtlijn als anderen die een nette PWM filtering willen hebben.
Kost het meer onderdelen, jazeker, maar vooral in de hobby sfeer zijn die paar extra onderdelen meestal geen probleem.
Wat nu hier op schema staat is makkelijk te schalen naar b.v. andere PWM frequenties of toepassingen, wil je b.v. wel een heel nette DC hebben,
dan kan je de MCP6002 vervangen door een betere dual opamp zoals deze typen: LTC2055, ADA4528-2, OPA2388 en de OPA2191 om er maar een paar te noemen.

Groet,
Bram

PS
Trouwens, als eerste had ik gedacht aan een van mijn passieve filters die ik hier op CO al had laten zien, die zou ik ook naar een derde orde kunnen schalen.
Maar of ik nu een enkele opamp gebruik voor de stroombron, of ik neem een dual en gebruik filter software voor het optimale resultaat, nou dan weet ik het wel. :)

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,

Een paar plaatjes en een vraag over mijn code waar ik en de code mee vastloopt. :+
Ik gaf al aan dat ik een Teensy LC wou gaan gebruiken en daar ben ik vandaag mee gaan experimenteren.
Als eerste heb ik van een Teensy LC die ik al een beetje het opgevoerd een Teensy LC "Abarth" gemaakt!

Hier heb ik de "0" punten op het micro-controler printje doorverbonden met vertind coperdraad.
Hierdoor is de Ri van deze punten zo'n 10x lager geworden.
De groene tekst op de controler koeler is de onbelaste spanning van de spannings referentie die onder op het printje gemonteerd is, 2,4997V.
Tussen het koelelement en de rechter tantaal elco is de NTC "PullUp" weerstadn te zien, 0.1%, 2K37 en 15PPM.
De twee tantaal condensatoren zijn voro de processor ontkoppeling en ontkoppeling van de 2,5V referentie spanning.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-55.png

.
Hier is de USB aansluiting te zien, waar ook de "0" verbindingen aan zitten.
Onderop is nog net een ontkoppel condensator te zien van het referentie circuit.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-56.png

.
De zijde waar aa nde rechter kant de eerste pin de voeding is, 3.7 tot 5.5V.
Dan de "0" aansluiting.
De volgende is de 3,3V uitgang.
Dan krijgen we A9 waar voor de test een TMP37 sensor aanhangt op het breadboard.
En dan komt A8 welke de 2K37 PullUp heeft.
Het printje is wat stoffig maar dat maak ik later schoon.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-57.png

.
En hier zit het masa brugje vast aan de "0" voor de DAC uitgang die ook aan deze kant zit.
De 12Bit DAC is het eerste vrije gaatje aan de rechter onderzijde, 0 tot 3,3V uit.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-58.png

.
Dit is de Maxim 2,5V referentie die aan de referentie ingang van de controler vast zit.
Linksboven is te zien dat aansluiting 26 de DAC is zoals ik al had aangegeven.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-59.png

.
Hier is te zien dat de 1uF ontkoppel condensator is aangebracht om de ruis van de NTC ingang wat te verlagen.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-61.png

.
Hier is het geheel op het breadbord te zien, de 5K NTC heb ik op de print gesoldeerd, het breadbord gebruiken is een grote Nono!
De 1uF ontkoppeling voor de TMP37 ingang zit op deze foto nog niet op zijn plek.
De 5K NTC zit in het roze stukje schuim, dan heb ik wat minder last van "tocht" of thermiek, ik lees met een resolutie van 0,001C de temperatuur uit, vandaar dat dit nodig is.
De TMP37 heeft een dopje, dit is voor de zelfde rede.
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-62.png

.
Ok dan heb ik twee vragen, maar laten we beginnen met de eerste waar ik waarschijnlijk weer last heb van een "blinde vlek" :+
Door deze Teensy LC te gebruiken kan ik voor deze temperatuur kalibrator de ADC van de Teensy gebruiken, waarvan zij zeggen dat 13Bit altijd mogelijk is maar het een 16 Bit ADC is.
Doordat mijn referentie temperatuur sensor zo rond de 0,1°C is heb ik er voor dit project er vrede mee dat ik zo'n 13Bit echt goed kan doen.
Mijn PullUp weerstand voor de NTC ligt dicht bij de waarde van de NTC bij een temperatuur van 45°C, dit maximaliseert de resolutie.
De processor is gekoeld, ja ik eb het effect hiervan gemeten.
En ik heb een externe spanning referentie in gebruik, vandaar dat ik dit een Teensy LC Abarth noem.

Mooi, Ik had nog wat verder gelezen over middeling, ondermeer op de website van Felix Donkers: https://www.felixdonkers.nl/2012/07/smart-sensor-filtering/
En heb zijn middeling, de laatste versie onderaan de pagina toegepast voor het uitlezen/middelen van de NTC waarde en dat ging goed.

De code die ik zo laat zien heeft ook geen NTC library maar de berekening staat gewoon in de loop.
Ook de AnalogSmooth library wil ik er dan graag uit hebben en de zelfde code die ik voor de NTC gebruik van Felix Donkers ook gaan gebruiken voor de TMP37 ingang.

Met mijn houtje touwtje manier heb ik de variabelen aangepast voor de middeling van de TMP37 sensor.
Alleen heb ik bij de meeste variabelen voor de TMP37 sensor er _1 bij geplakt, en "i" heb ik aangepast in "j"

c code:


#include <ADC.h>

//#include <PID_v1.h>
#include <Wire.h>
#include <ADC.h>

ADC *adc = new ADC();                                                           // ADC object voor de Teensy ADC
 

// Thermistor Eigenschappen Vishay NTCLE300E3502SB
#define RT0 5000                                                                // Ω
#define B 3977                                                                  // K

#define VCC 2.4985                                                              // Referentie Spanning
#define R 2368.85                                                               // Weerstand naar de referentie spanning voor de NTC in Ohm

// Variabelen voor NTC
float RT, VR, ln, TX, T0, VRT;

// Configuratie middeling voor de NTC ingang
const int N = 32;                                                               // Aantal te middelen waarde
int meetwaardes[N];                                                             // Opslag individuele meetwaarden
int filteraccumulator = 0;                                                      // Optelsom van alle individuele meetwaarden
int i = 0;                                                                      // Meetwaarden teller

// Configuratie middeling voor TMP37 ingang
const int N_1 = 32;                                                             // Aantal te middelen waarde
int meetwaardes_1[N_1];                                                         // Opslag individuele meetwaarden
int filteraccumulator_1 = 0;                                                    // Optelsom van alle individuele meetwaarden
int j = 0;                                                                      // Meetwaarden teller
float T_TMP37 = 0;


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void setup() {
    Serial.begin(115200);

 // Configuratie van ADC_0 Teensy-LC
    adc->adc0->setReference(ADC_REFERENCE::REF_EXT);                            // Selecteer de externe referentie ingang voor ADC_0
    adc->adc0->setAveraging(32);                                                // Selecteer de middeling van de gebruikte ADC
    adc->adc0->setResolution(16);                                               // Selecteerd de resolutie van de geselecteerde ADC
    adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS);     // Selecteerd de conversie snelheid
    adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED);                 // Selecteerd de sample snelheid
    adc->adc0->recalibrate();                                                   // Kalibreeer de ADC


  T0 = 25 + 273.15;                                                             // Temperature T0 from datasheet, conversion from Celsius to kelvin fot the NTC Sensor
}


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void loop() {
unsigned long start = micros();                                                   // Debug mode... voor het meten van een deel van de code in de loop


// Middelen van ADC ingang voor de TMP37
  filteraccumulator_1 -= meetwaardes_1[j];                                        // [b]ALS DIT STUKJE CODE AAN STAAT( VIJF OPVOLGENDE REGELS) GAAT OOK DE CODE VOOR DE NTC OM ZEEP[/b]
  meetwaardes_1[j] = analogRead(A9);                                              // Bewaar nieuwe meetwaarde
  filteraccumulator += meetwaardes[j];                                            // Accumuleer nieuwste meetwaarde
  j++; j %= N_1;                                                                  // Teller loopt van 0 tot N-1
  T_TMP37 = filteraccumulator_1/N_1;                                              // Bereken de gemmiddelde waarde

// Print TMP37 Temperatuur
  Serial.print("TMP37:  ");
  Serial.println(T_TMP37 * (2.4985/65536 / 0.02), 3);                             // Geeft na berekening de gemeten temperatuur van de TMP37 sensor in beeld


// Middelen van ADC ingang voor de NTC
  filteraccumulator -= meetwaardes[i];                                            // Vergeet oudste meetwaarde
  meetwaardes[i] = analogRead(A8);                                                // Bewaar nieuwe meetwaarde
  filteraccumulator += meetwaardes[i];                                            // Accumuleer nieuwste meetwaarde
  i++; i %= N;                                                                    // Teller loopt van 0 tot N-1
  VRT  = filteraccumulator/N;                                                     // Bereken de gemmiddelde waarde
  
  
// Bereken temperatuur voor de NTC ingang 
  VRT = (2.4985 / 65536.00) * VRT;                                                // Conversion naar spanning
  VR = VCC - VRT;
  RT = VRT / (VR / R);                                                            // Bereken de weerstand van RT

  ln = log(RT / RT0);
  TX = (1 / ((ln / B) + (1 / T0)));                                               // Bereken de Temperatuur in Kelvin

  TX = TX - 273.15;                                                               // Conversie naar Celsius

// Bereken code run time
unsigned long end = micros();
unsigned long delta = end - start;
  Serial.println(delta);

// Print NTC Temperatuur
  Serial.print("Temperature-NTC:");
  Serial.print("\t");
  Serial.print(TX, 3);                                                            // Geeft de gemeten temperatuur van de NTC sensor in beeld
  Serial.print("C\t\t");

      delay(10);
}

Als de regels die bij de volgende opmerking aan staan: // Middelen van ADC ingang voor de TMP37
Dan gaat de code voor het middelen van de NTC ook omzeep, ik heb het duidelijk niet goed gedaan, maar zie niet waar de fout zit.
Het zal zondermeer in het omnummeren van de variabel zitten, maar waar!

Dank vast voor de hulp.

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.

code:


// Middelen van ADC ingang voor de TMP37
  filteraccumulator_1 -= meetwaardes_1[j];                                        // [b]ALS DIT STUKJE CODE AAN STAAT( VIJF OPVOLGENDE REGELS) GAAT OOK DE CODE VOOR DE NTC OM ZEEP[/b]
  meetwaardes_1[j] = analogRead(A9);                                              // Bewaar nieuwe meetwaarde
  filteraccumulator += meetwaardes[j];                                            // Accumuleer nieuwste meetwaarde
  j++; j %= N_1;                                                                  // Teller loopt van 0 tot N-1
  T_TMP37 = filteraccumulator_1/N_1;                                              // Bereken de gemmiddelde waarde

Verkeerde meetwaardes[j] wordt hier bijgeteld in de verkeerde filteraccumulator. Dus 2x '_1' te weinig.

Je kunt het zo wel afhandelen maar zoals je ziet is het nogal foutgevoelig. Ik zou er een class van maken:

code:



#include <ADC.h>

//#include <PID_v1.h>
#include <Wire.h>
#include <ADC.h>

ADC *adc = new ADC();                                                           // ADC object voor de Teensy ADC
 

// Thermistor Eigenschappen Vishay NTCLE300E3502SB
#define RT0 5000                                                                // Ω
#define B 3977                                                                  // K

#define VCC 2.4985                                                              // Referentie Spanning
#define R 2368.85                                                               // Weerstand naar de referentie spanning voor de NTC in Ohm

// Variabelen voor NTC
float RT, VR, ln, TX, T0, VRT;

// Configuratie middeling voor de NTC ingang
class Filter
{
public:
   const int N = 32;                           // Aantal te middelen waarde
   int   meetwaardes[N];                       // Opslag individuele meetwaarden
   int   accumulator = 0;                      // Optelsom van alle individuele meetwaarden
   int   index = 0;                            // Meetwaarden teller

   void AddSample(int NewSample)
   {  accumulator -= meetwaardes[index];       // [b]ALS DIT STUKJE CODE AAN STAAT( VIJF OPVOLGENDE REGELS) GAAT OOK DE CODE VOOR DE NTC OM ZEEP[/b]
      meetwaardes[index] = NewSample;          // Bewaar nieuwe meetwaarde
      accumulator += meetwaardes[index];       // Accumuleer nieuwste meetwaarde
      index++; index %= N;                     // Teller loopt van 0 tot N-1
   }
   
   float Average()
   {  return accumulator/N;                    // Bereken de gemmiddelde waarde
   }
};


float T_TMP37 = 0;


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void setup() {
    Serial.begin(115200);

 // Configuratie van ADC_0 Teensy-LC
    adc->adc0->setReference(ADC_REFERENCE::REF_EXT);                            // Selecteer de externe referentie ingang voor ADC_0
    adc->adc0->setAveraging(32);                                                // Selecteer de middeling van de gebruikte ADC
    adc->adc0->setResolution(16);                                               // Selecteerd de resolutie van de geselecteerde ADC
    adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS);     // Selecteerd de conversie snelheid
    adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED);                 // Selecteerd de sample snelheid
    adc->adc0->recalibrate();                                                   // Kalibreeer de ADC


  T0 = 25 + 273.15;                                                             // Temperature T0 from datasheet, conversion from Celsius to kelvin fot the NTC Sensor
}


Filter Filter_TMP37;
Filter Filter_VRT; 

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void loop() 
{
unsigned long start = micros();                                                   // Debug mode... voor het meten van een deel van de code in de loop


// Middelen van ADC ingang voor de TMP37
  Filter_TMP37.AddSample( analogRead(A9) );
  T_TMP37 = Filter_TMP37.Average() ;                                              // Bereken de gemmiddelde waarde

// Print TMP37 Temperatuur
  Serial.print("TMP37:  ");
  Serial.println(T_TMP37 * (2.4985/65536 / 0.02), 3);                             // Geeft na berekening de gemeten temperatuur van de TMP37 sensor in beeld


// Middelen van ADC ingang voor de NTC
  Filter_VRT.AddSample( analogRead(A8) );
  VRT = Filter_VRT.Average() ;                                              // Bereken de gemmiddelde waarde
  
// Bereken temperatuur voor de NTC ingang 
  VRT = (2.4985 / 65536.00) * VRT;                                                // Conversion naar spanning
  VR = VCC - VRT;
  RT = VRT / (VR / R);                                                            // Bereken de weerstand van RT

  ln = log(RT / RT0);
  TX = (1 / ((ln / B) + (1 / T0)));                                               // Bereken de Temperatuur in Kelvin

  TX = TX - 273.15;                                                               // Conversie naar Celsius

// Bereken code run time
unsigned long end = micros();
unsigned long delta = end - start;
  Serial.println(delta);

// Print NTC Temperatuur
  Serial.print("Temperature-NTC:");
  Serial.print("\t");
  Serial.print(TX, 3);                                                            // Geeft de gemeten temperatuur van de NTC sensor in beeld
  Serial.print("C\t\t");

  delay(10);
}

blackdog

Golden Member

Ha deKees,

Zoals altijd heb je gelijk, echt niet gezien, tientallen keren er overheen gekeken! |:(

Je aangepaste code ga ik later bekijken, net een paar uur zitten lezen en de letters dansen nu helemaal voor mijn ogen!

Mijn eerst blik op je code laat volgens mij zien dat voor iedere ingang de zelfde middeling gebruikt wordt, klopt dat?
Dat zou ik per sensor ingang willen instellen, dit omdat de NTC een ander ruis niveau heeft als b.v. een TMP37 of een orginele ruisbron MCP9801A. ;)

Laters meer, nu eerst een uurtje wandelen.
Groet en bedankt,

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.

Bij ons heet dit het copy-monster. Dat monster slaat toe als je een stukje code copiëert en dan moet aanpassen aan de nieuwe toepassing.
Dan vergeet je makkelijk een paar aanpassingen met vreemde bugs als gevolg.

blackdog

Golden Member

Hi deKees,

Dat geloof ik direct dat er veel fouten optreden bij een copie.
Maar je wil niet weten hoeveel fouten ik heb gemaakt bij het overtypen van de code die op de website staat van Felix Donkers betreffende de filter code. |:(

Ook nu heb ik weer een tijdje zitten staren naar jouw code, ik krijg en error melding die je hier onder kan zien:

c code:



C:\***\Arduino\Teensy-Tempsensor-PID-03-deKees\Teensy-Tempsensor-PID-03-deKees.ino:26:22: error: invalid use of non-static data member 'Filter::N'

    int   meetwaardes[N];                       // Opslag individuele meetwaarden

                      ^

C:\***\Arduino\Teensy-Tempsensor-PID-03-deKees\Teensy-Tempsensor-PID-03-deKees.ino:25:18: note: declared here

    const int N = 32;                           // Aantal te middelen waarde

                  ^

C:\***\Arduino\Teensy-Tempsensor-PID-03-deKees\Teensy-Tempsensor-PID-03-deKees.ino: In member function 'void Filter::AddSample(int)':

C:\***\Arduino\Teensy-Tempsensor-PID-03-deKees\Teensy-Tempsensor-PID-03-deKees.ino:31:22: error: 'meetwaardes' was not declared in this scope

    {  accumulator -= meetwaardes[index];       // 

                      ^

Ik heb wat jij in de class hebt gezet vergeleken met mijn code maar mijn valt daar niets op waarvan ik denk dat niet goed is.

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.

Je moet de variabele N static maken. Dat is de snelste oplossing, niet de mooiste :P Heeft als gevolg dat alle instanties van het type Filter dezelfde buffergroote hebben.

c code:


const static int N = 32;
int   meetwaardes[N];

Dit stukje vind ik trouwens wel mooi opgelost zo.

c code:


   void AddSample(int NewSample)
   {  accumulator -= meetwaardes[index];       // [b]ALS DIT STUKJE CODE AAN STAAT( VIJF OPVOLGENDE REGELS) GAAT OOK DE CODE VOOR DE NTC OM ZEEP[/b]
      meetwaardes[index] = NewSample;          // Bewaar nieuwe meetwaarde
      accumulator += meetwaardes[index];       // Accumuleer nieuwste meetwaarde
      index++; index %= N;                     // Teller loopt van 0 tot N-1
   }

[Bericht gewijzigd door hardbass op zondag 5 juli 2020 23:13:36 (51%)

PE2BAS
blackdog

Golden Member

Hi hardbass,

Ja ik had het door empirisch onderzoek aan de hand van je opmerking al gevonden. ;)
De code werkt zo zonder errors.

Ik begrijp(denk ik) dat een class een stukje code is die je meermalen gebruikt voor verschillende stukjes code die de zelfde bewerking verlangen.
Hier dus het middelen van twee verschillende temperatuur sensoren.

De hier gebruite class heet Filter

En de twee regels hieronder worden twee van de filter objecten aangemaakt:
Filter Filter_TMP37;
Filter Filter_VRT;

Die dan weer in de loop worden gebruikt voor het uitlezen van de analoge ingangen.

Maar hoe zorg ik er voor dat deze regel: static const int N = 32;
Voor iedere analoge ingang die ik wil middelen appart kan instellen?

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.

Ik zie dat nu in basis begrijpt wat een class is. Dat is een grote stap vooruit als je in c++ wilt programmeren.

Als je een array declareert in C moet de grootte van deze array tijdens compile-time beschikbaar zijn. Dit is ook de reden van jouw error die je eerst kreeg. Omdat N niet statisch was kan hij een andere waarde hebben voor iedere instantie van de classe Filter. Dit is ook waar ik op doelde met "niet de meest nette oplossing", omdat het window van het filter niet voor alle filters gelijk is. Je wilt dit per instantie van het filter kunnen aanpassen. Er zijn natuurlijk meerdere manieren om dit op te lossen, maar ik heb hier gekozen voor de volgende oplossing.

http://cpp.sh/5cwz6

Zoals je ziet, maak ik in de main een filter aan waarbij ik mee geef dat ik een window wil hebben van 32 samples. Je zou hier meerdere filters kunnen maken met een window die je per filter kan kiezen. Dit heb ik voor elkaar gekregen door een constructor aan de class toe te voegen. In de constructor maak ik een nieuwe array aan, afhankelijk van de opgegeven grootte (n). De pointer van deze array sla ik op in de variabele meetwaardes.

Wat nog wel even belangrijk is, is de deconstructor. Deze wordt aangeroepen zodra het object wordt verwijderd. Hier moet de array ook weer worden verwijderd. Stel je zou dit niet doen dan kun je een hardfault in de vorm van een stack overflow krijgen. Ik raad je aan om hier een stuk over te lezen!

Ik merk dat ik niet zo een ster ben ik het uitleggen van C++ via een stukje tekst dus ik hoop dat je het snapt. :)

PE2BAS

Ook nu heb ik weer een tijdje zitten staren naar jouw code, ik krijg en error melding die je hier onder kan zien:

Ja sorry, dat is natuurlijk niet de bedoeling.
Ik kon het hier niet testen door het ontbreken van de ADC library op mijn systeem.

En ik had verwacht dat 'const' wel voldoende zou zijn voor een array lengte, net als in het oorspronkelijke voorbeeld. Niet dus, wel voor een globale array, maar niet voor een array binnen de class.

De oplossing van hardbass om de filter diepte in te stellen ziet er wel goed uit.

Wel 2 opmerkingen:
- meetwaardes zou ik nog als int declareren. Geheugen is schaars op een AVR
- de delete in de destructor moet een array delete zijn(extra haakjes). Al maakt dat hier niet veel uit omdat die toch niet gebruikt wordt.

code:


  ~Filter()
   {
      delete[] meetwaardes;
   }
blackdog

Golden Member

Hi,

hardbass
Maak je niet druk wat het uitleggen beteft, ik ben ondermeer op CO begonnen met posten omdat ik mijn uitleg skils wou verbeteren naar ondermeer mijn klanten.
Daar ben ik een stuk beter in geworden maar het rammelt nog wel steeds. :-)

deKees
Ik heb de rechte haakjes in de code gezet zoals je aangaf(denk ik).

De code van hardbass heb ik over getyped, daar copieeren niet wou lukken, dus daar heb ik waarschijnlijk weer typefouten in gemaakt die ik weer niet kan terug vinden.

c code:



#include <ADC.h>

//#include <PID_v1.h>
#include <Wire.h>
#include <ADC.h>

ADC *adc = new ADC();                                                         // ADC object voor de Teensy ADC
 

// Thermistor Eigenschappen Vishay NTCLE300E3502SB
#define RT0 5000                                                              // Ω
#define B 3977                                                                // K

#define VCC 2.4985                                                            // Referentie Spanning
#define R 2368.85                                                             // Weerstand naar de referentie spanning voor de NTC in Ohm

// Variabelen voor NTC
float RT, VR, ln, TX, T0, VRT;

// Configuratie middeling voor de NTC ingang
class Filter {

public:
   int N = 0;                                                                  // Aantal te middelen waarde
   float   *meetwaardes;                                                       // Opslag individuele meetwaarden
   float   accumulator = 0;                                                    // Optelsom van alle individuele meetwaarden
   int   index = 0;                                                            // Meetwaarden teller

   Filter(const int n)
  {
      meetwaardes = new float[n];
      N = n;
  }

    ~Filter()
    {
        delete[] meetwaardes;
    }
    
   void AddSample(int NewSample)
   {  accumulator -= meetwaardes[index];        
      meetwaardes[index] = NewSample;                                          // Bewaar nieuwe meetwaarde
      accumulator += meetwaardes[index];                                       // Accumuleer nieuwste meetwaarde
      index++; 
      index %= N;                                                              // Teller loopt van 0 tot N-1
   }
   
   float Average()
   {  return accumulator/N;                                                    // Bereken de gemmiddelde waarde
   }
};


float T_TMP37 = 0;


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void setup() {
    Serial.begin(115200);

 // Configuratie van ADC_0 Teensy-LC
    adc->adc0->setReference(ADC_REFERENCE::REF_EXT);                            // Selecteer de externe referentie ingang voor ADC_0
    adc->adc0->setAveraging(32);                                                // Selecteer de middeling van de gebruikte ADC
    adc->adc0->setResolution(16);                                               // Selecteerd de resolutie van de geselecteerde ADC
    adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS);     // Selecteerd de conversie snelheid
    adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED);                 // Selecteerd de sample snelheid
    adc->adc0->recalibrate();                                                   // Kalibreeer de ADC

    T0 = 25 + 273.15;                                                           // Temperature T0 from datasheet, conversion from Celsius to kelvin fot the NTC Sensor
}


Filter Filter_TMP37(64);
Filter Filter_VRT(16); 


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void loop() 
{
unsigned long start = micros();                                                   // Debug mode... voor het meten van een deel van de code in de loop


// Middelen van ADC ingang voor de TMP37
  Filter_TMP37.AddSample( analogRead(A9) );
  T_TMP37 = Filter_TMP37.Average() ;                                              // Bereken de gemmiddelde waarde

// Print TMP37 Temperatuur
  Serial.print("TMP37:  ");
  Serial.println(T_TMP37 * (2.4985/65536 / 0.02), 3);                             // Geeft na berekening de gemeten temperatuur van de TMP37 sensor in beeld


// Middelen van ADC ingang voor de NTC
  Filter_VRT.AddSample( analogRead(A8) );
  VRT = Filter_VRT.Average() ;                                                    // Bereken de gemmiddelde waarde
  
// Bereken temperatuur voor de NTC ingang 
  VRT = (2.4985 / 65536.00) * VRT;                                                // Conversion naar spanning
  VR = VCC - VRT;
  RT = VRT / (VR / R);                                                            // Bereken de weerstand van RT

  ln = log(RT / RT0);
  TX = (1 / ((ln / B) + (1 / T0)));                                               // Bereken de Temperatuur in Kelvin

  TX = TX - 273.15;                                                               // Conversie naar Celsius

// Bereken code run time
unsigned long end = micros();
unsigned long delta = end - start;
  Serial.println(delta);

// Print NTC Temperatuur
  Serial.print("Temperature-NTC:");
  Serial.print("\t");
  Serial.print(TX, 3);                                                            // Geeft de gemeten temperatuur van de NTC sensor in beeld
  Serial.print("C\t\t");

  delay(10);
}

Het filter voor de TMP37 heb ik een waarde gegeven van 64 en de NTC heeft een waarde gekregen van 16, deze waarden zijn willekeurig.
De serial output geeft een error voor de NTC uitlezing, zie plaatje hieronder bij: Temperature-NTC: nanC
https://www.bramcam.nl/NA/DS18B20-TMP37-Kal/DS18B20-TMP37-Kal-63.png

deKees, de ADC library wordt geinstaleerd als je het Teensy pakket voor de Arduino IDE installeerd.
Pedro heeft hier veel werk in gestoken: https://github.com/pedvide/ADC/
Lijkt mij niet zinnig voor jou om deze library te installeren als je niet met Teensy werkt.

Ik begrijp niet goed waarom de class voor de TMP37 wel goed werkt maar niet voor de NTC input.
De rede van het niet begrijpen is natuurlijk mijn gebrek aan kennis van C++

Ik heb hier twee boeken liggen die volgens mij vrij goed zijn, deze zijn van Michael McRoberts en van Jack Purdum.
In geen van beide boeken staat een simpele uitleg van het gebruik van classis, wat ik met Google kon vinden, springen ze vaak ook direct in het diepe.
Ik ben geen deKees of hardbass, om dit soort tekst georrienteerde kennis op te nemen heb ik simpele voorbeelden nodig zodat ik rustig aan een basis kan opbouwen.
Een ex vriendin die Neerlandica is en een van mijn zusters die Remedial teacher is hebben mij geprobeerd beter Nederland te leren.
Dat lukt dus niet echt goed, door mijn afwijking kan ik heel goed simpele opdrachten in een keer vastzetten in mijn brein, zoals Rob, een oud collega van mij, hij zij zo'n 40 jaar geleden: Bram,
meegenomen is altijd met twee maal een "e" in het eerste deel, dat heb ik daarna nooit meer fout gedaan.
Mijn brein slaat veel in plaatjes op voor tekst is dat veel moeilijker, en electronica, gooi maar een hand onderdelen op tafel, wat meetapparatuur en geef de richting aan wat je wilt, gaat bijna altijd goed.

Niet zolang geleden mijn handschrift gecontroleerd van schriften van de LTS waar op ik zat, wat ongelovelijk lelijk was dat, luisteren en dan gelijk schrijven met dyslectie kost heel veel processor tijd. :-)
Maar ik klaag niet, ik ken mijn beperkingen, ben ook blij met wat ik wel kan, ik wil alleen duidelijk maken dat ik niet lui ben of het zelf niet zou willen uitzoeken.

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,

Mmmm, ik loop nog tegen iets aan, bij de laatste code is de temperatuur van de TMP37 die wel schijnt de werken hoger hoe hoger is de middeling instel...
Bij de laatste versie van deKees is dit niet zo, daar kan ik dus 1x de middeleing ingeven en die kan ik tussen 1 en 128 varieren en de uitegelezen temperatuur blijft gelijk.
Natuurlijk wel ruis bij het laagste middeling getal maar geen 0,8°C verschil.

Ik vermoet dat dit door de fouten in de code zijn van wat ik net heb laten zien, eerst maar zorgen dat de code goed gaat werekn.

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.

nan betekent Not-A-Number, en betekent een overflow van een float getal.

Het probleem hier is dat de meetwaarde array niet geïnitialiseerd is, dus daar staat ongeldige data. Die wordt sample voor sample overschreven, zodat er op een gegeven moment wel geldige data in de meetwaarde array staat, maar de accumulator komt nooit meer goed hier als die een keer op nan komt door ongeldige array floats.

Het is dus puur toeval dat het voor de TMP37 wel goed gaat. Na powerdown kan het net zo goed andersom zijn.

Je moet hier de array voor gebruik initialiseren. Je kunt de array op 0 zetten, met als gevolg dat de accumulator langzaam naar de eindwaarde toegroeit. Eigenlijk moet je die nullen niet meenemen in je gemiddelde berekening, maar dat maakt het weer ingewikkelder.

Dus :

code:


class Filter {

public:
   int N = 0;                                                                  // Aantal te middelen waarde
   int   *meetwaardes;                                                       // Opslag individuele meetwaarden
   float   accumulator = 0;                                                    // Optelsom van alle individuele meetwaarden
   int   index = 0;                                                            // Meetwaarden teller

   Filter(const int n)
  {
      meetwaardes = new int[n];

      for(int i = 0; i < n; i++)
      {  meetwaardes[i] = 0;
      }

      N = n;
  }

Let op, je moet 2 regels aanpassen om weer terug naar ints te gaan :

code:


   int   *meetwaardes;                                                          

   meetwaardes = new int[n];

En initialisatie kan in de constructor :

code:


      for(int i = 0; i < n; i++)
      {  meetwaardes[i] = 0;
      }

Dit is wel een serieus nadeel van deze methode om een gemiddelde te berekenen:

code:


   void AddSample(int NewSample)
   {  accumulator -= meetwaardes[index];        
      ...

Hier wordt de oude meetwaarde van de accumulator afgetrokken, voordat de nieuwe meetwaarde wordt bijgeteld. Dat gaat dus goed fout, -en komt nooit meer goed- als de accumulator in het begin op 0 staat terwijl de meetwaardes array wel data bevat. Om dit goed te doen moet je accumulator bij het opstarten berekenen uit de som van alle meetwaardes, (of alles op 0 zetten).

[Bericht gewijzigd door deKees op maandag 6 juli 2020 14:15:38 (14%)

deKees heeft het hier juist. Ik vond het al vrij spannend dat alle variabelen niet werden geïnitialiseerd. Ik ging ervan uit dat de Arduino framework dit voor je oploste, omdat het eerst wel goed ging. Als je geen waardes toekent aan de variabelen dan weet je nooit zeker wat er in de variabelen staat. Dit is maar net wat er op dat plekje in RAM stond. Een kleine toevoeging aan deKees zijn antwoord, als je weer met ints wilt werken, je moet ook nog de return van de functie 'Average' op int zetten.

Nog even iets, je gaf aan dat in je boeken niets over classes werd verteld. Dit komt vermoedelijk, omdat je een C boek hebt en niet een C++ boek. Ik raad je aan hier te beginnen. https://www.w3schools.com/cpp/cpp_oop.asp

Ik heb de vrijheid genomen om de code iets op te schonen. Ook heb ik van het filter een template gemaakt, ik raad je aan hier nog even niet in te verdiepen, maar het geeft de mogelijk makkelijk te switchen tussen floats en ints. Ik zou ook nog even de floats gebruiken. Het kost wat meer geheugen en processorkracht al denk ik dat je daar meer dan genoeg van hebt op een Teensy, maar het voordeel is wel dat je niet hoeft na te denken over afrondingsfouten. Eerst maar eens zorgen dat het werkt en dan kun je later nog verbeteren mocht je dat willen.

Ik heb de code even in de bijlage gestopt, zo kun je het kopiëren en blijft de opmaak ook netjes. Voor de leesbaarheid in dit topic ook nog eens tussen de code tags:

c code:


#include <ADC.h>
//#include <PID_v1.h>
#include <Wire.h>
#include <ADC.h>

// Thermistor Eigenschappen Vishay NTCLE300E3502SB
#define RT0 5000                                                              // Ω
#define B 	3977                                                              // K
#define VCC 2.4985                                                            // Referentie Spanning
#define R 	2368.85                                                           // Weerstand naar de referentie spanning voor de NTC in Ohm
#define T0  (25 + 273.15)													  // Temperature T0 from datasheet, conversion from Celsius to kelvin fot the NTC Sensor

ADC *adc = new ADC();                                                         // ADC object voor de Teensy ADC
 


// Configuratie middeling voor de NTC ingang
template <class T>
class Filter 
{
public:
	int N = 0;                                                                // Aantal te middelen waarde
	T *meetwaardes;                                                       // Opslag individuele meetwaarden
	T accumulator = 0;                                                    // Optelsom van alle individuele meetwaarden
	int index = 0;                                                            // Meetwaarden teller

	Filter(const int n)
	{
		meetwaardes = new T[n];
		N = n;
		for(int i = 0; i < n; i++)
		{  
			meetwaardes[i] = 0;
		}
	}

	~Filter()
	{
		delete[] meetwaardes;
	}

	void AddSample(int NewSample)
	{  
		accumulator -= meetwaardes[index];        
		meetwaardes[index] = NewSample;                                          // Bewaar nieuwe meetwaarde
		accumulator += meetwaardes[index];                                       // Accumuleer nieuwste meetwaarde
		index++; 
		index %= N;                                                              // Teller loopt van 0 tot N-1
	}

	T Average()
	{  
		return accumulator/N;                                                    // Bereken de gemmiddelde waarde
	}
};





//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void setup() 
{
    Serial.begin(115200);
	
 // Configuratie van ADC_0 Teensy-LC
    adc->adc0->setReference(ADC_REFERENCE::REF_EXT);                            // Selecteer de externe referentie ingang voor ADC_0
    adc->adc0->setAveraging(32);                                                // Selecteer de middeling van de gebruikte ADC
    adc->adc0->setResolution(16);                                               // Selecteerd de resolutie van de geselecteerde ADC
    adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS);     // Selecteerd de conversie snelheid
    adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED);                 // Selecteerd de sample snelheid
    adc->adc0->recalibrate();                                                   // Kalibreeer de ADC
                
}


Filter<float> Filter_TMP37(64);
Filter<float> Filter_NTC(16); 

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void loop() 
{
	
	unsigned long start = micros();                                                

	//Temperatuur van de TMP37
	float sample_TMP37_RAW = (float)analogRead(A9);
	float sample_TMP37_Celcius = sample_TMP37_RAW * (2.4985/65536 / 0.02);	
	


	//Temperatuur van de NTC
	float sample_NTC_RAW = (float)analogRead(A8);
	float VRT = 2.4985 * sample_NTC_RAW / 65536.00; 
	float VR = VCC - VRT;
	float RT = VRT * R / VR; 
	float ln = log(RT / RT0);
	float TX = (1 / ((ln / B) + (1 / T0)));                                        
	float sample_NTC_Celcius = TX - 273.15;   


	//Samples toevoegen aan het filter.
	Filter_TMP37.AddSample(sample_TMP37_Celcius);
	Filter_NTC.AddSample(sample_NTC_Celcius);

	//Uitlezen resultaat filters.
	float avg_TMP37_Celcius = Filter_TMP37.Average();
	float avg_NTC_Celcius = Filter_NTC.Average();

	// Print TMP37 Temperatuur
	Serial.print("TMP37: ");
	Serial.print(avg_TMP37_Celcius, 3);                          
	Serial.print("C\t\t\t");
	
	// Print NTC Temperatuur
	Serial.print("Temperature-NTC: ");
	Serial.print(avg_NTC_Celcius, 3);                                                            // Geeft de gemeten temperatuur van de NTC sensor in beeld
	Serial.println("C");

	// Bereken code run time
	unsigned long end = micros();
	unsigned long delta = end - start;
	Serial.println(delta);

	delay(10);
}
PE2BAS