文章程式碼顯示

2018年1月20日 星期六

《進階※應用篇》寫程式Arduino教學 - 04:使用 BLYNK 監控 Arduino 並使用手機遙控冷氣家電

BLYNK 較完整的使用教學請參閱以下文章

《進階※應用篇》寫程式Arduino教學 - 03:手機與 Arduino 的連結 BLYNK 應用簡述

我最終整合了 BLYNK + Arduino Mega + ESP8266 + DHT + 紅外線發射 電路組成使用手機來監控家中溫度,並且可以使用手機遙控冷氣的功能

實際成品如下


電路的細節就不多說了,電源輸入的部分可以參考此文

《進階※電子電路篇》寫程式Arduino教學 - 04:以電池 為 Arduino 供電的各種方法

紅外線放大電路部分可以參考此文

《進階※電子電路篇》寫程式Arduino教學 - 01:BJT電晶體 飽合區 截止區 到底該怎用?

《進階※應用篇》寫程式Arduino教學 - 02:紅外線遙控冷氣機(東元TECO、艾普頓APTON)、複製紅外線編碼訊號

DHT 以及 ESP 8266 部分也沒什麼秘密,在網路上依基本教學就可以找到該如何接線

程式碼的部份我參考了很多不同的連結,此套程式碼包含以下功能

1. Arduino Mega 與 BLYNK 連結
2. Watch dog (當機自動重啟)
3. 每隔 31*300 秒 , Mega & ESP8266 自動重啟(無論當機與否)
4. 手機藉由 DHT11  監控家中溫度
5. 手機藉由 紅外線發射器 遠端遙控冷氣



#define BLYNK_PRINT Serial

#include "ESP8266_Lib.h"
#include "BlynkSimpleShieldEsp8266.h"
#include "SimpleTimer.h"
#include "IRremote.h" // Pin7 for Arduino Due, Pin9 for Arduino Mega, Pin3 for Arduino UNO
#include "DHT.h"

// ===== watch dog , 重啟 設置=====
#include "avr/wdt.h"
void(* resetFunc) (void) = 0; //指向位置0的指針函數
// ==========================================

// ===== Wi-fi設定 =====
char auth[] = "我的auth";
char ssid[] = "我的wifi名稱";
char pass[] = "我的wifi密碼";
// =====================

// ===== ESP8266設定 =====
#define EspSerial Serial3 // for Mega
#define ESP8266_BAUD 115200
ESP8266 wifi(&EspSerial);
#define CH_PD 8
// =====================

// ===== DHT設定 =====
#define DHTPIN 10
#define DHTTYPE DHT11   
DHT dht(DHTPIN, DHTTYPE);
// =====================

#define OnPin 13 //是否連結上BLYNK的指示燈

SimpleTimer timer;
IRsend irsend;
WidgetLED con(V3);
WidgetLCD lcd(V25);

// ===== 全域變數 =====
int v4,v6,t,h;
int i,R,aa,D,F,RR,Du = 0;
int Rst_count = 299;
// =====================

unsigned int Power_OFF{
  //略
};

unsigned int Power_ON[]={
  //略
}; 

void setup()
{
  pinMode(CH_PD,OUTPUT);  digitalWrite(CH_PD,HIGH); delay(10);
  wdt_disable();
  pinMode(OnPin,OUTPUT); digitalWrite(OnPin,LOW); delay(10);
  Serial.begin(9600);   delay(10);
  EspSerial.begin(ESP8266_BAUD);  delay(10);
  
  Blynk.config(wifi, auth);      delay(10);
  Blynk.connectWiFi (ssid, pass); 
  Blynk.connect();
  
  if (Blynk.connected())  Serial.println ("Blynk connected."); 
    else  Serial.println ("Blynk disconnected."); 
      
  dht.begin();  delay(10);
  lcd.clear();  delay(40);
  
  RR = Rst_count - R;
  lcd.print(1, 0, "My BLYCK"); //(X: 0-15, Y: 0-1, "message") 
  delay(10);
  lcd.print(8, 1, "RST:"); 
  delay(10);    
  lcd.print(12, 1, RR);
  delay(10);
  
  timer.setInterval(2000L, timer_2000); delay(10);
  timer.setInterval(5000L, timer_5000); delay(10);
  timer.setInterval(31000L, timer_31000); delay(10);
  
  digitalWrite(OnPin,HIGH);  delay(10);
  BLYNK_LOG1(BLYNK_F("===== Initial process has been completed ======"));
  wdt_enable(WDTO_8S);
  delay(10);
}

// ===== 上電後從雲端抓值,會觸發對應的BLYNK_WRITE() =====
BLYNK_CONNECTED() { 
  Blynk.syncVirtual(V4,V6,V19,V20);
  //Blynk.syncAll();
  }

