Arduino uno 开发
前言
写下此文字时,是24年6月10日,我刚刚结束24年6月1,2日的中国机器人及人工智能大赛的北京市省赛和6号的模电考试,省赛是线下比赛,第一天调试不顺,第二天比赛也是匆匆忙忙,十分混乱。比完后内心感慨,思绪良久。七八号左右出成绩,幸运的是,二队省一,一队三队省二,基本上都可以进国赛。虽然十五号四级,但内心有一种强烈的欲望,想要对自己进行整理,生理上的,心理上的。我开始对我的技术栈进行整理,决定从最简单的auduino开始,这也是我写下本文的初衷,对知识进行整理。
本文大概分为四个部分,第一部分,arduino基础知识学习,第二部分,外设的使用,第三部分,电机的驱动,第四部分,实战。第三部分按理应放在第二部分,但个人认为电机驱动部分相对重要,就单列一部分了。我将遵循简约,准确的原则开始编写本文。本文并不针对初学者,需要一些C语言知识,电学知识作为前置知识,本文不介绍此部分。
本文使用了chat,加速本文的开发。
第一章 Arduino uno初识
1.1 Arduino简介
Arduino 旗下系类有很多,其中用途广泛的有四种,Arduino UNO,Arduino mega 2560,Arduino nano,Arduino uno wifi.

顺序从左到右对应。
Arduino UNO为通用型号,mega 2560引脚多,功能更强大,Arduino nano,板子小巧,质量轻,体积小,Arduino UNO wifi,多了个wifi功能,建议别用,直接用esp32.
本文主要针对的是arduino uno进行开发介绍。
中文网站如下
1.2 Arduino 引脚功能介绍

引脚分为5个区,区域如下

1区为引脚供电区,
- IORES,输入输出参考电压
- RESET,复位引脚,默认输出为1,下拉即可复位。
- 3.3V和5V是供电引脚,uno可通过USB输入电源,
此时,3.3V和5V可对外供电,也可通过3.3V和5V
对单片机进行供电,不使用usb供电
- GND,地线
- Vin,外部电源为开发板供电
2区为模拟口引脚区(analog)
ADC表示模拟到数字转换器。 ADC是用于将模拟信号
转换为数字信号的电子电路。模拟信号的这种数字表示
允许处理器(其是数字设备)测量模拟信号并在其操作中使用它。
Arduino引脚A0-A5能够读取模拟电压。在Arduino上,ADC具有10位分辨率,这意味着它可以通过1,024个数字电平表示模拟电压。 ADC将电压转换成微处理器可以理解的位。
模拟引脚只能模拟输入,不能模拟输出。
3区为ICSP插头接口区
4区为同3区,部分板子无此区域
5区为数字引脚区(digital)
Arduino Uno的引脚0-13用作数字输入/输出引脚。其中,引脚13连接到板载的LED灯;
引脚3、5、6、9、10、11具有PWM功能

以下是 Arduino Uno 的一些关键硬件规格:
• 微控制器:ATmega328P
• 工作电压:5V
• 输入电压(推荐):7-12V
• 输入电压(限制):6-20V
• 数字I/O引脚:14(其中6个提供PWM输出)
• 模拟输入引脚:6
• 每个I/O引脚的直流电流:20 mA
• 3.3V引脚的直流电流:50 mA
• 闪存:32 KB(ATmega328P),其中0.5 KB用于引导加载程序
• SRAM:2 KB(ATmega328P)
• EEPROM:1 KB(ATmega328P)
• 时钟速度:16 MHz
1.3 Arduino 供电与取电

Arduion UNO 的供电方式有四种
1. USB接口供电(5V)
2. 外部电源接口供电,直流电源电压必须为7V ~ 12V
3. Vin供电引脚供电,供电电压7~12V
4. 5V引脚5V供电。
注意通过VIN引脚供电,有一定可能性造成降压芯片烧毁,所以,如果电源12V,走外部电源接口供电,如果电源5V,走5V引脚供电。
3.3V无法通过3.3V引脚供电,会造成单片机工作异常。
大功率用电模块不要走单片机的引脚供电,一方面,供电不足,另一方面,可能造成烧毁或异常。
1.4 Arduino 引脚设置
打开Arduino的开发IDE,插上arduino,使用USB接口,另一端接入电脑,选择端口和开发板。IDE的安装和端口选择及中文语言选择自行百度,这里略过。IDE如下。

