1. 数码管
(1)数码管简介
数码管是一种半导体发光器件,其基本单元是发光二极管。数码管按段数分为七段数码管
和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数的显示);
按发光二极管单元连接方式分为共阳极数码管和共阴极数码管。共阳极数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)数码管。共阳数码管在应用时应将公共极
COM 接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮。当某一字段的阴极为高电平时,相应字段就不亮。
(2)实验:数码管随机显示数字
int BUTTON=2;
void style_0(void){
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
}
void style_1(void){
digitalWrite(4,LOW);
digitalWrite(7,LOW);
}
void style_3(void){
digitalWrite(4,LOW);
digitalWrite(3,LOW);
digitalWrite(5,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void style_2(void){
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
}
void style_4(void){
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
}
void style_5(void){
digitalWrite(3,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void style_6(void){
digitalWrite(3,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
}
void setup() {
// put your setup code here, to run once:
for(int i=3;i<=9;i++){
pinMode(i,OUTPUT);
pinMode(BUTTON,INPUT);
}
}
void loop() {
// put your main code here, to run repeatedly:
int Number = GetRandomNumber(0,7);
DisplayNumber(Number);
delay(250);
DisplayClear();
delay(250);
}
int GetRandomNumber(int MinNum,int MaxNum){
int RandNumber = random(MinNum,MaxNum);
return RandNumber;
}
void DisplayClear(){
for (int i=3;i<=9;i++){
digitalWrite(i,HIGH);
}
}
void DisplayNumber(int GetNumber){
switch(GetNumber){
case 1:
style_1();
break;
case 2:
style_2();
break;
case 0:
style_0();
break;
case 3:
style_3();
break;
case 4:
style_4();
break;
case 5:
style_5();
break;
case 6:
style_6();
break;
}
}
需要注意的地方就是,这里是共阳极数码管,所以给数码管通上低电平数码管才会亮,而当数码管亮了一次后需要将所有灯管都熄灭,负责则会导致已亮的灯管一直亮着。
2.伺服电机
(1)在使用伺服电机时需要用到ARDUINO的扩展库<Servo.h>,该库中有控制伺服电机的函数,伺服电机有三个接口,分别是电源、接地、控制口,先来看看我们的代码:
# include <Servo.h> //伺服电机扩展库
Servo myservo;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
myservo.attach(2);
}
int INPUTdata=0;
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()>0){
INPUTdata+=1;
int toPos = Serial.parseInt();
int fromPos = myservo.read();
if(toPos>=fromPos){
for (int i=fromPos;i<=toPos;i++){
myservo.write(i);
delay(15);
}
}
else{
for (int i=fromPos;i>=toPos;i--){
myservo.write(i);
delay(15);
}
}
Serial.print("INPUTdata");
Serial.print(INPUTdata);
Serial.print(" fromPos: ");
Serial.print(fromPos);
Serial.print(" toPos: ");
Serial.println(toPos);
while(Serial.available()>0){
Serial.read();
}
}
}
语句介绍
Servo myservo;
定义一个伺服电机对象
myservo.attach(2);
将伺服电机对象接到2号口,可对伺服电机控制
Serial.parseInt();
parseInt()函数,从串口接收数据,只读取数字;
myservo.read();
伺服电机库函数,读取当前电机状态,返回电机位置
myservo.write(value);
伺服电机库函数,控制电机转动到值为value的位置 0=<value<=180;
(2)程序解释,从串口接收一个数据然后转到对应位置,但是我们将程序烧到UNO板上,发现电机转动的很快,这里我们设置一个for()循环,控制电机转动速度。
3.超声波测距模块
(1)模块介绍
US=015超声波测距模块
电气参数 | US-015 |
---|---|
工作电压 | DC 5V |
工作电流 | 2.2mA |
工作温度 | 0~+70度 |
输出方式 | GPIO |
探测距离 | 2cm-400cm |
探测精度 | 0.1cm+1% |
分辨率 | 高于1mm |
模块一共四个接口
1号pin:接VCC电源(直流5V)。
2号pin:接外部电路的Trig端,向此管脚输入一个10us以上的高电平,可触发模块测距
3号pin:接外部电路的Echod端,当测距结束时,此管脚会输出一个高电平,电平宽度会输出一个高电平,电平宽度为超声波往返时间之和
4号pin:接外部电路的地
测距原理:在Trig引脚输入一个10us以上的高电平,系统便可发出8个40KHZ的超声波脉冲,然后检测回波信号。当检测到回波信号后,通过Echo管脚输出,最后通过 L=1/2time340m/s 则可得出距离
(2)模块搭配数码管和伺服电机的实验
现在,我们已经知道了如何使用数码管、伺服电机和超声模块,那么接下来我们要做的就是将这三部分结合:测定障碍物的距离,当障碍物与装置的距离小于10cm时,通过数码管显示当前距离,并且让舵机转动,想象一些,如果将这些东西只能装到避障小车会是什么效果?就是寻找没有障碍的方向。
首先看看代码:
#include <Servo.h>
Servo my_servo;
int TrigPin=11;
int EchoPin=12;
long Echo_time=0; //接收到高电平所用时间
double distance;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
my_servo.attach(2); //将伺服电机接到2号引脚
pinMode(TrigPin,OUTPUT);
pinMode(EchoPin,INPUT);
for (int i=3;i<=9;i++){ //将所有数码管设置为输出模式
pinMode(i,OUTPUT);
}
my_servo.write(90);
}
void style_0(void){ //显示的数字设置
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
}
void style_1(void){
digitalWrite(4,LOW);
digitalWrite(7,LOW);
}
void style_3(void){
digitalWrite(4,LOW);
digitalWrite(3,LOW);
digitalWrite(5,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void style_2(void){
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
}
void style_4(void){
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
}
void style_5(void){
digitalWrite(3,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void style_6(void){
digitalWrite(3,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
}
void style_7(void){
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(7,LOW);
}
void style_8(void){
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
}
void style_9(void){
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void loop() {
// put your main code here, to run repeatedly:
for (int i=3;i<=9;i++){
digitalWrite(i,HIGH);
}
digitalWrite(TrigPin,LOW);
delayMicroseconds(2);
digitalWrite(TrigPin,HIGH);
delayMicroseconds(10); //让测距模块开始工作发出频率电波
digitalWrite(TrigPin,LOW);
Echo_time=pulseIn(EchoPin,HIGH); //读取接收到声波来回的时间
if (Echo_time>1&&Echo_time<85000){
distance=Echo_time*0.017; //通过接收到高电平的时间算出当前距离
}
Serial.print("the distance is: ");
Serial.print(distance);
Serial.println(" cm");
int real_dis=(int)distance; //将浮点数类型的distance转换为整数
if (real_dis<10){
waring_num(real_dis); //显示危险距离
delay(200);
for(int i=3;i<=9;i++){
digitalWrite(i,HIGH); //熄灭所有灯管
}
int fromPos=my_servo.read();
servo_turn(fromPos);
delay(100);
}
delay(500);
}
void waring_num(int waring_dis){ //显示小于10的危险距离
switch(waring_dis){
case 1:
style_1();
break;
case 2:
style_2();
break;
case 0:
style_0();
break;
case 3:
style_3();
break;
case 4:
style_4();
break;
case 5:
style_5();
break;
case 6:
style_6();
break;
case 7:
style_7();
break;
case 8:
style_8();
break;
case 9:
style_9();
break;
}
}
void servo_turn(int fromPos){ //舵机转动函数
int toPos=30*random(1,6);
if (fromPos<toPos){
for (int i=fromPos;i<=toPos;i++){
my_servo.write(i);
delay(15);
}
}
else{
for (int i=fromPos;i>=toPos;i--){
my_servo.write(i);
delay(15);
}
}
Serial.print("the formPos: ");
Serial.print(fromPos);
Serial.print(" the toPos: ");
Serial.println(toPos);
delay(100);
}
将舵机初始位置设为90°,然后每次测距之后都判断距离是否在安全范围类,如果不在安全范围内,显示当前距离,然后就让舵机随机像一个方向转动任意的30°的倍数,然后再次检测。代码本身是没有什么难度,而是在于将三个部分组合起来使用的思维,使用合适的代码将三个部分的代码组合并且使之连贯。