網頁

解決NodeMCU使用ampy出現could not enter raw repl的問題(Mircopython)



在前陣子玩Blynk之後,決定要來鑽研Python這套程式語言,同時NodeMCU又可以使用MircoPython來運行,於是買了超圖解 Python 物聯網實作入門:使用 ESP8266 與 MicroPython來進行研讀,順便學習Python的一些基礎。



但是今天在前幾章建立環境的部分,在CMD要使用ampy讀取NodeMCU時卻出現could not enter raw repl的訊息。起初我以為是板子的問題,但是我測試另一塊ESP8266-01卻是可以使用的,但是之前燒錄Blynk等等韌體都沒問題,應該不是這塊NodeMCU有問題才對,於是我上網找了一下,原來也有人跟我有一樣的問題。ESP8266 Micropython "Could not enter raw repl"

這個解決方法在留言串markserrano915 commented on 22 Jul 2017有提出解決方案,想不到解決的方法只需要在C:\Users\Mars\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\ampy\pyboard.py,這個檔案中修改加上一行time.sleep(2)即可(加入位置見下圖)。pyboard.py的位置每個人可能有所不同,要搜尋一下。



加上這行指令之後我就能順利使用ampy連接NodeMCU了,本來還打算買一塊新的板子,幸好沒有白花錢。

讓學習實際的應用在生活中 我學習的下一步



最近在寫Blynk雲端平台的工具筆記時,突然感覺到有一些空虛,突然覺得自己不知道在做些什麼。回顧自己過去的一些文章,測試過也玩了一些東西,但玩完後發現就僅止於這樣而已,做了一台寫字機,然後就放在那邊,有了一台3D印表機,然後也沒有印些甚麼,購買了好多模組,然後試過範例就放著。實際上有運用在生活中、增進自己生產力的屈指可數,如此一來不禁讓我思考,我學習、玩這些的目標究竟是甚麼?

then?

偶然地看到這篇文章謝KK - 我是跑者_[心得與推薦] Python初學特訓班,突然猶如當頭棒喝一般一般的有所體悟,作者在文中提到"無論是運算思維或是程式教學,都應該要讓學習能與生活結合。要是好不容易學了程式的邏輯思考跟語法,卻不知道可以應用在哪裡,就像學了一堆的武功心法,結果整天只是找木人椿練習。"這句話真是讓我驚醒,我買了許多模組但僅止於玩過範例,學習了程式語言也就僅止於不斷的Hello world與點燈(當然是三腳貓而已),那這樣何必繼續浪費時間跟金錢在上面呢?

while

不斷的買模組玩模組,學人家程式的範例永遠就只是這樣而已,就像謝KK老師在文章中所提到的"目前看到的設計所做出來的東西本質上是差不多的(一樣無趣)",是阿,這也就是我目前所癥結的,不斷的試著大同小異的東西,做著人家做過的範例。現在的程式、軟體、機器等技術類的東西幾乎都已經成章成冊了,看著書局陳列著的程式語言教學書籍一版又一版的出,技術手冊是絕對不會少的,但我要怎麼樣的運用在我的生活中,甚至進一步的提升自己?

break

連國中生現在都要學寫程式了,到底是為什麼?
學習資訊科學的目的莫過於在這個資訊爆炸的世代,能更加站得住腳與提升自己的競爭力,但回歸學習的本質還是要去使用它,而運用在生活與工作上就是最直接與有效的方法。一直玩模組的範例我能學到甚麼? 複製人家的程式碼又會帶給我生活什麼幫助?

我真正的目標,應該持續學習與善用機械、電子、資訊的知識,並利用這些工具來讓自己的生活更加的便利與舒適,而不是一直繞圈圈做著一樣的事情。(再次引用謝KK老師的話:走出電腦教室之後,他們仍然不曉得那隻貓能為他們的生命帶來什麼。)

do!

回顧我撰寫文章的本質,主要是因為之前在網路上找到問題的解答時(尤其是中文),總會感覺到如獲至寶一般的快樂,於是我也想將自己的經驗、學習的筆記給記錄下來,說不定有人剛好這麼一兩個問題跟我一樣,進而看了我的文章之後能有所幫助並得到解答。這是我寫文章的初衷。

接著還要做的是學習Python這套程式語言,因為在網路上諸多的評論都提到,Python是最好入門且生產力強大的一套程式語言,同時使用領域廣泛也是我選擇學習它的重要原因,如此一來才能在資訊工具上有更多的發揮。(20230211補充:最後我還是沒學了,覺得寫程式我真的不是塊料,還是乖乖玩3D印表機吧XD)

exit

之前參加創客閣樓的聚會時就發現,許多的創客反而是相當的偏向學習軟體的,除了老師教學及產品開發階段的模型(prototype)之外,3D列印與Arduino所製作出來的東西,實在有點難以在生活中實際使用,就算做出來了也很難像量產的產品那樣使用,畢竟硬體產品開模的成本以及電路板印刷的數量等等,這些算起來都是白花花的銀子,就算有那個技術也難以這樣製造。

"我想"這或許就是創客的一個癥結點,但玩玩軟體可就不一樣了,軟體的擴展性、成本以及應用上就比較不受人事時地物限制,在生活上的應用也是相當的廣泛,同時軟體逐漸強調開源化,更進一步拓展了它的應用性。
(20230211補充:回顧上面這段話覺得蠻可愛的,現在的我正是靠3D列印在賺取一些外塊,所以還是做自己真正熱愛與有興趣的就對了,這樣才能做得長久,而且有時候在思考興趣這東西就別太功利主義了。)

我這裡要強調以上都是個人觀點,並沒有哪個好哪個壞的問題,而且創客更強調的是一種精神與態度,但是在現實層面上的確會有這樣的一個限制存在(硬體的金錢與成本)。這篇文章純粹是一種感覺以及抒發,接著目標是學習更多能應用在生活中的知識與技術,來增進我的生產力以及讓生活更加便利,更希望能夠幫助到其它人,重點還是要好玩就對了。

繼續前進吧

可調式握力器原理



今天看到一個很有趣的東西,那就是可調式握力器
這個東西不貴,但是我覺得它的設計相當的有巧思,因為它算是利用了力矩的原理,去進行握力緊度的調整,這樣無論男生女生、高矮胖瘦,都可以用同一支握力器進行訓練。



從上方可以看到裡面有一個螺桿,靠著這根螺桿去調整彈簧拉伸的固定點,藉此來調整握力。



生活中無處不電子,也無處不機構。我很喜歡去觀察生活中一些有趣的設計小細節,這就是一個很好的例子。

意外查到這篇關於握力器的文章世界最專業握力器COC#系列,到底130kg的握力器是甚麼怪物在用的啊? 另外我也在思考這個世界的握力標準其重量是依據哪個位置做計算,畢竟這種扭轉彈簧的握力器,握得遠相對力矩就大,我猜測應該是從握柄中央的分隔線作基準吧?(20230207補充:後面才看到公職考試內有一種握力測量器,那種就屬於直上直下的彈簧結構,就不會有上述那種力矩的問題了。)

基於Blynk雲端平台的RTC工具之LCD1602時鐘加上序列留言功能



透過Blynk的RTC工具製作自動對時TM1637七節顯示時鐘的文章中,我使用Blynk的RTC工具抓取伺服器的標準時間,然後在顯示在TM1637上。而我今天要顯示在LCD1602的螢幕上,因為LCD可以顯示比較多的資訊,好比溫濕度、時間日期等等,比起單純七節時鐘顯示器TM1637有更多可以拓展的用途,而且之後還可以搭配更大塊的液晶(或oled)顯示更多的資訊。

首先我使用的是帶有IIC的LCD1602模組,因為這樣可以省下相當多的接腳問題,而因為這塊液晶是5V的電壓,所以我使用的Vcc是NodeMCU的Vin腳(5V)。至於訊號腳電平轉換的問題,我倒是沒有去考慮,因為我看國外不少人也是這樣直接連接的,至少到目前為止還沒有任何問題,然後將SCL接上D1;SDA接上D2。

接下來我先使用i2c_scanner掃描LCD1602的硬體位址,接著再使用Wiring NodeMCU ESP8266 12E with i2C 16×2 LCD Screen這篇文章的程式碼測試NodeMCU點亮LCD1602,確認好可以顯示後我就準備將這個程式與Blynk的RTC程式做結合。



接著我整併LCD與RTC的程式碼,並且與電腦端的NTP校時軟體進行對照,總體來說大概都會差約一秒左右的時間,但考慮到網路的延遲之類的就別太勉強了,至少我不用去進行調整它就會自動較正時間。



