はじめに
M5Stackにサーマルカメラをつなぐ のMaixduino版です。
時節柄、部屋にこもることが多くなってます、簡単な工作をしてみましょう。
準備
-
Maixduino まずはこれ
-
Grove Base Shield V2.0 for Arduino MaixduinoにGPIO、I2Cなどのコネクターを追加します。Maixduinoに接続する時は、スイッチを3.3V側に設定する必要があります。
-
Grove - Infrared Temperature Sensor Array (AMG8833) サーマルカメラ/赤外線温度センサー。時節柄サーマルカメラの欠品が多いです
コード
ほぼ、参考にさせて頂いた M5Stackにサーマルカメラをつなぐ のままです。
MaixduinoのI2Cのデフォルト転送速度が500kですが、センサーの最大が400kなので、400kを指定してます。あと、まだ原因を調査してないですが、I2Cの転送サイズを128バイトにしたときにWireライブラリーがクラッシュしてしまうので、64バイト単位で転送するようにしています。
main.cpp
# include <Arduino.h>
# include <Sipeed_ST7789.h>
# include <Wire.h>
# define PCTL 0x00
# define RST 0x01
# define FPSC 0x02
# define INTC 0x03
# define STAT 0x04
# define SCLR 0x05
# define AVE 0x07
# define INTHL 0x08
# define TTHL 0x0E
# define INT0 0x10
# define T01L 0x80
# define T33L 0xC0
# define AMG88_ADDR 0x68 // in 7bit
# define WIDTH (320 / 8)
# define HEIGHT (240 / 8)
SPIClass spi_(SPI0); // MUST be SPI0 for Maix series on board LCD
Sipeed_ST7789 lcd(320, 240, spi_);
float gain = 10.0;
float offset_x = 0.2;
float offset_green = 0.6;
float sigmoid(float x, float g, float o) {
return (tanh((x + o) * g / 2) + 1) / 2;
}
uint16_t heat(float x) { // 0.0〜1.0の値を青から赤の色に変換する
x = x * 2 - 1; // -1 <= x < 1 に変換
float r = sigmoid(x, gain, -1 * offset_x);
float b = 1.0 - sigmoid(x, gain, offset_x);
float g = sigmoid(x, gain, offset_green) + (1.0 - sigmoid(x, gain, -1 * offset_green)) - 1;
return (((int)(r * 255)>>3)<<11) | (((int)(g * 255)>>2)<<5) | ((int)(b * 255)>>3);
}
void write8(int id, int reg, int data) {
Wire.beginTransmission(id);
Wire.write(reg);
Wire.write(data);
uint8_t result = Wire.endTransmission();
// Serial.printf("reg: 0x%02x, result: 0x%02x\r\n", reg, result);
}
void dataread(int id, int reg, int *data, int datasize) {
Wire.beginTransmission(id);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(id, datasize);
int i = 0;
while (Wire.available() && i < datasize) {
data[i++] = Wire.read();
}
}
void setup() {
pll_init();
uarths_init();
lcd.begin(15000000, COLOR_BLACK);
Serial.begin(115200);
Wire.begin((uint8_t) SDA, (uint8_t) SCL, 400000);
write8(AMG88_ADDR, FPSC, 0x00); // 10fps
write8(AMG88_ADDR, INTC, 0x00); // INT出力無効
write8(AMG88_ADDR, 0x1F, 0x50); // 移動平均出力モード有効
write8(AMG88_ADDR, 0x1F, 0x45);
write8(AMG88_ADDR, 0x1F, 0x57);
write8(AMG88_ADDR, AVE, 0x20);
write8(AMG88_ADDR, 0x1F, 0x00);
}
void loop() {
float temp[64];
int sensorData[128];
dataread(AMG88_ADDR, T01L, sensorData, 64);
dataread(AMG88_ADDR, T33L, sensorData + 64, 64);
for (int i = 0 ; i < 64 ; i++) {
int16_t temporaryData = sensorData[i * 2 + 1] * 256 + sensorData[i * 2];
if(temporaryData > 0x200) {
temp[i] = (-temporaryData + 0xfff) * -0.25;
} else {
temp[i] = temporaryData * 0.25;
}
}
// lcd.fillScreen(COLOR_BLACK);
int x, y;
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
float t = temp[(8 - y - 1) * 8 + 8 - x - 1];
uint16_t color = heat(map(constrain((int)t, 0, 60), 0, 60, 0, 100) / 100.0);
lcd.fillRect(x * WIDTH, y * HEIGHT, WIDTH, HEIGHT, color);
lcd.setCursor(x * WIDTH + WIDTH / 2, y * HEIGHT + HEIGHT / 2);
lcd.setTextColor(COLOR_BLACK, color);
lcd.printf("%d", (int)t);
}
}
delay(500);
}
最後に
MaixduinoにGrove Base Shieldを組み合わせて、簡単にサーマルカメラを読むことができました。