设为首页 收藏本站
开启辅助访问 切换到宽版

  找回密码
  立即注册

QQ登录

只需一步,快速开始

快捷导航
  • 论坛
  • 问答区
  • 单片机教程
  • 单片机DIY
  • 电子DIY
  • 帮助

热门: 51单片机 | 24小时必答区 | 单片机教程 | 单片机DIY制作 | STM32 | Cortex M3 | 模数电子 | 电子DIY制作 | 音响/功放 | 拆机乐园 | Arduino | 嵌入式OS | 程序设计

搜索
» 论坛 电子技术分类讨论区 智能小车/机器人 DIY一辆智能电磁循迹小车(提供原理图和PCB STM32程序)
返回列表 发新帖
查看: 19013|回复: 10
收起左侧

DIY一辆智能电磁循迹小车(提供原理图和PCB STM32程序)

  [复制链接]
ID:163153 发表于 2019-12-1 21:08 | 显示全部楼层 | 阅读模式
近期为了迎接校赛,折腾了很久搞了一辆电磁循迹小车,现在决定将小车的资料开源。楼主目前还是小白,大佬勿喷,欢迎大家参考和下载。
59BDE612A05D376C54131C66CF55B42C.jpg

小车采用三轮车结构,前驱,驱动部分为2个步进电机,驱动模块是A4988,电源采用2节3000mAH的松下18650锂电池,续航开源达到2-3小时。A4988模块供电电压为12V,所以板载集成了一个XL6009升压电路,电压升至12V,电源部分还有2个低压LDO,提供5V和3.3V电源,分别共给电磁循迹模块和单片机等等。XL6009升压电路有点小毛病,建议大家修改一下。
862CC9F20BEFE594FD0B27B0A0BC6771.jpg



57C200C46D3C745CFFF759A56C4D63CC.jpg



IMG_20191105_165128.jpg

底盘是咸鱼收的二手平衡小车之家底盘,然后自己找了2个42步进电机。
3.jpg

