1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

M5StackをPlatformIOで使う

1
Last updated at Posted at 2024-03-21

デバイス

ATOMS3

https://docs.m5stack.com/en/core/AtomS3
https://www.switch-science.com/products/8670

Core2

https://docs.m5stack.com/en/core/core2
https://docs.m5stack.com/ja/core/Core2%20v1.1 V1.1
https://www.switch-science.com/products/9349
https://logikara.blog/core2/
https://logikara.blog/core2_2/

CoreS3SE

https://docs.m5stack.com/en/core/M5CoreS3%20SE
https://www.switch-science.com/products/9690

CoreInk

https://docs.m5stack.com/ja/core/coreink
https://www.switch-science.com/products/6735

VL53L1X

https://shop.m5stack.com/products/time-of-flight-distance-unit-vl53l1x
https://www.switch-science.com/products/9427

環境

VisualStudioCodeを設定

VisualStudioCodeをインストール

バージョン: 1.106.3 (user setup)
コミット: bf9252a2fb45be6893dd8870c0bf37e2e1766d61
日付: 2025-11-25T22:28:18.024Z
Electron: 37.7.0
ElectronBuildId: 12781156
Chromium: 138.0.7204.251
Node.js: 22.20.0
V8: 13.8.258.32-electron.0
OS: Windows_NT x64 10.0.26200

[表示][拡張機能]

  • C/C++ v1.21.6
  • C/C++ Extension Pack v1.3.0
  • Japanese Language Pack for Visual Studio Code v1.93.2024091109
  • PlatformIO IDE Core 6.1.18·Home 3.4.4
  • Arduino v0.6.0 廃止なので使用せず
  • Command Palette (CTRL+SHIFT+P)
    ** Configure Display Language = 日本語(ja)

参考
https://elchika.com/article/6a153bc2-318f-44c7-871b-0ddbdce2ca42/

PlatformIOでプロジェクト作成

[PlatformIO昆虫アイコン][QUICK ACCESS][PIO Home][Home]
[+ New Project]
Project Wizard
Name[プロジェクト名]
Board[M5Stack AtomS3]又は[M5Stack CoreS3]又は[M5Stack-CoreInk]
Framework[Arduino]
Location[プロジェクトフォルダを置くフォルダ]
[Finish]

BMI270 IMU 加速度角速度

LibraryにM5Unifiedを追加

[PlatformIO昆虫アイコン][QUICK ACCESS][PIO Home][Library]
[M5Unifiedで検索][M5Unified by M5Stack, lovyan03][Add to Project]
Add project dependency
Select a project[プロジェクト名][Add]

platform.iniに追加される

lib_deps = m5stack/M5Unified@^0.2.11

BMP280 気圧温度センサ

LibraryにM5Unit-ENVを追加

[PlatformIO昆虫アイコン][QUICK ACCESS][PIO Home][Library]
[M5Unitで検索][M5Unit-ENV by M5Stack][Add to Project]
Add project dependency
Select a project[プロジェクト名][Add]

platform.iniに追加される

lib_deps = m5stack/M5Unit-ENV@^1.0.1

VL53L1X 距離センサ

platformio.iniに追加

[env:m5stack-atoms3]
platform = espressif32
board = m5stack-atoms3
framework = arduino
lib_deps = 
	m5stack/M5Unified@^0.1.16
	m5stack/M5Unit-ENV@^1.0.1
	https://github.com/pololu/vl53l1x-arduino
	https://github.com/Seeed-Studio/Grove_3_Axis_Compass_V2.0_BMM150

BM150 方位センサ

platformio.iniに追加

[env:m5stack-atoms3]
platform = espressif32
board = m5stack-atoms3
framework = arduino
lib_deps = 
	m5stack/M5Unified@^0.1.16
	m5stack/M5Unit-ENV@^1.0.1
	https://github.com/pololu/vl53l1x-arduino
	https://github.com/Seeed-Studio/Grove_3_Axis_Compass_V2.0_BMM150

