萌新的Arduino大作业

**

全自动收/晾衣服机

备注:本人因学校社团假期作业要求,用Arduino IDE编写并模拟实现了一个全自动
收/凉衣服的机器(由于硬件条件不足只能模拟),本人也是萌新一枚,希望观看的
大佬们不喜勿喷,有发现做错的话欢迎在评论区讨论,如果对你有帮助,本人也会
非常开心哒

文章目录

  • 全自动收/晾衣服机
    • 实现功能:
    • 功能细节:
    • 硬软件准备:
    • 涉及知识:
    • 代码及注释:
      • 伪代码:
      • 代码:
    • 最终效果视频

实现功能:

1.下雨时报警,如果没有人反应,则自动收衣服
2.晴天时自动晒衣服

功能细节:

1.用流水灯不同的方向显示电机运转的不同方向
2.检测晴天和下雨时蜂鸣器发出的声音不一样
3.本人采用了开始时令数据稳定,三次取两次等方法防止数据波动出现异常

硬软件准备:

1.减速电机
2.蜂鸣器
3.HC-SR04超声波测距(可不用)
4.DHT11温湿度传感器
5.LED
6.Arduino单片机
7.杜邦线若干根
8.在电脑上安装IDE
软件截图

涉及知识:

串口通信协议,c/c++编程语言,各种传感器的数据手册等

代码及注释:

伪代码:

  • 定义函数:
    • 自定义的蜂鸣器报警旋律:void ring();
    • 温湿度信号读取:byte readData();
    • 开始检测温湿度:void start_test();
    • 检测为下雨:boolean test_rain();
    • 检测为晴天:boolean test_sun();
    • 控制流水灯的函数,用于显示电机正向运作:void liushui1();
    • 控制流水灯的函数,用于显示电机反向运作:void liushui2();
  • 开始准备(void setup()):
    • 定义8,4,7脚为输出脚
    • 串口初始化
  • 循环开始(void loop()):
    • 设置一个判断变量(judge),初始值为0,为初始化阶段,当检测到下雨,则赋值为1,当检测到晴天,则赋值为2
    • if(judge == 0)(初始化,开始默认晾衣杆正在外面晾晒):
      • 先检测6次数据让传感器保持稳定
      • 在没检测到下雨时,保持原状
      • 当检测到下雨时,开始报警,judge赋值为1
      • 如果没有人收衣服,则开始自动收,同时开启流水灯以显示电机工作状态。(这里就需要测距仪了,但是由于硬件条件不允许,本人就没加)
    • else if(judge == 1)(如果为下雨)
      • 打印:现在正在下雨!
      • 检测温湿度,在没检测到晴天之前保持输出温湿度
      • 当检测到晴天,蜂鸣器发声,开始晾衣服,judge赋值为2
    • else if(judge == 1)(如果为晴天)
      • 打印:现在是晴天!
      • 检测温湿度,在没检测到下雨之前保持输出温湿度
      • 当检测到晴天,蜂鸣器报警,开始收衣服,judge赋值为1

代码:

void ring();//自定义的蜂鸣器报警旋律
byte readData();// 温湿度信号接脚连入 Arduino 的 Pin 2
void start_test();// 每次要与 DHT11 沟通并开始检测温湿度
boolean test_rain();//检测为下雨(湿度超标),返回True,否则返回False
boolean test_sun();//检测为晴天(湿度和温度都合适),返回True,否则返回False
void liushui1();//控制流水灯的函数,用于显示电机正向运作(持续时间大约18s)
void liushui2();//控制流水灯的函数,用于显示电机反向运作(持续时间大约18s)
int judge = 0;//设置一个变量判断现在的情况,0为初始化阶段,1为下雨,2为晴天
int val;//流水灯中电平变量
//float range;设置HC-SR04的距离
//float time1;设置HC-SR04返回信号的时间

