智能小车速通版——手把手教程

考虑到大部分学校,会发放简易小车来作为智能车初期培训和筛选的工具,

于是,我写一个简单的教程,能够实现简单小车的电磁循迹。

通过这个教程,能够通过简化的步骤搭建寻迹小车,进而了解整个智能车是如何实现的,快速上手,为后续参与智能车竞赛做准备。

这里我不会讲解原理,直接手把手带着使用,需要看原理的时候就看我相关博客。

目录

一、准备

C语言

单片机

二、器件

三、安装编程环境软件KEIL

1.安装KEIL

 2.激活License

 3.安装pack包

四、下载逐飞开源库

五、测试器件

电机转

屏幕

ADC

六、装车

七、循迹

电机

循迹


一、准备

C语言

智能车入门——编程语言(c)的学习

 智能车入门补充篇——模块化编程

首先要有一定的C语言基础。

想要学嵌入式,C语言必须学会!

这里一定不要为了进度图快,打好基础很重要。当时带我们的学长,给了我们一周的时间让我们复习C语言。

推荐平台:

菜鸟教程 - 学的不仅是技术,更是梦想!

 郝斌C语言

下面必须要掌握:

初学阶段要学会掌握基本的概念、函数、数组、语法关键词if,for,while的使用即可,指针与结构体部分可以在后期再进行补充学习。

这虽然就两行字,但是一定要扎实,好好打好基础,数据类型、运算符号都要会,别到时候用除法打了个"\"还不知道哪里错了。uint=unsigned int这种小知识别漏了。

单片机

需要简单了解一下什么是单片机,起码知道什么是IO口。

智能车入门——I/O、PWM

推荐学习平台:

51单片机普中科技视频完整版0基础入门学习_哔哩哔哩_bilibili

51单片机入门教程-2020版 程序全程纯手打 从零开始入门_哔哩哔哩_bilibili

 最低的要求是跟着教程,能够点亮LED灯。

二、器件

一个舵机将近100块,一个摄像头得两三百,大部分学校选拔应该会选用这种廉价的小车,靠电机实现前进和转向。

那么我就拿这种最简单的小车举例,介绍循迹最起码有的器件:

单片机(一般是STC)

电源(电池),

电机驱动(一般练手用的是L298N),

电机(小马达)、轱辘,

还有传感器,光电循迹用光电传感器,电磁循迹用电容电感对+运放

如果硬件给力点,还会有主板将前面的接口合并到一个板子上

为了方便看参数,还会有屏幕。

三、安装编程环境软件KEIL

Keil C51是美国Keil软件公司(现已被ARM公司收购)出品的支持8051系列单片机架构的一款 IDE

 【精选】智能车入门——IDE安装以及库函数选用

STC8系列 MDK FOR C51 IDE软件
链接:https://pan.baidu.com/s/10eqOQOFn7JapLJ_1Wc_DTQ   提取码:aom2

STC16专用 MDK FOR C251 IDE软件:链接:https://pan.baidu.com/s/1euVGEsRCV_novTHqnhQD7Q   提取码:krw6

 需要这三个文件,MDK532是keil的安装文件,keygen是破解软件,C51V960a是C51的pack包

1.安装KEIL

首先点击运行mdk532.exe文件

然后一路Next

路径自己选,name随便填

 2.激活License

(1)右击图标,用管理员身份运行!

(2)把ID复制下来

(3)把电脑静音

(4)右击keygen_new2032,用管理员身份运行

 把ID粘贴进去,

Target这里,STC8选C51,STC32选C251

不知道自己手里的该装哪个,你就百度或者问卖板子的客服

下面的选prof....PLUS

点击Generate,生成激活码

 (5)打开KEIL复制生成的激活码,粘贴在New License ID Code处,点击Add LIC,即可成功激活mdk,显示mdk的使用期限2032年

 3.安装pack包

双击c51v960a.exe,一路next。

这里pack包需要与自己的单片机相匹配,没有pack包的话,向卖板子的客服要就行了。

四、下载逐飞开源库

 智能车入门——库函数选用

找到自己的型号下载 

SeekFree (seekfree) - Gitee.com

 复制Seekfree_XXXXXXX_Opensource_Library文件夹,在此基础上增添代码,最后放到中文路径。

Seekfree_STC8A8K64S4_Opensource_Library\Project\MDK

双击该路径下的SEEKFREE.uvproj文件,即可打开工程

五、测试器件

首先写代码,看自己能不能调用那些器件。

【逐飞科技】STC8G2K 核心板与智能车常用模块搭配使用视频教程_哔哩哔哩_bilibili

【精选】智能车入门——简单驱动常用模块

电机转

电机驱动有两种

一种是两路PWM,另一种是一路PWM,一路 GPIO。

两路PWM,就是根据两个pwm信号 差值的正负决定电机转动方向,差值大小决定电机转速,

 一路PWM,一路 GPIO,就是pwm控制转速,GPIO控制方向。

想知道你手上的驱动属于哪一种,你就淘宝扫一扫识图,看哪家店卖的一模一样,然后看商品介绍。

以一路PWM,一路 GPIO举例:


#include "headfile.h"uint16 duty = 7000;void main()
{DisableGlobalIRQ();	//¹Ø±Õ×ÜÖжÏboard_init();	pwm_init(PWM5_P25, 10000, 9500);   EnableGlobalIRQ();	//¿ªÆô×ÜÖжÏwhile(1){pwm_duty(PWM5_P25,duty);gpio_pull_set(P2_6, 0);}
}

这就实现了让一个电机固定转速转。

接下来测试整个驱动好不好使


#include "My.h"void pwm_duty_init()
{pwm_init(PWM3_P63,17000,0);pwm_init(PWM4_P64,17000,0);}
/****************************************************************
电机驱动测试
12假设2路pwm的正反转
34假设64口控制方向的正反转(1个PWM,1控制方向)
56假设63口控制方向的正反转(1个PWM,1控制方向)
****************************************************************/
void mitor_duty(char mode)
{
if(mode==1)
{pwm_duty(PWM3_P63,0);pwm_duty(PWM4_P64,800);
}
if(mode==2)
{pwm_duty(PWM3_P63,800);pwm_duty(PWM4_P64,0);
}
if(mode==3)
{pwm_duty(PWM3_P63,800);pwm_duty(PWM4_P64,0);
}
if(mode==4)
{pwm_duty(PWM3_P63,800);pwm_duty(PWM4_P64,1000);
}
if(mode==5)
{pwm_duty(PWM3_P63,0);pwm_duty(PWM4_P64,800);
}
if(mode==6)
{pwm_duty(PWM3_P63,1000);pwm_duty(PWM4_P64,800);
}}


#ifndef __MY_H_
#define __MY_H_
#include "headfile.h"void pwm_duty_init();void mitor_duty(char mode);#endif

屏幕

下面是常见三款屏幕,同样的,不知道什么型号就淘宝搜,不会接线就问客服。

我以1.8TFT举例:

首先去淘宝搜到这个型号屏幕,在商品详情页可以看到引脚名称

在 seekfree_peripheral文件夹下找到屏幕对应的文件

 首先打开18TFT.h文件找到接线定义:
 

                    接线定义:
                    ------------------------------------ 
                        模块管脚            单片机管脚
                        SCL                 查看TFT_SCL_PIN        宏定义的引脚     硬件SPI引脚不可随意切换
                        SDA                 查看TFT_SDA_PIN        宏定义的引脚     硬件SPI引脚不可随意切换
                        RES                 查看REST_PIN        宏定义的引脚    
                        DC                  查看DC_PIN_PIN        宏定义的引脚  
                        CS                  查看TFT_CS_PIN        宏定义的引脚      
                        
                        电源引脚
                        BL  3.3V电源(背光控制引脚,也可以接PWM来控制亮度)
                        VCC 3.3V电源
                        GND 电源地
                        最大分辨率128*160
                    ------------------------------------ 

//--------------------软件SPI--------------------

#define    TFT_SCL_SIMSPI_PIN         P25                //定义SPI_SCK引脚
#define    TFT_SDA_SIMSPI_PIN        P23               //定义SPI_MOSI引脚
#define TFT_REST_SIMSPI_PIN      P20                //定义复位引脚
#define TFT_DC_SIMSPI_PIN          P21                //液晶命令位引脚定义
#define TFT_CS_SIMSPI_PIN          P22                //定义SPI_CS引脚
#define TFT_BL_SIMSPI_PIN          P24                //液晶背光引脚定义  