然而在寫時間顯示的程式時有遇到一個問題,那就是時間數字補零的問題,如果個位數時它會往前跑(等於靠左),這樣在顯示上會不太好看,這個問題我在Real Time Clock Module, LCD Display and Controller Time這篇文章找到很好的解決方案,它另外寫了一個副程式去進行判斷,讓程式碼看起來不會落落長。

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

char auth[] = "";

char ssid[] = "";
char pass[] = "";

BlynkTimer timer;
WidgetRTC rtc;

void setup()
{
  //Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  rtc.begin();

  lcd.init();
  lcd.clear();
  lcd.backlight();

  timer.setInterval(500L, digitalClockDisplay);
  setSyncInterval(3600);
}

void loop()
{
  Blynk.run();
  timer.run();
}

void digitalClockDisplay()
{
  bool result = Blynk.connected();
  if (result) {
    lcd.setCursor(3, 0);
    lcd.print(year());
    lcd.setCursor(7, 0);
    lcd.print("/");
    lcd.setCursor(8, 0);
    printDigits(month());
    lcd.setCursor(10, 0);
    lcd.print("/");
    lcd.setCursor(11, 0);
    printDigits(day());

    lcd.setCursor(4, 1);
    printDigits(hour());
    lcd.setCursor(6, 1);
    lcd.print(":");
    lcd.setCursor(7, 1);
    printDigits(minute());
    lcd.setCursor(9, 1);
    lcd.print(":");
    lcd.setCursor(10, 1);
    printDigits(second());
  }
  else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Disconnected");
  }
}

void printDigits(int digits) {
  if (digits < 10)
    lcd.print('0');
  lcd.print(digits);
}

但是只有顯示RTC的時間不夠看,我還想要測試在Blynk的APP上利用Terminal發送訊息,讓LCD上面可以顯示一些我輸入在裡面的字串,同時在上方顯示時間,測試後是沒有問題的,只是要注意不要超過16個字元不然會截尾。



#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

char auth[] = "";
char ssid[] = "";
char pass[] = "";

WidgetTerminal terminal(V1);
BlynkTimer timer;
WidgetRTC rtc;

void setup()
{
  //Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  rtc.begin();

  lcd.init();
  lcd.clear();
  lcd.noBacklight();

  timer.setInterval(500L, digitalClockDisplay);
  setSyncInterval(3600);
}

void loop()
{
  Blynk.run();
  timer.run();
}

void digitalClockDisplay()
{
  bool result = Blynk.connected();
  if (result) {
    lcd.setCursor(4, 0);
    printDigits(hour());
    lcd.setCursor(6, 0);
    lcd.print(":");
    lcd.setCursor(7, 0);
    printDigits(minute());
    lcd.setCursor(9, 0);
    lcd.print(":");
    lcd.setCursor(10, 0);
    printDigits(second());
  }
  else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Disconnected");
  }
}

void printDigits(int digits) {
  if (digits < 10)
    lcd.print('0');
  lcd.print(digits);
}

BLYNK_WRITE(V1)
{
  lcd.setCursor(0, 1);
  lcd.print("                ");
    lcd.setCursor(0, 1);
  lcd.print(param.asStr());
}

總算是完成LCD的顯示工作了,在我接著想做的多功能雲端智慧時鐘專案中,我還想加入溫溼度、PM2.5等等的設計,只是目前還在物色哪一些模組比較適合(DHT11真的太不準了),因此現在先多方面的測試單一元件,到時候再將它整併再一起。 至於1602實在能顯示的字太少了,這個之後看看能不能用Oled來克服。

拆解輕觸開關內部構造



暨上次拆解薄膜觸摸開關之後,今天再來拆看看這種在電路板上常見的輕觸開關,這種輕觸開關的規格有相當多種,可以參考這篇文章

接著讓我們進行拆解,首先要剪開它上方的四個塑膠固定點,然後把上方的鐵蓋給撬開。



拆開後可以發現它內部的構造跟薄膜式的幾乎一樣,都是利用一塊金屬彈片進行開關,而這種開關算是常常容易壞的一個東西,不常用也容易氧化壞掉,常用又容易磨損壞掉(好像用不用都會壞這樣.....)。只是這種按鈕的好壞就真的不知道該怎麼挑選了,畢竟電子材料行所賣的都是一包包好好的,也沒有什麼廠牌之類的。



接著我們剪開塑膠外殼,發現它的設計是兩兩成對的引腳,一邊是連接兩旁的接點,另外一邊是連接中間的接點。而金屬彈片就是能在按壓時會觸碰到中間的接點進而導通,所以接觸面的氧化就會造成按鈕接觸不良的現象。



