第四章(先学习第五章)-openmv和arduino和stm32的通信

2024-08-26 02:52

本文主要是介绍第四章(先学习第五章)-openmv和arduino和stm32的通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

4.1-openmv与arduino通信

https://www.bilibili.com/video/BV1VK411j733/?vd_source=16940ba3adbc66f0fb14e0c1d87db878

json

通信 控制一个lED. 0:关,1:开

控制两个LED灯 LED1 0 LED2 1 LED3 0

X:1 Y:8 (1,8)

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以易于阅读和编写的文本格式表示结构化数据。它由键值对组成,其中键是字符串,值可以是字符串、数字、布尔值、对象、数组或者 null。

JSON 数据格式由以下几个基本规则组成:

  1. 键值对:键值对由键和值组成,用冒号 : 分隔。键是字符串,值可以是字符串、数字、布尔值、对象、数组或 null。示例:"key": "value"
  2. 对象(Object):对象由一系列键值对组成,用花括号 {} 包围。示例:{"key1": "value1", "key2": "value2"}
  3. 数组(Array):数组是一个有序的值列表,用方括号 [] 包围。示例:["value1", "value2", "value3"]
  4. 值可以是嵌套的对象或数组。示例:{"key": ["value1", {"nested_key": "nested_value"}]}
  5. JSON 数据必须使用双引号 " 来包围字符串值。示例:{"key": "value"}
  6. JSON 文件的 MIME 类型是 application/json

arduino-需要再次确定 效果一般

这里我们使用arduino进行通信。

下面是arduino的代码,代码中使用了json 所以我们要安装一下json 的库。
在这里插入图片描述
在这里插入图片描述
上传到板子
在这里插入图片描述
带注释的代码

