浏览量: 662 次浏览

智能无线控制窗帘

2020年2月12日 2 作者 Nie Hen

使用 28BYJ-48步进电机 esp8266-12f(或nodemcu) mqtt 基于arduino IDE开发实现
通过mqtt发送指令给wifi模块进而控制电机,电机拖动窗帘打开或闭合

效果演示:

搭建模型

如何制作电动窗帘,牛人给你解释它的原理
参考这个视频 搭建窗帘模型
enter description here

模型搭建很重要 就算电机能够稳定控制但是模型搭建的不好 窗帘的打开和关闭都会受到影响

  • 电机要粘牢固
  • 绳子要选细的粗糙的(摩擦力大)
  • 窗帘选软纸 或者布
  • 滑轮一定要认真做 很影响转动

我第一次试验论证是否能够行得通的时候 制作了一个窗帘模型,犯了很多错做的也很丑
但是试验成功了!!!
enter description here

第二次我们的窗帘模型是我和另外一个java大佬熬夜做出来的,两个工科生做手工真的是太折磨人了…
enter description here

步进电机原理

28BYJ-48步进电机
enter description here

28BYJ-48的含义为外径28毫米四相八拍式永磁减速型步进电机
对于驱动28BYJ-48步进电机,最常用的方法是使用ULN2003驱动板。
用Arduino开发板的+5V电源直接为ULN2003驱动板供电的方法短时间测试是可以的,但是不要在长时间使用Arduino为ULN2003驱动板进行供电。
enter description here

更详细的原理分析 链接

控制步进电机

电路接线图
enter description here

使用Stepper库
建立步进电机对象
定义电机控制引脚以及电机基本信息。
电机控制引脚为 8,9,10,11
以上引脚依次连接在ULN2003 驱动板 In1, In2, In3, In4
创建电机 对象

示例代码
参考 dianji.ino 学习stepper库的使用方法
创建对象 Stepper steppermotor(STEPS_PER_ROTOR_REV, 8, 10, 9, 11);
其中的第一个参数为 一次转动的步数
在这里可以设置为2048

示例代码

/*
  Arduino控制28BYJ-48步进电机测试程序
  本示例程序旨在演示如何通过Arduino控制28BYJ-48步进电机。
*/

//本示例程序使用Stepper库
#include 

// 定义电机控制用常量

// 电机内部输出轴旋转一周步数
const int STEPS_PER_ROTOR_REV = 32; 

//  减速比
const int GEAR_REDUCTION = 64;

/*
 * 转子旋转一周需要走32步。转子每旋转一周,电机输出轴只旋转1/64周。
 * (电机内部配有多个减速齿轮,这些齿轮会的作用是让转子每旋转一周,
 * 输出轴只旋转1/64周。)
 * 因此电机输出轴旋转一周则需要转子走32X64=2048步,即以下常量定义。
*/

// 电机外部输出轴旋转一周步数 (2048)
const float STEPS_PER_OUT_REV = STEPS_PER_ROTOR_REV * GEAR_REDUCTION;

// 定义电机控制用变量

// 电机旋转步数
int StepsRequired;

// 建立步进电机对象
// 定义电机控制引脚以及电机基本信息。
// 电机控制引脚为 8,9,10,11 
// 以上引脚依次连接在ULN2003 驱动板 In1, In2, In3, In4 

Stepper steppermotor(STEPS_PER_ROTOR_REV, 8, 10, 9, 11); 

void setup()
{
//setup函数内无内容
}

void loop()
{
  // 极慢转动4步用于观察ULN2003电机驱动板LED变化
  steppermotor.setSpeed(1);    
  StepsRequired  =  4;
  steppermotor.step(StepsRequired);
  delay(1000);

   // 慢速顺时针旋转一圈
  StepsRequired  =  STEPS_PER_OUT_REV; 
  steppermotor.setSpeed(500);   
  steppermotor.step(StepsRequired);
  delay(1000);

  // 快速逆时针旋转一圈
  StepsRequired  =  - STEPS_PER_OUT_REV;   
  steppermotor.setSpeed(800);  
  steppermotor.step(StepsRequired);
  delay(2000);

}

参考太极创客链接

wifi模块控制电机

依旧使用的stepper库更改了GPIO引脚
创建对象
Stepper steppermotor(STEPS_PER_OUT_REV, D1, D2, D5, D6);
Stepper steppermotor(STEPS_PER_OUT_REV, 5, 4, 14, 12);
(两个一样)

看到国外一个使用nodemcu mqtt 以及 28BYJ-48步进电机的使用方法
更换了引脚 更改了部分参数 成功了

接线图
enter description here
enter description here
(对应GPIO 分别是GPIO 5,GPIO 4, GPIO14, GPIO12)

创建的对象为 Stepper steppermotor(STEPS_PER_OUT_REV, D1, D2, D5, D6);
其中第一个参数设置为200 速度设置80 相比于arduino都比较小
将第一个参数提升到600时电机转不动.. 没找到原因

代码

完整参考代码:

// 作者 : 涅痕 
// 更多IOT开发 访问 niehen.cn
#include <Stepper.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const int STEPS_PER_ROTOR_REV = 32; 
const int GEAR_REDUCTION = 64;
const float STEPS_PER_OUT_REV = 400;// 电机外部输出轴旋转一周步数 (2048)
const int stepsPerRevolution = 200;
//Stepper steppermotor(STEPS_PER_OUT_REV,  D1, D2, D5, D6); 
Stepper steppermotor(STEPS_PER_OUT_REV,  5, 4, 14, 12); 

const char* ssid = "niehen_pc";
const char* password = "*";
const char* mqtt_server = "192.168.137.41";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
String tmpTopic;
String strplayload;
bool start_on = false;

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
   Serial.print(".");
  }

randomSeed(micros());
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {


 tmpTopic = String((char *)topic);
 payload[length] = '\0';
 strplayload  = String((char*)payload);
 int isint = 0;
String inString = "";
int older_circle = 0;
client.publish("curtain/status", "curtain get the older");

for (int i=1; i< strplayload.length();i++)  // 检测接收到的命令是否符合
  {
    if (strplayload[0] == '-') {
      inString += strplayload[i];
    }
    if (!isDigit(strplayload[i]))
    {
      isint = 1;
      break;
      }    
    }
if(isint == 0){
if (strplayload[0] == '-') {
  // 反转
  older_circle = inString.toInt();
  value = (-1) * older_circle; 
  start_on = true;
}else{
  // 正转
  older_circle = strplayload.toInt();
  value =  older_circle; 
  start_on = true;
  }

 }
}                                                                                                                                                                                                                                                                           
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str())) {
     Serial.println("connected");

      client.publish("curtain/status", "init...");
      // ... and resubscribe
      client.subscribe("curtain/older");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
   Serial.begin(115200);
   setup_wifi();

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
 steppermotor.setSpeed(80);
}

void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
if(start_on ){

  if(value >0)
  {
  steppermotor.step((value)*STEPS_PER_OUT_REV);
  client.publish("curtain/status", "curtain runing");
    }else if(value <0){ 
    steppermotor.step((value)*STEPS_PER_OUT_REV);
    client.publish("curtain/status", "curtain runing");
      }
  start_on = false;
  }
}