從背面可以看到它引腳有一個記號,代表同方向的是有導通的。這種按鈕它的間隔約2.54*2的寬度,因此在電路板上還可以在走線時當作跳線之類的功能,達到一個連接的目的。



我當初第一個修理的東西就是更換這種按鈕,後來覺得光學習更換按鈕(銲錫、解銲)就能夠修理超級多東西了。

透過Blynk的RTC工具製作自動對時TM1637七節顯示時鐘



我是一個相當在意時間精準的人,過沒幾天就會把我手上的錶拿起來做個校正,務必要做到分秒不差才行,這純粹只是一種執著與個性,當然有人時間差了好幾分鐘也無所謂,但我個人就不喜歡這樣。

於是我一直希望在家能有一個時鐘,無時無刻顯示的都是最準確的時間,同時又會自己校正,但是我搜尋外面賣的電波校正時鐘(錶)實在是太貴了,於是我今天就要透過Blynk的RTC工具,來做一個會自動連線校準的時鐘,而我之後還會考慮加上溫溼度、PM2.5等等的功能監控家裡環境,最好還可以留一些訊息打字在鬧鐘上。所以我今天就要先嘗試將TM1637七節顯示器,顯示RTC的時間。至於之後顯示的載具要用OLED、LCD、七節就在看情況了。

程式部份我結合了傑森創工所提供的TM1637範例,以及Blynk官方所提供的RTC範例進行結合,將讀取到的RTC時間直接顯示在七節顯示器上。程式碼如下所示,CLK接上NodeMCU的GPIO16(D0);DIO接上GPIO5(D1),至於VCC的部份我接NodeMCU的3.3V是能工作的,只是亮度"稍微"弱了一點,但擔心接5V會有電位基準的問題,所以還是接3.3V保險,畢竟關於ESP8266能不能直接連接5V的IO訊號還是個爭論不停的議題

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include "TM1637.h"

#define CLK 16 //CLK pin,可自行決定接到哪個PIN
#define DIO 5 //DIO pin,可自行決定接到哪個PIN
TM1637 tm1637(CLK, DIO);

int point_flag = 0;

char auth[] = "YourAuthToken";

char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";

BlynkTimer timer;
WidgetRTC rtc;

void setup()
{
  Blynk.begin(auth, ssid, pass);
  rtc.begin();

  tm1637.init();
  tm1637.set(BRIGHTEST); //BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;

  timer.setInterval(1000L, digitalClockDisplay);
  setSyncInterval(3600);
}

void loop()
{
  Blynk.run();
  timer.run();
}

void digitalClockDisplay()
{
  bool result = Blynk.connected();
  if (result) {
    //設定每一位燈號顯示的內容,參數1:燈號,參數2:顯示的數字
    tm1637.display(0, hour() / 10);
    tm1637.display(1, hour() % 10);
    tm1637.display(2, minute() / 10);
    tm1637.display(3, minute() % 10);

    //顯示時和分之間的:,如果目前是顯示,就設定下次不顯示
    if (point_flag) {
      tm1637.point(POINT_OFF);
      point_flag = 0;
    } else {
      tm1637.point(POINT_ON);
      point_flag = 1;
    }
  }
  else {
    tm1637.display(0, 0);
    tm1637.display(1, 0);
    tm1637.display(2, 0);
    tm1637.display(3, 0);
    tm1637.point(POINT_ON);
  }
}

上面的程式中每1小時會自動更新一次RTC時間,當硬體斷線後則會顯示00:00的畫面提示,同時中間的":"符號則會間隔1秒點滅,以模擬時鐘的樣子。如此一來這個時鐘就可以永遠不用調整(除非WIFI斷了或Blynk伺服器收掉了),而比較美中不足的地方是,這個時鐘沒有顯示到秒的單位。

下一次我嘗試使用LCD1602來製作顯示日期、時間的樣式,順便試試看能不能透過Terminal工具將一些字句顯示在上面,做一個小小的留言板。

Blynk雲端平台的Time input工具-像鬧鐘一樣自訂時間、星期與時區



在Blynk雲端平台中,Time Input工具Timer工具有異曲同工之妙,更可以說是Timer工具的加強版。這次介紹的這個工具可以自行設定開始與結束時間(或日出日落)、星期以及時區,同時也支援12小時或24小時制的設定。

