2022年2月9日 星期三

零基础入门学用Arduino-基础知识篇 - 重點記錄

零基础入门学用Arduino-基础知识篇 - YouTube  

本篇學習完畢,接下來進入零基础入门学用Arduino-MeArm机械臂篇 - YouTube

重點記錄:

2022.02.09

  • 全部成本大概台幣兩百元,裝在犀牛盾保護殻的包裝外盒實在有點醜,隨手弄了個封面:

2022.02.08

  • 今天要 Flash ◄A08► 基於ESP8266(或8255) NodeMcu Lua WIFI 開發板 CP2102 | 蝦皮購物 的 Firmware 才發現它無法連接的原因,原來是這個小轉接頭的關係,把 USB 延長線直接插在 Mac mini 的 USB 上,與 Arduino IDE 的連接沒問題,於是把時鐘換上它,程式上傳後執行也無誤,就用熱熔膠把插線接頭處固定,然後裝在犀牛盾保護殻的包裝外盒裡,留下來做記念。

2022.02.07

  • 麵包板及另購的◄A08► 基於ESP8266(或8255) NodeMcu Lua WIFI 開發板 CP2102 | 蝦皮購物到貨,才發現與早些時候買的 NodeMcu Lua WIFI 開發板 基於 ESP8266 wifi模組 無線開發 物聯網 無線傳輸 無線模組 | 蝦皮購物 是不一樣的,後者較寬,插上麵包板後無法引腳出來,前者較窄,才能上下各留一排插孔能夠插線:

  • 結果 NodeMcu Lua WIFI 開發板 CP2102 (上圖右較窄的那塊)在 Arduino IDE 無法連接:

  • 即使去下載了 Driver :CP210x USB to UART Bridge VCP Drivers - Silicon Labs 安裝後仍無法連接,進一步 Google 後,從這篇文章:NodeMCU/ESP8266 - Getting Started with Arduino IDE on macOS | by basspj | Medium 大概還需要 flash firmware 才能使用(等以後有需要時再來處理),只好改使用 V3.0 的另一塊較寬版,但無法插在麵包板上,因此以 F-M 杜邦線直接連 ESP8266 的接腳。

  • 先叫出 Arduino IDE 裡 ESP8266 的 NTPClient 範例來了解如何改寫程式碼,有點複雜,Complier 都過不了,於是上網查,沒想到查到這篇文章:Getting Date & Time From NTP Server With ESP8266 NodeMCU ,不用了解 NTP 的原理,在 Arduino IDE 裡再多加個 NTP Client Library,把文章裡的範例拷貝過來,簡單修改一下就完成時鐘程式—很準確的時鐘(還有個不完善的地方就是沒有隨著秒跳動的 ""),因為能夠透過 WI-FI 連上 NTP 伺服器即時校正時間

  • 程式碼:
     
    #include <NTPClient.h>
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    
    const char *ssid     = "YOUR_SSID";//此處改為家裡基地台的 SSID
    const char *password = "YOUR_PASS";//輸入登入基地台的密碼
    
    const long utcOffsetInSeconds = 28800;//台灣在 UTC+08:00 時區,所以 8*60*60 = 28800
    
    char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
    
    // Define NTP Client to get time
    WiFiUDP ntpUDP;
    NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
    
    // 以上是從範例程式拷貝過來的程式碼
    
    const int dataPin  = D5;  // Arduino 原先 12 腳位對應 74HC595 pin 8 DS    // 以shiftOut(dataPin,clockPin,MSBFIRST,Val)
    const int clockPin = D6;   // Arduino 原先 9 腳位腳位對應 74HC595 pin 10 SHCP // 儲存 8 bits 資料後
    const int latchPin = D7;  // Arduino 原先 11 腳位腳位對應 74HC595 pin 9 STCP  // 給予高電位後把上述資料 Out 到七段顯示器
    const int digit0   = D1;   // Arduino 原先 7 腳位腳位對應 7-Segment pin D4    //
    const int digit1   = D2;   // Arduino 原先 6 腳位腳位對應 7-Segment pin D3    // 控制要顯示的位數
    const int digit2   = D3;   // Arduino 原先 5 腳位腳位對應 7-Segment pin D2    //
    const int digit3   = D4;   // Arduino 原先 4 腳位腳位對應 7-Segment pin D1    //
    
    //以上因改用 ESP8266 後,腳位名稱也須跟著改變
    
    //以下程式碼與前述所附完全相同,不再附上
    ...
    ...
    ...
    .
    .
    .
    .
    .
    //簡單修改 void loop() 即完成準確的時鐘程式
    void loop() {
    
      timeClient.update();
    
      int hourntp = timeClient.getHours();
      int minntp = timeClient.getMinutes();
      int sensor_value = hourntp * 100 + minntp;//配合之前寫的程式 hourntp * 100 後得到千位及百位
    
      seven_seg(sensor_value);
      delay(1);
      }
    
  • 這支影片純欣賞:

  • 如果也想做做看,這裡也有作者的教學:

2022.02.04

  • 訂的麵包板還未到貨,ESP8266 無法接四位七段顯示器,加上花上不少時間好不容易接好的 74HC595 線路捨不得拆掉,於是把原先接在 Arduino 上的接線改接到擴充板上,將 Arduino 空出來,加上小塊的麵包板,剛好用來把買來的套件其他小配件做個驗貨:
    • RGB LED 燈:
    • 定時炸彈???小心,不要碰!!!
    • 小小的一顆傾斜感測器如下圖(Tilt sensor) 光碟內附的範例實在單調無聊,就拿來與前面已接好的四位七段顯示器組合,程式加入倒數的功能,而這個倒數則是偵測傾斜感測器是否動到來觸發。四位七段顯示器 + 74HC595 複雜的線路,看起來就像電影裡的定時炸彈一樣,不小心動到就開始倒數計時。
2022.02.03
  • 年初三,又下雨了,加上全家物流爆發群聚感染,蝦皮下訂的麵包板因為使用全家取付大概得等好一陣子, ESP8266要接上就再說了(因為電路上使用了 74HC595 可以節省腳位,所以 ESP8266 取代 Arduino 應該是可行的)。只好繼續玩其他的感測器,像是超聲波傳感器。
  • 接上 Ultrasonic Sensor Module,只要接腳沒弄錯,函數引用正確,就可以正確顯示:

  • 只是問題還是存在,最右邊位數還是最亮,其他三位數為了不閃爍,把 Dtime 設為 1 後變太暗了。起先還懷疑是線路的問題,但把Lesson 28 - 4 Digit 7 Segment Display - YouTube 附的範例上傳後,四個位數的亮度一樣,顯然自己按 Arduino - 4-Digit 7-Segment Display (EN) - YouTube 建立的程式有問題,應該是處理 Multiplexing 的程式結構部份,只得進入寫程式最傷腦的 Debug 模式……
    • 檢視之前錄過的影片,接可變電阻那支影片並沒有出現最右邊的數字過亮的情形,而是四個位數都一樣,這意味著按Arduino - 4-Digit 7-Segment Display (EN) - YouTube 建立的程式並沒有問題,有可能就出現在 DHT11 溫濕度模塊、超聲波傳感器於讀取數據時出了問題。
    • 總算找出問題所在,不是DHT11 溫濕度模塊、超聲波傳感器讀取數據的問題,而是程式seven_seg()函數的最後加入關掉四個數字的顯示即可:

    • 現在四個數字的亮度一樣了,剩下就是等電阻包到貨,把 5KΩ 換成 4.7KΩ 後,亮度應該就能提升:

  • 2022.02.03

  • 邏輯只要通了,後續大概就沒問題,拿掉可變電阻,換上同樣三隻腳位的 DHT11 溫濕度模塊,程式稍為改一下就能顯示溫度(因為顯示器位數只有四位,所以只叫用溫度的數據):

    • 先把光碟所附的 DHT11 函數庫加入 Arduino IDE 裡。
    • 叫出 DHT11 範例程式,把這段拷貝到自己的程式裡:

    • 四位數的左邊兩位顯示溫度,右邊兩位數則固定顯示℃:
      • 由於線路接法排列改變:

      • 所以要顯示度,需要點亮 ABFG(如下圖),由上圖的排列得到二進位 1000 0111 ,換算成十六進位為 0X87:

      • 需要自行在數字陣列再加入,由於是固定顯示,seven_seg()直接給固定值:

      • choose_digit()裡也要加入:

  • 直接拷貝 DHT11 範例程式是可以顯示出溫度,但是會閃爍地很厲害,花了不少時間才找出原來是 DHT11 的更新頻率為 1 秒 1 次(1Hz),程式碼放在 Void Loop()才會出問題,因此移出,獨立成一個函數,讀取感測器資料返回溫度數據:

  • 這樣在 Loop()叫用後,顯示就不會有問題了(至於為何 seven_seg(tempA *100) 還要再乘 100,這是因為只有兩位數的溫度值傳入seven_seg() 函數時要顯示在千、百的位置):

  • 其實還是有點閃爍,把原為 5 的 Dtime 改為 1 ,不再閃爍了:

  • 不曉得為何最右邊的 C 特別亮?猜測可能是接在這個腳位的電晶體放大率與其他三個不同,又或者接在此腳位的電阻較小?
    • 四根接 NPN 電晶體的 5K Ω(原電路圖為 4.7K,電阻稍大,所以比較暗),經量測後都差不多,誤差也不大,應該不是它造成的。
    • 四根 NPN 電晶體拔下來以三用電錶量它們的 hFE 放大率,有三根差不多都在 270~280,只有一根為 160 ,將其換掉,改用一顆也是 270~280的,重新開啟,還是一樣!顯然 C 字母特別亮的原因也不是電晶體造成的,或許與整個電路有關,難解決,先不理它了。