実装

UDP送受信

本家
https://www.arduino.cc/reference/en/libraries/wifi/
参考
https://note.com/khe00716/n/n65a479049078

NTP時刻同期

実装例

#include <M5Unified.h>
#include <WiFi.h>
#include <time.h>
#include "image.h"
#include <VL53L1X.h>
#include <M5UnitENV.h>
#include "bmm150.h"
#include "bmm150_defs.h"

#if ARDUINO_USB_MODE
#if ARDUINO_USB_CDC_ON_BOOT
//NOP
#else
#define Serial USBSerial
#endif
#endif

#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))

static const char *l_ssid;
static const struct {
  const char *ssid;
  const char *password;
} l_ssidlist[] = {
  // ここにSSID,PASSWORDを記載
  { "foo", "bar" },
};
static bool l_IpValid;
static VL53L1X vl53l1x;
static BMP280 bmp280;
static bool l_M5AtomS3;
static bool l_M5StackCoreInk;
static bool l_M5StackCore_line;
static float l_TextSize = 1.0;
static int l_CursorMulY = 1;
static bool l_VL53L1X;
static bool l_BM1422;
static bool l_IMU;
static bool l_BMP280;
static const uint8_t BM1422addr = 0x0e;
static BMM150 bmm150;
static bool l_BMM150;

static WiFiUDP c_udp[4];
static const uint16_t l_rxport = 55555;

static void setTextCursor(int32_t x, int32_t y) {
  M5.Lcd.setCursor(x, y * l_CursorMulY);
}

static bool isPushed() {
  bool push = false;
  M5.update();
  if (l_M5AtomS3) {
    if (0 < M5.BtnA.isPressed()) {
      push = true;
    }
  }
  if (l_M5StackCoreInk) {
    if (M5.BtnEXT.isPressed()) {
      push = true;
    }
  }
  if (l_M5StackCore_line) {
    if (0 < M5.Touch.getCount()) {
      push = true;
    }
  }
  return push;
}

static bool ssidlist() {
  M5.Lcd.clearDisplay();
  M5.Lcd.setTextSize(l_TextSize);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("ssid scanning");
  Serial.println("ssid scanning");
  WiFi.disconnect();
  int n = WiFi.scanNetworks();  // 6秒程度
  if (n == 0) {
    M5.Lcd.println("no networks found");
    Serial.println("no networks found");
  } else {
    int i;
    for (i = 0; i < n; i++) {
      const char *ssid = WiFi.SSID(i).c_str();
      M5.Lcd.printf("%d:%s(%d)%s", i + 1, ssid, WiFi.RSSI(i), WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? " " : "*");
      M5.Lcd.println();
      Serial.printf("%d:%s(%d)%s", i + 1, ssid, WiFi.RSSI(i), WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? " " : "*");
      Serial.println();
    }
  }
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  return 0 < n;
}

static bool ipaddress() {
  bool bOk = false;
  int i;
  for (i = 0; i < ARRAY_SIZE(l_ssidlist); i++) {
    bOk = false;
    WiFi.mode(WIFI_STA);
    WiFi.begin(l_ssidlist[i].ssid, l_ssidlist[i].password);
    int trycnt = 10;
    while (WiFi.status() != WL_CONNECTED) {
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.printf("                      ");
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.printf("%s %d ", l_ssidlist[i].ssid, trycnt);
      Serial.printf("%s %d ", l_ssidlist[i].ssid, trycnt);
      if (--trycnt <= 0) {
        break;
      }
      bool push = false;
      int j;
      for (j = 0; j < 10; j++) {
        if (isPushed()) {
          push = true;
          break;
        }
        delay(100);
      }
      if (push) {
        while (isPushed()) {
          delay(100);
        }
        trycnt = 0;
        break;
      }
    }
    bOk = 0 < trycnt;
    if (bOk) {
      l_ssid = l_ssidlist[i].ssid;
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.printf("%s OK", l_ssidlist[i].ssid);
      Serial.println("OK");
    } else {
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.printf("%s NG", l_ssidlist[i].ssid);
      Serial.println("NG");
    }
    delay(1000);
    if (bOk) {
      break;
    }
  }
  return bOk;
}

