non vorrei lavorare

昔はおもにプログラミングやガジェット系、今は?

Arduinoで測った室温をデスクトップマスコットのgopheronに表示させた

背景

arduinoを手に入れて、何かPCと連携してみたくなった。

Arduinoで測った室温をデスクトップマスコットのgopheronに表示

構成

  • node.jsでarduinoの計測結果をシリアルポート経由で受信し、ファイルに出力
  • ファイル出力はリダイレクトで実現

node.jsでarduinoの計測結果をシリアルポート経由で受信

シリアル通信には、以下のモジュールを使用した。

serialport.io

インストールは以下のようにできる。

npm i -S serialport

このserialportモジュールはパーサーをいくつか選べるようで、今回はreadLineパーサーを使って、 arduino側で"\n"を入れることで、このパーサーと連携した。

node.jsの受信部

const SerialPort = require("serialport")
const Readline = SerialPort.parsers.Readline
const sp = new SerialPort("/dev/cu.usbmodem14201", {
    baudRate: 9600
})
const parser = new Readline()
sp.pipe(parser)

parser.on('data', (line) => {
    console.log(`line : ${line}`)
})

sp.on("open", () => {
    console.log('open')
})

arduino側のコード

arduino側はサンプルのコードの結果をシリアルポートに書き込むように処理を追加した程度。

//www.elegoo.com
//2016.12.9

#include <LiquidCrystal.h>
int tempPin = 0;
//                BS  E  D4 D5  D6 D7
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
void setup()
{
  lcd.begin(16, 2);
  Serial.begin(9600);
}
void loop()
{
  int tempReading = analogRead(tempPin);
  // This is OK
  double tempK = log(10000.0 * ((1024.0 / tempReading - 1)));
  tempK = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * tempK * tempK )) * tempK );       //  Temp Kelvin
  float tempC = tempK - 273.15;            // Convert Kelvin to Celcius
  float tempF = (tempC * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
  /*  replaced
    float tempVolts = tempReading * 5.0 / 1024.0;
    float tempC = (tempVolts - 0.5) * 10.0;
    float tempF = tempC * 9.0 / 5.0 + 32.0;
  */
  // Display Temperature in C
  lcd.setCursor(0, 0);
  lcd.print("Temp         C  ");
  // Display Temperature in F
  //lcd.print("Temp         F  ");
  lcd.setCursor(6, 0);
  // Display Temperature in C
  lcd.print(tempC);
  Serial.print(tempC);
  Serial.print("\n");
  // Display Temperature in F
  //lcd.print(tempF);
  delay(500);
}

デスクトップマスコットへの通信コマンド

デスクトップマスコットはWebSocketを受け付けているので、 先ほどの計測した室温のファイルをtailコマンド風に追加された行を読み込んで、これを WebSocketに書き込む。

アイコンは例によって、PNGを同期APIのfs#readFileSyncで読み込んで、base64でHTMLに埋めむ実装

node.jsでtailコマンド風の処理をする

以下のモジュールでnode.jsでtailコマンド風にファイルに追加された行を取得できる。

npm i -S node-tail

tail風の処理は以下のようになる。

const Tail = require('tail').Tail

const filename = "/path/to/roomTemp.dat"

const tail = new Tail(filename);

tail.on('line', (line) => {
        const temp = line.split(':')[1]
        console.log(`temp : ${temp}`)
}

tail.on('close', () => {
      console.log('watching stopped');
})
     
tail.watch()

setTimeout(()=>{
     tail.unwatch()
},5000)
const socket = require('socket.io-client')('http://localhost:5050')
const Tail = require('tail').Tail
const fs = require('fs')

const filename = "/Users/kjunichi/work/nodejs/arduino/serial/roomTemp.dat"
const logo = fs.readFileSync("./ArduinoCommunityLogo.png")

socket.on('connect', () => {
    const tail = new Tail(filename);
    let count;

    socket.on('gopher recv', (msg) => {
        console.log(`recv: ${msg}`)
        count--
        if (count <= 0) {
          process.exit(0)
        }
    })

    const displayTemp = (temp) => {
        count=2;
        socket.emit('gopher front', '1000')
        const html = `<img width="192" src="data:image/png;base64,${logo.toString('base64')}"><span style=\"font-size:larger;font-family: 'Segoe UI Emoji';\"><div style=\"font-size: 48px;wrap\">🌡 ${temp}℃</div></span>`
        socket.emit('gopher sendHtml', html)
        tail.unwatch()
    }

    tail.on('line', (line) => {
        const temp = line.split(':')[1]
        console.log(`temp : ${temp}`)
        displayTemp(temp)
    })
     
    tail.on('close', () => {
      console.log('watching stopped');
    })
     
    tail.watch()
})

実行結果

youtu.be

今回使用したArduino

関連記事

gopheronつながり

4年前の記事

3年前の記事

2年前の記事