5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

骨折して入院して車椅子になりました。関連した困りごとを実装してみました。

IoTLTでの発表内容補足的な感じです。

https://speakerdeck.com/n0bisuke2/gu-zhe-toru-yuan-toiot-number-iotlt

骨折しました。

骨折して入院して車椅子になりました。

車椅子以外と疲れる問題

入院中は車椅子での移動だったのですが、車椅子は意外と疲れます。

入院で運動量がガクッと落ちたというiPhoneの計測
スクリーンショット 2024-07-17 23.46.09.png

疲れるんですけど、ヘルスケアアプリでの活動量はだいぶ低いという結果に。

車椅子でどれくらい移動しているかを計測したいなと思いました。

松葉杖よりは疲れないです。今のところ松葉杖が最上級。

車椅子にAtomS3を取り付け

たまたま持っていたAtomS3を取り付けました。

スクリーンショット 2024-07-17 23.42.59.png

実際のコード

M5Unifiedを使っています。

GPT-4oに聞きながらやってみましたが、M5unifideでの書き方もバッチリでした。

#include <M5Unified.h>

float gyroZOffset = 0.0;

void calibrateGyro() {
  const int numReadings = 1000;
  float sum = 0.0;

  for (int i = 0; i < numReadings; i++) {
    float gyroX, gyroY, gyroZ;
    M5.Imu.getGyro(&gyroX, &gyroY, &gyroZ);
    sum += gyroZ;
    delay(1);
  }

  gyroZOffset = sum / numReadings;
}

void setup(void) {
  auto cfg = M5.config();
  M5.begin(cfg);

  M5.Display.setTextSize(2);  // 文字サイズを1.5倍に設定

  const char* name;
  switch (M5.getBoard()) {
    case m5::board_t::board_M5AtomS3:
      name = "ATOM S3";
      break;
    default:
      name = "Who am I ?";
      break;
  }
  M5.Display.startWrite();
  M5.Display.print("Core:");
  M5.Display.println(name);
  Serial.printf("core:%s\n", name);

  switch (M5.Imu.getType()) {
    case m5::imu_t::imu_mpu6886:
      name = "MPU6886";
      break;
    default:
      name = "none";
      break;
  }
  M5.Display.print("IMU:");
  M5.Display.println(name);
  M5.Display.endWrite();
  Serial.printf("imu:%s\n", name);

  // Calibrate the gyro
  calibrateGyro();
}

float calculateRotationAngle(float gyroRate, float deltaTime) {
  return gyroRate * deltaTime;
}

void loop(void) {
  delay(1);
  int h = M5.Display.height() / 8;

  M5.update();

  static constexpr const int colors[] = { TFT_WHITE, TFT_CYAN, TFT_RED, TFT_YELLOW, TFT_BLUE, TFT_GREEN };
  static constexpr const char* const names[] = { "none", "wasHold", "wasClicked", "wasPressed", "wasReleased", "wasDeciedCount" };

  M5.Display.startWrite();

  auto state = M5.BtnA.wasHold()          ? 1
          : M5.BtnA.wasClicked()          ? 2
          : M5.BtnA.wasPressed()          ? 3
          : M5.BtnA.wasReleased()         ? 4
          : M5.BtnA.wasDeciedClickCount() ? 5
                                          : 0;
  if (state) {
    Serial.printf("BtnA:%s  count:%d\n", names[state], M5.BtnA.getClickCount());
    if (!M5.Display.displayBusy()) {
      M5.Display.fillRect(0, h * 3, h, h - 1, colors[state]);
      M5.Display.setCursor(0, h * 3);
      M5.Display.printf("%d", M5.BtnA.getClickCount());
    }
  }

  M5.Display.endWrite();

  static float accumulatedAngle = 0;
  static int rotationCount = 0;
  static int partialTurns = 0;

  if (M5.Imu.isEnabled()) {
    float gyroX, gyroY, gyroZ;
    M5.Imu.getGyro(&gyroX, &gyroY, &gyroZ);

    // Apply gyro offset and reverse the sign
    gyroZ = - (gyroZ - gyroZOffset);

    static unsigned long lastTime = 0;
    unsigned long currentTime = millis();
    float deltaTime = (currentTime - lastTime) / 1000.0; // delta time in seconds
    lastTime = currentTime;

    // Assuming the wheelchair rotates around the Z-axis (yaw)
    float rotationAngle = calculateRotationAngle(gyroZ, deltaTime);
    accumulatedAngle += rotationAngle;

    // Keep accumulatedAngle within 0 to 359 degrees
    if (accumulatedAngle >= 360.0) {
      rotationCount++;
      accumulatedAngle -= 360.0;
    } else if (accumulatedAngle < 0.0) {
      rotationCount--;
      accumulatedAngle += 360.0;
    }

    // Calculate partial turns within the range of 0 to 59
    partialTurns = static_cast<int>(accumulatedAngle / 6.0); // 1/60 turn = 6 degrees

    M5.Display.startWrite();
    M5.Display.setCursor(0, h * 5);
    M5.Display.printf("Rotations: %d", rotationCount);
    M5.Display.setCursor(0, h * 6);
    M5.Display.printf("Partial Turns: %d", partialTurns);
    M5.Display.endWrite();

    Serial.printf("Rotations: %d, Partial Turns: %d\n", rotationCount, partialTurns);
  }
  M5.Display.display();
}

結構良い感じに計測ができました

スクリーンショット 2024-07-17 23.51.48.png

今後

計測した値をスプレッドシートに記録するなどやりたいですが、病院で使えるWi-Fiがなかったのでそこは断念してました。

上手いやり方検討したい。。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?