static void initWIFI() {
  ssidlist();
  l_IpValid = ipaddress();
  M5.Lcd.clearDisplay();
  M5.Lcd.setTextSize(l_TextSize);
  if (l_ssid != NULL) {
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.println(l_ssid);
    setTextCursor(0, 1);
    M5.Lcd.println(WiFi.localIP());
  }
}

static void ntp() {
  const long gmtOffset_sec = 3600 * 9;
  const int daylightOffset_sec = 0;
  const char *const server1 = "ntp.jst.mfeed.ad.jp";
  configTime(gmtOffset_sec, daylightOffset_sec, server1);
}

static void initI2C() {
  // https://lang-ship.com/blog/work/m5unified-1/#toc21
  Serial.printf("I2C Scan SDA:%d SCL:%d", M5.Ex_I2C.getSDA(), M5.Ex_I2C.getSCL());
  Serial.println();
  for (byte address = 0; address <= 127; address++) {
    Wire.beginTransmission(address);
    byte error = Wire.endTransmission();
    if (error == 0) {
      Serial.printf("%02X ", address);
    } else {
      Serial.print(".. ");
      if (address % 8 == 7) {
        Serial.println();
      }
    }
    delay(1);
  }
}

static void initVL53L1X() {
  // https://www.switch-science.com/products/9427
  // https://shop.m5stack.com/products/time-of-flight-distance-unit-vl53l1x
  // https://docs.m5stack.com/en/unit/Unit-ToF4M
  // https://docs.m5stack.com/ja/unit/Unit-ToF4M
  // https://github.com/pololu/vl53l1x-arduino
  vl53l1x.setTimeout(500);
  if (!vl53l1x.init()) {
    Serial.println("VL53L1X fail");
    return;
  }
  l_VL53L1X = true;
  // Use long distance mode and allow up to 50000 us (50 ms) for a measurement.
  // You can change these settings to adjust the performance of the sensor, but
  // the minimum timing budget is 20 ms for short distance mode and 33 ms for
  // medium and long distance modes. See the VL53L1X datasheet for more
  // information on range and timing limits.
  vl53l1x.setDistanceMode(VL53L1X::Long);
  vl53l1x.setMeasurementTimingBudget(50000);
  // Start continuous readings at a rate of one measurement every 50 ms (the
  // inter-measurement period). This period should be at least as long as the
  // timing budget.
  vl53l1x.startContinuous(50);
}

static void BM1422_write_data(uint8_t addr, uint8_t reg, uint8_t data) {
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.write(data);
  Wire.endTransmission();
}

static uint8_t BM1422_read_byte_data(uint8_t addr, uint8_t reg) {
  uint8_t data;
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(addr, 1);
  if (Wire.available() >= 1) {
    data = Wire.read();
  }
  return data;
}

static int16_t BM1422_read_word_data(uint8_t addr, uint8_t reg) {
  uint8_t data1, data2;
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(addr, 2);
  if (Wire.available() >= 2) {
    data1 = Wire.read();
    data2 = Wire.read();
  }
  return (int16_t)((data2 << 8) + data1);
}

