gadgewota が 2022年09月12日01時34分16秒 に編集
初版
タイトルの変更
自作水槽をspresenseでIoT化(自動餌やりと定点撮影となるべく省電力)
タグの変更
spresense
IoT
水槽
メイン画像の変更
記事種類の変更
製作品
本文の変更
**はじめに** ==== 今回2022年 SPRESENSE™ 活用コンテストにてspresense本体と、拡張ボード、カメラモジュールをご提供いただけたので、 やってみたかった**100均自作水槽のIoT化にチャレンジ**してみる。 ちなみに今回IoT化する水槽はこちら。 **【100均自作】小型オーバーフロー&アクアポニックス水槽 #1水槽作り** @[youtube](https://youtu.be/oUiOgpN9lRM) ※正確には植物も栽培するアクアポニックス+オーバーフロー水槽です やはりspresenseといえば**GPSを搭載している**事が最大の特徴だと思っているので、お試しで少しだけ利用してみる。 加えて**カメラモジュールも約500万画素**とマイコンとは思えない性能を持っているため、ここもしっかりと利用します (マイコンでカメラといえばESP32-CAMが思い浮かびますが、SPRESENSEの性能は倍以上らしい、期待大)。 あとやはりマイコンということで**省電力化**はできる限り行いたい(公式な使用方法から外れない程度で) よって搭載した機能は以下の通り。 - GPSで正確な時間を取得する - 毎朝ある時間になったら、自動で魚に餌やりをする(自動餌やり装置を自作) - 餌やりのタイミングで定点カメラが植物の様子を撮影し、SDに保存 - その後スリープして、朝付近にまた起動させ正確な時間を読みに行く(省電力化) フローにするとこんなイメージ  **使用物品** ==== ○マイコン  - spresense本体 - 拡張ボード - カメラモジュール - SD ○自動餌やり装置  - 100均のケース - サーボモータ(Amazon格安品) - ジャンパーワイヤー **コードと接続** ==== プログラミングに関しては完全なる初学者のため、動いてるだけで良しとした(ifが便利すぎで初学者使いがち) SPRESENSEとの接続は、サーボモータの信号線をD15ピンに繋げただけですね!!  ```arduino:水槽IoT化装置 #include <Camera.h> #include <SDHCI.h> #include <Servo.h> //GPS #include <Arduino.h> #include <LowPower.h> #include <RTC.h> #include <GNSS.h> SpGnss Gnss; #define MY_TIMEZONE_IN_SECONDS (9 * 60 * 60) // JST int state = false; ///// //servo static Servo servo; ///// SDClass theSD; void setup() { //servo servo.attach(PIN_D15); servo.write(0); //GPS LowPower.clockMode(CLOCK_MODE_32MHz); Serial.begin(115200); while (!Serial); RTC.begin(); LowPower.begin(); pinMode(LED0, OUTPUT); //Get time from GPS pinMode(LED1, OUTPUT); //take a picture pinMode(LED2, OUTPUT); //GPS connect digitalWrite(LED0, LOW); digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); // Initialize and start GNSS library int ret; ret = Gnss.begin(); assert(ret == 0); ret = Gnss.start(); assert(ret == 0); ///// } void loop() { //GPS Serial.print("."); state = !state; digitalWrite(LED2, (state)? HIGH: LOW); // Wait for GNSS data if (Gnss.waitUpdate()) { SpNavData NavData; // Get the UTC time Gnss.getNavData(&NavData); SpGnssTime *time = &NavData.time; // Check if the acquired UTC time is accurate if (time->year >= 2000) { Serial.println("."); Serial.println("Get time from GPS"); digitalWrite(LED0, HIGH); char buf[128]; // Convert SpGnssTime to RtcTime RtcTime gps(time->year, time->month, time->day, time->hour, time->minute, time->sec, time->usec * 1000); gps += MY_TIMEZONE_IN_SECONDS; sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d\t", gps.year(), gps.month(), gps.day(), gps.hour(), gps.minute(), gps.second()); Serial.print("Data: "); Serial.println(buf); int t = gps.hour(); delay(1000); digitalWrite(LED0, LOW); ///// //Shooting conditions if(t < 10){ digitalWrite(LED2, LOW); Serial.println("Re GPS connect after 10 min"); //deepsleep digitalWrite(LED0, LOW); digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); Serial.println("deepsleep start (10 min)"); LowPower.deepSleep(10 * 60); }else{ theCamera.begin(); while(!theSD.begin()); theCamera.setStillPictureImageFormat( CAM_IMGSIZE_QUADVGA_H ,CAM_IMGSIZE_QUADVGA_V ,CAM_IMAGE_PIX_FMT_JPG); digitalWrite(LED1, HIGH); CamImage img = theCamera.takePicture(); if (img.isAvailable()) { char filename[16] = {0}; sprintf(filename, "%04d%02d%02d%02d%02d%02d.JPG", gps.year(), gps.month(), gps.day(), gps.hour(), gps.minute(), gps.second()); File myFile = theSD.open(filename, FILE_WRITE); myFile.write(img.getImgBuff(), img.getImgSize()); myFile.close(); Serial.println("take a picture"); digitalWrite(LED1, LOW); } //servo ON Serial.println("servo ON"); servo.write(180); delay(3000); servo.write(0); delay(1000); //deepsleep digitalWrite(LED0, LOW); digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); Serial.println("deepsleep start (23 h)"); LowPower.deepSleep(23 * 60 * 60); } } } } ``` **完成品はこちら** ==== @[twitter](https://twitter.com/gadgewota/status/1568990612342587393?t=Y5gji-4ICWU9SS53ZuFyGA&s=19) ※一日一回しか作動しないため、設置前のデモ動画を掲載しています(自動餌やり装置とSPRESENSE) ズボラな私的には、IoT化で餌やりを自動化出来たことがかなりのメリットでした。 また、写真は期待通りの高画質で大満足ですね。  定点カメラで撮影ができると成長過程が見れて、ますます植物を育てたくなりますね。 **今後の展望** ==== 実は腑に落ちてない部分もあり… 省電力化(deepsleep使ってるのにサーボモーターには常に電流が流れている件)やコード(とりあえず動いてる感)にまだまだ改善の余地がありですね。 照明もUSB給電なので、リレーモジュールを組み込めばライトのOnOFFも管理できそうです。 ひとまず形にはなったので、これで完成としたいと思います。 省電力化にアドバイスがあったら是非お願いします!!