043 Project 43: TinyGo UART Sensor Loop
043 TinyGo: UART Console + Timed Sensor Loop
Build a periodic control loop: sample a sensor (or simulated ADC), emit CSV over serial, and keep loop timing steady enough for soft realtime logging.
Architecture
tick every T ms
│
▼
read sensor / mock ──► filter (EMA) ──► UART CSV line
│
└── deadline miss counter++
Step 1: Serial hello
package main
import (
"fmt"
"machine"
"time"
)
func main() {
machine.Serial.Configure(machine.UARTConfig{BaudRate: 115200})
for {
fmt.Fprintf(machine.Serial, "hello tinygo %d\n", time.Now().UnixNano())
time.Sleep(time.Second)
}
}Host:
# Linux example — adjust device
screen /dev/ttyACM0 115200
# or: picocom -b 115200 /dev/ttyACM0Step 2: Fixed-rate loop with miss detection
package main
import (
"fmt"
"machine"
"time"
)
const period = 50 * time.Millisecond // 20 Hz
func readMockSensor() int {
// Replace with machine.ADC when available on your board
return int(time.Now().UnixNano()%1000) / 10 // 0..99 fake
}
func main() {
machine.Serial.Configure(machine.UARTConfig{BaudRate: 115200})
var ema float32
var misses int
next := time.Now()
for {
start := time.Now()
if start.After(next.Add(period / 2)) {
misses++
}
raw := readMockSensor()
// EMA: y = αx + (1-α)y
const alpha = 0.2
ema = alpha*float32(raw) + (1-alpha)*ema
fmt.Fprintf(machine.Serial, "t_ns=%d raw=%d ema=%.2f misses=%d\n",
start.UnixNano(), raw, ema, misses)
next = next.Add(period)
if d := time.Until(next); d > 0 {
time.Sleep(d)
} else {
// fell behind — resync
next = time.Now().Add(period)
misses++
}
}
}Step 3: Real ADC (when target supports it)
Concept:
import "machine"
var adc machine.ADC
func initADC() {
adc = machine.ADC{Pin: machine.ADC0} // board-specific
adc.Configure(machine.ADCConfig{})
}
func readMockSensor() int {
return int(adc.Get()) // width depends on target
}Consult your board’s pinout. If no ADC: keep mock and still complete timing/miss metrics.
Step 4: Soft realtime checklist
| Practice | Why |
|---|---|
Fixed period |
Stable sample rate for filters |
| Count deadline misses | Visibility when loop overruns |
| Avoid allocs in hot loop | GC/heap pressure on tiny heaps |
| Short UART lines | Don’t block forever on full buffers |
Optional: build with size report and note RAM pressure.
Learning Goals
- UART as primary debug channel
- Timed loops and miss accounting
- Simple digital filter (EMA)
- Path to real ADC sensors
Extensions
- Change rate via serial command (
r 100→ 100 ms).
- Threshold alarm: print
ALERTwhen ema exceeds N.
- Dual-rate: fast sample, slow print.
Checkpoint
- Serial output visible on host
- Fixed-rate loop with miss counter
- EMA or similar filter
- Notes: period chosen and why