はじめに
卒論実験ⅠのBF装置の開発にソフトウェアの解説も取り入れるため、ChatGPTを用いてプログラムを解読中。といっても長野(2022)の測定器開発で半分書いてあるから、「FB有無の切り替え, 液晶ディスプレイ, 安静管理の自動化」を組み込めば終わり。Processingのプログラム解説もつけるべきか?
プログラム
#include <Adafruit_NeoPixel.h> //LEDのライブラリ
#include <ST7032_asukiaaa.h> //液晶ディスプレイのライブラリ
#define PIN 3 //LEDの制御ピン
#define NUMPIXELS 1 //LEDの数
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); //LEDのライブラリを使用
ST7032_asukiaaa lcd; //液晶ディスプレイのライブラリを使用
const int switchPin = 7; //FB有無の切り替えに用いるスイッチ
double mv, temp0, temp1, tempd; //温度データを格納する変数
double sum, average; //温度データの合計値と平均値を格納
long t, t0, cnt; //現在の時刻・温度データをサンプリングした時の時刻・温度データのサンプリング数
int Bpin = 2; //ブザーPIN2
const int HISTORY_SIZE = 180; // 履歴のサイズ
double history[HISTORY_SIZE]; // 測定値の履歴
int historyIndex = 0; // 履歴のインデックス
double minTemp = 0.0; // 最小温度
double maxTemp = 0.0; // 最大温度
bool readyFlg=false; //安静準備フラグ
void setup() {
pinMode(switchPin, INPUT_PULLUP); // 内部プルアップ抵抗を有効にする
pinMode(Bpin, OUTPUT);
pinMode(13, OUTPUT);
Serial.begin(115200); //シリアル通信115200
analogReference(INTERNAL); //参照電圧を1.1Vに設定
cnt = sum = 0;
pixels.begin(); //LEDを初期化
lcd.begin(8, 2); //液晶ディスプレイで8列2行で指定表示
lcd.setContrast(5); //液晶ディスプレイのコントラスト
}
void loop() {
t0 = t;
t = millis(); //現在時刻をms単位で取得
mv = (double)1100 / (double)1024 * analogRead(0); //デジタル値を電圧に変換
sum = sum + mv;
cnt++; //サンプリング数のカウント
if (t0 / 1000 != t / 1000) { //1秒(100ms)毎に平均算出
average = sum / (double)cnt; //平均を計算
temp0 = temp1; //前回の温度を保存
temp1 = average * 0.1; //電圧を温度に変換
tempd = temp1 - temp0; //温度変化量を算出
int mag, dir; //変化の程度(mag)と方向(dir)
if (tempd > 0) {
mag = abs(tempd * 100);
dir = 1; //温度上昇時
} else if (tempd <= 0) {
mag = abs(tempd * 100);
dir = -1; //温度下降時
}
int switchState = digitalRead(switchPin);
if (switchState == LOW) { //FBスイッチがオフの時に
pixels.clear();
if (dir == 1) {
pixels.setPixelColor(0, pixels.Color(mag, 0, 0)); //温度上昇を赤で表示
if (mag > 0) {
tone(Bpin, 500, 10); //温度上昇時は500Hz
}
}
if (dir == -1) {
pixels.setPixelColor(0, pixels.Color(0, 0, mag)); //温度下降を青で表示
if (mag > 0) {
tone(Bpin, 1000, 10); //温度下降時は1000Hz
}
}
} else if (switchState == HIGH) { //左下のスイッチを入れるとFBなし
pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //LEDを消す
noTone(Bpin); //ブザー音を消す
}
pixels.show();
Serial.print(temp1); //現在温度
Serial.print(","); //カンマ区切り
Serial.print(tempd); //温度変化量
Serial.print(",");
Serial.print(mag); //変化の強さ
Serial.print(",");
Serial.print(cnt); //サンプリング数
if(readyFlg==true){
Serial.print(",***"); //安静期間終了時に「***」表示
}
else{
Serial.print(",---"); //安静期間が終了していない場合「---」表示
}
Serial.println(); //シリアルモニタに「***/---」を表示するための空行
sum = 0; //合計値の初期化
cnt = 0;
delay(10); //10ms単おきに行う
history[historyIndex] = temp1; //温度データを記録するための配列
historyIndex = (historyIndex + 1) % HISTORY_SIZE; //新しい温度データを保存
minTemp = history[0]; //最小温度をデータの最初の要素で初期化
maxTemp = history[0]; //最大温度をデータの最初の要素で初期化
for (int i = 1; i < HISTORY_SIZE; i++) { //温度データから最小・最大温度を算出
if (history[i] < minTemp) { //データ内で最小温度より低い場合
minTemp = history[i]; //最小温度を更新
}
if (history[i] > maxTemp) { //データ内で最大温度より低い場合
maxTemp = history[i]; //最大温度を更新
}
}
//3分間の皮膚温の変動が0.4℃以内の時にアスタリスク表示
if (maxTemp - minTemp <= 0.4) { //最大・最小温度の差が0.4℃以内の場合
lcd.setCursor(7, 0); //液晶ディスプレイの右上に
lcd.print("*"); //「*」表示
//Serial.println("***");
readyFlg=true;
} else { //条件を満たさなかった場合
lcd.setCursor(7, 0); //液晶ディスプレイの右上に
lcd.print(" "); //何も表示しない
}
String buf1, buf2;
buf1 += temp1; //buf1は現在温度
buf2 += tempd; //buf2は温度変化量
lcd.setCursor(0, 0); //液晶ディスプレイの1行目にカーソルを移動
lcd.print(buf1.c_str()); //1行目に現在温度を表示
lcd.setCursor(0, 1); //液晶ディスプレイの2行目にカーソルを移動
lcd.print(buf2.c_str()); //2行目に温度変化量を表示
}
}
【液晶ディスプレイ】
#include <ST7032_asukiaaa.h> //液晶ディスプレイのライブラリ
ST7032_asukiaaa lcd; //液晶ディスプレイのライブラリを使用
double temp1, tempd; //温度データを格納する変数
double minTemp = 0.0; // 最小温度
double maxTemp = 0.0; // 最大温度
void setup() {
lcd.begin(8, 2); //液晶ディスプレイで8列2行で指定表示
lcd.setContrast(5); //液晶ディスプレイのコントラスト
}
void loop() {
//3分間の皮膚温の変動が0.4℃以内の時にアスタリスク表示
if (maxTemp - minTemp <= 0.4) { //最大・最小温度の差が0.4℃以内の場合
lcd.setCursor(7, 0); //液晶ディスプレイの右上に
lcd.print("*"); //「*」表示
readyFlg=true;
} else { //条件を満たさなかった場合
lcd.setCursor(7, 0); //液晶ディスプレイの右上に
lcd.print(" "); //何も表示しない
}
String buf1, buf2;
buf1 += temp1; //buf1は現在温度
buf2 += tempd; //buf2は温度変化量
lcd.setCursor(0, 0); //液晶ディスプレイの1行目にカーソルを移動
lcd.print(buf1.c_str()); //1行目に現在温度を表示
lcd.setCursor(0, 1); //液晶ディスプレイの2行目にカーソルを移動
lcd.print(buf2.c_str()); //2行目に温度変化量を表示
}
【安静期間の自動管理化】
double temp1; //現在温度のデータを格納する変数
double sum, average; //温度データの合計値と平均値を格納
long cnt; //温度データのサンプリング数
const int HISTORY_SIZE = 180; // 履歴のサイズ
double history[HISTORY_SIZE]; // 測定値の履歴
int historyIndex = 0; // 履歴のインデックス
double minTemp = 0.0; // 最小温度
double maxTemp = 0.0; // 最大温度
bool readyFlg=false; //安静期間のフラグ
void loop() {
if(readyFlg==true){
Serial.print(",***"); //安静期間終了時に「***」表示
}
else{
Serial.print(",---"); //安静期間が終了していない場合「---」表示
}
Serial.println(); //シリアルモニタに「***/---」を表示するための空行
sum = 0; //合計値の初期化
cnt = 0;
delay(10); //10ms単おきに行う
history[historyIndex] = temp1; //温度データを記録するための配列
historyIndex = (historyIndex + 1) % HISTORY_SIZE; //新しい温度データを保存
minTemp = history[0]; //最小温度をデータの最初の要素で初期化
maxTemp = history[0]; //最大温度をデータの最初の要素で初期化
for (int i = 1; i < HISTORY_SIZE; i++) { //温度データから最小・最大温度を算出
if (history[i] < minTemp) { //データ内で最小温度より低い場合
minTemp = history[i]; //最小温度を更新
}
if (history[i] > maxTemp) { //データ内で最大温度より低い場合
maxTemp = history[i]; //最大温度を更新
}
}
//3分間の皮膚温の変動が0.4℃以内の時にアスタリスク表示
if (maxTemp - minTemp <= 0.4) { //最大・最小温度の差が0.4℃以内の場合
lcd.setCursor(7, 0); //液晶ディスプレイの右上に
lcd.print("*"); //「*」表示
//Serial.println("***");
readyFlg=true;
} else { //条件を満たさなかった場合
lcd.setCursor(7, 0); //液晶ディスプレイの右上に
lcd.print(" "); //何も表示しない
}
①測定している値を60回分覚えるプログラム
const int HISTORY_SIZE = 60; // 履歴のサイズを60に変更
double history[HISTORY_SIZE]; // 測定値の履歴
int historyIndex = 0; // 履歴のインデックス
// 履歴に温度データを追加する部分
history[historyIndex] = temp1; //温度データを記録するための配列
historyIndex = (historyIndex + 1) % HISTORY_SIZE; //新しい温度データを保存
②180個覚えた履歴の中から最大値と最小値を求めて, その差を算出するプログラム
const int HISTORY_SIZE = 180; // 履歴のサイズ
double history[HISTORY_SIZE]; // 測定値の履歴
int historyIndex = 0; // 履歴のインデックス
double minTemp = 0.0; // 最小温度
double maxTemp = 0.0; // 最大温温度
void loop() {
history[historyIndex] = temp1; // 温度データを記録するための配列に保存
historyIndex = (historyIndex + 1) % HISTORY_SIZE; // 新しい温度データを保存するインデックスを更新
minTemp = history[0]; // 最小温度をデータの最初の要素で初期化
maxTemp = history[0]; // 最大温度をデータの最初の要素で初期化
// 温度データから最小・最大温度を算出
for (int i = 1; i < HISTORY_SIZE; i++) {
if (history[i] < minTemp) {
minTemp = history[i]; // 最小温度を更新
}
if (history[i] > maxTemp) {
maxTemp = history[i]; // 最大温度を更新
}
}
}
③最大値と最小値の差が0.4℃以内であった場合は, 液晶ディスプレイにアスタリスクを表示するプログラム
const int HISTORY_SIZE = 180; // 履歴のサイズ
double history[HISTORY_SIZE]; // 測定値の履歴
int historyIndex = 0; // 履歴のインデックス
double minTemp = 0.0; // 最小温度
double maxTemp = 0.0; // 最大温度
void loop() {
history[historyIndex] = temp1; // 温度データを記録するための配列に保存
historyIndex = (historyIndex + 1) % HISTORY_SIZE; // 新しい温度データを保存するインデックスを更新
minTemp = history[0]; // 最小温度をデータの最初の要素で初期化
maxTemp = history[0]; // 最大温度をデータの最初の要素で初期化
// 温度データから最小・最大温度を算出
for (int i = 1; i < HISTORY_SIZE; i++) {
if (history[i] < minTemp) {
minTemp = history[i]; // 最小温度を更新
}
if (history[i] > maxTemp) {
maxTemp = history[i]; // 最大温度を更新
}
}
// 最大・最小温度の差が0.4℃以内の場合、アスタリスク表示
if (maxTemp - minTemp <= 0.4) {
lcd.setCursor(7, 0); // 液晶ディスプレイの右上に
lcd.print("*"); // 「*」表示
} else {
lcd.setCursor(7, 0); // 液晶ディスプレイの右上に
lcd.print(" "); // 何も表示しない
}
}
【FB有無の切り替え】
#include <Adafruit_NeoPixel.h> //LEDのライブラリ
#include <ST7032_asukiaaa.h> //液晶ディスプレイのライブラリ
#define PIN 3 //LEDの制御ピン
#define NUMPIXELS 1 //LEDの数
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); //LEDのライブラリを使用
const int switchPin = 7; //FB有無の切り替えに用いるスイッチ
int Bpin = 2; //ブザーPIN2
void setup() {
pinMode(switchPin, INPUT_PULLUP); // 内部プルアップ抵抗を有効にする
pinMode(Bpin, OUTPUT);
void loop() {
int switchState = digitalRead(switchPin);
if (switchState == LOW) { //FBスイッチがオフの時に
pixels.clear();
if (dir == 1) {
pixels.setPixelColor(0, pixels.Color(mag, 0, 0)); //温度上昇を赤で表示
if (mag > 0) {
tone(Bpin, 500, 10); //温度上昇時は500Hz
}
}
if (dir == -1) {
pixels.setPixelColor(0, pixels.Color(0, 0, mag)); //温度下降を青で表示
if (mag > 0) {
tone(Bpin, 1000, 10); //温度下降時は1000Hz
}
}
} else if (switchState == HIGH) { //左下のスイッチを入れるとFBなし
pixels.setPixelColor(0, pixels.Color(0, 0, 0)); //LEDを消す
noTone(Bpin); //ブザー音を消す
}