給卡伯

這個部落格已經許久沒更新,有點半荒廢的狀態了…。雖然還是有繼續做自己喜歡的韌體,學新的技術,玩新的模組,但現在大多的事情的 priority 都已高過紀錄自己所學、和大家分享新知。

原本也沒有打算要寫這篇並且放在這,畢竟這個部落格應該是專注在韌體技術的分享,我的學習心得,但又想說,現在在做的東西何嘗不是一種學習,因此就把這些有感而發也紀錄在自造者萊恩吧。

這篇紀錄,是寫給卡伯的。

記得前陣子在系上學長姐要畢業時,有看到系學會會長都會代表應屆有一篇感人肺腑的致詞 (應該是系學會會長吧…嗎?),後來去查發現每年好像都有,好奇心驅動下,我就往前幾屆找,找到了讓我印象非常深刻『電機命』的那篇,只覺得這個詞真的形容得太好。

為什麼會從電機命開始講起,一切都是因為卡伯現在在做的事情,看起來和團隊幾個電機仔過去在學校學的東西,even 我們各自原先擅長的領域,實在沒什麼太大的關係,但因為電機命,好像也就合理了,我們的使命就是解決問題吧。

(這邊沒有要特別說電機命是啥,有興趣的人我附上連結)

之所以會做卡伯,當初原因很單純,主要是因為我自己也是受害者,再加上自己幾個身旁很好的朋友也有這樣的困擾,我們都一致認為信用卡優惠真的太雜亂,規則太多,一旦沒有符合某些即便很小的條件,就是拿不到原先預期的回饋,然後這種感覺認真很糟。

在這些聲音的驅使下我便開始思考,是否有機會運用自己既有的技術能力來解決這個問題,答案是肯定的。如果我可以把信用卡的優惠整理出來,根據不同使用者手上擁有的信用卡,讓他們在消費當下可以利用我做的應用得到個人化的推薦結果豈不是很好?

帶著這個簡單不過的想法,藉著台大創創學程的機會,找到了一群志同道合的人就開幹了。一年創創學程的課程,在下學期期中之前,我都沒有特別想過這個東西會在學程結束後繼續做下去,一方面因為過程中各種被 challenge (e.g. 商業模式),另一方面則是對於自己唸電機系的期待,兩者的層層交互作用下,難免會有自我懷疑,萌生放棄的念頭。

幸好撐下來了,可能因為電機命吧 (嗎),就讓我姑且認定是這樣,心裡總有個聲音告訴我還沒到頭,那個問題還沒被我解決阿,談何放棄?所以現在說放棄也未免太早,輕易放棄一直都不是我的風格。

幾個心臟很大的夥伴,願意相信我這個傻子,相信這個團隊,相信這個題目,相信這個東西是有價值的。從原本的學程專案直到錢從戶頭領出來,遞出去的那刻,卡伯變成了一個真槍實彈的創業題目。

這篇文發出去的同時,卡伯對外正式的第一個版本已經上線了。不免俗的還是要感謝一路以來給予指導的業師,最重要的還是一直都很相信我這個傻子的夥伴們和過去曾經幫助過這個題目的各位

沒有大家的幫忙卡伯無法在這短短幾個月就可以推出現在這個看起來還可以的版本,謝謝你們。當然,產品有很多地方有待加強,需要大家的反饋,以及使用上的建議,目前使用人數有雖有稍漲的趨勢,不過還需更努力才行。

講成這樣好像是在看什麼創業有成後的心路歷程分享,完全不然。這篇文只是一個心情的抒發,加上我們最近看到了一個機會,或許這個東西可以成為我們可靠的商業模式。

不過這項計畫的內容會需要更多志同道合的人一起加入才有可能在短時間內實現,總不可能永遠靠我和 Toby 或其他友人的義氣相挺,我們需要更多開發能量,若螢幕前的你有興趣,歡迎私訊我或是卡伯團隊中的任何夥伴。(怎麼突然變徵才哈)

