数码之家

 找回密码
 立即注册
搜索
查看: 201|回复: 1

[Arduino] 使用STM32DUINO玩一下吃灰的小钢炮 CANNON开发板STM32F401

[复制链接]
发表于 2024-11-9 20:12:33 | 显示全部楼层 |阅读模式
好久了,一直把这堆吃灰的单片机放着没有动。最近刚好有时间再拿出来继续玩玩。
stm32cubemax配置什么的学习起来一直没找到合适的思路,刚好最近在玩esp32的arduino环境,刚好搜了一下也有stm32的。且所有的例子都适配了聚码的这块STM32F401RET6的板子,
硬件配置:
加速度计/陀螺仪:LSM6DS3
磁力计:LSM303AGR
温湿度计:HTS221
气压计:LPS25H
还有蓝牙 目前还没有跑起来  ble的。
目前可以做到的就是把几个传感器模块综合跑起来,储存数据到sd卡。支持串口交互。
目前研究到这,先记录一下吧。
在arduino附加开发板里边加载这个网址:导入资料。其他库稍等上传附件。目前综合陀螺仪做了数据滤波。数据保存。温湿度获取,但是没大有想法做飞控什么的,因为目前主要方向还是智能家居用,所以算是捎带。


[color=var(--fgColor-accent, var(--color-accent-fg))]https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicro electronics_index.json
目前基本所有stm32g0,f1,f4都有支持。对于新手还是比较简单。可以尝试一下。
附加的库我也基本都导出了。使用stlink下载。调试目前还不清除如何调试。稍等会打包上来bin文件。
硬件文档也在网盘里。内部有做好的单独传感器的ino程序。可以尝试。
资料参考网址:
https://github.com/stm32duino
通过百度网盘分享的文件:CANNON_JUMA_STM32F401资料
链接:https://pan.baidu.com/s/1xyQEpKxGSSyeHw87ZUJpfA
提取码:4v13



最终贴个程序吧:

#include <LSM6DS3Sensor.h>       // 陀螺仪传感器库
#include <LSM303AGR_ACC_Sensor.h> // 加速度传感器库
#include <LSM303AGR_MAG_Sensor.h> // 磁力计传感器库
#include <HTS221Sensor.h>         // 温湿度传感器库
#include <LPS25HBSensor.h>        // 气压计传感器库
#include <STM32SD.h>              // SD卡库

#define I2C2_SCL PB6
#define I2C2_SDA PB7
#define LED_BUILTIN PB3
#define SerialPort Serial

// 初始化I2C通信
TwoWire DEV_I2C(I2C2_SDA, I2C2_SCL);

// 传感器对象实例化
LSM6DS3Sensor AccGyr(&DEV_I2C);    // 陀螺仪和加速度计
LSM303AGR_ACC_Sensor Acc(&DEV_I2C); // 加速度计
LSM303AGR_MAG_Sensor Mag(&DEV_I2C); // 磁力计
HTS221Sensor HumTemp(&DEV_I2C);     // 温湿度
LPS25HBSensor PressTemp(&DEV_I2C);  // 气压计

// SD卡检测引脚定义
#ifndef SD_DETECT_PIN
#define SD_DETECT_PIN SD_DETECT_NONE
#endif

File dataFile;
bool isSDMounted = false; // 判断SD卡是否挂载

// 卡尔曼滤波器类,用于数据平滑处理
class KalmanFilter {
public:
  KalmanFilter(double q, double r) : q_(q), r_(r), p_(1.0), x_(0.0) {}
  double update(double measurement) {
    p_ += q_;
    double k = p_ / (p_ + r_);
    x_ += k * (measurement - x_);
    p_ *= (1 - k);
    return x_;
  }
private:
  double q_, r_, p_, x_;
};

// 卡尔曼滤波器对象实例化
KalmanFilter kalmanAccX(0.1, 0.1), kalmanAccY(0.1, 0.1), kalmanAccZ(0.1, 0.1);
KalmanFilter kalmanGyrX(0.1, 0.1), kalmanGyrY(0.1, 0.1), kalmanGyrZ(0.1, 0.1);

// 传感器初始化函数
void initializeSensors() {
  DEV_I2C.begin();
  AccGyr.begin();
  AccGyr.Enable_X();
  AccGyr.Enable_G();
  Acc.begin();
  Acc.Enable();
  Acc.EnableTemperatureSensor();
  Mag.begin();
  Mag.Enable();
  HumTemp.begin();
  HumTemp.Enable();
  PressTemp.begin();
  PressTemp.Enable();
}