在設定頁面的部分,它只需要一個虛擬引腳即可,同時你也可以放置多組的Time input工具,Format則可以選擇你要12小時或24小時制(HH:MM and HH:MM AM/PM.)。



而下面這些選項則可以讓你選擇更多的時間設定,例如:
ALLOW START/STOP INPUT:是否要開啟開始與結束時間,如果不開啟的話就只會有一組時間而已(程式內定為START)。

ALLOW DAY OF WEEK SELECTION:是否要開啟星期的設定。

ALLOW SUNSET/SUNRISE SELECTION:是否要開啟日出日落設定,這個功能可以讓時間傳送的字串變成SUNSET或SUNRISE,如果要做一個透過日光(光強度模組)啟動的窗簾or鬧鐘,這是不錯的選擇。

ALLOW TIMEZONE SELETION:是否開啟時區設定




單純看設定介面不太能理解它的功能,讓我們實際依照官方所提供的三個範例來試試看。
首先是第一個範例Simple Time Input for start time

在這個範例中,它會採用3600 * hours + 60 * minute的格式來輸出時間,這個時間是用在上述星期、時區等功能全部關閉的情況下,僅只有單一時間的設定時,此功能會把你所設定的時間列印在序列上,要注意的是APP裡面的Format,無論是12小時或24小時制都是傳送3600 * hours + 60 * minute的格式。另外就是它只會在更改參數後才發送時間的設定數據(因為BLYNK_WRITE(V1))


第二個範例的功能就多上許多,它能夠進一步支援各種設定,例如開始、結束時間、星期的選擇與時區的選擇。幾個關鍵的程式碼如下:Sketch: Advanced Time Input


t.hasStartTime() 有無開始時間(True or False)
t.getStartHour() 開始時間小時
t.getStartMinute() 開始時間分鐘
t.getStartSecond() 開始時間秒
t.isStartSunrise() 是否開始時間設定為日出時間(True or False)
t.isStartSunset() 是否開始時間設定為日落時間(True or False)

t.hasStopTime() 有無結束時間(True or False)
t.getStopHour() 結束時間小時
t.getStopMinute() 結束時間分鐘
t.getStopSecond() 結束時間秒
t.isStopSunrise() 是否結束時間設定為日出時間(True or False)
t.isStopSunset()) 是否結束時間設定為日落時間(True or False)

t.getTZ() 時區名稱(時區區域名稱請參考)
t.getTZ_Offset() 時區的時間偏置,例如Taipei時間就是GMT+8(3600*8=28800)
t.isWeekdaySelected(i) 星期是否有被選擇(1~7),輸出一樣是True or False

虛擬引腳在輸出的參數為:(開始 結束 時區 星期 時區時間偏置)
28800 61200 Asia/Taipei 1,2,3,4,5 28800


最後一個範例則是透過程式碼,去改變APP內Time input工具的時間(You can also change state of widget on UI. See below sketches.),範例Update Time Input State on UI

//0 - min, 86399 - max
int startAt = 5 * 60; //設定開始時間,範例為00:05
int stopAt = (60 + 5) * 60; //設定結束時間,範例為01:05
char tz[] = "Europe/Kiev"; 時區設定,更多的區域請見此
Blynk.virtualWrite(V1, startAt, stopAt, tz);  複寫APP內工具的時間(日期全不選)

//you may also pass day
//char days[] = "1,2,3"; //Monday, Tuesday, Wednesday
//Blynk.virtualWrite(V1, startAt, stopAt, tz, days);  這裡會加上複寫星期的功能

這個運行後當硬體連接上伺服器,就會自動將你APP內的Time input複寫成硬體內所設定的時間(如下圖),透過這個工具也可以做一個雲端與硬體都可以修改時間設定的模型。


這個工具搭配上RTC工具,我們可以做一個具有自動更新時間及定時鬧鐘提示的多功能雲端智慧時鐘。現在比較困擾我的是時間必須要在APP的時間修改後才會"發送",如果今天硬體端停電後,該如何重新跟伺服器取得所設定的鬧鐘時間,這個工具似乎是直接從APP端傳送至硬體,而沒有傳到伺服器保留的功能,因此並不像RTC工具那樣可以從伺服器獲取上傳的時區資訊。

這個工具在撰寫程式時需要細心一點,考慮到斷線或是裝置重啟的問題,我想還要視情況採用。

Blynk雲端平台的RTC工具-讓開發板線上更新實時時間