Setup(){}函数为初始化函数,会在arduino开机时执行一次。
Loop(){}函数为循环函数,主程序会在这里循环执行。
我们在这里学习数字和模拟引脚的设置。
1.4.1数字引脚
数字引脚即可以输入也可以输出。该类引脚有两种状态,高电平(1)与低电平(0),高低电平的确定由参考电压(AREF)确定。每个数字I/O口(input,输入,output,输出)可提供最高40mA的电流和5V的电压。
数字I/O口定义函数。
pinMode(pin,mode)
pinMode()函数为数字引脚定义函数,第一个参数pin,为引脚标号,即要设置那个引脚,范围为0-13,即数字引脚区。Mode有三种模式,INPUT(输入),INPUT_PULLUP(带上拉电阻输入),OUTPUT(输出)。
digitalWrite(pin,mode);
设置引脚输出状态后,可用digitalWrite函数设置引脚置为0还是1,不设置的话默认为LOW,低电平。第一个参数为引脚标号,第二个参数为状态,LOW或者HIGH;
digitalRead(pin);
digitalRead(pin)该函数为读取引脚状态,返回值为int型。结果为HIGH,LOW。
注意:在进行读取引脚操作前,需先对引脚输入模式进行定义
1.4.2模拟引脚
使用模拟引脚时,在模拟方面只能模拟输入无法模拟输出。
int b=analogRead(A0);
A0为模拟口的一个引脚,可替换为A0,A1- A5;
返回值为0-1023一个数字,模拟引脚内置10位A/D转换器,能将0~5V的电压转换为0-1023的数值,读取精度为5V/210即,每单位4.9mV.
模拟口也可作为数字引脚使用。使用如下
pinMode(A0,OUTPUT);
digitalWrite(A0,HIGH);
A0A5也可用14-19表示。号,这说明此引脚具有PWM输出的功能。如何使用这些引脚输出PWM波呢?
1.4.2PWM引脚
在数字引脚上,我们可以观察到有的数字引脚旁边带
首先,这些引脚是数字引脚区,应先设置引脚输出状态,再设置PWM波的占空比。
pinMode(3,OUTPUT);
analogWrite(3,100);
通过anglogWrite(pin,Value);设置占空比,占空比范围为0-255。PWM波不是模拟输出,arduino的PWM波输出频率较低,一千Hz以内,后续再详细介绍PWM.
1.5 Arduino串口通讯
通过USB线将板子和计算机连接,可实现串口通讯,UNO的硬件串口资源仅有一个,一个串口资源,仅支持1对1,板子与计算机通讯时不要使用其他模块占用此通道,否则可能造成串口传输乱码,或者下载失败。
本小节仅讨论计算机与板子的串口操作,串口的其他操作后续内容后面章节补充
1.5.1串口初始化
使用 Serial.begin(baudRate) 函数来初始化串口通信,参数 baudRate 是波特率(数据传输速率),常见值是 9600, 115200 。初始化内容一般放在setup函数里。如下。
1 | void setup() { |
1.5.2发送数据
• Serial.print(data):发送数据,但不换行。
• Serial.println(data):发送数据并换行。
可用串口接收器接受。
1.5.3接受数据
• Serial.available():返回串口缓冲区中的字节数。
• Serial.read():读取串口缓冲区中的一个字节,返回值为 -1 表示没有数据可读。
• Serial.readString():读取串口缓冲区中的字符串,直到超时(需要 Serial.setTimeout() 配合)。
• Serial.readStringUntil(char terminator):读取串口缓冲区中的字符串,直到遇到终止符(如换行符)。
Serial.setTimeout(500); // 设置超时为500毫秒
1.5.4串口综合
1 | void setup() { |
操作时,要注意程序运行在uno上,主体是单片机而不是计算机。
1.6 Arduino AREF与IOREF的使用
部分arduino的板子的IOREF引脚会该成5V供电引脚 ,查阅原理图,IOREF被锁死。
AREF
在mega328中,有六个模拟输入引脚,这些模拟输入引脚简单的说测量的是输入的电压值然后用 0~ 1023来表示电压的大小,当然,这个值有一个范围,通常来说是0~5V,查阅UNO的规格书可以知道UNO是具有10位的ADC。
10位ADC以为着什么呢?以为着它能将0 ~ 5 V的电压分成1024份(2^10),算出来即为4.882mV的测量精度,举个例子就是0V的时候测量结果为0,5V为1023,3V约为615,但是有一种情况就是你输入的电压最大是3.3V,测量出来的最大值也就是675,这个时候你或许会想到map,确实这不失为一个好办法。
但是AREF提供了另一个更好的解决办法,即在AREF接入一个最大模拟输入量作为参考值(比如上面所说的3V3),这样不仅能直接读到1023,更为重要的是精度提高,用3V3作为AREF的时候精度是多少?? 3.3/1023 ==3.223mV,测量精度提高了。
使用外部电源注意事项:
- 确保外部参考电压在 0 到 Vcc 之间,对于 5V Arduino 板,电压应在 0 到 5V 之间。
- 外部参考电压不应超过 Vcc,否则可能会损坏 Arduino 板。
- 使用一个稳定的电压源作为外部参考电压。如果外部参考电压不稳定,ADC 的精度会受到影响。
- 如果已经连接了外部参考电压,不要在代码中使用 analogReference(DEFAULT); 或 analogReference(INTERNAL);。这样可能会引起冲突和不正确的读数。
1 | void setup() { |
1.7 Arduino 上拉电阻
上拉电阻是什么?在I/O口模式设置中,输入模式有两种,INPUT和INPUT_PULLUP,这两者有什么区别吗?
本节将解答上面的问题。
输入模式的引脚相当于电压表的探头,如果测得电压比基准电压高,则为1,比基准电压低为0;
首先我们要了解一个概念,引脚悬空,即当某个引脚处于输入模式时,而该引脚什么也没有接的情况称之为引脚悬空。灵魂画手上线,如下图。

引脚悬空会有什么问题呢?会造成读取的引脚状态不对,此时是高电平还是低电平呢?无法确定。
1 | void setup() { |
打印结果如下,特别是将手指捏在悬空引脚尤为明显。

而将引脚模式设置为输入上拉后,输出不飘了,为1.
pinMode(2,INPUT_PULLUP);
Arduino内部的上拉电阻为20K欧,一般上拉电阻为10K欧

此时引脚不接东西时,测的电压为VCC,即高电平,上拉电阻阻值较大,能够限流,防止大电流灌入引脚。当引脚接GND时,此时pin测的电压为GND的电压,为低电平。
不使用单片机的内置上拉电阻,自行在输入引脚外接一个阻值大小合适电阻是相同的效果。上拉电阻稳定输入引脚状态,克服了引脚悬空带来的引脚测量值不准的问题。
1.8 Arduino 定时器资源
Arduino Uno 基于 ATmega328P 微控制器,该微控制器包含三个硬件定时器资源:Timer0、Timer1 和 Timer2。每个定时器有不同的特性和用途,具体如下:
Timer0
类型:8位定时器
用途:主要用于 Arduino 内部计时功能,例如 millis() 和 delay() 函数。它可以生成中断,用于更新系统时间。尽量不要更改这个定时器。
PWM 引脚:5和 6(对应 Arduino 引脚)
Timer1
类型:16位定时器
用途:由于其较高的分辨率,Timer1 常用于需要精确时间控制的任务,例如 Servo 库。它也可以生成高精度的 PWM 信号。
PWM 引脚:9 和 10(对应 Arduino 引脚)
Timer2
类型:8位定时器
用途:通常用于生成较低频率的 PWM 信号或执行其他定时任务。其频率设置比较灵活,适用于音频生成等应用。
PWM 引脚:3 和 11(对应 Arduino 引脚)
中断频率(Hz)=(Arduino时钟速度16MHz)/(预分频器*(比较匹配寄存器+ 1))
WGM02、WGM01、WGM00:这三个位用于选择相位校正(phase correct)模式、快速(Fast)模式或CTC模式。
相位校正模式:计数器在达到最大值(255)后开始减小,形成一个三角形波形。
快速模式:计数器达到最大值后归零,形成锯齿波形。
CTC模式:计数器在达到OCR0A(比较寄存器A)后归零,形成可变的锯齿波形。
CS02、CS01、CS00:用于控制预分频系数,即将系统时钟分频得到计时器时钟。
分频系数1:无分频。
分频系数8:系统时钟除以8。
比较寄存器A、B:除了设置定时器外,还有两个寄存器用于控制PWM比较值,从而控制占空比。
COM0A1、COM0A0、COM0B1、COM0B0:用于设置PWM输出引脚的电平。
COM0A1/COM0B1、COM0A0/COM0B0为1、1时,当OCR比较寄存器小于计数器值时引脚输出0,大于计数器值时输出1。
COM0A1/COM0B1、COM0A0/COM0B0为1、0时,当OCR比较寄存器小于计数器值时引脚输出1,大于计数器值时输出0。
CTC模式下,COM0A1/COM0B1、COM0A0/COM0B0为0、1时,每当计数器溢出,引脚输出取反。
1 | int toggle0, toggle1, toggle2; |
1.9 其他
板间通讯。
如果想对板子进行更细致的操作,建议更换STM32,或者其他单片机。
第二章 常用模块的使用
2.1 红外对光管的检测

应用场合:
1.电度表脉冲数据采样
2.传真机碎纸机纸张检测
3.障碍检测
4.黑白线检测
DO 为数字输出口
AO为模拟输出口
可5V或3.3V供电。
中间的螺旋可以调节探测的距离。
当红外接收器接受到信号时,开光指示灯亮起。DO为低电平,检测这个端口的值,即可知道探测状态。
测试
5V供电,DO引脚接3号,AO接A0
1 | void setup() { |
当开关灯亮时,一个模拟值,一个数字值。串口显示器显示如下

2.2光敏/热敏传感器的检测

这里以光敏传感器为例,热敏检查代码相同。
应用场景
1. 暗室监测
2. 熄屏亮灯
此类传感器与红外检查方法基本类似,将检测的模拟值,根据
实际情况转化为实际量,温度,光照等。
接线:DO接数字引脚2,AO接模拟引脚A0。
原理,这两个相当于电阻,电阻值随环境变化而变化。
1 | void setup() { |
读到的模拟量需根据光敏电阻的参数转化为具体的亮度。

2.3超声波传感器

应用场合:
1.机器人避障和导航
2.距离测量
3.接近测量
4.智能垃圾桶
可3.3V或者5V输入
HC-SR04超声波测距模块可提供
2cm-60cm的非接触式距离感测功能,
测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。
超声波测距模块——触发信号后发射超声波,当超声波投射到物体而反射回来时,模块输出——回响信号,以触发信号和回响信号间的时间差,来判定物体的距离。
使用
首先要安装NewPing 库。
注意,该库会调用定时器2资源。
网上的很多关于超声波模块的教程,不使用定时器,并且使用delay(),会挤占主进程。
1 |
|
经测试,结果如下
注意,当靠的太近时,距离不准,会增加。本代码对数据只进行求平均处理,可用其他方法进行滤波。减小误差。
2.4 4PIN-OLED 小屏幕的驱动

应用场景:
1. 显示输出
2. 多级菜单
3. 表情显示
可3.3V或者5V输入,一般使用有多重库函数,
这里使用u8g2库
SCL接A5,SDA接A4,示例如下
使用:
首先要安装u8g2库,该库可以驱动4pin,0.96寸OLED小屏幕
1 |
|
屏幕显示还有ISP协议的,这种一般为7PIN,这里只介绍相对简单,接线少,使用I2C协议的4pin,0.96寸OLED屏幕。
2.5温湿度传感器

使用DHT11,温湿度传感器还有其他类型DHT22等
应用场景
1. 温湿度检测
2. 小闹钟配件

引脚正对着自己,从左至右。

使用,安装库Adafruit Unified Sensor及DHT-sensor-library两个库
1 | // 需要以下 Arduino 库: |
2.6HW504摇杆的使用

引脚说明
GND 地
5V 电源5V
SW 按键(数字量)
VRX X轴 (模拟量)
VRY Y轴 (模拟量)
1.输入电压范围:直流3.3V 至 5V。
2.输出信号:模块特设二路模拟输出和一路数字输出接口,输出值分别对应(X,Y)双轴偏移量,其类型为模拟量;按键表示用户是否在Z轴上按下,其类型为数字开关量
VRx,VRy (X、Y轴)为模拟输入信号,连接到模拟IO口A0A7。右,上~下。中间值为512。
VRx,VRy 的值:从 0 ~ 1023 分别代表 左
SW (Z轴)是数字输入信号,连接到数字端口,并启用上拉电阻。
SW 的值:1代表未按下,0代表按下。
实验这里VRx接A0,VRy接A1,SW接D6
1 | int value = 0; |

2.7WIFI模块的使用
这里我们使用的是4Pin的ESP8266模块,这里只做简单的介绍,具体可后面学习ESP32.ESP8266模块内置TCP/IP协议,能够实现串口与WIFI之间的转换。该模块有三种工作WIFI模式,STA,AP,STA+AP.
STA,客户端模式,可连接其他WIFI,手机等设施实现对设备的远程连接。
AP,接入点模式,模块作为WIFi热点。
STA+AP,混合模式。
1 |
|
测试,在串口里输入AT,会返回OK;




2.8 其他
Arduino uno的模块还有蓝牙模块等,不过感觉有些鸡肋,使用uno的板子搭配这些模块,不如直接买esp32.所以一些无线通讯的模块就不介绍了。
Arduino的外设很丰富,这里就不多介绍了。
第三章 电机的驱动
3.1PWM波的认识
PWM(Pulse Width Modulation,脉宽调制)是一种用于模拟信号和功率控制的技术,通过改变脉冲的宽度来调节信号的平均电压或功率.
PWM 信号在一定周期内以高电平和低电平交替出现,通过改变高电平的持续时间(占空比)来实现对输出电压或功率的调节。
应用场景有电机控制,LED调光,电源转换和通信等。

PWM的重要参数有,
- 频率(Frequency):频率的选择取决于具体应用。例如,电机控制通常使用几千赫兹的频率,而 LED 调光可能使用几百赫兹到几千赫兹。
- 占空比(Duty Cycle):占空比是指高电平时间相对于一个周期的比例,通常用百分比表示
- 分辨率(Resolution):分辨率是指占空比可调节的最小步进,通常与控制器的位数有关。例如,8 位分辨率的 PWM 控制器可以将占空比调整到 256 个不同的级别。
- 电压幅度(Voltage Amplitude):PWM 信号的高电平和低电平的电压值。高电平通常是电源电压(如 5V 或 3.3V),低电平通常是 0V。
一般而言,要特别注意频率,频率过低,在驱动电机时可能出现异常,电机哮鸣。一般电机是需要较高频率的PWM信号控制.
单片机的PWM一般作为信号使用,驱动一些小功率LED时,可作为电源使用。
3.2 PWM波驱动小功率直流电机
我们在前面学习到,UNO的数字引脚上有几个特定引脚可以输出PWM波,分别为3,5,6,9,10,11.但是这种方式 PWM 信号的频率是固定的默认值,引脚上的 PWM 信号频率约为490 Hz,在 Uno板上,引脚5和6的频率约为980Hz。
1 |
|
通过这种方法产生的PWM波频率过低,在驱动电机时可能出现异常。因此需要输出更高频率的PWM信号。
此时,小功率的直流电机一端接GND,一端接3号引脚也是可以驱动的,通过调节占空比即可调节速率。
为了使PWM的发生不占用主进程,这里使用定时器来操作。
1 | /** |
示波器测量频率为62.5KHZ,改变下面的124,改变占空比,占空比0-255。
analogWrite(6,124);
3.3 L298N的使用与双路电机驱动

供电方式:
- 7-12V电源走VCC供电,电源上的跳线帽连接,5v的位置不用接电源,该位置可输出一个5v,可用于给单片机供电。
- 当输入电压大于12v时,需要拔掉电源旁的跳线帽,5V端需要接入5v的电压,GND还是接GND
- 接入5V电源, L298N的12V和5V都接5V供电。
注意:GND不但要接驱动电源的GND,一定要从这里再引出一根GND和单片机或者系统的GND相连,使电压有参考电平
控制引脚
IN1 & IN2 电机驱动器A的输入引脚,控制电机A转动及旋转角度
IN1输入高电平HIGH,IN2输入低电平LOW,对应电机A正转
IN1输入低电平LOW,IN2输入高电平HIGH,对应电机A反转
IN1、IN2同时输入高电平HIGH或低电平LOW,对应电机A停止转动
调速就是改变IN1、IN2高电平的占空比(需插上ENA处跳帽)IN3 & IN4 电机驱动器B的输入引脚,控制电机B转动及旋转角度
IN3输入高电平HIGH,IN4输入低电平LOW,对应电机B正转
IN3输入低电平LOW,IN4输入高电平HIGH,对应电机B反转
IN3、IN4同时输入高电平HIGH或低电平LOW,对应电机B停止转动
调速就是改变IN3、IN4高电平的占空比(需插上ENB处跳帽)

控制有两种方式,以一边电机为例:
1. ENA,引脚通过跳帽线与+5V连接,IN1悬空或接GND,IN2输入PWM信号。
2. ENA拔掉跳帽线,输入PWM信号,IN1接1,IN2接0。改变IN1与IN2的值就可以停止或正反转。
3.4舵机的驱动
普通舵机有3根线:GND(黑)、VCC(红)、Signal(黄),一般情况下,建议为舵机单独供电,此处实验为了图方便,用arduino为舵机供电。
1 | /* |
3.5 其他
还有无刷电机,步进电机,arduino驱动这些电机设备时,一般不直接驱动,中间都会连接一个驱动模块,上文的L298N就是一种驱动模块。
第四章 成品制作
4.1可以制作哪些?如何制作?
个人DIY时,除了学习单片机外,还需要学习PCB焊接和3D打印的一些知识,并且熟悉一些常见的DIY材料,丙烯颜料,环氧树脂等,以及钳子,等常见工具的使用。当然最最最重要的是热爱。
基于UNO,我们可以做出很多有意思的作 品,小时钟,个性灯等,在开源社区有很多有意思的作品,可以自行搜索。