HaLake Magazine

コワーキングスペースHaLakeの技術情報発信サイト!IoT,AR,VRなど最新技術情報をお届け!

加湿器をロボアームで起動してみよう!<2020年版>

f:id:mischief_cat:20210228145742p:plain

今回は、以前投稿した記事のバージョンアップまでは行きませんがある程度改良していきます。
その記事に関しては以下になります。

magazine.halake.com

この記事の続編となりますので先に読んでおく事をお勧めします。

大きく改良する点は以下になります。

改良点

  • HaLake Kitから汎用のESP8266への取り換え
  • 回路の見直し(少し)
  • プログラムの見直し(少し)
  • ラズパイからの別の制御方法



主に使ったもの

  • ロボットアーム(Romi用ロボットアームキット)
  • ESP8266
  • Raspberry pi 3B+

ロボットアームに関しては前回の記事と同じものを使うので説明は省きます。

ESP8266に関しては写真の物を使います。

f:id:mischief_cat:20210228141351p:plain

スイッチサイエンスさんの物を使用していますがHaLakeの備品を使ったのでいつ購入したものなのかわかりません。そのため現在販売しているものとは一部仕様が変わっている可能性があるので注意してください。

念のため同じようなもののリンクを貼っておきます。

www.switch-science.com

  • 注意:前述したように仕様が違う場合がありますので注意してください。ESP8266チップを使用した物であれば問題なく動作すると思いますが、リンクの物を使用する場合は自己判断でお願いします。



汎用ESP8266への取り換えと回路の変更

前回の記事ではHaLake Kitを使っていましたが入手性やピン配列が若干違うようなので汎用性が高い市販品に取り換えた方が、お試しいただけやすいと思うので取り換えていきます。

ESP8266は前述したスイッチサイエンスのリンクの物とピン配列がほぼ同じなので画像で示した位置と同じように使っていただければ問題ないと思います。

Fritzingパーツはこちらの物を使わせていただきました。

github.com

f:id:mischief_cat:20210228145524p:plain

電源(5V) GND 制御線
制御線 ピンチ アーム 手首
ESPピン 16 5 4

前回の記事を読んで頂いた方にはわかると思いますが、今回はサーボモータの電源制御用のMOSFETを使用していないため多少回路が簡略化されています。
しかし、サーボモータの電源を入れっぱなしなので消費電力や音などが気になる方は入れる必要がありそうです。
HaLakeでは電源を入れっぱなしで運用していたようなので、今回は省いてあります。



プログラムの見直し

前回の記事で実際にHaLakeで稼働うさせていたプログラムとして紹介されていたものが以下になります。

github.com

今回はこちらのプログラムを少し簡略化していきたいと思います。
大まかな流れは変えていませんので前回の記事にプログラムの説明が書かれているので参照していただけると幸いです。

esp8266側

#include <Arduino.h>
#include <Servo.h>
#include <vector>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

// hand: 0-180 | open-close
// arm: 0-100 | up-down
// wrist: 115-180  | down-up

#define HAND_SERVO_PIN 16
#define ARM_SERVO_PIN 5
#define WRIST_SERVO_PIN 4

Servo HandServo; 
Servo WristServo; 
Servo ArmServo; 

ESP8266WebServer server(80); 

uint8_t changeHandServo(uint8_t percentage){ // 0-100 : close-open
  Serial.println(180 - (percentage * 1.8));
  if(percentage <= 100) return 180 - (percentage * 1.8);
}

uint8_t changeWristServo(uint8_t percentage){ // 0-100 : down-up
  Serial.println(map(percentage, 0, 100, 115, 180));
  if(percentage <= 100) return map(percentage, 0, 100, 115, 180);
}

uint8_t changeArmServo(uint8_t percentage){ // 0-100 : down-up
  Serial.println(100 - percentage);
  if(percentage <= 100) return 100 - percentage;
}

int16_t str2uint8(String target){
  long result = target.toInt();

  if(result > 255) return -1;
  if(target == "" || result > 0) return result;
  else -1;
}

