完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1.材料准备
需要用到的材料:Arduino Uno板,L298N电机驱动模块,两个12V直流减速电机,舵机一个,超声波模块,11.1V锂电池,小车车架等。 因为我后续还要添加其他功能,如加装机械臂和openmv模块,所以选用了功率较大的12V电机。以后还会推出相关的博文。 Uno板: L298N: 12V直流减速电机: 11.1V锂电池 超声波模块+舵机: 2.代码实现 面向对象顾名思义就是把现实中的事务都抽象成为程序设计中的“对象”,其基本思想是一切皆对象,是一种“自下而上”的设计语言,先设计组件,再完成拼装。 首先我们需要写一个arduino库,这个库的作用是用来存储我们写的类,包含.h文件和.cpp文件。其中.h文件是类的声明,.cpp文件是成员函数的定义。 废话不多说,直接上代码~ 头文件.h: #ifndef TENNIMATE_H_ #define TENNIMATE_H_ #include "Arduino.h" #include // Tennimate类 class Tennimate{ public: // 提供电机的转向控制引脚,电机速度控制引脚, 测距传感器引脚参数以及舵机控制引脚参数的构造函数 Tennimate(int ENA_pin, int In1_pin, int In2_pin, int In3_pin, int In4_pin, int ENB_pin, byte M_Speed,int trigPin, int echoPin, int servoPin); void forward(); // 前进 void backward(); // 后退 void turnL(); // 左转 void turnR(); // 右转 void forwardL(); // 左前 void forwardR(); // 右前 void backwardL(); // 左后 void backwardR(); // 右后 void stop(); // 停车 int getDistance(); // 获取距离传感器读数 void setHeadPos(int pos); // 设定舵机角度 int getHeadPos(); // 获取舵机角度 void headServoIni(); // 舵机初始化 private: Servo headServo; // 建立头部舵机对象 int headServoPin; // 舵机控制引脚 byte motorSpeed; //电机速度 int ENA; //L298N上的ENA引脚 int In1; //L298N上的In1引脚 int In2; L298N上的In2引脚 int ENB; int In3; int In4; int hcTrig; // 超声测距传感器Trig引脚 int hcEcho; // 超声测距传感器Echo引脚 long duration, cm; // 超声测距传感器用变量 }; #endif .cpp: #include "Tennimate.h" // 提供电机的转向控制引脚,电机速度控制引脚, 测距传感器引脚参数以及舵机控制引脚参数的构造函数 Tennimate::Tennimate(int ENA_pin, int In1_pin, int In2_pin, int In3_pin, int In4_pin, int ENB_pin, byte M_Speed,int trigPin, int echoPin, int servoPin) { headServoPin = servoPin; hcTrig = trigPin; hcEcho = echoPin; motorSpeed = M_Speed; ENA = ENA_pin; //L298N上的ENA引脚 In1 = In1_pin; //L298N上的In1引脚 In2 = In2_pin; ENB = ENB_pin; In3 = In3_pin; In4 = In4_pin; pinMode(ENA,OUTPUT); //设置为输出模式 pinMode(In1,OUTPUT); pinMode(In2,OUTPUT); pinMode(ENB,OUTPUT); pinMode(In3,OUTPUT); pinMode(In4,OUTPUT); pinMode(hcTrig, OUTPUT); pinMode(hcEcho, INPUT); } // 初始化舵机 void Tennimate::headServoIni(){ headServo.attach(headServoPin); } // 设置舵机位置 void Tennimate::setHeadPos(int pos){ headServo.write(pos); } // 获取舵机位置 int Tennimate::getHeadPos(){ return headServo.read(); } // 读取传感器距离读数(单位为厘米) int Tennimate::getDistance(){ digitalWrite(hcTrig, LOW); delayMicroseconds(5); digitalWrite(hcTrig, HIGH); delayMicroseconds(10); digitalWrite(hcTrig, LOW); duration = pulseIn(hcEcho, HIGH); cm = (duration/2) / 29.1; return cm; } // 前进 void Tennimate::forward(){ digitalWrite(In1,HIGH); //给高电平 digitalWrite(In2,LOW); //给低电平 analogWrite(ENA,motorSpeed); //pwm控制速度 digitalWrite(In3,HIGH); //给高电平 digitalWrite(In4,LOW); //给低电平 analogWrite(ENB,motorSpeed); } // 后退 void Tennimate::backward(){ digitalWrite(In1,LOW); digitalWrite(In2,HIGH); analogWrite(ENA,motorSpeed); digitalWrite(In3,LOW); digitalWrite(In4,HIGH); analogWrite(ENB,motorSpeed); } // 左转 void Tennimate::turnL(){ digitalWrite(In1,HIGH); digitalWrite(In2,LOW); analogWrite(ENA,motorSpeed); digitalWrite(In3,LOW); digitalWrite(In4,HIGH); analogWrite(ENB,motorSpeed); } // 右转 void Tennimate::turnR(){ digitalWrite(In1,LOW); digitalWrite(In2,HIGH); analogWrite(ENA,motorSpeed); digitalWrite(In3,HIGH); digitalWrite(In4,LOW); analogWrite(ENB,motorSpeed); } // 左前 void Tennimate::forwardL(){ digitalWrite(In1,HIGH); digitalWrite(In2,LOW); analogWrite(ENA,motorSpeed); digitalWrite(In3,LOW); digitalWrite(In4,LOW); analogWrite(ENB,0); } // 右前 void Tennimate::forwardR(){ digitalWrite(In1,LOW); digitalWrite(In2,LOW); analogWrite(ENA,0); digitalWrite(In3,HIGH); digitalWrite(In4,LOW); analogWrite(ENB,motorSpeed); } // 左后 void Tennimate::backwardL(){ digitalWrite(In1,LOW); digitalWrite(In2,HIGH); analogWrite(ENA,motorSpeed); digitalWrite(In3,LOW); digitalWrite(In4,LOW); analogWrite(ENB,0); } // 右后 void Tennimate::backwardR(){ digitalWrite(In1,LOW); digitalWrite(In2,LOW); analogWrite(ENA,0); digitalWrite(In3,LOW); digitalWrite(In4,HIGH); analogWrite(ENB,motorSpeed); } // 停止 void Tennimate::stop(){ digitalWrite(In1,LOW); digitalWrite(In2,LOW); analogWrite(ENA,0); digitalWrite(In3,LOW); digitalWrite(In4,LOW); analogWrite(ENB,0); } 在创建好类之后,我们需要将其实例化,然后就能调用各种成员函数。如果需要添加其他功能,只需要修改或添加数据成员和成员函数即可。 下面就是实现超声波避障小车的程序: #include #define DIST_THRESHOLD 35 // 避障距离阈值(cm) #define TURN_LEFT_90 900 // 左转90度延迟参数 #define TURN_RIGHT_90 1000 // 右转90度延迟参数 #define TURN_BACK 1600 // 掉头延迟参数 // 建立Tennimate对象(实例化)。其中对象参数分别是: // (L298N模块的ENA, In1, In2, In3, In4,ENB引脚 // 车轮电机运转速度,测距传感器TRIG引脚, 测距传感器ECHO引脚,头部舵机信号引脚 ) Tennimate TM(5, 12, 13, 7, 8, 6, 100, 2, 3, 10); void setup() { TM.headServoIni(); //头部舵机初始化 TM.setHeadPos(90); // 系统启动时将头部设置为90位置 } void loop() { autoMode(); } // 左转90度 void turnL90(){ TM.turnL(); delay(TURN_LEFT_90); } // 右转90度 void turnR90(){ TM.turnR(); delay(TURN_RIGHT_90); } // 掉头 void turnBack(){ TM.turnL(); delay(TURN_BACK); } // 检查左右方向距离并返回专项方向 void autoTurn(){ // 检查右侧距离 for (int pos = 90; pos >= 0; pos -= 1) { TM.setHeadPos(pos); delay(3); } delay(300); int rightDist = TM.getDistance(); // 检查左侧距离 for (int pos = 0; pos <= 180; pos += 1) { TM.setHeadPos(pos); delay(3); } delay(300); int leftDist = TM.getDistance(); //将头部调整到正前方 for (int pos = 180; pos >= 90; pos -= 1) { TM.setHeadPos(pos); delay(3); } delay(500); //检查左右距离并做出转向决定 if ( rightDist < DIST_THRESHOLD && leftDist < DIST_THRESHOLD){ // 如果左右方向距离均小于允许距离 turnBack(); // 掉头 return; } else if ( rightDist >= leftDist){ // 如果右边距离大于左边距离 turnR90(); // 右转90度 return; } else { // 如果左边距离大于右边距离 turnL90(); // 左转90度 return; } } void autoMode(){ delay(50); // 提高系统稳定性等待 int frontDist = TM.getDistance(); // 检查前方距离 if(frontDist >= DIST_THRESHOLD){ // 如果检测前方距离读数大于等于允许距离参数 TM.forward(); // 向前 } else { // 如果检测前方距离小于允许距离参数 TM.stop(); // 停止 autoTurn(); // 检测左右侧距离并做出自动转向 } } 3.接线 关于接线问题,就得好好讲一下L298N。 可以看到,L298N有三个跳帽,我们只需要拔掉其中的A Enable和B Enable,这样就可以对电机进行PWM调速了。 关于供电, L298N有两个供电,一个是逻辑控制部分的5V供电,一个是电机的供电。图中的12V是给电机供电的,所以要把锂电池接在这里。板上有一个5伏稳压管,如果板上5VEnabl没有拔掉的话,L298N的逻辑部分供电就从这个稳压管获得,这样就不用外接5伏,此时还可以将得到的5v稳压对其他模块供电。如果外接5伏的话,板上5VEnabl就要拔掉了。 我们这里因为是11.1v供电,所以只需要将锂电池连接到+12V,然后用+12V旁边的+5V给arduino板供电即可。 具体的连线图如下: 这里再强调一下,A Enable和B Enable需要接到arduino中带~的引脚上,因为带 ~的引脚才能输出PWM;In1-4的话随意。再一个就是arduino和L298N要共地!要共地! 超声波和舵机的接线就没什么好讲的了,定义了哪个接口就接哪个就行。 在测试过程中,我出现过一些问题,就是有一边不工作。 |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2956 浏览 16 评论
3458 浏览 1 评论
8996 浏览 16 评论
4051 浏览 18 评论
1109浏览 3评论
572浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1858浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 06:11 , Processed in 1.182038 second(s), Total 80, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号