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.
Autor: Alekander Kawęczyński
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:
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