スタックチャンのAvatarクラスとサーボの動作確認

M5Stack Core2 / PlatformIO で検証。
サーボはG27とG19に接続。

platformio.ini

[env:m5stack-core2]
platform = espressif32
board = m5stack-core2
framework = arduino
lib_deps =
#   最新版のM5UnifiedとESP32Servoの組み合わせだとサーボが動かない?
#   m5stack/M5Unified@^0.2.7
#   meganetaaan/M5Stack-Avatar@^0.10.0
#   arminjo/ServoEasing@^3.4.0
#   madhephaestus/ESP32Servo@^3.0.8
    m5stack/M5Unified@0.1.16
    meganetaaan/M5Stack-Avatar@^0.9.2
    arminjo/ServoEasing@^2.4.0
    madhephaestus/ESP32Servo @ 0.13.0

main.cpp

#include <M5Unified.h>
#include <Avatar.h>
#include <ServoEasing.hpp>

#define SERVO_PIN_X 27
#define SERVO_PIN_Y 19
#define START_DEGREE_VALUE_X 90
#define START_DEGREE_VALUE_Y 85

using namespace m5avatar;
Avatar avatar;

ServoEasing servo_x;
ServoEasing servo_y;

bool servo_home = false;

void servo_setup() {
  if (servo_x.attach(SERVO_PIN_X, START_DEGREE_VALUE_X, DEFAULT_MICROSECONDS_FOR_0_DEGREE, DEFAULT_MICROSECONDS_FOR_180_DEGREE) == INVALID_SERVO) {
    Serial.print("Error attaching servo x");
  }
  if (servo_y.attach(SERVO_PIN_Y, START_DEGREE_VALUE_Y, DEFAULT_MICROSECONDS_FOR_0_DEGREE, DEFAULT_MICROSECONDS_FOR_180_DEGREE) == INVALID_SERVO) {
    Serial.print("Error attaching servo y");
  }
  servo_x.setEasingType(EASE_QUADRATIC_IN_OUT);
  servo_y.setEasingType(EASE_QUADRATIC_IN_OUT);
  setSpeedForAllServos(30);

  servo_x.setEaseTo(START_DEGREE_VALUE_X); 
  servo_y.setEaseTo(START_DEGREE_VALUE_Y);
  synchronizeAllServosStartAndWaitForAllServosToStop();
}

void servo(void *args)
{
  float gazeX, gazeY;
  DriveContext *ctx = (DriveContext *)args;
  Avatar *avatar = ctx->getAvatar();
  for (;;)
  {
    if(!servo_home)
    {
      avatar->getGaze(&gazeY, &gazeX);
      servo_x.setEaseTo(START_DEGREE_VALUE_X + (int)(15.0 * gazeX));
      if(gazeY < 0) {
        int tmp = (int)(10.0 * gazeY);
        if(tmp > 10) tmp = 10;
        servo_y.setEaseTo(START_DEGREE_VALUE_Y + tmp);
      } else {
        servo_y.setEaseTo(START_DEGREE_VALUE_Y + (int)(10.0 * gazeY));
      }
    } else {
       servo_x.setEaseTo(START_DEGREE_VALUE_X); 
       servo_y.setEaseTo(START_DEGREE_VALUE_Y);
    }
    synchronizeAllServosStartAndWaitForAllServosToStop();
    delay(50);
  }
}


void setup()
{
  auto cfg = M5.config();
  cfg.external_spk = true;    /// use external speaker (SPK HAT / ATOMIC SPK)
  M5.begin(cfg);

  servo_setup();
  delay(1000);

  avatar.init();
  avatar.addTask(servo, "servo");
  avatar.setSpeechFont(&fonts::efontJA_16);
  avatar.setSpeechText("こんにちは");
  delay(2000);
  avatar.setSpeechText("");
}

void loop()
{
  avatar.setExpression(Expression::Happy);
  delay(3000);
  avatar.setExpression(Expression::Sleepy);
  delay(3000);
}