safety, before implementing 22_compass
This commit is contained in:
parent
1d0a29f2a3
commit
d9c270c28f
3 changed files with 280 additions and 0 deletions
1
exercises/11_Set_RTC2GPS/.gitignore
vendored
Normal file
1
exercises/11_Set_RTC2GPS/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
exercises/11_Set_RTC2GPS/*.log
|
||||||
76
exercises/21_six_axis/platformio.ini
Normal file
76
exercises/21_six_axis/platformio.ini
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
; 20260414 ChatGPT
|
||||||
|
; Exercise 21_six_axis
|
||||||
|
|
||||||
|
[platformio]
|
||||||
|
default_envs = guy
|
||||||
|
|
||||||
|
[env]
|
||||||
|
platform = espressif32
|
||||||
|
framework = arduino
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
board_build.partitions = default_8MB.csv
|
||||||
|
monitor_speed = 115200
|
||||||
|
lib_deps =
|
||||||
|
Wire
|
||||||
|
olikraus/U8g2@^2.36.4
|
||||||
|
lewisxhe/XPowersLib@0.3.3
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
-I ../../shared/boards
|
||||||
|
-I ../../external/microReticulum_Firmware
|
||||||
|
-I /usr/local/src/LilyGo-LoRa-Series/lib/SensorLib/src
|
||||||
|
-D BOARD_MODEL=BOARD_TBEAM_S_V1
|
||||||
|
-D ARDUINO_USB_MODE=1
|
||||||
|
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
-D OLED_SDA=17
|
||||||
|
-D OLED_SCL=18
|
||||||
|
-D OLED_ADDR=0x3C
|
||||||
|
|
||||||
|
[env:amy]
|
||||||
|
extends = env
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-D BOARD_ID=\"AMY\"
|
||||||
|
-D NODE_LABEL=\"Amy\"
|
||||||
|
|
||||||
|
[env:bob]
|
||||||
|
extends = env
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-D BOARD_ID=\"BOB\"
|
||||||
|
-D NODE_LABEL=\"Bob\"
|
||||||
|
|
||||||
|
[env:cy]
|
||||||
|
extends = env
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-D BOARD_ID=\"CY\"
|
||||||
|
-D NODE_LABEL=\"Cy\"
|
||||||
|
|
||||||
|
[env:dan]
|
||||||
|
extends = env
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-D BOARD_ID=\"DAN\"
|
||||||
|
-D NODE_LABEL=\"Dan\"
|
||||||
|
|
||||||
|
[env:ed]
|
||||||
|
extends = env
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-D BOARD_ID=\"ED\"
|
||||||
|
-D NODE_LABEL=\"Ed\"
|
||||||
|
|
||||||
|
[env:flo]
|
||||||
|
extends = env
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-D BOARD_ID=\"FLO\"
|
||||||
|
-D NODE_LABEL=\"Flo\"
|
||||||
|
|
||||||
|
[env:guy]
|
||||||
|
extends = env
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-D BOARD_ID=\"GUY\"
|
||||||
|
-D NODE_LABEL=\"Guy\"
|
||||||
203
exercises/21_six_axis/src/main.cpp
Normal file
203
exercises/21_six_axis/src/main.cpp
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <U8g2lib.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <XPowersLib.h>
|
||||||
|
|
||||||
|
#include "Boards.h"
|
||||||
|
#include "SensorQMI8658.hpp"
|
||||||
|
#include "tbeam_supreme_adapter.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr uint32_t kUiUpdateIntervalMs = 100;
|
||||||
|
constexpr uint32_t kSplashDelayMs = 1200;
|
||||||
|
|
||||||
|
U8G2_SH1106_128X64_NONAME_F_HW_I2C g_oled(U8G2_R0, U8X8_PIN_NONE);
|
||||||
|
XPowersLibInterface* g_pmu = nullptr;
|
||||||
|
SensorQMI8658 g_qmi;
|
||||||
|
IMUdata g_accel{0.0f, 0.0f, 0.0f};
|
||||||
|
IMUdata g_gyro{0.0f, 0.0f, 0.0f};
|
||||||
|
|
||||||
|
bool g_sensorReady = false;
|
||||||
|
bool g_displayReady = false;
|
||||||
|
|
||||||
|
uint32_t g_lastUiUpdateMs = 0;
|
||||||
|
uint32_t g_lastSampleMicros = 0;
|
||||||
|
float g_lastSamplePeriodMs = 0.0f;
|
||||||
|
uint32_t g_sampleCount = 0;
|
||||||
|
float g_temperatureC = 0.0f;
|
||||||
|
uint32_t g_sensorTimestamp = 0;
|
||||||
|
|
||||||
|
void initDisplay() {
|
||||||
|
Wire.begin(OLED_SDA, OLED_SCL);
|
||||||
|
g_oled.begin();
|
||||||
|
g_oled.setI2CAddress(OLED_ADDR << 1);
|
||||||
|
g_oled.setBusClock(400000);
|
||||||
|
g_oled.clearBuffer();
|
||||||
|
g_oled.setFont(u8g2_font_6x10_tf);
|
||||||
|
g_oled.drawStr(0, 12, "Exercise 21");
|
||||||
|
g_oled.drawStr(0, 28, "QMI8658 Six-Axis");
|
||||||
|
g_oled.drawStr(0, 44, "Starting...");
|
||||||
|
g_oled.sendBuffer();
|
||||||
|
g_displayReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initImu() {
|
||||||
|
pinMode(SD_CS, OUTPUT);
|
||||||
|
digitalWrite(SD_CS, HIGH);
|
||||||
|
|
||||||
|
SPI.begin(SD_CLK, SD_MISO, SD_MOSI, IMU_CS);
|
||||||
|
|
||||||
|
if (!g_qmi.begin(SPI, IMU_CS, SD_MOSI, SD_MISO, SD_CLK)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_qmi.configAccelerometer(
|
||||||
|
SensorQMI8658::ACC_RANGE_4G,
|
||||||
|
SensorQMI8658::ACC_ODR_250Hz,
|
||||||
|
SensorQMI8658::LPF_MODE_1);
|
||||||
|
|
||||||
|
g_qmi.configGyroscope(
|
||||||
|
SensorQMI8658::GYR_RANGE_256DPS,
|
||||||
|
SensorQMI8658::GYR_ODR_224_2Hz,
|
||||||
|
SensorQMI8658::LPF_MODE_3);
|
||||||
|
|
||||||
|
g_qmi.enableGyroscope();
|
||||||
|
g_qmi.enableAccelerometer();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawStatus(const char* line1, const char* line2 = nullptr, const char* line3 = nullptr) {
|
||||||
|
if (!g_displayReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_oled.clearBuffer();
|
||||||
|
g_oled.setFont(u8g2_font_6x10_tf);
|
||||||
|
g_oled.drawStr(0, 12, line1);
|
||||||
|
if (line2) g_oled.drawStr(0, 28, line2);
|
||||||
|
if (line3) g_oled.drawStr(0, 44, line3);
|
||||||
|
g_oled.sendBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sampleImu() {
|
||||||
|
if (!g_sensorReady || !g_qmi.getDataReady()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_qmi.getAccelerometer(g_accel.x, g_accel.y, g_accel.z)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!g_qmi.getGyroscope(g_gyro.x, g_gyro.y, g_gyro.z)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t nowMicros = micros();
|
||||||
|
if (g_lastSampleMicros != 0) {
|
||||||
|
g_lastSamplePeriodMs = (nowMicros - g_lastSampleMicros) / 1000.0f;
|
||||||
|
}
|
||||||
|
g_lastSampleMicros = nowMicros;
|
||||||
|
|
||||||
|
g_temperatureC = g_qmi.getTemperature_C();
|
||||||
|
g_sensorTimestamp = g_qmi.getTimestamp();
|
||||||
|
++g_sampleCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printSerialFrame() {
|
||||||
|
Serial.printf(
|
||||||
|
"sample=%lu dt=%.1fms ts=%lu temp=%.2fC "
|
||||||
|
"acc[g]={%.4f,%.4f,%.4f} gyro[dps]={%.3f,%.3f,%.3f}\r\n",
|
||||||
|
static_cast<unsigned long>(g_sampleCount),
|
||||||
|
g_lastSamplePeriodMs,
|
||||||
|
static_cast<unsigned long>(g_sensorTimestamp),
|
||||||
|
g_temperatureC,
|
||||||
|
g_accel.x,
|
||||||
|
g_accel.y,
|
||||||
|
g_accel.z,
|
||||||
|
g_gyro.x,
|
||||||
|
g_gyro.y,
|
||||||
|
g_gyro.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawFrame() {
|
||||||
|
if (!g_displayReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char line[32];
|
||||||
|
|
||||||
|
g_oled.clearBuffer();
|
||||||
|
g_oled.setFont(u8g2_font_5x8_tf);
|
||||||
|
|
||||||
|
snprintf(line, sizeof(line), "QMI8658 %s", NODE_LABEL);
|
||||||
|
g_oled.drawStr(0, 8, line);
|
||||||
|
|
||||||
|
snprintf(line, sizeof(line), "A X:% .3f", g_accel.x);
|
||||||
|
g_oled.drawStr(0, 16, line);
|
||||||
|
snprintf(line, sizeof(line), "A Y:% .3f", g_accel.y);
|
||||||
|
g_oled.drawStr(64, 16, line);
|
||||||
|
|
||||||
|
snprintf(line, sizeof(line), "A Z:% .3f", g_accel.z);
|
||||||
|
g_oled.drawStr(0, 24, line);
|
||||||
|
|
||||||
|
snprintf(line, sizeof(line), "G X:% .1f", g_gyro.x);
|
||||||
|
g_oled.drawStr(0, 36, line);
|
||||||
|
snprintf(line, sizeof(line), "G Y:% .1f", g_gyro.y);
|
||||||
|
g_oled.drawStr(64, 36, line);
|
||||||
|
|
||||||
|
snprintf(line, sizeof(line), "G Z:% .1f", g_gyro.z);
|
||||||
|
g_oled.drawStr(0, 44, line);
|
||||||
|
|
||||||
|
snprintf(line, sizeof(line), "T:%5.2fC", g_temperatureC);
|
||||||
|
g_oled.drawStr(0, 56, line);
|
||||||
|
snprintf(line, sizeof(line), "dt:%4.1f", g_lastSamplePeriodMs);
|
||||||
|
g_oled.drawStr(60, 56, line);
|
||||||
|
snprintf(line, sizeof(line), "N:%lu", static_cast<unsigned long>(g_sampleCount));
|
||||||
|
g_oled.drawStr(96, 56, line);
|
||||||
|
|
||||||
|
g_oled.sendBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
tbeam_supreme::initPmuForPeripherals(g_pmu, &Serial);
|
||||||
|
initDisplay();
|
||||||
|
|
||||||
|
drawStatus("Exercise 21", "QMI8658 live view", "Init IMU...");
|
||||||
|
|
||||||
|
g_sensorReady = initImu();
|
||||||
|
if (!g_sensorReady) {
|
||||||
|
Serial.println("QMI8658 init failed");
|
||||||
|
drawStatus("QMI8658 init", "FAILED", "Check wiring/power");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("QMI8658 device ID: 0x%02X\r\n", g_qmi.getChipID());
|
||||||
|
Serial.println("Streaming raw accel[g], gyro[dps], temp[C]");
|
||||||
|
Serial.println("UI refresh: 100 ms, sensor ODR: accel 250 Hz, gyro 224.2 Hz");
|
||||||
|
|
||||||
|
drawStatus("QMI8658 ready", "Serial + OLED live", "Move the device");
|
||||||
|
delay(kSplashDelayMs);
|
||||||
|
g_lastUiUpdateMs = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
sampleImu();
|
||||||
|
|
||||||
|
const uint32_t now = millis();
|
||||||
|
if (now - g_lastUiUpdateMs < kUiUpdateIntervalMs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_lastUiUpdateMs = now;
|
||||||
|
|
||||||
|
if (!g_sensorReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printSerialFrame();
|
||||||
|
drawFrame();
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue