【内含实物图】一款可独立行走且支持远程对话的微型巡逻摄像头——嵌入式方案

本文主要是介绍【内含实物图】一款可独立行走且支持远程对话的微型巡逻摄像头——嵌入式方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上篇给大家分享了微型巡逻摄像头的整体硬件方案及各单元的工作原理。本篇将重点分享微型巡逻摄像头自平衡功能和移动控制功能的实现。
cam

MCU固件开发

本demo直接使用涂鸦智能SC012-WD2摄像头,因此摄像头和APP相关固件程序,并不需要开发者进行开发。开发者只需要开发底盘小车平衡运动这方面即可。

1.姿态读取

在控制平衡之前,开发者需要先获取当前平衡姿态,即先读取MPU6050数据,参考如下

void Get_Angle(uint8_t way)
{ float Accel_Y,Accel_Z,Gyro_X,Gyro_Z;Temperature=Read_Temperature();      //===读取MPU6050内置温度传感器数据,近似表示主板温度。if(way==1)                           //===DMP的读取在数据采集中断读取,严格遵循时序要求{	Read_DMP();                      //===读取加速度、角速度、倾角Angle_Balance=-Roll;             //===更新平衡倾角Gyro_Balance=-gyro[0];            //===更新平衡角速度Gyro_Turn=gyro[2];               //===更新转向角速度Acceleration_Z=accel[2];         //===更新Z轴加速度计}			else{Gyro_X=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_XOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_XOUT_L);    //读取Y轴陀螺仪Gyro_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_L);    //读取Z轴陀螺仪Accel_Y=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_YOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_YOUT_L); //读取X轴加速度计Accel_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_L); //读取Z轴加速度计if(Gyro_X>32768)  Gyro_X-=65536;                       //数据类型转换  也可通过short强制类型转换if(Gyro_Z>32768)  Gyro_Z-=65536;                       //数据类型转换if(Accel_Y>32768) Accel_Y-=65536;                      //数据类型转换if(Accel_Z>32768) Accel_Z-=65536;                      //数据类型转换Gyro_Balance=Gyro_X+Gyro_X_OFFSET;                                  //更新平衡角速度Accel_Angle=atan2(Accel_Y,Accel_Z)*180/PI;                 //计算倾角	Gyro_X=Gyro_X/16.4;                                    //陀螺仪量程转换	if(way==2)		  	Kalman_Filter(Accel_Angle,Gyro_X);//卡尔曼滤波	else if(way==3)   Yijielvbo(Accel_Angle,Gyro_X);    //互补滤波Angle_Balance=angle;                                     //更新平衡倾角Gyro_Turn=Gyro_Z+Gyro_Z_OFFSET;                                      //更新转向角速度Acceleration_Z=Accel_Z;                                //===更新Z轴加速度计	}
}
2.姿态平衡控制

获取姿态之后,开发者就可以着手控制小车保持平衡了。

在直立控制里面加入速度负反馈无法达到速度闭环的目的,而且还会破坏直立控制系统,因此在保证直立控制的优先级条件下,开发者们要把速度控制放在直立控制的前面,也就是速度控制调节的结果仅仅是改变直立控制的目标值。根据经验可知,小车的运行速度和小车的倾角是相关的。比如要提高小车向前行驶的速度,就需要增加小车向前倾斜的角度,倾斜角度加大之后,车轮在直立控制的作用下需要向前运动保持小车平衡,速度增大;如果要降低小车向前行驶的速度,就需要减小小车向前倾斜的角度,倾斜角度减小之后,车轮在直立控制的作用下向后运动保持小车平衡,速度减小。

开发者们把速度和直立两个控制器串联起来工作,其中速度控制的输出作为直立控制的输入,而直立控制的输出作为系统的输出,这其实就是一个串级控制系统。其中直立控制使用PD控制。因为编码器可能存在的噪声,为防止噪声被放大并消除系统的静差,这里速度控制使用PI控制。

