工程学导论Tech Tutorial
本博客为 ENGR1000J-S2-24SU Tech-TA 讲义的中文版本
希望帮助大部分更加熟悉中文的同学更好理解这些内容
也希望能够帮助非本课程的同学们上手单片机的基础使用
注: 中文版的内容和英文讲义完全一样
Arduino + 超声波传感器
模块原理
- 触发位引脚(Trig)获得约10微秒的高电平,发射超声波,同时接收位引脚(Echo)也变为高电平
- 当超声波模块接收到回声,接收位引脚重新变回低电平
- 计算接收位引脚高电平的持续时间,结合声速,计算出距离
接线
(使用tinkercad绘制)
- vcc接5V供电
- Gnd接Arduino板上的GND接地
- Trig和Echo分别接两个通用输入输出引脚即可,这里选择9和10
代码编写
完整代码
// 定义引脚
const int trigPin = 9;
const int echoPin = 10;
// 定义时间变量
long duration;
int distance;
// 初始化函数
void setup() {
// 初始化串口通信
Serial.begin(9600);
// 设置引脚模式
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
// 主循环函数
void loop() {
// 调用测距函数
distance = measureDistance();
// 输出测得的距离
Serial.println("Distance: " + String(distance) + " cm");
// 延迟1秒
delay(1000);
}
// 测距函数
int measureDistance() {
// 清空trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// 发送10微秒的脉冲到trigPin
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// 读取echoPin,返回脉冲宽度(微秒)
duration = pulseIn(echoPin, HIGH);
// 计算距离(单位:厘米)
int distance = duration * 0.034 / 2;
return distance;
}
函数理解
pinMode(pin, mode)
- 功能: 设置指定引脚的工作模式。
- 参数:
pin
: 要设置模式的引脚编号。mode
: 引脚模式,可以是INPUT
(输入模式)或OUTPUT
(输出模式)。
- 示例:
pinMode(13, OUTPUT); // 设置13号引脚为输出模式
Serial.println(data)
- 功能: 向串行监视器发送数据,并在发送的数据末尾添加换行符。
- 参数:
data
: 要发送的字符串或数值数据。
- 示例:
Serial.begin(9600); // 初始化串行通信,波特率为9600 Serial.println("Hello, Arduino!"); // 向串行监视器发送字符串
digitalWrite(pin, value)
- 功能: 向指定引脚输出高电平(HIGH)或低电平(LOW)。
- 参数:
pin
: 要输出信号的引脚编号。value
: 输出值,可以是HIGH
(高电平)或LOW
(低电平)。
- 示例:
digitalWrite(13, HIGH); // 将13号引脚设置为高电平
delay(ms)
- 功能: 暂停程序执行指定的毫秒数。
- 参数:
ms
: 暂停的时间,单位为毫秒。
- 示例:
delay(1000); // 暂停程序执行1秒(1000毫秒)
pulseIn(pin, value)
- 功能: 测量指定引脚上一个脉冲的持续时间。
- 参数:
pin
: 要测量脉冲的引脚编号。value
: 脉冲的类型,可以是HIGH
(高电平脉冲)或LOW
(低电平脉冲)。
- 返回值: 脉冲的持续时间,单位为微秒。
- 示例:
unsigned long duration; duration = pulseIn(7, HIGH); // 测量7号引脚上高电平脉冲的持续时间
代码说明
定义引脚:
const int trigPin = 9; const int echoPin = 10;
trigPin
连接到HC-SR04传感器的触发引脚(Trig),echoPin
连接到回声引脚(Echo)这里的 9 和 10 是和实际的接线对应起来的
就是给引脚数字起名字,这两行代码也可以用宏定义实现,即:
#define TRIG_PIN 9 #define ECHO_PIN 10
初始化函数:
void setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); }
设置串口通信速率为9600波特,并设置引脚模式
这里波特率只要和串口监视器的波特率一致就可以,建议9600
主循环函数:
void loop() { distance = measureDistance(); Serial.println("Distance: " + String(distance) + " cm"); delay(1000); }
在主循环中调用
measureDistance
函数测量距离,并将结果通过串口输出,每次测量后延迟1秒测距函数:
int measureDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); int distance = duration * 0.034 / 2; return distance; }
该函数首先清空
trigPin
,然后发送10微秒的脉冲信号,读取从echoPin
接收到的回声信号的持续时间,并计算出距离pulseIn
函数用于测量某个引脚上的脉冲宽度(高电平或低电平的持续时间)
运行
点击上传按钮
打开串行监视器
传感器读取到的数据实时显示在窗口中
Arduino + L298N + DC Motor
直流电机简介
基本参数
额定电压:额定电压(Rated Voltage)是指直流电机在最佳性能下运行时所需的电压。
转速:转速(Speed),通常用转每分钟(RPM, Revolutions Per Minute)表示。转速与扭矩之间存在反比关系,在电机的应用中需要平衡两者以满足具体的使用需求。
对于VG100-S2第一阶段的项目,电机额定电压的选择要求小于等于12V,转速可以选择较低转速以提高扭矩。
使用原理
在直流电机的两个电极分别接高电压和低电压,不同的电压差形成不同的转速。
L298N电机驱动板
接口介绍
- OUT1, OUT2, OUT3, OUT4: 电流输出,连接直流电机
- 12V(VS),和 GND: 用于电流输入(不一定要12V的电源。5V~35V都OK)
- 5V(VSS),可用于输出5V电压
- IN1, IN2, IN3, IN4: 信号输入,连接Arduino
- EN1,EN2: A侧输入和B侧输出的使能,可用于控制电机转速
可以提供最大约2A的电流
使用方法1
IN1, IN2 控制电机方向和电机速度
需要两个模拟输出引脚
实现思路简单一些
接线
Arduino与L298N驱动模块的连接
IN1
: Arduino的D5引脚连接到L298N的IN1引脚。IN2
: Arduino的D3引脚连接到L298N的IN2引脚。- 不要拔掉ENA的跳线帽
电源连接
- 驱动模块电源输入:
- 将L298N的
VCC
引脚连接到电池 - 将L298N的
GND
引脚连接到电源的负极(地)。
- 将L298N的
- Arduino电源:
- 可以通过USB供电,或使用外部电源供电。
- 驱动模块电源输入:
电机连接
- 将直流电机的两根线连接到L298N的
OUT1
和OUT2
引脚。确保电机连接正确,以便IN1和IN2控制电机的正反转。
- 将直流电机的两根线连接到L298N的
代码编写
int IN1 = 5; // D5引脚连接到驱动模块的IN1
int IN2 = 3; // D3引脚连接到驱动模块的IN2
void motor(int speed1) { // speed1 驱动电机的速度,值范围-255到255,正值正转,负值反转
int s1, s2; // 定义s1和s2变量,用于表示电机正反转状态
if(speed1 > 0) {
s1 = IN1; // 正转时,s1表示IN1
s2 = IN2; // 正转时,s2表示IN2
} else {
s1 = IN2; // 反转时,s1表示IN2
s2 = IN1; // 反转时,s2表示IN1
speed1 = -speed1; // 将speed1取绝对值,使其成为正数
}
digitalWrite(s1, LOW); // 给s1所代表的引脚写入低电平,确定电机的负极
analogWrite(s2, speed1); // 给s2所代表的引脚写入模拟信号,根据speed1的绝对值控制电机速度
}
void setup() {
pinMode(IN1, OUTPUT); // 设置D5为输出引脚
pinMode(IN2, OUTPUT); // 设置D3为输出引脚
Serial.begin(9600);
}
void loop() {
motor(50); // 调用motor函数,设置电机速度为50,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor(100); // 调用motor函数,设置电机速度为100,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor(255); // 调用motor函数,设置电机速度为255(最大速度),电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor(-100); // 调用motor函数,设置电机速度为-100,电机反转
delay(1000); // 等待1秒钟,使电机保持当前速度
}
函数介绍
digitalWrite
- 功能:
digitalWrite
用于将数字引脚设置为高电平(HIGH)或低电平(LOW)。 - 使用方法:
digitalWrite(pin, value);
pin
: 要操作的引脚编号(如 D5)。value
:HIGH
或LOW
,分别表示高电平和低电平。
- 引脚要求: 可以用于任何所有引脚。
示例:
digitalWrite(5, HIGH); // 将D5引脚设置为高电平
digitalWrite(3, LOW); // 将D3引脚设置为低电平
analogWrite
- 功能:
analogWrite
用于向PWM引脚输出模拟信号,范围是0到255,通过PWM技术模拟模拟信号。 - 使用方法:
analogWrite(pin, value);
pin
: 要操作的PWM引脚编号(如 D6)。value
: 0到255之间的值,0表示0%占空比(低电平),255表示100%占空比(高电平)。
- 引脚要求: 只能用于支持PWM的引脚。
示例:
analogWrite(6, 128); // 在D6引脚输出50%占空比的PWM信号
使用方法2
IN1, IN2 控制电机方向
ENA 控制电机速度
需要两个数字输出引脚+一个模拟输出引脚
节约模拟引脚,代码优雅一点,接线稍麻烦一点
分别控制正反转和速度
接线
Arduino与L298N驱动模块的连接
IN1
: Arduino的D5引脚连接到L298N的IN1引脚。IN2
: Arduino的D3引脚连接到L298N的IN2引脚。EN1
: Arduino的D6引脚连接到L298N的EN1引脚。
电源连接
- 驱动模块电源输入:
- 将L298N的
VCC
引脚连接到电池 - 将L298N的
GND
引脚连接到电源的负极(地)。
- 将L298N的
- Arduino电源:
- 可以通过USB供电,或使用外部电源供电。
- 驱动模块电源输入:
电机连接
- 将直流电机的两根线连接到L298N的
OUT1
和OUT2
引脚。确保电机连接正确,以便IN1和IN2控制电机的正反转。
- 将直流电机的两根线连接到L298N的
代码编写
C style
int IN1 = 8; // D8引脚连接到驱动模块的IN1
int IN2 = 7; // D7引脚连接到驱动模块的IN2
int EN1 = 6; // D6引脚连接到驱动模块的EN1,用于控制电机速度
void motor(int speed1) { // speed1 驱动电机的速度,值范围-255到255,正值正转,负值反转
if(speed1 > 0) {
digitalWrite(IN1, HIGH); // IN1高电平,电机正转
digitalWrite(IN2, LOW); // IN2低电平
} else {
digitalWrite(IN1, LOW); // IN1低电平
digitalWrite(IN2, HIGH); // IN2高电平,电机反转
speed1 = -speed1; // 将speed1取绝对值,使其成为正数
}
analogWrite(EN1, speed1); // 使用PWM信号控制电机速度
}
void setup() {
pinMode(IN1, OUTPUT); // 设置D8为输出引脚
pinMode(IN2, OUTPUT); // 设置D7为输出引脚
pinMode(EN1, OUTPUT); // 设置D6为输出引脚
Serial.begin(9600); // 初始化串口通信,设置波特率为9600
}
void loop() {
motor(50); // 调用motor函数,设置电机速度为50,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor(100); // 调用motor函数,设置电机速度为100,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor(255); // 调用motor函数,设置电机速度为255,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor(-100); // 调用motor函数,设置电机速度为-100,电机反转
delay(1000); // 等待1秒钟,使电机保持当前速度
}
C++ style
class Motor {
private:
int IN1; // 电机驱动模块的IN1引脚
int IN2; // 电机驱动模块的IN2引脚
int EN1; // 电机驱动模块的EN1引脚,用于控制电机速度
public:
Motor(int in1, int in2, int en1) { // 构造函数,用于初始化引脚
IN1 = in1;
IN2 = in2;
EN1 = en1;
pinMode(IN1, OUTPUT); // 设置IN1为输出引脚
pinMode(IN2, OUTPUT); // 设置IN2为输出引脚
pinMode(EN1, OUTPUT); // 设置EN1为输出引脚
}
void setSpeed(int speed) { // 设置电机速度的方法,speed值范围为-255到255
if (speed > 0) {
digitalWrite(IN1, HIGH); // IN1高电平,电机正转
digitalWrite(IN2, LOW); // IN2低电平
} else {
digitalWrite(IN1, LOW); // IN1低电平
digitalWrite(IN2, HIGH); // IN2高电平,电机反转
speed = -speed; // 将speed取绝对值,使其成为正数
}
analogWrite(EN1, speed); // 使用PWM信号控制电机速度
}
};
Motor motor1(8, 7, 6); // 创建Motor类的实例,指定IN1, IN2, EN1引脚
void setup() {
Serial.begin(9600); // 初始化串口通信,设置波特率为9600
}
void loop() {
motor1.setSpeed(50); // 设置电机速度为50,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor1.setSpeed(100); // 设置电机速度为100,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor1.setSpeed(255); // 设置电机速度为255,电机正转
delay(1000); // 等待1秒钟,使电机保持当前速度
motor1.setSpeed(-100); // 设置电机速度为-100,电机反转
delay(1000); // 等待1秒钟,使电机保持当前速度
}
参考资料
- Arduino L298N Guide | https://nju-robot-club.gitbook.io/arduino/week4/l298n
- L298N Motor Driver Tutorial | https://lastminuteengineers.com/l298n-dc-stepper-driver-arduino-tutorial/
材料购买建议
lab上发放的材料仅以教学为目的,搭建项目的材料是大家自由购买的
硬件的选型也是项目制作的重要部分,适用性、易用性、价格成本都是大家需要考虑的因素
以下是我们给大家的一些建议
结构材料
已在5.25的announcement里提及
电子模块
发放材料中推荐使用的
- Arduino UNO
- 作为主控单片机
- 对于第一阶段的项目来说足够且适合
- L298N
- 不错的电机驱动板选项
- 还有其它品种的电机驱动板,可以按需选择
- 格式 2S 800mah 电池
- 这是一块品质很不错的电池
- 但参数不一定是最合适的
- 超声波传感器
- 距离信息也是不错的判断标准
需购买或建议购买的
- 电池
- 电压建议 3S
- 容量自行选择。越大->续航时间越长、充放电周期长、重量较大、价格较高
- 放电倍率(c数)不需要追求太高
- 传感器
- 市面上有很多品种的传感器,分别用来检测不同的环境信息
- 请根据Phase 1的项目任务选择合适的传感器
- 可以考虑多传感器的融合检测
- 直流电机
- 也许你需要新的专门用于小车的电机
- 注意电机和支架、联轴器、车轮的搭配
- 电机还有其它种类,可自行选择
- 其它机电模块
- 多了解,多参考其它方案。有很多好用的模块
关于报销
- 有平均每人200RMB的报销额度。(即每队报销额度1000~1200)
- 一定要开好发票,发票信息见
上海交通大学开票信息.docx
。其中纳税人名称和纳税人识别号是最重要的。单位注意选择“企业”而非“个人” - 商家不应以任何理由拒绝开票。请大家维护自己的消费者权益
工程学导论Tech Tutorial