完成品

皮膚電位,皮膚温センサのArduino IDEのスケッチ

#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiUDP.h>
#include "time.h"


#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 26 // データ(黄)で使用するポート番号
#define SENSER_BIT   9 // 精度の設定bit
// 0.5, 0.25, 0.125, 0.0625度:9, 10, 11, 12ビット
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

const char* ssid       = "ssid";     //秘密
const char* password   = "password"; //秘密
const char* saddr = "XXX.XXX.XXX.XXX"; //受け手の端末のIPアドレス

double vbat = 0.0;
int8_t bat_charge_p = 0;

const char* ntpServer =  "ntp.jst.mfeed.ad.jp";
const int sport = 55999;
const int kport = 5556;

RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;

uint8_t mac3[6];

WiFiUDP Udp;
char packetBuffer[255];


void setup() {
  // put your setup code here, to run once:
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  M5.Axp.ScreenBreath(9); // MIN7-MAX12
  
  sensors.setResolution(SENSER_BIT);
  pinMode(26,INPUT);
  
  esp_read_mac(mac3, ESP_MAC_WIFI_STA);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setCursor(1, 0, 2);
  M5.Lcd.println("Welcome \n If the connection fails, turn off and on the power again.");
 
  // connect to WiFi
  M5.Lcd.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    M5.Lcd.print(".");

  }
  M5.Lcd.println(" CONNECTED");
//  Serial.println(" CONNECTED");
  delay(1000);

  // Set ntp time to local
  configTime(9 * 3600, 0, ntpServer);
  // Get local time
  struct tm timeInfo;
  if (getLocalTime(&timeInfo)) {
    // 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);
  }
  M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(0, 1, 2);
    M5.Lcd.print("WIFI: ");
    M5.Lcd.println(WiFi.localIP());
   uint8_t mac3[6];
   esp_read_mac(mac3, ESP_MAC_WIFI_STA);
  M5.Lcd.printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac3[0], mac3[1], mac3[2], mac3[3], mac3[4], mac3[5]);
  Udp.begin(kport); 
  
}

void loop() {
  int mil = millis(); 

  vbat = M5.Axp.GetVbatData() * 1.1 / 1000;
  bat_charge_p = int8_t((vbat - 3.0) / 1.2 * 100);
  if(bat_charge_p > 100){
    bat_charge_p = 100;
  }else if(bat_charge_p < 0){
    bat_charge_p = 0;
  }
  M5.Lcd.setCursor(0, 34);
  M5.Lcd.printf("CHARGE: %3d%%", bat_charge_p);
  
  // put your main code here, to run repeatedly:
  M5.Rtc.GetTime(&RTC_TimeStruct);
  M5.Rtc.GetData(&RTC_DateStruct);
  M5.Lcd.setCursor(0, 50);
  M5.Lcd.printf("%04d-%02d-%02d ", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
//  M5.Lcd.printf("millis: %6d\n",mil);
  M5.Lcd.printf("%02d:%02d:%02d\n", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
//  Serial.printf("%04d-%02d-%02d (%s) %02d : %02d : %02d\n", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date, RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);

  int val = analogRead(33);

  sensors.requestTemperatures();              // 温度取得要求
  float tp = sensors.getTempCByIndex(0);      //温度の取得

  M5.Lcd.printf("GSR: %4d TEMP: %4.1f'C   ", val, tp);

  //UDP
  Udp.beginPacket(saddr, sport);
  Udp.printf("gsrtemp![%02X:%02X:%02X:%02X:%02X:%02X], %04d-%02d-%02d %02d:%02d:%02d, %6d, %4d, %4.1f", mac3[0], mac3[1], mac3[2], mac3[3], mac3[4], mac3[5], RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date, RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds, mil, val, tp);
  Udp.endPacket();  
  delay(100);
}

加速度センサのArduino IDEのスケッチ

#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiUDP.h>
#include "time.h"

const char* ssid       = "ssid";     //秘密
const char* password   = "password"; //秘密
const char* saddr = "XXX.XXX.XXX.XXX"; //受け手の端末のIPアドレス

double vbat = 0.0;
int8_t bat_charge_p = 0;

const char* ntpServer =  "ntp.jst.mfeed.ad.jp";
const int sport = 55998;
const int kport = 5556;

RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;

float accX = 0.0F;
float accY = 0.0F;
float accZ = 0.0F;

uint8_t mac3[6];

WiFiUDP Udp;
char packetBuffer[255];


void setup() {
  // put your setup code here, to run once:
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  M5.Axp.ScreenBreath(9); // MIN7-MAX12

  M5.IMU.Init();
  
  esp_read_mac(mac3, ESP_MAC_WIFI_STA);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setCursor(1, 0, 2);
  M5.Lcd.println("Welcome \n If the connection fails, turn off and on the power again.");
 
  // connect to WiFi
  M5.Lcd.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    M5.Lcd.print(".");

  }
  M5.Lcd.println(" CONNECTED");
//  Serial.println(" CONNECTED");
  delay(1000);

  // Set ntp time to local
  configTime(9 * 3600, 0, ntpServer);
  // Get local time
  struct tm timeInfo;
  if (getLocalTime(&timeInfo)) {
    // 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);
  }
  M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(0, 1, 2);
    M5.Lcd.print("WIFI: ");
    M5.Lcd.println(WiFi.localIP());
   uint8_t mac3[6];
   esp_read_mac(mac3, ESP_MAC_WIFI_STA);
  M5.Lcd.printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac3[0], mac3[1], mac3[2], mac3[3], mac3[4], mac3[5]);
  Udp.begin(kport); 
  
}

