Membrana piezo PCA-4B – pomiar impedancji

Wykonałem pomiar impedancji przetwornika piezoakustycznego PCA-4B wykorzystując następujący układ:

Pomiar był wykonywany dla częstotliwości ok. 3,5 KHz, ponieważ taką deklaruje producent jako rezonansową. Ustawiałem potencjometr tak, aby amplituda sygnału na kanale CH2 była równa połowie amplitudy na kanale CH1 (wejściowej). Następnie rozłączyłem układ i odczytałem wartość potencjometru. Wyszło 750 Ω. Przesunięcie fazowe wyniosło 53 stopnie (napięcie na CH2 „opóźnione”). Pomiar multimetrem pojemności membrany dał wynik 90 nF – tak jak w dokumentacji.

Reaktancja kondensatora 90 nF dla częstotliwości 3,5 kHz to 500 Ω. To oznaczałoby, że układ można modelować jako szeregowo połączony kondensator 90 nF oraz rezystor 560 Ω. Dlaczego 560? Bo moduł impedancji to 750 Ω, a reaktancja to 500 Ω. Więc rezystancję należy policzyć z równania pitagorasa sqrt(750^2 – 500^2) = 560? Chyba, już nie pamiętam z teorii obwodów.

 

 

 

Logika wykluczeń

Układ logiczny zabezpiecza przed aktywacją obydwu wyjść. Jedynie jedno wyjście jest możliwe do pobudzenia w danym momencie. Stan wysoki na obydwu wejściach zeruje obydwa wyjścia.

Układ można rozbudować dla n wejść i m wyjść stosując m bramek AND n-wejściowych.

Nie trzeba używać bramek AND gdy dane wyjścia nie są potrzebne.

Przykład zastosowania: sterowanie stycznikami silnika przyciskami przód/tył – zabezpieczenie przed jednoczesnym naciśnięciem dwóch przycisków naraz.

Szum – notatki

Szum rezystora 1kΩ to 4 nV/√Hz. Dla rezystorów o innej wartości wyliczamy pierwiastek rezystancji i odnosimy do tego. Np. dla 100kΩ to będzie √100 = 10 ⋅ 4 nV/√Hz = 40 nV/√Hz. To oczywiście przybliżenie dla normalnej temperatury itp.

Szumy dodaje się nie bezpośrednio, a dodając ich kwadraty i pierwiastkując całość (jak moduł wektora).

Wzmacniacz operacyjny w konfiguracji nieodwracającej / odwracającej.

Szum rezystora w pętli sprzężenia (podłączonego do wyjścia wzm. op.) wchodzi bezpośrednio w skład szumu wyjściowego. Szum drugiego rezystora (podłączonego do masy i wejścia wzm. op.) musimy pomnożyć przez wzmocnienie układu.

Szum napięciowy wzmacniacza z karty katalogowej mnoży się przez wzmocnienie układu.

Szum prądowy wzmacniacza przeliczamy na napięcie odłożone na równoległych obu rezystorach, następnie mnożymy przez wzmocnienie układu.

Przykład:

