nicebadge/examples/thermal-camera/main.go

102 lines
2.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
// Thermal camera example using AMG88xx 8x8 IR sensor.
// Connect the sensor to I2C1: SDA=P0_17, SCL=P0_20 (3.3V power).
//
// The 8x8 sensor data is scaled to 24x24 with bilinear interpolation and
// rendered with an iron-palette color map on the 240x135 display.
// Each scaled pixel is drawn as a 10x5 px block → 240x120 total, centered.
import (
"image"
"machine"
draw2 "golang.org/x/image/draw"
"tinygo.org/x/drivers/amg88xx"
"tinygo.org/x/drivers/st7789"
)
const (
sensorSize = 8 // AMG88xx is 8x8
scaledSize = 24 // intermediate bilinear-scaled image
blockW = 10 // px per scaled pixel (horizontal): 24*10 = 240
blockH = 5 // px per scaled pixel (vertical): 24*5 = 120
yOffset = 7 // center 120px vertically in 135px display: (135-120)/2
)
var (
display st7789.Device
data [sensorSize * sensorSize]int16
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.P1_01,
SDO: machine.P1_02,
Frequency: 8000000,
Mode: 0,
})
machine.I2C1.Configure(machine.I2CConfig{
SDA: machine.P0_17,
SCL: machine.P0_20,
Frequency: 400000,
})
display = st7789.New(machine.SPI0,
machine.P1_15, // TFT_RESET
machine.P1_13, // TFT_DC
machine.P0_10, // TFT_CS
machine.P0_09) // TFT_LITE
display.Configure(st7789.Config{
Rotation: st7789.ROTATION_90,
Width: 135,
Height: 240,
RowOffset: 40,
ColumnOffset: 53,
})
camera := amg88xx.New(machine.I2C1)
camera.Configure(amg88xx.Config{})
src := image.NewRGBA(image.Rect(0, 0, sensorSize, sensorSize))
dst := image.NewRGBA(image.Rect(0, 0, scaledSize, scaledSize))
for {
camera.ReadPixels(&data)
// map each sensor pixel to a palette color
for j := 0; j < sensorSize; j++ {
for i := 0; i < sensorSize; i++ {
v := data[63-(i+j*sensorSize)]
// clamp to 18°C33°C range → index 0432
if v < 18000 {
v = 0
} else {
v = (v - 18000) / 36
if v > 432 {
v = 432
}
}
src.Set(i, j, colors[v])
}
}
// bilinear upscale 8x8 → 24x24
draw2.BiLinear.Scale(dst, dst.Bounds(), src, src.Bounds(), draw2.Over, nil)
// draw horizontally mirrored (acts as a selfie mirror)
for j := 0; j < scaledSize; j++ {
for i := 0; i < scaledSize; i++ {
display.FillRectangle(
int16((scaledSize-1-i)*blockW),
yOffset+int16(j)*blockH,
blockW, blockH,
dst.RGBAAt(i, j),
)
}
}
}
}