We leggen graag uit hoe je de data van onze stadssensoren zelf ook kunt gebruiken. Deze uitleg hoort bij ons Smart City project voor de Kanaalzone in Alkmaar: https://junioriot.nl/burgernetwerken/

In vogelvlucht – hoe stroomt de data door onze systemen

Onze software op de sensoren zorgt ervoor dat de meetgegevens als een compact bericht wordt verstuurd via Lora. Volgens de regels van Lora sturen we ongeveer eens per 4 minuten een data bericht. Zodra dit wordt ontvangen door TTN, The Things Network, zorgt onze decoder software dat er per verzonden bericht een los bestand ontstaat, een file in Json formaat. Met Json kunnen we flexibel velden toevoegen, aanpassen en verwijderen.

Wij hebben ingesteld dat elk Json bericht direct doorstroomt naar onze dataopslag in onze data cloud bij Amazon AWS, waar het direct via een Amazon API wordt doorgegeven aan onze Lambda functie, waarmee meerdere files worden aangemaakt in de S3 opslag. In een configuratieveld bij deze Lambda functie stellen we nog enkele parameters in voor het spelen van het GPS spel, en het registreren van extra data op de kaart. We slaan alle files voor je op in een structuur die past bij de aanpak met partitionering voor Big Data analyse in AWS. De files zijn via static web hosting op de S3 bucket en Route53 beschikbaar onder een unieke url. We merken dat de file binnen enkele secondes na de meting al beschikbaar is; zo kunnen we elke meting echt ‘real-time’ volgen.

Elke opgeslagen datafile kan je benaderen in je webbrowser. De filenamen zijn uniek, met de datum/tijd van de meting, en zijn daardoor echter onvoorspelbaar. Om de losse datafiles te vinden, hebben we ervoor gezorgd voor index bestanden. Omdat de filenaam van deze indexen wel voorspelbaar is, kunnen we hiermee de meetdata makkelijk automatisch ophalen.

Met een webapplicatie voor de Smart City Challenge in 2018 laten we zien hoe je deze meetdata makkelijk kunt ophalen en zichtbaar maken. Alle software voor de landkaart en de bijbehorende grafieken draait gewoon in de browser. Daardoor kan je de code van deze software zelf bekijken om te onderzoeken hoe wij dit hebben gedaan. Je ontdekt dan hoe we omgaan met de indexen en de logfiles.

Als je zelf gaat bouwen: Let op dat je bewust omgaat met het lezen van onze data. Zeker voor automatische data loads naar jouw server werk je alleen met de nieuwe aanvullingen. We willen voorkomen dat er continu data wordt gelezen. Bij meer dan ‘incidenteel’ gebruik zal de rekening voor onze dataopslag merkbaar op gaan lopen, en dat is geen deel van onze propositie. Je wilt voorkomen dat jouw datafeed per ongeluk automatisch wordt afgesloten.

Uitgangspunten – basic principles

Met 20 jaar ervaring in ICT, datamanagement en Big Data kan ik een aantal handvatten formuleren waarmee we makkelijker onze data omgeving kunnen inrichten, onderhouden en verder kunnen laten groeien.

Serverless data flow

De verwerking van Lora berichten in TTN verloopt via een samenwerking van queues, buffers en transformaties. Een goede configuratie zorgt ervoor dat elk bericht onderweg de juiste stappen doorloopt, en uitkomt bij de verwerking of de opslag die bij dat bericht past.

Op geen enkel moment is het nodig om ons daarbij druk te maken over technische aspecten die te maken hebben met hardware en servers: We hoeven niets te weten, in te stellen of te reserveren rond het aantal servers, verwerkingscapaciteit, CPU’s, bandbreedtes, hosting, opschalen en loadbalancing. Dit is binnen TTN voor ons geregeld, onzichtbaar verstopt achter de services die we gebruiken.

De rest van de datapipeline hebben we op dezelfde manier opgebouwd. Daardoor maakt het voor de hele pipeline niet uit of we één bericht per minuut moeten verwerken, of drie miljoen – ons landschap is technisch reeds geoptimaliseerd voor beide scenario’s.

Kosten. We zien geen losse servers, en we huren geen losse servers. Dit maakt de kosten beter beheersbaar. We betalen voor het opslaan en opvragen per bericht een paar microcent; de kosten dansen daardoor naadloos mee omhoog als jouw gebruik omhooggaat.

Geen traditioneel gebruik van data

Traditioneel data gebruik is geen Big Bata: Traditioneel wordt data gefilterd en opgeslagen in databases en tabellen die zijn afgestemd op een zeker gebruiksdoel. Denk dan aan een webwinkel met orders, producten en inventaris. De applicatie die erbij hoort bepaalt welke datasets nodig zijn. Voor elke toepassing wordt gericht een datastructuur ontworpen, met vaste tabellen en kolommen.

Dit ontwerp is alleen geldig gedurende de lifecycle van de betreffende applicatie. Naast de applicatie heeft de data weinig reden om te bestaan. In onze toepassing gebruiken we een andere benadering om juist de data centraal te stellen.

Onze data heeft Big Data eigenschappen

Bij onze meetdata begrijpen we intuïtief al dat de waarde in de data zit, en een applicatie van ondergeschikt belang is. Een weergave applicatie is alleen maar een hulpmiddel of een instrument om iets met deze meetdata te doen.

Onze meetdata leeft. We leren nieuwe dingen, en bouwen nieuwe sensoren waarmee weer andere dingen worden gemeten. In de datastroom ontstaan vanaf een zekere datum nieuwe velden. Op andere momenten in de lifecycle kunnen velden ook weer verdwijnen.

De vastgelegde meetwaarden welke op een zeker meetmoment zijn vastgelegd zullen echter nooit veranderen. Iets wat eenmaal is vastgelegd, hoeft niet meer te veranderen.

Dit ‘meetwaardes veranderen niet’ is erg belangrijk. De originele files blijven ongewijzigd, ook als we onderweg iets nieuws leren, waardoor we de gemeten waardes anders interpreteren. De interpretatie van de data staat los van de dataopslag.

Dataflow gaat altijd vooruit

Bij Big Data tools is het een gegeven dat opgeslagen datasets niet worden gemuteerd. Het past beter bij de Big Data gedachte om data niet te interpreteren of te bewerken voordat deze wordt opgeslagen. Opgeslagen data is bovendien read-only. Zo is er altijd maar één versie van de waarheid. Data ‘in motion’ kan wel veranderen.