我們現在的狀態還在爬,用力地往前爬,期待在山洞還沒坍掉前,能夠看到盡頭的一道光。不過說真的,不論接下來怎麽發展,這段時光都是我人生中很寶貴的回憶,回憶在辦公室和夥伴一起工作從早到深夜,寫 code 到凌晨再到早上,睡到一半接到電話不是叫我起床尿尿,而是太多人同時使用導致系統當機,種種種種都已在我記憶中留下痕跡。

講了這麼多,回到電機命本體,就像致詞文裡提到的,或許我們走的不是一個典型的電機仔路線,或許看起來很像在做一些有的沒的、一事無成,好像我們沒在為自己的未來做更有意義的事。不過我們的確就是一群會為了一個相同目標共同努力拼命的人。

我至始至終認為,電機仔不一定就得走研究、進大廠,到國外工作的路線,我們的發展應該可以是更多元的,反正電機命嘛,我們的存在就是要解決某個問題,創造某些價值,期許自己因為我們的存在可以讓這個世界有一點點的改變,那我想這個過程就不該是唯一解,但目的地卻可以一樣。

總之期待聽到更多同好的聲音和興趣,我們可以賣你一個夢想,歡迎一起來實踐它。

電子標籤 (二) – Modbus protocol (下)

上篇只有稍微介紹完 Modbus 的種類,接下來就從 Modbus protocol packet format 繼續吧!

Modbus RTU protocol 傳輸資料格式 (packet format)

如同上篇所述,我主要會專注在目前主流 Modbus – Modbus RTU 做介紹,我們就直接來看 master 傳出去的資料以及格式是什麼吧!(Modbus TCP 傳出去的資料會在實作過程中稍微提及)

螢幕快照 2019-08-21 下午3.27.11

圖片出處:Modbus 101 – Introduction to Modbus

這個 format 剛開始看到一定會霧颯颯,因為包括 function code,和使用到的 register type,都屬於 Modbus protocol 自定義的一部份。就一個個來看吧。

Device address 應該不難懂,即 master 要將這整個 packet 傳給哪個 slave,slave address 則可以事先定義好,在我的 use case,RTU slave 就是電子標籤本身,所以可以事前在 MCU 中 define slave address。

而要講 function code 之前,一定要先瞭解 Modbus 自定義的 register type。

螢幕快照 2019-08-21 下午5.07.02.png

圖片出處:Modbus protocol over RS485

嚴格來說,不能稱以上這些被定義的 register 為 register,最多稱之為 “Object",只是有四種不同的形式,即上圖所示的 Discrete Inputs, Coils, Input Registers 和 Holding Registers。

之所以不能稱之為 register 的原因,相信如果有接觸單晶片開發的同好朋友一定知道,因為 MCU (device) 本身內部就是由一堆 registers 的設定,才能做出不同的功能表現。而這裡和實體那些擁有特定 address 的 register 不同,此為軟體模擬,和硬體不直接相關,因此用 Object 稱之會較為準確。

Discrete Inputs 和 Coils 只有 single byte,很明顯就是用來做 I/O 的 digital INPUT/OUTPUT,由表中也可得知此二種不同的 typologies 的差別:Coil 是 R/W,Discrete Inputs 則是只能 Read。

而 Input Registers 和 Holding Registers 皆是可存 0-65535 值 (2 bytes) 的 typologies。最常見的就是 analog 值的應用以及其他客製化所需的資料,像是進入 ISR 的次數等等。

講到這,應該還是很難想像那到底要怎麼使用這些 typologies?slave 的 code 到底要設定哪些東西才能讓 master 在對應的位置抓到或是寫入有效的資料呢?下圖見分曉。

螢幕快照 2019-08-21 下午4.52.04.png

圖片出處:Modbus protocol over RS485

既然已經定義了各種 typologies (Discrete Inputs, Coils, Input Registers 和 Holding Registers),那給不同 typologies 不同的軟體位置定義其實也就搞定了。如上圖,00001 – 09999 就屬於 Coils 的部分,或者也可以用 prefix 的角度,如果是 0 開頭的就一定是 Coils,以此類推做出四種 typologies 的區別,至於 PDU address 的部分,下方會和 function code 的部分一起做解釋。

