LoginSignup
3
1

More than 3 years have passed since last update.

ATOM Matrixにセンサを繋ぐ

Last updated at Posted at 2020-04-20

ATOM MatrixのセンサとIOで、ATOM Matrixの背面のピンを調べましたが、アナログ系のI/Oはピンが固定されるものの通信系のペリフェラル機能は好きなポートに割り当てられることがわかりました。

Wio LTEに複数のI2CなGroveモジュールを繋げるの記事で作った紫外線センサ VEML6070と気温、湿度、気圧、空気の汚染度が計測できるセンサ BME680、それとGroveのCo2センサーを繋げてI2CとUARTを確認してみます。

センサとの接続

もともとATOM MatrixにはGrove互換ポートがありますが電源が5Vのため、3.3V動作のセンサは直接繋げられません。
裏のポートからブレッドボード経由で繋げても良かったのですが、専用に基板を作りました。

image.png

専用基板経由で、センサを繋げます。

image.png

BME680(I2C)の確認

まずはI2C接続のBME680だけで動作を確認してみます。BME680はストロベリーリナックスで販売されているモジュールを使用していますが、現在はseeedからもGroveのモジュールが販売されています。
使い方はどちらも同じだと思います。

プログラム

Adafruitのライブラリがありましたので、それを使用しました。BME680で検索すれば出てきますので、インストールします。これだけでは足らなかったので、Adafruit_SensorもZipでダウンロードしてインストールします。

プログラムはほぼサンプルのままです。Wireはデフォルトのポートと異なるので、そこだけ接続しているポートに変更しています。

#include <Wire.h>
#include "Adafruit_BME680.h"

Adafruit_BME680 bme;

void setup() {
  Serial.begin(115200);
  Wire.begin(23,22);
  bme.begin();

  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms
}

void loop() {
  if (! bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  Serial.print("Temperature = ");
  Serial.print(bme.temperature);
  Serial.println(" *C");

  Serial.print("Pressure = ");
  Serial.print(bme.pressure / 100.0);
  Serial.println(" hPa");

  Serial.print("Humidity = ");
  Serial.print(bme.humidity);
  Serial.println(" %");

  Serial.print("Gas = ");
  Serial.print(bme.gas_resistance / 1000.0);
  Serial.println(" KOhms");

  Serial.println();
  delay(2000);
}

結果

シリアルモニタにセンサから取得された値が出力されました。

Temperature = 23.30 *C
Pressure = 994.49 hPa
Humidity = 50.67 %
Gas = 354.47 KOhms

Co2センサ(UART)の確認

次にUART接続のCo2センサーを確認してみます。このセンサは電源が5VでもOKなので直接繋げられますが、専用基板にも5VのGrove互換ポートを用意しているので、そちらに繋げました。

プログラム

こちらも主にサンプルのままですが、UART部分を変更しています。このセンサは温度も取得できます。

#include <HardwareSerial.h>

HardwareSerial Co2SensorSerial(1);
const unsigned char cmd_get_sensor[] =
{
    0xff, 0x01, 0x86, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x79
};

unsigned char dataRevice[9];
int temperature;
int CO2PPM;

void setup() {
  Serial.begin(115200);
  Co2SensorBegin();

};

void loop() {

  if(dataRecieve())
  {
      Serial.printf("Temperature=%d\n",temperature);
      Serial.printf("Co2=%d\n",CO2PPM);
  }
  delay(1000);
};


void Co2SensorBegin()
{
  Co2SensorSerial.begin(9600,SERIAL_8N1,25,21);
}

bool dataRecieve(void)
{
    byte data[9];
    int i = 0;

    //transmit command data
    for(i=0; i<sizeof(cmd_get_sensor); i++)
    {
        Co2SensorSerial.write(cmd_get_sensor[i]);
    }
    delay(10);
    //begin reveiceing data
    if(Co2SensorSerial.available())
    {
        while(Co2SensorSerial.available())
        {
            for(int i=0;i<9; i++)
            {
                data[i] = Co2SensorSerial.read();
            }
        }
    }

    if((i != 9) || (1 + (0xFF ^ (byte)(data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]))) != data[8])
    {
        return false;
    }

    CO2PPM = (int)data[2] * 256 + (int)data[3];
    temperature = (int)data[4] - 40;

    return true;
}