//--------------------硬件SPI--------------------

#define TFT_SPIN SPI_2                     //定义使用的SPI号
#define    TFT_SCL_PIN     SPI2_SCLK_P25    //定义SPI_SCK引脚
#define    TFT_SDA_PIN        SPI2_MOSI_P23   //定义SPI_MOSI引脚
#define    TFT_SDA_IN_PIN    SPI2_MISO_P24   //定义SPI_MISO引脚  TFT屏幕没有MISO引脚,但是这里任然需要定义,在spi的初始化时需要使用

#define TFT_REST_PIN      P20
#define TFT_DC_PIN          P21
#define TFT_CS_PIN          P22            //定义SPI_CS引脚
#define TFT_BL_PIN          P24

 根据接线定义去接线,硬件SPI、软件SPI根据喜好去选就行了。

函数有这些:

//--------------------Ó²¼þSPI--------------------
void lcd_init(void);
void lcd_clear(int color);
void lcd_drawpoint(uint16 x,uint16 y,uint16 color);
void lcd_showchar(uint16 x,uint16 y,uint8 dat);
void lcd_showstr(uint16 x,uint16 y,uint8 dat[]);
void lcd_showint8(uint16 x,uint16 y,int8 dat);
void lcd_showuint8(uint16 x,uint16 y,uint8 dat);
void lcd_showint16(uint16 x,uint16 y,int16 dat);
void lcd_showuint16(uint16 x,uint16 y,uint16 dat);
void lcd_showint32(uint16 x,uint16 y,int32 dat,uint8 num);
void lcd_showfloat(uint16 x,uint16 y,double dat,uint8 num,uint8 pointnum);
void showimage(const unsigned char *p);

然后初始化、调用代码就行了

/********************************************************************************************************************** COPYRIGHT NOTICE* Copyright (c) 2020,逐飞科技* All rights reserved.* 技术讨论QQ群:一群:179029047(已满)  二群:244861897(已满)  三群:824575535** 以下所有内容版权均属逐飞科技所有,未经允许不得用于商业用途,* 欢迎各位使用并传播本程序,修改内容时必须保留逐飞科技的版权声明。** @file       		main* @company	   		成都逐飞科技有限公司* @author     		逐飞科技(QQ790875685)* @version    		查看doc内version文件 版本说明* @Software 		MDK FOR C51 V9.60* @Target core		STC8A8K64S4* @Taobao   		https://seekfree.taobao.com/* @date       		2020-5-13********************************************************************************************************************/#include "headfile.h"board.h文件中FOSC的值设置为0,则程序自动识别系统频率///*board.h文件中FOSC的值设置不为0,则系统频率为FOSC的值,
//在使用stc-isp工具下载程序的时候需要将IRC频率设置为FOSC的值*/void main()
{DisableGlobalIRQ();		//关闭总中断board_init();			//初始化内部寄存器,勿删除此句代码。lcd_init();//此处编写用户代码(例如:外设初始化代码等)EnableGlobalIRQ();		//开启总中断while(1){//此处编写需要循环执行的代码
//    lcd_showstr(0,0,"lucky");
//		pca_delay_ms(1000);lcd_showchar(0,0,'x');//坐标0,0写一个字符x}
}

ADC

同样的运放,哪里弄得,从哪里获取资料

最简单的循迹只需要2个电感电容对,按照下面的接线就行

 将采集到的电感值显示到屏幕上

