M5StickCを環境センサーにしてみた話
M5StickCとAmbientというサービスを使って
温度・湿度・土壌湿度をネットワーク上で監視するシステムを試しました。
Ambient は、アンビエントデーター株式会社が提供しているサービスとのことです
まず、Ambientのユーザー登録をして、Ambientのサイトのチュートリアルやサンプルコードを参考にすると比較的すぐ導入可能と思います。
8チャンネルまで無料です。
個人で使っている分には8チャンネルは超えないかもですね。
WiFi経由でセンサーデータを送ると、
センサーのデータをグラフ化できました。
今回使用したセンサー環境
・M5StickC
・温湿度センサーDHT11
・土壌湿度センサー
温度、湿度、体感温度(DHT11が温度・湿度から計算)、土壌湿度を取得。
ちなみに土壌湿度は土に挿していないため0Vを出力しています。
Ambient画面
サイトの管理画面で、送られてきたセンサーのグラフが見れます。
対時間軸のグラフやメータ、散布図などが作成できました。
Ambientのグラフの作成のし易さ、見易さは、無料で良いのだろうかというレベルで
使いやすいです。
とりあえずIoTを体感してみたいひとにおススメできるサービスです。
M5StickCを使用してみた話
発売されたのが何年か前なので、今更ですが初めて「M5stickC」を使ってみました。
本体カラーのオレンジ色が万人受けする感じで良いです。
スマート農業的なものにも興味があり、
とりあえず、家にあったBMP180と土壌湿度センサーを付けてみました。
機能
・温度測定
・気圧測定
・土壌湿度測定
ArduinoIDEでBMP085/BMP180両方に使えるライブラリ「Adafruit_BMP085.h」が
インストール出来るので、
比較的簡単に組むことが出来ました。
M5stickCの33ピンを土壌湿度センサーに使用し、
BMP180のSDAを0ピン、SCLを26ピンに使用しています。
ソース
#include <Adafruit_BMP085.h>
#include <M5StickC.h>
Adafruit_BMP085 bmp;
int AIN = 33;
int VREF = 3.3;
void setup() {
M5.begin();
M5.Axp.ScreenBreath(9);
M5.Lcd.setRotation(3);
M5.Lcd.fillScreen(BLACK);
Wire.begin(0, 26);
pinMode(AIN, ANALOG);
Serial.begin(9600);
if (!bmp.begin()) {
Serial.println("Could not find a valid BMP085 sensor, check wiring!");
while (1) {}
}
}
void loop() {
float temp = bmp.readTemperature();
float press = bmp.readPressure();
float alti = bmp.readAltitude();
float aread = analogRead(AIN);
float areadx = aread/4095*VREF;
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.printf("Temp: %2.2f C\n", temp);
M5.Lcd.setCursor(0, 20, 2);
M5.Lcd.printf("Press: %2.2f hPa\n", press / 100);
M5.Lcd.setCursor(0, 40, 2);
M5.Lcd.printf("Alti: %2.2f m\n", alti );
M5.Lcd.setCursor(0, 60, 2);
M5.Lcd.printf("Soil: %2.2f V\n", areadx);
delay(10000);
}
M5stickCは
・ディスプレイが内蔵
・マイク内蔵
・6軸IMUによる加速度、角速度センサー内蔵
・赤外線トランスミッター内蔵
・ホールセンサ内蔵
など、最初からセンサー機能がついているので
アイデア次第でいろいろ作れそうな気がしますね。
少しづつ試してみたいと思います。
ヘッドフォンアンプ製作(FET差動増幅)
作製したのは5年ほど前になりますが、ヘッドフォンアンプの紹介です。
以下の本に付いていた基板を使っています。
楽天ブックス: 理解しながら作るヘッドホン・アンプ - FET差動増幅回路採用で低ひずみ/低ノイズを実現し - 木村哲 - 9784789812504 : 本 (rakuten.co.jp)
部品は全ディスクリート、電源はトランスを使用。
回路のブロックは、
・初段はFET差動増幅回路
・定電流回路
・ダイヤモンド・バッファ
・負帰還回路
・プラス/マイナス電源回路
に分けられます。
部品は、秋月電子などでネット注文したかと思います。
このヘッドフォンアンプはアナログ入力なので、
USB-DACを使ってPCの音源を再生する使い方が一番多いです。
感想としては、音が良いのはもちろんのこと、
「今まで聞こえなかった音が聞こえる。」でした。
当時、ちゃんとしたヘッドフォンアンプを持っていなかったので
今まで聴いていた環境は良くなかったのだなと
思った記憶があります。
天気予報センサー 試作1号機
ラズパイZeroWHを用いた、気温・湿度・気圧・水滴検知センサーです。
機能
・センサーBME680により、気温、湿度、気圧を取得する。
取得値の3、6、9回の移動平均を同時に計算。
気温、湿度、気圧の変化をモニターして、天候の崩れを予知する。
・水滴検知センサーにより雨を検知して、
指定されたメールアドレスにGmailを送信する。
・概要
水滴検知センサーの出力がアナログなので、MCP3208(12bitADC)を使って
SPIにしてからラズパイZeroWHへ送っています。
ラズパイZeroWHには、ADC機能がありません。
センサーBME680が動かすのが自力では難しかったので
サンプルコードを探して動かしました。
いろいろ探して、動くものはC言語でした。
今回、書いたプログラムは載せませんが、BME680さえ動けば、、
個人でもこういうセンサが比較的簡単に作れる時代になっています。
・使用感
この天気予報センサーは、なかなか面白いのですが
ベランダなど外において、雨風にあたる環境に置くほどの耐久性がないので
使用途中でセンサーの値がおかしくなりました。
電源もUSBから取っているので、置き場所が限られるデメリットもあります。
ということで、まだまだ改良が必要ということで
「試作2号機」の製作をしようかという感じになっています。
Raspberry Pi Picoに無線機能を付けてみました
Raspberry Pi Picoと無線モジュールESP8266が載ったBOARD_ESP02D(4MB)_SIMPLE
を組み合わせて、無線によるデータの取得をしました。
Picoで実現させなくてもよい話ですが、
Picoに持っていない無線機能を追加するのも面白いかと思い、
試してみました。
機能
・Rasberry Pi PicoとESP8266をUARTで接続。
・ESP8266をアクセスポイントとして動かし、スマホとESP8266を無線で繋げて、
Rasberry Pi Picoで取得したデータをスマホに表示。
・今回使用したセンサーはポテンショメータ。
ポテンショメータは回転させた角度によって電圧が変わります。
・5秒おきに表示データを更新。
・乾電池2本で動作。
外観
接続図
必要な物
・Raspberry Pi Pico
・BOARD_ESP02D(4MB)_SIMPLE (スイッチサイエンスから購入)
※無線モジュールESP8266の動作に必要な抵抗(プルアップ/プルダウン)
やバイパスコンデンサが実装されています。
・BOARD_ESP02D(4MB)_SIMPLE にプログラムを書き込む環境
例えば、ArduinoIDEとシリアル通信基板。
ネットに先人の情報はあるが、慣れないと構築は結構めんどうか。
・ポテンショメータ (他のセンサーでもOK)
UART
・UARTが非同期のためなのか、たまにタイミングによって、
データの取得が不完全になるので、データに「;」を付けて2回取得しています。
「;」が来たら取得終了。
その後、必要な部分のみ抽出していますが、他に方法があるかと思うため
要勉強したい所です。
Raspberry Pi Picoのソースコード
from machine import UART, Pin
import time
PIN_ADC = 26
VREF = 3.3
adc = machine.ADC( PIN_ADC )
uart0 = UART(0, baudrate=115200, tx=Pin(12), rx=Pin(13))
while True:
value = adc.read_u16()
volt = (value /65535 * VREF)
voltx = "{0:.3f}".format(volt) + ";" #ケタ数を揃えて;を追加
time.sleep(1)
uart0.write(voltx)
BOARD_ESP02D(4MB)_SIMPLE (ESP8266)のソースコード
・ネットにある先人の情報を組み合わせていきました。
your-ssidとyour-passwordは、自由に決めて入力してください。
ssidは他人からも見える名前なので注意。
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define WIFI_SSID "your-ssid" //ネットワーク名。各自入力する
#define WIFI_PWD "your-password" //パスワード。各自入力する
ESP8266WebServer server( 80 );
IPAddress ip( 192, 168, 10, 1 );
IPAddress subnet( 255, 255, 255, 0 );
void setup() {
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(ip, ip, subnet);
WiFi.softAP(WIFI_SSID, WIFI_PWD);
Serial.begin(115200);
server.on("/", [](){
String str = "";
String msg = "";
int strlen = 0;
String str_send = "";
if ( Serial.available() ) {
{
str = Serial.readStringUntil(';'); //「;」を検出したら終了
str += Serial.readStringUntil(';'); //「;」を検出したら終了
strlen = str.length();
str_send = str.substring(str.length()-5,str.length()); //データ抽出
};
}
msg += "<!DOCTYPE html>";
msg += "<html><head>";
msg += "<meta http-equiv='refresh' content='5'>"; //5秒おきに更新
msg += "<title>Sensor</title><body>";
msg += "<font size='5'>" + str + "</font>";
msg += "<br>";
msg += "<font size='5'>" + str_send + "</font>";
msg += "<br>";
msg += "</body></html>";
server.send(200, "text/html", msg);
});
server.begin();
}
void loop() {
server.handleClient();
}
スマホでの表示
ソースコードを書き込むことが出来たら、スマホでWiFiをONにすると
WIFI_SSIDが見えるはずなので、パスワードを入れて接続します。
そして、スマホのブラウザにアドレス「192.168.10.1」を入れると、
データが表示されます。
※スマホのネットワーク設定で、「モバイルネットワーク」がONになっていると
一旦外部ネットワーク経由になるのか上手く接続できないかもしれません。
「モバイルネットワーク」をOFFするとインターネットに繋がらなくなるため、
OFFにしても支障がない「普段使っていないスマホ」で行うことを推奨します。
マイコンは本業ではないので、プログラム的に足りない物や逆に要らない物が
あるとは思いますが、こんな感じで出来ました。
Micro Pythonの書き方 (Time時間関数)
Rasberry Pico用にメモ。時間に関しての関数です。
import time
# 1秒間止める
time.sleep(1)
# 100ミリ秒間止める
time.sleep_ms(100)
#50マイクロ秒間 止める
time.sleep_us(50)
#startからの時間差を測定
start = time.ticks_ms()
delta = time.ticks_diff(time.ticks_ms(), start)
#100msec後の時間を計算。イベント/タスクのデッドラインを算出するのに便利
delta = time.ticks_add(time.ticks_ms(), 100)
Micro Python の書き方(ボタン割り込み)
Rasberry Pi Picoでの割り込み操作について記載しました。
IRQ(Interrupt Request)を用いて、ボタンを押したときに関数を呼ぶようにしています。
機能
ボタンを押したときだけLEDが光る。
接続
・PicoのGPIO21 --- LED(アノード)---LED(カソード)---680Ω---GND
・PicoのGPIO8 --- ボタン---GND
from machine import Pin
import time
# ピンの入出力設定
BUTTON_PIN = 8
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
LED_PIN = 21
led = Pin(LED_PIN, Pin.OUT)
# 関数定義
def callback(p):
led.value(1)
time.sleep(1)
def ledoff():
led.value(0)
time.sleep(1)
# IRQの設定
button.irq(trigger=Pin.IRQ_FALLING, handler=callback)
while True:
ledoff()
解説
ボタンを押した時のGPIO8の立下りをトリガーにしたいので、
GPIO8をプルアップして3.3Vに釣り上げて待機させます。
BUTTON_PIN = 8
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
トリガーに掛かった時にcallback関数を読むようにしています。
ちなみに、callbackという名前でなくても、ledonなど別名でも動きました。
callback()はピン情報を引数として必ず持つため、pという引数を渡しています。
triggerのタイプはいくつかあり
Pin.IRQ_FALLING
Pin.IRQ_RISING
Pin.IRQ_LOW_LEVEL
Pin.IRQ_HIGH_LEVEL
があるようです。
以下の公式ドキュメントも参考になると思います。
割り込みができれば、マイコンの操作の幅が広がりそうですね。
micropython-docs-ja.readthedocs.io