void setup(){
  HandServo.attach(HAND_SERVO_PIN);
  WristServo.attach(WRIST_SERVO_PIN);
  ArmServo.attach(ARM_SERVO_PIN);

  HandServo.write(changeHandServo(30));
  WristServo.write(changeWristServo(0));
  ArmServo.write(changeArmServo(80));

  Serial.begin(74800);
  delay(500);

  WiFi.config(IPAddress(192,168,3,220),IPAddress(192,168,3,1),IPAddress(255,255,255,0));
  WiFi.begin("nyampass-2g", "kijibuchitama");
  while(WiFi.status() != WL_CONNECTED){
    delay(1000);
    Serial.print(".");
  } 

  if(WiFi.status() != WL_CONNECTED){
    Serial.println("No Connection");
    ESP.restart();
  }
  else Serial.println(WiFi.localIP());

  server.on("/hand", [](){
    if(server.args() == 1){
      if(server.argName(0) == "percentage"){
        int16_t angle = str2uint8(server.arg(0));

        if(angle >= 0){
          HandServo.write(changeHandServo(angle));
          server.send(200, "text/html", "Hand was changed.");
        }
      }
    }

    server.send(200, "text/html", "Failed.");
  }); 

  server.on("/wrist", [](){
    if(server.args() == 1){
      if(server.argName(0) == "percentage"){
        int16_t angle = str2uint8(server.arg(0));

        if(angle >= 0){
          WristServo.write(changeWristServo(angle));
          server.send(200, "text/html", "Wrist was changed.");
        }
      }
    }
    server.send(200, "text/html", "Failed.");
  });

  server.on("/arm", [](){
    ArmServo.write(changeArmServo(0));
    delay(500);
    ArmServo.write(changeArmServo(100));
    server.send(200, "text/html", "Arm was changed.");
  });

  server.begin();
}

void loop(){
  server.handleClient();
 }

変更点を挙げるとボタンを押すために重要なアームの動きを制御するときパーセントで指定せず/armにアクセスすると自動でボタンを押す動作をしてくれます。以前のプログラムではアームを下に降ろして上げる動作をパーセントで指定してあげないといけなかったので簡略化しました。そのほかはあまり使うことがなかったのでそのままのプログラムにしておきました。必要に応じて消してもよさそうです。
もう一つの変更点は、シリアル通信での操作が出来るようになっていましたがそれをすべて削除しました。以前の記事では説明されていなかったと思いますがデバッグや何かあったときに導入されていたんだと思います。

次にラズパイ側からの制御プログラムを紹介していきたいと思います。と言ってもとても簡単なつくりなので紹介する必要があるかはいまいちなところですが...
今回はnodejsではなくPythonからの制御にしてみました。
ラズパイ側

import requests

URL = 'http://192.168.3.220/arm'

res = requests.get(URL)
print(res)

とても簡易的なものになっているのでエラーなどが出てもわからない作りです。重大なエラーが出たら加湿器がつかないのでこれでも十分だと思っています。
あとはラズパイの方の設定をしていきましょう。ラズパイのコマンドプロンプト

crontab -e

でcrontabの設定を編集できます。その中に私の場合は水曜日以外の朝8:30にこのプログラムを起動させたいので以下のように追加していきます。

30 8 * * 0,1,2,4,5,6 sudo python3 ~/humidifier/cron.py

分、時、日、月、曜日の順で書かれていて曜日はカンマで区切ることによって複数指定できます。(0が日曜日で番号が順にふられています。)そのあとにラズパイで実行したいコマンドを記述することで指定した時にコマンドを実行してくれます。
これで最後のプログラムは味気ないですが完成しました。
実を言うとスマホPCからローカルのサイトにアクセスしていつでも簡単に起動や自動起動時間の設定を出来るものを作っていたのですが問題があり思い通りに動かなかったので前述した案に切り替えました。いつか完成出来たら載せたいです。

まとめ

  • 汎用性の高い基盤に差し替えられた
  • プログラムの簡略化(少し)
  • 設置をし直して見た目の改善が出来た