void loop()
{
  if(Blynk.connected())
  {
    Blynk.run();
    digitalWrite(OnPin,HIGH);
  }
   else
    {
      Serial.println("Blynk connected failed");
      digitalWrite(OnPin,LOW);
      delay(400);
    }
  
  timer.run();  
}// loop end

BLYNK_WRITE(V0)
{
  RESET();
}

BLYNK_WRITE(V4)
{
  v4 = param.asInt(); 
  Serial.print("AutoMode = ");
  Serial.println(v4);
  
  t = dht.readTemperature();
  if ( v4==1 & t >= 28 & F==0 ) { irsend.sendRaw(Power_ON, sizeof(Power_ON)/sizeof(Power_ON[0]), 38); Serial.println("Send ON"); F = F+1;}
}


BLYNK_WRITE(V6)
{
  v6 = param.asInt(); 
  Serial.print("Air. Control Switch Status = ");
  Serial.println(v6);
}

BLYNK_WRITE(V7)
{
  if( D%2 == 0)
  {
    if(v6==0) // OFF
    {
        irsend.sendRaw(Power_OFF, sizeof(Power_OFF)/sizeof(Power_OFF[0]), 38);
        delay(1200);  
        Serial.println("OFF");
        D=D+1;
    }
      else if (v6==1) //ON
      {
      irsend.sendRaw(Power_ON, sizeof(Power_ON)/sizeof(Power_ON[0]), 38);
      delay(1200);  
      Serial.println("ON");
      D=D+1;
      }
  }
  
  else { Serial.println("D mod 2 = 1"); D=D+1; }    
}

//=================
//  2000毫秒計時器(arduino觸發) 用於APP上查看雙方是否連線成功
//=================
void timer_2000()
{  
  wdt_reset();
  
  if( (i%2)==0 )  con.on();
  else            con.off();
  i=i+1;
} //timer_2000 end

//=================
//  5000毫秒計時器(arduino觸發) 若偵測到Blynk斷線超過15秒,重啟ESP8266及Arduino
//=================
void timer_5000()
{  

boolean a = Blynk.connected();
if (a == false)
  {
  aa = aa + 1;
  Serial.print("a is FALSE "); Serial.print("("); Serial.print(aa); Serial.println(")");
  
    if(aa>=3) {    RESET();    }

  }
} //timer_5000 end

//=================
//  31000毫秒計時器(arduino觸發)
//=================
void timer_31000()
{    
   int RR = Rst_count - R;
   if(RR==9) lcd.print(13, 1, " ");
   else if(RR==99) lcd.print(14, 1, " ");
   
   lcd.print(12, 1, RR); //(X: 0-15, Y: 0-1, "message")

   t = dht.readTemperature();
   Blynk.virtualWrite(V1, t); // 把值傳上雲端
   h = dht.readHumidity();
   Blynk.virtualWrite(V2, h);  

   if ( v4==1 & t >= 28 & F==0 ) { irsend.sendRaw(Power_ON, sizeof(Power_ON)/sizeof(Power_ON[0]), 38); Serial.println("Send ON"); F = F+1;}
   
if(R >= Rst_count) RESET();
else R++;
  
} //timer_31000 end

void RESET(){
    Serial.println("RESET");
    digitalWrite(CH_PD,LOW); // 先將 ESP8266重啟,再重啟 MEGA
    delay(2000);
    digitalWrite(CH_PD,HIGH);
    delay(300);
    resetFunc(); //呼叫重啟
}



這半年下來的監控結果是滿穩定的,在 12 月份以前幾乎每天都持續監測,不過某一天他當機了就是 .. 而我直到 1 月才發現這件事。

程式碼內我總共用了三個 timer 來輔助我完成這個專案

會出現 Auto Mode 是因為我在去年夏天晚上睡覺用的,我習慣睡前冷氣開定時吹個兩三小時,但我發現睡到早上六七點的時候房間會變超熱,所以我就設了一個 28 度,並且在睡前把 Auto mode 打開。

這樣當冷氣關掉並且 Arduino 偵測到溫度超過 28 度以後就會自動幫我打開冷氣

當然這部分還可以再加上吹了多久之後自動在幫我把冷氣關掉,不過我當時沒這麼做就是

最後值得注意的是,因為我有在程式碼內對 Mega 進行軟重啟(也就是用程式碼將 Arduino 重啟)

而我發現若 Arduino 配上 ESP8266 其重啟需要具有順序之分

我們需要 "先對 ESP8266 重啟" 接著再對 Arduino 進行重啟,這樣才可以成功讓 Arduino 重啟後可以自動再用 ESP8266 連上 BLYNK

↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引