当前位置: 首页 > news >正文

第四章(先学习第五章)-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连接 调试

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • python把dbc转换成excel
  • Python 中的 `AsyncIterable` 和 `AsyncGenerator`:对比、优缺点及使用场景
  • 兔子序列(c语言)
  • RabbitMQ 常见问题与故障排查
  • 推荐一款强大的 macOS 剪贴板增强工具:CleanClip
  • 设计模式 13 责任链模式
  • 简而不减,极致便捷!泰极预付费解决方案震撼上市
  • Flink CDC读取Mysql时,Decimal类型数据异常,变成了字符串(源码解析及解决方案)
  • 19行为型设计模式——备忘录模式
  • qml tabbar tabbutton toolbar toolbutton 的区别
  • Error: Can not import paddle core while this file exists
  • 【STM32单片机_(HAL库)】3-4-1【中断EXTI】【智能排队控制系统】LCD1602显示字符串
  • 25考研计算机组成原理复习·4.3程序的机器级代码表示
  • Pytorch构建网络模型结构都有哪些方式
  • 通过C# 读取PDF页面大小、方向、旋转角度
  • Akka系列(七):Actor持久化之Akka persistence
  • Android单元测试 - 几个重要问题
  • Druid 在有赞的实践
  • express.js的介绍及使用
  • Javascript基础之Array数组API
  • JS变量作用域
  • Linux链接文件
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Netty 4.1 源代码学习:线程模型
  • Python进阶细节
  • V4L2视频输入框架概述
  • 扑朔迷离的属性和特性【彻底弄清】
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 什么软件可以剪辑音乐?
  • 数据仓库的几种建模方法
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 昨天1024程序员节,我故意写了个死循环~
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​iOS实时查看App运行日志
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ###STL(标准模板库)
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (rabbitmq的高级特性)消息可靠性
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (九)One-Wire总线-DS18B20
  • (七)Knockout 创建自定义绑定
  • (转)jQuery 基础
  • (转)菜鸟学数据库(三)——存储过程
  • ***监测系统的构建(chkrootkit )
  • . Flume面试题
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET MVC第五章、模型绑定获取表单数据
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .NET 中 GetProcess 相关方法的性能
  • .NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF!(完整版)
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .pyc文件是什么?
  • [ solr入门 ] - 利用solrJ进行检索