3. 直立PD控制
int balance(float Angle,float Gyro)
{  float Bias;int balancePID;Bias=Angle-Angle_OFFSET;                       //===求出平衡的角度中值 和机械相关balancePID=Balance_Kp*Bias+Gyro*Balance_Kd;   //===计算平衡控制的电机PWM  PD控制   kp是P系数 kd是D系数 return balancePID;
}
4.速度PI控制
int velocity(int encoder_left,int encoder_right)
{  static float Velocity,Encoder_Least,Encoder,Movement;static float Encoder_Integral,Target_Velocity;//=============遥控前进后退部分=======================// Target_Velocity=40;                 if(Direction.Current==GO_STRAIGHT)    	Movement=-Target_Velocity/Flag_speed;	        //===前进标志位置1 else if(Direction.Current==GO_BACK)	Movement=Target_Velocity/Flag_speed;         //===后退标志位置1else  Movement=0;	//=============速度PI控制器=======================//	Encoder_Least =(encoder_left+encoder_right)-0;                   Encoder *= 0.8;		                                                //===一阶低通滤波器       Encoder += Encoder_Least*0.2;	                                    //===一阶低通滤波器    Encoder_Integral +=Encoder;                                       //===积分出位移 积分时间:10msEncoder_Integral=Encoder_Integral-Movement;                       //===接收遥控器数据,控制前进后退if(Encoder_Integral>8000)  	Encoder_Integral=8000;             //===积分限幅if(Encoder_Integral<-8000)	Encoder_Integral=-8000;              //===积分限幅	Velocity=Encoder*Velocity_Kp+Encoder_Integral*Velocity_Ki;        //===速度控制	if(Turn_Off(Angle_Balance,BAT_VOL)==1||Direction.Current==TURN_OFF)   Encoder_Integral=0;      return Velocity;
}
5.转向控制

除了保持平衡之外,小车也涉及到左右转动,因此还需要加入转向的控制,可参考如下

int turn(int encoder_left,int encoder_right,float gyro)//转向控制
{static float Turn_Target,Turn,Encoder_temp,Turn_Convert=0.9,Turn_Count; float Turn_Amplitude=30/Flag_speed,Kp=32,Kd=0; 	//=============遥控左右旋转部分=======================//if(Direction.Current==TURN_LEFT||Direction.Current==TURN_RIGHT)                      {if(++Turn_Count==1)Encoder_temp=myabs(encoder_left+encoder_right);Turn_Convert=50/Encoder_temp;if(Turn_Convert<0.6)Turn_Convert=0.6;if(Turn_Convert>3)Turn_Convert=3;}	else{Turn_Convert=0.9;Turn_Count=0;Encoder_temp=0;}			if(Direction.Current==TURN_LEFT){Turn_Target+=Turn_Convert;}else if(Direction.Current==TURN_RIGHT){Turn_Target-=Turn_Convert; }else Turn_Target=0;if(Turn_Target>Turn_Amplitude)  Turn_Target=Turn_Amplitude;    //===转向速度限幅if(Turn_Target<-Turn_Amplitude) Turn_Target=-Turn_Amplitude;if(Direction.Current==GO_STRAIGHT||Direction.Current==GO_BACK||Direction.Current==KEEP_STOP)  Kd=-1 ;        else Kd=0;   //=============转向PD控制器=======================//Turn=-Turn_Target*Kp-gyro*Kd;                 //===结合Z轴陀螺仪进行PD控制return Turn;
}
6.电机PWM控制

通过上述一系列控制计算后,开发者就得到了使小车平衡的PWM值,将该PWM值幅值给对应寄存器,就可以查看小车运动状态。

void Set_Pwm(int moto1,int moto2)
{     if(moto2>0)		{AIN2_RESET;AIN1_SET;}else 	        {AIN2_SET;AIN1_RESET;}		TIM16_PWM_Set(myabs(moto2));if(moto1>0)	{BIN1_RESET;BIN2_SET;}else        {BIN1_SET;BIN2_RESET;}TIM17_PWM_Set(myabs(moto1));
}

结语

以上就是带有可视通话功能且可以行走微型巡逻摄像头的实现方案。感兴趣的同学可以尝试动手操作,这种巡逻摄像头体积小巧可爱,可以放在家里和家人互动,也可以解决很多因空间原因无法解决的很多工作场景问题。

这篇关于【内含实物图】一款可独立行走且支持远程对话的微型巡逻摄像头——嵌入式方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Java实现远程执行Shell指令

《Java实现远程执行Shell指令》文章介绍使用JSch在SpringBoot项目中实现远程Shell操作,涵盖环境配置、依赖引入及工具类编写,详解分号和双与号执行多指令的区别... 目录软硬件环境说明编写执行Shell指令的工具类总结jsch(Java Secure Channel)是SSH2的一个纯J

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方

Mac电脑如何通过 IntelliJ IDEA 远程连接 MySQL

《Mac电脑如何通过IntelliJIDEA远程连接MySQL》本文详解Mac通过IntelliJIDEA远程连接MySQL的步骤,本文通过图文并茂的形式给大家介绍的非常详细,感兴趣的朋友跟... 目录MAC电脑通过 IntelliJ IDEA 远程连接 mysql 的详细教程一、前缀条件确认二、打开 ID

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

MySQL容灾备份的实现方案

《MySQL容灾备份的实现方案》进行MySQL的容灾备份是确保数据安全和业务连续性的关键步骤,容灾备份可以分为本地备份和远程备份,主要包括逻辑备份和物理备份两种方式,下面就来具体介绍一下... 目录一、逻辑备份1. 使用mysqldump进行逻辑备份1.1 全库备份1.2 单库备份1.3 单表备份2. 恢复