2020年5月 1日 (金)

Arduinoで作ろう(51) パルスオキシメータ

Esp32max30102_

 新型コロナウイルスに感染した「軽症者」が,自宅療養中に急速に肺炎が悪化し手遅れになるケースがあるようです。
これを防ぐために,パルスオキシメータでときどき血中酸素飽和度SpO2を測定することをお勧めします。SpO2が96~99%なら大丈夫ですが,90%を下回ったら早急に医師に連絡すべきです。僕は2月にちゃんとした製品を買ってときどき測定していますが,今回はマイコンで自作してみましょう。

 MAX30102というパルスオキシメータ用のセンサを手に入れたので,ESP32につないでみました。
20200501-184622

 ライブラリはコレで,スケッチ例「Example8_SPO2」を少し書き換えて,OLEDディスプレイSSD1306に心拍数とSpO2を表示させてみました。
スケッチはこれです→ 20200501example8_spo2.ino

20200501-184503

| | コメント (0)

2020年4月27日 (月)

Arduinoで作ろう(50) 温度・湿度・気圧データをBlynkで見てみる

Blynk_bme280_

 ESP32に温度・湿度・気圧センサBME280をつないで,データをBLEでスマホへ送り,Blynkで見てみました。
Blynkの画面は,なかなかカッコ良くて「ナウなヤングにバカウケ」ですなあ。
設定はこんな感じ ↓
Blynk_20200427_20200427100001

//ESP32 + BME280 -> Blynk 

#define BLYNK_PRINT Serial
#define BLYNK_USE_DIRECT_CONNECT
#include <BlynkSimpleEsp32_BLE.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <Wire.h>
#include "SparkFunBME280.h"
char auth[] = " あなたのAuth Token ";
BME280 sensor;
float temp,humidity,pressure;
char buff[50];

void setup(){
  Wire.begin();
  sensor.beginI2C();
  Serial.begin(9600);
  Serial.println("Waiting for connections...");
  Blynk.setDeviceName("BME280");
  Blynk.begin(auth);
}

void loop(){
  getdata();
  Blynk.run();
}

void getdata() {
  temp = sensor.readTempC() ;
  humidity = sensor.readFloatHumidity() ;
  pressure = sensor.readFloatPressure()/100 ;
}

BLYNK_READ(V0) {
  formattedFloat(temp, 1, buff);
  Blynk.virtualWrite(V0, buff);
}
BLYNK_READ(V1) {
  formattedFloat(humidity, 1, buff);
  Blynk.virtualWrite(V1, buff);
}
BLYNK_READ(V2) {
  formattedFloat(pressure, 0, buff);
  Blynk.virtualWrite(V2, buff);
}

void formattedFloat(float x, uint8_t precision, char *buff) {
  dtostrf(x, 7, precision, buff);
}

でも,ちょっと問題があって,「SuperChart」が「Live」のグラフは描いてくれるんだけど,「1h」(1時間のグラフ)を描いてくれないんですよね。いつまでたっても「No data yet」って表示されてるんですよ。アプリの不具合だと思うんだけどなあ?
20200427

| | コメント (0)

2020年4月25日 (土)

Arduinoで作ろう(49) BLEでリモートLチカ

Blynk_lchika_

 ESP32の BLE (Bluetooth Low Energy) を使ってLチカをやってみました。
Blynkというスマホアプリを使ってESP32とスマホをBluetoothで接続し,3つのLEDをリモートから点けたり消したりします。
「それで?」というハナシですが,とりあえずBlynkを使う練習ですね。

 App StoreやGoogle PlayでBlynkをスマホにインストールしてユーザ登録したら,さっそくプロジェクトを作ります。
プロジェクト名は「L-chika」としておきましょうかね。

Blynk1

 「AUTH TOKEN」は,ESP32のスケッチに書き込みますからE-Mailボタンをタップして自分に送っておきましょう。
続けてウィジェットからボタン等の必要なパーツを選んで操作画面に並べていきます。
Blynk2

 雑な説明ですが(^^;), 触ってれば直観的に何をすればいいのか分かりますから大丈夫。

 次にESP32のスケッチを書きます。
Blynkのライブラリが必要ですから,Arduino IDEで スケッチ>ライブラリをインクルード>ライブラリを管理 と進んでライブラリマネージャでBlynkを検索すればすぐ見つかります。

