Arduino Mega2560 基础模块小综合

本文最后更新于:2021年2月26日 晚上

摘要
以前做过个课题,整个项目是建立在 arduino 上的,但是程序比较乱,现在正好趁这个机会完善一下。

[TOC]

设计目标

通过按钮控制两组十字滑杆上下左右运动,并通过显示器显示实时坐标。

难点

  • LED 显示
  • 总共五个按钮,四个为方向键,另一个切换十字滑杆
  • 步进电机控制

设计方案

– 零部件选型

本装置搭建所需的材料及零部件的选型中十字丝杠滑台电机电机驱动器Arduino 控制板是重点。

十字丝杠滑台的选择主要考虑尺寸问题。为了以后自己搭 3D打印机做准备(已经买了赤兔主板,在研究),就买了400mm×400mm规格的滚珠丝杆滑台。

电机选型主要考虑合适的扭矩,电机驱动器则需要与电机配套,最后选用了 42步进电机DM542 电机驱动器

Arduino 控制板有各种配置,选型时主要考虑针脚数量需求。由于装置预计大约需要15个针脚,超出 Arduino nano、Arduino uno 的针脚数,最终选择了拥有更多针脚的 Arduino Mega 2560 控制板(省事)。

– 硬件连接设计

image-20210226182420646

按钮控制开关、超声波传感器、LCD液晶屏与Arduino Mega2560单片机的线路连接如图:

image-20210226182536114

电机驱动器与 Arduino Mega2560 单片机的线路连接如图:

image-20210226182702178

– 软件设计

软件设计主要是逻辑问题,关于代码,这里展示电机控制部分关键代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//以左侧x方向电机为例,程序如下:
if (Choice_LorR == 0) //Choice_LorR为0时控制左边电机
{
//向左按钮按下
else if (State_B_L == HIGH)
{
Serial.println("Left left");
// tone(EM_Pulse_common, 8000);
digitalWrite(EM_enable_M2, HIGH);
digitalWrite(EM_2_4_dirX_common, HIGH);
delay(50);
}

//向右按钮按下
else if (State_B_R == HIGH)
{
Serial.println("Left right");
// tone(EM_Pulse_common,8000);
digitalWrite(EM_enable_M2, HIGH);
digitalWrite(EM_2_4_dirX_common, LOW);
delay(50);
}
}

程序完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#include <SR04.h>  //调用SR04头文件,用于超声波测量
#include <Wire.h> //用于液晶显示
#include <LiquidCrystal_I2C.h> //用于液晶显示

//定义Arduino板与4个电机驱动器的连接
#define EM_Pulse_common 7 // 定义电机控制脉冲信号PIN脚,4路电机脉冲信号共用同一个PIN脚
#define EM_1_3_dirY_common 3 //定义两个上下移动电机的上下移动方向控制信号,两路电机方向信号共用一个
PIN脚。电机1为左方上下移动电机,电机3为右方上下移动电机
#define EM_2_4_dirX_common 5 //定义两个左右移动电机的左右移动方向控制信号,两路电机方向信号共用一个PIN脚。电机2为左方左右移动电机,电机4为右方左右移动电机
#define EM_enable_M1 4 // 1号电机enable脚定义
#define EM_enable_M2 6 // 2号电机enable脚定义
#define EM_enable_M3 13 // 3号电机enable脚定义
#define EM_enable_M4 12 // 4号电机enable脚定义

//定义Arduino板操作按钮总开关的连接
#define B_General 2 //左方丝杠十字滑台 vs 右方丝杠十字滑台

//定义Arduino板与上、下、左、右四方向按钮的连接
#define B_U 11 // 向上移动按钮对应的Arduino PIN脚
#define B_D 10 // 向下移动按钮对应的Arduino PIN脚
#define B_L 9 // 向左移动按钮对应的Arduino PIN脚
#define B_R 8 // 向右移动按钮对应的Arduino PIN脚

//以下定义全局变量并初始化
//上下左右按钮状态变量定义
int State_B_U = 0; // 向 上 移动 按钮状态变量定义
int State_B_D = 0; // 向 下 移动 按钮状态变量定义
int State_B_L = 0; // 向 左 移动 按钮状态变量定义
int State_B_R = 0; // 向 右 移动 按钮状态变量定义
bool Choice_LorR = 0; // 总控制按钮状态变量声明

//超声波传感器设置,UV1/2/3/4分别对应左侧Y/X、右侧Y/X位置
const int UV1_TrigPin = A1;
const int UV1_EchoPin = A2;
const int UV2_TrigPin = A3;
const int UV2_EchoPin = A4;
const int UV3_TrigPin = A5;
const int UV3_EchoPin = A6;
const int UV4_TrigPin = A7;
const int UV4_EchoPin = A8;

//定义超声波传感器类变量,分别对应各传感器
// 定义ultrasonic1/2/3/4为4个SR04类变量,分别对应4个超声波传感器,SR04类变量可以调用函数获取超声波位置数据
SR04 ultrasonic1 = SR04(UV1_TrigPin, UV1_EchoPin);
SR04 ultrasonic2 = SR04(UV2_TrigPin, UV2_EchoPin);
SR04 ultrasonic3 = SR04(UV3_TrigPin, UV3_EchoPin);
SR04 ultrasonic4 = SR04(UV4_TrigPin, UV4_EchoPin);

//液晶屏设置
LiquidCrystal_I2C lcd(0x27, 20, 4); // 液晶显示地址设置 set the LCD address to 0x27 for a 16 chars and 2 line display