Deze gedachte leg ik uit aan de hand van onze decibel waardes. Technisch meten we een analoge geluidssterkte, maar in alle communicaties spreken we over decibel. De decibel waarde is dan de uitkomst van een berekening, het is aldus eigenlijk een interpretatie als onderdeel van de datastroom. Dit betekent voor ons dat we in de datastroom de decibel waarde toevoegen en dan ook de originele meetgegevens behouden in de databerichten.

Indien we later door onze ervaring een betere formule ontdekken voor de decibel waarde, dan kunnen we een verbeterde versie toevoegen in de interpretatie. Maar op dat moment zullen we deze niet opslaan als deel van de originele bestanden; immers deze blijven ongewijzigd.

Velden en veld namen

We leggen de waardes vast met duidelijke, en vooral betekenisvolle namen. Het kan daarbij door groeiend inzicht gebeuren dat bij de ontwikkeling van ons product een aantal veldnamen wordt aangepast. We proberen deze aanpassingen zoveel mogelijk te beperken.

In de veldnamen gebruiken we een soort hiërarchie of groepering binnen de naam. Bijvoorbeeld alle waarden afkomstig van de BME280 sensor beginnen met BME280_. Een handig bijeffect is dat in lijsten, toelichtingen, data weergaven deze velden doorgaans alfabetisch bij elkaar gesorteerd worden.

Als eenmaal een correcte benaming is gekozen, dan houden we hieraan vast, zolang de betekenis van de data gelijk blijft. Ook bij herstel van fouten in de meetapparatuur behouden we dezelfde veldnamen; ook als een trendbreuk ontstaat in de data. Hergebruik van een veldnaam voor een geheel andere betekenis is niet de bedoeling.

Een eenmaal gekozen naam hanteren we vervolgens door alle stadia die de data doormaakt. Dit kan, en moet, want de waarde verandert immers niet.

In de decoder zie je de namen voor de output values, zoals de velden in de Json genoemd worden. De interne naam in de decoder software is dan dezelfde variabele naam met een _ underscore als prefix. Zo blijft de naamgeving voldoende consistent. Het doel is dat dezelfde variabele namen worden gebruikt in de Arduino code waar het Lora bericht wordt aangemaakt.

Geen edits en deletes in opgeslagen data

Elk sensor meetmoment levert een databestand met meetwaarden. Deze bestanden worden in principe niet meer aangepast.

Mochten we willen breken met deze regel, dan is dat alleen als het écht niet anders kan worden opgelost. Een oplossing via verdere verwerkingsstappen, of in de visualisatie laag gaat altijd voor. En als we toch de bestanden aanpassen, dan voegen we alleen velden toe; nooit vervangen of verwijderen we bestaande data.

We vragen je ook deze gedachte aan te houden in de verdere verwerking van de data. Als je onze files overneemt in ons systeem, hou dan alle data aan. Ook als je er nog geen doelstelling voor hebt. Geloof mij, dit voorkomt je een hoop vermijdbare re-engineering en vervelende excuus vergaderingen.

Afleidingen, formules zijn herhaalbaar, brondata altijd opgeslagen

Doordat de originele meetdata altijd door de hele data pipeline beschikbaar blijft, kunnen andere varianten op de interpretaties worden ontwikkeld.

Voor wetenschapers klinkt het als onwaarschijnlijk dat een interpretatie noemenswaardig verandert. De formule voor een decibel is immers behoorlijk duidelijk vastgelegd. Een denkbaar voorbeeld is wellicht indien we ontdekken dat we de wegingsfactoren in onze formule voor dB(A) anders hebben ingesteld dan onze partner RIVM dit verwacht. Het zou zomaar kunnen.

Een veranderende interpretatie is wel meer gebruikelijk bij financiële data waarmee bedrijfsbeslissingen worden gestuurd. En een andere betekenis vraagt hierbij telkens om een andere veldnaam. Zo kunnen meerdere interpretaties zonder probleem naast elkaar blijven bestaan.

Data afnemers lezen alleen de delta’s

Met de informatie onder de andere kopjes begrijpen we nu dat data die eenmaal is gepubliceerd niet zal veranderen. Waar bij traditionele data de data middels transacties continu verandert, is dat bij ons nadrukkelijk niet het geval.

Hierdoor is het nuttig om als data afnemer dagelijks alleen de ontbrekende files van de voorgaande dag in te laden. Deze opmerking is relevant.

In de praktijk, bijvoorbeeld bij Azure, is het veel makkelijker om een ‘full initial load’ te configureren, en deze dan dagelijks te herhalen. De systemen zijn dan iedere dag data opnieuw aan het overpompen die hoofdzakelijk niet verandert. De ontwikkelaar komt weg met de uitleg ‘maar de brondata kan veranderen’ – deze uitleg geldt in ons geval echter niet. Te veel herhaling kan bovendien worden gedetecteerd als misbruik. Het lijkt erop dat het zelfherstellend vermogen van onze serverless omgeving een dergelijke afnemer de toegang tot de data ontzegt, geheel automatisch, en zonder dat wij het merken.

Suggesties om het anders te doen, en lessons learned

Onze datapipeline is ontstaan bij ons eerste GPS tracker project wat in 2016 is begonnen. Maar ook de beslissingen in dat project steunen weer op ervaring en vuistregels uit datawarehousing en datamanagement. Het doel is onze data en de onderdelen van de pipeline een zo lang mogelijke Lifecycle of zo lang mogelijk bestaansrecht te geven.

Je zou onze pipeline kunnen aanpassen om makkelijker te passen bij de klik-en-sleep versie in Azure van vandaag. Of we kunnen overleggen over welke velden je wel en niet nodig hebt, en dat je kleinere files leuker vindt. En vanuit een ander applicatie perspectief zou je andere wensen kunnen ontdekken. Dit zijn echter vermijdbare discussies. We hebben dit neergezet in pure vorm, zonder de budgetten van de grote ICT-bedrijven. We laten met een eenvoudige proof-of-concept kaart- en grafiek applicatie zien dat de data werkbaar is.

Desondanks kunnen we onze aanpak opeens aanpassen. Of het ritme van de data kan veranderen. Het aantal velden zal zeker nog kunnen groeien. Wij passen ons aan, en elk deel van onze pipeline voegt zich dan soepel naar de aanpassing. Het beste is om ook in jouw software rekening te houden met verandering.