//Blynk で リモートLチカ

#define BLYNK_PRINT Serial
#define BLYNK_USE_DIRECT_CONNECT
#include <BlynkSimpleEsp32_BLE.h>
#include <BLEDevice.h>
#include <BLEServer.h>
char auth[] = "あなたのAuth Token";

void setup(){
  pinMode(21, OUTPUT);
  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);
  Serial.begin(9600);
  Serial.println("Waiting for connections...");
  Blynk.setDeviceName("L-chika");
  Blynk.begin(auth);
}

void loop(){
  Blynk.run();
}


| | コメント (0)

2020年4月22日 (水)

Arduinoで作ろう(48) GPSのデータをAmbientに投げる

20200422

 前回の装置をテザリングでスマホにつないで,GPSモジュールで得られた緯度・経度のデータを1分おきにAmbientに投げてみました。
上のがクルマに積んで近所を一周してできた地図。Ambientはこんなこともできるんですね。おもしろいなあ。

//ESP32 + GPSモジュール NEO-6M → Ambient

#include <WiFi.h>
#include "Ambient.h"
#include "TinyGPS++.h" 
#include "HardwareSerial.h"
#include "Wire.h"
#include "SSD1306.h"
const char* ssid = "無線LANのSSID";
const char* password = "パスワード";
WiFiClient client;
unsigned int channelId = 20050; // あなたのチャネルID
const char* writeKey = "123456789abcde";//あなたのライトキー
Ambient ambient;
SSD1306 display(0x3c, 21, 22); //I2Cアドレス0x3c,SDA->GPIO21,SCL->GPIO22
TinyGPSPlus gps;
HardwareSerial serial2(2); //ESP32_GPIO16->GPS_TX , ESP32_GPIO17->GPS_RX

void setup() {
  display.init();
  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
  Serial.begin(9600);
  Serial.println("Start GPS... ");
  display.clear();
  display.drawString(0,0,"Start GPS... ");
  display.display();
  serial2.begin(9600);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  ambient.begin(channelId, writeKey, &client);
}

void loop() {
  if (serial2.available()){
  char c = serial2.read();
  gps.encode(c);
    if (gps.location.isUpdated()) {
     digitalWrite(2, HIGH);
     Serial.print("LAT: "); Serial.println(gps.location.lat(), 9);
     Serial.print("LONG: "); Serial.println(gps.location.lng(), 9);
     display.clear();
     display.drawString(0,0,String(gps.time.hour()+9)+":"+String(gps.time.minute())+":"+String(gps.time.second())+" JST");
     display.drawString(0,20,"LAT : "+String(gps.location.lat(),9));
     display.drawString(0,35,"LNG : "+String(gps.location.lng(),9));
     display.drawString(0,50,"ALT : "+String(gps.altitude.meters())+"m");
     display.display();
    } else{
      digitalWrite(2, LOW);
   }
 }
 if (int(millis()/1000%60) == 0){    //1分ごとに
  char buf[16];
  ambient.set(1, gps.altitude.meters());  // 標高をデータ1に
  dtostrf(gps.location.lat(), 12, 8, buf);
  ambient.set(9, buf);  // 緯度をデータ9に
  dtostrf(gps.location.lng(), 12, 8, buf);
  ambient.set(10, buf);  //経度をデータ10に
  ambient.send(); 
  }
}

| | コメント (0)

2020年4月18日 (土)

Arduinoで作ろう(47) GPSモジュールで現在地の緯度・経度を取得

Esp32gps_

 aitendoで買ったGPSモジュールNEO-6MをESP32につないで。現在地を取得してみました。
TinyGPS++というライブラリを使うと,GPSモジュールから簡単に時刻,緯度(LAT),経度(LNG),標高(ALT)などを取り出すことができます。

20200418

 よく行くパソコンショップの駐車場にクルマを止めて,この装置で現在地を取得し,GoogleMapに緯度・経度を入力してみると正確に測位できていることが確認できました。これは普通にすごいな。

Gps_map

//ESP32 + GPSモジュール NEO-6M 