void setup() {
Serial.begin(9600);

pinMode(B_General, INPUT); // 控制左方滑台电机还是右侧滑台电机
pinMode(B_U, INPUT); // 向 上 移动
pinMode(B_D, INPUT); // 向 下 移动
pinMode(B_L, INPUT); // 向 左 移动
pinMode(B_R, INPUT); // 向 右 移动

//Arduino板输出信号定义
pinMode(EM_1_3_dirY_common, OUTPUT);
pinMode(EM_2_4_dirX_common, OUTPUT);
pinMode(EM_enable_M1, OUTPUT);
pinMode(EM_enable_M2, OUTPUT);
pinMode(EM_enable_M3, OUTPUT);
pinMode(EM_enable_M4, OUTPUT);
pinMode(EM_Pulse_common, OUTPUT);

//使用起动时候电机不会工作
digitalWrite(EM_enable_M1, LOW);
digitalWrite(EM_enable_M2, LOW);
digitalWrite(EM_enable_M3, LOW);
digitalWrite(EM_enable_M4, LOW);

//LCD初始化
lcd.init(); // initialize the lcd
lcd.backlight();
}

void loop() {
tone(EM_Pulse_common, 8000); //电机驱动器控制脉冲设置

if (digitalRead(B_General) == HIGH) //当按下开关时将切换控制方向,当Choice_LorR=0时控制左侧滑台电机,当Choice_LorR=1时控制右侧滑台电机
{
Serial.println("in loop");
Choice_LorR = !(Choice_LorR);
Serial.println(Choice_LorR);
delay(500);
}

//读取方向按钮信号
State_B_U = digitalRead(B_U);
State_B_D = digitalRead(B_D);
State_B_L = digitalRead(B_L);
State_B_R = digitalRead(B_R);

//左侧滑台电机控制
if (Choice_LorR == 0) //Choice_LorR为0时控制左边电机
{
//向上按钮按下
if (State_B_U == HIGH)
{
Serial.println("Left UP");
digitalWrite(EM_enable_M1, HIGH);
Serial.println("after enable");
digitalWrite(EM_1_3_dirY_common, HIGH);
delay(50);
}

//向下按钮按下
else if (State_B_D == HIGH)
{
Serial.println("Left down");
//tone(EM_Pulse_common,8000);
digitalWrite(EM_enable_M1, HIGH);
digitalWrite(EM_1_3_dirY_common, LOW);
delay(50);
}

//向左按钮按下
else if (State_B_L == HIGH)
{
Serial.println("Left left");
// tone(EM_Pulse_common, 8000);
digitalWrite(EM_enable_M2, HIGH);
digitalWrite(EM_2_4_dirX_common, HIGH);
delay(50);
}

//向右按钮按下
else if (State_B_R == HIGH)
{
Serial.println("Left right");
// tone(EM_Pulse_common,8000);
digitalWrite(EM_enable_M2, HIGH);
digitalWrite(EM_2_4_dirX_common, LOW);
delay(50);
}
}
else
{
//向上按钮按下
if (State_B_U == HIGH)
{
Serial.println("Right UP");
tone(EM_Pulse_common, 8000);
digitalWrite(EM_enable_M3, HIGH);
digitalWrite(EM_1_3_dirY_common, HIGH);
delay(50);
}

//向下按钮按下
else if (State_B_D == HIGH)
{
Serial.println("Right down");
tone(EM_Pulse_common, 8000);
digitalWrite(EM_enable_M3, HIGH);
digitalWrite(EM_1_3_dirY_common, LOW);
delay(50);
}

//向左按钮按下
else if (State_B_L == HIGH)
{
Serial.println("Right left");
// tone(EM_Pulse_common,8000);
digitalWrite(EM_enable_M4, HIGH);
digitalWrite(EM_2_4_dirX_common, LOW);
delay(50);
}
//向右按钮按下
else if (State_B_R == HIGH)
{
Serial.println("Right right");
// tone(EM_Pulse_common,8000);
digitalWrite(EM_enable_M4, HIGH);
digitalWrite(EM_2_4_dirX_common, HIGH);
delay(50);
}
}
digitalWrite(EM_enable_M1, LOW);
digitalWrite(EM_enable_M2, LOW);
digitalWrite(EM_enable_M3, LOW);
digitalWrite(EM_enable_M4, LOW);

//使用GetDistance()函数获取当前超声波传感器返回的距离值,并存入变量distance中
//LCD显示设置,4行分别显示当前位置,单位cm
float distance_2_Left_X = 440-ultrasonic2.GetDistance() * 10; //左-X 位置
Serial.println(distance_2_Left_X);
lcd.setCursor(0, 0);
lcd.print("Left(mm)");
lcd.setCursor(11, 0);
lcd.print("Right(mm)");

lcd.setCursor(0, 1);
lcd.print("X=");
lcd.print(distance_2_Left_X, 1);

float distance_4_Right_X = 450-ultrasonic4.GetDistance()*10; //右-X 位置
Serial.println(distance_4_Right_X);
lcd.setCursor(11, 1);
lcd.print("X=");
lcd.print(distance_4_Right_X,1);

float distance_1_Left_Y = 65+ultrasonic1.GetDistance()*10; //左-Y 位置
Serial.println(distance_1_Left_Y);
lcd.setCursor(0, 2);
lcd.print("Y=");
lcd.print(distance_1_Left_Y,1);

float distance_3_Right_Y = 65+ultrasonic3.GetDistance()*10; //右-Y 位置
Serial.println(distance_3_Right_Y);
lcd.setCursor(11, 2);
lcd.print("Y=");
lcd.print(distance_3_Right_Y,1);
}

过程性图片

image-20210226184937907 image-20210226184902086 image-20210226185013579 image-20210226185156780 image-20210226185214064 image-20210226185233635

成品展示

image-20210226184032295 电控上下移动1 电控左右移动1 电控上下移动2 电控左右移动2

image-20210226184750611

参考文章:
参考链接


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!