void ring(){
  for(int i=0;i<3;i++){
    digitalWrite(8,HIGH);
    delay(233);
    digitalWrite(8,LOW);
    delay(33);
    digitalWrite(8,HIGH);
    delay(132);
    digitalWrite(8,LOW);
    delay(33);
    digitalWrite(8,HIGH);
    delay(200);
    digitalWrite(8,LOW);
    delay(33);
    digitalWrite(8,HIGH);
    delay(266);
    digitalWrite(8,LOW);
    delay(66);
    digitalWrite(8,HIGH);
    delay(233);
    digitalWrite(8,LOW);
    delay(33);
    digitalWrite(8,HIGH);
    delay(132);
    digitalWrite(8,LOW);
    delay(33);
    digitalWrite(8,HIGH);
    delay(200);
    digitalWrite(8,LOW);
    delay(33);
    digitalWrite(8,HIGH);
    delay(266);
    digitalWrite(8,LOW);
    delay(2400);
  } 
}
int dhPin = 2;  
byte dat[5];   // 存放湿度2byte, 温度 2 byte, checksum 1 byte
byte readData() {  // 每次读取 8 bits  ( one byte)
  byte data = 0 ; // 初始化数据,不然可能出错
  for (int i = 0; i < 8; i++) {
    if (digitalRead(dhPin) == LOW) {  // 一开始要 LOW 才表示要传过来
      while (digitalRead(dhPin) == LOW); //等待 50us;
      // 现在已经变成 HIGH 了
      delayMicroseconds(30); //判断高电平持续时间,以判定资料是‘0’还是‘1’;
      if (digitalRead(dhPin) == HIGH) // 持续了 30 us 以上就是 1
        data |= (1 << (7 - i)); //高位在前,低位元在后;
      //如果这时已经是 LOW, 表示这 bit 是 0, 不必塞入 data
      //..而且以下的 while 也会立即结束(因为 LOW), 准备接收下一个 bit
      while (digitalRead(dhPin) == HIGH); // 等待下一bit的接收;
      //这时一定已经变成 LOW 了
    }
  }
  return data;   // 收完 8 bit = one byte = one char
}
void start_test() {  
  digitalWrite(dhPin, LOW); //拉低到 LOW,发送表示要开始沟通的信号;
  delay(30); //延时要大于 18ms,以便 DHT11 能检测到开始信号;我们用30ms
  digitalWrite(dhPin, HIGH);  // 拉高HIGH, 让 DHT11 拉低到 LOW 告诉我们要传送
  delayMicroseconds(40);  // 给40us等待 DHT11 响应;
  pinMode(dhPin, INPUT); // 改为输入 mode 准备 digitalRead( )
  while (digitalRead(dhPin) == HIGH);  // 必须等到 LOW
  delayMicroseconds(80); //DHT11 发出响应,会拉低 80us;所以至少等80us
  while (digitalRead(dhPin) == LOW); // 继续等到变 HIGH
  delayMicroseconds(80); //DHT11 会拉高到HIGH 80us 后开始发送数据;
  /// 以下连续读入 5 bytes (40 bits), 最后的 byte 是 checksum 校验值
  for (int i = 0; i < 5; i++) dat[i] = readData(); //接收温湿度资料,校验位元;
  pinMode(dhPin, OUTPUT); // 改为 Output mode, 准备拉高HIGH
  digitalWrite(dhPin, HIGH); //发送完一次资料后释放bus,等待下一次开始信号;
}
boolean test_rain(){
  int count = 0;
  for(int i=0;i<3;i++){//防止数据波动
      start_test( );
      if (dat[0] > 70)
        count++;
      delay(1985);
  }
  if(count >=2)//三次测试如果有两次超标,则返回True,表示雨天
    return true;
  else
    return false;
}
boolean test_sun(){
  int count = 0;
  for(int i=0;i<3;i++){//防止数据波动
      start_test( );
      if ((dat[0] < 40)&&(dat[2] > 30))
        count++;
        delay(1985);
  }
  if(count >=2)//三次测试如果有两次达到标准,则返回True,表示晴天
    return true;
  else
    return false;
}
void liushui1(){//控制流水灯的函数,用于显示电机正向运作(持续时间大约18s)
  for(int i=0;i < 2;i++){
    for(val=0;val<=255;val++){
      analogWrite(9,val);
      delay(6);
    }
    for(val=255;val>=0;val--){
      analogWrite(9,val);
      delay(6);
    }
    for(val=0;val<=255;val++){
      analogWrite(10,val);
      delay(6);
    }
    for(val=255;val>=0;val--){
      analogWrite(10,val);
      delay(6);
    }
    for(val=0;val<=255;val++){
      analogWrite(11,val);
      delay(6);
    }
    for(val=255;val>=0;val--){
      analogWrite(11,val);
      delay(6);
    }
  }
}
void liushui2(){//控制流水灯的函数,用于显示电机反向运作(持续时间大约18s)
  for(int i=0;i < 2;i++){
    for(val=0;val<=255;val++){
      analogWrite(11,val);
      delay(6);
    }
    for(val=255;val>=0;val--){
      analogWrite(11,val);
      delay(6);
    }
    for(val=0;val<=255;val++){
      analogWrite(10,val);
      delay(6);
    }
    for(val=255;val>=0;val--){
      analogWrite(10,val);
      delay(6);
    }
    for(val=0;val<=255;val++){
      analogWrite(9,val);
      delay(6);
    }
    for(val=255;val>=0;val--){
      analogWrite(9,val);
      delay(6);
    }
  }
}
/*float distance(){//返回超声波测距的距离
  digitalWrite(12, LOW);
  delayMicroseconds(2); 
  digitalWrite(12,HIGH); 
  delayMicroseconds(10);
  digitalWrite(12, LOW); 
  time1=float(pulseIn(3,HIGH));
  range=time1*17/1000;
  delay(100);
  return range;
}*/
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(8,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(7,OUTPUT);
  Serial.println("begin!");
  pinMode(dhPin, OUTPUT);
  //pinMode(3,INPUT_PULLUP);
  //pinMode(12,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  int i;
  boolean rain = test_rain(),sun = test_sun();
  if(judge == 0){//如果处于初始化阶段(晾衣杆在外面)
    for(i=0;i<6;i++){//先检测6次让数据稳定
      start_test();
      Serial.print("检测到湿度为 = ");
      Serial.print(dat[0], DEC); //显示湿度的整数部分;
      Serial.print('.');
      Serial.print(dat[1], DEC); //显示湿度的小数位;(其实是 0)
      Serial.println(" %");  // 注意有空格要用 " %"  不可用 ' %'
      Serial.print("检测到温度为 = ");
      Serial.print(dat[2], DEC); //显示温度的整数部分;
      Serial.print('.');
      Serial.print(dat[3], DEC); //显示温度的小数位;
      Serial.println(" C");
      delay(1985);
    }
    Serial.println("数据已稳定!");
    
    while((rain||sun) == false){//两个测试都为假的话,保持初始化阶段,直到检测出有变化
      Serial.println("当前未检测到有变化");
      rain = test_rain();
      sun = test_sun();
    }
    if(rain){//如果检测到下雨
      judge = 1;//将判断条件设为1
      ring();//发出警报
      Serial.println("检测到下雨!开始警报并且收衣服!");
      digitalWrite(4,HIGH);
      digitalWrite(7,LOW);
      liushui1();//电机开始工作,同时流水灯显示电机正转
      //当然有些情况下电机转动后距离依然不够,于是我添加了HC-SR04超声波测距,但是由于硬件条件不足,我无法将
      //其在现实中实现,这里只提供代码。。(使用时要把上面一行代码删除)
      /*float distance1 = distance();
      while(distance1 >= 10){//当距离超过10cm时,持续收回晾衣杆
        distance1 = distance();
        Serial.print("当前距离");
        Serial.println(range);
      }*/
      digitalWrite(4,LOW);
      Serial.println("已成功收回晾衣杆!");
    }
  }
  else if (judge == 1){//如果是处于下雨的情况
    Serial.println("现在在下雨!");
    while(!sun){
      sun = test_sun();
      Serial.print("检测到湿度为 = ");
      Serial.print(dat[0], DEC); //显示湿度的整数部分;
      Serial.print('.');
      Serial.print(dat[1], DEC); //显示湿度的小数位;(其实是 0)
      Serial.println(" %");  // 注意有空格要用 " %"  不可用 ' %'
      Serial.print("检测到温度为 = ");
      Serial.print(dat[2], DEC); //显示温度的整数部分;
      Serial.print('.');
      Serial.print(dat[3], DEC); //显示温度的小数位;
      Serial.println(" C");
    }
    Serial.println("检测到已经晴天!");
    digitalWrite(8,HIGH);
    delay(1200);
    digitalWrite(8,LOW);
    judge = 2;
    digitalWrite(4,LOW);
    digitalWrite(7,HIGH);
    liushui2();//电机开始工作,同时流水灯显示电机反转
    digitalWrite(7,LOW);
    Serial.println("已成功伸出晾衣杆!");
    //这里关于使用HC-SR04的代码和上面初始化时的情况类似,就不赘述了
  }
  else if(judge == 2){//如果是处于晴天的情况
    Serial.println("现在是晴天!");
    while(!rain){
      rain = test_rain();
      Serial.print("检测到湿度为 = ");
      Serial.print(dat[0], DEC); //显示湿度的整数部分;
      Serial.print('.');
      Serial.print(dat[1], DEC); //显示湿度的小数位;(其实是 0)
      Serial.println(" %");  // 注意有空格要用 " %"  不可用 ' %'
      Serial.print("检测到温度为 = ");
      Serial.print(dat[2], DEC); //显示温度的整数部分;
      Serial.print('.');
      Serial.print(dat[3], DEC); //显示温度的小数位;
      Serial.println(" C");
    }
    Serial.println("检测到下雨了!");
    ring();
    judge = 1;
    digitalWrite(7,LOW);
    digitalWrite(4,HIGH);
    liushui1();//电机开始工作,同时流水灯显示电机正转
    digitalWrite(4,LOW);
    Serial.println("已成功收回晾衣杆!");
    //这里关于使用HC-SR04的代码和上面初始化时的情况类似,就不赘述了
  }
}

最终效果视频

注:由于本人囊中羞涩+时间不足,无法购买一些曲轴、齿轮等零件,所以只能将
晾衣架模拟为竖直方向的运动,在这里深感抱歉(不过改成水平运动的代码和原理
是差不多的啦)

萌新的Arduino大作业(自动收\晾衣服)

最后,我的有部分代码转载自某些大佬之手,如果侵权请与本人联系,本人会尽快
删除!

你可能感兴趣的:(单片机)