LoginSignup
6
2

More than 3 years have passed since last update.

Sony Spresense LTE拡張ボードで温湿度、eCO2、TVOCのデータをCloud(Thingspeak)にアップロード

Last updated at Posted at 2021-01-04

Sony Spresenseで室内環境データを取得してLTE拡張ボードを使ってデータをThingspeakにアップロードしました。
なお取得したデータはメディアンフィルター処理をしています。

機器構成

名称 型名 メーカー
メインボード CXD5602PWBMAIN1 Sony
LTE拡張ボード CXD5602PWBLM1J Sony
センサーボード NS-SPR-0308 Next Step
SIMカード IoT SIM(Plan-D) SORACOM

image.png

使用したセンサー

センサー データ データシート
SHTC1 温度・湿度 https://www.mouser.jp/datasheet/2/682/Sensirion_Humidity_Sensors_SHTC1_Datasheet-1511754.pdf
SGP30-2.5k eCO2・TVOC https://www.mouser.jp/datasheet/2/682/Sensirion_Gas_Sensors_SGP30_Datasheet-1843629.pdf

センサーボード回路図
image.png

Thingspeakの設定は以下のように
Field 1 : eCO2
Field 2 : TVOC
Field 3 : TEMP
Field 4 : HUM
にしています。

image.png

以下が今回のスケッチになります。

すみません、コメント少ないです

LteWebClient_thingspeak.ino
/*
  Sample program for the Sensirion SGP30&SHTC1 Indoor Air Quality Sensor
  By: Kazuaki Ueno
  Next Step LLC
  Date: Dec. 30th, 2020
  License: This code is public domain.

  SGP30 Datasheet: https://cdn.sparkfun.com/assets/c/0/a/2/e/Sensirion_Gas_Sensors_SGP30_Datasheet.pdf

  Feel like supporting our work? Buy a board from Next Step!

  This example reads the sensors calculated CO2 and TVOC values
*/

// libraries
#include <LTE.h>
#include <Wire.h>
#include <stdlib.h>
#include "SparkFun_SGP30_Arduino_Library.h"                 // Click here to get the library: http://librarymanager/All#SparkFun_SGP30
#include <shtc1.h>

SGP30 mySensor;                                             //create an object of the SGP30 class
SHTC1 shtc1;

// APN data
#define LTE_APN       "soracom.io"                          // replace your APN
#define LTE_USER_NAME "sora"                                // replace with your username
#define LTE_PASSWORD  "sora"                                // replace with your password

// アップロード間隔
#define SAMPLE_NUMS (12)                                    // 2分間隔

// initialize the library instance
LTE lteAccess;
LTEClient client;

// URL, path & port (for example: arduino.cc)
char server[] = "api.thingspeak.com";
char path[100];
int  port = 80;                                             // port 80 is the default for HTTP


int compareFloat(const void*, const void*);
float get_median(const float*, uint8_t);

int compareFloat(const void* a, const void* b)
{
    int aNum = *(float*)a;
    int bNum = *(float*)b;

    if( aNum < bNum ){
        return -1;
    }
    else if( aNum > bNum ){
        return 1;
    }
    return 0;
}

float get_median(const float* array, uint8_t size)
{
    float median;

    float* array_copy = malloc(sizeof(float) * size);
    memcpy(array_copy, array, sizeof(float) * size);
    qsort(array_copy, size, sizeof(float), compareFloat);
    median = array_copy[size / 2];
    free(array_copy);
    return median;
}

void setup()
{
  Wire.begin();
  //Initialize sensor for air CO2&TVOC readings
  if (mySensor.begin() == false) {
    Serial.println("No SGP30 Detected. Check connections.");
    while (1);
  }
  //Initializes sensor for air quality readings
  //measureAirQuality should be called in one second increments after a call to initAirQuality
  mySensor.initAirQuality();


  // initialize serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
      ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("Starting web client.(LTE connection)");
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  while (true) {
    if (lteAccess.begin() == LTE_SEARCHING) {
      if (lteAccess.attach(LTE_APN, LTE_USER_NAME, LTE_PASSWORD) == LTE_READY) {
        Serial.println("attach succeeded.");
        break;
      }
      Serial.println("An error occurred, shutdown and try again.");
      lteAccess.shutdown();
      sleep(1);
    }
  }
}