Data format – Json vanuit de decoder

Vanuit onze decoder software in TTN ontstaat ons Json data bericht. Dit wordt min of meer zonder verdere aanpassingen opgeslagen in AWS, en dat is ook de data die jouw applicatie zal consumeren. Alle data die we relevant vinden zit hierin. Daarmee is dit een goede start voor een uitgebreide toelichting.

De programmacode van deze decoder zal een waardevol en beknopt handvat vormen voor de developer die de data wil gebruiken. Om een idee te vormen kan je in github kijken naar de toelichting, en ook naar de code van de decoder van één van onze eerdere projecten: https://github.com/JuniorIOT/Junior-IOT-in-a-box-Project

Een ander compact begin voor de developer is een voorbeeld file te nemen van de actuele data. Project deelnemers in een andere rol zullen eerder kijken naar de actuele data grafiek bij één van hun sensoren.

Niet alle velden zullen zijn gevuld met data. Dat hangt af van de versie van de sensor, en de meetwaardes die we voor die toepassing hebben gekozen. Niet gebruikte velden vertonen iedere keer een vast getal, een dummy waarde, of zijn niet opgenomen in de Json files. Dat verschilt per veld, en per versie van onze implementatie. In onze voorbeeld grafieken zie je dan dat voor zo’n veld geen grafieklijn wordt toegevoegd.

Kijk naar de data om te herkennen hoe deze dat vandaag bij jouw sensors is geregeld, en hou er rekening mee dat hier verandering in kan komen.

Voorbeeld datafile

Als voorbeeld datafile kan je kijken naar: http://junioriotchallenge.nl/ttn_data/ttn_messages_partitioned/app=bvhva-samenmeten/y=2021/m=02/d=24/2021-02-24%2023.39.09.25331.txt

Deze meetwaarde betreft de Smart City sensor op overstad, geplaatst naast de Junior IOT werkplaats. De sensor is geplaatst op een mast, en staat circa 5 meter boven het maaiveld. Er is rondom voldoende vrij zicht, zodat het Lora signaal onbelemmerd alle kanten op wordt verzonden,

Het betreffende bericht laat dan ook zien dat het door 7 gateways wordt ontvangen. We ontdekken de gateways en de signaal sterkte in onze regio via bijvoorbeeld TTN Mapper. Deze gateways zijn:

  • eui-c0ee40ffff29f2da, rssi= -114. De heatmap suggereert dat deze gateway in de buurt van Junior IOT is te vinden, maar het signaal is daar eigenlijk niet sterk genoeg voor.
  • eui-008000000000ba5b, rssi= -120. Deze ‘Triple LoraWanGW2 Outdoor’ staat op het bedrijfspand van Tripple.
  • eui-0000024b080e0c15, rssi= -117. De gateway ‘Data Science Alkmaar/VU 1’ van gemeente Alkmaar staat op het dak van de telefooncentrale.
  • junior_iot_bus_001, rssi= -72. De gateway ‘junior_iot_bus_001’ staat in de Junior IOT werkplaats, op 5 meter afstand van de zender.
  • eui-0000024b080e0bb6, rssi= -89. Deze gateway is ‘Data Science Alkmaar/VU 2’ en staat boven op het stadskantoor.
  • eui-b827ebfffef799b1, rssi= -96. We vinden deze op de kaart midden in de huiswaard als ‘DX-TTN-V2’, vermoedelijk een particuliere gateway.
  • eui-58a0cbfffe8019b8, rssi= -43. Gezien de heatmap lijkt deze gateway zich ook in de Junior IOT werkplaats te bevinden. We moeten misschien binnen een keer gaan opruimen.

Uit dit enkele bericht kunnen we al concluderen dat data ontvangst vanaf deze opstelling absoluut geen probleem is. Ook wanneer enkele gateways onverhoopt wegvallen zal de ontvangst goed blijven.

