呃呃,为啥写这个教程呢~

俺也不知道!

唉,说多了都是泪,心酸,卷啊~

以下内容是我的个人理解,专业名词解释可能存在错误,望广大读者指出,万分感谢!


回归内容,今天在这里用一篇博文,带领大家玩转Arduino、入门数电模电、入门传感驱动设计!

这些是我准备的东西,一把杜邦线、一些传感器、一块板子!

杜邦线就是导线,把传感器模块和单片机(Arduino板)连接起来。这里的Arduino板是我之前在双臂机械臂课程用到的板子,其实也就是一块Arduino Nano的扩展板,将所有的IO口引出(D13引脚除外),D13引脚接到了蜂鸣器上面,同时有个LM2596S-5.0的模块实现12V转5V 3A(最大3A输出)的调压功能。

玩单片机呢,大家玩的就是IO口,也就是引脚!这些引脚具备输入(Input)和输出(Output)两种形态,所以被称为IO口。

玩电子的呢,大家经常听到的就是数电模电,而单片机的引脚呢,也分为数字(digital)和模拟(analog)两种。

玩单片机的话,ADC和DAC两个名词,是跳不掉的!

ADC,Analog Digital Change,模拟转数字,模数转换,AD模拟量采集。

DAC,Digital Analog Change,数字转模拟,数模转换,DA数字量输出。

所以,Arduino编程就有了以下四个函数:

digitalRead(int pin) 数字量读取,参数pin为引脚序号;返回该引脚的状态,只有HIGH和LOW(bool类型)
digitalWrite(int pin, int value) 数字量输出,参数pin为引脚序号;参数value为状态量,只有HIGH和LOW(bool类型)
analogRead(int pin) 模拟量读取,参数pin为引脚序号;返回该引脚的模拟值,范围0~1024
analogWrite(int pin, int value) 模拟量输出,参数pin为引脚序号;参数value为状态值,范围0~255

那么什么是数字,什么是模拟呢?数电是什么,模电又是什么呢?

我们拿灯来做一个栗子。我们通过开关来控制灯的亮和灭,我们规定灯亮为1,灯灭为0,这种符合正常人类逻辑的方式,被称为正逻辑;也有规定灯亮为0,灯灭为1,这种被称为负逻辑。正逻辑和负逻辑本质上没有什么差别,因为我们习惯了有就是1,无就是0这样的逻辑方式(推荐阅读《编程珠玑》)。我们将信号分为有和无、或者是当前的电压值是HIGH或低、或者是当前的状态是0或1,这就是数字量——只有0和1两种状态的的量。这在我们的单片机里面,也就对应了IO引脚输出一个高电平或者输出一个低电平、检测当该IO引脚是高电平还是低电平!

那么模拟量呢!我们还是拿灯来做一个栗子。数字量可以用来表示灯开了没有,那么灯的亮度呢?我们可以控制开和关,那么我们能不能控制亮度呢?答案是可以的!这里用来表示一定程度的量,就是模拟量!我们通过单片机的引脚输出一个模拟量,可以实现控制对“程度(灯的亮度、声音的响度等等)”的控制,这就是DAC;同理,我们通过单片机的引脚获取传感器的“程度(温度、湿度、电压值)”的数值,这就是ADC!

那么ADC采集和DAC输出是怎么实现的呢!

我们这里使用的是Arduino Nano,它有A0~A7共计8个ADC模拟量读取的引脚,这些引脚也可以当成普通的IO来使用,顺序为A0~A7对应14~21。其中A4、A5引脚复用为IIC通讯引脚(听不懂没关系,后面会学到)。Arduino的ADC采集精度是10位,所以读取到的数值为0~1024(210),这里的ADC数值其实就是电压值,Arduino的模拟量基准电压(Aref)默认是5V,也就是说,在ADC采集这里,是将0~5V的电压值,进行读取,转成0~1024的数值进行输出。

而Arduino Nano的DAC输出呢,是通过PWM(脉冲宽度调制技术)来实现的,具备PWM的引脚为D3、D5、D6、D9、D10、D11六个引脚。

要说PWM啊,我们先来聊两个概念——频率和占空比!

频率这个词大家应该都不会陌生,是指单位时间内完成周期性变化的次数,这个单位时间我们大多默认的就是1秒钟。比如说我在1秒钟执行了20次,那么我就可以说频率是20Hz,频率=1/单位时间。

占空比这个概念呢,大家可能会陌生一些。我先做个假设,假如单片机的一个引脚输出20Hz的频率,那么产生1Hz的频率需要的时间是多久呢?答案是1s/20=0.05s=50ms!

也就是说,我控制单片机的引脚每50ms完成一次高低电平的变化,实现这个引脚在1s的时间内可以产生20次高低电平的变化,这就是控制单片机的引脚输出20Hz的频率。

我在20ms的时间内,保持引脚处于高电平10ms,处于低电平10ms,那么此时的占空比就是50%;如果我保持引脚处于高电平5ms,处于低电平15ms,那么此时的占空比就是25%,所以占空比就是在一次周期性的电平变化中,所处于高电平的时间与周期时间的比值。

PWM产生的是方波信号(还正弦波、三角波等等,后续我们再聊),Arduino的PWM精度是8位,所以输出的PWM值为0~255(28),默认的频率是490Hz(基本认为是500Hz),这里给大家一个参考资料。图太多了,不想画,人家做的挺好的!

数字输入,就是引脚读取传感器过来的信号,这个信号可能是高电平也可能是低电平,比如按键模块。

数字输出,通过引脚对外输出一个高电平或者输出一个低电平,比如单片机引脚点亮一个LED。

