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; // 初始化左边的值为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连接 调试

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

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部