動機
天気をあれこれする子たちいわく、ただの空模様に心を動かされてしまうらしい。晴れると気持ちが良くなるよね。ならばそれをいつでもできるようになれば、どこでも気分を盛り上げることが…。なんてことはなく、愛と、天気を変える瞬間を体験したい思いだけで、僕にできることをやった結果。
再現方法の選定
雨音の再現
ビーズを紐に結んだりなど色々試してみた結果、針金が直接傘を叩く音が一番近いという結論に。
材料
- 針金
- プラバン
- 結束バンド
- ソレノイド
- サーボモータの丸型ホーン
- ガムテープ
- プラバンを円形に切り、適当な長さの針金を括り付けていく(向きを整えるガイドとして結束バンドで固定)
- サーボモータの丸型ホーンを繋ぎとして、針金を取り付けた円盤をソレノイドに固定する
- ソレノイドと傘は、ガムテープで固定
- ソレノイドを上下運動させると、針金が揺れて傘を叩く
祈りの再現
手を組んで、一定時間祈ることを再現したいため、湿度センサーを選択。
手でくるむと、じわじわと湿度が上がっていくので、適当に決めたしきい値を超えるとソレノイドを止める=晴れにすることにする。
回路部仕組み
材料
- M5GO[M5GO IoTスターターキット]
- 温湿度センサー[M5Go IoTスターターキット内のENVセンサー]
- モータードライバ[PU-2709]
- ソレノイド[CBS07300140]
- モバイルバッテリー(PD対応)
- Type-C USBテスター[TC66C] (モバイルバッテリーから指定電圧を出力させるために使用)
- micro SDカード
構成
- ソレノイドの電源をモバイルバッテリーから9Vとる
- GNDは 共通化する
プログラム
- hum_thresholdが湿度のしきい値
- 演出として、SDカードに保存したイラストを画面に表示することで、現在の状態を示す
- 演出として、M5GOのLEDバーの色を雨と晴れで変更させる
#include <M5Stack.h>
#include <Adafruit_NeoPixel.h>
#include "DHT12.h"
#define M5GO_NUM_LEDS 10
#define M5GO_DATA_PIN 15
#define SOLENOID 26
Adafruit_NeoPixel ledBar = Adafruit_NeoPixel(M5GO_NUM_LEDS, M5GO_DATA_PIN, NEO_GRB + NEO_KHZ800);
DHT12 dht12; //Preset scale CELSIUS and ID 0x5c.
float hum_threshold = 20.0;
boolean raining = false;
boolean sole_tgle = true;
// 画像の描画する座標
int image_x = 44;
int image_y = 0;
// ledBar
int gray_r = 216;
int gray_g = 214;
int gray_b = 213;
// デバッグ用
boolean debug_mode = false;
// 文字位置
int text_x = 280;
int text_y = 0;
int text_line = 16;
// バー位置
int bar_x = 280;
int bar_y = text_y + text_line*2;
int bar_w = 35;
int bar_h = 200;
void setup() {
M5.begin();
M5.Power.begin();
Wire.begin();
ledBar.begin();
pinMode(SOLENOID, OUTPUT);
M5.Lcd.setBrightness(10);
Serial.println(F("ENV Unit(DHT12 and BMP280) test..."));
M5.Lcd.clear(WHITE);
}
void loop() {
// float tmp = dht12.readTemperature();
float hum = dht12.readHumidity();
// Serial.printf("Temperatura: %2.2f*C Humedad: %0.2f%%\r\n", tmp, hum);
// デバッグ
if (debug_mode == true) {
M5.Lcd.fillRect(bar_x, bar_y, 320, 240, WHITE);
M5.Lcd.setTextColor(BLACK, WHITE);
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(text_x, text_y);
M5.Lcd.printf("%2.0f%%", hum);
M5.Lcd.setCursor(text_x, text_y + text_line);
M5.Lcd.printf("%2.0f%%", hum_threshold);
M5.Lcd.fillRect(bar_x, bar_y + bar_h - (int)hum*2, bar_w, (int)hum*2, GREEN);
M5.Lcd.drawRect(bar_x, bar_y, bar_w, bar_h, BLUE);
int bar_t = bar_y + bar_h - (int)hum_threshold*2;
M5.Lcd.drawLine(bar_x, bar_t, bar_x + bar_w, bar_t, RED);
}
if ( hum >= hum_threshold ) {
raining = false;
Serial.println("weather is sun");
}
if (raining == true) {
rainSole();
M5.Lcd.drawJpgFile(SD, "/mark_tenki_umbrella.jpg", image_x, image_y);
setLedBarColor(0, 0, 255);
switch ( (int)(hum_threshold - hum) ){
case 0:
case 1:
ledBar.setPixelColor(3, ledBar.Color(gray_r, gray_g, gray_b));
ledBar.setPixelColor(M5GO_NUM_LEDS - 4, ledBar.Color(gray_r, gray_g, gray_b));
case 2:
ledBar.setPixelColor(2, ledBar.Color(gray_r, gray_g, gray_b));
ledBar.setPixelColor(M5GO_NUM_LEDS - 3, ledBar.Color(gray_r, gray_g, gray_b));
case 3:
case 4:
case 5:
ledBar.setPixelColor(1, ledBar.Color(gray_r, gray_g, gray_b));
ledBar.setPixelColor(M5GO_NUM_LEDS - 2, ledBar.Color(gray_r, gray_g, gray_b));
case 6:
case 7:
case 8:
ledBar.setPixelColor(0, ledBar.Color(gray_r, gray_g, gray_b));
ledBar.setPixelColor(M5GO_NUM_LEDS - 1, ledBar.Color(gray_r, gray_g, gray_b));
ledBar.show();
break;
}
}
else if (raining == false) {
digitalWrite(SOLENOID, LOW);
M5.Lcd.drawJpgFile(SD, "/mark_tenki_hare.jpg", image_x, image_y);
setLedBarColor(255, 60, 46);
if ( hum < hum_threshold - 10 ) {
setLedBarColor(gray_r, gray_g, gray_b);
}
}
// スイッチ操作
// update button state
M5.update();
// if you want to use Releasefor("was released for"), use .wasReleasefor(int time) below
if (M5.BtnA.wasReleased()) {
raining = true;
Serial.println("reset");
} else if (M5.BtnB.wasReleased()) {
if (debug_mode) {
hum_threshold--;
}
} else if (M5.BtnC.wasReleased()) {
if (debug_mode) {
hum_threshold++;
}
} else if (M5.BtnB.wasReleasefor(700)) {
debug_mode = !debug_mode;
Serial.printf("debug:%d\n", debug_mode);
if (debug_mode == false) {
M5.Lcd.fillRect(text_x, text_y, 320, 240, WHITE);
}
}
delay(50);
}
void rainSole(void) {
if (sole_tgle) {
digitalWrite(SOLENOID, HIGH);
}
else {
digitalWrite(SOLENOID, LOW);
}
sole_tgle = !sole_tgle;
}
void setLedBarColor(int r, int g, int b) {
for (int i=0; i < M5GO_NUM_LEDS; i++) {
ledBar.setPixelColor(i, ledBar.Color(r,g,b));
}
ledBar.show();
}
実際の挙動
投稿者の人気記事
-
forest516
さんが
2021/02/20
に
編集
をしました。
(メッセージ: 初版)
ログインしてコメントを投稿する