摸摸鱼,把大二的课堂作业总结一下发出来,很基础的小白代码,希望能给入门的同学一点参考。
由于实物卖掉啦,只能尽量用文字配上接线图等,写详细一点。
| Arduino UNO R3开发板(带USB) | 1个 |
| XD-201 4路红外传感器 | 1个 |
| DRV8833 2路直流电机驱动 | 2个 |
| 母对母、公对母杜邦线 | 若干 |
| 直流减速电机 | 4个 |
| 4WD底盘 | 1个 |
| 接插件 | 若干 |
根据实际接线情况绘制,需要配合代码使用的端口进行接线。

使用前需了解清楚每个端口的作用哦~

为了控制转速和满足功率,所以需要电机驱动模块。老师要求,所以选了这一款,但拿到手蛮小巧可爱的,就是比起常用的L298多花了一番功夫寻找控制原理。

首先定义引脚,设置输出和输入情况,同时进行初始化。
使用到的5,6,10,11号脚不仅是I/O口,还可以输出PWM。则搭配7,8,12,13号引脚控制四个电机。PWM控制转速,普通I/O口输出高低电平控制转向。
连续从红外循迹模块读取四个传感器的高低电平,输入到单片机,motorRun函数根据传感器相应数据,输出不同的PWM值和高低电平,控制电机的转向和转速,以适应不同的情况。
#include <Servo.h>
//函数调用说明:调用servo.h里的库函数,类似stdio.h是标准输入输出,常用的 printf scanf 这些输入输出函数 以及fopen fclose一系列的文件操作函数都是在这个头文件里面的,所以这个最常见
#define STOP 0
#define FORWARD 1
#define BACKWARD 2
#define TURNLEFT 3
#define TURNRIGHT 4
const int leftMotor1_1 = 5; // 定义5引脚为左前侧电机,PWM控制速度
const int leftMotor1_2 = 7; // 定义7引脚为左前侧电机控制方向
const int leftMotor2_1 = 6; // 定义6引脚为左后侧电机,PWM控制速度
const int leftMotor2_2 = 8; // 定义8引脚为左后侧电机控制方向
const int rightMotor1_1 = 10; // 定义10引脚为右前侧电机,PWM控制速度
const int rightMotor1_2 = 12; // 定义12引脚为右前侧电机控制方向
const int rightMotor2_1 = 11; // 定义11引脚为右后侧电机,PWM控制速度
const int rightMotor2_2 = 13; // 定义13引脚为右后侧电机控制方向
const int trac1 = 9; //从车头方向的最左边开始排序 (传感器)
const int trac2 = 2;
const int trac3 = 3;
const int trac4 = 4;
void setup() {
Serial.begin(9600); //串口初始化
pinMode(leftMotor1_1, OUTPUT);// 配置引脚为输出或输出模式,它是一个无返回值函数,函数有两个参数pin和mode
pinMode(leftMotor1_2, OUTPUT);
pinMode(leftMotor2_1, OUTPUT);
pinMode(leftMotor2_2, OUTPUT);
pinMode(rightMotor1_1, OUTPUT);
pinMode(rightMotor1_2, OUTPUT);
pinMode(rightMotor2_1, OUTPUT);
pinMode(rightMotor2_2, OUTPUT);
pinMode(trac1, INPUT);
pinMode(trac2, INPUT);
pinMode(trac3, INPUT);
pinMode(trac4, INPUT);
}
void loop()
{
tracing(); //是一个函数,在下面有对这个函数的定义
}
void tracing() // tracing()函数定义:上面void loop里面只有tracing这一个函数,arduino标准程序必须包含setup函数和loop函数,loop函数其实是一个循环,因为这个程序很简单没循环做的事情,所以循环函数为空,但必须要保留,这是arduino的语法规范。
{
int data[4]; //定义一个数组data[]包含四个数据,读取来自9,2,3,4引脚的信号存储到这个数组中,而9,2,3,4引脚连接的就是四个传感器,因此这个数组的功能就是记录四个传感器的信号,由下面的程序可以知道,通过对这几个传感器信号的判断,并根据这几个不同的情况作出不同的反应
data[0] = digitalRead(9);
data[1] = digitalRead(2);
data[2] = digitalRead(3);
data[3] = digitalRead(4);
//高电平-关断状态(没有反射)-有黑线-灯不亮;低电平-接收(反射)-无黑线-灯亮
//左右都没有检测到黑线,直行
if(!data[0] && !data[1] && !data[2] && !data[3]) //0000,灯亮
{
motorRun(FORWARD, 220);
}
if(!data[0] && data[1] && data[2] && !data[3]) //0110
{
motorRun(FORWARD, 220);
}
//右边检测到黑线,右转
if(!data[0] && !data[1] && data[2] && !data[3]) //小转 0010
{
motorRun(TURNRIGHT, 150);
}
if(!data[0] && !data[1] && data[2] && data[3]) //中转 0011
{
motorRun(TURNRIGHT, 200);
}
if(!data[0] && !data[1] && !data[2] && data[3]) //大转 0001
{
motorRun(TURNRIGHT, 220);
}
//左边检测到黑线,左转
if(!data[0] && data[1] && !data[2] && !data[3]) //小转 0100
{
motorRun(TURNLEFT, 120);
}
if(data[0] && data[1] && !data[2] && !data[3]) //中转 1100
{
motorRun(TURNLEFT, 150);
}
if(data[0] && !data[1] && !data[2] && !data[3]) //大转 1000
{
motorRun(TURNLEFT, 200);
}
//左右都检测到黑线是停止
if(data[0] && data[1] && data[2] && data[3]) //0000
{
motorRun(STOP, 0);
while(1);
}
Serial.print(data[0]);
Serial.print("---");
Serial.print(data[1]);
Serial.print("---");
Serial.print(data[2]);
Serial.print("---");
Serial.println(data[3]);
}
void motorRun(int cmd,int value) // 定义一个函数motorRun()
{
// 设置PWM输出,即设置速度 analogWrite(pin, value) 通过PWM的方式在引脚上输出一个模拟量,较多的应用在LED亮度控制、电机转速控制等方面。该函数支持以下引脚:3、5、6、9、10、11。在Arduino控制板上引脚号旁边标注~的就是可用作PWM的引脚,analogWrite函数为无返回值函数,有两个参数pin和value,参数pin表示所要设置的引脚,只能选择函数支持的引脚;参数value表示PWM输出的占空比,范围在0~255的区间,对应的占空比为0%~100%
analogWrite(leftMotor1_1, value);
analogWrite(leftMotor2_1, value);
analogWrite(rightMotor1_1, value);
analogWrite(rightMotor2_1, value);
//方向
switch(cmd)
{
//判断cmd的状态:如果cmd==FOTWARD,输出“FORWARD/r/n”的状态,为LEFTMotor1设置为高电平,为leftMotor2设置为低电平,为RightMotor1设置为高电平,为RightMotor2设置为低电平
case FORWARD:
Serial.println("FORWARD"); //输出状态
//Arduino 的输出基本就用两个函数 print 和 println,区别在于后者比前者多了回车换行,Serial.println(data)
//从串行端口输出数据,跟随一个回车('r')和一个换行符('n')。这个函数所取得的值与 Serial.print()一样。
//其作用为设置引脚的输出电压为高\低电平。该函数无返回值,有两个参数pin和value,pin参数表示所要设置的引脚,value参数表示输出的电压,HIGH为高电平,LOW为低电平。在使用digitalWrite(pin, value)函数之前要将引脚设置为OUTPUT模式。例:pinMode(x, OUTPUT);其中x为引脚编号。pinMode函数用于设置引脚模式。
digitalWrite(leftMotor1_2,HIGH );
digitalWrite(leftMotor2_2, LOW);
digitalWrite(rightMotor1_2, HIGH);
digitalWrite(rightMotor2_2, LOW);
break; //完成以上一系列函数后结束这个函数
break;
case TURNLEFT:
Serial.println("TURN LEFT"); //输出状态
digitalWrite(leftMotor1_2, LOW);
digitalWrite(leftMotor2_2, HIGH);
digitalWrite(rightMotor1_2, HIGH);
digitalWrite(rightMotor2_2, LOW);
break;
case TURNRIGHT:
Serial.println("TURN RIGHT"); //输出状态
digitalWrite(leftMotor1_2, HIGH);
digitalWrite(leftMotor2_2, LOW);
digitalWrite(rightMotor1_2, LOW);
digitalWrite(rightMotor2_2, HIGH);
break;
default:
//如果以上情况都不是,输出STOP,所有电机输出为低电平
Serial.println("STOP"); //输出状态
digitalWrite(leftMotor1_2, LOW);
digitalWrite(leftMotor2_2, LOW);
digitalWrite(rightMotor1_2, LOW);
digitalWrite(rightMotor2_2, LOW);
}
}
只能找到咸鱼上视频截图了,前面那个白色块是充电宝。

现在看来,可以使用PID控制算法,当时写得太死板了,完全是一一对应的一个萝卜一个坑的速度,慢且机械,还是PID顺滑~~。同时咧,车车的四个轮,参照现实中的轿车,分为驱动轮方向轮,啊,我这写的嘛呀,四个轮又转向又驱动。很待改进,但摆烂了,在这里献丑了。
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty