
【STM32开发板】 FryPi炸鸡派
简介
这是一个比手掌还小的STM32F411RET6迷你开发板,可以用于AI开发,UI开发,数字电源控制板等等,甚至可以拿去用于你的毕业设计和其他相关的项目。
简介:这是一个比手掌还小的STM32F411RET6迷你开发板,可以用于AI开发,UI开发,数字电源控制板等等,甚至可以拿去用于你的毕业设计和其他相关的项目。开源协议
:GPL 3.0
描述
FryPi炸鸡派
STM32F411RET6开发板
|
|
|
|
简介
这是一个比手掌还小的STM32F411RET6迷你开发板,核心板成本在60元以内,可以用于AI开发,UI开发,数字电源控制板等等,甚至可以拿去用于你的毕业设计和其他相关的项目。
最开始做这块板子的目的是因为上一个智能手表的项目OV-Watch,很多复刻的人说很多器件非常难焊接,特别是主控是太小了,二次开发不太方便,再加上我也打算在STM32上部署一下AI相关的东西,做下教程,因此,FryPi炸鸡派就诞生了。这一块开发板不仅适用于初学者,也适用于进阶开发者,项目中的高级例程可能需要一定的知识储备。
同时,选这个MCU的原因也是因为STM32F411REU6可以完美替代原来智能手表项目的CEU6,而且在simulink中也有F411的硬件选项。
功能特点
- MCU使用STM32F411RET6,Cortex-M4 core with DSP and FPU,512 Kbytes of Flash memory, 100 MHz CPU, ART Accelerator.
- 可额外焊接外置SPI Flash.
- 例程丰富:例如有高级例程:智能手表,热成像手势识别,手写数字识别,与matlab联合开发,simulink在环开发等等.
- 留有端口可外接扩展板.(例如最上面的演示动态图,都是在Core板插上Cam扩展板)
- 有双TypeC和单TypeC版本的Core板.
- FryPi炸鸡派的pin map如下所示,目前仅有一部分IO口被用到LCD和触摸屏等外设.
硬件说明
目前的硬件工程版本为V1.1,有一个Core核心板,一个单typeC的Core核心板,一个CAM扩展板,以及一个OV2640摄像头模块,这个摄像头模块是可以在网上买的。Core板的3D示意图如下所示,希望之后大家可以自由发挥,做一些扩展板,例如做一个传感器的扩展板,或者直接插在小车上使用。
软件说明
目前的例程demo如下目录所示,例程很丰富,分为基础例程Basic,和高级例程Advanced。详细可点击链接进入或直接在github仓库中查看。demo和教学文档非常多,快来使用吧~
上机测试
开发板焊接完毕拿到手后,烧录模板例程观察现象,如果硬件没有问题,那么插串口对应的TypeC连接电脑,L2会闪烁,按下Key切换模式,L2闪烁频率会改变,同时上位机会接收到模式的信息;

部分例程说明
这里拿热成像手势识别为例进行demo工程说明(其他的详细的见github):
一、文件夹组成
├─python_codes
│ │ data_2_imgfile.py
│ │ data_get.py
│ │ data_show.py
│ │ gesture.h5
│ │ test.py
│ │ train.py
│ │
│ └─camera_data
│ test_data.npz
│ train_data.npz
│
└─stm32_codes
├─ThermalCamera_data_send
├─Thermalgesture
文件夹大致如上,`python_codes`存放的是:从下位机获取数据、网络训练、测试的代码等。采集的热成像数据保存在.npz格式的文件中,用于网络的训练和测试,模型保存为.h5格式。`stm32_codes`存放的是STM32的代码,第一个是LCD刷屏+串口发送炸鸡派获得的热成像原始数据。第二个则是已经部署好的热成像手势识别的代码。
二、热成像推流至屏幕
直接使用提供的MLX90640的API,然后对应更改了IO口即可,详细更多相关的代码细节见代码,同时为了让刷屏更快,在mlx90640_display_process(void)函数中将drawPicture(void)中刷屏显示使用缓存空间进行刷屏,因为打点刷屏太慢了。详见代码~
1、CNN搭建与训练
搭建的卷积神经网络如下图所示,训练集大概有4000多张图片数组数据,num_epochs 设置为了50,batch_size 设置为64,Adam优化器learning_rate 设置为0.01。最后Acc大概可以超过0.9。具体详细的网络搭建详见./python_codes/train.py。
#------------------------------【搭模型】---------------------------------
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=5, kernel_size=(5, 5), padding='valid', activation=tf.nn.relu, input_shape=(24, 32, 1)),
tf.keras.layers.MaxPool2D(pool_size=(2, 2), padding='same'),
tf.keras.layers.Conv2D(filters=3, kernel_size=(3, 3), padding='valid', activation=tf.nn.relu, input_shape=(10, 14, 5)),
tf.keras.layers.MaxPool2D(pool_size=(2, 2), padding='same'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(units=32, activation=tf.nn.relu),
tf.keras.layers.Dense(units=16, activation=tf.nn.relu),
tf.keras.layers.Dense(units=6, activation=tf.nn.softmax)
])
model.summary()
2、CNN部署至STM32
首先将训练好得到的gesture.h5模型使用cubemx AI工具生成代码后,调用API,这里主要使用的ai_mnetwork_run(),具体如下代码块中函数user_ai_run(const ai_float *in_data, ai_float *out_data)所示。由于CubeMX生成代码选择的systemperform,所以要注释MX_X_CUBE_AI_Process(),这个里面主要是用来测试模型的性能,他默认使用的随机数填充输入。
uint8_t user_ai_run(const ai_float *in_data, ai_float *out_data)
{
int idx = 0;
int batch = 0;
ai_buffer ai_input[AI_MNETWORK_IN_NUM];
ai_buffer ai_output[AI_MNETWORK_OUT_NUM];
ai_float input[1] = {0};
ai_float output[1] = {0};
if (net_exec_ctx[idx].handle == AI_HANDLE_NULL)
{
printf("E: network handle is NULL\r\n");
return -1;
}
ai_input[0] = net_exec_ctx[idx].report.inputs[0];
ai_output[0] = net_exec_ctx[idx].report.outputs[0];
ai_input[0].data = AI_HANDLE_PTR(in_data);
ai_output[0].data = AI_HANDLE_PTR(out_data);
batch = ai_mnetwork_run(net_exec_ctx[idx].handle, ai_input, ai_output);
if (batch != 1) {
aiLogErr(ai_mnetwork_get_error(net_exec_ctx[idx].handle),
"ai_mnetwork_run");
return -2;
}
return 0;
}
注意,这里我给到输入的数据,还是正常做了归一化的,如下代码所示。
static void normalizeArray()
{
float range = maxTemp - minTemp;
for(uint16_t i=0; i<24*32; i++) {
normalizetempValues[i] = (tempValues[i] - minTemp) / range;
}
}
输出的数据格式为一个长度6的数组,分别对应无手势和手势1~5,类别判定条件为选择最大的数,即判哪个数最大,其对应的手势判断为当前手势,以下代码为寻找最大数对应的index。
static uint8_t findMaxIndex(float arr[], uint8_t size) {
if (size <= 0) {
// 处理空数组或无效大小的情况
return -1;
}
uint8_t maxIndex = 0; // 假设最大值的索引为第一个元素的索引
for (int i = 1; i < size; ++i) {
// 检查当前元素是否大于当前最大值
if (arr[i] > arr[maxIndex]) {
maxIndex = i; // 更新最大值的索引
}
}
return maxIndex;
}
最后给出整个一轮识别的流程如下所示。
normalizeArray();//先归一化
if(user_ai_run(normalizetempValues, outputs))//将归一化数据代入,正向运算
{
printf("\r\n run erro \r\n");
}
uint8_t temp = findMaxIndex(outputs, sizeof(outputs) / sizeof(outputs[0]));//寻找最大值的索引
printf("\r\npredict gesture:%d\r\n", temp);//打印出判断的手势
当然,上面只是demo中的其中一个,更多的基础和高级例程demo详见github仓库。
购买清单
1.触摸屏型号: 淘宝搜 P169H002-CTP
2.STM32F411RET6: 一般我在优信电子买
3.其他: 其他的阻容为了方便我一般就直接在立创买的
演示视频
bilibili链接: https://www.bilibili.com/video/BV1u2421F7kf/
代码仓库
github: https://github.com/No-Chicken/FryPi.
gitee: https://gitee.com/kingham/FryPi.
github上的software里面的demo工程很多我都写的比较详细,所以建议大家直接去github里面查看代码和demo教程。如果仓库没办法打开,可以在网上找一下github镜像,或者搭梯子,或者去gitee搜我。
教程
手册网站:https://no-chicken.xyz
基础教程视频:https://www.bilibili.com/video/BV1Gy411e7EH
进阶教程视频:https://www.bilibili.com/video/BV1nw4m1e7TJ
QQ交流群
群1:572216445
群2:912218004
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。