結果

シリアルモニタにセンサから取得された値が出力されました。

Temperature=27
Co2=1114
Temperature=27
Co2=1110
Temperature=27
Co2=1104
Temperature=27

センサ値をAmbientにアップロード

すべてのセンサを組み合わせてAmbientにアップロードし、グラフ化してみます。

プログラム

Ambientについては、ATOM MatrixをAmbientに繋ぐを参考にしてください。

#include <HardwareSerial.h>
#include <Wire.h>
#include "Adafruit_BME680.h"
#include "Adafruit_VEML6070.h"
#include "Ambient.h"
#include <WiFi.h>

Adafruit_BME680 bme;
Adafruit_VEML6070 uv;
HardwareSerial Co2SensorSerial(1);
WiFiClient client;
Ambient ambient;

const unsigned char cmd_get_sensor[] =
{
    0xff, 0x01, 0x86, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x79
};

unsigned char dataRevice[9];
int temperature;
int CO2PPM;

// Wi-FiのSSID
const char* ssid = "ssid";
// Wi-Fiのパスワード
const char* password = "pass";

// AmbientのチャネルID
unsigned int channelId = 100; 
// Ambientのライトキー
const char* writeKey = "write key"; 

void setup() {
  Serial.begin(115200);
  // Wi-Fi APに接続
  WiFi.begin(ssid, password);
  //  Wi-Fi AP接続待ち
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.print("WiFi connected\r\nIP address: ");
  Serial.println(WiFi.localIP());

  ambient.begin(channelId, writeKey, &client);

  Co2SensorBegin();
  Wire.begin(23,22);
  bme.begin();
  uv.begin(VEML6070_1_T);

  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms
};

void loop() {
  Serial.printf("----------------------------------------------------------------\n");
  if(bme.performReading()) {
    Serial.printf("Temperature = %f *C\n",bme.temperature);
    Serial.printf("Pressure = %f hPa\n",bme.pressure / 100.0);
    Serial.printf("Humidity = %f %%\n",bme.humidity);
    Serial.printf("Gas = %f KOhms\n",bme.gas_resistance / 1000.0);
    ambient.set(1, bme.temperature);
    ambient.set(2, bme.pressure / 100.0);
    ambient.set(3, bme.humidity);
    ambient.set(4, bme.gas_resistance / 1000.0);
  }
  Serial.printf("UvLightLevel = %d \n",uv.readUV());
  ambient.set(5, (float)uv.readUV());

  if(dataRecieve())
  {
    Serial.printf("Co2 = %d ppm\n",CO2PPM);
    ambient.set(6, (float)CO2PPM);
  }
  ambient.send();
  Serial.printf("----------------------------------------------------------------\n\n");
  delay(30000);
};


void Co2SensorBegin()
{
  Co2SensorSerial.begin(9600,SERIAL_8N1,25,21);
}

bool dataRecieve(void)
{
    byte data[9];
    int i = 0;

    //transmit command data
    for(i=0; i<sizeof(cmd_get_sensor); i++)
    {
        Co2SensorSerial.write(cmd_get_sensor[i]);
    }
    delay(10);
    //begin reveiceing data
    if(Co2SensorSerial.available())
    {
        while(Co2SensorSerial.available())
        {
            for(int i=0;i<9; i++)
            {
                data[i] = Co2SensorSerial.read();
            }
        }
    }

    if((i != 9) || (1 + (0xFF ^ (byte)(data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]))) != data[8])
    {
        return false;
    }

    CO2PPM = (int)data[2] * 256 + (int)data[3];
    temperature = (int)data[4] - 40;

    return true;
}

結果

センサから取得した各値がAmbient上でグラフ化されました。
(室内で計測したため、UV Levelは0のままです。日に当てると変化することは確認しています)
image.png

あとがき

センサーの精度と計測環境的に値の精度はそれほど高くないと思います。どちらかというと変化を検出したいのでAIで解析させて、環境の状態通知をやってみたいと思いました。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1