#include "TinyGPS++.h" //http://arduiniana.org/libraries/tinygpsplus/
#include "HardwareSerial.h"
#include "Wire.h"
#include "SSD1306.h"
SSD1306 display(0x3c, 21, 22); //I2Cアドレス0x3c,SDA->GPIO21,SCL->GPIO22
TinyGPSPlus gps;
HardwareSerial serial2(2); //ESP32_GPIO16->GPS_TX , ESP32_GPIO17->GPS_RX

void setup() {
  display.init();
  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
  Serial.begin(9600);
  Serial.println("Start GPS... ");
  display.clear();
  display.drawString(0,0,"Start GPS... ");
  display.display();
  serial2.begin(9600);
}

void loop() {
  if (serial2.available()){
   char c = serial2.read();
   gps.encode(c);
   if (gps.location.isUpdated()) {
    digitalWrite(2, HIGH);
    Serial.print("LAT: "); Serial.println(gps.location.lat(), 9);
    Serial.print("LONG: "); Serial.println(gps.location.lng(), 9);
    display.clear();
    display.drawString(0,0,String(gps.time.hour()+9)+":"+String(gps.time.minute())+":"+String(gps.time.second())+" JST");
    display.drawString(0,20,"LAT : "+String(gps.location.lat(),9));
    display.drawString(0,35,"LNG : "+String(gps.location.lng(),9));
    display.drawString(0,50,"ALT : "+String(gps.altitude.meters())+"m");
    display.display();
  } else{
    digitalWrite(2, LOW);
  }
 }
}

| | コメント (0)

2020年4月14日 (火)

Arduinoで作ろう(46) APIを叩いて現在の為替レートを取得する

20200414_esp32_oled_20200414120901

 ESP8266は日本の技適を通ってないので,厳密なことを言うと国内でこれを使う(電波を出す)ことは違法です。僕みたいなアマチュアはそんなこと気にしなくてもいいと思いますが,そろそろ「技適厨」が沸いてきそうな気がするので,今日からESP32に切り替えることにします。
 ところで,「技適厨」ってのは「ネトウヨ」と心性が似てる気がしますね。なんだか承認欲求をこじらせてる感じ(笑)。「技適厨」のネトウヨ率を調べてみたら面白いんじゃないかなー。

 話がそれましたが,AmazonでESP32の開発ボード(990円)を買いました。Wi-FiのほかにBluetoothも使えるんですね。またしばらく遊べそうです。
 ESP32をArduino IDEで使えるようにする手順は例によって省略。僕はこのあたりを参考にしました。ツール>ボードは ESP32 Dev Moduleを選択します。

 とりあえずスケッチ例のBlinkを書き込んでみようとしたら,書き込み中にTimeOutしてしまいます。どうやら書き込むときにはタクトスイッチの複雑な操作が必要みたい。でも,ENとGNDの間に0.1μFくらいのコンデンサを入れてやればめんどうな操作なしで自動書込できるようになるらしいです。(僕が買った開発ボードは0.1μFではダメで,0.22μF(224)にしてやったらうまく書き込めるようになりました)

20200414_20200414120401

 前回,天気予報APIを叩いてみましたが,今回は openexchangerates.org のAPIを叩いて為替レート(USD/JPY)を取得してみました。ここも無料アカウントを作ってIDをもらっておく必要があります。

//ESP32でhttps://openexchangerates.org/から USD/JPY の為替レート情報を取得する
//I2C OLED SSD1306

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "Wire.h"  
#include "SSD1306.h"
#define SDA 21 //SDA-GPIO21
#define SCL 22 //SCL-GPIO22
SSD1306 display(0x3c, SDA, SCL); //I2Cアドレス 0x3c
const char* ssid = "あなたの無線LANのSSID";
const char* password = "あなたのパスワード";
const String endpoint = "http://openexchangerates.org/api/latest.json?app_id=あなたのID";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  display.init();
}