在Blynk雲端平台中,Real-time clock(RTC)能夠從伺服器中獲取當前的時間,因此不需要在硬體上外接時鐘模組(例如DS1302之類的)來進行時間的運算,同時這個工具也能夠設定你指定的時區去同步時間。

這個工具的設定不需要任何虛擬引腳(Virtual Pin),只需要指定你所需要的時區(timezone)即可。接著燒錄官方提供的程式碼到硬體端,當硬體啟動時會自動抓取伺服器上的時間。這個工具的特色是只要有新增在APP中,並運行過一次(APP端離線也沒關係),Blynk的伺服器就會記住你設定的時區,並告訴你的硬體目前的時間。要注意的是如果移除RTC工具,Blynk的伺服器就不會提供RTC的時間給硬體,這時硬體就會從1970年1月1日開始計算,請參考UNIX時間


接著我們在APP中在新增一個LCD工具,並在SIMPLE模式中設定[0]為V1;[1]為V2,這個是範例程式碼中,會發送時間與日期的虛擬引腳。

// Send time to the App 
Blynk.virtualWrite(V1, currentTime); 
// Send date to the App 
Blynk.virtualWrite(V2, currentDate); 



如此一來運行後就可以看到即時的時間在LCD工具上面了。


同時我們也可以打開序列視窗,可以看到時間也同時發送在上面。


這個工具可以讓我們簡單的做一個實體的RTC時鐘。然而這個程式是不是僅止於RESET時讀取RTC時間我不得而知。因此我必須要在程式碼的初始階段(void setup)的rtc.begin();程式碼後加入一個setSyncInterval(Second)的程式碼(參考這篇文章),這個程式碼可以讓硬體定時的上線去更新時間,可以在Second中指定更新的間隔,如此一來才能達到及時同步的效果。當同步時完成序列會跟著顯示[142079] Time sync: OK的提示。

之後有一個小目標是能做一個時鐘,同時顯示溫溼度與PM2.5和當前時間,放在床邊做一個雲端居家監控系統與時鐘(還可以做鬧鐘喔)。

最後建議在程式的timer.setInterval(10000, clockDisplay);其數值不要設定的太小,不然似乎會出現斷線的現象(這一點尚待驗證就是)。

Blynk雲端平台的Email工具 按個按鈕自動發一封email



使用Blynk雲端平台的PUSH Notification推播工具製作居家安全防盜提示的文章中,我使用Notification工具去發送按鈕的觸發通知。而我今天要使用Blynk中的Email工具來測試按鈕觸發後,會寄送mail到指定信箱的功能。



基本上在程式碼中,這個工具跟Notification工具很相似。程式碼分成三個區塊,分別為寄件人、主旨、信件內容。官方的Email範例程式碼可以在這裡複製

Blynk.email("my_email@example.com", "Subject", "Your message goes here");

因此mail工具並不像Notification工具一樣,它不一定要在程式中置入一個mail的工具。它只要在程式碼中編譯一組指定的mail,當程式碼被觸發的時候它就會透過這個寄件人<dispatcher@blynk.io>發送信件。


但是如果要指定mail發送到APP中Email工具所登打的位置,那就把程式碼中寄件人的部份給省略掉就可以了,就像以下的程式碼,僅包含主旨與內文的部分,如此一來硬體就會抓取你Blynk APP裡面Email工具的信箱位置寄信:

Blynk.email("Subject", "Your message goes here");

唯一比較困擾的問題是,當我想和Notification工具一樣,嘗試使用中文內文來進行寄信,但是卻出現了亂碼。



而官方每天寄信的上限是100封,每封信間隔至少5秒以上(也不太可能這麼頻繁的寄信)。而信件的長度(使用英文),在我的測試下大概超過1000以上的字元(Bytes)會有無法傳送的現象,雖然官方說可以更改#define BLYNK_MAX_SENDBYTES來改變可傳送的大小,但我測試1200Bytes就無法傳送了,這個要自己實驗看看。

如果需要發送到許多的信箱,可以使用間隔時間的傳送方法,避免5秒內寄多封信被擋的問題,可以參考這個討論串。Multiple email address in email widget

這個功能相較於Notification,好像實用性上少了許多,但想一想它其實可以做一件事,好比在每天早上寄一封mail給你,告訴家裡目前的溫濕度、PM2.5數據,或是在下午寄一份儀器的監控報告,這個工具的實用性就得靠自己去發想了。