Bekijk hier de inhoud van de data file…
{
	"resource": "/",
	"path": "/",
	"httpMethod": "PUT",
	"headers": {
		"Accept-Encoding": "gzip",
		"CloudFront-Forwarded-Proto": "https",
		"CloudFront-Is-Desktop-Viewer": "true",
		"CloudFront-Is-Mobile-Viewer": "false",
		"CloudFront-Is-SmartTV-Viewer": "false",
		"CloudFront-Is-Tablet-Viewer": "false",
		"CloudFront-Viewer-Country": "IE",
		"content-type": "application/json",
		"Host": "a8gd4bvigb.execute-api.eu-west-1.amazonaws.com",
		"User-Agent": "http-ttn/2.6.0",
		"Via": "2.0 7dc07eed8f5996bab114638bc1ffca05.cloudfront.net (CloudFront)",
		"X-Amz-Cf-Id": "R5uINo45jF4lY_3yJG9INEbdn9aTGC-KPIr4yCQzDQyNzTx8m-lC8A==",
		"X-Amzn-Trace-Id": "Root=1-6036e39d-55758357210e2c6b54846856",
		"X-Forwarded-For": "52.169.225.45, 70.132.45.144",
		"X-Forwarded-Port": "443",
		"X-Forwarded-Proto": "https"
	},
	"multiValueHeaders": {
		"Accept-Encoding": ["gzip"],
		"CloudFront-Forwarded-Proto": ["https"],
		"CloudFront-Is-Desktop-Viewer": ["true"],
		"CloudFront-Is-Mobile-Viewer": ["false"],
		"CloudFront-Is-SmartTV-Viewer": ["false"],
		"CloudFront-Is-Tablet-Viewer": ["false"],
		"CloudFront-Viewer-Country": ["IE"],
		"content-type": ["application/json"],
		"Host": ["a8gd4bvigb.execute-api.eu-west-1.amazonaws.com"],
		"User-Agent": ["http-ttn/2.6.0"],
		"Via": ["2.0 7dc07eed8f5996bab114638bc1ffca05.cloudfront.net (CloudFront)"],
		"X-Amz-Cf-Id": ["R5uINo45jF4lY_3yJG9INEbdn9aTGC-KPIr4yCQzDQyNzTx8m-lC8A=="],
		"X-Amzn-Trace-Id": ["Root=1-6036e39d-55758357210e2c6b54846856"],
		"X-Forwarded-For": ["52.169.225.45, 70.132.45.144"],
		"X-Forwarded-Port": ["443"],
		"X-Forwarded-Proto": ["https"]
	},
	"queryStringParameters": null,
	"multiValueQueryStringParameters": null,
	"pathParameters": null,
	"stageVariables": null,
	"requestContext": {
		"resourceId": "3owsj86a35",
		"resourcePath": "/",
		"httpMethod": "PUT",
		"extendedRequestId": "bRiAoFrLDoEFkjg=",
		"requestTime": "24/Feb/2021:23:39:09 +0000",
		"path": "/prod",
		"accountId": "667242083879",
		"protocol": "HTTP/1.1",
		"stage": "prod",
		"domainPrefix": "a8gd4bvigb",
		"requestTimeEpoch": 1614209949541,
		"requestId": "62872e88-de8a-4d27-8dee-70e1465d1713",
		"identity": {
			"cognitoIdentityPoolId": null,
			"accountId": null,
			"cognitoIdentityId": null,
			"caller": null,
			"sourceIp": "52.169.225.45",
			"principalOrgId": null,
			"accessKey": null,
			"cognitoAuthenticationType": null,
			"cognitoAuthenticationProvider": null,
			"userArn": null,
			"userAgent": "http-ttn/2.6.0",
			"user": null
		},
		"domainName": "a8gd4bvigb.execute-api.eu-west-1.amazonaws.com",
		"apiId": "a8gd4bvigb"
	},
	"isBase64Encoded": false,
	"body": {
		"app_id": "bvhva-samenmeten",
		"dev_id": "alkmaar2021-009",
		"hardware_serial": "00D6FD994A11DE4A",
		"port": 1,
		"counter": 49,
		"payload_raw": "yt0Tg2CgAAAAAAAAAAAAAAAAAAAAAAAAAAArrRtYKAkAPQEiAAAAAAAAAAAAlwCyAMgAnAC3AJwAsgkBAQAAAAMIAALbAAWcAAEkAAb6AA7SAAHoJxAAAAAAAiYAAA==",
		"payload_fields": {
			"BME280_Hum": 70,
			"BME280_Press": 102490,
			"BME280_Temp": 11.81,
			"BME280internal_Hum": 0,
			"BME280internal_Press": 0,
			"BME280internal_Temp": 0,
			"LAT": "52.638457",
			"LON": "4.749538",
			"Lux": 0,
			"P": 1024.9,
			"PM10": 29,
			"PM25": 6.1,
			"RH": 70,
			"T": 11.81,
			"Vbat": 3.64,
			"Vsupply": 5.1,
			"arduino_VCC": 0,
			"arduino_Vbat": 0,
			"arduino_tempCPU": -100,
			"bytes_length": 94,
			"dB_EQ7_1____63Hz": -10.4,
			"dB_EQ7_2___160Hz": -8.97,
			"dB_EQ7_3___400Hz": -7.96,
			"dB_EQ7_4__1000Hz": -10.12,
			"dB_EQ7_5__2500Hz": -8.73,
			"dB_EQ7_6__6250Hz": -10.12,
			"dB_EQ7_7_16000Hz": -8.97,
			"dB_Vmic": 0,
			"dB_Vmic_ref": 0,
			"dB_activated": 0,
			"dB_flag": 1,
			"dB_levelflag": 1,
			"dB_samplecount": 9,
			"dBa_avg": 54.93,
			"dBa_max": 60.79,
			"dBa_min": 46.96,
			"dBc_avg": 62.69,
			"dBc_max": 69.23,
			"dBc_min": 51.42,
			"dBc_val": 0,
			"gps_alt": 0,
			"gps_hdop": 0,
			"gps_lat": "52.638457",
			"gps_lng": "4.749538",
			"pm10": 29,
			"pm25": 6.1,
			"raw_dB_EQ7_1": 151,
			"raw_dB_EQ7_2": 178,
			"raw_dB_EQ7_3": 200,
			"raw_dB_EQ7_4": 156,
			"raw_dB_EQ7_5": 183,
			"raw_dB_EQ7_6": 156,
			"raw_dB_EQ7_7": 178,
			"raw_dBa_avg": 731,
			"raw_dBa_max": 1436,
			"raw_dBa_min": 292,
			"raw_dBc_avg": 1786,
			"raw_dBc_max": 3794,
			"raw_dBc_min": 488
		},
		"metadata": {
			"time": "2021-02-24T23:39:09.253315088Z",
			"frequency": 867.9,
			"modulation": "LORA",
			"data_rate": "SF7BW125",
			"coding_rate": "4/5",
			"gateways": [{
				"gtw_id": "eui-c0ee40ffff29f2da",
				"timestamp": 3587583580,
				"time": "",
				"channel": 7,
				"rssi": -114,
				"snr": -6,
				"rf_chain": 0
			}, {
				"gtw_id": "eui-008000000000ba5b",
				"timestamp": 698627836,
				"time": "2021-02-25T02:08:51.317214Z",
				"channel": 7,
				"rssi": -120,
				"snr": -4,
				"rf_chain": 0,
				"latitude": 52.62452,
				"longitude": 4.77436,
				"altitude": 14
			}, {
				"gtw_id": "eui-0000024b080e0c15",
				"timestamp": 4235280908,
				"time": "2021-02-24T23:39:09.239779Z",
				"channel": 7,
				"rssi": -117,
				"snr": -2.2,
				"rf_chain": 0,
				"latitude": 52.61756,
				"longitude": 4.76675,
				"altitude": 21
			}, {
				"gtw_id": "junior_iot_bus_001",
				"timestamp": 3703469156,
				"time": "2021-02-24T23:39:11Z",
				"channel": 0,
				"rssi": -72,
				"snr": 8.25,
				"rf_chain": 0
			}, {
				"gtw_id": "eui-0000024b080e0bb6",
				"timestamp": 3689718876,
				"time": "2021-02-24T23:39:09.239771Z",
				"channel": 7,
				"rssi": -89,
				"snr": 9,
				"rf_chain": 0,
				"latitude": 52.63545,
				"longitude": 4.74609,
				"altitude": 21
			}, {
				"gtw_id": "eui-b827ebfffef799b1",
				"timestamp": 3120564380,
				"time": "2021-02-24T23:39:08.239769Z",
				"channel": 7,
				"rssi": -96,
				"snr": 9.8,
				"rf_chain": 0,
				"latitude": 52.64538,
				"longitude": 4.76077,
				"altitude": 14
			}, {
				"gtw_id": "eui-58a0cbfffe8019b8",
				"timestamp": 3306161116,
				"time": "2021-02-24T23:39:09.449579Z",
				"channel": 0,
				"rssi": -43,
				"snr": 10,
				"rf_chain": 0
			}]
		}
	},
	"message_ymdhm": 202102242339,
	"url": "http://junioriotchallenge.nl/ttn_data/ttn_messages_partitioned/app=bvhva-samenmeten/y=2021/m=02/d=24/2021-02-24 23.39.09.25331.txt"
}

 