void loop() {
  if ((WiFi.status() == WL_CONNECTED)) {
  HTTPClient http; http.begin(endpoint); 
  int httpCode = http.GET(); 
  if (httpCode > 0) { 
  String payload = http.getString(); 
  Serial.println(httpCode);
  Serial.println(payload);

  DynamicJsonBuffer jsonBuffer;
  String json = payload;
  JsonObject& ratedata = jsonBuffer.parseObject(json);
  if(!ratedata.success()){
  Serial.println("parseObject() failed");
  }

  const double JPY = ratedata["rates"]["JPY"].as<double>();
  const int timestamp = ratedata["timestamp"].as<int>();
  static const char *wd[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  time_t t = timestamp;
  struct tm *tm = localtime(&t);
  char buff[12];
  sprintf( buff, "%04d/%02d/%02d(%s)",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,wd[tm->tm_wday] );
  display.clear(); 
  display.setFont(ArialMT_Plain_16); 
  display.drawString(0,0,buff);
  display.display(); 
  display.drawString(0,30,"USD/JPY " + String(JPY));
  display.display(); 
  }
  http.end(); 
  delay(60*60*1000); //60分おきに更新
 }
}

| | コメント (0)

2020年4月12日 (日)

Arduinoで作ろう(45) OpenWeatherMapの天気情報を取得してみる

Wemos_d1_ntp_tokei__20200412094701

 WeMos D1 (ESP8266)をネットにつないで OpenWeatherMapの無料天気情報をAPIで取得し,現在の岐阜市の天気をLCDに表示してみました。「外出自粛中」でも,外の天気がよく分かって便利(?)
参考にしたのはこちらのサイト。とても丁寧な説明で勉強になりましたm(__)m

 APIを使うためには,API Keyが必要になりますから,Sign Upページで無料アカウントを作ってキーを取得します。
あと,APIを叩いて得られるJSON形式の天気情報を成型するためのライブラリArduinoJson.h (バージョンは5.13.4がいいみたい)をインストールしておきましょう。

↓ とりあえず岐阜市の「現在の天気」,「気温」,「湿度」,「気圧」を表示させてみました。

20200412

//OpenWeatherMapから天気情報を取得する

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <ST7032.h>
const char* ssid = "あなたの無線LANのSSID";
const char* password = "あなたのパスワード";
const String endpoint = "http://api.openweathermap.org/data/2.5/weather?q=gifu,jp&units=metric&APPID=";
const String key = "あなたのAPIキー";
ST7032 lcd ;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  lcd.begin(16, 2) ;
  lcd.setContrast(30);
}

void loop() {
  if ((WiFi.status() == WL_CONNECTED)) {
   HTTPClient http;
   http.begin(endpoint + key); 
   int httpCode = http.GET();
   if (httpCode > 0) {
     String payload = http.getString();
     Serial.println(payload);
     DynamicJsonBuffer jsonBuffer;
     String json = payload;
     JsonObject& weatherdata = jsonBuffer.parseObject(json);
     const char* weather = weatherdata["weather"][0]["main"].as<char*>();
     const char* description = weatherdata["weather"][0]["description"].as<char*>();
     const double temp = weatherdata["main"]["temp"].as<double>();
     const double pressure = weatherdata["main"]["pressure"].as<double>();
     const double humidity = weatherdata["main"]["humidity"].as<double>();
     lcd.setCursor(0, 0);
     lcd.print(description);lcd.print("");
     lcd.setCursor(0, 1);
     lcd.print((int)temp); lcd.write(0b11011111); lcd.print("C");lcd.print(" ");
     lcd.print((int)humidity);lcd.print("%");lcd.print(" ");
     lcd.print((int)pressure);lcd.print("hPa");
    }
    http.end(); 
   }
 delay(10*60*1000); //10分おきに更新
}

 

|

2020年4月10日 (金)

Arduinoで作ろう(44)  WeMos D1でNTP時計

Wemos_d1_ntp_tokei

 新型コロナウイルスの感染拡大に伴って,外出を自粛中です。
やることがないから,毎日「自宅警備」に専念しつつマイコンで遊んでます。
WeMos D1(ESP8266)はすでにArduinoでもなんでもないんだけど,開発環境としてArduino IDEを使ってるから引き続き「Arduinoで作ろう」の表題で続けます。
 今日は,WeMos D1をWi-FiでインターネットにつないでNTP (Network Time Protocol)を使った時計を作ってみました。LCDは秋月電子通商のコレを使っています。

20200410

//WeMos_D1 (ESP8266)  NTPデジタル時計

#include <ESP8266WiFi.h>
#include <time.h>
#include <ST7032.h> //https://ore-kb.net/archives/195
#define JST 3600 * 9
const char* ssid = "あなたの無線LANのSSID";
const char* password = "あなたのパスワード";
ST7032 lcd ;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  lcd.begin(16, 2) ;
  lcd.setContrast(30);
  configTime(JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
}

