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 数据格式由以下几个基本规则组成:
- 键值对:键值对由键和值组成,用冒号
:
分隔。键是字符串,值可以是字符串、数字、布尔值、对象、数组或 null。示例:"key": "value"
- 对象(Object):对象由一系列键值对组成,用花括号
{}
包围。示例:{"key1": "value1", "key2": "value2"}
- 数组(Array):数组是一个有序的值列表,用方括号
[]
包围。示例:["value1", "value2", "value3"]
- 值可以是嵌套的对象或数组。示例:
{"key": ["value1", {"nested_key": "nested_value"}]}
- JSON 数据必须使用双引号
"
来包围字符串值。示例:{"key": "value"}
- 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; // 初始化左边的值为0
right = 0; // 初始化右边的值为0
c = 0; // 初始化接收到的字符为0
json = ""; // 初始化接收到的JSON数据为空字符串
Serial.begin(115200); // 初始化串口通信,波特率为115200
softSerial.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) { // 判断左右的值是否都不为0
Serial.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 = 2
sensor.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\PB11
while True:
data = {
"left": left,
"right": right
}
right = right+1
data_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\PB11
sensor.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=0
flag = [0,0,0,0,0]
flag[0] = 0
flag[1] = 1
flag[2] = -1
flag[3] = 500
flag[4] = -99
print(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的通信
发表评论 取消回复