/********************************************************************************************************************** COPYRIGHT NOTICE* Copyright (c) 2020,逐飞科技* All rights reserved.* 技术讨论QQ群:一群:179029047(已满)  二群:244861897(已满)  三群:824575535** 以下所有内容版权均属逐飞科技所有,未经允许不得用于商业用途,* 欢迎各位使用并传播本程序,修改内容时必须保留逐飞科技的版权声明。** @file       		main* @company	   		成都逐飞科技有限公司* @author     		逐飞科技(QQ790875685)* @version    		查看doc内version文件 版本说明* @Software 		MDK FOR C51 V9.60* @Target core		STC8A8K64S4* @Taobao   		https://seekfree.taobao.com/* @date       		2020-5-13********************************************************************************************************************/#include "headfile.h"board.h文件中FOSC的值设置为0,则程序自动识别系统频率///*board.h文件中FOSC的值设置不为0,则系统频率为FOSC的值,
//在使用stc-isp工具下载程序的时候需要将IRC频率设置为FOSC的值*/void main()
{DisableGlobalIRQ();		//关闭总中断board_init();			//初始化内部寄存器,勿删除此句代码。lcd_init();adc_init(ADC_P01,ADC_SYSclk_DIV_2);            //adc_init(ADC_P02,ADC_SYSclk_DIV_2);            ////此处编写用户代码(例如:外设初始化代码等)EnableGlobalIRQ();		//开启总中断while(1){//此处编写需要循环执行的代码lcd_showuint16(2,2,adc_once(ADC_P01, ADC_10BIT)  );lcd_showuint16(3,3,adc_once(ADC_P02, ADC_10BIT)  );}
}

六、装车

七、循迹

智能车入门——跑车前的零碎知识

 智能车入门补充篇——电感值处理、转向控制与巡线

 智能车入门——电磁循迹原理与实现

电机

