用面向对象的编程方法制作一台超声波避障arduino小车(代码+接线+供电详解)

Bree ·
更新时间:2024-11-11
· 900 次阅读

目录1.材料准备2.代码实现3.接线 1.材料准备

需要用到的材料:Arduino Uno板,L298N电机驱动模块,两个12V直流减速电机,舵机一个,超声波模块,11.1V锂电池,小车车架等。
因为我后续还要添加其他功能,如加装机械臂和openmv模块,所以选用了功率较大的12V电机。以后还会推出相关的博文。

Uno板:在这里插入图片描述
L298N:
在这里插入图片描述
12V直流减速电机:
在这里插入图片描述
11.1V锂电池
在这里插入图片描述
超声波模块+舵机:
在这里插入图片描述

2.代码实现

面向对象顾名思义就是把现实中的事务都抽象成为程序设计中的“对象”,其基本思想是一切皆对象,是一种“自下而上”的设计语言,先设计组件,再完成拼装。
首先我们需要写一个arduino库,这个库的作用是用来存储我们写的类,包含.h文件和.cpp文件。其中.h文件是类的声明,.cpp文件是成员函数的定义。
关于如何自建arduino库可以参考: Arduino自定义库的编写。
关于类的创建我这里就不详细讲解了,自行百度就能搜到很多。
废话不多说,直接上代码~

头文件.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 = 90; pos -= 1) { TM.setHeadPos(pos); delay(3); } delay(500); //检查左右距离并做出转向决定 if ( rightDist < DIST_THRESHOLD && leftDist = 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要共地!要共地!
超声波和舵机的接线就没什么好讲的了,定义了哪个接口就接哪个就行。
在测试过程中,我出现过一些问题,就是有一边不工作,具体解决方法参考我这篇博文: #Arduino Uno 关于PWM输出的问题(L298N驱动电机只有一边工作)。
觉得有帮助就点个赞吧~ 预告下下期!arduino和openmv通信(传送识别物体的中心坐标)

参考: 零基础入门学用Arduino教程 – 专项教程篇


作者:你的学渣



方法 对象 面向对象 arduino

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章