Sony Spresense LTE 확장판으로 온습도, eCO2, TVOC 데이터를 클라우드에 업로드(Thingspeak)

Sony Spresense를 통해 실내 환경 데이터를 얻고 LTE 확장판을 사용하여 데이터를 Thingspeak에 업로드합니다.
또 얻은 데이터는 중치 여과 처리가 진행 중이다.
기계 구성
이름:
유형 이름
제조사
메인보드
CXD5602PWBMAIN1
Sony
LTE 확장판
CXD5602PWBLM1J
Sony
센서판
NS-SPR-0308
Next Step
SIM 카드
IoT SIM(Plan-D)
SORACOM

사용된 센서
센서
데이터
데이터 테이블
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
센서판 회로도

Thingspeak의 설정은 다음과 같습니다.
Field 1 : eCO2
Field 2 : TVOC
Field 3 : TEMP
Field 4 : HUM
하고 있어.

다음은 이번 사생.
미안합니다.
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 데이터 표시 페이지
이전 페이지의 화면 캡처

센서판의 agele 데이터 공개 중
https://github.com/kaz19610303/SPRESENSE_CO2/

좋은 웹페이지 즐겨찾기