mirror of
https://github.com/meshtastic/firmware.git
synced 2025-10-29 15:46:46 +00:00
Added two screens for QMC6310 and QMI8658 data
This commit is contained in:
parent
8dbb4597e6
commit
162ab54a16
@ -1015,6 +1015,15 @@ void Screen::setFrames(FrameFocus focus)
|
|||||||
normalFrames[numframes++] = graphics::UIRenderer::drawCompassAndLocationScreen;
|
normalFrames[numframes++] = graphics::UIRenderer::drawCompassAndLocationScreen;
|
||||||
indicatorIcons.push_back(icon_compass);
|
indicatorIcons.push_back(icon_compass);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
// After GPS, add QMC6310 and QMI8658 debug screens
|
||||||
|
#if !MESHTASTIC_EXCLUDE_I2C
|
||||||
|
normalFrames[numframes++] = graphics::DebugRenderer::drawQMC6310Screen;
|
||||||
|
indicatorIcons.push_back(icon_compass);
|
||||||
|
#endif
|
||||||
|
#if defined(IMU_CS)
|
||||||
|
normalFrames[numframes++] = graphics::DebugRenderer::drawQMI8658Screen;
|
||||||
|
indicatorIcons.push_back(icon_system);
|
||||||
#endif
|
#endif
|
||||||
if (RadioLibInterface::instance && !hiddenFrames.lora) {
|
if (RadioLibInterface::instance && !hiddenFrames.lora) {
|
||||||
fsi.positions.lora = numframes;
|
fsi.positions.lora = numframes;
|
||||||
|
|||||||
@ -30,6 +30,8 @@
|
|||||||
#include <DisplayFormatters.h>
|
#include <DisplayFormatters.h>
|
||||||
#include <RadioLibInterface.h>
|
#include <RadioLibInterface.h>
|
||||||
#include <target_specific.h>
|
#include <target_specific.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "motion/SensorLiveData.h"
|
||||||
|
|
||||||
using namespace meshtastic;
|
using namespace meshtastic;
|
||||||
|
|
||||||
@ -693,6 +695,48 @@ void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int1
|
|||||||
display->drawString(textX, getTextPositions(display)[line++], "World!");
|
display->drawString(textX, getTextPositions(display)[line++], "World!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------- Additional IMU/Magnetometer debug screens ----------------
|
||||||
|
void drawQMC6310Screen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
static uint32_t last = 0;
|
||||||
|
display->clear();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
graphics::drawCommonHeader(display, x, y, "QMC6310");
|
||||||
|
int line = 1;
|
||||||
|
if (g_qmc6310Live.initialized) {
|
||||||
|
if (!Throttle::isWithinTimespanMs(last, 1000)) {
|
||||||
|
last = millis();
|
||||||
|
char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "Head %3.0f offX %.0f offY %.0f", g_qmc6310Live.heading, g_qmc6310Live.offX,
|
||||||
|
g_qmc6310Live.offY);
|
||||||
|
display->drawString(x, getTextPositions(display)[line++], buf);
|
||||||
|
snprintf(buf, sizeof(buf), "rawX %d rawY %d", g_qmc6310Live.rawX, g_qmc6310Live.rawY);
|
||||||
|
display->drawString(x, getTextPositions(display)[line++], buf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
display->drawString(x, getTextPositions(display)[line++], "No data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawQMI8658Screen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
(void)state; (void)x; (void)y;
|
||||||
|
display->clear();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
graphics::drawCommonHeader(display, x, y, "QMI8658");
|
||||||
|
int line = 1;
|
||||||
|
if (g_qmi8658Live.initialized) {
|
||||||
|
char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "ACC %.2f %.2f %.2f", g_qmi8658Live.acc.x, g_qmi8658Live.acc.y, g_qmi8658Live.acc.z);
|
||||||
|
display->drawString(x, getTextPositions(display)[line++], buf);
|
||||||
|
snprintf(buf, sizeof(buf), "GYR %.2f %.2f %.2f", g_qmi8658Live.gyr.x, g_qmi8658Live.gyr.y, g_qmi8658Live.gyr.z);
|
||||||
|
display->drawString(x, getTextPositions(display)[line++], buf);
|
||||||
|
} else {
|
||||||
|
display->drawString(x, getTextPositions(display)[line++], "No data");
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace DebugRenderer
|
} // namespace DebugRenderer
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#endif
|
#endif
|
||||||
@ -36,6 +36,9 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
|
|
||||||
// Chirpy screen display
|
// Chirpy screen display
|
||||||
void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
|
// IMU/Magnetometer debug screens
|
||||||
|
void drawQMI8658Screen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
|
void drawQMC6310Screen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
} // namespace DebugRenderer
|
} // namespace DebugRenderer
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "QMC6310Sensor.h"
|
#include "QMC6310Sensor.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "SensorLiveData.h"
|
||||||
|
|
||||||
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<SensorQMC6310.hpp>)
|
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<SensorQMC6310.hpp>)
|
||||||
|
|
||||||
@ -54,9 +55,18 @@ int32_t QMC6310Sensor::runOnce()
|
|||||||
int16_t ry = sensor.getRawY();
|
int16_t ry = sensor.getRawY();
|
||||||
int16_t rz = sensor.getRawZ();
|
int16_t rz = sensor.getRawZ();
|
||||||
|
|
||||||
if (rx < minX) minX = rx; if (rx > maxX) maxX = rx;
|
if (rx < minX)
|
||||||
if (ry < minY) minY = ry; if (ry > maxY) maxY = ry;
|
minX = rx;
|
||||||
if (rz < minZ) minZ = rz; if (rz > maxZ) maxZ = rz;
|
if (rx > maxX)
|
||||||
|
maxX = rx;
|
||||||
|
if (ry < minY)
|
||||||
|
minY = ry;
|
||||||
|
if (ry > maxY)
|
||||||
|
maxY = ry;
|
||||||
|
if (rz < minZ)
|
||||||
|
minZ = rz;
|
||||||
|
if (rz > maxZ)
|
||||||
|
maxZ = rz;
|
||||||
|
|
||||||
offsetX = (maxX + minX) * 0.5f;
|
offsetX = (maxX + minX) * 0.5f;
|
||||||
offsetY = (maxY + minY) * 0.5f;
|
offsetY = (maxY + minY) * 0.5f;
|
||||||
@ -71,6 +81,16 @@ int32_t QMC6310Sensor::runOnce()
|
|||||||
while (heading < 0.0f) heading += 360.0f;
|
while (heading < 0.0f) heading += 360.0f;
|
||||||
while (heading >= 360.0f) heading -= 360.0f;
|
while (heading >= 360.0f) heading -= 360.0f;
|
||||||
|
|
||||||
|
g_qmc6310Live.initialized = true;
|
||||||
|
g_qmc6310Live.rawX = rx;
|
||||||
|
g_qmc6310Live.rawY = ry;
|
||||||
|
g_qmc6310Live.rawZ = rz;
|
||||||
|
g_qmc6310Live.offX = offsetX;
|
||||||
|
g_qmc6310Live.offY = offsetY;
|
||||||
|
g_qmc6310Live.offZ = offsetZ;
|
||||||
|
g_qmc6310Live.heading = heading;
|
||||||
|
g_qmc6310Live.last_ms = millis();
|
||||||
|
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
|
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
|
||||||
switch (config.display.compass_orientation) {
|
switch (config.display.compass_orientation) {
|
||||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "QMI8658Sensor.h"
|
#include "QMI8658Sensor.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
|
#include "SensorLiveData.h"
|
||||||
|
|
||||||
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<SensorQMI8658.hpp>)
|
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<SensorQMI8658.hpp>)
|
||||||
|
|
||||||
@ -46,7 +47,8 @@ bool QMI8658Sensor::init()
|
|||||||
uint8_t id = qmi.getChipID();
|
uint8_t id = qmi.getChipID();
|
||||||
LOG_DEBUG("QMI8658: chip id=0x%02x", id);
|
LOG_DEBUG("QMI8658: chip id=0x%02x", id);
|
||||||
#ifdef QMI8658_DEBUG_STREAM
|
#ifdef QMI8658_DEBUG_STREAM
|
||||||
LOG_INFO("QMI8658 debug stream enabled (10 Hz)");
|
LOG_INFO("QMI8658 debug stream enabled (1 Hz)");
|
||||||
|
lastLogMs = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Basic configuration similar to lewisxhe examples
|
// Basic configuration similar to lewisxhe examples
|
||||||
@ -78,21 +80,35 @@ bool QMI8658Sensor::init()
|
|||||||
LOG_DEBUG("QMI8658: dump control registers ->");
|
LOG_DEBUG("QMI8658: dump control registers ->");
|
||||||
qmi.dumpCtrlRegister();
|
qmi.dumpCtrlRegister();
|
||||||
LOG_DEBUG("QMI8658: init ok");
|
LOG_DEBUG("QMI8658: init ok");
|
||||||
|
g_qmi8658Live.initialized = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t QMI8658Sensor::runOnce()
|
int32_t QMI8658Sensor::runOnce()
|
||||||
{
|
{
|
||||||
#ifdef QMI8658_DEBUG_STREAM
|
#ifdef QMI8658_DEBUG_STREAM
|
||||||
// Always sample/log when debug stream is enabled
|
// Always sample/log when debug stream is enabled (throttle to ~1 Hz)
|
||||||
IMUdata acc = {0};
|
IMUdata acc = {0};
|
||||||
IMUdata gyr = {0};
|
IMUdata gyr = {0};
|
||||||
bool ready = qmi.getDataReady();
|
bool ready = qmi.getDataReady();
|
||||||
bool gotAcc = qmi.getAccelerometer(acc.x, acc.y, acc.z);
|
qmi.getAccelerometer(acc.x, acc.y, acc.z);
|
||||||
bool gotGyr = qmi.getGyroscope(gyr.x, gyr.y, gyr.z);
|
qmi.getGyroscope(gyr.x, gyr.y, gyr.z);
|
||||||
LOG_DEBUG("QMI8658: ready=%d ACC[x=%.3f y=%.3f z=%.3f] m/s^2 GYR[x=%.3f y=%.3f z=%.3f] dps",
|
|
||||||
(int)ready, acc.x, acc.y, acc.z, gyr.x, gyr.y, gyr.z);
|
uint32_t now = millis();
|
||||||
return 100; // ~10 Hz
|
g_qmi8658Live.ready = ready;
|
||||||
|
g_qmi8658Live.acc.x = acc.x;
|
||||||
|
g_qmi8658Live.acc.y = acc.y;
|
||||||
|
g_qmi8658Live.acc.z = acc.z;
|
||||||
|
g_qmi8658Live.gyr.x = gyr.x;
|
||||||
|
g_qmi8658Live.gyr.y = gyr.y;
|
||||||
|
g_qmi8658Live.gyr.z = gyr.z;
|
||||||
|
g_qmi8658Live.last_ms = now;
|
||||||
|
if (now - lastLogMs > 1000) {
|
||||||
|
lastLogMs = now;
|
||||||
|
LOG_DEBUG("QMI8658: ready=%d ACC[x=%.3f y=%.3f z=%.3f] m/s^2 GYR[x=%.3f y=%.3f z=%.3f] dps",
|
||||||
|
(int)ready, acc.x, acc.y, acc.z, gyr.x, gyr.y, gyr.z);
|
||||||
|
}
|
||||||
|
return MOTION_SENSOR_CHECK_INTERVAL_MS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!config.display.wake_on_tap_or_motion)
|
if (!config.display.wake_on_tap_or_motion)
|
||||||
|
|||||||
@ -13,6 +13,7 @@ class QMI8658Sensor : public MotionSensor
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SensorQMI8658 qmi;
|
SensorQMI8658 qmi;
|
||||||
|
uint32_t lastLogMs = 0;
|
||||||
|
|
||||||
// Simple motion threshold in Gs above steady 1g
|
// Simple motion threshold in Gs above steady 1g
|
||||||
static constexpr float MOTION_THRESHOLD_G = 0.15f; // ~0.15 g
|
static constexpr float MOTION_THRESHOLD_G = 0.15f; // ~0.15 g
|
||||||
|
|||||||
5
src/motion/SensorLiveData.cpp
Normal file
5
src/motion/SensorLiveData.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "SensorLiveData.h"
|
||||||
|
|
||||||
|
QMI8658LiveData g_qmi8658Live;
|
||||||
|
QMC6310LiveData g_qmc6310Live;
|
||||||
|
|
||||||
29
src/motion/SensorLiveData.h
Normal file
29
src/motion/SensorLiveData.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct Vec3f {
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
float z = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QMI8658LiveData {
|
||||||
|
bool initialized = false;
|
||||||
|
bool ready = false;
|
||||||
|
Vec3f acc; // m/s^2
|
||||||
|
Vec3f gyr; // dps
|
||||||
|
uint32_t last_ms = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QMC6310LiveData {
|
||||||
|
bool initialized = false;
|
||||||
|
int16_t rawX = 0, rawY = 0, rawZ = 0;
|
||||||
|
float offX = 0, offY = 0, offZ = 0;
|
||||||
|
float heading = 0; // degrees 0..360
|
||||||
|
uint32_t last_ms = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern QMI8658LiveData g_qmi8658Live;
|
||||||
|
extern QMC6310LiveData g_qmc6310Live;
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user