Goedemiddag allemaal,

Drie jaar geleden heb ik mijn eerste echte, ik had eerst een DSO nano, oscilloscope gekocht. Een OWON SDS7072. Deze scope heeft een bandbreedte van 70MHz en een samplerate van 1GSa/S. Afgelopen drie jaar heb ik veel met deze oscilloscope gemeten en daarnaast alle functies en mogelijkheden onderzocht.

Eén van deze functies is het opslaan van de meetdata. Deze meetdata kan opgeslagen worden als een .bmp plaatje, of als .bin databestand. Het opslaan als .bmp plaatje heb ik regelmatig gebruikt, maar het .bin databestand kon ik nog niet zoveel mee.

Inmiddels heb ik ook redelijk wat ervaring opgedaan met "GNU Octave", de open source variant van Matlab. Hiermee kan je eigenlijk alles doen op gebied van dataverwerking.

Nu kwam bij mij een tijdje terug het idee boven drijven om deze .bin databestanden te lezen en te verwerken met GNU Octave. En dat heb ik dus maar eens geprobeerd.

In deze post is te vinden wat ik tot nu toe heb uitgevonden van de indeling van het databestand en hoe je met GNU Octave dit bestand kan lezen en verwerken. Mijn grootste bron is dit bestand van OWON zelf. Hierin wordt, in gebrekkig Engels, beschreven hoe het databestand in elkaar zit. Erg mooi dat OWON dit wil delen met de gebruikers van de OWON scope's.

Er bestaat ook nog een mogelijkheid om de .bin databestanden via USB of ethernet binnen te halen, tot nu toe doe ik dat nog via een usb flash drive. Eventueel kan in een later stadium ook het binnenhalen van de bestanden door GNU Octave worden overgenomen.

Maar nu to-the-point.

.bin databestand ontleden

Als basis van deze beschrijving gebruik ik dit .bin bestand om te verwerken.

Het is belangrijk om te weten dat het bestand Little-Endian is. Bij het lezen van een 32 bit integer (= 4 bytes) staan de bytes dus van LSB naar MSB. Ook zijn alle byte's signed.

Octave script

Het octave script is een mooie lap tekst geworden. Het effectieve script is slechts 15 regels. Het script bestaat dus voornamelijk uit commentaar om het script te verduidelijken.

% Open het .bin databestand. "le" opent het bestand als Little-Endian
fileID = fopen("20160722_255650.bin", "r", "ieee-le");

% Lees het .bin databestand, dit bestand bestaat uit signed characters
% en deze worden in de array 'data' opgeslagen.
data = fread(fileID,"signed char");

% Sluit het bestand, de data uit het bestand staat nu in het geheugen.
fclose(fileID);

% BEGIN MET HET VERWERKEN VAN DE DATA

% Deze arrays bevatten de niveau's van de volt/div en van de t/div.
voltage_level_lookup  = [2e-3 5e-3 10e-3 20e-3 50e-3 100e-3 200e-3 500e-3 1 2 5 10];
timebase_level_lookup = [2e-9 5e-9 10e-9 20e-9 50e-9 100e-9 200e-9 500e-9 1e-6 2e-6 5e-6 10e-6 20e-6 50e-6 100e-6 200e-6 500e-6 1e-3 2e-3 5e-3 10e-3 20e-3 50e-3 100e-3 200e-3 500e-3 1 2 5 10 20 50 100];


% Byte 57 bevat het kanaal nummer, geformateerd als ASCII. Door daar 48 af 
% te trekken wordt het kanaalnummer van ASCII omgezet naar decimaal. 
channel = data(57) - 48


% Byte 58 t/m 61 bevat de data block lengte (geteld vanaf Byte 58). De 
% typecast maakt van de 4 losse bytes één 32-bit integer. Als deze 
% block lengte negatief is dan gaat het om een deep memory wave.
data_length = typecast(int8(data(58:61)),'int32');


% Byte 82 t/m 85 bevat de index voor het timebase level welke daarna
% gebruikt kan worden om de bijbehorende array "timebase_level_lookup" uit
% te lezen. Er wordt 1 bij opgeteld omdat de array index beginnen te tellen
% bij 1 en de ontvangen index begint te tellen bij 0.
timebase = timebase_level_lookup(typecast(int8(data(82:85)),'int32')+1)


% Byte 86 t/m 89 bevat de voltage offset van het kanaal. Dus op welk 
% punt de 0 volt lijn ligt (op het scopescherm).
y_offset = typecast(int8(data(86:89)),'int32');


% Byte 90 t/m 93 bevat de index voor het voltage level welke daarna
% gebruikt kan worden om de bijbehorende array "voltage_level_lookup" uit
% te lezen. Er wordt 1 bij opgeteld omdat de array index beginnen te tellen
% bij 1 en de ontvangen index begint te tellen bij 0.
voltage = voltage_level_lookup(typecast(int8(data(90:93)),'int32')+1)


% Byte 94 t/m 97 bevat de ingestelde probe verzwakking. Deze waarde wordt
% gegeven als macht van 10. (Net zoals het exponent bij wetenschappelijke
% notatie).
probe_attenuation = 10 ^ typecast(int8(data(94:97)),'int32');


% Byte 98 t/m 101 bevat de x-as interval. Gegeven in uS. Deze is nodig 
% om tijdens het plotten de x-as te maken. Moet gelezen worden als float
% en wordt daarom getypecast naar 'single'.
timebase_interval = typecast(int8(data(98:101)),'single')*1e-6;


