Posts Tagged ‘输出’

Arduino开发板实验二:模拟输入和输出(用电位器和开关控制直流电机)

在上一个Arduino小实验里,我们尝试了用开发板来读写数字信号(0和1),貌似非常简单,难度系数跟吃苹果差不多。昨天淘宝的直流电机控制板终于送到了,接下来这个实验准备测试读写模拟信号。这个实验难度系数稍大一点,达到了吃香蕉的程度,搞不定的同学请去动物园请教猴子兄弟(开个玩笑,但是Arduino的确非常好开发)

我计划的实验目标是:
1,使用电位器控制直流电机的转速
2,使用开关控制直流电机的旋转方向

模拟输入

查了下资料,许多单片机的管脚电压都是+5V或0V,分别对应1和0。而机器人面对的自然界却没有这么泾渭分明,例如大气温度,到墙壁的距离,声音的强度等等,这些值就是模拟值。Arduino开发板上,标记了“Analog In”的16个管脚,就是用来测量模拟值输入的。这些输入电压的范围是0~+5V,开发板会把它映射到0~1023的整数。从这个数值范围,我们可以估算出Arduino能识别的电压精度大概是5mV,小于这个范围的变换无法识别。

电位器

这个东西是从邻居小朋友那里骗来的。在我读高中的时候,好像把这个东西叫滑动变阻器,个头很大。现在都是小小的旋转电位器了,原理图应该是一样的:

电位器

电位器

接线方式是两端分别接GND和+5V,中间随意接在一个Analog In的管脚上。我选择了一个大吉大利的6号。

电位器接线

电位器接线

读取模拟电压值的函数为:

int readValue = analogRead(readPin);

用端口监视器做个分解实验,使用Serial.println命令把readValue显示在电脑上,和想象中的结果完全一样。端口读写部分准备做为下一个实验主题,这里就不细说了:

端口监视

端口监视

PWM输出

作为一个外行,我之前曾经想过怎么让单片机输出一个模拟值。觉得必须用10个管脚,对应的二进制从0~1023,然后找一个数模转换的东西变成模拟电压值。结果一看资料发现自己太圭了,原来有一种叫做占空比的东西,只用一个管脚就可以输出0~255的数值。从这里也了解到嵌入式常用的一个叫“时序”的东西,以后应该会经常遇到,这种方式可以用很少的管脚实现非常复杂的功能(估计业内人士又要鄙夷的飘过了)。看下面的图解,从Arduino官网顺来的:

PWM模拟输出

PWM模拟输出

板子上标注了“PWM”的区域就是管脚均可以用于这种输出。使用的函数是:

analogWrite(pin, value);

注意value值的范围是0~255。

直流电机控制板

这个控制板的功能是把PWM的输出,转换成真正的模拟电压值,从而控制直流电机旋转。电机的种类很多,还有舵机,步进电机等等,控制方式都不一样,那些以后再试。先看一下这个板子的介绍,也是一个顺手牵来的图:

直流电机控制板

直流电机控制板

这个图里信息太多了,咱们捞干的讲几个:
1,左右两边是对称的,可以控制两个直流电机,咱们下面只看左边
2,绿色的“直流电机A接口”,用于接电机的两根电源线
3,直流电机A信号输入接口,一共有3个脚,分别是I1,I2和EA。其中I1和I2是数字接口,用于控制开关和方向,EA是模拟接口,用于控制转速
例如:I1=1,I2=0顺时针转,I1=0,I2=1就逆时针转,I1=I2的时候,停止转动。EA是0~255的PWM值,对应从小到大的转速
4,最下面的VMS接电源正极,GND接地,边上还有一个+5V,不用管它,本来是由它给逻辑电路供电的,但是默认情况下,是通过DUAL那个跳线帽由VMS搭车送电。

看看最终的接线图,专业人士一般用面包板之类的东西实验,我就直接把铜丝拧上了,请大家不要效仿:

接线图

接线图

接下来是写代码,一共也没几行,大家看注释吧:
注意:我发现Analog输入区编号是0~15,PWM输出区也有0~13,为了验证这两类管脚编号会不会冲突,我特地把readPin和speedPin都设置成了大吉大利的6号。事实证明两者不冲突。

int readPin = 6;    //用来连接电位器
int buttonPin = 38; //用来连接开关,这次用了个吉利的端口号
int i1Pin = 31;     //连接电机驱动板的I1接口
int i2Pin = 30;     //连接电机驱动板的I2接口
int speedPin = 6;   //连接电机驱动板的EA接口

void setup()
{
  pinMode(buttonPin, INPUT);  //开关用于输入
  pinMode(i1Pin, OUTPUT);     //I1和I2都是数字信号
  pinMode(i2Pin, OUTPUT);     //通过设置I1和I2来控制电机旋转方向
  pinMode(speedPin, OUTPUT);  //按占空比方式输出的模拟信号
  digitalWrite(buttonPin, HIGH);  //设置上拉电阻
}