舉例我就用光敏電阻模組,接上NodeMCU的AD腳位,當按下按鈕時就會發送光敏電阻的數值到信箱內,我覺得比起單純文字,搭配數據發送的mail會更加有意思。

if (isButtonPressed) // You can write any condition to trigger e-mail sending
{
    int sensorValue = analogRead(A0); // Read the analog in value:
    String thisString = String(sensorValue);
    Serial.println("Button is pressed."); // This can be seen in the Serial Monitor
    Serial.println(sensorValue);
    Blynk.email("Your mail", "Blynk email test by MardDIY", "The sensor value is:(" + thisString + ")");
}

Blynk如何在單一專案中執行多個裝置



介紹了許多的Blynk工具之後,總會想到各式各樣能夠應用的地方,可以做個雲端電鎖、溫溼度監控裝置、PM2.5監測儀、電燈泡開關、門窗警報器等等,但是一個家中這麼多個裝置,該怎麼樣在單一Blynk介面中呈現呢? 這時候我們就要使用多裝置連線了。

如果不熟悉單一裝置的點燈或是Blynk的燒錄、安裝可以先參考以下文章:
利用NodeMCU透過Blynk APP建立雲端開關點亮LED燈
製作ESP8266-01燒錄器並透過Blynk APP點亮LED燈


在Blynk APP中多裝置連接是相當容易上手的功能(Control of multiple devices),我們只要在專案的設定頁面中新增就可以了。在專案設定的My Devices中進行硬體的新增,就可以增加新的裝置了。同時在新增裝置時Blynk也會產生一組新的Auth Tokens,這就是屬於這組裝置的ID碼,在燒錄時務必進行修改,可別搞混裝置了。



而下面的Tag功能更是有趣,它能夠將許多裝置設為一個"群組",因此我可以設計一個開關同時打開多組裝置,舉例我將MarsDIY1~2設為1F的標籤,MarsDIY3~5則為2F的標籤。



在進行多裝置的新增之後,在工具中會出現TARGET的選項,詢問你該工具是要用來操控哪一個裝置,如果沒有Tags群組的話就只能選擇單一裝置。



但是我們可以在工具的指定裝置選項中看到,Tags可以讓多個裝置綁為一組進行操控。



當然這個功能看似方便,但是在使用上要更加的注意,不要搞混了裝置之間的用途或接腳位置,導致後面Debug的困難。而且建議是同一種開發板比較合適,畢竟這樣引腳之類的才相同,不然就是要用虛擬引腳Virtual進行程式的設計來指定特定功能。



但是Tags的功能對於學習階段的我來說有點太多,所以我還是先以指定單一裝置為主。在設定好之後運行,可以發現上線的裝置會變成兩個(如果不正常要檢查一下Token是不是搞混),我要用來操控ESP8266-01與NodeMCU上面的板載LED燈,測試後效果非常非常的不錯,反應速度也沒有因為多裝置而變得遲鈍。



透過這個方法我們不需要分成好幾個專案來執行多裝置的控制,搭配上Tabs工具更能清楚的分類不同的工具與裝置關係,讓雲端家庭的功能能在一個介面中就搞定。


另外Blynk還有多手機操控單一裝置的功能,但因為我現在手邊只有一支手機,所以就等有機會再進行測試了(而且它要花費1000的能量點數,這個動作還不可逆)。Blynk這個APP真的越玩越覺得它真是思考周到,該有的功能都有,同時又做的不會太複雜,讓我這個不太會寫程式的人也能輕鬆使用雲端工具。

使用Tabs工具讓Blynk APP主畫面多一些空間


在使用Blynk APP中,有時候總會覺得它的介面實在是太小了。於是貼心的Blynk也替大家想到了這個問題,因此設計了一個Tabs工具。

這個工具跟程式碼其實沒有什麼關係,單純只是把原本單頁的APP介面拓展到4頁之多(Android系統甚至可達10頁),重點是這個工具還不需要消耗能量就能使用。

在設定頁面中可以發現這個工具沒有任何的虛擬引腳或開關等等,它就只是一個單純的標籤頁,你可以設定2~4組標籤頁,而向左滑則可以進行刪除標籤的動作。



在專案的主畫面中,點選每一個標籤就是一個頁面,因此我們可以透過這個裝置來改變不一樣的配置,好比Blynk可以在一個專案中使用多組硬體(之後會測試),這樣我們就能夠利用標籤來分類不同的空間或裝置,同時也不會讓整個介面看起來很撩亂。





