心理サイエンス基礎演習Ⅱ-13

前回リアクションへのフィードバック
 前回は、M5StickCを使用してみました。今回初めてArduinoに触れ、ものづくり特有のワクワク感、充実感を感じたかたも多かったようです。一方で、トラブルでうまく進められなかった方もいらっしゃったようでした。 M5StickCがうまく認識されない場合は、下記の動画をリンクからドライバーインストールをお試し下さい。
USB to Serial Driverのインストールはこちらから
Arduino開発環境のインストールはこちらから

温度センサーと環境センサーを同時に用いる
 今回はより本格的な実験を想定して、部屋の温度や湿度と、指先の温度を同時に測定できる環境を整えてみましょう。まずは温度センサーだけを接続し、それができることを確認したら、温度センサーと環境センサー同時に接続し動作を確認してみます。 これらのプログラムは、MCP342xというライブラリを必要としますので、あらかじめインストールをお願いします。
※下記動画ですが、昨年度貸与した環境センサーが一部返却されず、十分な数が確保できなかったため、今年は配布しておりません。温度センサーを動作させる部分のみ行って下さい。

MCP9700という温度センサーで温度を測るプログラム

//TEMP2
#include <M5StickC.h>
#include <Wire.h>
#include <MCP342x.h>
uint8_t address = 0x68;
MCP342x adc = MCP342x(address);
float temp;
 
void setup(void)
{
  M5.begin();
  M5.Lcd.setRotation(1);
  M5.Lcd.setTextSize(3);

  Serial.begin(115200);
  Wire.begin();
  MCP342x::generalCallReset();
  delay(1);
 
  Wire.requestFrom(address, (uint8_t)1);
  if (!Wire.available()) {
    Serial.print("指定のデバイスが見つかりません。");
    Serial.println(address, HEX);
    while (1);
  }
}
 
void loop(void)
{
  long value = 0;
  MCP342x::Config status;
 
  uint8_t err = adc.convertAndRead(MCP342x::channel1, MCP342x::oneShot,
           MCP342x::resolution16, MCP342x::gain1,
           100000, value, status);
  if (err) {
    Serial.print("Convert error: ");
    Serial.println(err);
  }
  else {
    temp=  value * 2.048 / 32767 * 100 - 50;
    Serial.println(temp);

    String buf="";
    buf=temp;
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.print(buf);
  }
  delay(100);
}

温度センサーと環境センサーを同時に用いるプログラム

//TEMP_ENV
#include <M5StickC.h>
#include "ClosedCube_SHT31D.h"
#include <Wire.h>
#include "Adafruit_Sensor.h"
#include <Adafruit_BMP280.h>
#include <MCP342x.h>
uint8_t address = 0x68;
MCP342x adc = MCP342x(address);
float temp;
ClosedCube_SHT31D sht3xd;
SHT31D result;
Adafruit_BMP280 bme;

 
void setup(void)
{
  M5.begin();
  M5.Lcd.setRotation(1);
  M5.Lcd.setTextSize(2);

  Serial.begin(115200);
  Wire.begin();               // I2Cを初期化する
 
  MCP342x::generalCallReset();
  delay(1);
 
  Wire.requestFrom(address, (uint8_t)1);
  if (!Wire.available()) {
    Serial.print("指定のデバイスが見つかりません。");
    Serial.println(address, HEX);
    while (1);
  }

  while (!bme.begin(0x76)) {  // BMP280を初期化する
      M5.Lcd.println("BMP280 init fail");
  }  
  sht3xd.begin(0x44); // I2C address: 0x44 or 0x45
  if (sht3xd.periodicStart(SHT3XD_REPEATABILITY_HIGH, SHT3XD_FREQUENCY_10HZ) != SHT3XD_NO_ERROR)
    Serial.println("[ERROR] Cannot start periodic mode");
}
 
