【2日で作る二足歩行ロボット】-ソフト編-

* こちらの記事はクソアプリカレンダー2021投稿作品です 広い心持ってあくまでもネタとしてお楽しみ下さい

#1. はじめに
[前回](https://qiita.com/chrmlinux/items/806bccfcbbd03b6d0df8)の投稿でハード部の構築はおわっております
まだご覧になっていらっしゃらない方は合わせてお読みください

![IMG-4115.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/a843cf02-fbb5-b0fe-2cea-8f9bd2355bde.jpeg)

#2. 二足歩行に関して調べる

https://qiita.com/wukunn/items/05c1e94b547191cb8e83

https://qiita.com/wukunn/items/89292b3be095af3aed9a

そうなんですね💦　大変なのですね💦　甘く見てました💦
ご飯はもうおかわりしません　お味噌汁だけはおかわり勘弁してください

![publicdomainq-0027601qaj.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/28cfc075-efdc-1f85-235c-e2467fe918c9.jpeg)

#3. 再度二足歩行を熟考する

自分で歩いてみるとHIP(腰)サーボ / TOES(つま先)サーボだけではどうも足りない気がする
そう何かが足りないのだ
あぁ　そもそも自分の体は 4自由度では無いから💦
出来上がったハード(術式：Chrm式サーボ直結) は
電源を入れないでおくと自由に動かす事が出来る
これを使ってまさに 0から制御部を組み立てる事にする

#4. 0°から180°までさらに往復
Lチカ等の点滅にこういう構文が多用される
確かにこれはこれで判りやすいのですが

```
for (int i=0; i<180; i++) {
 func(i);
}
for (int i=180; i>0; i--) {
 func(i);
}

```

センサ屋さんとしてはこちらの方がピンと来る
特に stp = -stp; でご飯がおかわり出来そう

```
static int stp = 1;
static int cnt = 0;
func(cnt);
cnt += stp;
if ((cnt <=0) || (cnt >= 180)) stp = -stp;

```

つまり __正解は一つではなくプログラマの数だけあると言う事だ__

#5. HIP(腰)サーボの動きについて考える
話を戻そう...
Chrm式サーボ直結を使って手で動かしてみると
HIP(腰)サーボは常に 0°から180°までの間を行き来する
そう　見事なくらい
従って HIP(腰)サーボの動きは以下の記述で済んでしまう

ESP32で無くなった AnalogWrite の代わりになる ledc系の関数の
詳しい資料は是非　[lang-ship](https://lang-ship.com/blog/work/esp32-pwm-max/) さんを
ご参照くださいませ

```
  static int deg = 90;
  static int stp = WALK_STEP;

  setDeg(deg);
  execServo();
  deg += stp;
  if ((deg <= MIN_DEG) || (deg >= MAX_DEG)) stp = -stp;

```
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/d33e67fc-73db-8d00-1c42-fd85b97e7014.jpeg)

いずれ投稿する [台形制御]()が反映されていないので非常に直線的な波形であるが要件は満たしている
ここでサーボの動きだけではなく全体の動きを見てみよう
アイススケート場で前に進もうとしているが滑って前に進めない状態である
ちょっと可愛い♡

#6. 歩くためにはどうしたら良いのか?

電源が入って居ないChrm式サーボ直結をいじっているうちに何か答えが見えて来た
腰の動きは変えずに　TOES(つま先)サーボの動きを制御すれば良い
だが　どのタイミングで?
.
.
.
上図の赤い線　stp が上下を繰り返すタイミングっぽい事が分かった
では　どのように？

#7. バランスが崩れるとこはどこだ？

右の TOES(つま先)サーボを思い切り閉じると同時に 左の TOES(つま先)サーボを思い切り開く
まさにつま先立ち状態で

![IMG-4110.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/0c1c65e1-6dce-4fd6-01f1-7b8d5cb9bf69.jpeg)

HIP(腰)サーボの動きが加わると　あら不思議バランスが右脚に移動する

![IMG-4113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/2cda2177-386a-0947-1cc4-b41ed8afa8d4.jpeg)

そのまま　パタンとTOES(つま先)サーボを元に戻す

![IMG-4114.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/1d0c4f5b-44a3-f50d-95f3-329ce5f2260b.jpeg)

右脚もおなじように傾けてぇ

![IMG-4111.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/71079906-1b75-6554-32ff-e9498946d8ff.jpeg)

パタンっ
![IMG-4112.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/44d3c0cf-cb47-633a-88d4-0c46e9989f4e.jpeg)

* こいつ、動くぞ！

![FullSizeRender.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/9f9e5967-768b-b3db-8ae7-323538b86133.gif)

#8. 全ソース
https://github.com/chrmlinux/ChrmWalk
* Chrm式サーボ直結ハードが無いと動きません

``` ChrmWalk.ino

#include <ESP32Servo.h>

#define SERVO_MAX   (4)

#define LIM_DEG     (45)
#define MAX_DEG     (180 - LIM_DEG)
#define MIN_DEG     (  0 + LIM_DEG)
#define WALK_DELAY  (30)
#define WALK_STEP   (-4)

#define MIN_uSEC ( 600)
#define MAX_uSEC (2500)

enum {RIGHT_TOES = 0, RIGHT_HIP, LEFT_TOES, LEFT_HIP};
enum {FWD = 0, BACK, LEFT, RIGHT};
typedef struct {
  int pin;    // pin no.
  int deg;    // degree
} SERVO_T;
Servo sv[SERVO_MAX];

SERVO_T _svc[SERVO_MAX] = {
  33, 90,
  23, 90,
  19, 90,
  22, 90,
};
static int _lr = 0;

void setDeg(int hipdeg, int toesdeg)
{
  _svc[RIGHT_HIP].deg = hipdeg;
  _svc[LEFT_HIP].deg = hipdeg;
  _svc[RIGHT_TOES].deg = (180 - toesdeg);
  _svc[LEFT_TOES].deg = (180 - toesdeg);
}

void execServo() {
  for (int i = 0; i < SERVO_MAX; i++) {
    sv[i].write(_svc[i].deg);
  }
  delay(WALK_DELAY);
}

void walk(int fb)
{
  static int hipdeg = 90;
  static int toesdeg = 90;
  static int stp = WALK_STEP;

  Serial.printf("%d %d\n", hipdeg, stp);
  setDeg(hipdeg, toesdeg);
  execServo();
  hipdeg += stp;
  toesdeg += stp;
  if ((hipdeg <= MIN_DEG) || (hipdeg >= MAX_DEG)) {
    stp = -stp;
    toesdeg = 90;
    _lr = (_lr + 1) % (SERVO_MAX / 2);
  }

}

void turn(int lr)
{
}

void setup() {
  Serial.begin( 115200 );
  for (int i = 0; i < SERVO_MAX; i++) {
    sv[i].setPeriodHertz(50);
    sv[i].attach(_svc[i].pin, MIN_uSEC, MAX_uSEC);
    sv[i].write (_svc[i].deg);
  }
}

void loop()
{
  walk(FWD);
  delay(1);
}
```

#9. さいごに
回転やら後退のロジックも確実に見えて来ているので
また時間が空きましたら投稿させて頂こうと思います
さらに　ESP32の持ちうる無線関連も合わせるときっと良いものが作成できるかと信じております
今回は 【2日で作る二足歩行ロボット】という事でここで終了

新型コロナが　落ち着いて来てはおりますがまだまだ油断が出来ないことは判っております
CPU＋サーボ代金合わせまして 2千円くらいの出費でロボットは作れますので
お父さまお母さま冬休みの間にお子様にロボットを作ってあげるのも良いのではないかと思います

最後までご視聴頂き
ありがとうございました

@chrmlinux03