void loop()
{
  //读取按钮状态
  boolean buttonPressed = digitalRead(buttonPin);
  //设置转动方向,I1和I2值相反时,分别对应两种不同的转向;I1和I2值相同时停止转动
  digitalWrite(i1Pin, buttonPressed);
  digitalWrite(i2Pin, !buttonPressed);
  //读取电位器(传感器)的读数,值范围从0到1023
  int readValue = analogRead(readPin);
  //PMW的值范围是0~255
  readValue/=4;
  //设置转速
  analogWrite(speedPin, readValue);
  delay(500);
}

上传程序以后,旋转电位计,可以看到电机的转速不断变化着;掰一下开关,电机就会反转,实验到此顺利结束。

Arduino开发板实验一:数字输入输出

最近有很多朋友关心小爱的进展,真是非常感谢。这段时间我主要在研究小爱的制作方案,大致的工作分为几个部分:机械设计,电子电路,嵌入式开发和人工智能几个部分。

为了确定最终的方案,我最近总在淘宝上晃悠,劲头跟美女购物狂们逛商场有一拼。前一段时间无意中看到了一个叫Arduino的东西,貌似还挺好用,暂定以这个板子为基础来开发电子电路和嵌入式的部分。我以前没有接触过嵌入式开发,如果路过的朋友有更好的方案,请一定要吱一声,谢谢 :)

昨天淘宝的Arduino板子终于到了,型号是Arduino MEGA ATmega1280-16AU AVR(完全不清楚不同型号之间有什么区别),秀一下样子:

Arduino 开发板

Arduino 开发板

今天进行了第一个小实验,跟大家分享一下。实验的目的是实现一个简单的功能,外接一个开关,通过打开或者关闭开关,来控制一个小灯的亮和灭
电子专业的老婆冷笑飘过,这个实验太简单了吧,用传统电路甚至更简单,一个开关直接切断电路即可(传说中的手电筒)。不过我通过这个小实验了解了一个重要信息:原来嵌入式开发可以直接对CPU的管脚直接进行读写,0就是低电压,1就是高电压。以前一直使用高级语言,读CPU的某个脚电压貌似非常遥远。

第一步:到Arduino官网下载Arduino开发IDE和相关驱动
下载完一看,这个软件是绿色的,并且绿的相当彻底,里面还包含了板子的驱动,双击打开就可以使用,我在Windows7,Server2008以及Vista下都用的挺好。

第二步:用USB线连接Arduino板子和电脑,发现驱动可以被自动识别,然后添加了一个USB UART的设备。查看一下这个设备的COM端口号,后面需要用到:

查看COM端口号

查看COM端口号

第三步:
双击运行arduino.exe,第一次使用前,需要设置设备端口号和板子的型号,看下面的抓图:

设置主板型号,我这个是Mega

设置主板型号,我这个是Mega

选择刚才看到的端口号

选择刚才看到的端口号

第四步:接线
为了做这个小实验,我还真拆了家里一个手电筒(真是败家)。文档里说开发板有个LED小灯接在13号管脚,据说术语叫做Pin13,所以就不需要外接小灯了。开关的两个脚一个接地(GND),另一个随便接某个管脚。考虑到13这个数字不吉利,我特地选了一个44号管脚避个邪。看下图:

接了个开关,红色灯是13号LED

接了个开关,红色灯是13号LED

第五步:写代码

int ledPin=13;
int buttonPin=44;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop()
{
  digitalWrite(buttonPin, HIGH);
  digitalWrite(ledPin, digitalRead(buttonPin));
  delay(100);
}

经常搞windows软件开发的朋友可能有点迷糊,这个程序入口在哪里,出口在哪里?事实上这个程序是被Arduino的IDE封装了,它的规则就是先定义几个变量,然后在setup里做几个设置,最后就孜孜不倦的反复跑loop里面的程序。我猜想应该有些中断机制来执行一些特殊处理,这个以后再慢慢学。看来单片机的程序通电以后就没打算让它歇着,高级语言的程序员需要适应一下。
接下来的程序就很好解释了:
pinMode 用于设置管脚的用途,输入还是输出
digitalWrite 用于把某个管脚的电压设置成High还是LOW
digitalRead 用于读取某个管脚的电压状态,返回的也是HIGH或LOW

有一句 digitalWrite(buttonPin, HIGH); 需要解释一下。我希望44号管脚当开关打开时是1,开关闭合是是0。但是请注意第一次闭合以后,这个管脚电压降到0,它不会自动升到1。为了让下次开关打开的时候管脚电压置1,我在每次循环前都给它设置初始值1。画了一个非常丑的电路图:

电路图

电路图

第六步,编译并上传代码

用IDE中的Verify来编译代码,然后用Upload上传。选的44号辟邪管脚果然有效,代码直接编译通过上传成功(真相是确实太简单了)。结果就不给大家贴图了,没啥好看的。不过好人做到底,虽然Arduino的IDE按钮都有提示,我还是画了个说明:

Arduino 0017的菜单

Arduino 0017的菜单

总结:这虽然是个很简单的实验,但是对于一个像我这样没有接触过嵌入式的程序员来说,还是有很多的知识点。我相信有很多和我一样的人,想做机器人但是觉得无从下手,希望这些学习经验有所帮助。高手们就请优雅的飘过吧 :)