欢迎阅读教程系列的第五篇文章,其中我正在构建一个基于遥控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.h"namespace 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

arduino 停止程序_建立Arduino机器人,第五部分:障碍规避相关推荐

  1. arduino 停止程序_极路由1S OpenWrt开机自启程序及串口调试

    如何给openwrt添加启动项?首先在/etc/init.d中创建一个文件,在CRT终端中直接用vi命令即可,自行创建startCamera文件,如下图所示. vi编辑器中输入下图所示内容,START ...

  2. arduino 休眠 节能_优化arduino程序存储空间

    0x00 Abstract 我们一般在开发Arduino的程序时都是根据功能需求来编写代码,当经过测试后程序满足功能需求后就停止开发,剩下的就是只有在功能需求变更或代码中存在bug时才会再次动手修改代 ...

  3. arduino nano 蓝牙_用Arduino玩转掌控板(ESP32):ESP32概述与Arduino软件准备

    前言 近年来,掌控板(英文名:mPython)在创客教育中应用越来越广泛.掌控板集成了 ESP32 高性能双核芯片,具备 WiFi 和蓝牙连接功能,同时在板子上又配置了丰富的传感器,最重要的是它是专门 ...

  4. arduino编码器计数_基于Arduino开发环境的光电编码器检测仪设计方案 - 全文

    0 引言 Arduino是一款基于单片机系统的电子产品开发平台,它的软硬件系统都具有高度的模块化,而且软件系统是完全开源的.其硬件系统也是高度模块化的,在核心控制板的外围有开关量输入/输出模块.各种模 ...

  5. arduino 长传出错_请问Arduino IDE在编译时正常,却无法上传且显示找无效库是怎么回事?...

    开发板:"Arduino Nano atmega328p" 警告:库 Mozzi 中的分类 'audio' 不可用.设置为 'Uncategorized' 项目使用了 2750 字 ...

  6. arduino智能闹钟_【Arduino综合项目】小闹钟

    小闹钟项目 在额济纳支教这一年,给孩子们上了很多Arduino开发的课,也带他们完成了几个Arduino综合项目,下面陆续把这些小项目放上来,欢迎围观~~~非科班出身,C语言学的不好,望各路大神批评指 ...

  7. arduino 停止程序_Arduino 中断

    中断(interrupt)停止Arduino的当前工作,以便可以完成一些其他工作. 假设你坐在家里和别人聊天.突然电话响了.你停止聊天,拿起电话与来电者通话.当你完成电话交谈后,你回去和电话响之前的那 ...

  8. arduino 停止程序_Arduino-常用指令

    pinMode(LEDPin,OUTPUT);        //设置引脚模式 参数1      引脚 参数2      OUTPUT  输出:INPUT   输入 用在setup()函数里 digi ...

  9. arduino灯光装置_基于Arduino的智能家居灯控系统设计

    &能应用 ------ T X 阵 W S 2 8 1 2 全 彩 灯 带 R X 工 G N D r 0 引言 智能家居的概念虽然已经有了几十年,但进入我国并取 得一定发展还是最近几年的事, ...

最新文章

  1. java多线程3.设计线程安全类
  2. mysql8中怎么增删一列_关于MySQL的增删改查知识
  3. git 使用_Git使用总结
  4. mysql为什么行数据库_关系数据表中的行称为什么?
  5. 与40mhz信道不兼容设置_为什么面包板不适合高频电路
  6. VideoSolo Blu ray Player for Mac - 强大的蓝光播放器
  7. fedora启动进入命令窗口_查看版本_修改hostname
  8. java maven strom 启动异常
  9. java test20006_Java单例7种测试实践
  10. iOS打包后收不到推送信息
  11. SAM2695 带效果器的低功耗单芯片合成器
  12. 在C语言中使用中文,本地化全攻略
  13. Android App脱壳
  14. 网页外挂技术浅谈(入门篇)
  15. 类和对象11:描述符方法
  16. 51单片机mq3酒精浓度检测mq3酒驾醉驾检测酒精报警ADC0832采集
  17. pap.er for mac高清壁纸下载后的储存位置在哪里?小编告诉你!!
  18. Java学习 --- 类与对象
  19. spring boot 使用javaMailSender 发送qq邮箱验证码
  20. 美团、抖音、淘宝,为什么App们爱上“群聊”?

热门文章

  1. C语言、C++学习路线
  2. 10万码农五年的C语言笔记!你现在知道别人为什么这么优秀了吗?
  3. webpack+react+es6开发模式
  4. Spring3 整合 Hibernate4实现数据库操作(1)
  5. java 显示透明背景png图片
  6. c语言:malloc函数的简介
  7. 计算机寄存器端口,CPU和外设之间的数据传送方式有哪几种
  8. ecs硬盘数据迁移_阿里云ECS新增数据盘以及迁移数据方法
  9. hbase 页面访问_HBase
  10. linux远程拷贝免手动输入密码,scp远程拷贝避免输入密码