d03f1a62b48a4dab83ee60fab59542e8.gif

甜橙pro|一个正经的信息老师数字信号和模拟信号是Arduino中处理的重要的对象,通过Arduino控制板的运算和处理,我们能实现丰富的功能。数字信号的处理是Arduino最基本的功能,在两者中也是更容易掌握的,所以我们的学习和应用也从数字信号开始。

Arduino中的数字信号和通常所说的数字信号有一点差别。通常所说的数字信号是计算机科学中的一个重要的概念,用来表示将数据表示为离散值序列的信号,在任何给定的时刻,它只能取有限数量值中的一个。而Arduino中的数字信号比它的范围还要小,只能取0或者1(LOW或者HIGH)。

从模拟信号到数字信号,再到Arduino中的数字信号,是越来越简单的。我们不妨从最简单的上手,一步步来解决更复杂的问题。

01

数字信号及其输入输出

Arduino中的数字信号

Arduino中的数字信号是指取值只有0或者1的信号,Arduino中的所有的引脚都能读取或者输出0与1信号。

Arduino控制板的电源电压一般是5V,只要输入值超过电源电压的一半(如2.6V),就代表高电位(1);如果输入值低于电源电压的一半,则代表低电位(0)。

输出数字信号通常也只有两种情况,如果输出0则端口的电压是0V,输出1端口的电压是5V。

读取或者输出信号通常要用到变量,变量的类型有很多,Arduino中为数字信号量身定做的变量类型是布尔型变量。布尔型变量的定义和其它类型是一样的,语句的标准格式是:

boolean 变量名称 = 变量初值;

其中,boolean是指定义的这个变量是布尔型的;变量名称是你为这个变量起的名字,要遵守变量命名的规则,同时也要用起来方便;等号后面是在定义变量的时候为它赋的初值,一般只能是0或1。

数字输入及元器件

数字输入这个说法似乎让人摸不着头脑,其实没有那么难,就是Arduino控制板从一个端口读电压值,如果超过2.5V就是1,不到2.5V就是0。

Arduino的所有端口都能读入或者输出数字信号。当Arduino控制板的端口正确地连接元器件以后,就能从这个端口读入信号,但首先要把这个端口设置成数字输入模式。

pinMode(pin,mode);

其中,pin是你要设置的端口号,也就是元器件连接在Arduino控制板的哪个端口;mode可以设置成INPUT或者OUTPUT,分别代表输入或者输出。

读取输入端口的状态需要用到另一个命令:

val = digitalRead(pin);

其中,val是之前就定义好的一个布尔型变量;pin是连接元器件并且设置为INPUT模式的端口号。

这个命令的作用读入引脚pin的状态,如果检测到高电压,则将1赋给val;如果检测到低电压,则将0赋给val。

有很多元器件都能实现数字读入的功能,最常见的是按钮开关、触摸感应器、光敏传感器、继电器等等。要让这些元器件正常工作就需要正确地连线,由于我们接触Arduino并不久,所以给自己降低一点难度,用配套的扩展板和元器件,可以很方便地连接而不会出错。

数字输出及元器件

数字输出也只是说起来很高深,其实很简单,就是Arduino控制板向一个端口输出电压值,如果是1就输出5V,如果是0就输出0V。

Arduino的所有端口都能读入或者输出数字信号。当Arduino控制板的端口正确地连接元器件以后,就能从这个端口读入信号,但首先要把这个端口设置成输出模式。

输出数字信号需要用到另一个命令:

digitalWrite(pin,value);

其中,pin是连接元器件并且设置为OUTPUT模式的端口号;value是要向pin端口输出的状态,如果value=0,则向pin端口输出低电压;如果value=1,则向pin端口输出高电压。

有很多元器件都能实现数字输出的功能,最常见的是LED灯、蜂鸣器、继电器等等。要让这些元器件正常工作就需要正确地连线,由于我们接触Arduino并不久,所以给自己降低一点难度,用配套的扩展板和元器件,可以很方便地连接而不会出错。

串口输入和输出

前面所说的输入和输出是Arduino控制板通过端口连接元器件进行读写。我们在前面的操作中知道,Arduino有一个USB端口连接电脑,IDE通过USB端口给控制板烧写程序。

除此以外,Arduino控制板还能通过USB端口与电脑收发信息,电脑向Arduino控制板发信息我们成为串口输入,Arduino控制板向电脑发信息,我们称为串口输出。

val = Serial.read();//从串口读取一个字节的数据;

Serial.println(val);//发送一些数据到串口;

这两个功能光在书本上看很难理解到底是完成什么工作,最好的方法是自己打开电脑,接上Arduino控制板试一试。要观察这个功能需要用到串口监视器,点击一下右上角的放大镜图标,就可以打开。

1b5763290e20ec296b02f47ab5097d98.png

△ 串口监视器的启动

打开串口监视器以后,我们看到的只是一个白屏,那是因为我们还没有利用它传输数据。上面介绍的两个语句就是实现和串口进行数据交互的,试试执行这些命令会得到什么结果。

6c6aa0a93bafa2cdf779d8702c0f3304.png

△ 串口监视器的观察页面

02

Arduino的控制结构

正常情况下,程序代码按照从上往下的顺序依次执行,但有时我们并不希望程序完全按我们写代码的顺序执行,这就需要用到控制结构语句。

改变程序流程的判断语句

程序中,依照某个状况来决定执行哪些语句,或者重复执行那些动作的代码,称为控制结构。if条件式是基本的控制结构,它具有“如果……则……”的意思。

你在自助购物机上选定了东西,屏幕上会出现一个付款码。“如果”你在一段时间内扫码付款,“则”把商品送至取货口;“如果”你在规定时间内没有扫码付款,“则”退出付款页面。这是一个非常典型的判断语句。