static void initBM1422() {
  // https://www.switch-science.com/products/2777
  // https://doc.switch-science.com/media/files/9811fbe3-a6a1-4a90-80cf-c87583ddfa00.pdf
  // https://github.com/SWITCHSCIENCE/samplecodes/tree/master/Conta/2777_BM1422GMV_module
  const uint16_t info = BM1422_read_word_data(BM1422addr, 0x0d);
  const uint8_t wia = BM1422_read_byte_data(BM1422addr, 0x0f);
  if (!(info == 0x0101 && wia == 0x41)) {
    Serial.println("BM1422 fail");
    return;
  }
  l_BM1422 = true;
  BM1422_write_data(BM1422addr, 0x1b, 0x80);  // CNTL1
  delay(10);
  BM1422_write_data(BM1422addr, 0x5c, 0x00);  // CNTL4
  BM1422_write_data(BM1422addr, 0x5d, 0x00);
  delay(10);
  //BM1422_write_data(BM1422addr, 0x1c, 0x08); // CNTL2
  //delay(10);
  uint8_t wk_dat;
  uint8_t offx_dat, offy_dat, offz_dat;
  uint16_t diff_x = 9999, diff_y = 9999, diff_z = 9999;
  for (wk_dat = 1; wk_dat < 96; wk_dat++) {
    BM1422_write_data(BM1422addr, 0x6c, wk_dat);  // OFF_X
    BM1422_write_data(BM1422addr, 0x6d, 0x00);
    BM1422_write_data(BM1422addr, 0x72, wk_dat);  // OFF_Y
    BM1422_write_data(BM1422addr, 0x73, 0x00);
    BM1422_write_data(BM1422addr, 0x78, wk_dat);  // OFF_Z
    BM1422_write_data(BM1422addr, 0x79, 0x00);
    BM1422_write_data(BM1422addr, 0x1d, 0x40);  // CNTL3
    delay(10);
    uint8_t sta1 = BM1422_read_byte_data(BM1422addr, 0x18);
    while ((sta1 & 0x40) != 0x40) {
      sta1 = BM1422_read_byte_data(BM1422addr, 0x18);
    }
    int16_t datax, datay, dataz;
    datax = BM1422_read_word_data(BM1422addr, 0x10);
    delay(1);
    datay = BM1422_read_word_data(BM1422addr, 0x12);
    delay(1);
    dataz = BM1422_read_word_data(BM1422addr, 0x14);
    delay(1);
    if (abs(datax) < diff_x) {
      offx_dat = wk_dat;
      diff_x = abs(datax);
      Serial.printf("BM1422 offx %d datx %d", offx_dat, diff_x);
      Serial.println();
    }
    if (abs(datay) < diff_y) {
      offy_dat = wk_dat;
      diff_y = abs(datay);
      Serial.printf("BM1422 offy %d daty %d", offy_dat, diff_y);
      Serial.println();
    }
    if (abs(dataz) < diff_z) {
      offz_dat = wk_dat;
      diff_z = abs(dataz);
      Serial.printf("BM1422 offz %d datz %d", offz_dat, diff_z);
      Serial.println();
    }
    delay(10);
  }
  BM1422_write_data(BM1422addr, 0x6c, offx_dat);  // OFF_X
  BM1422_write_data(BM1422addr, 0x6d, 0x00);
  BM1422_write_data(BM1422addr, 0x72, offy_dat);  // OFF_Y
  BM1422_write_data(BM1422addr, 0x73, 0x00);
  BM1422_write_data(BM1422addr, 0x78, offz_dat);  // OFF_Z
  BM1422_write_data(BM1422addr, 0x79, 0x00);
  delay(10);
}

static void initIMU() {
  // nothing to do
  l_IMU = true;
}

static void initBMP280() {
  // https://www.switch-science.com/products/9426
  // https://docs.m5stack.com/en/unit/IMU%20Pro%20Mini%20Unit
  // https://docs.m5stack.com/ja/unit/IMU%20Pro%20Mini%20Unit
  // https://github.com/m5stack/M5Unit-ENV/tree/master/examples/Unit_ENV_M5AtomS3
  if (!bmp280.begin(&Wire, BMP280_I2C_ADDR, M5.Ex_I2C.getSDA(), M5.Ex_I2C.getSCL(), 400000U)) {
    Serial.println("BMP280 fail");
    return;
  }
  l_BMP280 = true;
  bmp280.setSampling(BMP280::MODE_NORMAL,     /* Operating Mode. */
                     BMP280::SAMPLING_X2,     /* Temp. oversampling */
                     BMP280::SAMPLING_X16,    /* Pressure oversampling */
                     BMP280::FILTER_X16,      /* Filtering. */
                     BMP280::STANDBY_MS_500); /* Standby time. */
}

