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);
}

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