而刪除時它只會保留第一個標籤的內容,其餘的會跟著一起刪除,這一點要特別的注意。




嘗試了許多Blynk的工具之後,接著有機會來玩看看多裝置在單一專案中的運作。

使用Blynk雲端平台的PUSH Notification推播工具製作居家安全防盜提示



Blynk APP雲端平台讀取按鈕狀態這篇文章中,我使用ESP8266-01讀取上面連接GPIO 0的按鈕狀態。然而在讀取硬體裝置狀態的變換時,不可能依賴人去無時無刻的盯著,如同居家保全系統會在家中門窗開啟時發送通知到你的手機一樣,因此Blynk中的Push Notifications工具,可以說是專門為了這個功能所設計出來的。

在Push Notifications工具中僅有兩個選項,一個是Notify When Hardware Goes Offline,另外一個則是Priority。
前者的功能如果開啟時,當硬體端離線的時候系統會發出警告,而它也能設定離線過後大概幾秒後提示,如果在離線的時間小於這個秒數,則不會提示出離線警告(可能是避免過於敏感)。
後者則是選擇推播的速度,選擇HIGH的話會在觸發的當下馬上推播(大概像人家傳LINE給你的速度),但是後者LOW模式的推播延遲時間其實我並不太知道,官方網站給了這個頁面去解釋兩者的差異,另外也警告說選擇HIGH的模式的話手機端會比較耗電一些(因為頻繁的進行連線更新),這點要自己進行取捨。



官方在這個工具也有提供相關的範例程式,它一樣使用按鈕觸發,並且使用了GPIO 2的外部中斷腳。在這篇博客中也提到ESP8266的中斷能連接到除了GPIO 16以外的任何GPIO腳位,詳見WiFi-ESP8266入门开发(十二)-使用GPIO中断。因此承襲上一篇雲端平台讀取按鈕的文章,我把GPIO 2改成了GPIO 0,以對應我開發板上面的按鈕。

同時在Blynk的介紹中,這個工具是支援UTF8 Unicode格式的,舉例我使用Windows版的Arduino IDE 1.8.5編譯器,在程式中打入下面這串文字,程式是能夠成功編譯並燒錄的,官方也有解釋說如果沒辦法編譯的話可能就是編譯器的支援問題。
Blynk.notify("家裡被闖空門了!");



而我選擇HIGH的推播頻率,大概在按鈕觸發後2秒內就推播到我的手機了,並且顯示了我燒錄的"家裡被闖空門了!"的設定文字。



在離線通知的部分也是一樣有效,只是我選擇Instant的推播時間,卻大概過了半分多鐘才顯示,是說這個時間也還在能接受的範圍內就是了。



另外需要注意的是在通知的文字長度部分,Blynk的伺服器提供了128 Bytes的長度,如果使用中文字的話會比較消耗空間,如果有字串長度上的疑慮,可以使用UTF-8 string length & byte counter這個試算工具,貼上你要撰寫的文字它會自動幫你計算字數以及Byte長度。
(只是我在實際使用上400多Bytes也是照樣傳送過去就是了,並沒有發生截尾的現象,這個可能就要自行嘗試看看了。




另外Blynk官方在本文的範例中使用了內部上拉電阻開啟的程式碼。
pinMode(2, INPUT_PULLUP);

因此我查詢了一下ESP8266這個晶片的內部上拉電阻資訊,在小狐狸事務所-MicroPython on ESP8266 (八) : GPIO 測試的文章中找到,ESP8266 每一個 GPIO 腳都有內建上拉電阻。知道了這個資訊之後我就不需要另外再接外部電阻了,在使用上方便許多,開啟內部上拉電阻後只要按鈕連接GPIO與GND就能進行工作了。(只是要注意不要用到已經有連接板子上LED燈的引腳)

如此一來我們就可以購買門磁開關,並且將它接上雲端開發板,當門開啟時會導通or斷開,利用這種方法就可以製作門窗的雲端防盜器了,並且在第一時間收到資訊。

而Blynk的官方範例程式中還有一個Push Notification Interval的範例,這個範例會每60秒發送一次通知到手機,告訴你裝置已經開啟多久了。這個功能可以用在數據的定期提示,但我覺得已經有SuperChart工具了,就不太需要這樣子定期提示就是。

最後記得要有推播提示,APP專案的運行按鈕一定要按下去,不然提示功能沒有用,這一點相當重要務必牢記。