static void initBMM150() {
  if (bmm150.initialize() == BMM150_E_ID_NOT_CONFORM) {
    Serial.println("BMM150 fail");
    return;
  }
  l_BMM150 = true;
}

void setup() {
  Serial.begin(9600);
  delay(500);
  Serial.println("HelloWorld");
  if (true) {
    auto cfg = M5.config();
    M5.begin(cfg);
  } else {
    M5.begin();
  }
  l_M5AtomS3 =
    M5.getBoard() == m5::board_t::board_M5AtomS3 || M5.getBoard() == m5::board_t::board_M5AtomS3Lite;
  l_M5StackCoreInk =
    M5.getBoard() == m5::board_t::board_M5StackCoreInk;
  l_M5StackCore_line =
    M5.getBoard() == m5::board_t::board_M5StackCoreS3SE || M5.getBoard() == m5::board_t::board_M5StackCore2;
  if (l_M5AtomS3) {
    l_TextSize = 1.0;
    l_CursorMulY = 12;
  }
  if (l_M5StackCoreInk) {
    l_TextSize = 2.0;
    l_CursorMulY = 16;
  }
  if (l_M5StackCore_line) {
    l_TextSize = 2.0;
    l_CursorMulY = 16;
  }
  M5.Lcd.begin();
  M5.Lcd.setTextWrap(false);
  initWIFI();
  ntp();
  if (true) {
    Wire.begin(M5.Ex_I2C.getSDA(), M5.Ex_I2C.getSCL(), 400000);
  }
  if (false) {
    Wire.begin();
  }
  int i;
  for (i = 0; i < ARRAY_SIZE(c_udp); i++) {
    c_udp[i].begin(l_rxport + i);
  }
  initI2C();
  initVL53L1X();
  initBM1422();
  initIMU();
  initBMP280();
  initBMM150();
}

static void PutJpg(uint16_t x, uint16_t y, uint16_t number) {
  static const unsigned char *image_data[17] = {
    image0, image1, image2, image3, image4,
    image5, image6, image7, image8, image9,
    sun, mon, tue, wed, thu, fri, sat
  };
  static const uint32_t image_size[17] = {
    sizeof image0, sizeof image1, sizeof image2, sizeof image3, sizeof image4,
    sizeof image5, sizeof image6, sizeof image7, sizeof image8, sizeof image9,
    sizeof sun, sizeof mon, sizeof tue, sizeof wed, sizeof thu, sizeof fri, sizeof sat
  };
  M5.Lcd.drawJpg(image_data[number], image_size[number], x, y);
}

static void PutNum2(uint16_t x, uint16_t y, uint16_t x_offset, uint16_t number) {
  PutJpg(x, y, number / 10);
  PutJpg(x + x_offset, y, number % 10);
}

static void runNixie(struct tm &timeinfo) {
  const int y1 = 72;
  const int y2 = 156;
  PutNum2(0, y1, 52, timeinfo.tm_mon + 1);
  PutNum2(108, y1, 52, timeinfo.tm_mday);
  PutJpg(108 * 2, y1 + 27, timeinfo.tm_wday + 10);
  M5.Lcd.setCursor(0, 136);
  PutNum2(0, y2, 52, timeinfo.tm_hour);
  PutNum2(108, y2, 52, timeinfo.tm_min);
  PutNum2(108 * 2, y2, 52, timeinfo.tm_sec);
}