2022.02.02

  • 看了許多遍 Lesson 28 - 4 Digit 7 Segment Display - YouTube 在GitHub 下載回來的原程式,始終無法完全弄懂,又礙於已接好他的線路,只好繼續礸研,特別是 shiftOut(dataPin,clockPin,MSBFIRST,Val) 這個函數,還是得請出 Google,找到這篇:Arduino中shiftOut怎麼用? - 台部落有著詳盡的解說,然後再看到這篇帖文:arduino中shiftOut()函数控制74hc595的的问题! - 求助区 - 极客工坊 - Powered by Discuz! ,突然豁然開朗,程式的思路其實很簡單,再度照著 Arduino - 4-Digit 7-Segment Display (EN) - YouTube 的流程把程式寫出,現在接上可變電阻,就可以把電阻值顯示在四位七段顯示器上,而且線路用的是Lesson 28 - 4 Digit 7 Segment Display - YouTube 改良過的,74HC595 用上了,所以在 Arduino 上用了較少的接腳:

  • 程式碼:
        
    const int dataPin  = 12;  // Arduino 腳位對應 74HC595 pin 8 DS    // 以shiftOut(dataPin,clockPin,MSBFIRST,Val)
    const int clockPin = 9;   // Arduino 腳位對應 74HC595 pin 10 SHCP // 儲存 8 bits 資料後
    const int latchPin = 11;  // Arduino 腳位對應 74HC595 pin 9 STCP  // 給予高電位後把上述資料 Out 到七段顯示器
    const int digit0   = 7;   // Arduino 腳位對應 7-Segment pin D4    //
    const int digit1   = 6;   // Arduino 腳位對應 7-Segment pin D3    // 控制要顯示的位數
    const int digit2   = 5;   // Arduino 腳位對應 7-Segment pin D2    //
    const int digit3   = 4;   // Arduino 腳位對應 7-Segment pin D1    //
    
    byte SW0 = A0;
    int Dtime = 5;
    
    byte Number[]=             //儲放數字值的陣列,由於作者重新排列過,電路也跟著配合,因此要沿用他的電路就必須採用。
        {   0x5F,  // = 0
            0x44,  // = 1
            0x9D,  // = 2
            0xD5,  // = 3
            0xC6,  // = 4
            0xD3,  // = 5
            0xDB,  // = 6
            0x45,  // = 7
            0xDF,  // = 8
            0xC7,  // = 9
            0x20,  // = Dp
            0x00   // blank
        };  
    
    void seven_seg(int TimeVal){
      
      unsigned char  n3 = int (TimeVal/1000); 
      unsigned char  n2 = int ((TimeVal/100)%10);
      unsigned char  n1 = int ((TimeVal/10)%10);
      unsigned char  n0 =  int (TimeVal%10);
    
      choose_digit(n3);
      pick_digit(4);
      delay(Dtime);
    
      choose_digit(n2);
      pick_digit(3);
      delay(Dtime);
    
      choose_digit(n1);
      pick_digit(2);
      delay(Dtime);
    
      choose_digit(n0);
      pick_digit(1);
      delay(Dtime);    
    }
    
    void pick_digit(int digit){
      
        digitalWrite(digit0,LOW);
        digitalWrite(digit1,LOW);
        digitalWrite(digit2,LOW);
        digitalWrite(digit3,LOW);
        
        switch(digit){
          case 1: digitalWrite(digit0,HIGH); break; 
          case 2: digitalWrite(digit1,HIGH); break;
          case 3: digitalWrite(digit2,HIGH); break;
          case 4: digitalWrite(digit3,HIGH); break; 
        }
    }
    
    void choose_digit(char num){
        switch(num){
          default:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[0]);
          digitalWrite(latchPin,HIGH);
          break;
    
        case 1:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[1]);
          digitalWrite(latchPin,HIGH);
          break;
        case 2:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[2]);
          digitalWrite(latchPin,HIGH);
          break;
        case 3:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[3]);
          digitalWrite(latchPin,HIGH);
          break;
        case 4:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[4]);
          digitalWrite(latchPin,HIGH);
          break;
        case 5:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[5]);
          digitalWrite(latchPin,HIGH);
          break;
        case 6:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[6]);
          digitalWrite(latchPin,HIGH);
          break;
        case 7:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[7]);
          digitalWrite(latchPin,HIGH);
          break;
        case 8:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[8]);
          digitalWrite(latchPin,HIGH);
          break;
        case 9:
          digitalWrite(latchPin,LOW);
          shiftOut(dataPin,clockPin,MSBFIRST,Number[9]);
          digitalWrite(latchPin,HIGH);
          break;
      }
    }
    
    void setup() {
        pinMode(latchPin,OUTPUT);
        pinMode(clockPin,OUTPUT);
        pinMode(dataPin,OUTPUT);
    
        pinMode(digit0,OUTPUT);
        pinMode(digit1,OUTPUT);
        pinMode(digit2,OUTPUT);
        pinMode(digit3,OUTPUT);
    
        digitalWrite(digit0,LOW);
        digitalWrite(digit1,LOW);
        digitalWrite(digit2,LOW);
        digitalWrite(digit3,LOW);
    
        pinMode(SW0, INPUT);
        digitalWrite(SW0, LOW);
        
    }
    
    void loop() {
    
      int sensor_value = analogRead(SW0);
      seven_seg(sensor_value);
      delay(1);
      }
    
  • 程式總算有了進展,至於要改用 ESP8266,則還欠一片麵包板才能把接腳接出來,已在蝦皮下訂,等貨到後看看能否改寫成上網取得 NTP 時間,換算成所在時區,然後再以四位數字送進上述的函數,每隔 24 小時更新一次 NTP 時間(或許 ESP8266 的函數庫有內建的自動更新函數),如此就能得到一個很準確的時鐘了。
  • 依照 Arduino - 4-Digit 7-Segment Display (EN) - YouTube 的流程把程式寫出後,只要傳一個四位數,就可以顯示在七段顯示器上,或許也可以把 DHT11 溫濕度模塊、超聲波傳感器接上來測試。