模拟输入,通过引脚感应得到一个电压值,将电压值等比转成一个数值,比如读取一个温度传感器的温度值。

模拟输出,通过引脚输出一个电压值,Arduino的模拟输出范围0~255,也就是说将0~5V的电压值分成255分,我们通过调控电压值就可以来控制引脚输出的程度(这里理解为功率吧)。

这四个,是单片机的基本概念。如果你是资深单片机玩家的话,也会听说过推挽、开漏、浮空、上拉、下拉五个名词!这些内容我们稍后来处理。

上面我们聊了,模拟输出是通过PWM来实现的,而PWM说开了就是通过引脚高低电平的快速切换实现的,那么这个为什么能控制引脚输出的程度呢?这个问题留个大家思考,给大家一个提示:结合LED的闪烁来分析,如果让LED闪烁的频率增加会发现什么呢?调整闪烁频率的占空比又会发生什么呢?留给大家思考+尝试!

基础概念的补充到这里就结束了,接下来开始我们实战的内容!

在文章刚开始的地方,我就贴出来一张图,这些是我现在手头有的零件,接下来我会用这些零件类为大家展现Arduino编程!

这段时间我在古月学院的两门课程——PCB设计和CAD设计,应该就是这两天上线了吧,公开课,免费的不要钱,课程都是一个多小时那种吧!我这里用的板子是自己设计的,现在立创打板不要钱,还是挺方便的!

如果你手上没有这些东西也没关系,你们可以去这个网站进行仿真,效果是一样的,记得网络环境好点!Arduino在线仿真

我这里使用的是Arduino Nano开发板 + LM2596S-5.0降压模块,这里我把Arduino Nano的引脚全部按照Sign Vcc Gnd的顺序留出,避免出现Vcc和Gnd引脚不够用的情况。同时使用了一个DC 5.5-2.1(外径5.5mm,内径2.1mm)的座子,这个算是常见的型号,LM2596S-5.0实现了5~40输出,5V 3A(Max)输出的性能,引脚按照SVG的顺序留出,可以直插舵机,也就是说,这块板子可以直接用来玩机械臂!这里插进来一个我之前的博客《基于Firmata协议的ROS Moveit六轴机械臂设计》,板子不一样其他的一样!博文看不懂的可以去古月学院购买一下我的课程《软硬结合带你玩转ROS机械臂》、《MoveIt玩转双臂机器人》任意一个都可以上手!板子是这样的!

哦对了,D13引脚我没有引出,这个引脚在所有的Arduino板子上面,接有一个LED灯,在上传程序或者上电、掉电的时候会出现电平的变化。这里我把D13引脚接到蜂鸣器上面,在上传程序或者上电、掉电的时候蜂鸣器会发出声音,算是一个提示音吧!

原理图十分简单,就是引脚留出!蜂鸣器那里的话,用了一个三极管来控制。当基极处于高电平的时候,三极管导通,5V过三极管、过蜂鸣器,流向GND,蜂鸣器发出声音;当基极处于低电平的时候,三极管处于截至状态造成短路,电流无法流过、蜂鸣器无法发出声音!

其他的也就没啥了,挺简单的!成本的话,Arduino Nano不超过20块钱,LM2596S-5.0不超过5块钱,30块钱以内可以搞定,传感器和杜邦线的话,去学校实验室嫖吧!


硬件聊完了,我们来聊聊软件的代码!Arduino环境啊、怎么下载程序啊,大家自行百度吧,那玩意写着简直要命,不介意的可以等几天,我这几天打算做这部分的公开课程!

Arduino语法基础的话,给大家个传送门,大家可以去参考一下!Arduino语法教程

Arduino的语法是C语言和C++都有,我是C语言用的多,毕竟简简单单的功能分得面向对象写个类,秀操作没啥意思,实用才是正道!当然,你要是做类库的话,建议你还是用C++,不然会被喷(个人观点,我可以写屎一样的代码,但是你不行。因为我要Crtl C+Ctrl V你的代码)。

我们先来看个Arduino的实例程序——闪烁的LED,代码如下。

//定义LED所在的引脚
#define LED 13

#初始化函数,程序从这里开始,setup函数的内容只执行一次
void setup()
{
    pinMode(LED,OUTPUT);    //设置LED引脚为输出模式
    digitalWrite(LED,LOW);     //设置LED引脚为低电平
}

//在执行结束setup函数后,循环执行loop函数的内容
void loop()
{
    digitalWrite(LED,HIGH);    //设置LED引脚为高电平
    delay(1000);                      //延时1000ms
    digitalWrite(LED,LOW);    //设置LED引脚为低电平
    delay(10000);                   //延时1000ms
}

这里增加了两个新的函数——pinMode和delay。

pinMode是设置引脚模式的,我们在使用引脚前,需要指定该引脚的模式(模拟输入无需指定,因为模拟输入口是指定了的)。

pinMode(uint_8 pin,uint_8 mode)    //参数pin为引脚序号,mode为模式,有OUTPUT和INPUT两个数值

delay(unsigned long ms)          //参数ms为延时的时间,单位ms

这里的逻辑如果换成C语言的话,如下,大家可以比对理解一下!

void setup()
{
    //执行初始化
}

void loop()
{
    //执行功能主体
}

int main()
{
    setup();
    while(1)
    {
        loop();
    }
    return 0;
}

呃,反正大概就这个意思吧!

大致Arduino的介绍有了,接下来就是如何来玩这些传感器,等我接下来的博客吧!

以上的概念,不仅仅是Arduino,它对于所有的单片机和嵌入式都是通用的,在学习不同的单片机,大家可以来比对一下!