static void runDateTime(struct tm &timeinfo, bool force) {
  if (l_M5AtomS3) {
    setTextCursor(0, 4);
    M5.Lcd.printf("%04d-%02d-%02d %02d:%02d:%02d",
                  timeinfo.tm_year + 1900,
                  timeinfo.tm_mon + 1,
                  timeinfo.tm_mday,
                  timeinfo.tm_hour,
                  timeinfo.tm_min,
                  timeinfo.tm_sec);
  }
  if (l_M5StackCoreInk) {
    static struct tm l_prevtimeinfo = { 0 };
    bool show = force;
    if (l_prevtimeinfo.tm_min != timeinfo.tm_min) {
      show = true;
    }
    l_prevtimeinfo = timeinfo;
    if (show) {
      setTextCursor(0, 4);
      M5.Lcd.printf("%04d-%02d-%02d %02d:%02d",
                    timeinfo.tm_year + 1900,
                    timeinfo.tm_mon + 1,
                    timeinfo.tm_mday,
                    timeinfo.tm_hour,
                    timeinfo.tm_min);
    }
  }
  if (l_M5StackCore_line) {
    runNixie(timeinfo);
  }
  Serial.printf("NTP %04d-%02d-%02d %02d:%02d:%02d",
                timeinfo.tm_year + 1900,
                timeinfo.tm_mon + 1,
                timeinfo.tm_mday,
                timeinfo.tm_hour,
                timeinfo.tm_min,
                timeinfo.tm_sec);
  const int hourtrig = 4;
  const int mintrig = 0;
  const int sectrig = 0;
  static bool hour = false;
  static bool min = false;
  static bool sec = false;
  if (timeinfo.tm_hour == hourtrig) {
    if (!hour) {
      hour = true;
    }
  } else {
    hour = false;
  }
  if (timeinfo.tm_min == mintrig) {
    if (!min) {
      min = true;
    }
  } else {
    min = false;
  }
  if (timeinfo.tm_sec == sectrig) {
    if (!sec) {
      sec = true;
      ntp();
    }
  } else {
    sec = false;
  }
}

static void runVL53L1X(char *buf_milli) {
  const int array_size = 16;
  static int l_cnt = 0;
  static uint16_t l_data[array_size] = { 0 };
  uint16_t milli = vl53l1x.readRangeContinuousMillimeters();
  if (0 < milli) {
    l_data[l_cnt++] = milli;
    l_cnt = l_cnt % array_size;
    long sum = 0;
    int i;
    for (i = 0; i < array_size; i++) {
      sum += l_data[i];
    }
    milli = sum / array_size;
    sprintf(buf_milli, "%d", milli);
  }
  Serial.printf("VL53L1X %4d %s", milli, vl53l1x.timeoutOccurred() ? "TIMEOUT" : "mm");
  setTextCursor(0, 2);
  M5.Lcd.printf("VL53L1X %4d %s", milli, vl53l1x.timeoutOccurred() ? "TIMEOUT" : "mm");
}

static void runBM1422() {
  const uint8_t sta1 = BM1422_read_byte_data(BM1422addr, 0x18);
  if ((sta1 & 0x40) == 0x40) {
    int16_t X, Y, Z;
    X = BM1422_read_word_data(BM1422addr, 0x10);
    delay(1);
    Y = BM1422_read_word_data(BM1422addr, 0x12);
    delay(1);
    Z = BM1422_read_word_data(BM1422addr, 0x14);
    Serial.printf("BM1422 X %d Y %d Z %d", X, Y, Z);
  }
}

static void runIMU() {
  // https://lang-ship.com/blog/work/m5unified-1/#toc16
  float ax, ay, az;
  float gx, gy, gz;
  float mx, my, mz;
  if (M5.Imu.getAccel(&ax, &ay, &az)) {
    Serial.printf("IMU Accel X %6.1f Y %6.1f Z %6.1f", ax, ay, az);
  } else {
    Serial.print("IMU Accel fail                      ");
  }
  if (M5.Imu.getGyro(&gx, &gy, &gz)) {
    Serial.printf(" Gyro X %6.1f Y %6.1f Z %6.1f", gx, gy, gz);
  } else {
    Serial.print(" Gyro fail                      ");
  }
  if (false) {
    if (M5.Imu.getMag(&mx, &my, &mz)) {
      Serial.printf(" Mag X %6.1f Y %6.1f Z %6.1f", mx, my, mz);
    } else {
      Serial.print(" Mag fail                      ");
    }
  }
}

