DHT11 是許多人都用過的溫濕度模組, 不過在 2017 年 3 月時 DHT11 開始供給新版本的模組, 舊版模組就停產了。新版模組可說是功能加強版, 可偵測的範圍變大, 而且溫度也可以提供到小數 1 位。不過就是因為這小數 1 位, 如果您是使用 Arduino Playground 的程式庫讀取溫濕度, 遇到新版的 DHT11 模組就會發生校驗不正確, 幾乎無法讀取溫濕度的情況。
會出現這樣的問題, 主要是因為從 DHT11 讀取到的資料共 5 個位元組, 依序是相對濕度的整數部分、小數部分, 攝氏溫度的整數部分、小數部分, 以及由前面這 4 個位元組相加所得到的校驗值, 在程式庫中就是 bits[0]~bits[4]。不過由於舊版 DHT11 的濕度與溫度精確度都只到整數, 不會有小數, 也就是 bit[1] 和 bit[3] 永遠為 0, 所以程式庫中計算校驗值時就偷懶的只把 bit[0] 和 bit[2] 相加, 如以下所示:
當遇到溫度有小數部分時, 上列程式最後一行的校驗值檢查就一定不相等, 所以就無法正確讀取溫濕度了。要解決這個問題很簡單, 只要在計算校驗值時乖乖的把 4 個位元組相加就可以了:
雖然市面上可能還有為數不少的舊版模組, 不過我自己最近買到的就是新版的模組, 還差點因為這個問題以為買到了瑕疵品。大家可以先修改程式庫, 這樣不論新舊版模組都不會有問題。
highlight.js
星期四, 8月 10, 2017
星期六, 7月 08, 2017
製作給 Arduino PCM 程式庫使用的聲音資料
使用 Arduino PCM 程式庫需要一個儲存聲音數位化後的資料陣列, 這個陣列的內容就是以 8KHz 頻率取樣的樣本, 為了讓你自己的聲音檔可以轉換成此陣列格式, 可以合用兩個工具:Audacity 和 EncodeAudio (這個網頁有 Mac OS 和 Linux 版), Audacity 可以把音樂檔轉成 8KHz 單聲道, 而 EncodeAudio 可以把轉好的聲音檔案轉成所需的資料陣列。
首先使用 Audacity 匯入原始的聲音檔, 然後改成單聲道:
再從左下角將取樣頻率改為 8000, 也就是 8KHz:
之後就可以匯出聲音檔案:
儲存時存檔類型請選『WAV 16-bit PCM』
接著請執行 EncodeAudio, 指定要使用的聲音檔案:
轉換完成它會把資料複製到剪貼簿中:
接著用編輯器開啟使用 PCM 程式庫的檔案, 把其中的聲音資料陣列內容換掉就可以了:
首先使用 Audacity 匯入原始的聲音檔, 然後改成單聲道:
再從左下角將取樣頻率改為 8000, 也就是 8KHz:
之後就可以匯出聲音檔案:
儲存時存檔類型請選『WAV 16-bit PCM』
接著請執行 EncodeAudio, 指定要使用的聲音檔案:
轉換完成它會把資料複製到剪貼簿中:
接著用編輯器開啟使用 PCM 程式庫的檔案, 把其中的聲音資料陣列內容換掉就可以了:
星期四, 6月 29, 2017
解決 PCM 播放與 Servo 程式庫衝突的問題
由於同事在製作使用伺服馬達的六腳機器人專案, 想要讓機器人遇到障礙物時可以用喇叭播放驚恐的聲音, 因此就利用了善心人士寫好的 PCM 播放程式庫, 不過一用才知道, 原來 Servo 程式庫和 PCM 程式庫都用到了 Arduino UNO 上的 Timer, 因此無法共存。研究了一下發現, Servo 會用到 Timer1 產生中斷送出給伺服馬達的方波訊號, 而 PCM 程式庫為了播放 8KHz 的聲音, 同時用了 Timer1 和 Timer2, Timer1 負責每秒產生 8000 次中斷, 每次中斷切換下一個 PCM 採樣值, 而 Timer2 則負責將 Sample 資料以 PWM 方式送出給喇叭發聲。兩個程式庫都用到了 Timer1, 如果混在一起用, 連編譯都不會過。即使編譯會過, 程式也無法正常運作, 因為兩個程式所需要的 Timer1 頻率根本不一樣。
為了解決問題, 必須有一方讓出 Timer1 給對方使用。討論之後發現, 機器人遇到障礙時可發出聲音後再繼續動作, 並不一定要邊發出聲音邊動作, 所以決定修改 PCM 程式庫, 把 Timer1 讓出來, 改成用很單純的迴圈搭配 delayMicroseconds(), 每 125μs 切換 PCM 採樣值發聲, 問題就解決了。修改過的程式庫可在這裡下載, 如果您也有一樣的困擾, 也許可以試用看看。
有關 Timer, 可參考這一篇文章, 有簡明易懂的說明, 並且整理了常用的程式庫所佔用的 Timer, 如果你的程式遇到怪現象, 例如使用了 tone() 函式後, 3 和 11 腳的 PWM 就失效, 很可能就是 Timer 的問題。
為了解決問題, 必須有一方讓出 Timer1 給對方使用。討論之後發現, 機器人遇到障礙時可發出聲音後再繼續動作, 並不一定要邊發出聲音邊動作, 所以決定修改 PCM 程式庫, 把 Timer1 讓出來, 改成用很單純的迴圈搭配 delayMicroseconds(), 每 125μs 切換 PCM 採樣值發聲, 問題就解決了。修改過的程式庫可在這裡下載, 如果您也有一樣的困擾, 也許可以試用看看。
有關 Timer, 可參考這一篇文章, 有簡明易懂的說明, 並且整理了常用的程式庫所佔用的 Timer, 如果你的程式遇到怪現象, 例如使用了 tone() 函式後, 3 和 11 腳的 PWM 就失效, 很可能就是 Timer 的問題。
星期六, 6月 17, 2017
Windows 上 Python2/3 共存的最簡單方式
我真是後知後覺, 原來在 Windows 上從 Python 3.3 之後就提供了 Python launcher 工具程式, 可以讓你用 "py -版本" 的方式執行 Python 2 或是 Python 3 的直譯器。而對於套件管理軟體 pip, 也可以使用 pip2 或是 pip3 來區別管理 Python 2 與 Python 3 的套件:
星期四, 6月 01, 2017
Windows 下如何清除 DNS 快取與 NetBios 快取
平常我們再使用網路時, 可以直接透過主機名稱, 向是 www.yahoo.com.tw 瀏覽網頁, 或是透過區網中的電腦名稱直接連線, 例如我的主機電腦名稱叫做 tom, 就可以在檔案總管直接瀏覽 \\tom 察看分享的資源, 前者靠的是 TCP/IP 中的 DNS 名稱對應, 幫你從名稱找到對應的 IP 位址;後者靠的是微軟的 WINS 服務從 NetBIOS 協定使用的電腦名稱對應到 IP 位址。這兩種位址對應的資訊都會由系統快取下來, 後續再遇到相同的名稱實際不需要重新透過較繁瑣的查詢程序, 而可以直接從快取中找出之前查到的 IP 位址來使用。
但是當電腦在不同的網路中切換時, 比如說辦公室中有兩個以上的無線網路, 當你從 A 無線網路切換到 B 無線網路時, 系統還是會從快取中取得之前查詢的 IP 位址, 就可能會導致同樣以檔案總管瀏覽 \\tom 時卻無法連線的問題。這時我們可以先清除快取, 強迫讓系統重新查詢。要做到這件事, 必須以管理員身份執行『命令提示字元』(也就是 cmd.exe), 並透過以下指令清除 DNS 服務的名稱對應快取內容:
如果要清除 WINS 服務的 NetBIOS 名稱快取, 則要使用以下指令:
但是當電腦在不同的網路中切換時, 比如說辦公室中有兩個以上的無線網路, 當你從 A 無線網路切換到 B 無線網路時, 系統還是會從快取中取得之前查詢的 IP 位址, 就可能會導致同樣以檔案總管瀏覽 \\tom 時卻無法連線的問題。這時我們可以先清除快取, 強迫讓系統重新查詢。要做到這件事, 必須以管理員身份執行『命令提示字元』(也就是 cmd.exe), 並透過以下指令清除 DNS 服務的名稱對應快取內容:
C:\WINDOWS\system32>ipconfig /flushdns Windows IP 設定 成功清除 DNS 解讀器快取。
如果要清除 WINS 服務的 NetBIOS 名稱快取, 則要使用以下指令:
C:\WINDOWS\system32>nbtstat -R 順利清除和預先載入 NBT 遠端快取名稱表格。
星期四, 5月 11, 2017
Windows 10 下切換私人/公用網路的方法
許多人都遇到找不到切換 Windows 10 中私人/公用網路的設定, 其實很簡單, 只是現在沒有直接的選項, 而是必須以切換『讓此電腦可供探索』的方式來變更, 開啟『讓此電腦可供探索』就是私人網路, 關閉該選項就是公用網路。詳細設定過程就是先進『控制台』:
選取『網路與網際網路』:
我要改的是無線網路設定, 所以選『Wi-Fi』:
再按一下出現的無線網路名稱:
根據要切換成私人或是公用網路, 開啟或關閉『讓此電腦可供探索』選項即可。
選取『網路與網際網路』:
我要改的是無線網路設定, 所以選『Wi-Fi』:
再按一下出現的無線網路名稱:
根據要切換成私人或是公用網路, 開啟或關閉『讓此電腦可供探索』選項即可。
星期三, 5月 03, 2017
使用 SSD1306 晶片控制的 OLED 顯示模組
由於 OLED 顯示實在很有科技感, 所以我測試了這一款從淘寶買到的模組, 賣家其實有提供一堆資料,包含 Arduino 可用的函式庫, 我自己測試時是採用 Adafruit 的 Adafruit_SSD1306 函式庫, 不過在使用這一個函式庫時有幾個注意事項:
- 它需要使用到 Adafruit 的另一個函式庫 Adafruit GFX graphics core library 才能運作, 這個函式庫是 Adafruit 所有繪圖類函式庫的核心。
- 我所買到的模組是使用 I2C 傳輸介面, 但是它的 I2C 位址和 Adafruit 自己賣的不一樣,經檢測後發現我的模組是 0x3C,如果你購買時買家沒有提供相關資訊,也可以接上 Arduino 後, 用 i2c_scanner 程式幫你搜尋。並修改範例中 display.begin(SSD1306_SWITCHCAPVCC, 0x3D);的 0x3D 為你模組的 I2C 位址。
- 必須修改函式庫中的 Adafruit_SSD1306.h 檔, 根據你模組的解析度調整取消對應的註解:
#define SSD1306_128_64 // #define SSD1306_128_32 // #define SSD1306_96_16
訂閱:
文章 (Atom)











