目录

  • 前言
  • 功能介绍:
  • 无中断版本
  • 中断版本
  • 接线
  • 无中断版本
  • 粗略概览图
  • 步进电机
  • 按键1 2 3
  • 中断版本
  • 效果图
  • 无中断版本
  • 核心代码
  • 无中断版本
  • 中断版本


前言

本文是根据 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 Uno+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo_i++

步进电机

电机         Arduino
IN1   ————> 8
IN2   ————> 9
IN3   ————> 10
IN4   ————> 11
+     ————> 5V
-     ————> GND

Arduino Uno+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo_Arduino_02

按键1 2 3

Arduino Uno+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo_Arduino_03


(裂开,这图画了我3遍)

Arduino Uno+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo_i++_04

Arduino Uno+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo_步进电机_05

中断版本

即无中断版本的5 6脚换到 2 3脚即可。

Arduino Uno+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo_ci_06


Arduino Uno+步进电机28BYJ-48 简单应用之摇头、转圈、自定义模式demo_ci_07

效果图

无中断版本

视频和图片中顺逆搞反了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() {
  // 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);
  }

  // 设置中断脚为输入上拉
  pinMode(interrupt_array[0], INPUT_PULLUP);
  pinMode(interrupt_array[1], INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interrupt_array[0]), get_key1, HIGH);
  attachInterrupt(digitalPinToInterrupt(interrupt_array[1]), get_key2, HIGH);

  // 中断使能
  interrupts();

  // 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() { 
  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);
  }
}