Amazon data objecten – te negeren

De data wordt opgeslagen zoals deze door onze API in AWS wordt ontvangen. Dit betekent dat in het ‘headers’ object en in multiValueHeaders informatie wordt weergegeven over Cloudfront, User-agent en de forwarding naar AWS. Het is interessant om de timestamp van de verwerking te zien, maar verder heb ik nog geen toepassing gevonden voor deze informatie.

Ook het requestContext object toont timestamps, en andere informatie over de reis die dit bericht heeft meegemaakt.

Het ‘body’ object bevat de data vanuit TTN

Het ‘body’ object geeft ons het eigenlijke bericht zoals het vanuit TTN aan de API in AWS is verzonden. Het geeft inze inhoud, plus de context betreffende de afhandeling in TTN. Hier zitten heel leerzame onderdelen tussen.

Het ‘counter’ veld informeert ons over de voortgangsteller; een waarde die we in de Arduino code bewust aan het bericht moeten meegeven. Wanneer de spanning wegvalt wordt in de Arduino code de teller terug gezet naar 0.

Payload_raw toont een bijzondere ascii weergave van de Lora data string. Let op, dit is encoded, en is niet zo bruikbaar als bijvoorbeeld de binaire weergave.

Het metadata object geeft informatie over de datumtijd van ontvangst in TTN, over de lora zendmethode en de modulatie. Je ziet hier dat wij de data altijd verzenden op een nette, beschaafde methode volgens spreading factor SF7.

Binnen het metadata object is bovendien een verzameling ‘gateways’ beschikbaar, waarin gegevens zoals ontvangststerkte wordt getoond voor elke TTN gateway waar het bericht is ontvangen. De gps locatie en plaatsingshoogte van de gateway zijn zichtbaar. Een rssi hoger dan -110 geeft vertrouwen dat de berichten vanaf de betreffende locatie goed ontvangen zullen worden. Een lijst van meer dan één of twee gateways geeft ook aan dat data vanaf de betreffende locatie altijd goed ontvangen zal worden. Een overzicht van gateways in jouw regio, met een indicatie voor de ontvangst sterkte kan je zien op  bijvoorbeeld https://ttnmapper.org/heatmap/

Het veld ‘message_ymdhm’ hebben wij middels onze data pipeline toegevoegd om duidelijker weer te geven welke datum en tijd we gebruiken als timestamp voor het bericht. Dit is belangrijk voor de url waar we het bericht hebben opgeslagen. Let op: De datum en tijd van de berichten worden genoteerd in GMT wereld tijd. Dit betekent dat de weergave éénk of twee uur scheef loopt met onze zomer- en wintertijd. Een handige vuistregel is dat het meest recente bericht ongeveer vier minuten geleden is geplaatst.

Het veld ‘url’ hebben we ook middels onze data pipeline toegevoegd, om aan te geven waar het bericht is opgeslagen. Een voorbeeld is de waarde:  http://junioriotchallenge.nl/ttn_data/ttn_messages_partitioned/app=bvhva-samenmeten/y=2021/m=02/d=24/2021-02-24 23.39.09.25331.txt

Onze meetdata vind je in het object ‘payload_fields’ binnen de ‘body’. Hierbinnen vind je onze data velden met de betreffende meetdata.

De ruim 60 datavelden en hun beschrijving

Bij de veldbeschrijving zie je soms ook het aantal bytes dat de waarde inneemt in het Lora bericht. Dit is informatief en kan je als programmeur in principe verder negeren. Wanneer meer bytes worden gebruikt dan heeft de doorgegeven waarde een grotere range of een hogere precisie.

Een deel van de code en de toelichting is na te zien in één van onze eerdere projecten op GitHub: https://github.com/JuniorIOT/Junior-IOT-in-a-box-Project

Sensors die worden gemeten

We werken met

  • SDS011 voor fijnstof
  • BME280 voor temperatuur, luchtdruk en luchtvochtigheid
  • Een Lux meter
  • BN180 als GPS
  • Interne meetwaarden uit de Arduin CPU
  • Een custom decibel sensor board
  • Controle metingen van meerdere voltages middels spanningsdeler
  • Frequentiebanden voor geluid middels de EQ7

De electronica wordt ingebouwd met een accupakket in een luchtarmatuur (2020), of is op verzoek voorzien van een compacte behuizing met accupakket en lader (2021).

Onderlinge beïnvloeding en externe beïnvloeding is mogelijk. In de data is het volgende te herkennen als warmte effecten:

  • In een lichtarmatuur functioneert de verlichting in feite als een verwarming van 40 watt. Hierdoor zal de binnentemperatuur aanmerkelijk oplopen wanneer het licht aangeschakeld wordt. De meting wordt gedaan in een afgescheiden sectie welke aan het armatuur is gemonteerd.
  • De meetunit in een armatuur, maar ook die in een compacte behuizing zal in de volle zon opwarmen.
  • In een compacte behuizing, verbonden met een voeding die af en toe aan gaat, wordt de batterij iedere dag enkele uren krachtig geladen. Tijdens het laden kan de temperatuur wellicht enkele graden oplopen. De lader is in feite een verwarming van 1 tot 5 watt afhankelijk van de laadsterkte.

