forest516のアイコン画像
forest516 2021年02月20日作成
製作品 製作品 閲覧数 960
forest516 2021年02月20日作成 製作品 製作品 閲覧数 960

天気を雨から晴れにするのを体験できる傘

天気を雨から晴れにするのを体験できる傘

動機

天気をあれこれする子たちいわく、ただの空模様に心を動かされてしまうらしい。晴れると気持ちが良くなるよね。ならばそれをいつでもできるようになれば、どこでも気分を盛り上げることが…。なんてことはなく、愛と、天気を変える瞬間を体験したい思いだけで、僕にできることをやった結果。

再現方法の選定

雨音の再現

ビーズを紐に結んだりなど色々試してみた結果、針金が直接傘を叩く音が一番近いという結論に。

材料

  • 針金
  • プラバン
  • 結束バンド
  • ソレノイド
  • サーボモータの丸型ホーン
  • ガムテープ
  1. プラバンを円形に切り、適当な長さの針金を括り付けていく(向きを整えるガイドとして結束バンドで固定)
  2. サーボモータの丸型ホーンを繋ぎとして、針金を取り付けた円盤をソレノイドに固定する
  3. ソレノイドと傘は、ガムテープで固定
  4. ソレノイドを上下運動させると、針金が揺れて傘を叩く

キャプションを入力できます

祈りの再現

手を組んで、一定時間祈ることを再現したいため、湿度センサーを選択。
手でくるむと、じわじわと湿度が上がっていくので、適当に決めたしきい値を超えるとソレノイドを止める=晴れにすることにする。

回路部仕組み

材料

  • 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();
}

実際の挙動

ここに動画が表示されます

ログインしてコメントを投稿する