void loop() {
  static const char *wd[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  time_t t = time(NULL);
  struct tm *tm = localtime(&t);
  char buff[12];
  sprintf( buff, "%04d/%02d/%02d(%s)",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,wd[tm->tm_wday] );
  lcd.setCursor(0, 0) ;
  lcd.print(buff) ;
  sprintf( buff, "%02d:%02d:%02d",tm->tm_hour,tm->tm_min,tm->tm_sec );
  lcd.setCursor(0, 1) ;
  lcd.print(buff) ;
  delay(1000);
}

|

2020年4月 7日 (火)

ガイガーカウンタ GC10(6)空間放射線量データをAmbientへ送信する

Wemos_gc10_ambient_

Gc10_wemos_d1

 WeMos D1(ESP8266)につないだガイガーカウンタGC10で測定した空間放射線量データをAmbientに送信してグラフを作ってみました。

// WeMos D1(ESP8266) + GC10 による空間放射線量測定 → Ambientに送信

#include <ESP8266WiFi.h>
#include "Ambient.h"
const char* ssid = "あなたの無線LANのSSID";
const char* password = "あなたのパスワード";
WiFiClient client;
unsigned int channelId = 12345; // あなたのチャネルID
const char* writeKey = "123456789abcde";//あなたのライトキー
Ambient ambient;

void setup(void){
  Serial.begin(9600);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  ambient.begin(channelId, writeKey, &client);
}

void loop(void){
  String cpm="";
  if (Serial.available()) {
    cpm="";
    cpm = Serial.readStringUntil('\r');
    Serial.flush();
    cpm.trim();
    delay(1000);
  }
  if (int(millis()/1000%600) == 0){ //10分ごとに
    ambient.set(1, cpm.toFloat()); // CPMをデータ1に
    ambient.set(2, cpm.toFloat()/165); // μSv/hをデータ2に
    ambient.send(); // Ambientに送信
  }
}

Ambientに作ってもらったグラフがこれです ↓

20200406

 現在1分間隔で測定中です。
この公開チャネルをご覧ください→ https://ambidata.io/ch/channel.html?id=20119

|

2020年4月 6日 (月)

Arduinoで作ろう(43) WeMos D1とAmbientの連携

 WeMos D1(ESP8266)につないだ気温・湿度・気圧センサBME280で取得したデータをAmbientに送信して,グラフを作ってみました。
Ambientというのは,『マイコンなどから送られるセンサデータを受信し,蓄積し,可視化(グラフ化)』してくれる無料サービスです。
Structure3

 チュートリアルも親切に書かれてるので,とってもカンタンでした。こんなすごいサービスが無料だなんて信じられん。
ユーザ登録して「チャネルID」と「ライトキー」を取得し,スケッチに書き込めばOK。ライブラリはココでダウンロードします。

// WeMos D1(ESP8266) + BME280 で気温・湿度・気圧測定 → Ambientに送信

#include <ESP8266WiFi.h>
#include "SparkFunBME280.h"
#include "Ambient.h"
const char* ssid = "あなたの無線LANのSSID";
const char* password = "あなたのパスワード";
WiFiClient client;
unsigned int channelId = 12345; //あなたのチャネルID
const char* writeKey = "123456789abcde";//あなたのライトキー
Ambient ambient;
float temp,humidity,pressure;
String webString="";
BME280 sensor;

void setup(void){
  Serial.begin(9600);
  Wire.begin();
  sensor.beginI2C();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  ambient.begin(channelId, writeKey, &client); 
}

void loop(void){
  getdata();
  ambient.set(1, temp); 
  ambient.set(2, humidity);
  ambient.set(3, pressure);
  ambient.send();
  delay(300000); //5分待つ
}

void getdata() {
  temp = sensor.readTempC() ;
  humidity = sensor.readFloatHumidity() ;
  pressure = sensor.readFloatPressure()/100 ;
}

 データを5分間隔で24時間送信して,できたグラフがこれ↓ です。
ってか,Webブラウザで「Myチャネル」のページを開いてると,リアルタイムでどんどんグラフが作られていくのです。これは面白い。

Ambient

|