diff --git a/go.mod b/go.mod index 2cce03b..e823da3 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,12 @@ go 1.25.2 require ( github.com/soypat/cyw43439 v0.1.1 github.com/soypat/lneto v0.3.2 + tinygo.org/x/drivers v0.36.0 + tinygo.org/x/tinyfont v0.7.0 ) require ( + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/soypat/seqs v0.0.0-20250124201400-0d65bc7c1710 // indirect github.com/tinygo-org/pio v0.3.0 // indirect golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d // indirect diff --git a/go.sum b/go.sum index 3fc1ab5..88d9804 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/soypat/cyw43439 v0.1.1 h1:vcaTiVzfuz3keK7lJpVxStZ6tV8HCw7Ugzsh1k4mneE= github.com/soypat/cyw43439 v0.1.1/go.mod h1:R2uSILRwSPmcmmKy5Z0FtK4ypgiPf5YqK+F+IKmXqxc= github.com/soypat/lneto v0.3.2 h1:iUFeRSq2czT7Db6MMOsAnMCBlKCqvIr941zsNf9dcu0= @@ -8,3 +10,7 @@ github.com/tinygo-org/pio v0.3.0 h1:opEnOtw58KGB4RJD3/n/Rd0/djYGX3DeJiXLI6y/yDI= github.com/tinygo-org/pio v0.3.0/go.mod h1:wf6c6lKZp+pQOzKKcpzchmRuhiMc27ABRuo7KVnaMFU= golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0= golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +tinygo.org/x/drivers v0.36.0 h1:F0x342A6GWqh6abtCa57uAxCyz/b9MbGzvIVvIf+gpE= +tinygo.org/x/drivers v0.36.0/go.mod h1:DQgKyHkB4G6IEOKVTAjApbKnWGwESN91EVJO+nMOE9Y= +tinygo.org/x/tinyfont v0.7.0 h1:Ju901eGRThlHLoti9K7myMYyv4phd3I0DrJwc14NTTU= +tinygo.org/x/tinyfont v0.7.0/go.mod h1:onflMSkpWl7r7j4MIqhPEVV39pn7yL4N3MOePl3G+G8= diff --git a/main.go b/main.go index 89f3c96..3e4a59e 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,11 @@ import ( "machine" "strconv" "time" + "image/color" + + "tinygo.org/x/drivers/ssd1306" + "tinygo.org/x/tinyfont" + "tinygo.org/x/tinyfont/proggy" ) var StateTopic = fmt.Sprintf("homeassistant/sensor/%s/state", NodeID) @@ -292,10 +297,10 @@ func panicErr(msg string, err error) { func main() { time.Sleep(2 * time.Second) - // Configure I2C (Pin 16 SDA, Pin 17 SCL -> I2C0) + // Bump frequency to 400kHz for snappy display flushes i2c := machine.I2C0 err := i2c.Configure(machine.I2CConfig{ - Frequency: 100 * machine.KHz, + Frequency: 400 * machine.KHz, SDA: machine.GPIO16, SCL: machine.GPIO17, }) @@ -303,6 +308,18 @@ func main() { panicErr("I2C configuration", err) } + // Initialize OLED (shares the same I2C bus at 0x3C) + oled := ssd1306.NewI2C(i2c) + oled.Configure(ssd1306.Config{ + Address: 0x3C, // Check 0x3D if 0x3C doesn't respond + Width: 128, + Height: 64, + }) + oled.ClearBuffer() + white := color.RGBA{R: 255, G: 255, B: 255, A: 255} + tinyfont.WriteLine(oled, &proggy.TinySZ8pt7b, 0, 16, "Booting...", white) + oled.Display() + bme, err := NewBME280(i2c, BME280Addr) if err != nil { panicErr("BME280 init", err) @@ -338,12 +355,21 @@ func main() { if err != nil { println("BME280 read error:", err.Error()) } else { + // Publish MQTT stateJSON := fmt.Sprintf(`{"temperature":%.2f,"humidity":%.2f,"pressure":%.2f}`, t, h, p) if err := mqtt.Publish(StateTopic, []byte(stateJSON), false); err != nil { println("MQTT publish error:", err.Error()) } else { println(fmt.Sprintf("[%s] Published: %s", NodeName, stateJSON)) } + + // Render to OLED + oled.ClearBuffer() + tinyfont.WriteLine(oled, &proggy.TinySZ8pt7b, 0, 14, fmt.Sprintf("Node: %s", NodeName), white) + tinyfont.WriteLine(oled, &proggy.TinySZ8pt7b, 0, 30, fmt.Sprintf("Temp: %.1f C", t), white) + tinyfont.WriteLine(oled, &proggy.TinySZ8pt7b, 0, 46, fmt.Sprintf("Hum: %.1f %%", h), white) + tinyfont.WriteLine(oled, &proggy.TinySZ8pt7b, 0, 60, fmt.Sprintf("Pres: %.1f hPa", p), white) + oled.Display() } time.Sleep(UpdateInterval)