% Byte 102 t/m 105 zouden volgens de handleiding de frequentie moeten bevatten
% in alle binfiles die ik door de scope heb laten maken staat deze op 
% nul. Ik moet nog uitzoeken wat ik hiermee kan.


% Byte 106 t/m 109 zouden volgens de handleiding de cycle moeten bevatten
% in alle binfiles die ik door de scope heb laten maken staat deze op 
% nul. Ik moet nog uitzoeken wat ik hiermee kan.


% Byte 110 t/m 113 bevat de y-as interval. Gegeven in mV (of mA als op
% het kanaal de ampere probe is ingeschakeld). Deze moet vermenigvuldigd
% worden met de wave om de exacte spanningsniveaus weer te geven.
voltage_interval = typecast(int8(data(110:113)),'single')*1e-3;


% Byte 114 t/m de laatste byte van het bestand bevat de wave. Deze moet 
% worden gelezen als allemaal signed acht bit getallen. De functie 'double'
% zorgt ervoor dat deze wordt opgeslagen als een float, zodat deze later met
% de y-as interval (welke ook een float is) kan worden vermenigvuldigd.
wave = double(data(118:end) - y_offset);


% Hier begint het plotten, maak er maar wat moois van! :)
plot([0:timebase_interval:timebase_interval*(numel(wave)-1)], wave.*voltage_interval);

Het bovenstaande script levert deze plot op. Door het schalen is deze niet echt leesbaar meer, het gaat om het idee. Octave heeft ook een functie om plots te exporteren, hier moet ik nog mee experimenteren om mooie afbeeldingen te laten produceren.

http://e-miel.nl/co/owon_scope/screenshot_01.png

Hopelijk kunnen jullie hier iets mee. Misschien zijn er andere scopes die soortgelijke bestanden kunnen produceren waar ook eens mee geëxperimenteerd kan worden.

Groeten,
Emiel

Ha Emiel,

Mooi stukje werk. Petje af!

groet, Gertjan.

Goedenavond,

Gertjan, bedankt!

Het is inmiddels ook gelukt de data binnen te trekken via een TCP verbinding met de oscilloscope. Dus dit betekend geen gehannes met een flash drive en .bin bestanden meer.

Octave kan zelf met behulp van het 'Instrument-Control' package verbinding maken met de oscilloscope en de data opvragen. Bijkomende voordelen zijn dat kanaal één én kanaal twee tegelijk opgevraagd kunnen worden en dat de resolutie een stuk hoger ligt. Bij het .bin bestand was dit nog 8 bits, bij de TCP overdracht is dit 16 bits. Ik begrijp nog niet helemaal waar deze resolutie opeens vandaan komt, de ADC's van de oscilloscope zijn maar 8 bits.

Een interessante ontdekking die ik inmiddels heb gedaan is dat het signaal binnen de +5 en -5 div´s moet liggen, komt het erbuiten dan 'overflowt' de waarde.

Ook een leuke bijkomstigheid bij het meten via TCP is middelen. Hieronder twee plaatjes (wederom nog niet echt leesbaar). Links een enkele meting, Rechts 500 keer gemiddeld. De oscilloscope heeft ook een optie om te middelen, maar deze gaat maar tot 128 keer.

http://e-miel.nl/co/owon_scope/middelen.png

Zodra ik de functie voor het ophalen van de data wat opgefrist heb zal ik hem uploaden en hier plaatsen. Nu bezig met een plot en export functie.

Groeten,
Emiel

ps. wie raadt wat ik aan het meten ben?

Hi leime,

Ik denk dat je een "stabiliteit" meet, bij bepaalde belasting variaties...

:-)
Blackdog

PS
Leuk dat je je uitzoekwerk hier toont!

Ha Blackdog,

Jij moest natuurlijk ook wel je eigen signaal herkennen. De blauwe trace is het signaal uit mijn BDTPG (BlackDogTestPulsGenerator) 500Hz, 10% duty-cycle met flanken van 5us. Ik zal deze generator als deze volledig afgebouwd is binnenkort wel showen in het daarvoor bestemde topic.

Groeten,
Emiel

Goedemiddag,

Een kleine update.

Ik ben nog weer even bezig geweest met mijn scripts. Ik heb het nu zo gemaakt dat er ook metingen toegevoegd kunnen worden. Dat kan dan door simpleweg "measure_pkpk(channel1)" te doen. Deze zoekt dan automatisch de min en max waarde op en plot deze bij in het venster. Ook heb ik al een losse "measure_min(channel2)" en "measure_max(channel2)" gemaakt. Ik kan dus nu op het moment dat ik dit nodig heb gemakkelijk een nieuwe meet-functie toevoegen.

http://www.e-miel.nl/co/owon_scope/screenshot_02.png

Ik zal ook nog een mooie plek moeten vinden voor het aangeven van de gekozen instellingen. Met dit paatje kun je natuurlijk nog niet zo heel veel. Ik denk dat ik deze aan de onderkant van de plot ga plaatsen. Een eventueel alternatief is onder de titel van de plot.

Hier is de functie die ik gebruik om de data op te halen te vinden. De data wordt door de functie opgeslagen in een struct.

Het grootste verschil met het script dat ik in mijn eerste post heb laten zien is dat, zoals ik al aangaf, de data via de ethernet verbinding wordt doorgegeven als een 16bit signed integer ipv een bit signed integer. Ook worden nu beide kanalen in één keer opgehaald.

Groeten,
Emiel