Project: Smart Window

设计图

pic

连接图

link

代码

  1. 总体方案分析:

    由于需要随时监听430的消息并发送,而且要随时处理传感器的信息,如光照较强时需要开窗,光照较弱时需要关窗,因此使用前后台模式。

    //前台轮询
    void loop()
    {
     switch(sunlight_mode)
     {
       case SUNLIGHT_LOW:
         if(command_mode == AUTO && curtain_mode != CURTAIN_CLOSE) close_curtain();
         break;
       case SUNLIGHT_HIGH:
         if(command_mode == AUTO && curtain_mode != CURTAIN_OPEN) open_curtain();
         break;
       default:break;
     }  
     if(Serial.available()) ReceivePacket();
     if(send_deviceinfo == 1) SendDeviceInfo();
     delay(500);
    }
    //时间中断跑后台,修改各种标志,以便前台做相应处理
    void timer_handler(int irq)
    {
     if(irq!=SIGALRM) return;
     curtain_handler();
     //调用窗帘的处理
    
     timer_count++;
     //时间计数器增加
    
     if(timer_count == 100000) timer_count = 0;
     //当时间计数器达到100000时归零重新计数
    
     if(timer_count%light_time == 0)
     //当时间计数器达到光敏所要求的间隔,则调用光敏的后台处理
     {
       light_handler();
     }
    
     if((timer_count%com_time)== 0)
     //当时间计数器达到430所要求的间隔,则调用430的后台处理
     {
       com_handler();
     }
    }

  2. 宏定义各种状态

    
    #define SONAR_TIMEOUT 1000000
    
    //超过这个数值认为声呐超时
    
    //表示窗帘的状态
    
    #define CURTAIN_OPEN 0
    
    
    #define CURTAIN_MOVING 1
    
    
    #define CURTAIN_CLOSE 2
    
    
    //电机使用的GPIO引脚
    
    #define ENGINE_OPEN_PIN 6
    
    
    #define ENGINE_CLOSE_PIN 7
    
    
    //光敏传感器所使用的GPIO引脚
    
    #define LIGHT_PIN 2
    
    
    //光照状态,分别表示强光、中等光、弱光
    
    #define SUNLIGHT_HIGH 2
    
    
    #define SUNLIGHT_MIDDLE 1
    
    
    #define SUNLIGHT_LOW 0
    
    
    //用来判断光照的阈值,高于HIGH则认为是强光,低于LOW则认为是弱光,否则是中等光
    //双阈值用来防止单阈值在threshold旁的抖动
    
    #define THRESHOLD_HIGH 100
    
    
    #define THRESHOLD_LOW  40
    
    
    //当前系统的状态,手动或者自动
    
    #define HAND 0
    
    
    #define AUTO 1
    
  3. 初始化变量

    int trig[2] = {2,4};
    int echo[2] = {3,5};
    //两个超声波传感器的GPIO引脚
    
    int sunlight_mode = SUNLIGHT_LOW;
    int curtain_mode = CURTAIN_CLOSE;
    int command_mode = AUTO;
    //初始化各个状态
    
    int timer_count = 0; 
    //用来计数时间中断产生的次数,用处在之后可以观察到
    
    int light_time = 10;
    int com_time = 100;
    //用来表示中断间隔,在时间中断中可以看到
    
    int send_ack = 0;
    //表示是否需要发送一个ack包
    
    int send_seqnumber = 1;
    int receive_seqnumber = 0;
    //表示430通信时的seqnumber
    
    int mydeviceid = 883;
    //设备的ID号
  4. 重要函数解析:

    //接受430传输的信号
    void ReceivePacket()
    {
     count = 0;
     //从430模块中获取数据
     while (Serial.available()>0) {
       c = Serial.read();
       receive_buffer[count++] = c;
       printf  ("%02x ",c);
     }
    
     printf("\n");
     receive_buffer[count] = 0;
     if(*(int*)receive_buffer!=mydeviceid) return;
     //如果目标不是自己,则放弃这个包
    
     printf("%d\n",receive_buffer[8]);
    
     //根据协议,第9位为类型位
     switch(receive_buffer[8])
     {
        //接收到了一个Ack,说明当前的包发送成功
       case 0:if(send_seqnumber+1 == int(receive_buffer[4])) {
                 send_deviceinfo = 0;
                 send_seqnumber++;
               }
               break;
       //接受到一个数据包
       case 1:
              SendAck(int(receive_buffer[4])+1);
              //发送这个数据包的Ack
    
              //根据第10位(控制位)判断是自动模式还是手动模式
              command_mode = HAND; 
              if(receive_buffer[9] == 2) { //自动模式
                command_mode = AUTO;
              } else if(receive_buffer[9] == 1) open_curtain();  //手动模式要求开窗帘
              else close_curtain(); //手动模式要求关窗帘
    
              receive_seqnumber++;
              //接受Ack的seqnumber增加
    
              break;
       default:break;
     }
    }
    
    //检测光敏状态
    int detect_light()
    {
       int v = analogRead(LIGHT_PIN);
       if(v > THRESHOLD_HIGH) return SUNLIGHT_HIGH;
       else if(v < THRESHOLD_LOW) return SUNLIGHT_LOW;
       else return SUNLIGHT_MIDDLE;
       //双阈值法,生成三个状态,实际上有用的状态只有HIGH、LOW两个,MIDDLE只是用来防止抖动的。
    }
    
    //检测窗帘状态
    int get_curtain_state(int* echo,int* trig)
    {
    int covered[2] = {0,0};
    int i,sum = 0;
    for(i=0;i<2;i++)
    {
        covered[i] = supersonic_is_covered(echo[i],trig[i]);
        sum+=covered[i];
    }
    if(sum == 2) return CURTAIN_OPEN;
    if(sum == 1) return CURTAIN_MOVING;
    if(sum == 0) return CURTAIN_CLOSE;
    //两个超声波都没被挡住说明窗帘打开了
    //只有一个超声波被挡住说明窗帘正在移动
    //两个超声波都被挡住则说明窗帘关上
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值