专注电子技术学习与研究
当前位置:单片机教程网 >> Arduino >> 浏览文章

arduino驱动舵机步进电机与超声波程序

作者:huqin   来源:本站原创   点击数:  更新时间:2014年04月26日   【字体:
         外国人都很喜欢给产品起很厉害的名字,比如蓝牙,不过就是个近距离数据传输技术,比如wifi,一样的,其实是无线网络通信技术的一种,但是看起来名字酷帅狂拽的那种。
       这次给瓦力配的大脑是 ardiuno ,是不是听起来很高贵冷的样子,其实就是一块avr单片机而已.....

arduino是意大利人发明的,把底层的代码全部都封装好了,所以程序写起来就跟搭积木一样,灰常简单明了,没有电子基础的人都能用的来。而且它是开源的,人家写好的东西很多可以直接用,翻个墙还可以看到很多好东西,不过妥妥的注释全是英文,这个时候就很明显看到了国内国外在个人做电设上的差距,先不说人家的模块各种高大上,也不说人家的比赛各种多各种神奇,技术上咱们比不上人家。只是光是拿做模型模具的条件来说,国内的发展水平差太多了,木有办法,神马机械条件的使用都是要钱滴。
       扯偏了,我给儿子duby一号初步要实现的功能是,语音识别,语音播放,超声避障。暂时使用的模块是LD3320语音识别,WTV020-SD语音播放,HC-SR04超声测距,以及电机驱动,两个直流减速电机和三个舵机,用的是 arduino nano V3.0控制器,arduino家族里面最小的一款,因为我儿子实在太小了放不下太多东西......还好性能不错。
        想做个儿子纯粹是心血来潮= = ,有人证!!!不是为了泡妞好吗。
        许久没有碰过电设了,连中断定时器IO口神马的知识都忘得差不多了。而且还脑残选的一款木有很熟悉的单片机,要用的模块也是一个都没上手过,好吧,真的是一切从头开始。依稀记得去年搭过一辆会唱歌的车子,用的也是arduino ,依稀记得当时用的代码好像也是这里抄抄那里抄抄......结果本来想实现能写字功能的没实现就送掉了 因为懒得调参数
        demo,这次造儿子要认真一点,不可以再那么随便。
        接下来是技术贴,先上舵机程序,arduino有自己的库,灰常简单好用,去官网上看了人家的技术手册,拿过来改改就可以用了。
#include<Servo.h>
char buffer[10];
Servo servo1;
void setup()
{
servo1.attach(5);
Serial.begin(9600);                                          //波特率不是高频通信时9600足矣
Serial.flush();
servo1.write(90);                        // 舵机打到90度!get !是不是很方便!!!
Serial.println("starting.....");

}
void loop()
{
if(Serial.available()>0)
{
int index=0;
delay(100);
int numchar=Serial.available();
if(numchar>10)
{
numchar=10;
}
while(numchar--)
{
buffer[index++]=Serial.read();

}spliString(buffer);
}
}
void spliString(char*data)
{
Serial.print("Data entered:");
Serial.println(data);
char*parameter;
parameter=strtok(data,",");
while(parameter!=NULL)
{
setServo(parameter);
parameter=strtok(NULL,",");                   //long int strtol(const char *nptr,char **endptr,int base); 我一直觉得这种突然出现的
                                                                                      自带函数都是来给我添堵的。
这个函数会将参数nptr字符串根据参数base来转换
                                                                                    成长整型数。  新函数!get!
 }
for(int x=0;x<9;x++)
{
buffer[x]='\0';

}
Serial.flush();
}
void setServo(char*data)
{
if((data[0]=='L')||(data[0]=='l'))
{
int firstval=strtol(data+1,NULL,10);
firstval=constrain(firstval,0,180);                              // 限制!
servo1.write(firstval);
Serial.print("Servo1 is set to:");
Serial.println(firstval);
}
if((data[0]=='R')||(data[0]=='r'))
{
int secondval=strtol(data+1,NULL,10);
secondval=constrain(secondval,0,255);
servo1.write(secondval);
Serial.print("servo1 is set to:");
Serial.println(secondval);
}
}
       这是控制单个舵机的程序,通过串口通信在PC端控制舵机。红色线接6V电源,褐色线接地,橙色信号线接在D5口,因为要输出的是PWM信号,在nano中只有3,5,6,9,10,11和13脚具有该功能,可以输出模拟量,即固定脉冲。舵机转动范围是0~180度,现在的程序是上电时直接打到90度的位置。
我用两个18650供电,7806和7805稳压。
       改完这个程序瞬间觉得成就感满满有木有,接着就准备弄电机。我买的是uln2003,三毛五一片,用不起八块一片的mos。依稀记得我很久很久以前用uln2003成功驱动过,所以我把自己给坑了。芯片搭好以后特么的就是木有输出,查了各种之后,我笑了。它确实是能驱动....可是这玩意只适合驱动步进电机.....驱动直流电机的话只能走一个方向和停止,不能反转.....要想反转要用三极管加两个臂,构成类似H桥的东西,或者是用它两个口的反相器构建。早知这么麻烦,当时一定会买一个别的现成的,比如L298n.... 这是乱凭经验的教训。
      ULN2003的接法为,8脚接地,9脚悬空,其他是input和outpu,一共七路,负载一端接电源,另一端接输出。好像原理是集电极开路导通神马的= = ,原谅我当年模电没学好.......
      程序木有写,因为就一句digitalWrite(x,HIGH或者LOW)
       x是arduino的信号输出脚,输出的是数字量,控制通断。HIGH对应的是51里的高电平1,LOW对应的是低电平0,注意是要大写。补充一点,所有的口都可以做数字口,都可以输出HIGH 或者LOW。并不是标着A就只能做模拟口,模拟口只是那个脚特有的功能。
      池老师突然觉得这篇日志好适合入门......
      (⊙_⊙),困了,明天再写。
     昨天说到被电机驱动坑了,今天去实验室转悠的时候小城给了一个我心心念念的L298n,妥妥的正传反转180度360度随意转了好吗。附程序:
int a1=3;
int b1=5;
int zuo1=0;
int zuo2=1;
int you1=2;
int you2=4;
void setup()
{
pinMode(0,OUTPUT);
pinMode(1,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
}
void loop()
{
qianjin(100,100,8000);
tingzhi();
houtui(100,100,8000);
tingzhi();
}
void qianjin(int zuo,int you,int chang)
{
  digitalWrite(zuo1,HIGH);
  digitalWrite(you1,HIGH);
  digitalWrite(zuo2,LOW);
  digitalWrite(you2,LOW);
  analogWrite(a1,zuo);
analogWrite(b1,you);
delay(chang);
}
void tingzhi()
{analogWrite(a1,0);
analogWrite(b1,0);
digitalWrite(zuo1,LOW);
  digitalWrite(you1,LOW);
  digitalWrite(zuo2,LOW);
  digitalWrite(you2,LOW);
  delay(1000);
}
void houtui(int zuo,int you,int chang)
{
 digitalWrite(zuo1,LOW);
  digitalWrite(you1,LOW);
  digitalWrite(zuo2,HIGH);
  digitalWrite(you2,HIGH);
  analogWrite(a1,zuo);
analogWrite(b1,you);
delay(chang);
}
void zuozhuan(int zuo)
{
analogWrite(b1,0);
 digitalWrite(you2,LOW);
  digitalWrite(you1,LOW);
   digitalWrite(zuo1,HIGH);
 digitalWrite(zuo2,LOW);
  analogWrite(a1,100);
  delay(zuo*50);
  tingzhi();
}
void youzhuan(int you)
{
analogWrite(a1,0);
 digitalWrite(zuo2,LOW);
  digitalWrite(zuo1,LOW);
   digitalWrite(you1,HIGH);
 digitalWrite(you2,LOW);
  analogWrite(b1,100);
  delay(you*50);
  tingzhi();
}
这个程序毫无修饰一看就知道是我写的.....粗糙得一逼啊。
L298N可以驱动两路直流电机或者步进电机,程序中a1,b1对应为模块上的使能端A,B,使用pwm口输出可以控制电机转动的速度(即车速) ,值0~255,255代表5V,0代表0V,加1时步长为0.02V增量,此处取100可改。zuo1,zuo2和you1,you2是两个电机各自的方向控制口,两相不同时电机正反转,同为低电平时电机不转。
小记:nano 板上 pwm输出口只有 3,5,6,7,9,10,11,13 ,用analogWrite()函数输出,板上所有口均可做数字口输出。
电机舵机这两部分木有难的地方,毕竟这玩意上电就可以动弹。
 接着我就开搞超声波检测距离的模块。
 
      
这东西长这样,五块一个。
这东西原理是,我们声音发出去是会弹回来的对吧,就是基于这个原理。
控制口发一个10US 以上的高电平,就可以在接收口等待高电平输出.一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离.如此不断的周期测,就可以达到你移动测量的值了。
找到的参考例程都是51之类的,还好这东西原理不难,凭我这样子半吊子水平还能改改用,上程序
#define ECHOPIN 8                       
#define TRIGPIN 9 
void setup()
{
Serial.begin(9600);
pinMode(ECHOPIN, INPUT);
pinMode(TRIGPIN, OUTPUT);
void loop()
{
digitalWrite(TRIGPIN, LOW);
delayMicroseconds(2);                           //制造脉冲
digitalWrite(TRIGPIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGPIN, LOW);
float distance = pulseIn(ECHOPIN, HIGH);
distance= distance/58;
Serial.println(distance);
delay(500);
}
} 

这东西一共四个脚 ,一个是5V电源,一个是地,一个是ECHO一个是TRIG,这两个是数据的收发口,连到单片机上。我们通过TRIG发送一个10us以上的脉冲,就是一个有高有低的方波,然后就可以检测ECHO口的返回数据了,我们不用关心超声波是如何发送又是如何接收的,只要知道我们给一个脉冲,就可以在ECHO口守株待兔,读到一个高电平为止,然后把这中间的时间拿去处理就对了。
我们看到一个函数: 

pulseIn()函数用来读取一个引脚的脉冲(HIGH或LOW)。例如,如果value是HIGH,pulseIn()会等待引脚变为HIGH,开始计时,再等待引脚变为LOW并停止计时。返回脉冲的长度,单位毫秒。如果在指定的时间内无脉冲函数返回。
计时范围从10微秒至3分钟。(1秒=1000毫秒=1000000微秒)
语法:
pulseIn(pin, value) 
pulseIn(pin, value, timeout)
参数:
pin:你要进行脉冲计时的引脚号(int)。 
value:要读取的脉冲类型,HIGH或LOW(int)。 
timeout (可选):指定脉冲计数的等待时间,单位为微秒,默认值是1秒(unsigned long) 
这是一个灰常方便的函数,我爱arduino。
读到的东西是英寸单位,所以要除以58,这样一来就能化成厘米了,数据手册是这么说的,别问我为什么。得出来的数据通过串口监视器可以查看,精度不是很高,超过四米基本瞎了,低于二十厘米反应也迟钝了。但是用来做避障神马的妥妥地足够了,预计日后会用舵机配合它进行组合扫描探测,现在先放着吧。
然后就剩两个模块了,下次再来。
关闭窗口

相关文章