[AWS IoT] AWS IoTのデバッグ用にデータジェネレーターを作ってみました

2020.01.05

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