Arduino Uno+步进电机28BYJ-48 简单应用之摇头转圈自定义模式demo
Posted Love丶伊卡洛斯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Arduino Uno+步进电机28BYJ-48 简单应用之摇头转圈自定义模式demo相关的知识,希望对你有一定的参考价值。
前言
本文是根据 STM32F103+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo 这篇文章的拓展,针对此文章的程序进行了Arduino Uno版本的粗略适配,具体细节可以参考这篇文章。
开发板:Arduino Uno Rev3 创客主板
开发环境:Arduino IDE
开发语言:Arduino 语言(类C语言)
官方文档:https://www.arduino.cc/reference/en/
功能介绍:
无中断版本
1、串口打印日志信息(波特率9600)
2、按按键1(即5脚上的按键),切换模式,分别为
- 不工作模式 共0.5秒
- 摇头模式 (顺n个5.625度 停顿x个0.1秒 逆n个5.625度 停顿x个0.1秒) 共0.2x秒
- 转圈模式1 (顺1圈,停顿y个0.1秒) 共0.1y秒
- 转圈模式2 (逆1圈,停顿z个0.1秒) 共0.1z秒
- 自定义模式 (自行修改代码) 共3.5秒
3、按按键2(即6脚上的按键),电机顺时针旋转5.625度。按按键3(即7脚上的按键),逆时针旋转5.625度。
中断版本
1、串口打印日志信息(波特率9600)
2、按 按键1(即2脚上的按键),切换模式,分别为
- 不工作模式 共0.5秒
- 摇头模式 (顺n个5.625度 停顿x个0.1秒 逆n个5.625度 停顿x个0.1秒) 共0.2x秒
- 转圈模式1 (顺1圈,停顿y个0.1秒) 共0.1y秒
- 转圈模式2 (逆1圈,停顿z个0.1秒) 共0.1z秒
- 自定义模式 (自行修改代码) 共3.5秒
3、按 按键2(即3脚上的按键),电机顺时针旋转5.625度。(ps:这个转动得在循环中加打印才会转动。。。莫名其妙,暂时不知道啥问题)
接线
无中断版本
粗略概览图
步进电机
电机 Arduino
IN1 ————> 8
IN2 ————> 9
IN3 ————> 10
IN4 ————> 11
+ ————> 5V
- ————> GND
按键1 2 3
(裂开,这图画了我3遍)
中断版本
即无中断版本的5 6脚换到 2 3脚即可。
效果图
无中断版本
视频和图片中顺逆搞反了0.0
Arduino Uno+步进电机28BYJ-48 简单应用
核心代码
无中断版本
unsigned int forward[4] = {0x03,0x06,0x0c,0x09}; // 正转
unsigned int reverse[4]= {0x03,0x09,0x0c,0x06}; // 反转
int motor_array[4] = {8, 9, 10, 11}; // 电机引脚
int key_array[3] = {5, 6, 7}; // 按键引脚
// 按键变量
int key = 0;
// 工作模式变量
int mode = 0;
// n个5.625度
int n = 0;
// 停顿x,y,z个0.1秒
int x = 0, y = 0, z = 0;
int i = 0;
// 电机设置
void SetMotor(unsigned int InputData)
{
if(InputData == 0x03)
{
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
else if(InputData == 0x06)
{
digitalWrite(8, LOW);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, LOW);
}
else if(InputData == 0x09)
{
digitalWrite(8, HIGH);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, HIGH);
}
else if(InputData == 0x0c)
{
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
}
else if(InputData == 0x00)
{
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
}
/*
功能:转1/64圈
步距角5.625 360/5.625=64 减速比1/64
故64*64个脉冲转一圈
n 圈数
_direction 方向 1正转 非1反转
delay_ms delay_ms >= 2
*/
void motor_circle(int n, int _direction, int delay_ms)
{
int i, j;
for(i = 0; i < n * 8; i++)
{
for(j = 0; j < 4; j++)
{
if(1 == _direction)
{
SetMotor(0x00);
SetMotor(forward[j]);
}
else
{
SetMotor(0x00);
SetMotor(reverse[j]);
}
delay(delay_ms > 2 ? delay_ms : 2);
}
}
}
// 获取按键按压
int get_key(void)
{
if(LOW == digitalRead(key_array[0]))
{
delay(10);
if(LOW == digitalRead(key_array[0]))
return 1;
}
else if(LOW == digitalRead(key_array[1]))
{
delay(10);
if(LOW == digitalRead(key_array[1]))
return 2;
}
else if(LOW == digitalRead(key_array[2]))
{
delay(10);
if(LOW == digitalRead(key_array[2]))
return 3;
}
else
{
return 0;
}
}
// 初始化
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);//设置波特率为9600,这里要跟软件设置相一致。当接入特定设备(如:蓝牙)时,我们也要跟其他设备的波特率达到一致。
int i = 0;
for( i = 0 ; i < 4 ; i++ )
{
pinMode(motor_array[i], OUTPUT);
}
for( i = 0 ; i < 3 ; i++ )
{
pinMode(key_array[i], INPUT);
}
// 24 * 5.625 = 135
n = 24;
// 0.2 * 10 = 2
x = 10;
// 0.1 * 5 = 0.5
y = 5;
// 0.1 * 0 = 0
z = 0;
}
// 主循环
void loop() {
// 获取按键按压,注意,因为没有中断,所以需要持续按下按键,才能够响应。
key = get_key();
if(key != 0)
{
Serial.print("按键");
Serial.print(key);
Serial.println("按下(0表示无按键)");
Serial.print("当前模式:");
Serial.println(mode);
}
// key1 按下,切换工作模式
if(key == 1)
{
Serial.println("模式切换...");
mode++;
mode = mode > 4 ? 0 : mode;
Serial.print("当前模式:");
Serial.println(mode);
}
else if(key == 2)
{
Serial.println("key2按下,顺时针转5.625度");
// 顺时针转5.625度
motor_circle(1, 1, 2);
}
else if(key == 3)
{
Serial.println("key3按下,逆时针转5.625度");
// 逆时针转5.625度
motor_circle(1, 0, 2);
}
if(1 == mode) // 摇头模式 (顺n个5.625度 停顿x个0.1秒 逆n个5.625度 停顿x个0.1秒) 共0.2x秒
{
motor_circle(n, 0, 2);
for(i = 0; i < x; i++)
{
delay(100);
}
motor_circle(n, 1, 2);
for(i = 0; i < x; i++)
{
delay(100);
}
}
else if(2 == mode) // 转圈模式1 (顺1圈,停顿y个0.1秒) 共0.1y秒
{
motor_circle(64, 0, 2);
for(i = 0; i < y; i++)
{
delay(100);
}
}
else if(3 == mode) // 转圈模式2 (逆1圈,停顿z个0.1秒) 共0.1z秒
{
motor_circle(64, 1, 2);
for(i = 0; i < z; i++)
{
delay(100);
}
}
else if(4 == mode) // 自定义模式 (自行修改代码) 共3.5秒
{
motor_circle(1, 0, 2);
delay(500);
motor_circle(2, 0, 2);
delay(500);
motor_circle(4, 0, 2);
delay(500);
motor_circle(8, 0, 2);
delay(500);
motor_circle(16, 0, 2);
delay(500);
motor_circle(32, 0, 2);
delay(500);
motor_circle(64, 0, 2);
delay(500);
}
else // 不工作模式 共0.5秒
{
delay(500);
}
}
中断版本
unsigned int forward[4] = {0x03,0x06,0x0c,0x09}; // 正转
unsigned int reverse[4]= {0x03,0x09,0x0c,0x06}; // 反转
byte motor_array[4] = {8, 9, 10, 11}; // 电机引脚
byte interrupt_array[2] = {2, 3}; // 中断引脚
// 工作模式变量
byte mode = 0;
// n个5.625度
int n = 0;
// 停顿x,y,z个0.1秒
int x = 0, y = 0, z = 0;
int i = 0;
// 电机设置
void SetMotor(unsigned int InputData)
{
if(InputData == 0x03)
{
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
else if(InputData == 0x06)
{
digitalWrite(8, LOW);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, LOW);
}
else if(InputData == 0x09)
{
digitalWrite(8, HIGH);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, HIGH);
}
else if(InputData == 0x0c)
{
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
}
else if(InputData == 0x00)
{
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
}
/*
功能:转1/64圈
步距角5.625 360/5.625=64 减速比1/64
故64*64个脉冲转一圈
n 圈数
_direction 方向 1正转 非1反转
delay_ms delay_ms >= 2
*/
void motor_circle(int n, int _direction, int delay_ms)
{
/*
Serial.print("旋转配置,n:");
Serial.print(n);
Serial.print(" _direction:");
Serial.print(_direction);
Serial.print(" delay_ms:");
Serial.println(delay_ms);
*/
int i, j;
for(i = 0; i < n * 8; i++)
{
for(j = 0; j < 4; j++)
{
if(1 == _direction)
{
SetMotor(0x00);
SetMotor(forward[j]);
}
else
{
SetMotor(0x00);
SetMotor(reverse[j]);
}
//Serial.println("."); 不加串口换行打印 电机就不转。。。莫名其妙
delay(delay_ms > 2 ? delay_ms : 2);
}
}
}
// 中断服务函数 获取按键1按压
void get_key1(void)
{
if(LOW == digitalRead(interrupt_array[0]))
{
delay(10);
if(LOW == digitalRead(interrupt_array[0]))
{
// key1 按下,切换工作模式
Serial.println("模式切换...");
mode++;
mode = mode > 4 ? 0 : mode;
Serial.print("当前模式:");
Serial.println(mode);
}
}
else
{
}
}
// 中断服务函数 获取按键2按压
void get_key2(void)
{
if(LOW == digitalRead(interrupt_array[1]))
{
delay(10);
if(LOW == digitalRead(interrupt_array[1]))
{
Serial.println("key2按下,顺时针转5.625度");
// 顺时针转5.625度
motor_circle(1, 0, 2);
}
}
else
{
}
}
// 初始化
void setup(Arduino Stepper库驱动28BYJ-48步进电机测试程序
Proteus仿真Arduino UNO利用Stepper库实现uln2003驱动步进电机转动
Ardunio使用ULN2003驱动28BYJ-48步进电机
ESP8266 驱动步进电机(28BYJ-48电机 ULN2003 驱动板)