Waar we verder rekening mee houden:

  • De SDS011 heeft een ventilator om lucht langs de meter te voeren. De motor geeft een 30dB achtergrond geluid, en we willen nog lagere geluidsterktes kunnen meten. De SDS wordt in elke meetcyclus 20 tot 30 seconden aangeschakeld, gedurende welke tijd geen audio meting wordt gedaan.
  • Voor lage geluidsterktes is een uiterst gevoelige meting nodig. De electronica is ontworpen met nauwkeurigere componenten dan gebruikelijk is. Met electronische afscherming wordt bovendien electromagnetische storing vermeden.
  • Hardere wind langs de machine wordt gemeten als geluid.
  • Theoretisch kan de temperatuur en de voedingsspanning een zekere invloed hebben op de geluidsmeting, verschilend voor de verschillende types electronica componenten. Voor enkele units worden controlemetingen doorgegeven om te beoordelen welke correctie wenselijk is.
  • De BME280 is in de luchtstroom van de SDS011 geplaatst en meet daardoor vanuit de veilige omgeving toch zo goed mogelijk de buitenlucht.
  • De microfoon is buiten op de unit geplaatst, voorzien van een windkap, onder een afdakje. De microfoon wijst onder een hoek van 45 graden naar beneden. Doorgaans wordt de unit zo geplaatst dat deze naar de weg of naar de dichtbijzijnde drukke plek wijst.
  • De lichtsensor is naast de microfoon geplaatst, en wijst in een hoek van 45 graden naar beneden.
  • De GPS antenne wordt door een metalen behuizing gestoord, en is daarom onder een kunststof dop geplaatst. Het metalen deksel kan in een volgende versie een kunststof plaat worden.
  • De Lora antenne wordt door een metalen behuizinbg gestoord, en is daarom naast de microfoon aan de buitenzijde geplaatst. Het metalen deksel kan in een volgende versie een kunststof plaat worden.

GPS data

De eerste bytes van ons bericht zijn gereserveerd voor de locatie data. We gebruiken dit om de locatie van de sensor dynamisch te bepalen. Ook bij vaste locaties, en we voorkomen hiermee dat een aparte administratie nodig is voor de locatie van de sensor. Dit is een betrouwbare manier om locatie ook echt in de data zelf mee te kunnen nemen.

De TTN Mapper applicatie leest deze data ook, om te bepalen wat de netwerk dekking is op de locaties waar onze sensoren zijn geweest. Daarvoor worden de eerste 9 bytes van de ruwe data gelezen, welke daarvoor in een afgesproken format zijn samengesteld.

Diepere techniek details, de decoder en de veldbeschrijvingen, alsook de electrische aansluitgegevens zijn in te zien op onze pagina over de 2017 GPS Tracker: https://junioriot.nl/gps-tracker-2017/. Een zeer gedetailleerde achtergrond beschrijving inclusief details over het aanmaken van een applicatie in TTN, en de volledige bouw instructie van de GPS-tracker vind je op onze leerling/docent pagina: https://junioriot.nl/bouw-je-gps-tracker/

gps_lat. Drie bytes. Van -90 tot +90 graden.

gps_lng. Drie bytes, van -180 tot +180 graden. Positie nauwkeurigheid van ruim 2 meter; wat iets nauwkeuriger is dan de reguliere gps-plaatsbepaling.

gps_alt. Twee bytes. Hoogte van 0 tot 65025 meter. Waardes onder de zeespiegel worden in de Arduino code naar boven afgerond naar 0.

gps_hdop. Een enkele byte. Horizontal degree of precision, een indicatie van meetnauwkeurigheid. Waarde van 0 tot 25.5. Bij een waarde tot circa 4 is de plaatsbepaling nauwkeurig.

Analoge poorten

Het is mogelijk om onze sensoren te gebruiken om te monitoren of een deur open en dicht is. Of een andere analoge of digitale meting te monitoren. Dit hebben we gebruikt bij het spel waarbij juniors de stad veroveren. Enkele test-sensoren in de kasten van Stadswerk072 monitoren via een schakelaar of een LDR of een kastdeur open of dicht is. Het moment dat een ‘open/dicht’ situatie verandert, wordt via gps-tijd ook vastgelegd, dit tijdstip wordt in het databericht meegezonden.

In de huidige implementatie van de stadssensoren wordt deze data niet meegegeven. De locatie in de datastring moet bovendien herzien wegens overlap met andere waardes.

A0..A5       2 bytes, 10 bit analog read from A1 = TEMT6000  0..1023 A0on_dt DateTime btn on    4 bytes, bits 6 Y-2000, 4 M, 5 D, 5 H, 6 M, 6 S A0off_dt DateTime btn off    4 bytes, bits 6 Y-2000, 4 M, 5 D, 5 H, 6 M, 6 S

Internals

Traditioneel meten we een aantal standaard waardes om onze meetunit in de gaten te houden.

arduino_VCC. Een enkele byte. Het Lora32U4 board heeft ingebouwde monitoring voor de voedingspannig. Dit is geen officieel supported meting van de betreffende chip. De waarde houden we in stand om eer te doen aan de tradities uit onze eerdere projecten. Een waarde 0 geeft doorgaans aan dat de meting niet aanwezig is.

arduino_tempCPU. Een enkele byte. We hebben bij ons GPS-ballonproject de ingebouwde thermometer van de Lora32u4 gebruikt. Echter, de afwijking kan oplopen tot 10 graden. In de Alkmaar Smart City sensoren gebruiken we in plaats van deze waarde nu de betrouwbare BME280. Een waarde -100 geeft doorgaans aan dat de meting niet aanwezig is.

arduino_Vbatt. Een enkele byte. Ons Lora32U4 board heeft een ingebouwde meter om de on-board batterij in de gaten te houden. Echter, om de sensoren en andere extra apparatuur te voeden wordt nu een groter accu pakket. Deze meetwaarde wordt daarom bij de Alkmaar Smart City sensoren niet gebruikt. Een waarde 0 geeft doorgaans aan dat de meting niet aanwezig is.

Payload. De string weergave van de originele message. Deze was in TTN zichtbaar bij ‘data in motion’ maar niet bij de data zoals opgeslagen in de TTN data store. Het kan voor debugging handig zijn deze waarde af en toe aan te zetten, al is dat de laatste jaren niet meer nodig geweest.

Bytes_length of payload_size. De lengte fan het Lora bericht. Het kan voor debugging handig zijn deze waarde af en toe aan te zetten, al is dat de laatste jaren niet meer nodig geweest.

Smart City Sensoren

Reeds in 2018 hebben we verdere Smart City sensoring toegevoegd aan onze data. Met mobiele trackers werden de juniors de binnenstad van Alkmaar in gestuurd om de meetwaardes in kaart te brengen. Dit is dan ook de reden dat onze kaart nog telkens inzoomt op de binnenstad van Alkmaar. Milieu waardes werden gemeten met een BME280 voor temperatuur, luchtvochtigheid en luchtdruk, een SDS011 voor fijnstof PM 10 en PM 2,5, en een CO2 meter.

