Port WaveForms SDK na Pascal
Analog OUT - tryb DC

część 9

podstawowe informacje o urządzeniu i sterowanie zasilaczem
cykliczna akwizycja danych i histereza triggera
UART - Digital I/O i obsługa protokołów
I2C - Digital I/O i obsługa protokołów
SPI - Digital I/O i obsługa protokołów (mostek Wheatstone'a)
SPI - Digital I/O i obsługa protokołów (pomiar Iadj w LM317)
Digital I/O - ROM Mode, przerzutnik RS i dekoder do rosyjskiej VFD
Digital I/O - bezpośredni dostęp, wyświetlacz HDSP-2111 i termometr MCP9700
Analog OUT - woltomierz True RMS z przetwarzaniem sygnału

☘☘☘☘☘☘☘☘☘
woltomierz True RMS z przetwarzaniem sygnału

Obsługa analogowego wyjścia jest banalnie prosta, WaveForms SDK dostarcza jak zwykle komplet funkcji o spójnym i wygodnym w użyciu interfejsie. Generowanie przebiegów o różnym kształcie do pasjonujących nie należy, więc tym chwilowo zajmować się nie będziemy. Za to generowanie składowej stałej (DC), choć na pierwszy rzut oka nudne jak wczorajsza owsianka, można ubrać w większy temat, a przy okazji wykorzystać wcześniej opracowane kawałki kodu i układ na płytce stykowej.

MEA-1, 100uA

Głównym bohaterem wieczorynki będzie stary (rocznik '65), ale ciągle w pełni sprawny mikroamperomierz typu MEA-1 o nominalnym prądzie 100uA i rezystancji ceweczki 2kΩ, widzimy go na fotografii poniżej.



To typowy ustrój magnetoelektryczny klasy 1.5 wyposażony w dużą lusterkową skalę, mimo drobnych rysek i zżółknięć - działający doskonale. Ot, bazarowa zdobycz w ramach podtrzymywania farta w polowaniu.
Ustrój w formie woltomierza podłączyłam do wyjścia W1 (generator AD2, kanał 1) przez odpowiednio dobrany rezystor - posobnik. Drobne wyliczenia dla maksymalnego napięcia wyjściowego generatora równego 5V takie:

Uw=(Rm+Rp)Im
Uw=RmIm+RpIm
Rp=(Uw-RmIm)/Im = ( 5 - 100E-6 * 2E3 )/100E-6 = 48E3 = 48kΩ


W praktyce wyliczanka powyższa oznacza konieczność wstawienia stałego rezystora 40kΩ i niebieskiego potka 10kΩ do precyzyjnego wycyrklowania maksymalnego wychylenia wskazówki. Faktem, że skala ma podziałkę do 100, a my operujemy napięciem maksymalnym 5V nie należy się przejmować. Instalację testową przedstawia zdjęcie:



Działanie programu testowego, sterującego generatorem tak aby ustawiać wartości 0..10 widzimy na filmiku:



Oczywiście pascalowa implementacja zabawki: ➮ https://github.com/bienata/AnalogDiscovery2/blob/master/analogout_meter_1/analogout_meter_1.lpr i niejako z obowiązku kilka słów o API bloku Analog OUT naszego Analog Discovery 2. Na pracę wybranego kanału wyjściowego zezwalamy funkcją FDwfAnalogOutNodeEnableSet, tryb pracy (funkcję) generatora ustalamy wywołując FDwfAnalogOutNodeFunctionSet, z parametrów podstawowych tego co pojawi się na wyjściu interesuje na w tym przypadku amplituda, zatem do kompletu mam funkcję FDwfAnalogOutNodeAmplitudeSet. Całe wywołanie ustawiające inicjalne 0V na wyjściu pracującego bloku może wyglądać mniej więcej tak:

//analogout_meter_1.lpr
FDwfAnalogOutNodeEnableSet( hAd2, 0, AnalogOutNodeCarrier, true );
FDwfAnalogOutNodeFunctionSet( hAd2, 0, AnalogOutNodeCarrier, funcDC );
FDwfAnalogOutNodeAmplitudeSet( hAd2, 0, AnalogOutNodeCarrier, 0 (* napiecie wyjsciowe *) );

Uruchomiony blok generatora na nowe wartości amplitudy (jak i fazy, częstotliwości, etc) reaguje natychmiast, podając je kolejno w pętli możemy nacieszyć się kicającą po skali wskazówką.

A tak przy okazji - mimo dokładnego ustawienia wychylenia na 100 działek przy 5.0V tak gdzieś w 3/4 skali daje się zauważyć nieliniowość wskazań ustroju. Z czego wynikają? No cóż, przyrząd ma słuszne lata i trudno też oczekiwać, że nie ma za sobą żadnych przygód, choćby udarów mechanicznych wpływających na jednorodność pola magnetycznego w obrębie cewki, taki life i już. Oczywiście jest możliwość skorygowania takiego zachowania choćby programowo - przecież mamy pełną kontrolę nad tym co jest podawane na ustrój, ale to kiedy indziej.

true RMS

No i właśnie - skoro mamy w miarę opanowane sterowanie ustrojem i możemy prezentować na nim różne wartości w klasycznej, analogowej formie to czemu by nie zbudować ... woltomierza wartości skutecznej AC?

Koncepcyjnie zabawka sprowadza się do schematu jak poniżej:



Wykorzystałam to, co zostało przygotowane na okazję termometru z wyświetlaczem HDSP-2111 i odczytem wartości analogowej w trybie akwizycji danych do buforka. Jak pokazać wartość skuteczną? Można na upartego podzielić pozyskaną amplitudę przez pierwiastek z dwóch, ale wtedy nie byłoby zabawy. Zatem najpierw do poczytania:

➮ https://pl.wikipedia.org/wiki/Warto%C5%9B%C4%87_skuteczna
➮ http://www.eletrica.ufpr.br/edu/artigos/CIL22-012_final_gerson.pdf

Do wyliczenia RMS potrzebujemy zatem tabeli z próbkami, możliwie jak największej - tu przyjęłam sporo, bo całe 8k, samplowane z dość dużą częstotliwością:

//analogout_meter_2.lpr
const MAX_SAMPLES = 8192;
var samplesBuff : array [0..MAX_SAMPLES-1] of double;
//inicjalizacja IN
FDwfAnalogInFrequencySet( hAd2, 4E+6 ); // fs=4MHz
FDwfAnalogInBufferSizeSet( hAd2, MAX_SAMPLES ); // buforek 8k sampli


No i oczywiście cykliczne wyliczanie wartości skutecznej z tak zachomikowanych danych:

//analogout_meter_2.lpr
// RMS
U := 0.0;
for i := 0 to MAX_SAMPLES-1 do U := U + samplesBuff[ i ] * samplesBuff[ i ] ;
U := sqrt( U/MAX_SAMPLES );
// poslij na miernik
FDwfAnalogOutNodeOffsetSet( hAd2, 0, AnalogOutNodeCarrier, U/2 );


Prezentacja odbywa się jednocześnie na plastikowym wyświetlaczu i staroświeckim ustroju pomiarowym. Kontrola jakości przy pomocy oscyloskopu i niezastąpionego V640, zerknijmy na garść zdjęć dla różnych wartości sygnału wejściowego:

0V



1V



2V



3V



4V



Kolejny filmik (przepraszam za mizerną jakość, ale coś mi zabolieła PIXORD-owa kamerka) przedstawia całą instalację bardziej na żywo podczas zmian poziomu wyjściowego z generatora KZ1404



Kompletny kod programiku do RMS znajdziemy w lokalizacji ➮ https://github.com/bienata/AnalogDiscovery2/blob/master/analogout_meter_2/analogout_meter_2.lpr i w zasadzie tak mogłaby się ta pisanka zakończyć, ale...

gratisik - składowa stała

Jak nietrudno zauważyć powyższe wyliczanki i pomiary przeprowadzane były dla sygnału przemiennego, ale przy zerowej (w miarę możliwości) składowej stałej. Dodanie owej do przebiegu spowodowało, że całe moje pomiarowe towarzystwo przestało mieć wspólne zdanie odnośnie wyników - każdy pokazywał po swojemu. Zacznijmy zatem od spreparowania nowego programiku, który do obliczeń RMS weźmie tylko i wyłącznie składową AC, cześć stała zostanie wyłuskana i posłuży do prezentacji, ale z wyniku jej się pozbędziemy. Oto fragment zmodyfikowanej części obliczeniowej:

//analogout_meter_3.lpr
// DC
Udc := 0;
for i := 0 to MAX_SAMPLES-1 do Udc := Udc + samplesBuff[ i ];
Udc := Udc/MAX_SAMPLES;
// RMS AC
Urms := 0.0;
for i := 0 to MAX_SAMPLES-1 do Urms := Urms + (samplesBuff[ i ] - Udc)*(samplesBuff[ i ] - Udc);
Urms := sqrt( Urms/MAX_SAMPLES );
// poslij na miernik
FDwfAnalogOutNodeOffsetSet( hAd2, 0, AnalogOutNodeCarrier, Urms/2 );

I teraz garstka pomiarów, gdzie Meratronik V640 mierzy wartość RMS odfiltrowując składową stałą (przycisk LF) a dżenderuśny Rigol ma wejście ustawione w trybie DC (łapie i składową stałą i zmienną)





Jak widać programik podrasowany nieco poradził sobie z odcedzeniem składowej DC, cała aplikacja tu: ➮ https://github.com/bienata/AnalogDiscovery2/blob/master/analogout_meter_3/analogout_meter_3.lpr

A przy okazji - zerknijmy jak dla takiego sygnału testowego zachowa się neonowy V543:



Wciśnięcie DC - pokaże na lampkach nam tylko i wyłącznie składową DC sygnału, wciśnięcie AC - składową zmienną. A jak kto ma chęć, to proszę zerknąć jak do tego podchodzi WaveForms w oknie oscyloskopu, gdy poprosimy aby pokazać predefiniowane pomiary dla wybranego kanału (view/measurements) - tam jest do wyboru AC RMS i DC RMS. W sumie to logiczne - skoro te wartości powstają na skutek obróbki numerycznej, to można sobie wybierać co potrzeba.

No i na koniec zagadka drobna, może jednak komuś będzie się chciało zerknąć w listingi i zastanowić odrobinę. A mianowicie: po zapisaniu jako nowy projekt programiku w Pascal z poprzedniego odcinka, tego od temperatury z LM35, dołożyłam sterowanie wyjściem napięciowym AD2, podałam 4V z generatora i ... wyskoczyło na konsolę jak na zdjęciu, po lewo.



Wynik wprawdzie był, ale jednak daleki od tego co mi się wyśniło. Po chwili namóżdżania się nad kodem dał się zauważyć drobiazg, który był przyczynkiem tych durnych wyników. Po poprawieniu jednej wartości, wyliczana wartość zaczęła być całkiem sensowna, widzimy ją po prawej stronie zdjęcia. Powstaje pytanie - na czym polegała niedoróbka?

♣♣♣

odpowiedź - clipping

No więc jedynym słusznym rozwiązaniem zjawiska krzywych wartości RMS jest - ograniczanie amplitudy sygnału w torze przetwarzania A/C, z angielskiego tak zwany
➮ clipping. Przykrość sytuacji polega na tym, że wartości wejściowe przekraczające zakres pomiarowy konwertera A/C generują wartości liczbowe na poziomie maksymalnie dopuszczalnej wartości. Konsekwencją jest zniekształcenie przebiegu w formie takiego jakby przystrzyżenia (stąd nazwa clipping), oczywiście przycięcie to ma odzwierciedlenie w obrazie danych (wektor próbek) który bierzemy dalej do obliczeń. W pierwszym programiku, zupełnie z rozpędu, na zasadzie ctrl+copy,ctrl+paste ustawił mi się zakres pomiarowy AD2 na poziomie 5Vpp i to ten jeden drobiazg wygenerował takie z koziej trąbki wyniki. Zerknijmy najpierw na poprawny kod, ustawione 50Vpp, przy okazji dopisałam procedurkę zrzucania bufora próbek do pliku tekstowego:

//analogout_meter_4.lpr
procedure SaveBuffToFile( pbuff : PDouble; n : integer; fileName : string );
var
   f : TextFile;
   i : integer;
begin
  AssignFile( f, fileName );
  {$I+}
  try
      rewrite( f );
      for i := 0 to n - 1 do writeln( f, FormatFloat('00.000', pbuff[ i ] ) );
      CloseFile( f );
   except
     on E: EInOutError do writeln('disk err: ', E.ClassName, '/', E.Message);
   end;
end;

konfiguracja zakresu pomiarowego AD2:

//analogout_meter_4.lpr
FDwfAnalogInChannelRangeSet( hAd2, -1, 50.0 );

przechwycony plik z danymi: ➮ data_50vpp.txt oraz odczyt i wyliczenia programowe wraz z wykresikiem w gnuplot. Jak widać, dla zakresu 50Vpp (±25V) wszystko jest w należytym porządku, obliczenia i pomiary ładnie się spinają.



Wracamy zatem do pierwotnej wersji programiku, czyli tam, gdzie tasza dała odwłoka przy konfiguracji AD2 ustawiając puderniczkę na 5Vpp (±2.5V). Tak naprawdę to AD2 ma pewien zapas i przycięcie nie następuje na poziomie 2.5V ale deczko wyżej, niemniej jednak clipping jest co pokazują obrazki poniżej:

//analogout_meter_4.lpr
FDwfAnalogInChannelRangeSet( hAd2, -1, 5.0 );

próbka pliku z danymi z takiej konwersji: ➮ data_5vpp.txt oraz obliczenia i wykres ciachniętego przebiegu:



Oczywiście można skwitować powyższy materiał stwierdzeniem, że ten Pascal i cyferki na wyświetlaczu to jeden wielki fotomontaż, zatem spróbujmy obrobić zebrane dane niezależnym narzędziem - oczywiście SciLab!

samples = strtod( 
  read_csv( '/home/otoja/PROJECTS/AnalogDiscovery2/analogout_meter_4/data_5vpp.txt' ) 
);
plot2d( samples );
Umax = max( samples );
Umin = min( samples );
Udc = mean( samples );
Urms = sqrt( sum( samples.^2 ) / size(samples) );

Sprytny programik nasz wyliczył zgrabnie wartość RMS z bufora próbek, nieco na piechotę, ale chciałam pokazać przy okazji operację na parze wektor/skalar. Dodatkowo wyliczyła się wartość średnia, w tym przypadku jej fizyczną interpretacją jest składowa stała DC no i oczywiście wartości min/max amplitudy, tej przyciętej krzywo ustawionym zakresem pomiarowym. Całość wespół z wykresikiem widzimy ponieżej:



#slowanawiatr, styczeń 2019

Natasza Biecek 2004-2019/~, e-mail