Машинное обучение на Arduino Nano RP2040
imu
arduino-nano-rp2040
Я пытаюсь использовать Arduino Nano RP2040 для распознавания жестов с помощью IMU. Эта плата поддерживает основные функции машинного обучения, предоставляемые LSM6DSOX.
Я протестировал пример, предоставленный производителем, и все работает нормально . Теперь я хочу создать новую модель машинного обучения для распознавания пользовательских жестов.
Я нашел это руководство по STM, которое очень полезно, но я не могу найти код представлено в 5:48, чтобы записывать движения.
Кто-нибудь знает, где я могу найти весь код или как мне это сделать?
@Adrian, 👍0
1 ответ
Лучший ответ:
▲ 0
Отвечаю на вопрос сам, для тех, у кого такая же проблема, как и у меня.
Исходный код
#include "PluggableUSBMSD.h"
#include "FlashIAPBlockDevice.h"
#include "WiFiNINA.h"
#include "LSM6DSOXSensor.h"
#define INT_1 INT_IMU
#define SENSOR_ODR 104.0f // В герцах
#define ACC_FS 2 // В g
#define GYR_FS 2000 // В дпс
#define MEASUREMENT_TIME_INTERVAL (1000.0f/SENSOR_ODR) // В мс
#define FIFO_SAMPLE_THRESHOLD 199
#define FLASH_BUFF_LEN 8192
typedef enum {
DATA_STORAGE_STATE,
DATA_LOGGER_IDLE_STATE,
DATA_LOGGER_RUNNING_STATE
} demo_state_e;
volatile demo_state_e demo_state = DATA_STORAGE_STATE;
volatile int mems_event = 0;
uint32_t file_count = 0;
unsigned long timestamp_count = 0;
bool acc_available = false;
bool gyr_available = false;
int32_t acc_value[3];
int32_t gyr_value[3];
char buff[FLASH_BUFF_LEN];
uint32_t pos = 0;
static FlashIAPBlockDevice bd(XIP_BASE + 0x100000, 0x100000);
LSM6DSOXSensor AccGyr(&Wire, LSM6DSOX_I2C_ADD_L);
USBMSD MassStorage(&bd);
rtos::Thread acquisition_th;
FILE *f = nullptr;
void INT1Event_cb()
{
mems_event = 1;
}
void USBMSD::begin()
{
int err = getFileSystem().mount(&bd);
if (err) {
err = getFileSystem().reformat(&bd);
}
}
mbed::FATFileSystem &USBMSD::getFileSystem()
{
static mbed::FATFileSystem fs("fs");
return fs;
}
void led_green_thd()
{
while (1) {
if (demo_state == DATA_LOGGER_RUNNING_STATE) {
digitalWrite(LEDG, HIGH);
delay(100);
digitalWrite(LEDG, LOW);
delay(100);
}
}
}
void Read_FIFO_Data(uint16_t samples_to_read)
{
uint16_t i;
for (i = 0; i < samples_to_read; i++) {
uint8_t tag;
// Проверяем тег FIFO
AccGyr.Get_FIFO_Tag(&tag);
switch (tag) {
// Если у нас есть тег гироскопа, читаем данные гироскопа
case LSM6DSOX_GYRO_NC_TAG: {
AccGyr.Get_FIFO_G_Axes(gyr_value);
gyr_available = true;
break;
}
// Если у нас есть тег аккаунта, читаем данные аккаунта
case LSM6DSOX_XL_NC_TAG: {
AccGyr.Get_FIFO_X_Axes(acc_value);
acc_available = true;
break;
}
// Мы можем отбросить другие теги
default: {
break;
}
}
// Если у нас есть измерения акселератора и гироскопа, мы можем сохранить их с меткой времени
if (acc_available && gyr_available) {
int num_bytes;
num_bytes = snprintf(&buff[pos], (FLASH_BUFF_LEN - pos), "%lu %d %d %d %d %d %d\n", (unsigned long)((float)timestamp_count * MEASUREMENT_TIME_INTERVAL), (int)acc_value[0], (int)acc_value[1], (int)acc_value[2], (int)gyr_value[0], (int)gyr_value[1], (int)gyr_value[2]);
pos += num_bytes;
timestamp_count++;
acc_available = false;
gyr_available = false;
}
}
// Мы можем добавить в строку символ завершения, чтобы мы могли сохранить ее во флэш-памяти
buff[pos] = '\0';
pos = 0;
}
void setup()
{
Serial.begin(115200);
MassStorage.begin();
pinMode(LEDB, OUTPUT);
pinMode(LEDG, OUTPUT);
digitalWrite(LEDB, LOW);
digitalWrite(LEDG, LOW);
// Инициализируем шину I2C.
Wire.begin();
Wire.setClock(400000);
//Прерывания.
attachInterrupt(INT_1, INT1Event_cb, RISING);
// Инициализируем IMU.
AccGyr.begin();
AccGyr.Enable_X();
AccGyr.Enable_G();
// Настраиваем ODR и FS акселератора и гироскопа
AccGyr.Set_X_ODR(SENSOR_ODR);
AccGyr.Set_X_FS(ACC_FS);
AccGyr.Set_G_ODR(SENSOR_ODR);
AccGyr.Set_G_FS(GYR_FS);
// Включаем событие двойного касания
AccGyr.Enable_Double_Tap_Detection(LSM6DSOX_INT1_PIN);
// Настраиваем FIFO BDR для акк и гироскопа
AccGyr.Set_FIFO_X_BDR(SENSOR_ODR);
AccGyr.Set_FIFO_G_BDR(SENSOR_ODR);
// Запускаем поток мигания светодиодом
acquisition_th.start(led_green_thd);
}
void loop()
{
if (mems_event) {
mems_event = 0;
LSM6DSOX_Event_Status_t status;
AccGyr.Get_X_Event_Status(&status);
if (status.DoubleTapStatus) {
switch (demo_state) {
case DATA_STORAGE_STATE: {
// Переходим в состояние DATA_LOGGER_IDLE_STATE
demo_state = DATA_LOGGER_IDLE_STATE;
digitalWrite(LEDG, HIGH);
Serial.println("From DATA_STORAGE_STATE To DATA_LOGGER_IDLE_STATE");
break;
}
case DATA_LOGGER_IDLE_STATE: {
char filename[32];
// Переход в состояние DATA_LOGGER_RUNNING_STATE
snprintf(filename, 32, "/fs/data_%lu.txt", file_count);
Serial.print("Start writing file ");
Serial.println(filename);
// открываем файл для записи данных
// w+ означает перезапись, поэтому при каждой перезагрузке платы файл будет перезаписываться
f = fopen(filename, "w+");
if (f != nullptr) {
// пишем заголовок
fprintf(f, "Timestamp[ms] A_X [mg] A_Y [mg] A_Z [mg] G_X [mdps] G_Y [mdps] G_Z [mdps]\n");
fflush(f);
Serial.println("From DATA_LOGGER_IDLE_STATE To DATA_LOGGER_RUNNING_STATE");
demo_state = DATA_LOGGER_RUNNING_STATE;
digitalWrite(LEDG, LOW);
timestamp_count = 0;
pos = 0;
acc_available = false;
gyr_available = false;
// Устанавливаем FIFO в непрерывный режим
AccGyr.Set_FIFO_Mode(LSM6DSOX_STREAM_MODE);
}
break;
}
case DATA_LOGGER_RUNNING_STATE: {
// Очищаем FIFO
uint16_t fifo_samples;
AccGyr.Get_FIFO_Num_Samples(&fifo_samples);
Read_FIFO_Data(fifo_samples);
// Сохраняем строку во флэш-памяти
fprintf(f, "%s", buff);
fflush(f);
// Закрываем файл журнала и увеличиваем счетчик
fclose(f);
file_count++;
// Устанавливаем FIFO в режим обхода
AccGyr.Set_FIFO_Mode(LSM6DSOX_BYPASS_MODE);
// Переходим в состояние DATA_LOGGER_IDLE_STATE
demo_state = DATA_LOGGER_IDLE_STATE;
// Подождем, пока светодиодный поток прекратит мигать
delay(250);
digitalWrite(LEDG, HIGH);
Serial.println("From DATA_LOGGER_RUNNING_STATE To DATA_LOGGER_IDLE_STATE");
break;
}
default:
Serial.println("Error! Invalid state");
}
}
}
if (demo_state == DATA_LOGGER_RUNNING_STATE) {
uint16_t fifo_samples;
// Проверяем количество выборок внутри FIFO
AccGyr.Get_FIFO_Num_Samples(&fifo_samples);
// Если мы достигнем порога, мы сможем очистить FIFO
if (fifo_samples > FIFO_SAMPLE_THRESHOLD) {
// Очищаем FIFO
Read_FIFO_Data(fifo_samples);
// Сохраняем строку во флэш-памяти
fprintf(f, "%s", buff);
fflush(f);
}
}
if (demo_state == DATA_STORAGE_STATE && millis() > 10000) {
// Отключаем датчик и переходим в режим Mass Storage
AccGyr.Disable_Double_Tap_Detection();
AccGyr.Disable_X();
AccGyr.Disable_G();
while (1) {
digitalWrite(LEDB, HIGH);
delay(100);
digitalWrite(LEDB, LOW);
delay(100);
}
}
}
,
@Adrian
Смотрите также:
- Как подключить MPU9250 к NodeMCU с помощью SPI или I2C Slave?
- Примеры двухъядерных скетчей Rp2040
- Получение стабильных измерений с помощью ИДУ BNO055
- Правильный способ получить значения крена, тангажа и перемещения
- Определение относительно точной скорости с помощью ИДУ
- Arduino Nano IOT LSM6DS3 получить угол гироскопа в градусах
- Использование software serial на Arduino Mega
- Неустранимая ошибка Adafruit_SSD1306.cpp: pgmspace.h: нет такого файла или каталога с использованием SSD1306 на Arduino Nano RP2040