Op de kaart werden real-time de teamkleuren weergegeven in de vlakjes. Het aantal veroverde vlakjes was als teamscore zichtbaar naast de kaart.

De SDS en de BME zijn nog steeds de meest actuele en gangbare sensors voor deze soort toepassing, en zijn ook in 2021 onderdeel van de nieuwe Smart City sensoren. De BME is bij de nieuwe opstelling geplaatst in de luchtstroom van de SDS om werkelijk de buitenlucht te meten.

BME280_Temp. Twee bytes. Temperatuurmeting met nauwkeurige weergave per 1/100ste graad.

BME280_Hum. Twee bytes. Relatieve vochtigheid RH in percentage van 0 tot 100, doorgegeven met 1/100 nauwkeurigheid. Ergens in het dataproces wordt de waarde op gehele getallen afgerond, wat een leerzaam getrapt effect heeft op de grafiek.

BME280_Press. Twee bytes. Luchtdruk in tienden. De gemiddeld gemeten waarde is ruim 100.000, de waarde wordt blijkbaar doorgegeven in Pascal. Op weerkaarten wordt een waarde van 100.000 Pa doorgaans weergegeven als 1000 hPa.

pm10. Twee bytes. Fijnstof 10 um, de vanuit de SDS gemeten waarde wordt in tienden nauwkeurig doorgegeven.

pm25. Twee bytes. Fijnstof 2,5 um, de vanuit de SDS gemeten waarde wordt in tienden nauwkeurig doorgegeven.

Bij sommige test versies van de nieuwe Smart City sensor is ook de interne atmosfeer in de behuizing gemeten. Dit kan nut hebben bij onderzoek naar de toepasbaarheid in een lichtarmatuur, waar het doorgaans droog en warm is. We zien de waardes duidelijk verlopen zodra de lichtarmaturen aangeschakeld worden. Een uitzonderlijke waarde kan een indicatie zijn van defecten in het armatuur. Details en de time-line van dit deel van het project hebben we in 2020 beschreven in onze uitgebreide toelichting: https://junioriot.nl/lora-straatverlichting/

BME280internal_Temp. Twee bytes. Temperatuurmeting met nauwkeurige weergave per 1/100ste graad. Een waarde 0 geeft doorgaans aan dat de sensor niet aanwezig is.

BME280internal_Hum. Twee bytes. Relatieve vochtigheid RH in percentage van 0 tot 100. Ergens in het dataproces wordt de waarde op gehele getallen afgerond, wat een leerzaam getrapt effect heeft op de grafiek. Een waarde 0 geeft doorgaans aan dat de sensor niet aanwezig is.

BME280internal_Press. Twee bytes. Luchtdruk in tienden. Een waarde 0 geeft doorgaans aan dat de sensor niet aanwezig is.

Data formatted voor RIVM

Met RIVM hebben we een afspraak gemaakt dat de data van onze applicatie wordt opgenomen in hun data set. Zodra we een sensor toevoegen aan zo’n applicatie wordt deze automatisch ook toegevoegd aan de RIVM kaart.

We hebben in het beginstadium enkele tekortkomingen geconstateerd, maar hebben nog niet gecontroleerd of deze zijn verholpen. De data van sensoren in elkaars nabijheid wordt samengevoegd tot één grafiek. Detectie of een sensor binnen of buiten is geplaatst werkt niet, en fijnstof data van zo’n binnen sensor beïnvloed de stofkaart van Nederland. Van slechts enkele velden is een grafiek zichtbaar, en mogelijk wordt onze extra data niet bij RIVM opgeslagen. Slechts beperkte data beschikbaar voor afnemers van RIVM-data.

Om de Smart City data te gebruiken adviseren we onze directe route te volgen.

T. Temperatuur, identiek aan BME280_Temp

RH. Relatieve luchtvochtigheid, identiek aan BME280_Hum

P. Luchtdruk, dit is BME280_Press / 100

PM10. Fijnstof 10 um, identiek aan de waarde pm10.

PM25. Fijnstof 2,5 um, identiek aan de waarde pm25.

LAT. Locatie, identiek aan de waarde gps_lat.

LON. Locatie, identiek aan de waarde gps_lng.

Decibel metingen

De metingen van geluidsterkte gebeuren met een speciaal ingeregelde microfoon. De meetwaardes uit de microfoon worden middels een tweetal analoge weeg circuits omgezet naar de meting welke geschikt is voor dB(A) en dB(C). Vervolgens wordt de meetwaarde middels een AD-converter digitaal ingelezen, en middels een logaritmische formule vertaald naar decibel als dB(A) en dB(C).

Het circuit is uiterst zorgvuldig gebouwd om ook lage decibelwaardes te kunnen registreren. De logaritmische schaal maakt het lastig om in één meting de hele kleine alsook de grotere geluidsterktes te meten, en daarom schakelt het meetcircuit bij grotere geluidsterktes terug naar een ‘mildere’ meetstand.

In andere geluidsmetingen zagen we bijvoorbeeld digitale softwareoplossingen met Fourier analyses. Om hiermee een betrouwbaar resultaat te behalen is doorgaans een krachtigere chip nodig dan de bediening van de sensors voorhanden is. Hierdoor worden nu concessies in de software gedaan waarmee de meting onzuiver is. Bovendien zal bij elke sensorset een nieuwe software implementatie worden gedaan, en afhankelijk van libraries, instellingen, CPU-kracht een ander meetresultaat opleveren. We zagen dat er in de markt nog geen betrouwbare implementatie beschikbaar was.

Om zo’n digitale meting te vermijden heeft Leo ons analoge meetcircuit ontworpen. Hiermee wordt de meting onafhankelijk van lastige software implementaties. We verwachten op elke toepassingswijze dan ook een betrouwbaar en vergelijkbaar resultaat. Na inbouw in de behuizing wordt de dB meter bovendien afgesteld, met een semiprofessionele ‘ijk-machine’. Hoe de gedachtengang tot de geluidsmeting tot stand is gekomen, lees je op de blogpost van Thijs uit 2018: https://junioriot.nl/citizen-science-hart-van-alkmaar/

Bij de decibel meetwaardes hebben we na onze testperiode de meer passende naamgeving ontdekt. Hieronder zie je telkens de combinatie: nieuwe naam / oude naam. De overgang vindt plaats op ongeveer 25 februari 2021. Data is ongewijzigd, waardoor de data onder de oude naam gewoon gebruikt kan blijven worden. Het overgangsmoment is te zien in deze grafiek pagina: http://junioriotchallenge.nl/graph/?dateStart=20210222&dateEnd=20210225&application=bvhva-samenmeten&device=alkmaar2021-009

