2021年5月16日日曜日

工作メモ - オルゴール - その3 - サーボモーター+外装モデリング

 サーボモーターで回転機構

前回のarduinoスケッチにサーボモーター 部分を追加して書いていきます。
今回は無限回転サーボを使っているため動かしたいときのみ角度を設定してしまえば終わりなはずです。

曲が流れている間だけ回るように設定していきます。

#include <M5StickC.h>
#include "FS.h"
#include "SPIFFS.h"
#include "AudioFileSourceSPIFFS.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"

const uint8_t Srv0 = 33;//, Srv1 = 26, Srv2 = 32, Srv3 = 33; //GPIO No.
const uint8_t srv_CH0 = 0;//, srv_CH1 = 1, srv_CH2 = 2, srv_CH3 = 3; //チャンネル
const double PWM_Hz = 50;   //PWM周波数
const uint8_t PWM_level = 16; //PWM 16bit(0~65535)


// オーディオファイル名
const char AUDIO_FILE_NAME[] = "/bemine.mp3";

const int I2S_NUM_0 = 0;
// 電源ボタンが1秒未満押された
const uint8_t AXP_WAS_PRESSED = 2;

AudioGeneratorMP3 *generator = NULL;
AudioFileSourceSPIFFS *source = NULL;
AudioOutputI2S *output = NULL;

// メッセージ出力
void showMessage(const char *message) {
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(5, 35);
    M5.Lcd.setTextFont(2);
    M5.Lcd.setTextColor(WHITE);
    M5.Lcd.print(message);
}

void playAudio() {
    Serial.println("playAudio");

    stopAudio();
    if (!source->isOpen()) {
        source->open(AUDIO_FILE_NAME);
    }
    generator->begin(source, output);
}

void stopAudio() {
    Serial.println("stopAudio");

    if (generator->isRunning()) {
        generator->stop();
    }
}

void setup() {
    M5.begin();
    M5.Lcd.setRotation(1);
    showMessage("ESP8266Audio");

    // シリアルモニターの設定
    Serial.begin(115200);
    audioLogger = &Serial;

    pinMode(Srv0, OUTPUT);
    ledcSetup(srv_CH0, PWM_Hz, PWM_level);
    ledcAttachPin(Srv0, srv_CH0);

    // SPIFFSの設定
    if (!SPIFFS.begin()) {
        Serial.println("SPIFFS Mount Failed");
        return;
    }

    source = new AudioFileSourceSPIFFS(AUDIO_FILE_NAME);
    output = new AudioOutputI2S(I2S_NUM_0, AudioOutputI2S::INTERNAL_DAC);
    generator = new AudioGeneratorMP3();


  // Allow allocation of all timers
  //ESP32PWM::allocateTimer(0);
  //ESP32PWM::allocateTimer(1);
  //ESP32PWM::allocateTimer(2);
  //ESP32PWM::allocateTimer(3);
  //servo->setPeriodHertz(50);    // standard 50 hz servo
  //servo->attach(servoPin, 1000, 2000); // attaches the servo on pin 18 to the servo object
  // using default min/max of 1000us and 2000us
  // different servos may require different min/max settings
  // for an accurate 0 to 180 sweep
}

void loop() {
    delay(10);

    if (generator->isRunning()) {
        ledcWrite(srv_CH0, 4700);
        if (!generator->loop()) {
            stopAudio();
            ledcWrite(srv_CH0, 5000);
        }
    }
    else {
        // ボタンの状態を更新
        M5.update();

        // Aボタンが押されたら音声データ再生
        if (M5.BtnA.wasPressed()) {
            playAudio();
            //myservo.write(180, 30, false);
        }

        // 電源ボタンが押されたらリセット
        if (M5.Axp.GetBtnPress() == AXP_WAS_PRESSED) {
          playAudio();
            //esp_restart();
        }
    }
}


参考にしたスケッチはこちらになります。

http://blog.robotakao.jp/blog-entry-381.html


外装モデリング

外装はfusion360というCADツールで作り、3Dプリンターで出力していきます。

fusion360はめちゃくちゃ評判が良くて使ってみたのですが噂の通りすごい使いやすいです。
個人利用の範囲では1年間無料で使えるので使い始めましたが、1年以降は年間61000円かかるのでどうしよう・・・まあそれはその時に考えます。

基本的なスケッチ作成とそこから押し出しをする程度は習熟済みなのでサクサクと床壁を立ち上げていきます。

外装パーツは3つ。

  • m5stickC, サーボモーターを固定するベース部
  • 人形を乗せ、回転する回転部
  • 回転部以外の蓋になる部分、トップ部
ベース部はこんな感じに真ん中にサーボモーター、それと接する形でm5stickCを配置。固定は低めの枠のみで十分だと判断しました。下に空いている穴は電源ボタン用です。
周りにサーボモーターと接続するコードを収める壁を設置してみました。


3Dプリントしてみるとこんな感じになりました。プリント設定は標準、時間は約3時間半。


まずサーボモーターの線を収めるスペースを開けるのを忘れていてハマりませんでした・・・あとは線を収めるスペースも狭すぎて収まらず。二つをちょちょいと修正して再度プリント。


きれいに収まりました。線はちょっと暴れてますけどまあ収まっていればいいでしょう。
今記事を書きながら充電コードを刺す穴がないなぁと気づいたので後ほど修正します。

回転部はサーボモーターと接続できる穴があり、縁が波型にカットされていれば良しとします。テストプリントなので黒のフィラメントで出力していますが本番では白色のフィラメントに交換する予定です。


トップ部は蓋になっていればそれで良いです。一応縁は波型に。蓋が回ってしまわないようにm5stickCにひっかかる出っ張りをつけています。こちらも本番では白色でプリント予定です。


三つを組み合わせるとこんな感じになりました!



いい感じ!この状態で一回起動してみましょう。


いいんじゃないでしょうか。さて、残るは完全ノープランな原さん人形+できたら坂本さん人形作成・・・どうしましょうね?