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に保存 - その後スリープして、朝付近にまた起動させ正確な時間を読みに行く(省電力化) フローにするとこんなイメージ ![フローチャート](https://camo.elchika.com/1c06231e57c493bb0edfa19d485b2692489ea110/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38363163656637642d376563322d343363652d383034302d3138646133393463386661372f38313662313865622d363334642d343465652d393933612d613633653739353663633839/) **使用物品** ==== ○マイコン ![SPRESENSEとモジュール](https://camo.elchika.com/5d2d692911748e379511b06308e9df54d200110f/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38363163656637642d376563322d343363652d383034302d3138646133393463386661372f37326162633361372d616431332d343366392d613035642d353165353636323432643936/) - spresense本体 - 拡張ボード - カメラモジュール - SD ○自動餌やり装置 ![100均ケースとサーボモータ](https://camo.elchika.com/d78047a67c055e7777ebd6e80ee260b122711538/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38363163656637642d376563322d343363652d383034302d3138646133393463386661372f31633631346334372d396364362d343064372d623030392d333966653230316264366265/) - 100均のケース - サーボモータ(Amazon格安品) - ジャンパーワイヤー **コードと接続** ==== プログラミングに関しては完全なる初学者のため、動いてるだけで良しとした(ifが便利すぎで初学者使いがち) SPRESENSEとの接続は、サーボモータの信号線をD15ピンに繋げただけですね!! ![SPRESENSEとサーボモータ](https://camo.elchika.com/2be9382d6da50c3ef888f47f223d075c10d122e4/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38363163656637642d376563322d343363652d383034302d3138646133393463386661372f36623863376230382d333236352d346166352d393437332d613661653166613333333764/) ```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化で餌やりを自動化出来たことがかなりのメリットでした。 また、写真は期待通りの高画質で大満足ですね。 ![定点カメラ撮影15日目](https://camo.elchika.com/b2d79e3ec62c11fbb493020c8709f86d7af3984a/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38363163656637642d376563322d343363652d383034302d3138646133393463386661372f36343535323366332d613437632d343636642d383638352d343530376334353038616532/) 定点カメラで撮影ができると成長過程が見れて、ますます植物を育てたくなりますね。 **今後の展望** ==== 実は腑に落ちてない部分もあり… 省電力化(deepsleep使ってるのにサーボモーターには常に電流が流れている件)やコード(とりあえず動いてる感)にまだまだ改善の余地がありですね。 照明もUSB給電なので、リレーモジュールを組み込めばライトのOnOFFも管理できそうです。 ひとまず形にはなったので、これで完成としたいと思います。 省電力化にアドバイスがあったら是非お願いします!!