Meetwaardes:

Lux. De waarde van de lichtmeting aan de Smart City Stadssensor.

Vsupply / Noise9_Vpsu. De interne spanning welke door de converter na het accupack wordt aangeboden aan de overige componenten van de Stadssensor.

Vbat / Noise7_Vbatt. De batterijspanning. Wanneer de stadssensor aan de geschakelde voeding van de stadsverlichting is gemonteerd, kunnen we in deze grafiek herkennen hoeveel tijd de sensor kan overbruggen zonder externe voedingsspanning. Een dalende spanning geeft aan dat de externe voeding ‘uit’ staat. Een oplopende spanning geeft aan dat het accupack wordt geladen.

Aan de ontladingscurve van de Smart City unit ‘alkmaar2021-009’ van 24 februari 2021 zien we dat de accu in 23 uur terug loopt van de laadspanning van 4,2 volt naar een waarde van 3 volt. Boven deze batterijspanning van 3 volt blijft het apparaat goed functioneren. Onder de 3 volt blijkt er nog 15 tot 30 minuten bedrijfsduur beschikbaar te zijn. We verwachten dat bij een iets verouderde batterij de bedrijfsduur 10-25% kan afnemen.

dB_activated / Noise5_pushpull. Een Status flag: 0 is goed, 1 geeft aan dat er een storing is op de 5V voeding naar de DB meter print. In dat geval worden er geen DB-meetwaardes meegegeven.

dB_Vmic / Noise1_Comp. De spanning op de microfoon. Dit is een controlemeting om te analyseren in hoeverre de aansturings FET verloopt vanwege bijvoorbeeld de temperatuur. Wordt niet in alle sensor units gemeten. Een waarde 0 geeft doorgaans aan dat de meting niet aanwezig is.

dBc_val / Noise2_dB. Gemeten dB(C) waarde. Is bij meer recente sensors vervangen door dBc_min, dBc_max, dBc_avg. Een waarde 0 geeft doorgaans aan dat de meting niet aanwezig is.

dB_Vmic_ref / Noise3_Ref. Referentie spanning van precies 3 volt voor de FET-microfoon. Als deze constant blijft dan wordt de microfoon goed uitgelezen. Data alleen bij FET-microfoons. Een waarde 0 geeft doorgaans aan dat de meting niet aanwezig is.

dB_samplecount / Noise4_Loops. Het aantal samples welke gemeten zijn om _min, _max en _avg te bepalen. Bij onze gebruikelijke configuratie zit er circa 4 minuten tussen de data berichten. Andere metingen nemen 30 seconden. Tussen de geluidssamples zit telkens zo’n 20 seconden en het aantal samples is dan doorgaans 9. De geluidssterkte betreft hiermee ongeveer de afgelopen 4 minuten.

dB_flag / Noise8_Version. Een serie flags die aangeeft of er in dit model een dB meter circuit is gemonteerd. De waarde 1 geeft aan dat de aangeleverde dB waardes volgens de huidige afspraak wordt behandeld. In situatie voor februari 2021 is bij waarde 0 andere dB waarde aangeleverd, welke naar andere positie in het Lora bericht c.q. andere byte breedte is gedecodeerd. Kan in een later stadium vervallen zodra alle sensoren met dB zijn uitgevoerd.

dB_levelflag / level. Een serie flags die aangeeft of omlaag is geschakeld in meetsterkte. De eerste bit, waarde 1, geeft aan dat de dBa en dBc meting omlaag is geschakeld. De tweede bit, waarde 2, geeft aan dat de EQ7 meetwaardes omlaag zijn geschakeld. Dit geeft sturing aan de formule waarmee de dB waarde wordt bepaald.

dBa_avg / NoiseA_avg_dbA. De gemiddelde waarde over de gemeten samples voor dB(A)

dBa_max / NoiseB_max_dbA. De hoogste waarde over de gemeten samples voor dB(A)

dBa_min / NoiseC_Min_dbA. De laagste waarde over de gemeten samples voor dB(A)

dBc_avg / NoiseD_avg_dbC. De gemiddelde waarde over de gemeten samples voor dB(C)

dBc_max / NoiseE_max_dbC. De hoogste waarde over de gemeten samples voor dB(C)

dBc_min / NoiseF_Min_dbC. De laagste waarde over de gemeten samples voor dB(C)

raw_*. De ruwe onbewerkte meting zoals gemeten door de DA-converter.

EQ7 geluidsmetingen

De laatste geluidssample wordt door een standaard EQ7 chip opgesplitst in 7 overlappende frequentiebanden. Hiermee wordt het hoorbare spectrum van circa 0 tot 20.000 Hz opgedeeld in nette, overlappende delen.

We verwachten dat met deze meting een indicatie kan worden ontwikkeld in hoeverre het gemeten geluid als meer of minder hinderlijk wordt ervaren in de stadse omgeving. Wellicht kan zelfs het verschil worden gesignaleerd tussen mensen, muziek, verkeer, airco’s, machines en meer.

De 7 frequentiebanden worden weergegeven in de datasheet op sparkfun.

(bron: https://cdn.sparkfun.com/datasheets/Dev/Arduino/Shields/MSGEQ7_5-11.pdf)

dB_EQ7_1____63Hz. Geluidsterkte in dB van de eerste frequentieband, gelijkmatig rond 63 Hz.
dB_EQ7_2___160Hz. Geluidsterkte in dB van de 2e frequentieband, gelijkmatig rond 160 Hz.
dB_EQ7_3___400Hz. Geluidsterkte in dB van de 3e frequentieband, gelijkmatig rond 400 Hz.
dB_EQ7_4__1000Hz. Geluidsterkte in dB van de 4e frequentieband, gelijkmatig rond 1000 Hz.
dB_EQ7_5__2500Hz. Geluidsterkte in dB van de 5e frequentieband, gelijkmatig rond 2500 Hz.
dB_EQ7_6__6250Hz. Geluidsterkte in dB van de 6e frequentieband, gelijkmatig rond 6250 Hz.
dB_EQ7_7_16000Hz. Geluidsterkte in dB van de 7e frequentieband, gelijkmatig rond 1600 Hz.

raw_*. De ruwe onbewerkte meting zoals gemeten door de DA-converter.