在Arduino程序中,这个过程通过“if……else……”语句来实现。把刚刚这个过程写成计算机语句就应该是这样的:

if(规定时间内扫码付款) {把商品送至取货口;}

else{退出付款页面;}

简化编程代码的循环语句

有时类似的事情需要执行不止要做一次,就像学习新单词布置作业要抄写几遍,或者长跑需要绕操场跑多少圈。Arduino的程序代码经常也要重复,而且重复的次数通常比较多,循环语句会让写代码的行数大大减小。

Arduino中的循环语句和C语言中是一样的,主要用到for语句和while语句。

for(初始条件;判断条件;更新循环变量){

  循环操作;}

for语句的基本作用是让循环操作重复特定的次数,例如:

for(int i = 0;i < 10;i++){

  Serial.println(“digital”);}

这里完成的工作就是向串口重复10次发送“digital”的字符串。

while(判断条件;){

  循环操作;}

while语句与if相似,当while后的判断条件成立时,会执行之后的循环操作,然后检查判断条件是否成立,直到判断条件不成立为止。

LED = digitalRead(10);

while(LED = 0){

  digitalWrite(13,HIGH);

  LED = digitalRead(10);}

这里完成的工作就是重复地检测10号端口的电压,直到它变成高电平。

除了我们专门写的循环语句,Arduino程序本身就是循环执行的。Arduino程序和一般的计算机程序不一样,它不会同时执行多个程序也不会退出,loop()函数中的代码会一遍一遍地重复执行。当你给控制板供电之后,程序就开始运行,如果想停止运行,只能采取断电方式。

03

应用数字信号的实例

数字输入和输出虽然简单虽然简单,但是已经可以用来解决一些小问题,实现一些小想法。

按键控制LED灯

按键控制LED灯是一个非常简单的例子,但是我们自己增加一点难度。我们在按下按键的过程中,开关可能有一小段时刻接触不好,灯会闪烁,我们尝试一下通过编程让灯不再闪烁。

首先要连接好线路,这里还是选用傻瓜式的套装,开关连接在10号端口,LED灯连接在11号端口。

5e82ed73ee5acd03b0e18b48fe719a78.png

△ 用按键控制LED灯的线路连接

对于程序怎么运行的,我画了一个简单的流程图。开关按动的时候,首先要记录下当时开关是按下还是未按下,然后过一小段时间再看开关状态是不是跟前面一样,如果一样才开灯或者关灯。

42d03e8865895c9865156140b4e47cfe.png

△ 用按键控制LED灯的控制流程图

int ledPin = 11;      // LED灯管脚定义

int buttonPin = 10;     // 按键的管脚定义

int ledLight = LOW;      // LED灯状态定义

int buttonPress = LOW;      // 按键状态定义

void setup() {

  pinMode(ledPin, OUTPUT);  //设置LED管脚输出模式

  pinMode(buttonPin, INPUT); //设置按键管脚上拉输入模式

}

void loop() {

  if (digitalRead(buttonPin) != ledLight) { // 若灯的状态和开关不一样

    buttonPress = digitalRead(buttonPin);  // 读取开关的状态

    delay(100); //等待跳过按键抖动的不稳定过程

    if (digitalRead(buttonPin) == buttonPress){ // 若前后开关状态一样    

      digitalWrite(ledPin, buttonPress); // 改变LED灯的亮灭

      ledLight = buttonPress; // 改变LED灯的状态

    }

  }

}

我们可以在GIF图中看到,红色的LED灯没有出现忽闪忽闪的情况。我们也可以试试不用这些判断语句,开关按下就亮灯,未按下就关灯,看看LED灯会不会忽闪忽闪的。

a09806b10b36cda2a256bea9b17c930e.gif

△ 用按键控制LED灯的实物展示

LED流水灯

流水的LED灯也是一个非常简单的例子,我们要实现的效果是一排LED等从左到右依次点亮,再从右到左依次熄灭。

因为傻瓜套装里LED灯的数量不够,所以用到了面包板、导线、电阻等元器件,其实就是把六个LED灯依次连接到4-9号端口。但是LED灯要连接保护电阻,还要接地,电路的连接看起来复杂一点,我们在后面再找个机会专门讲电路的连接。

a7ad03508d0298a7e88f1a444fb9e124.png

△ LED流水灯的连线图

对于程序怎么运行的,我画了一个简单的流程图。这个流程比前面一个甚至还要简单,就是从1到6依次点亮LED灯,然后从6到1依次熄灭LED灯。

6f433d436d0391f2c120249fa5efba76.png

△ LED流水灯的控制流程图

int delayTime = 200;

int ledPin;

void setup()

{

  for (ledPin = 4; ledPin < 10;ledPin++)   { //依次设置4~9引脚为输出模式

    pinMode(ledPin, OUTPUT); //设置第ledPin个引脚为输出模式

  }

}

void loop()

{

  for (ledPin = 4; ledPin < 10;ledPin++)   { //依次点亮4~9引脚相连的灯

    digitalWrite(ledPin, HIGH); //点亮ledPin引脚相连的led灯

    delay(delayTime);//延时delayTime

  }

  for (ledPin = 9; ledPin > 3;ledPin--)   { //依次熄灭9~4引脚相连的灯

    digitalWrite(ledPin, LOW); //熄灭ledPin引脚相连的led灯

    delay(delayTime);//延时delayTime

  }

  delay(1000);

}

1d7ad46ec86ee55b8dac52a9e856f87a.gif

△ LED流水灯的实物展示


dd3791d17fcf6e94c4adf823e2ac1324.gif

甜橙pro

401ade4243e893a0b77128401eef6320.png

一个正经的信息老师

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