2022.02.01

  • 按照前面的思路,除非重新修改線路,試過了,都行不通,最後只得從Lesson 28 - 4 Digit 7 Segment Display - YouTube 在GitHub 的原程式下載回來改寫。
  • 把本為 16 進位計數器小改後成為十進位計數器,突然有個感覺,一堆線路加上一個計數器,不就像電影、電視劇裡壞蛋安放的炸彈一樣(如果改成倒數計數就更像了):

  • 把原為 50 ms 的Delay 改為 100 ms,這樣最右邊的位數以 0.1 秒跳動,右邊算過來的第二位就是 1 秒跳動。
  • 這樣的小改其實不算什麼,真正難的是很難搞懂原程式這段的寫法:

  • 改寫的核心就在這段,需要改成函數,內含一個引數可以接收一個四位數字,然後顯示在七段顯示器上,並計時以每秒更新數字。
  • 若能改寫成功,或許,加上 ESP8266 (甚至取代 Arduino Uno),上網取得 NTP 時間,換算成所在時區,然後再以四位數字送進上述的函數,就不需要再弄個設定時間的開關。最後每隔 24 小時更新一次 NTP 時間,如此就能得到一個很準確的時鐘了。

2022.01.30

  • YouTube 知道我現在對 74HC595 有興趣,打開後進入首頁,演算法就在首頁幫我找了好幾支相關的影片,其中這支影片:How Shift Registers Work! - YouTube 說明地最清楚詳細。
  • 完成麵包板上跳線的部分(接2N2222的 4.7KΩ以 5KΩ代替):
  • 全部接線完成,就算再細心的接線,還是有兩個地方接錯,上傳十六進位計數的範例程式,結果中間兩位數不顯示,原先以為是電晶體的問題,這是因為用了兩個 2N2222a及兩個 2N2222,但顯示正常的兩個位數,剛好是分別是 2N2222a及 2N2222,表示不是電晶體的問題。當然也不是換成 5KΩ 的問題,不然四個位數都不會亮。再仔細查找,原來是接錯孔位,修正後就成功了。由於計數到最後近四分鐘,所以只剪輯的前後的部份才不會太長(影片中有三個開關的小麵包板是未來要加上的):

  • 接線沒問題了,所以接下來拷貝十六進位計數的範例程式的開頭程式碼(定義腳位及顯示數字的部份,因為用的是他的電路圖),再以Arduino - 4-Digit 7-Segment Display (EN) - YouTube 的方式來編寫,最後參考 How to Make a Arduino Digital Clock : 5 Steps - Instructables 的電路(如下圖),加上三個開關來設定時鐘的時間,同時也改寫他的時鐘程式碼,寫成一個函數。或許還能自行建立一個函數庫,除了時鐘的顯示,像是溫度、距離……等等感測器讀取的值都可以叫用並顯示在七段顯示器上。(或許網路上也有各種感測器的函數庫可以下載,只要電路搭建好,函數叫用讀取即可顯示了。

2022.01.29

決定開始來接線路及改寫程式:

  • 電路決定使用 Lesson 28 - 4 Digit 7 Segment Display - YouTube 的電路圖,也順便學習 74HC595 (網路查到一顆也就不過四、五元),所以串接多個時也不傷財,重要的是可以節省 Arduino 的腳位:


  • 若能改寫成功,是否要 3D 列印個外框呢?那就不必了,淘汰的手機下載個時鐘 app 就比這個棒很多,這只是學習的一個過程而已。

2022.01.28

  • 把教學光碟的電路接好,以內附的範例程式來檢查是否有接錯。接好後,改了一點程式碼,上傳後測試沒有問題:

  • 開始去讀程式碼後,問題就來了,也是燒腦的開始。如下圖,程式碼定義顯示數字的陣列,陣列裡的值與說明書裡列出的值怎麼對都對不上,難道是 74HC595 IC的關係?

  • 查了 74HC595 的規格 ,第一頁就看到 shift register 這個詞,難道是值需要 shift

  • 然後以「Four Digital Seven Segment Display with 74HC595」為關鍵字查到這支影片:Lesson 28 - 4 Digit 7 Segment Display - YouTube,並下載了作者在 Github 的程式碼及各項資料:GitHub - rmorenojr/ElegooTutorial: Elegoo tutorials - revised sketches and diagrams for each Elegoo Lesson,內有一個 Excel 檔,開啟後才知道原來套件附的教學光碟說明書那個表格是錯誤的

  • 這才又讓我想起說明書隨便挑了個 RGB Led 說明就看到明顯的錯誤(圖與文字說及後續的電路接法相反):

  • 看來套件附的教學光碟說明書其他的部分想必也是錯誤很多,下次參考時要多加小心。
  • 由於Lesson 28 - 4 Digit 7 Segment Display - YouTube 的接法是 74HC595 還要再接四個 PN2222 transistors,但買的套件只有兩個,等有時間時再上電子街買(露天一顆 10 元,網購免運又有低消),當下先把影片的內容搞懂。
  • 目前的理解是影片的作者把教學光碟說明書的電路圖說成是垃圾,無法控制四位數字各別顯示,所以他改了電路圖,加了四顆 PN2222 當成可控制的開關來各別顯示數字,也附了計數的範例程式碼,等零件齊了後再來測試。
  • 下午去廣華買了五顆 2N2222(使用上與 PN2222 同樣,查網路說還比較貴,也問了元華,沒有 PN2222),拿回後在放大鏡下仔細看,竟然有三顆是 2N2222a ,兩顆是 2N2222,以三用電錶量 hFE, 2N2222 約 230 倍, 2N2222a 約 260 倍,套件裡的 PN2222a 約 153倍。因此在這個 Project 只能使用兩顆 2N2222a 及兩顆 2N2222 。
  • 對於增加的四個 NPN 電晶體,首先要搞清楚 EBC 三根接腳,用三用電錶量,找出後才發現網路找到的圖就有了:把印字平的部份面向自己,最左是 E ,中間 B,右邊 C:

  • PN 2222 也一樣:

  • 電晶體的原理老早還給老師了,找到這篇:把電晶體發動! @ 老音響資料庫/蘇桑部落格 :: 痞客邦 :: 複習一下。
  • 買這個套件並非要玩樂高一樣,把接線依樣畫胡蘆,上傳程式可以運作就了事。這樣不算學習,尤其是若要改寫程式,勢必非得懂程式不可,把 Lesson 28 - 4 Digit 7 Segment Display - YouTube 仔細看了幾遍,現在零件也齊全了,但並不急著接線,因為附的範例程式對於 74HC595 不夠了解,看了 Lesson 27 - 74HC595 and 7-Segment Display - YouTube 還是不行,才又再找到這支影片:Lesson 24 - 74HC595 Shift Register - YouTube ,等徹底了解後再來實際連接電路並改寫程式碼。
  • 關於 74HC595 的學習可以按底下順序來研究:

2022.01.27

  • 真是「踏破鐵鞋無覓處,得來全不費工夫」,在蝦皮買的套件所附教學光碟的說明 PDF 裡就有共陰四位七段顯示器的電路圖,這下子要完成時鐘程式的改寫就向前邁進一大步:


  • 前面雖已發覺錄製影片要使用 24P 的格式,但對於以 SONY A7s + Tamrom 90mm F2.8 微距鏡(早期底片時代的老鏡) + Atomos Ninja Flame ,以 S-Log2 格式錄製, 格式 4K 24P , ISO 3200,光圈 F4 ,快門 1/25 秒或 1/50 秒,加上可用光源(也就是抬燈調到最亮,盡量靠近目標,讓整個場景的亮度能夠趨於一致,但 Led 最亮時還是會過曝,顏色還是跑掉),想到可以使用可變 ND 濾鏡,才能在使用 ISO 3200 起跳的 S-Log2 格式時,光圈不用調得太小且快門能以 1/25 秒或 1/50 秒錄製,這樣紅色的 LED 燈才比較接近肉眼看到的顏色(還是沒有眼睛看到的紅)。
  • 這支影片是以 1/25 秒拍攝:

  • 這支影片是以 1/50 秒拍攝:

  • 在玩 DJI mini 2 空拍時看到的教學影片都說快門速度要錄製格數的兩倍,即錄 24P ,快門最好設在 1/50 秒,但上述兩支影片或許是木眼,實在看不出有何差別,有可能因為空拍是動態的,而這些影片是靜態錄製的關係才會沒有影響。

底下為先前的記錄,後續的記錄以日期排序,日期新的在前面,如之前學天文攝影的「觀測日記」一樣。

  • 關於發光二極體(LED):因為可通過的電流很小,這就是為何使用時要串聯電阻的原因,使其分壓約在 2V 左右。



二極體abcdefg
Arduino腳位3478965
數字0123456789
二極體abcdefbcabdegabcdgbcfgacdfgacdefgabcfabcdefgabcdfg
Arduino腳位34678947345893457845673567835678934673456789345678
字母AbcdEF
二極體abcefgcdefgdegbcdegadefgaefg
Arduino腳位3456795678958945789356893569
  • 在練習零基础入门学用Arduino-基础知识篇-19 MC猜数字 - 1 电路搭建 - YouTube 時,照著影片的接法,LED 燈始終不亮,這才發現蝦皮買的套件裡的麵包板上下兩排是分成兩半的,兩支接地線不能分在兩邊。為了以後使用上的方便,需要再購買短跳線,如下圖的方式固定下來:
  • 在接好 MC 猜數字的電路後,把 final 的範例程式上傳到 Arduino Uno 後,執行卻有問題,只能跑一次,無法像影片示範,可以一直執行。起先還以為是擴充板的問題,拆掉重接還是一樣,難道是Arduino Uno 板子的問題(用的是開發版),最後花了不少時間才解決(版子沒問題,擴充板也沒問題,是範例程式碼有點小問題)
    註:原程式碼顯示隨機圖案,是為了混淆注意力,讓隨機圖案顯示時間由慢到快到慢,自己則再增加一段由慢到快的程式碼,更能增加混淆。
  • 這次的影片不再使用手機拍攝,改用 SONY A7s + Tamrom 90mm F2.8 微距鏡 + Atomos Ninja Flame ,以 S-Log2 格式錄製, Final Cut Pro 快速剪輯:

  • 蠻有成就感的,於是使用 fritzing For Mac,用心地畫出來:

  • 再嚐試把電路也調整好(初始很亂):

  • 有了這個練習,還能找到程式碼裡的小 Bug,對理解程式就有點信心。想到套件裡有個四位數的七段顯示器,不就可以用來當成時鐘用嗎?就當作一個挑戰吧!
  • 首先要了解四位數的七段顯示器的規格,這可以從套件附的 CD 找到它是共陰的。
  • 這篇文章:葉難: Arduino練習:四合一的七段顯示器 有接腳的說明及範例,但作者沒有加電阻,照抄連接怕燒壞顯示器。
  • 這篇文章:mBlock & Arduino(17)四位數七段顯示器 就有電阻的接法:

  • YouTube 看了相關的幾支影片,最後選定這支影片的方式來練習:How to make Digital Clock with 4 Digit Seven Segment Display - YouTube
  • 下載了上述影片附的程式碼,一開頭就說明程式適合共陽四位數的七段顯示器,但影片電阻的接法與前述文章的接法一樣,於是先以影片說明的接線方式接好線及電阻,上傳程式碼,結果顯示得亂七八糟,按鈕也沒作用,顯然程式不適用於共陰四位數的七段顯示器
  • 改以mBlock & Arduino(17)四位數七段顯示器 的接線方式,但上傳的是葉難: Arduino練習:四合一的七段顯示器 的範例程式,顯示有問題,再仔細比較兩篇文章的接法是不同,最後換成後者的接法,但保留了前者的電阻接法,以後者的範例程式再次跑過就沒問題了。
  • 好不容易試出來,雖然離完成時鐘還有不少路要走,還是值得留下記錄,拍段影片。由於是以 S-Log2 格式錄製,由於 ISO 3200 起跳,所以快門調成 1/60秒,無法錄下眼睛看到的情形,一直閃爍:

  • 葉難: Arduino練習:四合一的七段顯示器 提到「因為有4個七段顯示器,我們必須使用掃描的方式不斷地顯示每一個七段顯示器,只要掃描速度夠快,基於視覺暫留原理,人眼便無法察覺,以為所有數字皆為同時顯示。」,因此把快門改成 1/30 秒,才能錄下數字計數的情形(還是會閃爍,只是比較不嚴重):

  • 剛好有空改以 24P 錄製,閃爍的問題幾乎看不到:

  • 接下來的做法是以葉難: Arduino練習:四合一的七段顯示器 的接線方式,然後把 How to make Digital Clock with 4 Digit Seven Segment Display - YouTube 附的範例程式改寫,雖然共陰顯示器不適用,但時鐘顯示的流程應該都是一樣,讀懂程式的結構,或許就能改寫吧!就試試看囉!
  • 葉難: Arduino練習:四合一的七段顯示器 裡面的範例程式,是個高手,寫得太精簡反而難懂,反而How to make Digital Clock with 4 Digit Seven Segment Display - YouTube 附的範例雖然較長,卻比較好弄懂,只是他用的是共陽的四位七段顯示器,如何改接成共陰的電路,對一個完全的電路新手實在是一大考驗。
  • 畢竟不是電子本科,光一個共陽的電路要轉成共陰的電路接法,就想了兩天才想到可能可以解決的方法。四位七段顯示器,可以單獨用一個來想即可,而之前在零基础入门学用Arduino-基础知识篇-19 MC猜数字 - 1 电路搭建 - YouTube 已接過一位共陰七段的接法,再配合 Microsoft Word - ch8 七段顯示器實習.doc 裡面這段話的說明,應該有辦法接出來:


  • 雖然懂得物理,但沒有實際的電路基礎,只好土法煉鋼胡搞瞎搞,
  • 根據上圖的說明,把各段連接 220 Ω 限流電阻接+5V ,而D3、D2、D1、D0 任一腳接地,並拷貝一小段範例程式的程式碼來檢查接法是否正確:

  • 做法是上傳程式後,把接地線一一接到 D3、D2、D1、D0,看那個顯示器能夠點亮(程式碼應該是要顯示 0 ,結果卻反相,顯然給的電位剛好相反;少拍了一張圖。另,Blog 上傳的圖片每次都會順序顛倒,懶得再排序):



  • 改好後,可以正確顯示 0 (Blog 上傳的圖片每次都會順序顛倒,懶得再排序):




  • 但仔細觀察 D3、D2、D1、D0 的腳位與找到的資料是相反的:

  • 拷貝程式碼,讓顯示的數字為 5 :

  • 這次把 D3、D2、D1、D0 的腳位全部接地,程式上傳後四位數全亮 5 :

  • 至此,第一階段算成功了…….(沒有電路基礎,只能慢慢來,對於懂電路的人大概覺得很可笑吧
  • 進一步研究時才發現 How to make Digital Clock with 4 Digit Seven Segment Display - YouTube 他應該是引用這個人的做法,把四個一位數七段顯示器改成一個四位數七位數顯示器而已,原始作者的文章裡有詳細的說明:How to Make a Arduino Digital Clock : 5 Steps - Instructables ,值得後續好好研究。

  • 目前已能用一個開關,以第 10 Pin 腳來顯示不同數字:

  • 程式碼如下:
int segA = 2; //Display pin A
int segB = 3; //Display pin b
int segC = 4; //Display pin c
int segD = 5; //Display pin d
int segE = 6; //Display pin e
int segF = 7; //Display pin f
int segG = 8; //Display pin g
int segDP = 9;//Display pin dotint

//int digit1 = 13; //控制顯示那一個位數
//int digit2 = 12; //目前還不會用到
//int digit3 = 11; //
//int digit4 = 10; //

void setup() {
  Serial.begin(9600);
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);
  pinMode(segDP, OUTPUT);

//pinMode(digit1, OUTPUT);
//pinMode(digit2, OUTPUT);
//pinMode(digit3, OUTPUT);
//pinMode(digit4, OUTPUT);


}

void loop() {

#define SEGMENT_OFF  LOW
#define SEGMENT_ON HIGH

#define DIGIT_ON  HIGH
#define DIGIT_OFF  LOW

const int buttonPin1 = 10;
//const int buttonPin2 = 11;
//const int buttonPin3 = 12;


int buttonState1 = 0;
//int buttonState2 = 0;
//int buttonState3 = 0;


buttonState1 = digitalRead(buttonPin1);
Serial.print(F("buttonState1 Start =  "));
Serial.println(buttonState1);
 
//buttonState2 = digitalRead(buttonPin2);
//buttonState3 = digitalRead(buttonPin3);

if  (buttonState1 == HIGH)  {  
          digitalWrite(segA, SEGMENT_ON);//顯示數字 5
     digitalWrite(segB, SEGMENT_OFF);
     digitalWrite(segC, SEGMENT_ON);
     digitalWrite(segD, SEGMENT_ON);
     digitalWrite(segE, SEGMENT_OFF);
     digitalWrite(segF, SEGMENT_ON);
     digitalWrite(segG, SEGMENT_ON);
 }   else {
         digitalWrite(segA, SEGMENT_OFF);//熄掉數字 5
         digitalWrite(segB, SEGMENT_OFF);
         digitalWrite(segC, SEGMENT_OFF);
         digitalWrite(segD, SEGMENT_OFF);
         digitalWrite(segE, SEGMENT_OFF);
         digitalWrite(segF, SEGMENT_OFF);
         digitalWrite(segG, SEGMENT_OFF);
     
         digitalWrite(segA, SEGMENT_OFF);//顯示數字 1
         digitalWrite(segB, SEGMENT_ON);
         digitalWrite(segC, SEGMENT_ON);
         digitalWrite(segD, SEGMENT_OFF);
         digitalWrite(segE, SEGMENT_OFF);
         digitalWrite(segF, SEGMENT_OFF);
         digitalWrite(segG, SEGMENT_OFF); 
 }
      digitalWrite(buttonPin1, DIGIT_ON);//還不懂這行的作用,不加,開關沒有作用,無法切換數字
       Serial.print(F("buttonState1 End =  "));
       Serial.println(buttonState1);
}

沒有留言:

張貼留言

您可以留下意見,但 Luke 可能無法馬上回覆,尚請見諒。