自己网站建设基本流程,便利的网站建设公司,上海网站建设公,鸿安建设集团网站欢迎阅读教程系列的第五篇文章#xff0c;其中我正在构建一个基于遥控Arduino的车辆机器人。这是我到目前为止发表的文章列表#xff1a;第一部分#xff1a;硬件组件第二部分#xff1a;Arduino编程第三部分#xff1a;组装机器人第四部分#xff1a;A(不是那样)基本机器…欢迎阅读教程系列的第五篇文章其中我正在构建一个基于遥控Arduino的车辆机器人。这是我到目前为止发表的文章列表第一部分硬件组件第二部分Arduino编程第三部分组装机器人第四部分A(不是那样)基本机器人固件第五部分避免障碍(本文)第六部分远程控制在上一篇文章中我写了我的Michelino机器人固件的第一个版本其中包括一个电机控制器驱动程序。今天我正在增加对距离传感器的支持。距离传感器驱动器正如我在上一篇文章中所示只要为其编写了设备驱动程序我的固件就可以处理任何电机控制器板。此上下文中的设备驱动程序只不过是一个实现我为此类设备定义的通用接口的类。距离传感器没有什么不同可以应用相同的想法。首先我将定义所有距离传感器设备通用的接口。这将进入文件distance_sensor.h/** * file distance_sensor.h * brief distance sensor driver definition for the Michelino robot. * author Miguel Grinberg */namespace Michelino{ class DistanceSensorDriver { public: /** * brief Class constructor. * param distance The maximum distance in centimeters that needs to be tracked. */ DistanceSensorDriver(unsigned int distance) : maxDistance(distance) {} /** * brief Return the distance to the nearest obstacle in centimeters. * return the distance to the closest object in centimeters * or maxDistance if no object was detected */ virtual unsigned int getDistance() 0; protected: unsigned int maxDistance; };};我的距离传感器驱动器非常简单驾驶员只需提供一种方法以厘米为单位报告距离最近物体的距离。这就是我现在所需要的我总是可以回来并在以后为驱动程序定义添加更多功能。驱动程序的构造函数占用最大距离。这是在getDistance()没有检测到障碍物时将返回的值。请注意maxDistance成员变量位于protected块中而不是private像我在其他类中使用的块。protected对于外部仍然是私有的变量但子类可以访问它们。我希望这个驱动程序的实现可以访问这个值这就是我创建它的原因protected。正如我在上一篇文章中提到的我发现我正在使用的HC-SR04距离传感器与arduino-new-ping开源库非常相配所以我现在将为它实现上面的驱动程序接口档案newping_distance_sensor.h/** * file newping_distance_sensor.h * brief distance sensor driver for distance sensors supported by the NewPing library. * author Miguel Grinberg */#include distance_sensor.hnamespace Michelino{ class DistanceSensor : public DistanceSensorDriver { public: DistanceSensor(int triggerPin, int echoPin, int maxDistance) : DistanceSensorDriver(maxDistance), sensor(triggerPin, echoPin, maxDistance) { } virtual unsigned int getDistance() { int distance sensor.ping_cm(); if (distance 0) return maxDistance; return distance; } private: NewPing sensor; };};请注意getDistance()实现如何maxDistance访问父类中定义的成员变量。如果我在private块中定义了此变量则此代码将无法编译。与固件集成作为第一次集成测试让机器人前进并在发现障碍物时停止。我将从我在前一篇文章中编写的固件开始并将替换initialize()和run()方法它们是我面向Arduino setup()和loop()函数的面向对象。如果您不熟悉可能需要返回该文章以查看完整草图的结构。在草图的顶部我使用与电机控制器相同的结构包括驱动器#define ENABLE_NEWPING_DISTANCE_SENSOR_DRIVER#ifdef ENABLE_NEWPING_DISTANCE_SENSOR_DRIVER#include #include newping_distance_sensor.h#define DISTANCE_SENSOR_INIT 14,15,MAX_DISTANCE#endif在类的private部分中创建Robot一个DistanceSensor对象private: DistanceSensor distanceSensor;在Robot类构造函数中初始化对象Robot() : leftMotor(LEFT_MOTOR_INIT), rightMotor(RIGHT_MOTOR_INIT), distanceSensor(DISTANCE_SENSOR_INIT){ initialize();}在initialize()方法中我启动电机并将状态设置为运行void initialize(){ leftMotor.setSpeed(255); rightMotor.setSpeed(255); state stateRunning;}并且在该run()方法中当距离传感器发现近距离障碍时我停止电机void run(){ if (state stateRunning) { if (distanceSensor.getDistance() TOO_CLOSE) { state stateStopped; leftMotor.setSpeed(0); rightMotor.setSpeed(0); } }}我在上面的所有更改中使用了两个常量MAX_DISTANCE并且TOO_CLOSE。这些常量在草图的顶部定义以便在需要修改时很容易找到它们#define TOO_CLOSE 10#define MAX_DISTANCE (TOO_CLOSE * 20)我将使用10厘米的距离来考虑障碍物太近。我需要跟踪的最大距离是该距离的20倍或2米。这些是我凭空掏出的数字我真的不知道它们是否会起作用但在我有机会测试之后我总能回来调整它们。草图现在处于可用状态。以下是完整的michelino.ino草图源代码#define ENABLE_ADAFRUIT_MOTOR_DRIVER#define ENABLE_NEWPING_DISTANCE_SENSOR_DRIVER#define TOO_CLOSE 10#define MAX_DISTANCE (TOO_CLOSE * 20)#ifdef ENABLE_ADAFRUIT_MOTOR_DRIVER#include #include adafruit_motor_driver.h#define LEFT_MOTOR_INIT 1#define RIGHT_MOTOR_INIT 3#endif#ifdef ENABLE_NEWPING_DISTANCE_SENSOR_DRIVER#include #include newping_distance_sensor.h#define DISTANCE_SENSOR_INIT 14,15,MAX_DISTANCE#endifnamespace Michelino{ class Robot { public: /* * brief Class constructor. */ Robot() : leftMotor(LEFT_MOTOR_INIT), rightMotor(RIGHT_MOTOR_INIT), distanceSensor(DISTANCE_SENSOR_INIT) { initialize(); } /* * brief Initialize the robot state. */ void initialize() { leftMotor.setSpeed(255); rightMotor.setSpeed(255); state stateRunning; } /* * brief Update the state of the robot based on input from sensor and remote control. * Must be called repeatedly while the robot is in operation. */ void run() { if (state stateRunning) { if (distanceSensor.getDistance() TOO_CLOSE) { state stateStopped; leftMotor.setSpeed(0); rightMotor.setSpeed(0); } } } private: Motor leftMotor; Motor rightMotor; DistanceSensor distanceSensor; enum state_t { stateStopped, stateRunning }; state_t state; };};Michelino::Robot robot;void setup(){ robot.initialize();}void loop(){ robot.run();}在这个草图的控制下机器人将一直运行直到距离墙壁或其他障碍物10厘米或更小然后停止。如果您正在构建一个像我一样的机器人并尝试草图您可能会发现机器人大部分时间都按预期运行但并非总是如此。偶尔它可能会停止即使没有近距离障碍或者有时它可能会不停地撞到墙上。继续阅读以了解我如何找出问题以及如何解决问题。记录运行上面的草图几次就可以清楚地发现意外情况正在发生但我怎样才能知道它是什么我真的需要看到草图正在接收的所有数据以及它如何对它做出反应以理解为什么事情不会像我预期的那样发展。换句话说我需要调试我的草图。调试这样的嵌入式系统非常有用的技术是将通过应用程序传递的信息写入可以查看的日志中。为了能够从我的草图中记录我将编写一个记录函数该printf()函数与C标准库中的旧函数具有相同的参数除了因为我的机器人没有屏幕输出将转到串口我可以从我的PC上运行的Arduino软件中捕获或者通过蓝牙从我的手机中捕获。我打算叫这个功能log()。以下是一个示例用法unsigned int distance distanceSensor.getDistance();log(distance: %u