void loop() {
  int mil = millis(); 

  vbat = M5.Axp.GetVbatData() * 1.1 / 1000;
  bat_charge_p = int8_t((vbat - 3.0) / 1.2 * 100);
  if(bat_charge_p > 100){
    bat_charge_p = 100;
  }else if(bat_charge_p < 0){
    bat_charge_p = 0;
  }
  M5.Lcd.setCursor(0, 34);
  M5.Lcd.printf("CHARGE: %3d%%", bat_charge_p);
  
  // put your main code here, to run repeatedly:
  M5.Rtc.GetTime(&RTC_TimeStruct);
  M5.Rtc.GetData(&RTC_DateStruct);
  M5.Lcd.setCursor(0, 50);
  M5.Lcd.printf("%04d-%02d-%02d ", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
//  M5.Lcd.printf("millis: %6d\n",mil);
  M5.Lcd.printf("%02d:%02d:%02d\n", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
//  Serial.printf("%04d-%02d-%02d (%s) %02d : %02d : %02d\n", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date, RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);

  // 加速度データ取得
  M5.IMU.getAccelData(&accX, &accY, &accZ);
  M5.Lcd.printf("X:%5.2f Y:%5.2f Z:%5.2f   ", accX, accY, accZ);

  //UDP
  Udp.beginPacket(saddr, sport);
  Udp.printf("acc![%02X:%02X:%02X:%02X:%02X:%02X], %04d-%02d-%02d %02d:%02d:%02d, %6d, %5.2f, %5.2f, %5.2f", mac3[0], mac3[1], mac3[2], mac3[3], mac3[4], mac3[5], RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date, RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds, mil, accX, accY, accZ);
  Udp.endPacket();  
  delay(100);
}

2つのM5StickCのデータを受け取って処理するProcessingのスケッチ

// import UDP library
import hypermedia.net.*;

String ip = "XXX.XXX.XXX.XXX"; //受け手の端末のIPアドレス

float mil;
float accX;
float accY;
float accZ;
float accXYZ;
int gsr;
float tp;
int g;

graphMonitor_acc accGraph;
graphMonitor_ondo ondoGraph;
graphMonitor_gsr gsrGraph;

UDP udp1;  // define the UDP object
UDP udp2;  // define the UDP object

PrintWriter output1;
PrintWriter output2;
PrintWriter output3;
  int loga = 0;
  int logb = 0;
  String mesa;
  String mesb;
  String mesab;

static final int dat_acc = 2;
static final int dat_ondo = 3;
static final int dat_gsr = 5;


void setup() {
  size(1366,768);
  PFont font = createFont("Arial",48,true);
  textFont(font);
  frameRate(60);
  smooth();
  accGraph  = new graphMonitor_acc("acc", 794, 50, 500, 300);
  gsrGraph  = new graphMonitor_gsr("GSR", 794, 418, 500, 300);
  ondoGraph  = new graphMonitor_ondo("temp", 122, 418, 500, 300);
 
  String filename1 = nf(year(),2)+nf(month(),2)+nf(day(),2)+nf(hour(),2)+nf(minute(),2)+nf(second(),2)+"_log1.csv";
  String filename2 = nf(year(),2)+nf(month(),2)+nf(day(),2)+nf(hour(),2)+nf(minute(),2)+nf(second(),2)+"_log2.csv";
  String filename3 = nf(year(),2)+nf(month(),2)+nf(day(),2)+nf(hour(),2)+nf(minute(),2)+nf(second(),2)+"_log3.csv";

  output1 = createWriter(filename1);
  output2 = createWriter(filename2);
  output3 = createWriter(filename3);

  udp1 = new UDP( this, 55998 );
  udp1.listen( true );
  udp2 = new UDP( this, 55999 );
  udp2.listen( true );

}

//process events
void draw() {
if (g == 1){
  background(245,245,245);
  accGraph.graphDraw_acc(accXYZ);
  ondoGraph.graphDraw_ondo(tp);
  gsrGraph.graphDraw_gsr(gsr);
  text(int(mil),100,18);
  g = 0;
}
}


void keyPressed() {
    
    String message  = str( key );   // the message to send
    int port1        = 55998;       // the destination port
    int port2        = 55999;    // the destination port
    

    message = message+";\n";
    udp1.send( message, ip, port1 );
    udp2.send( message, ip, port2 );

      if( key == 'e' ){
  output1.flush();
  output1.close();
  output2.flush();
  output2.close();
  output3.flush();
  output3.close();
  delay(1000);
  exit();
  }

}


class graphMonitor_acc {
    String TITLE;
    int X_POSITION, Y_POSITION;
    int X_LENGTH, Y_LENGTH;
    float [] y1;
    float maxRange;
    graphMonitor_acc(String _TITLE, int _X_POSITION, int _Y_POSITION, int _X_LENGTH, int _Y_LENGTH) {
      TITLE = _TITLE;
      X_POSITION = _X_POSITION;
      Y_POSITION = _Y_POSITION;
      X_LENGTH   = _X_LENGTH;
      Y_LENGTH   = _Y_LENGTH;
      y1 = new float[X_LENGTH];
      for (int i = 0; i < X_LENGTH; i++) {
        y1[i] = 0;
      }
    }

    void graphDraw_acc(float _y1) {
      y1[X_LENGTH - 1] = _y1;
      for (int i = 0; i < X_LENGTH - 1; i++) {
        y1[i] = y1[i + 1];
      }
      maxRange = 1.5;
      for (int i = 0; i < X_LENGTH - 1; i++) {
        maxRange = (abs(y1[i]) > maxRange ? abs(y1[i]) : maxRange);
      }

      pushMatrix();

      translate(X_POSITION, Y_POSITION);
      fill(255);
      stroke(130);
      strokeWeight(1);
      rect(0, 0, X_LENGTH, Y_LENGTH);
      line(0, Y_LENGTH / 2, X_LENGTH, Y_LENGTH / 2);
      textSize(25);
      fill(51,51,204);
      textAlign(LEFT, BOTTOM);
      text(TITLE, 20, -5);
      textSize(22);
      textAlign(RIGHT);
//      text(0, -5, Y_LENGTH / 2 + 7);
      text(nf(maxRange, 0, 1), -5, 18);
      text(0, -5, Y_LENGTH);

      translate(0, Y_LENGTH / 2);
      scale(1, -1);
      strokeWeight(3);
      for (int i = 0; i < X_LENGTH - 1; i++) {
        stroke(0, 102, 204);
        line(i, (y1[i] * Y_LENGTH / maxRange) - (Y_LENGTH / 2), i + 1, (y1[i + 1] * Y_LENGTH / maxRange) - (Y_LENGTH / 2));
      }
      popMatrix();
    }
}  

class graphMonitor_ondo {
    String TITLE;
    int X_POSITION, Y_POSITION;
    int X_LENGTH, Y_LENGTH;
    float [] y1, y2;
    float maxRange;
    graphMonitor_ondo(String _TITLE, int _X_POSITION, int _Y_POSITION, int _X_LENGTH, int _Y_LENGTH) {
      TITLE = _TITLE;
      X_POSITION = _X_POSITION;
      Y_POSITION = _Y_POSITION;
      X_LENGTH   = _X_LENGTH;
      Y_LENGTH   = _Y_LENGTH;
      y1 = new float[X_LENGTH];
      y2 = new float[X_LENGTH];
      for (int i = 0; i < X_LENGTH; i++) {
        y1[i] = 0;
        y2[i] = 0;
      }
    }

    void graphDraw_ondo(float _y1) {
      y1[X_LENGTH - 1] = _y1;
      for (int i = 0; i < X_LENGTH - 1; i++) {
        y1[i] = y1[i + 1];
      }
      maxRange = 34;
      for (int i = 0; i < X_LENGTH - 1; i++) {
        maxRange = (abs(y1[i]) > maxRange ? abs(y1[i]) : maxRange);
      }

      pushMatrix();

      translate(X_POSITION, Y_POSITION);
      fill(255);
      stroke(130);
      strokeWeight(1);
      rect(0, 0, X_LENGTH, Y_LENGTH);
      line(0, Y_LENGTH / 2, X_LENGTH, Y_LENGTH / 2);

      textSize(25);
      fill(51,51,204);
      textAlign(LEFT, BOTTOM);
      text(TITLE, 20, -5);
      textSize(22);
      textAlign(RIGHT);
//      text(0, -5, Y_LENGTH / 2 + 7);
      text(nf(maxRange, 0, 1), -5, 18);
      text(0, -5, Y_LENGTH);
      translate(0, Y_LENGTH / 2);
      scale(1, -1);
      strokeWeight(3);
      for (int i = 0; i < X_LENGTH - 1; i++) {
        stroke(0, 102, 204);
        line(i, (y1[i] * Y_LENGTH / maxRange) - (Y_LENGTH / 2), i + 1, (y1[i + 1] * Y_LENGTH / maxRange) - (Y_LENGTH / 2));
      }
      popMatrix();
    }
}  

class graphMonitor_gsr {
    String TITLE;
    int X_POSITION, Y_POSITION;
    int X_LENGTH, Y_LENGTH;
    int [] y1;
    int maxRange;
    graphMonitor_gsr(String _TITLE, int _X_POSITION, int _Y_POSITION, int _X_LENGTH, int _Y_LENGTH) {
      TITLE = _TITLE;
      X_POSITION = _X_POSITION;
      Y_POSITION = _Y_POSITION;
      X_LENGTH   = _X_LENGTH;
      Y_LENGTH   = _Y_LENGTH;
      y1 = new int[X_LENGTH];
      for (int i = 0; i < X_LENGTH; i++) {
        y1[i] = 0;
      }
    }

    void graphDraw_gsr(int _y1) {
      y1[X_LENGTH - 1] = _y1;
      for (int i = 0; i < X_LENGTH - 1; i++) {
        y1[i] = y1[i + 1];
      }
      maxRange = 450;
      for (int i = 0; i < X_LENGTH - 1; i++) {
        maxRange = (abs(y1[i]) > maxRange ? abs(y1[i]) : maxRange);
      }

      pushMatrix();

      translate(X_POSITION, Y_POSITION);
      fill(255);
      stroke(130);
      strokeWeight(1);
      rect(0, 0, X_LENGTH, Y_LENGTH);
      line(0, Y_LENGTH / 2, X_LENGTH, Y_LENGTH / 2);

      textSize(25);
      fill(51,51,204);
      textAlign(LEFT, BOTTOM);
      text(TITLE, 20, -5);
      textSize(22);
      textAlign(RIGHT);
//      text(0, -5, Y_LENGTH / 2 + 7);
      text(nf(maxRange, 0, 0), -5, 18);
      text(0, -5, Y_LENGTH);

      translate(0, Y_LENGTH / 2);
      scale(1, -1);
      strokeWeight(3);
      for (int i = 0; i < X_LENGTH - 1; i++) {
        stroke(0, 102, 204);
        line(i, (y1[i] * Y_LENGTH / maxRange) - (Y_LENGTH / 2), i + 1, (y1[i + 1] * Y_LENGTH / maxRange) - (Y_LENGTH / 2));
      }
      popMatrix();
    }
}  






void receive( byte[] data, String ip, int port ) {  // <-- extended handler
  
  String message = new String( data );
  println( "receive: \""+message+"\" from "+ip+" on port "+port );
  
  // print the result
  String dmessage[] = message.split("!", 0);
  if( dmessage[0].length() == 3 ){
  output1.println(message);
  mesa = message;
  loga += 1;
  }else{
  output2.println(message);
  mesb = message;
  logb += 1;
}
  if(loga > 0 && logb > 0){
    output3.println(mesa + ", " + mesb);
    loga = 0;
    logb = 0;
    mesab = mesa + ", " + mesb;
    String dummys[] = mesab.split(",", 0);
    mil = float(dummys[2]);
    accX = float(dummys[3]);
    accY = float(dummys[4]);
    accZ = float(dummys[5]);
    accXYZ = sqrt(sq(accX)+sq(accY)+sq(accZ));
    gsr = int(float(dummys[9]));
    tp = float(dummys[10]);
   //println(mesab);
    g = 1; 

}  
}

Processingの出力例

出力例(CSVファイル)
出力例(グラフ)

完成品の写真

皮膚温センサを小さくしてみたもの
.
皮膚温センサ部分

成長の軌跡

2019年8月
.
2020年1月

残された課題

ご参考: 作業の様子

試作を行っていた会議室だけ明かりの点る霞ヶ関

以下はテンプレ

コード

Code
Hogehoge

写真

優秀な講師陣

. .
大内善広師(国語) 大内善広師(数学) 大内善広師(英語)

左寄せ 中央寄せ 右寄せ
曲がり くねり はしゃいだ道
青葉の森 駆け回る

引用

あれは三年前 止めるあなた駅に残し 動き始めた汽車に 一人飛び乗った ひなびた町の昼下がり

取り消し線

国立教育政策研究所は楽しいところだ