#include "dianji.h"// 电机初始化
void dianji_init()   
{pwm_init(PWM3_P63,17000,0);       //IN1  右pwm_init(PWM4_P64,17000,0);				//IN2  右  +前pwm_init(PWM5_P65,17000,0);       //IN3  左  +前pwm_init(PWM6_P66,17000,0);       //IN4  左
}//驱动电机
void dianji_Control(int32 LDuty, int32 RDuty)   
{	if(LDuty > 0)                  //左正{pwm_duty(PWM5_P65, LDuty);pwm_duty(PWM6_P66, 0);}if(LDuty < 0)                  //左反{pwm_duty(PWM5_P65, 0);pwm_duty(PWM6_P66, LDuty);}if(RDuty > 0)                  //右正{pwm_duty(PWM3_P63, 0);pwm_duty(PWM4_P64, RDuty);}if(RDuty < 0)                  //右反{pwm_duty(PWM3_P63, RDuty);pwm_duty(PWM4_P64, 0);}if(LDuty == 0){pwm_duty(PWM3_P63, 0);pwm_duty(PWM4_P64, 0);}if(RDuty == 0){pwm_duty(PWM5_P65, 0);pwm_duty(PWM6_P66, 0);}}//限幅保护
int32 range_protect(int32 duty, int32 min, int32 max)
{if (duty >= max){return max;}if (duty <= min){return min;}else{return duty;}
}
#ifndef __dianji_H__
#define __dianji_H__
#include "headfile.h" int32 range_protect(int32 duty, int32 min, int32 max);//限幅保护
void dianji_init();
void dianji_Control(int32 LDuty, int32 RDuty);#endif

循迹

我找的小车,循迹只能靠电机的差速,由于这种小车速度很慢,因此,只需要偏差乘一个比例系数就能简单循迹,相当于PID中只给P系数,I、D的值为0.

首先初始化各个器件

void all_init()   
{adc_init(ADC_P01,ADC_SYSclk_DIV_2);            //³õʼ»¯P1.0ΪADC¹¦ÄÜ,ADCʱÖÓƵÂÊ£ºSYSclk/2adc_init(ADC_P02,ADC_SYSclk_DIV_2);            //³õʼ»¯P1.0ΪADC¹¦ÄÜ,ADCʱÖÓƵÂÊ£ºSYSclk/2dianji_init();                                 //µç»ú³õʼ»¯lcd_init();                                 //ÆÁÄ»³õʼ»¯pd_init();
}

获取ADC

void adc_collect()
{
adc1=adc_once(ADC_P01, ADC_10BIT);
adc4=adc_once(ADC_P02, ADC_10BIT);	
}	

 差速循迹

float kp=1.2;
now_error = adc1-adc4;
output=kp*now_errorLeftDuty =600-output;
RightDuty=600+output;LeftDuty =	range_protect( LeftDuty,-200, 1000);
RightDuty=	range_protect(RightDuty,-200, 1000);
dianji_Control(LeftDuty,RightDuty);


我会贴上完整代码,用来参考。

举一反三,如果要用到按键、舵机、陀螺仪等也是同样的步骤。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/161571.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis-Redis持久化,主从哨兵架构详解

Redis持久化 RDB快照&#xff08;snapshot&#xff09; 在默认情况下&#xff0c; Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。 你可以对 Redis 进行设置&#xff0c; 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时&#xff0c; 自动保存一次数…

【操作系统】I/O软件层次结构

文章目录 1. 前言2. I/O软件层次结构2.1 用户层软件2.2 设备独立性软件2.3 设备驱动程序2.4 中断处理程序 1. 前言 偶然看到“程序员的护城河是什么”这个话题&#xff0c;作为一个工作两年多的程序员吧&#xff0c;经常看到网上关于各种35岁危机、裁员甚至猝死之云云。最近也…

modbus协议及modbus TCP协议

一、Modbus协议 1.起源 Modbus由Modicon公司于1979年开发&#xff0c;是一种工业现场总线协议标准。 Modbus通信协议具有多个变种&#xff0c;其中有支持串口&#xff0c;以太网多个版本&#xff0c;其中最著名的是Modbus RTU&#xff08;通信效率最高&#xff0c;基于串口&am…

springboot前后端分离项目配置https接口(ssl证书)

文章目录 说明vue.js前端部署vue.js项目axios请求配置本地创建日志文件创建Dockerfile文件配置ssl证书nginx.confvue项目打包上传创建容器部署 后端springboot项目部署配置ssl证书打包部署 补充&#xff1a;jsk证书和pfx证书补充&#xff1a;两种证书的转化JKS转PFXPFX 转 JKS …

Elasticsearch:将最大内积引入 Lucene

作者&#xff1a;Benjamin Trent 目前&#xff0c;Lucene 限制 dot_product (点积) 只能在标准化向量上使用。 归一化迫使所有向量幅度等于一。 虽然在许多情况下这是可以接受的&#xff0c;但它可能会导致某些数据集的相关性问题。 一个典型的例子是 Cohere 构建的嵌入&#x…

使用 Lhotse 高效管理音频数据集

Lhotse 是一个旨在使语音和音频数据准备更具灵活性和可访问性的 Python 库&#xff0c;它与 k2 一起&#xff0c;构成了下一代 Kaldi 语音处理库的一部分。 主要目标&#xff1a; 1. 以 Python 为中心的设计吸引更广泛的社区参与语音处理任务。 2. 为有经验的 Kaldi 用户提供…

SpringBoot——启动类的原理

优质博文&#xff1a;IT-BLOG-CN SpringBoot启动类上使用SpringBootApplication注解&#xff0c;该注解是一个组合注解&#xff0c;包含多个其它注解。和类定义SpringApplication.run要揭开SpringBoot的神秘面纱&#xff0c;我们要从这两位开始就可以了。 SpringBootApplicati…

Spring实例化对象

默认proxyBeanMethods true&#xff0c;这种方法是用的代理模式创建对象&#xff0c;每次创建都是同一个对象&#xff0c;如果改为false每次都是不同的对象 FactoryBean的使用 定义的类A&#xff0c;造出来一个类B&#xff0c;可以在创造bean之前做一些自己的个性化操作

MFS分布式文件系统

目录 集群部署 Master Servers ​Chunkservers ​编辑Clients Storage Classes LABEL mfs高可用 pacemaker高可用 ​编辑ISCSI 添加集群资源 主机 ip 角色 server1 192.168.81.11 Master Servers server2 192.168.81.12 Chunkservers server3 192.168.81.13 Chunkserver…

【产品安全平台】上海道宁与Cybellum将整个产品安全工作流程整合到一个专用平台中,保持构建的互联产品的网络安全和网络合规性

Cybellum将 整个产品安全工作流程 整合到一个专用平台中 使设备制造商能够 保持他们构建的互联产品的 网络安全和网络合规性 产品安全性对 每个人来说都不一样 每个行业的系统、工作流程和 法规都存在根本差异 因此&#xff0c;Cybellum量身定制了 Cybellum的平台和技…

为何内存不够用?微服务改造启动多个Spring Boot的陷阱与解决方案

在生产环境中我们会遇到一些问题&#xff0c;此文主要记录并复盘一下当时项目中的实际问题及解决过程。 背景简述 最初系统上线后都比较正常风平浪静的。在系统运行了一段时间后&#xff0c;业务量上升后&#xff0c;生产上发现java应用内存占用过高&#xff0c;服务器总共64…

爱创科技总裁谢朝晖荣获“推动医药健康产业高质量发展人物”

中国医药市场规模已经成为全球第二大医药市场&#xff0c;仅次于美国。近年来&#xff0c;随着中国经济的持续增长和人民生活水平的提高&#xff0c;医药市场需求不断扩大。政府对医疗卫生事业的投入也在不断加大&#xff0c;为医药行业的发展创造了良好的政策环境。为推动医药…

结构体与指针_sizeof_static_extern_函数指针数组_函数指针_回调函数

一、结构体与指针 #include <stdint.h> #include <stdlib.h> #include <stdio.h> #define up_to_down(uuu) (downdemo_t *)(uuu->beg) #define __plc__ typedef struct updemo_s{uint8_t *head;uint8_t *beg;uint8_t *end; }updemo_t; typedef struct do…

陪玩圈子系统APP小程序H5,详细介绍,源码交付,支持二开!

陪玩圈子系统&#xff0c;页面展示&#xff0c;源码交付&#xff0c;支持二开&#xff01; 陪玩后端下载地址&#xff1a;电竞开黑陪玩系统小程序&#xff0c;APP&#xff0c;H5: 本系统是集齐开黑&#xff0c;陪玩&#xff0c;陪聊于一体的专业APP&#xff0c;小程序&#xff…

Linux进程通信——共享内存

概念 共享内存&#xff08;Shared Memory&#xff09;&#xff0c;指两个或多个进程共享一个给定的存储区。 特点 共享内存是最快的一种 IPC&#xff0c;因为进程是直接对内存进行存取。 因为多个进程可以同时操作&#xff0c;所以需要进行同步。 信号量共享内存通常结合在一…

Open3D (C++) 计算两点云之间的最小距离

目录 一、 算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、 算法原理 Open3D中ComputePointCloudDistance函数提供了计算从源点云到目标点云的距离的方法,计算点云的距离。也…

【C语法学习】26 - strcmp()函数

文章目录 1 函数原型2 参数3 返回值4 比较机制5 示例5.1 示例1 1 函数原型 strcmp()&#xff1a;比较str1指向的字符串和str2指向的字符串&#xff0c;函数原型如下&#xff1a; int strcmp(const char *str1, const char *str2);2 参数 strcmp()函数有两个参数str1和str2&a…

HCIP-四、MUX-vlanSuper-vlan+端口安全

四、MUX-vlan&Super-vlan端口安全 MUX-vlan实验拓扑实验需求及解法1. 在SW1/2/3分别创建vlan10 20 30 402. SW1/2/3之间使用trunk链路&#xff0c;仅允许vlan10 20 30 40 通过。3. SW与PC/Server之间使用access链路。4. ping验证&#xff1a; Super-vlan端口安全实验拓扑实…

【腾讯云云上实验室-向量数据库】腾讯云开创新时代,发布全新向量数据库Tencent Cloud VectorDB

前言 随着人工智能、数据挖掘等技术的飞速发展&#xff0c;海量数据的存储和分析越来越成为重要的研究方向。在海量数据中找到具有相似性或相关性的数据对于实现精准推荐、搜索等应用至关重要。传统关系型数据库存在一些缺陷&#xff0c;例如存储效率低、查询耗时长等问题&…

CentOS使用docker安装OpenGauss数据库

1.搜索OpenGauss docker search opengauss 2.选择其中一个源拉取 docker pull docker.io/enmotech/opengauss 3.运行OpenGauss docker run --name opengauss --privilegedtrue --restartalways -d -e GS_USERNAMEpostgres -e GS_PASSWORDmyGauss2023 -p 5432:5432 docker.…