void loop(void)
{
  long value = 0;
  MCP342x::Config status;
 
  uint8_t err = adc.convertAndRead(MCP342x::channel1, MCP342x::oneShot,
           MCP342x::resolution16, MCP342x::gain1,
           100000, value, status);
  if (err) {
    Serial.print("Convert error: ");
    Serial.println(err);
  }
  else {
    temp=  value * 2.048 / 32767 * 100 - 50;
    result=sht3xd.periodicFetchData();
    float pressure = bme.readPressure();
    double vbat = M5.Axp.GetVbatData() * 1.1 / 1000;  // バッテリー電圧を取得 ----D

    M5.Lcd.setCursor(0, 0, 1);
    M5.Lcd.printf("Ftemp:%.2f\r\n", temp);
    M5.Lcd.printf("Etemp:%.2f\r\n", result.t);
    M5.Lcd.printf("humid:%.2f\r\n", result.rh);
    M5.Lcd.printf("press:%.2f\r\n", pressure / 100);
    M5.Lcd.printf("vbat:%.2f\r\n", vbat);

    String buf="";
    Serial.printf("%.2f,", temp);
    Serial.printf("%.2f,", result.t);
    Serial.printf("%.2f,", result.rh);
    Serial.printf("%.2f,", pressure / 100-1000);
    Serial.printf("%.2f,\r\n", vbat);
  }
 
  delay(100);
}

時刻サーバーとリアルタイムクロックを使う
 今日は最後にインターネットに接続して時刻を取得するというプログラムを動かしてみましょう。M5StickCをインターネットに接続する練習となります。NTPサーバーとは、インターネットで正確な時刻を発信しているサーバーのことで、これに定期的に接続することにより携帯電話などの電子機器は、正確な時刻を保つことができます。さらに、時刻を電子機器に内蔵されているリアルタイムクロックに書き込み、保持することで、ネットがない環境でも正確な時間を刻むことができるようになります。

NTPとRTCを使うプログラム

//NTP_RTC
#include <M5StickC.h>
#include <WiFi.h>
#include "time.h"

const char* ssid       = "HELL";            //SSID
const char* password   = "hogehoge";  //パスワード
const char* ntpServer =  "ntp.jst.mfeed.ad.jp";

RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;

void setup() {
  // put your setup code here, to run once:
  M5.begin();
  M5.Lcd.setRotation(1);
  M5.Lcd.fillScreen(BLACK);

  M5.Lcd.setTextSize(1);
  M5.Lcd.setCursor(40, 0, 2);
  M5.Lcd.println("RTC NTP TEST");

  // connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" CONNECTED");

  // Set ntp time to local
  configTime(9 * 3600, 0, ntpServer);

  // Get local time
  struct tm timeInfo;
  if (getLocalTime(&timeInfo)) {
    M5.Lcd.print("NTP : ");
    M5.Lcd.println(ntpServer);

    // Set RTC time
    RTC_TimeTypeDef TimeStruct;
    TimeStruct.Hours   = timeInfo.tm_hour;
    TimeStruct.Minutes = timeInfo.tm_min;
    TimeStruct.Seconds = timeInfo.tm_sec;
    M5.Rtc.SetTime(&TimeStruct);

    RTC_DateTypeDef DateStruct;
    DateStruct.WeekDay = timeInfo.tm_wday;
    DateStruct.Month = timeInfo.tm_mon + 1;
    DateStruct.Date = timeInfo.tm_mday;
    DateStruct.Year = timeInfo.tm_year + 1900;
    M5.Rtc.SetData(&DateStruct);
  }

  //disconnect WiFi
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}

void loop() {
  static const char *wd[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
  
  // put your main code here, to run repeatedly:
  M5.Rtc.GetTime(&RTC_TimeStruct);
  M5.Rtc.GetData(&RTC_DateStruct);
  M5.Lcd.setCursor(0, 30);
  M5.Lcd.printf("Data: %04d-%02d-%02d\n", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
  M5.Lcd.printf("Week: %s\n", wd[RTC_DateStruct.WeekDay]);
  M5.Lcd.printf("Time: %02d : %02d : %02d\n", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
  delay(500);
}

 課題が終わった方は、下記アドレスからリアクションを登録してください。今日は特に送っていただくものはありません。リアクションは出欠記録を兼ねています。また、成績評価の対象となることに留意して下さい。リアクションは原則として授業配信日を含む3日以内にお送りください。
心理サイエンス基礎演習2リアクション