#include <ArduinoJson.h>
#include <SoftwareSerial.h>SoftwareSerial softSerial(10, 11); // 创建一个软串口对象,用于与其他设备通信(传输数据)10是Arduino板子的RX  11是Arduino板子上午TX 记得还需要连接GND引脚。
volatile int left; // 定义一个全局变量,用于存储左边的值
volatile int right; // 定义一个全局变量,用于存储右边的值
volatile char c; // 定义一个全局变量,用于存储接收到的字符
String json; // 定义一个字符串变量,用于存储接收到的JSON数据void setup(){left = 0; // 初始化左边的值为0right = 0; // 初始化右边的值为0c = 0; // 初始化接收到的字符为0json = ""; // 初始化接收到的JSON数据为空字符串Serial.begin(115200); // 初始化串口通信,波特率为115200softSerial.begin(115200); // 初始化软串口通信,波特率为115200
}void loop(){if (softSerial.available() > 0) { // 如果软串口中有数据可读取c = char(softSerial.read()); // 读取一个字符json = String(json) + String(c); // 将读取的字符添加到接收到的JSON数据字符串中if (c == '}') { // 判断是否接收到了完整的JSON数据DynamicJsonDocument doc(200); // 创建一个大小为200的JsonDocument对象deserializeJson(doc, json); // 解析接收到的JSON数据JsonObject obj = doc.as<JsonObject>(); // 将解析后的JSON数据转换为JsonObject对象int left = doc["left"]; // 从JsonObject对象中获取左边的值int right = doc["right"]; // 从JsonObject对象中获取右边的值if (left!=0 && right!=0) { // 判断左右的值是否都不为0Serial.print("left = "); // 打印左边的值Serial.print(left);Serial.print("right = "); // 打印右边的值Serial.println(right);}json = ""; // 清空接收到的JSON数据字符串,为下一次接收做准备}}
}

我们把上述文件烧录到Arduino 板子

我们调试Arduino 看Arduino收到数据是否可以正确解析

Arduino 连接如下图:
在这里插入图片描述
使用串口软件模拟openmv 发送给Arduino JSON字符串

然后在Arduino IDE 串口监视器中查看解析的数据是否正确。

{"left":1,"right":28}

在这里插入图片描述
然后Arduino IDE中打开 串口监视器
在这里插入图片描述
在这里插入图片描述

openmv-需要再次确定 效果一般

下面我们用电脑接受openmv 执行的时候,openmv通过串口发送出的数据。

使用openmv H7 plus 执行一下代码

注意 openmv 和arduino 串口通信速率有限 所以我们需要加入一个延时。

import sensor, image, time  # 导入sensor、image和time模块
import json  # 导入json模块
import time
from pyb import Servo  # 从pyb模块中导入Servo类
from pyb import UART  # 从pyb模块中导入UART类
left = 1
right = 2sensor.reset()  # 初始化摄像头传感器
sensor.set_pixformat(sensor.RGB565)  # 设置像素格式为RGB565
sensor.set_framesize(sensor.QQVGA)  # 设置帧大小为QQVGA以加快处理速度
sensor.skip_frames(10)  # 跳过一些帧,让新设置生效
sensor.set_auto_whitebal(False)  # 关闭自动白平衡功能
clock = time.clock()  # 创建一个时钟对象,用于跟踪FPS(每秒帧数)
uart = UART(3, 115200)  # 创建一个UART对象,用于串口通信 始化串口三、波特率115200 TXD:P4\PB10 RXD:P5\PB11while True:data = {"left": left,"right": right}right = right+1data_out = json.dumps(data)  # 将数据转换为JSON字符串uart.write(data_out + '')  # 通过串口发送数据print(data)time. sleep_ms(8)  #延时8毫秒 串口通信速率有限,测试后发现这里需要延时8ms

然后我们执行代码,并将openmv连接到电脑连接TTL 模块到电脑
在这里插入图片描述
串口软件显示接受的数据

检查数据 格式是JSON 格式
在这里插入图片描述

openmv和arduino连接调试

在这里插入图片描述
在这里插入图片描述

4.2-openmv与STM32通信

openmv

openmv和STM32通信我们使用自己构造数据帧进行通信
在这里插入图片描述
连接方法按照下图
在这里插入图片描述
在这里插入图片描述

import pyb, sensor, image, math, time
from pyb import UART
import ustruct
from image import SEARCH_EX, SEARCH_DS
import time
import sensor, lcd
#导入需要的库和模块
#2.注意是否有下面两句根据自己摄像头调整#sensor.set_vflip(True)#sensor.set_hmirror(True)uart = UART(3,115200,bits=8, parity=None, stop=1, timeout_char = 1000)#初始化串口三、波特率115200 TXD:P4\PB10 RXD:P5\PB11sensor.reset()#初始化相机传感器。
sensor.set_pixformat(sensor.RGB565)#设置相机模块的像素模式:sensor.RGB565: 16 bits/像素。
sensor.set_framesize(sensor.QQVGA)#设置图像分辨率、如果改变分辨率也要调整ROI区域。摄像头不同、应用场景不同可以选择不同分辨率。这里使用QQVGA可能画质很胡,但是为了兼容不同型号摄像头我们先使用QQVGA 不影响循迹效果
sensor.skip_frames(time=2000)#跳过指定数目的帧。在这里,设置为跳过2000毫秒(即2秒)的帧。这样可以给传感器一些时间进行初始化和自适应调整。
sensor.set_auto_whitebal(True)#设置为自动白平衡模式。这使得摄像头可以根据场景中的光照条件自动调整图像的白平衡,从而保持图像色彩更加准确和自然。
sensor.set_auto_gain(False)#关闭自动增益模式。通常情况下,开启自动增益会帮助摄像头自动调整亮度,并在低亮度环境下提高图像清晰度。通过设置为False,禁用了这个功能,使用固定增益值。# 注意是否有下面两句根据自己摄像头调整
sensor.set_vflip(True)  #垂直方向翻转 根据自己摄像头和模块安装位置调整 !!!重要不同摄像头是否需要镜像根据实际情况定,如果不需要镜像需要注释掉
sensor.set_hmirror(True) #水平方向反转 根据自己摄像头和模块安装位置调整 !!!重要不同摄像头是否需要镜像根据实际情况定,如果不需要镜像需要注释掉def send_five_uchar(c1,c2,c3,c4,c5):#功能发送五个整形global uart;data = ustruct.pack("<BBiiiiiB",#使用了 ustruct.pack() 函数将这些数据打包为二进制格式。使用 "<BBiiiiiB" 作为格式字符串来指定要打包的数据的类型和顺序:0xA5,0xA6,int(c1),int(c2),int(c3),int(c4),int(c5),0x5B)uart.write(data);#uart.write(data) 将打包好的二进制数据帧写入 UART 发送缓冲区,从而将数据通过串口发送出去print(data)#通过 print(data) 打印发送的数据到串行终端,方便调试和确认发送的内容。while(True):data=0flag = [0,0,0,0,0]flag[0] = 0flag[1] = 1flag[2] = -1flag[3] = 500flag[4] = -99print(flag[0],flag[1],flag[2],flag[3],flag[4])#把数据打印在串行终端方便调试send_five_uchar(flag[0],flag[1],flag[2],flag[3],flag[4])#把五个数据通过串口发送出去、发送五个无符号字符。time. sleep_ms(8)  #延时8毫秒 串口通信速率有限,测试后发现这里需要延时8ms

STM32

这里延时如何使用STM32F103接收数据

我们使用HAL库新建工程

我们先新建一个工程(工程不能中午目录和中午名字)

在这里插入图片描述
在这里插入图片描述
设置调试下载接口
在这里插入图片描述
设置晶振
在这里插入图片描述
输入 72然后回车
在这里插入图片描述
在这里插入图片描述
初始化串口一
在这里插入图片描述
串口二是用于和摄像头通信的!!!!
在这里插入图片描述
在这里插入图片描述
另外初始化一下PC13
在这里插入图片描述
起一个名字
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
生成代码
在这里插入图片描述
先编写串口一 映射printf
在这里插入图片描述
在这里插入图片描述

#include "stdio.h"

在这里插入图片描述

/**
* @brief 重定向printf (重定向fputc),使用时候记得勾选上魔法棒->Target->UseMicro LIB 可能需要在C文件加typedef struct __FILE FILE;包含这个文件#include "stdio.h"
* @param 
* @return 
*/
int fputc(int ch,FILE *stream)
{HAL_UART_Transmit(&huart1,( uint8_t *)&ch,1,0xFFFF);return ch;
}

然后我们要继续编写STM32串口二接收数据,然后把解析的数据值通过串口一发送出去

我们先定义一个串口二接收数据变量

uint8_t g_ucUsart2ReceiveData;  //保存串口二接收的数据

在这里插入图片描述
开启接收中断

  HAL_UART_Receive_IT(&huart2,&g_ucUsart2ReceiveData,1);  //串口二接收数据

在这里插入图片描述
声明一下变量

extern uint8_t g_ucUsart2ReceiveData;  //保存串口二接收的数据

在这里插入图片描述
我们需要在串口中断回调函数中加入我们对接收到数据的解析
在这里插入图片描述
在usart.c文件中定义一个函数

/*******************
*  @brief  摄像头串口协议解析函数 可以连接K210或openmv等
*  @param  data:串口接收到的每个字节
*  @return  
*
*******************/
void usartCamera_Receive_Data(uint8_t data)
{static uint8_t state = 0;//定义静态static 变量if(state==0&&data==0xA5) //判断第一个是不是帧头0xA5{state=1;//是帧头0xA5 赋值state=1 表示接收下一个数据//数据存储在数组中 "g_ucUsart2ReceivCounter++",这里是先用后加,比如g_ucUsart2ReceivCounter 初值为0,执行这个是先g_ucaUsart2ReceiveBuffer[0]=data,然后g_ucUsart2ReceivCounter++,即后g_ucUsart2ReceivCounter = 1的g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter++] = data;}else if(state==1&&data==0xA6) //第二个是不是帧头0xA6{state=2;//如果第二个是帧头0xA6 赋值state=2 表示接收下一个数据g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter++] = data;//保存数据}else if(state==2)//然后确定开头是0XA5 0XA6 就开始接收{g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter++]=data;if(g_ucUsart2ReceivCounter>25||data==0x5B) state=3;  //接收大于25个或者接收到帧尾0X5B 就置位状态三}else if(state==3) //状态三{if(g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter-1] == 0x5B)  //确定 最后一个是不是0x5B帧尾 是帧尾0x5B 就认为通信正确 处理数据{state = 0;//这里就可以处理数据了、处理完记得清空数组和重置标志位与计数值g_ucUsart2ReceivCounter = 0;//清零计数值g_iUsart2_Data1 = int(g_ucaUsart2ReceiveBuffer[2]<<0) | int(g_ucaUsart2ReceiveBuffer[3]<<8) | int(g_ucaUsart2ReceiveBuffer[4]<<16)| int(g_ucaUsart2ReceiveBuffer[5]<<24);g_iUsart2_Data2 = int(g_ucaUsart2ReceiveBuffer[6]<<0) | int(g_ucaUsart2ReceiveBuffer[7]<<8) | int(g_ucaUsart2ReceiveBuffer[8]<<16)| int(g_ucaUsart2ReceiveBuffer[9]<<24);			g_iUsart2_Data3 = int(g_ucaUsart2ReceiveBuffer[10]<<0) | int(g_ucaUsart2ReceiveBuffer[11]<<8) | int(g_ucaUsart2ReceiveBuffer[12]<<16)| int(g_ucaUsart2ReceiveBuffer[13]<<24);			g_iUsart2_Data4 = int(g_ucaUsart2ReceiveBuffer[14]<<0) | int(g_ucaUsart2ReceiveBuffer[15]<<8) | int(g_ucaUsart2ReceiveBuffer[16]<<16)| int(g_ucaUsart2ReceiveBuffer[17]<<24);				g_iUsart2_Data5 = int(g_ucaUsart2ReceiveBuffer[18]<<0) | int(g_ucaUsart2ReceiveBuffer[19]<<8) | int(g_ucaUsart2ReceiveBuffer[20]<<16)| int(g_ucaUsart2ReceiveBuffer[21]<<24);				//2.然后清空数组for(int i=0;i<25;i++) g_ucaUsart2ReceiveBuffer[i]=0x00;//清空数组}else //不是帧尾说明通信错误重新开始接收{state=0;g_ucUsart2ReceivCounter =0;for(int i=0;i<25;i++) g_ucaUsart2ReceiveBuffer[i]=0x00;//清空数组}}else{	//其他异常清空state=0;g_ucUsart2ReceivCounter =0;for(int i=0;i<25;i++) g_ucaUsart2ReceiveBuffer[i]=0x00;//清空数组}
}

在这里插入图片描述
增加一些变量的定义
uint8_t g_ucaUsart2ReceiveBuffer[25];//保存串口接收有效数据的数组
uint8_t g_ucUsart2ReceivCounter=0;//串口接收计数值
在这里插入图片描述
增加串口帧数据解析
usartCamera_Receive_Data(g_ucUsart2ReceiveData);
在这里插入图片描述
然后增加一个声明
extern void usartCamera_Receive_Data(uint8_t data);
在这里插入图片描述
然后我们main中定义保存接收值的变量
int g_iUsart2_Data1 = 0; //保存最后转化的值
int g_iUsart2_Data2 = 0;
int g_iUsart2_Data3 = 0;
int g_iUsart2_Data4 = 0;
int g_iUsart2_Data5 = 0;
在这里插入图片描述
然后声明一下

extern int g_iUsart2_Data1 ;		//保存最后转化的值
extern int g_iUsart2_Data2 ;
extern int g_iUsart2_Data3 ;
extern int g_iUsart2_Data4 ;
extern int g_iUsart2_Data5 ;

在这里插入图片描述
增加串口一输出代码
printf(“g_iUsart2_Data:%d %d %d %d %d\r\n”,g_iUsart2_Data1,g_iUsart2_Data2,g_iUsart2_Data3,g_iUsart2_Data4,g_iUsart2_Data5);
HAL_Delay(15);
HAL_GPIO_TogglePin(PC13_LED_GPIO_Port,PC13_LED_Pin);

在这里插入图片描述
如果爆警告记得包含头文件
#include “stdio.h”
编译之后没有报错我们就可以烧录测试了
在这里插入图片描述
把程序烧录到单片机中 可以使用DAP 、STlink等烧录均可
在这里插入图片描述
在这里插入图片描述

openmv与STM32连接 调试

在这里插入图片描述
在这里插入图片描述

这篇关于第四章(先学习第五章)-openmv和arduino和stm32的通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107343

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件