void loop()
{
  static float co2_arry[5]  = {0.0};
  static float tvoc_arry[5] = {0.0};
  static float temp_arry[5] = {0.0};
  static float hum_arry[5]  = {0.0};

  static float co2_sum  = 0.0;
  static float tvoc_sum = 0.0;
  static float temp_sum = 0.0;
  static float hum_sum  = 0.0;

  static uint8_t counter = 0;

  float co2,tvoc,temp,hum;
  uint8_t i;

  //First fifteen readings will be
  //CO2: 400 ppm  TVOC: 0 ppb
  //measure CO2 and TVOC levels
  mySensor.measureAirQuality();
  //measure TEMP and HUM levels
  shtc1.readSample();

  // Obtain data from the sensors.
  co2  = float(mySensor.CO2);
  tvoc = float(mySensor.TVOC);
  temp = shtc1.getTemperature();
  hum  = shtc1.getHumidity();

  // Median Filtering.
  for(i = 1 ; i < 5; i++){
    co2_arry[i-1]  = co2_arry[i];
    tvoc_arry[i-1] = tvoc_arry[i];
    temp_arry[i-1] = temp_arry[i];
    hum_arry[i-1]  = hum_arry[i];
  }
  co2_arry[4]  = co2;
  tvoc_arry[4] = tvoc;
  temp_arry[4] = temp;
  hum_arry[4]  = hum;

  co2   = get_median(co2_arry,5);
  tvoc  = get_median(tvoc_arry,5);
  temp  = get_median(temp_arry,5);
  hum   = get_median(hum_arry,5);

  co2_sum  += co2;
  tvoc_sum += tvoc;
  temp_sum += temp;
  hum_sum  += hum;

  Serial.print("CO2: ");
  Serial.print(co2,0);
  Serial.print("ppm  tTVOC: ");
  Serial.print(tvoc,0);
  Serial.print("ppb");

  Serial.print("  RH: ");
  Serial.print(hum, 2);
  Serial.print("%  TEMP: ");
  Serial.print(temp, 2);
  Serial.println("℃");
  counter++;

  // Data upload to Thingspeak.
  if(counter >= SAMPLE_NUMS){
    // Set data for Thingspeak.
    sprintf(path,"/update?api_key=xxxxxxxxxxxxxxxxxxxxxxx&field1=%4.0f&field2=%4.0f&field3=%5.2f&field4=%5.2f",co2_sum/SAMPLE_NUMS,tvoc_sum/SAMPLE_NUMS,temp_sum/SAMPLE_NUMS,hum_sum/SAMPLE_NUMS);
    // (xxxxxxxxxxxxxxxxxxxxxxxはThingspeakで発行されたAPIキーに変更して下さい)

    // if you get a connection, report back via serial:
    if (client.connect(server, port)) {
      Serial.println("connected");
      // Make a HTTP request:
      client.print("GET ");
      client.print(path);
      client.println(" HTTP/1.1");
      client.print("Host: ");
      client.println(server);
      client.println("Connection: close");
      client.println();
    } else {
      // if you didn't get a connection to the server:
      Serial.println("connection failed");
    }
    delay(100);
    // if there are incoming bytes available
    // from the server, read them and print them:
    if (int len = client.available()) {
      char buff[len + 1];
      buff[len] = '\0';
      client.read((uint8_t*)buff, len);
      Serial.print(buff);
    }

    // if the server's disconnected, stop the client:
    if (!client.available() && !client.connected()) {
      Serial.println();
      Serial.println("disconnecting.");
      client.stop();

      // do nothing forevermore:
      for (;;)
        sleep(1);
    }
    co2_sum  = 0.0;
    tvoc_sum = 0.0;
    temp_sum = 0.0;
    hum_sum  = 0.0;
    counter = 0;
  }
  delay(10000);
}

Thingspeakのデータ表示ページ

上記ページの画面キャプチャー
image.png


センサーボードのEagleデータを公開中
https://github.com/kaz19610303/SPRESENSE_CO2/

6
2
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
6
2