// 处理并格式化传感器数据函数
void processData() {
  int32_t accelerometer[3], gyroscope[3];
  float temperatureHum, temperaturePress, temperatureMag, humidity, pressure;
  int32_t accelerometer1[3], magnetometer[3];

  // 获取加速度计和陀螺仪数据,并进行卡尔曼滤波处理
  AccGyr.Get_X_Axes(accelerometer);
  AccGyr.Get_G_Axes(gyroscope);
  double filteredAccX = kalmanAccX.update(accelerometer[0] / 1000.0);
  double filteredAccY = kalmanAccY.update(accelerometer[1] / 1000.0);
  double filteredAccZ = kalmanAccZ.update(accelerometer[2] / 1000.0);
  double filteredGyrX = kalmanGyrX.update(gyroscope[0] / 1000.0);
  double filteredGyrY = kalmanGyrY.update(gyroscope[1] / 1000.0);
  double filteredGyrZ = kalmanGyrZ.update(gyroscope[2] / 1000.0);

  // 计算俯仰角和横滚角
  double pitch = atan2(filteredAccY, sqrt(filteredAccX * filteredAccX + filteredAccZ * filteredAccZ)) * 180.0 / M_PI;
  double roll = atan2(-filteredAccX, filteredAccZ) * 180.0 / M_PI;

  // 获取其他传感器数据
  Acc.GetAxes(accelerometer1);
  Acc.GetTemperature(&temperatureMag);
  Mag.GetAxes(magnetometer);
  HumTemp.GetHumidity(&humidity);
  HumTemp.GetTemperature(&temperatureHum);
  PressTemp.GetPressure(&pressure);
  PressTemp.GetTemperature(&temperaturePress);

  // 构建并格式化数据字符串
  String dataString = "";
  dataString += "Filtered Acc: " + String(filteredAccX) + ", " + String(filteredAccY) + ", " + String(filteredAccZ);
  dataString += " | Filtered Gyr: " + String(filteredGyrX) + ", " + String(filteredGyrY) + ", " + String(filteredGyrZ);
  dataString += " | Pitch: " + String(pitch) + " | Roll: " + String(roll);
  dataString += " | X轴加速度[mg]: " + String(accelerometer1[0]) + " " + String(accelerometer1[1]) + " " + String(accelerometer1[2]);
  dataString += " | 磁力[mGauss]: " + String(magnetometer[0]) + " " + String(magnetometer[1]) + " " + String(magnetometer[2]);
  dataString += " | 磁力计温度[C]: " + String(temperatureMag, 2);
  dataString += " | 磁力湿度[%]: " + String(humidity, 2) + " | 磁力温湿[C]: " + String(temperatureHum, 2);
  dataString += " | 气压[hPa]: " + String(pressure, 2) + " | 气温[C]: " + String(temperaturePress, 2);

  // 写入数据到SD卡和串口
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.flush();
  }
  Serial.println(dataString);
}

// 挂载SD卡并开始记录数据的函数
void mountSDCardAndStartRecording() {
  if (!isSDMounted && SD.begin(SD_DETECT_PIN)) {
    dataFile = SD.open("data.txt", FILE_WRITE);
    if (dataFile) {
      isSDMounted = true;
      Serial.println("SD卡挂载成功,开始写入数据。");
      writeDataLoop();
    }
   
  }
  else
        {
         Serial.println("挂载失败。");
        }
}

// 写入数据的循环处理函数
void writeDataLoop() {
  while (isSDMounted) {
    digitalWrite(LED_BUILTIN, HIGH);
    processData();   //读取数据
      if (Serial.available()) {   //如果有新数据则执行
        int command = Serial.read();
        handleSerialCommand(command);
      }
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
  }
}



// 卸载SD卡函数
void unmountSDCard() {
  dataFile.close();
  SD.end();
  isSDMounted = false;
  Serial.println("SD卡已卸载,停止数据写入。");
}

// 删除文件函数
void deleteFile(const char* filename) {
  if (SD.remove(filename))
    Serial.println(filename + String(" 文件已删除。"));
  else
    Serial.println("文件删除失败或不存在。");
}

// 读取SD卡文件内容
void readSDCardFile() {
  if (SD.begin(SD_DETECT_PIN) && SD.exists("data.txt")) {
    dataFile = SD.open("data.txt", FILE_READ);
    if (dataFile) {
      Serial.println("开始读取data.txt文件内容:");
      while (dataFile.available())
        Serial.write(dataFile.read());
      dataFile.close();
    }
  } else {
    Serial.println("无法读取文件或文件不存在。");
  }
}

// 处理串口命令
void handleSerialCommand(int command) {
  switch (command) {
    case '1':
      mountSDCardAndStartRecording();//挂载SD卡
      break;
    case '2':
        unmountSDCard();//卸载SD卡
        break;
    case '3':
        deleteFile("data.txt");//删除数据
        break;
    case '4':
      readSDCardFile();//读取sd数据
      break;
    default:
      Serial.println("未知命令");
      break;
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  SerialPort.begin(115200);
  while (!Serial);
  initializeSensors();
  Serial.println("初始化完成。输入1记录数据,2弹出SD卡,3删除数据,4读取数据。");
}

void loop() {
  if (Serial.available()) {
    int command = Serial.read();
    handleSerialCommand(command);
  } else {
    static bool firstRun = true;  // 使用静态变量来记录第一次运行
    if (firstRun) {
      int command = '1';  // 默认命令
      handleSerialCommand(command);
      firstRun = false;  // 设置为 false,防止再次执行
    }
  }
}







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 2024-11-12 13:44:40 | 显示全部楼层
很好的实践,值得学习。我在看STM32的一个例子,使用RTOS处理线程和任务,看的脑袋大
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-12-4 00:40 , Processed in 0.312001 second(s), 13 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表