(https://www.researchgate.net/figure/Example-non-inverting-Op-Amp-circuit_fig3_283082955)

Dane:

  • MCP6002, R2 = 100kΩ, R1 = 1kΩ
  • Wzmocnienie = 101.
  • Noise figure: eni = 28 nV/√Hz; ini = 0.6 fA/√Hz (https://ww1.microchip.com/downloads/en/DeviceDoc/MCP6001-1R-1U-2-4-1-MHz-Low-Power-Op-Amp-DS20001733L.pdf)

Składowe szumu wyjściowego:

  • Od rezystora R2: √100 = 10; 10 ⋅ 4 nV/√Hz = 40 nV/√Hz
  • Od rezystora R1: 4 nV/√Hz razy wzmocnienie czyli 404 nV/√Hz
  • Od szumu napięciowego wzmacniacza: 28 nV/√Hz ⋅ 101 = 2828 nV/√Hz
  • Od szumu prądowego wzmacniacza: R1||R2 ≅R1 = 1kΩ. 1kΩ ⋅ 0.6 fA/√Hz = 0.6 pV/√Hz i jeszcze razy wzmocnienie ≅ 60 pV/√Hz = 0.06 nV/√Hz.

Suma: √(40²+404²+2828²+0.06²) = 2857 nV/√Hz. Wyznaczyliśmy szum wyjściowy. Szum wejściowy wyznaczymy dzieląc przez wzmocnienie, czyli 2857 nV/√Hz / 101 = 28.3 nV/√Hz.

Jak widać, na poziom szumu w tym układzie główny wpływ ma szum napięciowy wzmacniacza. MCP6002 nie jest wzmacniaczem niskoszumnym, a low-power. Możnaby jeszcze dwukrotnie zwiększyć rezystory R1 i R2, co niewiele pogorszy charakterystykę szumową, a zmniejszy pobór prądu. Przy projektowaniu wzmacniaczy niskoszumnych należy wybrać odpowiednie układy, oraz stosować mniejsze rezystancje w układzie, aby nie pogarszać parametrów wzmacniacza.

 

TC77 odczyt temperatury.

Czujnik temperatury TC77 z interfejsem SPI.

https://www.microchip.com/wwwproducts/en/TC77

https://ww1.microchip.com/downloads/en/DeviceDoc/20092B.pdf

1. Odczytujemy 2 bajty po SPI w mode 0, MSB first.

Dla STM32 zrealizuje to taki kod:

uint8_t data[2];
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
HAL_SPI_Receive(&hspi1, data, 2, 100);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);

2. Ponieważ w 16 bitach danych temperatura jest zakodowana na 13 bitach w kodzie U2, musimy inaczej postąpić dla wartości ujemnych oraz dodatnich. Użyjemy zmiennej pomocniczej t, która przechowa wartość całkowitą.

uint8_t sign = data[1] & 0x80;
int t;
if(sign == 0)
t = (((data[1]<<8)|data[0]) >> 3);
else
t = (((data[1] & 0x7f)<<8 | data[0]) >> 3) - 4096;

Konwersja odczytanej liczby na rzeczywistą wartość temperatury:

float temperatura = 0.0;
if(data[0] & (1<<2))
temperatura = 0.0625 * t ;
printf("T = %.1f *C \r\n", temperatura);

Drugi najmłodszy bit (licząc od zera) wskazuje, czy odczytana wartość jest po prawidłowej konwersji temperatury.

 

STM32 Semihosting (printf w konsoli debugowania)

Uwaga! Program na mikrokontrolerze nie będzie pracował poza sesją debugowania!

1.w main.c

/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes */

2.w main.c

/* USER CODE BEGIN PFP */
extern void initialise_monitor_handles(void);

3. Project -> Properties -> C/C++ General -> Paths and Symbols -> Source Location -> /[nazwa projektu]/Core -> Edit Filter -> Src/syscalls.c

4. Project -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU GCC Linker -> Libraries

Libraries: rdimon

5. Project -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU GCC Linker -> Miscellaneous

Other flags: -specs=rdimon.specs

6. Run -> Debug Configurations… -> Debugger

    • Debug probe: ST-LINK (OpenOCD)
    • Reset mode: Software system reset

7. Run -> Debug Configurations… -> Startup

Initialization Commands: monitor arm semihosting enable

8. w main.c w main():

/* USER CODE BEGIN 1 */
initialise_monitor_handles();

Gotowe. Teraz umieszczając w kodzie printf() wyjście pojawi się w konsoli debuggera.

 

Źródło: https://www.youtube.com/watch?v=V16v9O5USF4

ESP32 D1 mini – problem z regulatorem napięcia

Moduł zakupiony na Aliexpress: D1 mini ESP32 ESP-32 WiFi+Bluetooth Internet of Things development board based ESP8266 Fully functional

Proste programy działały, aż do momentu użycia Bluetooth / Wifi – następował reset Brownout detector:

Po krótkich poszukiwaniach w internecie, okazało się że podejrzanym może być regulator napięcia: https://www.reddit.com/r/esp8266/comments/9itox8/survey_did_you_get_a_150ma_regulator_on_your/

Strona https://www.esp32.com/viewtopic.php?t=2662 podaje, jaki jest pobór prądu przez ESP32:

SCENARIO—————————CPU80MHz—-CPU160MHz—-CPU240MHz
– CPU + ELECTRONICS + BT———–113mA——-123mA——–141mA
– CPU + ELECTRONICS—————-38mA——–51mA ——–73mA
– CPU (deep sleep) + ELECTRONICS—3.5mA——-3.5mA——–3.5mA

Na płytce znajdował się układ w obudowie SOT23-5 i oznaczeniu 4B2X.

Jeżeli jego wydajność prądowa to 150mA, to można postawić tezę, iż nie daje on rady. Wykonany został zatem pomiar napięcia wyjściowego stabilizatora w układzie z ESP32, który próbował uruchomić Wifi:

Widać spadek napięcia z 3,3 V do ok. 2,4 V, czyli o 0, 7 V. Ponowny wzrost napięcia spowodowany jest resetem ESP32.

Stabilizator został wymieniony na MIC5504-3.3YM5, o gwarantowanej wydajności prądowej 300 mA. Układ wyprowadzeń zgadzał się.

Po wymianie układu resety nie następowały. Tak prezentuje się pomiar po:

Tutaj również widać spadki napięć, jednak nigdy nie są poniżej 2,8 V. Możliwe, że brakuje kondensatora na wejściu układu. Mimo wszystko, problem wydaje się być rozwiązany.

Zabawy z FFT na STM32F103C8T6 (bluepill)

Procesor STM32F103C8T6 z rdzeniem ARM®Cortex®-M3 mogącym pracować z taktowaniem do 72MHz. 20KB SRAM i 64KB FLASH są zaletami, ale brak FPU w tej serii poważnie zmniejsza wydajność obliczeniową dla FFT, które zwykle wykorzystują typ danych float.

Uwaga 1: W tych eksperymentach nie jest wykorzystywany ADC – sample są generowane przez zdefiniowaną funkcję.

Uwaga 2: Wykorzystałem bibliotekę https://github.com/leeshineSZ/fft_for_stm32 – w razie jakby zniknęła z sieci, załączam:

fft_for_stm32-master

Uwaga 3: Do pomiarów wydajności wykorzystuję timer TIM1 w roli zwykłego timera/licznika. Okres ustawiony na max, tj. 65535. Prescaler na 1000. Ponieważ zegar trafia z linii APB2, to w moim przypadku daje to 72MHz na wejściu, po prescalerze 72KHz. Daje to (1/72KHz) 13,89us na pojedynczą inkrementację licznika. Wystarczy zerować rejestr licznika TIM1->CNT przed pomiarem, i odczytać rejestr po zakończeniu pomiaru, a potem przemnożyć przez 13,89us, żeby otrzymać czas potrzebny na wykonanie obliczeń.

Najpierw sprawdzałem, ile zajmuje mnożenie liczb float, a dokładniej zmiennej przez stałą. Jest to ok 3,43us, wliczając obieg pętli for.

Obliczenia FFT dla tablicy 128 próbek zajmują 6,5ms. Do tego trzeba doliczyć wyliczanie modułów liczb zespolonych – kolejne 0,93ms. Łącznie 7,43ms.

Daje to ok. 134Hz częstotliwości aktualizacji widma. Jest to tylko 128 próbek, czyli realnie 64 wartości w widmie – może wystarczyć do spektrometru na led-ach, gdzie mamy kilkanaście pasków.

Dla 1024 próbek FFT 61ms + moduł 7,4ms = 68,5ms, co daje częstotliwość odświeżania 14,6Hz – dosyć mało jak na wizualizację „real time”.

Wniosek 1: Częstotliwość próbkowania jest niezależna od ilości próbek, jakie bierzemy do analizy.

Wniosek 2: Więcej próbek – znacznie więcej czasu na obliczenia. Warto tą kwestię najpierw przemyśleć, bo zmiana nie ogranicza nam pasma, jedynie rozdzielczość.

Wniosek 3: Nie zastosowałem tu okien, co powoduje, że np. w widmie fali prostokątnej ciężko się jest jej doszukać – kolejne prążki szybko gasną, zwłasza jak nie „trafimy” z częstotliwością.

Wniosek 4: Fajnie by było wyeliminować floaty i skorzystać z np obliczeń stałoprzecinkowych.

Wniosek 5: Żeby wartości modułów odpowiadały rzeczywistości, należy ich amplitudy podzielić przez [0,5 x ilość próbek].

Wizualizacja obliczeń dla fali prostokątnej, 128 próbek i dokładnie „trafionej” (jeden cały okres):

Widać niską wartość składowej stałej i szybko malejące prążki nieparzyste – parzyste są równe składowej stałej. Nie wiem skąd ta składowa stała – jest dokładnie 64 próbek o wartości -30 i 64 próbki o wartości 30. Takiego rezultatu spodziewałbym się, gdybym miał o jedną próbkę dodatnią na plusie. Chyba że chodzi o aliasing – w końcu nie ograniczałem pasma prostokątowi.

Kod pisany w STM32CubeIDE.

STM32 obsługa enkodera na przykładzie STM32F103C8T6 (bluepill)

Konfiguracja STM32CubeMX

W przykładzie: STM32F103C8T6, użycie TIMERA2, enkoder na pinach PA0, PA1

 

Zmiany w kodzie programu (main.c):

Przed główną pętlą

W pętli głównej, odczyt wartości enkodera:

Wartości uzyskiwane będą z przedziału 0 – [Counter Period] – w naszym przypadku 0 – 1000 włącznie. Po przekroczeniu wartości 1000 licznik zaczyna zliczać dalej od zera.

Nie trzeba uruchamiać przerwań, ani wykonywać dodatkowych konfiguracji.


Przykład uruchomienia na płytce Bluepill:

Enkoder podpięty pod wejścia PA0, PA1 – jak w konfiguracji.

Udostępniam projekt z kodami źródłowymi oraz binarnymi, które były używane do testów: encoder_test

W kodzie zaimplementowana jest obsługa wirtualnego portu szeregowego pod USB, oraz zmiana tempa błyskania LED PC13 w zależności od wartości licznika enkodera.

Powyższy opis w pliku PDF do wydruku: STM32 obsługa enkodera inkrementalnego

OLED-AG-L-12864-05-WHITE-1i3 – biblioteka Eagle

Wyświetlacz OLED 1.3″ z dystrybucji firmy Artronic – największy niewymagający zewnętrznej przetwornicy napięcia.
Dokumentacja:
Hardware: http://www.artronic.com.pl/o_produkcie.php?id=2075
Software: http://www.artronic.com.pl/pdf/pl/SH1106.pdf
Potencjalna biblioteka Arduino: https://github.com/wonho-maker/Adafruit_SH1106
Biblioteka Eagle 7.1.1:
oled_artronic
Footprint w 2 wersjach – „płaskiej”, oraz ze slotem w PCB i taśmą lutowaną od spodu płytki.
Uwaga: biblioteka (jeszcze) nie sprawdzona w praktyce!