截至目前,應該對於 register type (以免搞混我這不用 Object 就用原先的講法吧) 有稍微的理解,現在可以進一步前進至 function code 的部分了。

螢幕快照 2019-08-21 下午5.39.15.png

圖片出處:Modbus protocol over RS485

由於解釋完了四種 typologies,上方 related area 這個 column 的內容應該就可以對得起來了。也就是說,我們退回到 Modbus RTU packet format 來看,device address 後便是 function code,假設 master 期望對 slave 的某個 GPIO (eg. LED) 做 ON/OFF 的動作,那 function code 就會植入 5,目的是告訴 slave 我 (master) 要來 “寫” 你的 Single Coil 了。

在講下去之前,要先認識一個詞 – PDU (protocol data unit),整個 Modbus RTU packet 中 PDU 的部分包含 function code 和 data (包含 register number 和 register count),如下結構:

function code
Starting Address HI
Starting Address LO
Count of Register HI
Count of Register LO

而一組 PDU 最多 (maximum) 是 256 bytes。

回到主線,因為不同的 function code 就會對不同的 typologies 做各式的動作,這也是為什麼在講 typologies 時的那張圖,最後一個 column – PDU address,不論typologies 為何,皆是 0000 – 9998。舉例來說,如果 function code 為 1,接下來的 byte 就是填要從哪個 register 開始 (eg. 0x00),然後從開始的 register 數起共多少個 registers (eg. 0x0A),一次最多讀取 2000 的 coils。

至於 CRC error checking 就是大家常見的標準款,沒什麼特別 (雖是這樣說,我還是覺得發明的人真的太強…)。master 傳過去的 packet format 大致介紹是這樣,接下來,slave 在得到 master 的 packet 後回應的部分,我覺得也相當有趣,下方和大家分享。

Modbus RTU slave response

Modbus RTU slave 在收到 master 訊息後,只有兩種情況,正確接收和出現錯誤。

在正確接受的情況下,slave 會回的東西很簡單,exactly 就是 master 傳來的東西,packet 的結構完全和 master 的 packet 相同,包含 function code + data + CRC error check。

比較有趣的是出現錯誤的時候,slave 會將來自 master packet 裡的 function code 的 MSB,變為 logic 1,除此之外,原先來自 master data 位置的內容物會被 Modbus protocol 所定義的 exception code 所取代,如下圖:

螢幕快照 2019-08-26 下午5.05.43.png

eg. 從 master 來的 function code 假設是 3 (0000 0011),若有錯誤產生,slave 丟回給 master 的 packet中的 function code 會是 131 (1000 0011),data 的部分則是上圖中某個數字,端看錯誤的情形決定。

以上快速交代了 Modbus RTU protocol master 和 slave 互傳的資料內容,若有誤歡迎指教交流,下篇就會進入實作的部分,從透過 Modbus TCP 將 PC (master) 和 Ardunio UNO + ENC28J60 (slave) 打通的故事說起。

本文同步刊登於 MakerPRO

電子標籤 (一) – Modbus protocol (上)

我又跳票了。

Johnny Five clock 只進行到 part 1,後來的確有對 Johnny Five 繼續把玩了一番,REPL 是否會被綁架的實驗做完了,不過 STM32F7 才研究到一半,我想重新洗掉 default 的 os (應該是 mbed),灌自己的 linux distro,一邊了解整個 embedded os 的流程,一邊精進自已 linux command 的能力,不過前些日子還沒完全破關,未能整理成完整的文章,接著就又必須向現實低頭,停止玩耍,賺點生活費。

估計又要一陣子才能繼續 Johnny Five 和 F7 的動作了,先讓我欠著我一定會寫成文章。

這次到手邊的案子是客戶希望利用他們自家設計的硬體實作 Modbus 通訊,簡單來說,整個架構就如下圖:

68610251_2414983268608565_922549259964776448_n.png

圖片出處:Fun and Easy Modbus RTU protocol

基本上這張圖就完全是這次要實現的系統架構。(不要急,等等下面提到看起來很可怕的東西我都會再解釋。)

