Dit project beschrijft de bouw van een DIY USB-oscilloscoop op basis van het STM32F207 Nucleo-board.
Technische specificaties
Het apparaat haalt een sampling rate van 2 MSPS met een 12-bit resolutie. Dit wordt gerealiseerd via hardware-timed sampling (TIM2), een circulaire DMA-buffer en non-blocking UART-transmissie (921600 baud). Voor de visualisatie wordt een Python-GUI gebruikt die de data via de seriële poort ontvangt en plot met matplotlib.
Belangrijkste kenmerken
- Triggering: Voorzien van een rising-edge trigger met hysteresis en pre-trigger capture.
- Hardware: Gebruikt de NUCLEO-F207ZG; signalen worden ingevoerd via pin PA6.
- Veiligheid: Er wordt expliciet gewaarschuwd dat een analoog beschermingscircuit noodzakelijk is om de MCU te beschermen tegen voltages buiten het bereik van 0-3,3V.
Beperkingen en Roadmap
De praktische bandbreedte is beperkt tot circa 200 kHz en de trigger kan onstabiel zijn bij zeer lage frequenties. Toekomstige plannen bevatten de ontwikkeling van een analoog front-end (AC-koppeling, offset), ondersteuning voor meerdere kanalen en een variabele sample rate.
STM32 DIY Oscilloscoop
Een eenvoudige USB-oscilloscoop gebouwd rond een STM32F207 Nucleo-board. Het maakt gebruik van de interne ADC, DMA en een hardwaretimer om een stabiele sampling rate van 2 MSPS te bereiken met edge-triggering. Een Python-front-end ontvangt de vastgelegde golfvorm via UART en plot deze in realtime.
Dit project is onderdeel van een videoserie; dit eerste deel behandelt één werkend kanaal: ADC + DMA-acquisitie, hardware-timed sampling, een softwarematige trigger met pre-trigger capture en een minimale Python-omgeving. In toekomstige video's zal de sampling rate verder worden verhoogd en zullen er meerdere kanalen worden toegevoegd.
Kenmerken
- Tot 2 MSPS, 12-bit resolutie.
- Hardware-timed sampling via TIM2 → ADC externe trigger (geen CPU-betrokkenheid bij de timing).
- Circulaire DMA-buffer, double-buffered via half/full transfer complete callbacks.
- Rising-edge trigger met hysteresis en pre-trigger capture.
- Non-blocking UART-transmissie via DMA (921600 baud).
- Eenvoudige Python/matplotlib GUI met interactieve zoom- en panfuncties.
Hardware
- Board: NUCLEO-F207ZG
- Analoge ingang: PA6 (ADC1, kanaal 6)
- Verbinding met PC: Virtuele COM-poort van de ST-LINK (USART3), er is geen externe USB-naar-serieel adapter nodig.
⚠️ Waarschuwing: Een ingangsbeschermingscircuit is verplicht om het ingangssignaal binnen 0 - 3,3V te houden. Negatieve voltages of signalen boven de 3,3V kunnen de MCU beschadigen. Een analoog front-end (offset + clamping) wordt behandeld in de bovengenoemde video.
Structuur van de repository
.
├── firmware/ # STM32CubeIDE project
│ └── Core/
│ ├── Inc/
│ └── Src/
│ ├── main.c
│ └── stm32f2xx_hal_msp.c
└── software/ # PC-side Python GUI
├── oscilloscope1_ch.py
└── requirements.txt
Aan de slag
Firmware
- Open de map
firmware/ als project in STM32CubeIDE.
- Bouw het project en flash het naar een NUCLEO-F207ZG board.
- Sluit een signaal aan op PA6 (houd rekening met de bovengenoemde voltage-limieten).
PC-zijde
- Ga naar de softwaremap:
cd software
- Installeer de benodigdheden:
pip install -r requirements.txt
- Start de applicatie:
python oscilloscope1_ch.py
- Pas de variabele
PORT in oscilloscope1_ch.py aan om deze te laten overeenkomen met de seriële poort van je board (bijv. /dev/cu.usbmodemXXXX op macOS, COMx op Windows).
Hoe het werkt
- TIM2 triggert een ADC-conversie met een vast interval.
- Elk geconverteerd sample wordt geschreven in een circulaire DMA-buffer — de CPU is hierbij niet betrokken.
- Zodra de helft van de buffer is gevuld, scant de firmware deze op een stijgende flank (rising edge) die een configureerbare drempelwaarde overschrijdt (met hysteresis om ruis te onderdrukken).
- Wanneer een trigger wordt gevonden, wordt een vast venster van samples — sommige vóór het triggerpunt, de rest erna — gekopieerd en als één pakket via UART naar de PC verzonden. Hierbij wordt DMA gebruikt, zodat de overdracht de acquisitie niet blokkeert.
- Het Python-script ontvangt het pakket, pakt het uit en werkt de plot bij.
Bekende beperkingen
- Bandbreedte: Ongeveer 200 kHz is de praktische bovengrens voor het nauwkeurig reproduceren van de vorm van een signaal bij 2 MSPS (gebaseerd op een vuistregel van circa 10 samples per periode).
- Triggerstabiliteit: De trigger kan onstabiel zijn bij langzaam bewegende signalen met merkbare ruis (bijv. een sinusgolf onder de ~12 kHz tijdens tests). Dit komt omdat het signaal vele samples nodig heeft om langzaam de drempelwaarde te overschrijden, waardoor ruis meerdere kansen krijgt om de hysteresisband te passeren. Blokgolven zijn grotendeels ongevoelig hiervoor, aangezien hun flanken snel genoeg zijn. Het is gepland om de sample rate en hysteresis aanpasbaar te maken per frequentiebereik.
- Hardware: Er is nog geen ingangsbescherming of offset-circuitage aanwezig — een analoog front-end volgt in een toekomstige video.
Toekomstplannen (Roadmap)
- Variabele tijdbasis / sample rate bereiken.
- Analoog front-end (AC-koppeling, offset, ingangsbescherming).
- Hogere effectieve sampling rate via verminderde resolutie en/of interleaved gebruik van alle 3 de ADC's.
- Ondersteuning voor meerdere kanalen (tot 4 kanalen, waarbij de 3e ADC wordt gedeeld tussen twee ingangen).
Licentie
Dit project is gelicenseerd onder de MIT-licentie — zie het bestand LICENSE voor details. Firmware-bestanden die zijn gegenereerd door STM32CubeMX behouden hun oorspronkelijke STMicroelectronics copyright-headers, zoals vereist door hun licentie.
STM32 DIY Oscilloscoop
Een eenvoudige USB-oscilloscoop gebouwd rond een STM32F207 Nucleo-board. Het maakt gebruik van de interne ADC, DMA en een hardwaretimer om een stabiele sampling rate van 2 MSPS te bereiken met edge-triggering. Een Python-front-end ontvangt de vastgelegde golfvorm via UART en plot deze in realtime.
Dit project is onderdeel van een videoserie; dit eerste deel behandelt één werkend kanaal: ADC + DMA-acquisitie, hardware-timed sampling, een softwarematige trigger met pre-trigger capture en een minimale Python-omgeving. In toekomstige video's zal de sampling rate verder worden verhoogd en zullen er meerdere kanalen worden toegevoegd.
Kenmerken
- Tot 2 MSPS, 12-bit resolutie.
- Hardware-timed sampling via TIM2 → ADC externe trigger (geen CPU-betrokkenheid bij de timing).
- Circulaire DMA-buffer, double-buffered via half/full transfer complete callbacks.
- Rising-edge trigger met hysteresis en pre-trigger capture.
- Non-blocking UART-transmissie via DMA (921600 baud).
- Eenvoudige Python/matplotlib GUI met interactieve zoom- en panfuncties.
Hardware
- Board: NUCLEO-F207ZG
- Analoge ingang: PA6 (ADC1, kanaal 6)
- Verbinding met PC: Virtuele COM-poort van de ST-LINK (USART3), er is geen externe USB-naar-serieel adapter nodig.
⚠️ Waarschuwing: Een ingangsbeschermingscircuit is verplicht om het ingangssignaal binnen 0 - 3,3V te houden. Negatieve voltages of signalen boven de 3,3V kunnen de MCU beschadigen. Een analoog front-end (offset + clamping) wordt behandeld in de bovengenoemde video.
Structuur van de repository
.
├── firmware/ # STM32CubeIDE project
│ └── Core/
│ ├── Inc/
│ └── Src/
│ ├── main.c
│ └── stm32f2xx_hal_msp.c
└── software/ # PC-side Python GUI
├── oscilloscope1_ch.py
└── requirements.txt
Aan de slag
Firmware
- Open de map
firmware/ als project in STM32CubeIDE.
- Bouw het project en flash het naar een NUCLEO-F207ZG board.
- Sluit een signaal aan op PA6 (houd rekening met de bovengenoemde voltage-limieten).
PC-zijde
- Ga naar de softwaremap:
cd software
- Installeer de benodigdheden:
pip install -r requirements.txt
- Start de applicatie:
python oscilloscope1_ch.py
- Pas de variabele
PORT in oscilloscope1_ch.py aan om deze te laten overeenkomen met de seriële poort van je board (bijv. /dev/cu.usbmodemXXXX op macOS, COMx op Windows).
Hoe het werkt
- TIM2 triggert een ADC-conversie met een vast interval.
- Elk geconverteerd sample wordt geschreven in een circulaire DMA-buffer — de CPU is hierbij niet betrokken.
- Zodra de helft van de buffer is gevuld, scant de firmware deze op een stijgende flank (rising edge) die een configureerbare drempelwaarde overschrijdt (met hysteresis om ruis te onderdrukken).
- Wanneer een trigger wordt gevonden, wordt een vast venster van samples — sommige vóór het triggerpunt, de rest erna — gekopieerd en als één pakket via UART naar de PC verzonden. Hierbij wordt DMA gebruikt, zodat de overdracht de acquisitie niet blokkeert.
- Het Python-script ontvangt het pakket, pakt het uit en werkt de plot bij.
Bekende beperkingen
- Bandbreedte: Ongeveer 200 kHz is de praktische bovengrens voor het nauwkeurig reproduceren van de vorm van een signaal bij 2 MSPS (gebaseerd op een vuistregel van circa 10 samples per periode).
- Triggerstabiliteit: De trigger kan onstabiel zijn bij langzaam bewegende signalen met merkbare ruis (bijv. een sinusgolf onder de ~12 kHz tijdens tests). Dit komt omdat het signaal vele samples nodig heeft om langzaam de drempelwaarde te overschrijden, waardoor ruis meerdere kansen krijgt om de hysteresisband te passeren. Blokgolven zijn grotendeels ongevoelig hiervoor, aangezien hun flanken snel genoeg zijn. Het is gepland om de sample rate en hysteresis aanpasbaar te maken per frequentiebereik.
- Hardware: Er is nog geen ingangsbescherming of offset-circuitage aanwezig — een analoog front-end volgt in een toekomstige video.
Toekomstplannen (Roadmap)
- Variabele tijdbasis / sample rate bereiken.
- Analoog front-end (AC-koppeling, offset, ingangsbescherming).
- Hogere effectieve sampling rate via verminderde resolutie en/of interleaved gebruik van alle 3 de ADC's.
- Ondersteuning voor meerdere kanalen (tot 4 kanalen, waarbij de 3e ADC wordt gedeeld tussen twee ingangen).
Licentie
Dit project is gelicenseerd onder de MIT-licentie — zie het bestand LICENSE voor details. Firmware-bestanden die zijn gegenereerd door STM32CubeMX behouden hun oorspronkelijke STMicroelectronics copyright-headers, zoals vereist door hun licentie.