|
好久了,一直把这堆吃灰的单片机放着没有动。最近刚好有时间再拿出来继续玩玩。
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
|