PC (master) 透過 Modbus TCP 經由 Ethernet 給特定 IP 的 device (slave) 訊息,這裡的 device 在我實現的過程中我是利用 Arduino UNO + ENC28J60 Ethernet module。

而這個 Arduino UNO 又會被拿來當 Modbus RTU (remote terminal unit) 的 master,而電子標籤就是在這整個架構下做為 Modbus RTU 的 slave。

兩段都是利用 RJ45 連接,只是第一段是真的 Ethernet,第二段則是利用 RJ45 來實現 RS485 通訊。之所以要用 RS485 是因為客戶希望可以連接多個電子標籤,畢竟我們都知道 RS485 相對 RS232 更穩定。

我會從 Modbus 的介紹開始,接著實作過程,最後介紹電子標籤所使用的 MCU 作為此系列的結尾。

Modbus Protocol

Modbus protocol 事實上行之有年,早就不是個新東西,以往被應用的場域就屬 PLC 最為廣泛,只是菜鳥如我當然是第一次聽到這個東西,因此決定來研究研究。由於篇幅,這裡會省去所有歷史的部分,有興趣的同好朋友可以自行 google。

首先,Modbus protocol 走的是最常見的 master / slave 通訊架構,值得注意的是,在 Modbus protocol 中 slave 是無法主動發起通訊 (requirement),也就是說,slave 一定要等到收到 master 的訊息才有機會送出資料。

接著開始解釋文章上方,在敘述這次要實現的系統架構時所提到的一些名詞,像是 Modbus TCP 和 Modbus RTU,事實上這些的確都屬於 Modbus 的範疇。簡單來說,Modbus 共有三個種類,分別為:

  1. Modbus ASCII
  2. Modbus RTU (remote terminal unit)
  3. Modbus TCP

** 題外話,如果想瞭解 RTU 和 PLC 差異的同好朋友可以參考此文章

顯然第一項並沒有提到過。Modbus ASCII 其實是 Modbus 剛被設計出來時,這個通訊協定傳輸資料使用的編碼方式 (ASCII encoding),至今已經鮮少人使用,不特別介紹。

目前最常見,也最主流的則是使用 binary encoding,加上 CRC error checking 的 Modbus RTU,搭配的 interface 就是大家所熟悉的 RS232,RS485 或 RS422。當然,這其中最受歡迎的還是 RS485,畢竟他的表現備受肯定:理論上如果 baud rate 都相同,在沒有 repeater (就想像是一個中繼站即可) 的情況下,最多能連貫 32 個 devices,而在有 repeater 的情形下更是可以連貫 247 個 devices,距離遠達 1200 meters。

由於 Modbus RTU 的主流,接下來所介紹的 Modbus 資料傳輸格式 (format) 以及內容 (content) 都是環繞在這個種類的 Modbus,即 Modbus RTU protocol。

最後一個 Modbus TCP,嚴格來說,他並不是 master / slave 的通訊架構,而是 client / server,雖然小弟我覺得根本沒有太大差別,而且的確網路上很多資源都顯示,可以將 client 比擬為 master,server 則比擬為 slave (直覺來想可能會覺得我打錯了,不過並沒有)。

Modbus TCP 和 Modbus RTU 最大的差別在於兩個部分。

第一,Modbus TCP 會在把 Modbus RTU 的一段 chunk of data 再封裝 (encapsulate) 一層,變成 TCP packet,作為傳輸的單位。

第二,Modbus TCP 所使用的 error checking (eg. checksum) 是使用 TCP 的,不是使用 RTU 本身的 (這也很直覺,畢竟都用 TCP packet 傳了)。

另外,Modbus TCP 是可以同時運行多個 client (master) 和多個 server (slave) 的。

由於篇幅,被迫先停在這裡不然會很奇怪,下篇開始會從 Modbus RTU protocol packet format 開始解釋。想先瞭解更多的朋友,Youtube 上有個頻道 RealPars,小弟我認為他講解的 Modbus 非常清楚,可以參考看看,以下為影片連結:What is Modbus and How does it work?

下篇見。

本文同步刊登於 MakerPRO