[AWS IoT] AWS IoTのデバッグ用にデータジェネレーターを作ってみました
1 はじめに
CX事業本部の平内(SIN)です。
AWS IoTでエッジデバイスから温度センサーなどデータを処理している時、デバック用にそれらしいデータが欲しくなる場面があります。
ダミーのデータを生成する要領は、色々あると思いますが、今回は、ボリュームを回す感覚で、それらしいデータが生成できるジェネレーターを作ってみました。(冬休みの自由研究的な)
最初に利用している様子です。
ジェネレーターで生成したデータを逐次MQTTで送信しています。
本記事は、MQTTの送信には触れておりません、単にデータを生成するデバイスの工作に関するものです。それでも良いって方は、読み進めて頂ければ嬉しいです。
2 構成
構成は、図のとおりです。
データの生成は、可変抵抗で行っています。RaspberryPIには、アナログポートが無いため、ADS1115でAD変換を行っています。
生成されたデータを表示しているのは、4桁の7セグメントLEDとNeopixelのLEDです。
ADS1115と7セグメントLEDは、I2Cバスで接続されています。
NeoPixelのLEDは、内部のICで制御されており、専用のコントローラー(ライブラリー使用)が、RaspberryPIで動作しています。
3 RaspberryPI
使用したRaspberryPIは、以下のとおりです。
ハード
3 Model B
$ cat /proc/cpuinfo | grep Revision Revision : a32082
OSイメージ
OSイメージは、Raspbian Buster with desktop and recommended softwareの2019.9.24です。
uname -a Linux raspberrypi 4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019 armv7l GNU/Linux
$ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 10 (buster) Release: 10 Codename: buster
4 AD変換
AD変換は、ADS1115 16Bit ADC 4チャンネル I2Cのユニットを使用しています。
https://www.amazon.co.jp/gp/product/B07TZ56M65/
接続は、以下のとおりです。ADS1115は、電源とI2Cバスで接続され、アナログポート(A0)でボリュームで変化する電圧を取得しています。下記の構成では、電圧は、2.5〜4.0の間で変化するので、Node.jsのプログラムで、解像度1000で数値化しています。
ADS1115のI2Cバス上のアドレスは、デフォルトで0x48です。
$ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
下記は、取得したデータを数値化しているコードです。
"use strict"; const I2C = require('raspi-i2c').I2C; const ADS1x15 = require('raspi-kit-ads1x15'); class ADConv{ constructor(i2c){ this.adc = new ADS1x15({ i2c, chip: ADS1x15.chips.IC_ADS1015, address: ADS1x15.address.ADDRESS_0x48, pga: ADS1x15.pga.PGA_4_096V, sps: ADS1x15.spsADS1015.SPS_250 }); this.channel = ADS1x15.channel.CHANNEL_0; this.min = 1270; // 最低値 this.max = 2027; // 最高値 this.range = this.max - this.min; } async read(){ return new Promise((resolve,reject)=> { this.adc.readChannel(this.channel, (err, value, volts) => { if (err) { console.error('Failed to fetch value from ADC', err); reject(err); } else { let val = value - this.min; val = val / this.range * 100; if(val < 0){ val = 0; } if(100 <= val){ val = 100; } resolve(Math.round(val * 10) / 10); // 小数第一位を基準 } }) }); } } async function main() { const i2c = new I2C(); const adconv = new ADConv(i2c); while(true){ const value = await adconv.read(); console.log(value); await sleep(100); } } main();
データの生成をテストしている様子です。
5 4桁7セグメントLED
数値の表示は、4桁7セグメントLEDディスプレイモジュール HT16K33を使用しています。
https://www.amazon.co.jp/gp/product/B07QVGTVDV/
接続は、電源とI2Cバスで接続されています。
各桁は、メモリ上のワード配列と一致しています。
また、各セグメントは、下記のビットに対応しています。7セグメント(ドットを入れると8セグメント)なので、8ビットで表現できるため、ワードの上位バイトは関係ないことになります。
下記は、1,2,3を表示する場合のビット例です。
HT16K33のI2Cバス上のアドレスは、0x70です。
$ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: 70 -- -- -- -- -- -- --
そして、数字を表示しているコードの例です。
class SevenSegLED { constructor(i2c){ this.i2c = i2c; this.number = [0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f]; this.HT16K33 = 0x70; this.buffer = new Buffer.alloc(0x20); // initiaruize this.i2c.writeByteSync(this.HT16K33, (0x20 | 0x01), 1); this.i2c.writeByteSync(this.HT16K33, (0x80 | 0b00000001), 1); } disp(n){ let str = n.toFixed(1); str = ('000' + str).slice(-5); // .1桁 this.buffer[9] = this.number[Number(str[str.length-1])]; // 0桁 this.buffer[7] = this.number[Number(str[str.length-3])]; this.buffer[7] |= 0x80; // 小数点 // 10桁 this.buffer[3] = this.number[Number(str[str.length-4])]; // 100桁 this.buffer[1] = this.number[Number(str[str.length-5])]; // 0パディングは表示しない if(this.buffer[1] == 0x3f){ this.buffer[1] = 0; if(this.buffer[3] == 0x3f){ this.buffer[3] = 0; } } for(var i=0;i<10;i++){ this.i2c.writeByteSync(this.HT16K33, i, this.buffer[i+1]); } } } async function main() { const sevenSegLED = new SevenSegLED(i2c); let value = 0; while(true){ console.log(value); sevenSegLED.disp(value); value += 0.1; await sleep(10); } } main();
テストしている様子です。
6 WS2812B neopixel PCB 8連
レベルメーターのように使用しているLEDは、フルカラーが表現できるneopixelのWS2812Bです。
https://www.amazon.co.jp/waves-WS2812B-neopixel-PCB-8%E9%80%A3/dp/B07G45H23Y/
本体内の各LEDがICで制御されているため、接続は、電源以外に1線だけで終わりです。
そして、制御しているコードは、以下のようになっています。
var ws281x = require('rpi-ws281x-v2'); class Pixels { constructor(){ const config = { leds: 8, //dma: 10, // Use DMA brightness: 100,//255, // 0-255 gpio: 18,// BMC18(12pin) strip: 'rgb' // "rgb", "rbg", "grb", "gbr", "bgr", "brg". }; ws281x.configure(config); this.pixels = new Uint32Array(config.leds); } // dat=0..100 show(dat){ const n = dat * 0.08 for(var i=0; i < 8; i++) { if(i < n){ if (i < 4) { this.pixels[i] = 0xFF0000; // GREEN } else if(i < 6) { this.pixels[i] = 0xFFFF00; // YELLOW } else if(i < 7) { this.pixels[i] = 0x88FF00; // ORANGE } else { this.pixels[i] = 0x00FF00; // RED } } else { this.pixels[i] = 0x000000; } } ws281x.render(this.pixels); } } async function main() { const pixels = new Pixels(); let value = 0; while(true){ console.log(value); pixels.show(value); value += 0.1; await sleep(10); } } main();
表示をテストしている様子です。
7 接続テスト
全部繋いでテストしています。
そして、ユニバーサル基盤に載せたところです。
8 最後に
これで、AWS IoTのデバッグが捗れば(楽しくなれば)本望です。
すべてのコードは、下記に置きました。
https://github.com/furuya02/generator.git