Proste układy: Czujnik światła na fotodiodzie

Oświetlenie fotodiody powoduje przepływ większego prądu, a w konsekwencji wzrost napięcia na rezystorze R2 (10k). Gdy napięcie wzrośnie powyżej ok. 0,7 V, tranzystor otworzy się i załączy zasilanie buzzera. Można zamienić miejscami fotodiodę i rezystor R2, aby uzyskać barierę świetlną (przerwa oświetlenia aktywuje buzzer). Czułość można regulować rezystancją R2 – należy jednak pamiętać, iż zbyt duża rezystancja nie ma sensu, gdyż przeważy obciążenie prądu bazy tranzystora – wtedy warto dodać drugi tranzystor w konfiguracji darlingtona lub podobnej. W testowanym przypadku prąd wsteczny fotodiody nieoświetlonej wynosił ok. 4uA, a oświetlonej – powyżej 100uA, co dawało 1V na obciążeniu R2=10k. Pozwalało to na otwarcie tranzystora i zadziałanie buzzera. Układ jest najprostszej z możliwych konstrukcji. Całkowite usunięcie rezystora R2 spowoduje wzocnienie prądu fotodiody beta-krotnie (w praktyce kilkaset razy) na kolektorze tranzystora. Czyli dla 100uA można spodziewać się 10mA prądu kolektora. Rezystor R1 można zmniejszyć do rozsądnych granic (czyli do 1k). Można użyć 2 takie same rezystory. Układ jest “rozwleczony” na płytce stykowej, ponieważ nie da się zmienić rozstawu rezystorów w obecnej wersji programu Fritzing.

Proste układy: Licznik 4017

Podstawowa aplikacja układu CMOS 4017 – Licznik 1 z 10. W przykładzie ograniczono liczbę wyjść do 4 – Q0-Q3. Wyjście Q4 połączone z wejściem RST. Sygnał zegarowy pochodzi z przycisku. Można dodać zewnętrzne wyzwalanie np. poprzez tranzystor PNP. Można również zmieniać długość łańcucha. Pewną niewygodą jest rozkład wyjść układu – nie są po kolei.

Uwaga na zasilanie oraz ładunki statyczne – łatwo uszkodzić układ podczas testów na płytce stykowej. Dla bezpieczeństwa warto dodać diodę schottky’ego zaporowo na linii zasilania. Gdyby układ łapał “śmieci”, dodać kondensatory 100nF oraz 10uF na linii zasilania w pobliżu układu scalonego.

Zasilanie 5-15V, testowano z baterii 9V.

Proste układy: Łańcuch LED

LED Chaser

Układ sekwencyjnie miga diodami. Mignięcie kolejnej jest wyzwalane przez poprzednią. Łańcuch można wydłużać. Zastosowano kondensatory 10uF. Układ ładnie się wpasowuje w małą płytkę stykową. Wyprowadzenia kondensatora należy rozchylić na raster 0.2″ (jeden rząd przerwy pomiędzy). Ujemne wyprowadzenia do kolektorów, dodatnie do baz. Układ w zasadzie “transportuje” wygaszenie, pozostawiając resztę LED’ów zapalonych. Testowałem łańcuch 5 ledów. Należy pamiętać o sygnale zwrotnym z końca łańcucha na początek (białe połączenie).

 

89831-02020 Czujnik uderzeniowy Citroen C1

Kupiony używany na Allegro za 5zł.

Na płytce o wymiarach 21 x 24 mm znajdują się 2 układy scalone: SX1258EG oraz MC33793D, dwa kondensatory tantalowe, dwa koraliki ferrytowe / cewki, rezystor 1 kΩ, kondensator ceramiczny oraz element w obudowie SOT23 o oznaczeniu 33A – prawdopodobnie 2 diody ze wspólną anodą podłączoną do masy.

Układ SX1258EG prawdopodobnie jest podobny do układu MMA1254, z delikatnie zmienionym rozkładem wyprowadzeń.

Zasilanie 5V jest doprowadzone do pinu 8 zamiast 6. Pin 6 jest wyprowadzony tylko do padu testowego, co może sugerować, że jest to pin STATUS, ale nie wiadomo. Piny Vss oraz NC się zgadzają. Pin 4 doprowadzony do pinu LOGOUT układu MC33793D, czyli musi być wejściem, np wejściem ST (Selftest).

Pin 5 prawdopodobnie to wyjście napięciowe – przechodzi przez filtr RC do pinu nr 2 (I/O 0) MC33793D.

Do układu MC33793D jest dostępna dokumentacja.

Piny na płytce w kolejności ze zdjęcia od góry to prawdopodobnie:

1. DSI BUS IN

2. GND

3. GND

4. DSI BUS OUT

Test przy zasilaniu stałym napięciem 12V na potencjał DSI BUS IN, z pomiarem napięcia na pinie 2 układu MC33793D. Akcelerometr nie ma zbyt dużej czułości – obracanie płytki w przestrzeni (zakres 0-1G) nie powodowało zauważalnych zmian napięcia wyjściowego.

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