秋月 5 finger 制御編 (後編)
とりあえず サーボ1つで軽くテストできました ので、5指バージョンかつ 5V 動作に拡張します。
実験は ESP32 を用いましたため、信号線を 3.3V→5V するレベルコンバートが必要ですが、てっとり早くトランジスタと抵抗で簡単に仕上げてみました。
ECB じゃなくて EBC のほうが実装的に都合が良かったため 2N3904 を使いましたが、2SC1815 とかでも大丈夫です。
プログラムのほうは、ライブラリ的なものと、メインと分けてみました。
■ライブラリ的なほう(finger.h)
#ifndef _WAKWAK_FINGER_ #define _WAKWAK_FINGER_ #ifndef ESP32 #include <Servo.h> #endif class Finger { public: Finger(int pin, bool reverse = false); void set(int *job); void tick(); protected: int *job; int job_pos; unsigned long wait; private: int pin; bool reverse; #ifdef ESP32 int channel; #else Servo servo; #endif void setDegree(int degree = -1); }; #endif
■ライブラリ的なほう(finger.ino)
#include "finger.h" Finger::Finger(int pin, bool reverse) { Finger::pin = pin; Finger::reverse = reverse; setDegree(); } void Finger::set(int *job) { Finger::job = job; Finger::wait = 0; Finger::job_pos = 0; } void Finger::tick() { if(millis() > wait && job[job_pos] >= 0) { setDegree(job[job_pos]); job_pos++; wait = millis() + job[job_pos]; job_pos++; } } void Finger::setDegree(int degree) { #ifdef ESP32 const int degree_0 = 500; // 0.5ms at 0 degree const int degree_180 = 2400; // 2.4ms at 180 degree const int pulse_width = 20000; // 20ms static int last_channel = 0; #endif if(degree < 0) { // Initialize #ifdef ESP32 channel = last_channel; int freq = 1000000 / pulse_width; ledcSetup(channel, freq, 10); ledcAttachPin(pin, channel); // for PWM last_channel ++; #else servo.attach(pin); #endif } else { if(reverse) degree = 180 - degree; #ifdef ESP32 int pulse = (degree_0 + degree * (degree_180 - degree_0) / 180.0F); if(pulse < degree_0) pulse = degree_0; pulse = 1023 * pulse / pulse_width; ledcWrite(channel, pulse); #else servo.write(degree); #endif } }
■メイン部分
#include "finger.h" // degree, delay, degree, delay ... int job_1[] = {110, 5000, 110, 5000, 70, 5000, -1}; int job_2[] = {110, 5000, 70, 5000, 70, 5000, -1}; int job_3[] = {110, 5000, 70, 5000, 70, 5000, -1}; int job_4[] = {110, 5000, 110, 5000, 70, 5000, -1}; int job_5[] = {110, 5000, 110, 5000, 70, 5000, -1}; Finger *fingers[] = { new Finger(23) , new Finger(22) , new Finger(21) , new Finger(19, true) , new Finger(18, true) }; void setup() { // put your setup code here, to run once: fingers[0]->set(job_1); fingers[1]->set(job_2); fingers[2]->set(job_3); fingers[3]->set(job_4); fingers[4]->set(job_5); } void loop() { for(int i=0; i<sizeof(fingers) / sizeof(fingers[0]); i++) fingers[i]->tick(); }
Servo.h が使える ESP8266 等と Servo.h が使えない ESP32 とで共用ソースにしてみましたが、マイコン側が PWM を 5ch 使えるかどうかは要確認です。
あと、new Finger() の引数がピン番号なのですが、ESP32 前提になってますので要注意。
薬指と小指は、親指と比較して逆回転なのですが、その辺はライブラリ側で吸収してます。
サンプルは5指が5秒おきに同期して動きますが、プログラムとしては擬似的ながらも非同期ぽく動作しますので5指バラバラに動かす・・・極端いえば(理論的には)ピアノを弾かせることもできます。
結構、電気を食います。
以下、動作結果についてネタバレ要素を含んでますので、動いたときの楽しみを大事になさる方は、いますぐにブラウザを閉じて下さい。
いいですか。
本当に閉じましたか?
では・・・
こいつ・・・
握力なさすぎ!!!!
かなり組み立てるの面倒なんですが、左手も手元にあるものの、組み立てる気が起きません。
それくらいに残念な握力です。
ピアノ?
そんなの絶対に無理無理、鍵盤を押す力もありませんよ、これ。