原理图和PCB大家可以参考参考,板载有集成2片TP4056X充电芯片,这样可以方便充电,不至于每次都要取出来用专门的充电器充电。至于为什么要用2片TP4056X并联,是因为电池容量较大,单片TP4056X充电电流只有1A,充满需要6小时,实在是太久了。
D26C1PT575EF(}15{6((DTT.png



%C@A_TX[M2RHG~JGZ{JHKRO.png

前期时间比较赶,而且是抱着划水的态度,程序比较Low,仅供参考。

单片机源程序如下:
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"
  5. #include "oled.h"
  6. #include "pwm.h"
  7. #include "key.h"
  8. #include "adc.h"
  9. #include "timer.h"
  10. #include "flash.h"

  11.         

  12. #define FLASH_START_ADDR  0x0801f000          //写入的起始地址

  13. u8 t=0,flag=0,valu;
  14. u16 pwm=15000,adc_1,adc_2,adc_3,adc_4,adc_5,adc_6;
  15. void ADC_display();         //ADC采集界面
  16. void PWM_speed();                      //PWM参数
  17. void ADC_collection();                //ADC采集
  18. void MOTOR_different();         //步进电机差速        
  19. void way();                 //寻迹
  20. int main(void)
  21. {        

  22.         delay_init();             //延时初始化
  23.         uart_init(9600);                 //串口初始化为9600
  24.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
  25.          LED_Init();                                //初始化与LED连接的硬件接口
  26.         KEY_Init();
  27.         Adc_Init();                                  //ADC初始化
  28.         OLED_Init();                        //初始化OLED         
  29. //        pwm = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASH
  30.          
  31.     TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms  
  32.          
  33. //        TIM4_PWM_Init(pwm,0);//不分频。PWM频率=72000/(899+1)=80Khz
  34. //        TIM_SetCompare3(TIM4,pwm/2);            
  35. //        
  36. //        TIM5_PWM_Init(pwm,0);//不分频。PWM频率=72000/(899+1)=80Khz
  37. //        TIM_SetCompare2(TIM5,pwm/2);        
  38.          
  39.         DIR1=0;
  40.         ENA1=0;           //左轮
  41.         ENA2=0;
  42.         DIR2=1;    //右轮
  43.         
  44.         
  45.         
  46.          
  47.         OLED_Show_Font_16x16(0,00,8);
  48.         OLED_Show_Font_16x16(0+16,00,9);
  49.         OLED_Show_Font_16x16(0,16,10);
  50.         OLED_Show_Font_16x16(0+16,16,11);
  51.         OLED_Show_Font_16x16(0+32,16,12);   
  52.         OLED_Show_Font_16x16(0+48,16,13);        
  53.         OLED_ShowString(0+64,16,"......",16);  //系统初始化界面
  54.         OLED_Refresh_Gram();      //更新显示到OLED
  55.         delay_ms(500);
  56.         for(valu=0;valu<128;valu++)                                  //加载系统读条
  57.         {
  58.                 valu++;
  59.                 OLED_Fill(0,48,valu,64,1);   
  60.                 delay_ms(10);
  61.         }
  62.         

  63.                 while(1)
  64.                 {
  65.                         way();              //寻迹
  66.                         
  67.                 }

  68. }

  69. void ADC_display()
  70. {
  71.         
  72.         if(flag==0)
  73.         {
  74.                 OLED_Clear();       //清屏
  75.                 OLED_ShowString(5,0," ADC",24);  
  76.                 OLED_Show_Font_24x24(0+58,00,7);   
  77.                 OLED_Show_Font_24x24(0+80,00,8);                //显示ADC采集 字样
  78.                 OLED_ShowString(0,24,"CH1:       CH2:",12);  
  79.                 OLED_ShowString(0,38,"CH3:       CH4:",12);  
  80.                 OLED_ShowString(0,52,"CH5:       CH6:",12);  
  81.                 OLED_Refresh_Gram();      //更新显示到OLED         
  82.                 flag=1;     //标志位置1
  83.         }
  84.         
  85.         
  86. //        while(1)
  87. //        {
  88.                
  89.                 OLED_ShowNum(28,24, adc_1,4,12);    //ADC值
  90.                 OLED_ShowNum(100,24,adc_2,4,12);    //ADC值
  91.                 OLED_ShowNum(28,38, adc_3,4,12);    //ADC值
  92.                 OLED_ShowNum(100,38,adc_4,4,12);    //ADC值
  93.                 OLED_ShowNum(28,52, adc_5,4,12);    //ADC值
  94.                 OLED_ShowNum(100,52,adc_6,4,12);    //ADC值
  95.             OLED_Refresh_Gram();       //更新显示到OLED
  96.                 LED0=!LED0;
  97.                
  98.                 t=KEY_Scan(0);
  99. //            if(t==KEY2_PRES)
  100. //                PWM_speed();
  101. //        }
  102.         
  103. }

  104. void PWM_speed()
  105. {
  106.         u16 a,r,p;
  107.         
  108.         OLED_Clear();        //清屏
  109.         OLED_ShowString(5,0," PWM",24);         
  110.         OLED_Show_Font_24x24(0+56,00,9);                        
  111.         OLED_Show_Font_24x24(0+80,00,10);                        //显示PWM参数 字样
  112.         OLED_ShowString(0,24, "PWM CCRx:",16);  
  113.         OLED_ShowString(0,40,"Pulse:       Hz",12);  
  114.         OLED_ShowString(0,52,"Speed:       r/min",12);  
  115.         
  116.         OLED_ShowNum(70,24,pwm,5,16);  //pwm CCRx值    恢复上一次退出前的值
  117.         OLED_ShowNum(40,40,p,5,12);    //脉冲速度
  118.         OLED_ShowNum(45,52,r,3,12);    //电机转速
  119.         OLED_Refresh_Gram();       //更新显示到OLED                 
  120.    

  121. //        while(1)
  122. //        {        

  123.    
  124.         t=KEY_Scan(0);                //得到键值
  125.                 switch(t)
  126.                 {                                 
  127.                         case KEY0_PRES:
  128.                                 pwm=pwm-500;   //6000-50000
  129.                                         if(pwm<=6000)
  130.                                                 pwm=6000;
  131.                                         p=(72000000/pwm);
  132.                                         r=((p*60)/3200);
  133.                                 TIM4_PWM_Init(pwm,0);
  134.                             TIM_SetCompare3(TIM4,pwm/2);
  135.                                 TIM5_PWM_Init(pwm,0);
  136.                             TIM_SetCompare2(TIM5,pwm/2);
  137.                                 OLED_ShowNum(70,24,pwm,5,16);  //pwm CCRx值
  138.                             OLED_ShowNum(40,40,p,5,12);    //脉冲速度
  139.                             OLED_ShowNum(45,52,r,3,12);    //电机转速
  140.                             OLED_Refresh_Gram();  //更新显示到OLED
  141.                         //        FLASH_W(FLASH_START_ADDR,pwm); //从指定页的地址写入FLASH
  142.                                 break;
  143.                         case KEY1_PRES:
  144.                                 pwm=pwm+500;
  145.                                         if(pwm>=50000)
  146.                                                 pwm=50000;
  147.                                         p=(72000000/pwm);
  148.                                         r=((p*60)/3200);
  149.                                 TIM4_PWM_Init(pwm,0);
  150.                             TIM_SetCompare3(TIM4,pwm/2);
  151.                                 TIM5_PWM_Init(pwm,0);
  152.                             TIM_SetCompare2(TIM5,pwm/2);
  153.                                 OLED_ShowNum(70,24,pwm,5,16);
  154.                             OLED_ShowNum(40,40,p,5,12);
  155.                             OLED_ShowNum(45,52,r,3,12);
  156.                                 OLED_Refresh_Gram();//更新显示到OLED
  157.                         //        FLASH_W(FLASH_START_ADDR,pwm); //从指定页的地址写入FLASH
  158.                                 break;
  159.                         case KEY2_PRES:                                
  160.                                 ADC_display();
  161.                                 break;
  162.                         default:
  163.                                 delay_ms(10);        
  164. //                }
  165. //                OLED_ShowChar(36,52,t,12,1);//显示ASCII字符        
  166. //                OLED_ShowNum(94,52,t,3,12);        //显示ASCII字符的码值   
  167. //                OLED_ShowNum(36,52,t,3,12);        //显示ASCII字符的码值   
  168. //                OLED_Refresh_Gram();//更新显示到OLED

  169.         }         
  170. }

  171. void ADC_collection()
  172. {
  173.         adc_1=Get_Adc_Average(ADC_Channel_7,10);  //得到ADC采集值  CH7
  174.         adc_2=Get_Adc_Average(ADC_Channel_6,10);  //得到ADC采集值  CH6
  175.         adc_3=Get_Adc_Average(ADC_Channel_5,10);  //得到ADC采集值  CH5
  176.         adc_4=Get_Adc_Average(ADC_Channel_4,10);  //得到ADC采集值  CH4
  177.         adc_5=Get_Adc_Average(ADC_Channel_3,10);  //得到ADC采集值  CH3
  178.         adc_6=Get_Adc_Average(ADC_Channel_2,10);  //得到ADC采集值  CH2
  179. }

  180. void MOTOR_different()
  181. {
  182.         OLED_Show_Font_16x16(16,00,0);
  183.         OLED_Show_Font_16x16(16+16,00,1);
  184.         OLED_Show_Font_16x16(16+32,00,2);
  185.         OLED_Show_Font_16x16(16+48,00,3);
  186.         OLED_Show_Font_16x16(16+64,00,6);
  187.         OLED_Show_Font_16x16(16+80,00,7);
  188.                 while(1)
  189.                 {
  190.                         
  191.                 }
  192. }

  193. void way()
  194. {        
  195.         PWM_speed();
  196.         while(1)
  197.         {
  198.                 ADC_collection();      //ADC信号采集
  199.                 ADC_display();
  200.                
  201.                
  202.                 if(1500<adc_3 && adc_3<3000 && 1500<adc_4 && adc_4<3000)        //直行
  203.                 {
  204.                         if(ENA1==1)
  205.                         {
  206.                                 ENA1=0;           //左轮使能开启
  207.                                 ENA2=0;           //右轮使能开启
  208.                         }
  209.                                 TIM4_PWM_Init(pwm,0);
  210.                                 TIM_SetCompare3(TIM4,pwm/2);
  211.                                 TIM5_PWM_Init(pwm,0);
  212.                                 TIM_SetCompare2(TIM5,pwm/2);
  213.                                 
  214.                                 OLED_ShowString(116,0," ",24);
  215.                                 OLED_ShowString(116,0,"M",24);
  216.                                 OLED_Refresh_Gram();//更新显示到OLED
  217.                
  218.                 }
  219.                
  220.                 if(2500<=adc_4 && adc_3<=2000)     //左转弯
  221.                 {
  222.                         if(ENA1==1)
  223.                         {
  224.                                 ENA1=0;           //左轮使能开启
  225.                                 ENA2=0;           //右轮使能开启
  226.                         }
  227.                                 TIM4_PWM_Init(pwm,0);
  228.                                 TIM_SetCompare3(TIM4,pwm/2);
  229.                                 TIM5_PWM_Init(pwm/2,0);
  230.                                 TIM_SetCompare2(TIM5,pwm/4);
  231.                                 
  232.                                 OLED_ShowString(116,0," ",24);
  233.                                 OLED_ShowString(116,0,"L",24);
  234.                                 OLED_Refresh_Gram();//更新显示到OLED
  235.                
  236.                 }
  237.                
  238.                 if(adc_4<2000 && 2500<adc_3)     //右转弯
  239.                 {
  240.                         if(ENA1==1)
  241.                         {
  242.                                 ENA1=0;           //左轮使能开启
  243.                                 ENA2=0;           //右轮使能开启
  244.                         }               
  245.                                 TIM4_PWM_Init(pwm/2,0);
  246.                                 TIM_SetCompare3(TIM4,pwm/4);
  247.                                 TIM5_PWM_Init(pwm,0);
  248.                                 TIM_SetCompare2(TIM5,pwm/2);
  249.                                 
  250.                                 OLED_ShowString(116,0," ",24);
  251.                                 OLED_ShowString(116,0,"R",24);
  252.                                 OLED_Refresh_Gram();//更新显示到OLED
  253.                
  254.                 }
  255.                
  256.                 if(adc_3<300 && adc_4<300)            //停止
  257.                 {
  258.                         if(ENA1==0)
  259.                         {
  260.                
  261.                                 ENA1=1;           //左轮使能关闭
  262.                                 ENA2=1;           //右轮使能关闭
  263.                                 
  264.                         }
  265.                         
  266.                         OLED_ShowString(116,0," ",24);
  267.                         OLED_ShowString(116,0,"S",24);
  268.                         OLED_Refresh_Gram();//更新显示到OLED
  269.                         
  270.                         
  271.                 }
  272.                
  273. //                delay_ms(10);
  274.         }
  275.         
  276. }
复制代码

51hei.png

全部资料51hei下载地址:
原理图PCB.rar (18.35 MB, 下载次数: 260)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:526170 发表于 2020-5-3 00:14 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:590242 发表于 2020-6-9 21:22 | 显示全部楼层
请问有电磁循迹模块的bom表吗
回复

使用道具 举报

ID:780742 发表于 2021-3-31 10:09 | 显示全部楼层
同问,请问有电磁的bom表嘛
回复

使用道具 举报

ID:880210 发表于 2021-4-19 00:28 | 显示全部楼层
有传感器的原理图吗
回复

使用道具 举报

ID:582255 发表于 2022-10-12 16:05 | 显示全部楼层
请问那个AD采样是干什么用的
回复

使用道具 举报

ID:65066 发表于 2023-8-22 10:48 | 显示全部楼层

谢谢楼主分享,下载学习了
回复

使用道具 举报

ID:1097415 发表于 2023-10-28 12:35 | 显示全部楼层
用的什么仿真软件啊
回复

使用道具 举报

ID:1084042 发表于 2024-4-29 14:57 | 显示全部楼层
zzhh190807 发表于 2021-4-19 00:28
有传感器的原理图吗

亲亲 有原理图了吗
回复

使用道具 举报

ID:1084042 发表于 2024-4-29 14:58 | 显示全部楼层
帅同学 发表于 2021-3-31 10:09
同问,请问有电磁的bom表嘛

亲亲 有了吗
回复

使用道具 举报

ID:1119398 发表于 2024-5-6 09:44 | 显示全部楼层
想知道底盘大小还有电路板的尺寸大小
回复

使用道具 举报

返回列表 发新帖
高级模式
B Color Image Link Quote Code Smilies
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版| 小黑屋| 51黑电子论坛 | 51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表