static void runBMP280() {
  if (bmp280.update()) {
    Serial.printf("BMP280 %4.1f [deg] %5.0f [hPa] %3.0f [m]",
                  bmp280.cTemp, bmp280.pressure / 100.0, bmp280.altitude);
  }
}

static void runBMM150(char *buf_deg) {
  // Grove_3_Axis_Compass_V2.0_BMM150\examples\compass\compass.ino
  // DFRobot_BMM150\DFRobot_BMM150.cpp float getCompassDegree(void);
  // 同じ実装
  bmm150_mag_data value;
  bmm150.read_mag_data();
  value.x = bmm150.raw_mag_data.raw_datax;
  value.y = bmm150.raw_mag_data.raw_datay;
  float heading = atan2(value.x, value.y);
  if (heading < 0) {
    heading += 2 * PI;
  }
  if (heading > 2 * PI) {
    heading -= 2 * PI;
  }
  heading = heading * 180 / M_PI;
  sprintf(buf_deg, "%.0f", heading);
  Serial.printf("BMM150 %3d deg", (int)heading);
  setTextCursor(0, 3);
  M5.Lcd.printf("BMM150 %3d deg", (int)heading);
}

void loop() {
  static bool l_bShow = false;
  static int l_repeat = 0;
  static char buf_milli[20];
  static char buf_deg[20];
  static int l_localtime = -1;
  {
    const bool push = isPushed();
    if (push) {
      if (++l_repeat == 5) {
        l_bShow = !l_bShow;
      }
    } else {
      l_repeat = 0;
    }
    if (l_IpValid) {
      if (l_bShow) {
        struct tm timeinfo;
        bool ok = getLocalTime(&timeinfo, 1000);
        if (ok) {
          runDateTime(timeinfo, push);
          Serial.print(" ");
        } else {
          setTextCursor(0, 4);
          M5.Lcd.printf("NTP fail            ");
          Serial.print("NTP fail ");
        }
      } else {
        setTextCursor(0, 4);
        M5.Lcd.printf("NTP skip            ");
        Serial.print("NTP skip ");
      }
    }
    if (true) {
      strcpy(buf_milli, "-1");
      if (l_VL53L1X) {
        runVL53L1X(buf_milli);
        Serial.print(" ");
      }
      if (false && l_BM1422) {
        runBM1422();
        Serial.print(" ");
      }
      if (false && l_IMU) {
        runIMU();
        Serial.print(" ");
      }
      if (false && l_BMP280) {
        runBMP280();
        Serial.print(" ");
      }
      strcpy(buf_deg, "-1");
      if (l_BMM150) {
        runBMM150(buf_deg);
        Serial.print(" ");
      }
      Serial.println();
    }
    delay(100);
  }
  if (l_IpValid) {
    int i;
    for (i = 0; i < ARRAY_SIZE(c_udp); i++) {
      const int len = c_udp[i].parsePacket();
      if (0 < len) {
        char recvbuf[80];
        IPAddress addr = c_udp[i].remoteIP();
        const uint16_t port = c_udp[i].remotePort();
        const int rd = c_udp[i].read((uint8_t *)recvbuf, sizeof(recvbuf));
        if (0 < rd) {
          recvbuf[rd] = '\0';
          Serial.printf("udprecv%d ", i);
          Serial.print(addr);
          Serial.printf(":%d %d\r\n", port, rd);
          char sendbuf[80];
          sprintf(sendbuf, "%s,%s", buf_deg, buf_milli);
          const int len = strlen(sendbuf) + 1;
          const int bgn = c_udp[i].beginPacket(addr, l_rxport + i);
          const size_t wr = c_udp[i].write((const uint8_t *)sendbuf, len);
          const int end = c_udp[i].endPacket();
          Serial.printf("udpsend%d ", i);
          Serial.print(addr);
          Serial.printf(":%d %d\r\n", port, len);
        }
      }
    }
  }
}
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?