收藏和点赞,您的关注是我创作的动力
文章目录
- 一、研究的主要内容和目标
- 二、总体方案设计
- [三、 小车结构设计](#三、 小车结构设计)
- [四、 原理图](#四、 原理图)
- [五、 总结](#五、 总结)
- [五、 文章目录](#五、 文章目录)
概要
如何让道路清洁更加高效,清洁效果更好,清洁成本更低,安全性更好,清洁更加环保,各大新能源汽车企业给出的答案是电动道路清洁车,这种最高时速平均在20-30km/h的小车完美地解决了以上的大部分问题。
本论文将介绍如何设计一款拥有市面上新能源清洁扫地机大部分功能的智能小车,论文一共分为三部分,是以单片机为开发基础,详细描述了我进行硬件电路设计、软件程序编写及小车关键功能部分结构设计的过程及结果。
关键词:智能小车;单片机;电机控制;扫地机;红外遥控
一、研究的主要内容和目标
本文研究的主要内容是设计一款可以通过遥控器操控的拥有扫地吸尘洒水功能的清洁小车,我采用STC89C52芯片作整车控制的主控芯片,RZ7899作为驱动电机的驱动芯片,通过设计,小车可以做到红外遥控,控制扫刷清扫地面,控制水泵洒水并雾化控尘,控制风机高速旋转吸尘,控制舵机进行垃圾箱举升。
设计过程大致为:
(1)电机选型,估算电机需要带多少负载以及合适的电机转速,根据电机型号选择合适的驱动芯片。
(2)电路硬件设计,根据所需要的功能选择合适的芯片,然后从网上下载该芯片的芯片手册,根据芯片手册的提示和典型应用电路设计电路图并进行元器件选型并在Altium designer软件中绘制出电路原理图和PCB图。
(3)软件设计,通过KEIL软件编写程序实现对所需要功能的控制
(4)结构设计,使用Catia三维建模软件对小车底盘,扫刷,垃圾箱等关键部位进行设计。
设计目标是通过所学知识设计出一台拥有市面上出现的智能扫地车大部分功能的智能清洁小车。
二、总体方案设计
2.1智能清洁小车的硬件系统组成
本文设计的智能清洁小车硬件电路部分主要由以下几个部分构成:(1)基于STC89C52的单片机最小系统(2)行走电机驱动模块(3)扫刷电机驱动模块(4)
水泵电机驱动模块(5)吸尘风机驱动模块(6)垃圾箱举升舵机驱动模块(7)红外接收模块(8)红外遥控发射模块。这8个部分构成了小车的硬件电路,我可以通过遥控器上的按键控制小车的工作模式,来完成清扫,吸尘,倒垃圾等任务。
2.2智能清洁小车的硬件结构图
表2-2-1清洁小车硬件结构图
三、 小车结构设计
5.1基本布局和功能分析
本车结构是根据循迹小车的结构改进而来,小车最前头的扫刷是通过一个轴套和两个正反牙的连接轴组成,顺时针拧动轴套可以将扫刷升起,逆时针拧动可以将扫刷放下。
电池被放置在扫刷两侧,左边那一块电池组主要供应控制模块和行走、水泵、扫刷电机驱动模块。右边那一块主要供应吸尘风机。中间则放置电源电路板,最小系统板,各模块驱动板。
小车中后部是水箱和垃圾箱,水箱前放置的是水泵电机,通过水泵电机将水箱内的水抽出流经扫刷上方的雾化喷头,再流回水箱,水箱上方的是垃圾箱,垃圾箱和水箱中间放置舵机,舵机通过一个连杆机构将垃圾箱升起,倒出垃圾,这里也可以将舵机放置在垃圾箱另一侧,直接带动垃圾箱旋转180度倾倒垃圾,风机和滤尘装置放置在垃圾箱内侧后方,通过将垃圾箱内部空气抽出,造成气压差,从而吸尘。而吸尘管从垃圾箱延伸出来后,经过小车底盘连接吸盘,考虑到道路可能出现不平整的情况,这里吸盘底部可以增加两个轮子防止吸盘和道路碰撞摩擦而造成磨损。
5.2小车二维及三维图
小车二维图:
图5-2 1 清洁小车结构二维图
小车三维图:
图5-2 2 清洁小车结构三维图
四、 原理图
程序
clike
红外发射代码
#include"reg52.h"
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit IRM_E=P3^4; //TO口作为红外发射口
sbit Key_UP=P2^0; //键码0x09
sbit Key_DOWN=P2^1; //键码0x16
sbit Key_LEFT=P2^2; //键码0x19
sbit Key_RIGHT=P2^3; //键码0x0d
sbit Key_STOP=P2^4; //键码0x0c
sbit Key_DUSTBIN_UP=P2^5; //启动键码0x45
sbit Key_DUSTBIN_DOWN=P2^6; //启动键码0x46
sbit Key_A_ONOFF=P2^7; //启动键码0x47,停止键码0x44
sbit Key_B_ONOFF=P0^0; //启动键码0x40,停止键码0x43
sbit Key_C_ONOFF=P0^1; //启动键码0x07,停止键码0x15
bit flag0=0;
bit flag1=0;
bit flag2=0;
bit flag3=0;
bit flag4=0;
bit flag5=0;
bit flag6=0;
bit flag7=0;
bit flag8=0;
bit flag9=0;
//延时8.77us,即1/3周期
void Delay8_77us() //@11.0592MHz
{
uchar i;
i=19;
while(--i);
}
//载波发射周期,26.3us=8.77us(发射红外光)+8.77us*2(不发射红外光)
void Send_IRM(uint i)
{
while(i--) //循环65535次
{
IRM_E=1; //红外发射启动
Delay8_77us(); //延时8.77us
IRM_E=0; //红外发射停止
Delay8_77us(); //延时8.77us
Delay8_77us(); //延时8.77us
}
}
//载波不发射周期,26.3us=8.77us*3,(不发射红外光)
void NO_Send_IRM(uint i)
{
while(i--) //循环65535次
{
IRM_E=0; //红外不发射
Delay8_77us(); //延时8.77us
Delay8_77us(); //延时8.77us,
Delay8_77us(); //延时8.77us
}
}
//发射数据0(NEC协议 载波发射0.56ms+载波不发射0.56ms)
void Send_NEC_0()
{
Send_IRM(21); //0.56ms=26.3us*21
NO_Send_IRM(21); //0.56ms=26.3us*21
}
//发射数据1(NEC协议 载波发射0.56ms+载波不发射1.68ms)
void Send_NEC_1()
{
Send_IRM(21); //0.56ms=26.3us*21
NO_Send_IRM(64); //1.68ms=26.3us*64
}
//按NEC编码顺序发送一帧完整数据(引导码,用户码低八位,用户码高八位,八位数据码,八位数据反码,结束码)
void Send_NEC_Message(uchar Code_Date)
{
uint Code_User;
uchar i; //定义无符号字符型i
uint Code_User_2; //定义无符号整形Code_User_2
Code_User_2=Code_User; //使用临时变量,防止修改形参
//发送引导码(载波发射9ms,载波不发射4.5ms)
Send_IRM(342); //9ms=26.3*342
NO_Send_IRM(171); //9ms=26.3*171
//发送十六位用户码
for(i=0;i<16;i++) //发送十六位用户码
{
if(Code_User_2&0X0001) //判断用户码是否为1
Send_NEC_1(); //发射1
else //否则
Send_NEC_0(); //发射0
Code_User_2>>=1; //执行完后用户码右移一位
}
//发送八位数据码
Code_User_2=Code_Date; //Code_Date的值赋给Code_User2
for(i=0;i<8;i++) //发送八位数据码
{
if(Code_User_2&0x01) //判断数据码是否为1
Send_NEC_1(); //发射1
else //否则
Send_NEC_0(); //发射0
Code_User_2>>=1; //执行完后数据码右移一位
}
//发送八位数据反码
Code_User_2=(~Code_Date);
for(i=0;i<8;i++) //发送八位数据反码
{
if(Code_User_2&0x01) //判断数据码是否为1
Send_NEC_1(); //发射1
else //否则
Send_NEC_0(); //发射0
Code_User_2>>=1; //执行完后数据码右移一位
}
//发送结束码
Send_NEC_0(); //发送结束码
}
//DUSTBIN_UP按键函数(按键抬手启动消抖,按一次执行启动程序,再按一次执行停止程序)
void KeyDUSTBINUP()
{
if(Key_DUSTBIN_UP==0&&flag0==0) //如果按键按下并且标志位flag0为0
{
flag0=1; //则标志位flag0置1
}
if(flag0==1&&Key_DUSTBIN_UP==1) //如果标志位flag0为1并且按键松开
{
flag1=~flag1; //则标志位flag1取反
}
if(flag1==1) //当flag1为1时
{
Send_NEC_Message(0x45); //红外发送键码0x45
}
flag0=0; //标志位flag0清零
}
//DUSTBIN_DOWN按键函数
void KeyDUSTBINDOWN()
{
if(Key_DUSTBIN_DOWN==0&&flag2==0) //如果按键按下并且标志位flag2为0
{
flag2=1; //则标志位flag2置1
}
if(flag2==1&&Key_DUSTBIN_DOWN==1) //如果标志位flag2为1并且按键松开
{
flag3=~flag3; //则标志位flag3取反
}
if(flag3==1) //当flag3为1时
{
Send_NEC_Message(0x46); //红外发送键码0x47
}
flag2=0; //标志位flag2清零
}
//Key_A_ONOFF按键
void KeyAONOFF()
{
if(Key_A_ONOFF==0&&flag4==0) //如果按键按下并且标志位flag4为0
{
flag4=1; //则标志位flag4置1
}
if(flag4==1&&Key_A_ONOFF==1) //如果标志位flag4为1并且按键松开
{
flag5=~flag5; //则标志位flag5取反
}
if(flag5==1) //当flag5为1时
{
Send_NEC_Message(0x47); //红外发送键码0x40
}
else //否则
{
Send_NEC_Message(0x44); //红外发送键码0x43
}
flag4=0; //标志位flag4清零
}
//Key_B_ONOFF按键
void KeyBONOFF()
{
if(Key_B_ONOFF==0&&flag6==0) //如果按键按下并且标志位flag6为0
{
flag6=1; //则标志位flag6置1
}
if(flag6==1&&Key_B_ONOFF==1) //如果标志位flag6为1并且按键松开
{
flag7=~flag7; //则标志位flag7取反
}
if(flag7==1) //当flag7为1时
{
Send_NEC_Message(0x40); //红外发送键码0x07
}
else //否则
{
Send_NEC_Message(0x43); //红外发送键码0x15
}
flag6=0; //标志位flag6清零
}
//Key_C_ONOFF按键
void KeyCONOFF()
{
if(Key_C_ONOFF==0&&flag8==0) //如果按键按下并且标志位flag8为0
{
flag8=1; //则标志位flag8置1
}
if(flag8==1&&Key_C_ONOFF==1) //如果标志位flag8为1并且按键松开
{
flag9=~flag9; //则标志位flag9取反
}
if(flag9==1) //当flag9为1时
{
Send_NEC_Message(0x07); //红外发送键码0x09
}
else //否则
{
Send_NEC_Message(0x15); //红外发送键码0x16
}
flag8=0; //标志位flag8清零
}
//Key_STOP按键
void KeySTOP()
{
if(Key_STOP==0) //如果按键按下
{
Delay8_77us(); //延时8.77US
if(Key_STOP==0) //再次判断按键是否按下
{
Send_NEC_Message(0x09); //红外发送键码0x0c
}
}
}
//Key_UP按键
void KeyUP()
{
if(Key_UP==0) //如果按键按下
{
Delay8_77us(); //延时8.77US
if(Key_UP==0) //再次判断按键是否按下
{
Send_NEC_Message(0x16); //红外发送键码0x0c
}
}
}
//Key_DOWN按键
void KeyDOWN()
{
if(Key_DOWN==0) //如果按键按下
{
Delay8_77us(); //延时8.77US
if(Key_DOWN==0) //再次判断按键是否按下
{
Send_NEC_Message(0x19); //红外发送键码0x15
}
}
}
//Key_LEFT按键
void KeyLEFT()
{
if(Key_LEFT==0) //如果按键按下
{
Delay8_77us(); //延时8.77US
if(Key_LEFT==0) //再次判断按键是否按下
{
Send_NEC_Message(0x0d); //红外发送键码0x09
}
}
}
//Key_RIGHT按键
void KeyRIGHT()
{
if(Key_RIGHT==0) //如果按键按下
{
Delay8_77us(); //延时8.77US
if(Key_RIGHT==0) //再次判断按键是否按下
{
Send_NEC_Message(0x0c); //红外发送键码0x16
}
}
}
//发送按键的红外数据
void main()
{
while(1)
{
KeyUP(); //小车前进
KeyDOWN(); //小车后退
KeyLEFT(); //小车左转
KeyRIGHT(); //小车右转
KeySTOP(); //小车停止
KeyDUSTBINUP(); //垃圾箱升起
KeyDUSTBINDOWN(); //垃圾箱放下
KeyAONOFF(); //扫刷启动/停止
KeyBONOFF(); //吸尘风机启动/停止
KeyCONOFF(); //抑尘水泵启动/停止
}
}
红外接收驱动代码
#include"reg52.h"
#include"uart.h"
#include"intrins.h"
#define u8 unsigned char;
#define u16 unsigned short;
#define u32 unsigned int;
sbit IRM_R=P3^2;
u8 IR_CODE[5]; //定义5个8位数据,分别存放用户码、用户码反码、按键键值码、按键键值反码、验证后的键值
u8 i=0; //定义一个无符号字符型变量i,用于循环接收四组数据
u8 j=0; //定义一个无符号字符型变量j,用于接收一组数据中8个bit
u16 count; //定义一个计数变量,用来循环计数设置等待超时时间
sbit MA_F1=P0^5;
sbit MA_B1=P0^6;
sbit MB_F1=P0^7;
sbit MB_B1=P2^0;
sbit MC_F1=P2^1;
sbit MC_B1=P2^2;
sbit MD_F1=P2^3;
sbit MD_B1=P2^4;
sbit A_F1=P0^1;
sbit A_B1=P0^2;
sbit B_F1=P0^3;
sbit B_B1=P0^4;
sbit S_BRUSHA_F1=P2^5;
sbit S_BRUSHA_B1=P2^6;
sbit S_BRUSHB_F1=P2^7;
sbit S_BRUSHB_B1=P3^0;
sbit PWM0=P0^0;
u16 SERVO_PWM=500;
u8 j,k,l,m,n;
//延时函数8ms
void Delay8ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 87;
j = 12;
do
{
while (--j);
} while (--i);
}
//延时函数10us
void Delay10us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 25;
while (--i);
}
//延时函数100us
void Delay100us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
//延时函数300ms
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 13;
j = 156;
k = 83;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
//红外接收初始化函数
void IR_INIT()
{
IT0=1; //下降沿触发
EX0=1; //允许外部中断
EA=1; //开启总中断
IRM_R=1; //初始化端口为高电平
}
//串口初始化函数
void Uart_Init()
{
TMOD = 0x20; // T1设置为8位自动重装载定时器
SCON = 0x40; // 串口工作在模式1:8位UART波特率可变,且禁止接收
TH1 = 0xE6; // 波特率为2400且波特率加倍时的定时器设置值。
TL1 = TH1;
PCON = 0x80; // 设置为波特率加倍
EA = 1; // 开总中断
ES = 1; // 开串口中断
TR1 = 1; // 定时器1开启计数
}
//串口发送1字节
void Uart_SendByte(int c)
{
SBUF = c; //通过串口寄出数据
while (!TI); //查询T1标志位,等待八位数据发送完毕
TI = 0; //当八位数据发送完毕,中断标志位清零
}
//中断处理函数
void IRISR() interrupt 0
{
//判断引导码 //如果接收到红外信号,首先接收到的是引导码
Delay8ms(); //引导码低电平一共9ms,先延时8ms
if(IRM_R==0) //判断是不是低电平,如果是低电平,则继续判断,如果不是,则是干扰
{
count=200; //给超时检测count赋值200(由于之前延时了8ms,引导码低电平还剩1ms(100*10us=1ms))
while((IRM_R==0)&&(count>0)) //当红外接收引脚为低电平且count大于0时(如果循环100次后IRM_R变为1跳出循环,则继续判断)
{ //(如果将200次循环完,低电平一共持续10ms,超时,该信号不是引导码)
Delay10us(); //延时10us(间隔10us检测一次)
count--; //每循环一次,count值减一
}
if(IRM_R==1) //判断IRM_R是不是高电平(引导码高电平一共4.5ms)
{
count=500; //给超时检测count赋值500(500*10us=5ms)
while((IRM_R==1)&&(count>0)) //当红外接收引脚为高电平且count大于0时(如果循环450次后IRM_R变为0跳出循环,则该信号为引导码)
{ //(如果将500次循环完,高电平一共持续5ms,超时,该信号不是引导码)
Delay10us(); //延时10us(间隔10us检测一次)
count--; //每循环一次,count值减一
}
//接收用户码和数据码
for(i=0;i<4;i++) //接收四个字节(十六位用户码,八位数据码,八位数据反码)
{
for(j=0;j<8;j++) //接收八位数据
{
count=60; //count赋值60(60*10us=0.6ms)
while((IRM_R==0)&&(count>0)) //载波发射(低电平)0.56ms,循环56次后跳出循环
{
Delay10us();
count--;
}
count=0;
while(IRM_R==1) //判断载波不发射(高电平)持续时间,
{ //若为0.56ms,则接收0,若为1.68ms,则接收1
Delay100us(); //延时0.1ms
count++; //理论上count为17,接收1,count为6,接收0
}
IR_CODE[i]>>=1; //右移一位(数据从低位往高位传输)
if(count>=11) //判断count为17还是6,(168us-56us)/100us=11
{
IR_CODE[i]=0x80; //将数组放置最高位
}
}
}
}
if(IR_CODE[2]==~IR_CODE[3]) //判断按键数据码和数据反码是否相等
{
IR_CODE[4]=IR_CODE[2]; //如果相等,则将按键数据码跟新到IR_CODE[4]
return; //跳出子函数
}
}
}
//小车直走
void go_straight()
{
MA_F1=1; //根据RZ7899芯片手册,
MA_B1=0; //F1=1,B1=0电机正转
MB_F1=1; //F1=0,B1=1电机反转
MB_B1=0; //F1=0,B1=0电机悬空
MC_F1=1; //F1=1,B1=1电机制动
MC_B1=0; //所以小车直走就是四个电机全部正转
MD_F1=1;
MD_B1=0;
}
//小车后退
void back_off()
{
MA_F1=0; //小车后退是四个电机全部反转
MA_B1=1;
MB_F1=0;
MB_B1=1;
MC_F1=0;
MC_B1=1;
MD_F1=0;
MD_B1=1;
}
//小车左转
void turn_left()
{
MA_F1=0; //小车左转是右边电机正转,左边电机悬空
MA_B1=0;
MB_F1=0;
MB_B1=0;
MC_F1=1;
MC_B1=0;
MD_F1=1;
MD_B1=0;
}
//小车右转
void turn_right()
{
MA_F1=1; //小车右转是左边电机正转,右边电机悬空
MA_B1=0;
MB_F1=1;
MB_B1=0;
MC_F1=0;
MC_B1=0;
MD_F1=0;
MD_B1=0;
}
//小车刹车
void brake()
{
MA_F1=1; //刹车是四个电机制动
MA_B1=1;
MB_F1=1;
MB_B1=1;
MC_F1=1;
MC_B1=1;
MD_F1=1;
MD_B1=1;
}
//吸尘风机工作/停止
void A_ON()
{
A_F1=1;
A_B1=0;
}
void A_OFF()
{
B_F1=1;
B_B1=1;
}
//水泵电机工作/停止
void B_ON()
{
B_F1=1;
B_B1=0;
}
void B_OFF()
{
B_F1=1;
B_B1=1;
}
//扫刷电机工作/停止
void S_BRUSH_ON()
{ //扫刷是将垃圾清扫到中间
S_BRUSHA_F1=1; //所以要一个正转一个反转
S_BRUSHA_B1=0;
S_BRUSHB_F1=0;
S_BRUSHA_B1=1;
}
void S_BRUSH_OFF()
{
S_BRUSHA_F1=1;
S_BRUSHA_B1=1;
S_BRUSHB_F1=1;
S_BRUSHA_B1=1;
}
//垃圾箱举升舵机升起/降下
//ms延时函数
void Delayms(unsigned char ms) //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
//定时器清零
void Timer0_INIT()
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //开定时器0中断
}
//给定时器赋值产生中断
void Timer0_Value(unsigned int pwm)
{
unsigned short value;
value=0xffff-pwm; //因为定时器是TH0,TL0都要全部计数到0xFF后在计1个数就会产生中断,所以要想产生
//pwm毫秒的中断,那么TH0,TL0就应该赋值(0xFFFF-pwm)
TR0 = 0;
TL0=value; //16位数据给8位数据赋值默认将16位数据的低八位直接赋给八位数据
TH0=value>>8; //将16位数据右移8位,也就是将高8位移到低八位,再赋值给8位数据
TR0 = 1; //定时器启动
}
//中断处理函数
void Timer0_isr() interrupt 1 using 1
{
static u16 i = 1; //定义一个静态变量,每次调用函数时保持上一次所赋的值
switch(i)
{
case 1:
PWM0=1; //PWM控制管脚高电平
Timer0_Value(SERVO_PWM); //给定时器0赋值,计数SERVO_PWM个脉冲后产生中断,下次中断会进入下一个case语句
break;
case 2:
PWM0=0; //PWM控制管脚低电平
Timer0_Value(20000-SERVO_PWM); //高脉冲结束后剩下的时间(20000-SERVO_PWM)全是低电平了,
i = 0; //20000个脉冲正好为一个周期20毫秒
break;
}
i++;
}
//垃圾箱升起
void DUSTBIN_UP()
{
Timer0_INIT(); //定时器0初始化
EA = 1; //开总中断
SERVO_PWM = 500; //脉冲宽度在500微秒,对应0°
Delayms(500); //延时0.5秒
SERVO_PWM = 1000; //脉冲宽度在1000微秒,对应45°
Delayms(500);
SERVO_PWM = 1500; //脉冲宽度在1000微秒,对应90°
Delayms(500);
SERVO_PWM = 2000; //脉冲宽度在1000微秒,对应135°
Delayms(500);
SERVO_PWM = 2500; //脉冲宽度在1000微秒,对应180°
Delayms(500);
}
//垃圾箱降下
void DUSTBIN_DOWN()
{
Timer0_INIT(); //定时器0初始化
EA = 1; //开总中断
SERVO_PWM = 2500; //脉冲宽度在500微秒,对应180°
Delayms(500); //延时0.5秒
SERVO_PWM = 2000; //脉冲宽度在1000微秒,对应135°
Delayms(500);
SERVO_PWM = 1500; //脉冲宽度在1000微秒,对应90°
Delayms(500);
SERVO_PWM = 1000; //脉冲宽度在1000微秒,对应45°
Delayms(500);
SERVO_PWM = 500; //脉冲宽度在1000微秒,对应0°
Delayms(500);
}
void main(void)
{
IR_INIT();
Uart_Init();
while (1)
{
Uart_SendByte();
Delay300ms();
//小车行走
switch(j)
{
case 1: IR_CODE[4]=0x09;
go_straight();
break;
case 2: IR_CODE[4]=0x16;
back_off();
break;
case 3: IR_CODE[4]=0x19;
turn_left();
break;
case 4: IR_CODE[4]=0x0d;
turn_right();
break;
case 5: IR_CODE[4]=0x0c;
brake();
break;
default: j=0;
break;
}
//垃圾箱升降
switch(k)
{
case 1: IR_CODE[4]=0x45;
DUSTBIN_UP();
break;
case 2: IR_CODE[4]=0x46;
DUSTBIN_DOWN();
break;
default: k=0;
break;
}
//吸尘器工作
switch(l)
{
case 1: IR_CODE[4]=0x47;
A_ON();
break;
case 2: IR_CODE[4]=0x44;
A_OFF();
break;
default: l=0;
break;
}
//洒水器工作
switch(n)
{
case 1: IR_CODE[4]=0x40;
B_ON();
break;
case 2: IR_CODE[4]=0x43;
B_OFF();
break;
default: n=0;
break;
}
//扫刷工作
switch(m)
{
case 1: IR_CODE[4]=0x07;
S_BRUSH_ON();
break;
case 2: IR_CODE[4]=0x15;
S_BRUSH_OFF();
break;
default: m=0;
break;
}
}
}
五、 总结
第一个难点在于电机选型上,由于一开始设计整车的结构还没有确定,我无法判断需要多少扭矩及多少转速的电机,于是我在淘宝上买了一个智能小车模型,用卷尺量出模型的大致尺寸并加以修改,然后在三维软件里画出模型并赋予材料估算重量,再根据我实习时的经验,参考公司的新能源清洁车绘制了一个大概的小车结构,再结合网上的智能小车实验案例,进而估算出本设计需要的电机扭矩、转速和电压。
第二个难点是芯片选型和元器件选型,市面上主流的电机驱动芯片是L298N和ULN2003A,考虑到ULN2003A不适合驱动直流电机,而L298N外部电路相对复杂,所以我选择了更为简单的RZ7899作为电机驱动芯片。元器件选型应该算是我在设计过程中最难解决的问题了,一些描述详细的芯片手册还好,会给出典型应用电路和元件选型参考,但还是会遇到一些元器件需要自己来计算和判断参数,我的解决办法是去淘宝和立创商城里,搜索自己需要的元器件,再根据卖家或商城中给出的参数和元器件手册来选择。
第三个难点是PCB绘制,一开始我是根据元件手册给出的尺寸自己绘制元件库,工作量非常巨大,但因为疫情无法制作实物,我就改成去淘宝上买现成的二维三维封装库了,这导致本设计的部分元器件并不是按照电路设计中BOM表给出的封装来画的,如果要制作出实物,还是要按照元件尺寸重新绘制。
五、 文章目录
目 录
1 绪论 6
1.1 研究背景及意义 6
1.1.1 研究背景 6
1.1.2 本设计的目的、意义 6
1.2 国内外研究现状 7
1.3智能清扫车的发展趋势 7
1.4 研究的主要内容和目标 8
1.5 本章小结 8
2总体方案设计 9
2.1智能清洁小车的硬件系统组成 9
2.2智能清洁小车的硬件结构图 9
2.3智能清洁小车的电机选型 10
2.4本章小结 11
3 硬件电路设计 12
3.1单片机最小系统板设计 12
3.2锂电池平衡充电电路 16
3.3过放保护电路 21
3.4线性稳压电路 24
3.5行走电机、扫刷电机、水泵电机驱动电路 28
3.6吸尘风机驱动电路 32
3.7垃圾箱举升舵机驱动电路 35
3.8红外接收电路 40
3.9红外发送遥控电路 42
3.10本章总结 47
4.软件编程设计 48
4.1基本思路 48
4.2红外发射程序设计 48
4.3红外接收驱动程序设计 48
4.4本章总结 49
5.小车结构设计 50
5.1基本布局和功能分析 50
5.2小车二维及三维图 51
5.3本章小结 52
6.结束语 53
6.1结论 53
6.11设计总结和难点 53
6.1.2设计创新点 54
6.13设计的不足点 54
参考文献 55
致谢 55
附录A:系统原理图 56
附录B:程序代码 57
红外发射代码 57
红外接收驱动代码 66