Implement PMS3003 (G3) with Linkit Smart 7688 Duo

Behind the project…

我是最近一段時間才開始摸索 IoT 生態的,是興趣;但相對我過去的工作經驗,應該是算是業餘的嘗鮮族。然後,發現雖然不是電子背景出身要動動手當個【創客】好像不是件太困難的事。於是,我跟在智慧家電領域的同學 Harvey 聊了這個想法,他毫不考慮了丟了個 Arduino 套件讓我嘗試。這真是有趣的世界,我好像可以去做一些事,一些以前不認為可以獨力幹的事。這也開始了我的創客生活。

回到我那個搞智慧家電的同學 Harvey,在玩弄他丟給我的 Arduino 一段間後,有一天他又問我說能不能搞個空氣品質觀測的應用,因為… 有這個需求。聽起來很有趣,於是有了這個 project 的想法。

他說就很簡單,弄個空氣品質感測器,然後把測得的數據顯示出來,然後…
最好可以把數據資料給保存起來 (Database/Cloud?)
最好可以把數據資料整理再呈現 (Analysis and vistualization?)
最好可以透過不同的介面被呈現 (LCD/TFT/Web/App?)
最好可以盡可能地把體積小型化 (7688/Duo?)
最好可以把整體費用壓到最便宜 (Arduino+Wifi or 7688/Duo?)
最好可以… 明天醒來這一切都實現了。

Arduino 讓很多創客可以輕易的踏出第一步,而且獲得成就感。

但是隨著想法和功能越趨複雜,就發現 Arduino 開發板好像要疊的積木更多,要寫的 sketch code 更長,然後 Flash Rom 的 size 好像也開始不夠用了。於是,我開始尋找具備相當整合性的開發板:我想至少幫我把網路(Ethernet 或 Wifi 都好)整合在開發板吧,或至少讓我除了有 Arduino C 以外,還具備更有伸展性的開發環境吧(可以來點跟互聯網相關的嗎)!

我在想把這類裝置和互聯網連接上是一件有趣的事(我在講什麼!IoT 不就是為了這檔事嗎?),事實上我很喜歡這樣的結果。

於是我幾番考慮後決定使用【LinkIt Smart 7688 Duo】。當然,其他開發板也做得到,而且功能也更強大,只是我比較背骨偏偏選擇這個新上市的薄薄的一片來玩。

事實上,因為 7688/Duo 才上市(2015.12.25)不久,網路上的資源有限,摸索 MCU 和 MPU 的互動過程中也讓我吃了不少閉門羹,畢竟我只是幾個月的創客生手,這摸索的路是必經的過程就不再多做文章了。

有感這一路學習的資源都是透過互聯網來的,很多觀念和程式技巧的養成都是分享自許多前人的貢獻,我真的很感激(鞠躬+讚嘆)。那天跟 LASS 的哈爸在臉書訊息上聊了一下,發現除了 7688/Duo 資源的短缺著實讓很多人學習過程受挫外,開源共享的模式也還未遍地開花結果,很多成功的經驗自然無法繼續被擴充和延續。有鑑於此,既然自己是喝互聯網的奶水長大的,就也分享自己的奶水(呵)給大家吧,我決定把自己這走這一遭的經驗全部給紀錄並公開給大家參考,希望可以幫助更多初心者一路好走,ㄟ 是起步的順利一點。

Ready? Let’s Go!

有了之前一些嘗試的經驗,這次我決定要以簡潔和滿足最低功能需求的前提下去實作這個 project。

一開場就梭哈了,以下是這次硬體上我所用上的元件:

  • Planter PMS3003(G3)/PMS5003(G5)

    PMS3003
  • LinkIt Smart 7688 Duo

    Linkit Smart 7688 Duo
  • Grove Breakout for LinkIt Smart 7688 Duo

    Grove Breakout for LinkIt Smart 7688 Duo
  • Hitachi HD44780U 1602 LCD (I2C)

    Hitachi HD44780U 1602 LCD
  • DS1307 RTC(I2C)

    DS1307_RTC

選擇 PMS3003(或是叫 G3)的原因是有以下特點:

  • 數據準確:鐳射檢測,穩定、一致性好
  • 回應速度快速:使用環境變更時回應時間小於 10 秒
  • 獨立運作:使用標準的通訊埠輸出量測資料
  • 不須外加元件:自備風扇,不須外加。
  • 分析能力高:分辨顆粒最小直徑達 0.3 微米

為了降低實作過程中硬體配置的接線複雜度(另一方面是偷懶),我選擇搭配了 Grove Breakout for LinkIt Smart 7688 Duo 這塊擴充版來串接另外兩個 I2C 設備(用在 1602 LCD 和 RTC);當然這不是必要的,你也可以有另外兩個替代方案:

  • 如果想降低成本或是先做開發測試,可以使用麵包板(breadboard)用杜邦線來處理配線。
  • 如果想簡化整個硬體的體積,可以考慮剪裁一張適當的PCB來焊接處理配線。

接下來的步驟就像玩樂高積木一樣,請把它們組合起來。

  • 7688/Duo 開發板直接對準腳位插上 Grove Breakout就可以。
  • 另外 LCD 和 RTC 因為都是選用 grove I2C 規格,也直接插上去 Grove Breakout 就可以。
  • 加工(1),因為 PMS3003 的排線是 Molex 1.25mm 8P 的規格,為了方便和開發板那端接,我自己裁了一小塊PCB然後把這8條線焊上標準的 2.54mm 排插(參考附圖)。
  • 加工(2),非必要,請視實際情況參考,因為我選用LCD元件供電是5v,另外 PMS3003 的供電也是 5v,但是開發板上的 5v 只有一個插槽,我就直接利用加工(1)裁的那塊PCB焊上一條5v共腳的單排插,把所有要用到5v的供電的元件都一起接過來,然後再接一條線過去開發板上的5v。
  • 非必要,請視實際情況參考,把LCD元件的 VCC/5v 改接到PCB 剛剛焊的 5v 共腳排插。
  • 參考 PMS3003 的 datasheet 把: PIN(1) VCC/5v 接到 PCB 剛剛焊的 5v 共腳排插。
  • 參考 PMS3003 的 datasheet 把: PIN(2) GND 接到開發板的 GND 端。
  • 參考 PMS3003 的 datasheet 把: PIN(4) RXD 接到開發板的 D10 端。
  • 參考 PMS3003 的 datasheet 把: PIN(5) TXD 接到開發板的 D09 端。

PMS3003 PIN out

pms3003_pinout

PMS3003 G3 PM2.5 粉塵感測器接腳圖。資料出處:https://www.dfrobot.com/wiki/index.php?title=PM2.5_laser_dust_sensor_SKU:SEN0177

8 Pin 接腳和 5v共腳排插加工PCB

PCB for 8 PIN

整體實物佈線配置(由於我還沒有整理線路,所以圖片凌亂的線路傷眼睛請不要怪我)
另外圖中配線有一大把接到 LCD 的原因是那塊 LCD 和 I2C 控制晶片模組是我分開買自己再用杜邦排線焊接的,直接選購帶I2C控制晶片模組的 1602 LCD 省事多了,又免掉一堆線路。
The System


=================================================

Plan for the software architecture

接下來我們可以開始來聊聊程式架構和佈局了。

但是,在此之前我想先借用 Linkit Smart 7688 Duo Developers’ Guide 上面的一張圖片來引導7688/Duo程式架構可能的方式有哪些,以及我選擇用什麼模式來開發。

development model of Linkit Smart 7688 Duo

如果你選擇了 Linkit Smart 7688 Duo 這個開發板,你應該(或許)知道這個板子上面比 Linkit Smart 7688 多了一顆 ATMega32u4 MCU 晶片。這意味著兩件事,(1)你可以在 7688/Duo 上面實現大部分 Arduino(UNO) 可以做的事。(2)你的軟體開發模式可以有更多元的模式,如上圖(右)揭露的三種方式。

我的開發模式選擇第二種模型,也就是預設的方法,因為在這裡我不需要 MPU 下任何溝通指導給 MCU,單單僅要用它丟過來的資料即可:
SerialPort Model

我的想法是,既然開發板同時有 MPU(MT7688) 和 MCU(ATMega32u4),那麼就讓兩顆晶片分工做他們擅長的事吧;也就是對sensors 讀取資料的事完全交給 MCU 做,讀到的資料透過內部 Serial Port 協定傳給 MPU,然後所有邏輯處理和聯網作業就交給 MPU。以上理由是我自己掰的,不管有沒有道理聽聽就好,重點他真的可以跑得動(初心者,我好感動!)。

接下就是整體的架構規劃了,我把整個實作又再切成兩大塊,第一部分是純粹發生在 Linkit Smart 7688 Duo 身上的程式,這也是我會多著墨的地方,以及第二部分是在網頁呈現的部分這部分就偏離 7688/Duo 的探討範圍,我會僅就 UI 的呈現說明,不細究程式的撰寫。

在 Linkit Smart 7688 Duo 上面運行的程式分 MCU 端以及 MPU 端的工作,我們可以用兩隻獨立的程式來滿足不同的功能需求:

  • MCU 主要的工作有3件事,(1)讀取 sensors 資料,(2)把讀取到的 sensors 資料顯示在 LCD,(3)打包 sensors 資料給 MPU
  • MPU 的工作有就只有一件事,把收到來自 MCU 的 sensors 資料寫入資料庫。

在資料保存和網頁呈現端有兩種可以選擇,就端看你熟悉怎樣的程式技巧了。如果熟 PHP 可以考慮用第一種,如果非常懂Node.js 可以走第二種方法。我比較偷懶,用第一種架構(PHP)來實作資料保存。


Development Model 1


Development Model 2

MCU(ATMega32u4) side programming


MCU 程式下載 (.ino)

我要說好在 7688/Duo 用的 MCU 是和 Arduino(UNO) 相同的 ATMega32u4 晶片,所以我們可以把 Arduino IDE 開發的那套經驗,完全套用在這裡甚至不用修改程式碼(我試過了,移植性是 100%)。有關 Arduino IDE 的環境操作就請自己練習了,我唯一要提醒的是:請務必記得依照 Linkit Smart 7688 Duo Developer’s Guide 把 Arduino IDE 的開發板環境設定成 7688/Duo 啊~ 不然你的紅色錯誤訊息會一直出現…

我們直接切入主題,上面說我們規劃的時候,就只打算讓 MCU 負責以下3件事:

  • (1)讀取 sensors 資料
  • (2)把讀取到的 sensors 資料顯示在 LCD
  • (3)打包 sensors 資料給 MPU

(1)讀取 sensors 資料

RTC時間的讀取 和 LCD 資料的顯示應該算超簡單的練習,相信直接看 sketch code 就可以懂,這裡就不贅述了。我們直接來看 PMS3003 (G3) 這顆 sensor 的參數特性:

首先,它可以採樣測定的空氣懸浮微粒有三種規格 0.3-1.0um/1.0-2.5um/2.5-10um,也就是說我們可以拿到 PM1.0/PM2.5/PM10 的測定資料(ug/m3)。而且PMS3003 的 datasheet 寫到他有兩套檢定空氣品質濃度的方法,分別是可以獲得「大氣環境下」和「標準顆粒物」兩組資料值,所以程式裡面每一次從 sensor 那邊得到的資料就會有2組,6個測定值。(這裡我會在意的是「大氣環境下」測得的這組)

這裡我要補充說明的是,範例裡面使用程式去讀取 PMS3003 資料那段邏輯在網路上有多種不同的實作(讀到的資料值都相同啦),我是參考一個程式寫的很簡潔的網友的(雖然他的方法也偷懶少做了checksum),如果看不懂建議您直接看一下 PMS3003 的 datasheet。或是參考下面這另一個出處的邏輯:https://www.dfrobot.com/wiki/index.php?title=PM2.5_laser_dust_sensor_SKU:SEN0177

再來,它的資料介面使用標準序列阜(Serial port baudrate: 9600; Parity: None; Stop Bits: 1; packet length is fixed at 24 bytes.)讀取,從PIN(4)和PIN(5)接腳可以和他溝通 (RX/TX)。這裡有個注意的地方,如果我們直接以 Arduino 的 Serial1 類別去讀取 RX/TX 將會有問題。原因是 7688 把預設的第一組 UART(D0/D1) 保留給 MCU 和 MPU 的溝通使用,所以把 PMS3003的 RX/TX 插上 7688/Duo 的 D0/D1 是讀不到資料的,請記得預設情況下在 7688/Duo 裡面,Serial1是MCU丟資料給MPU的通道口。

我使用另一個替代方法即用 SoftwareSerial() 類別去實作 serialport 和他溝通,這個方法可以選用 7688/Duo 上面有限定可用的數位腳位去指定(RX/TX)。所以記得程式一開始必須把 SoftwareSerial.h 這句宣告(#include)包含進來。

(2)打包 sensors 讀取的資料

在這裡我選用 JSON 資料格式來打包 PMS3003 讀取到的資料和 DS1307 RTC 得到的日期和時間。所以在程式裡面一開始就會看到關於 ArduinoJson.h 宣告(#include)就是這個原因。

這裡我舉一個採集到的資料,他被包成 JSON 格式後的範例給大家參考:

{
"sensor": "PMS3003",
"date": "2016-03-13",
"time": "05:34:11",
"pm010_TSI": "07",
"pm010_ATM": "07",
"pm025_TSI": "10",
"pm025_ATM": "10",
"pm100_TSI": "16",
"pm100_ATM": "16"
}

資料名稱 _ATM 指的就是「大氣環境下」方法測得的數據。
資料名稱 _TSI 指的就是「標準顆粒物」方法測得的數據。

接下來打包完的 JSON 資料,就是要把資料往 MPU 送。


之前寫個這一段,後來我重新看過程式,發現 FIRMATA protocol 只被我宣告,但是在我的 code 裡面宣告後一直沒有使用(因為我發現那個是我移植另一個測試用的),所以下面粉紅色這塊注釋裡面,我把之前 sketch code 裡面這兩行給直接刪除掉(程式已經更新了)。


Firmata.h 的宣告那行(#include)
Firmata.begin(Serial1);

設定MCU/MPU溝通(Serial Port) 的 Baud Rate Rate = 57600,然後把打包的 JSON 資料物件(這裡的範例是 Jasonroot)直接寫進去 Serial1即可:


Serial1.begin(57600);
Jasonroot.printTo(Serial1);

最後我們把範例程式 compiler 完 upload 到 7688/Duo 板子後,打開 Arduino IDE 的 Serial Monitor 觀看執行結果,應該會如同下圖所示。
SerialPort_Monitor

LCD 端的顯示應該如下圖:
LCD 1602 Display

補充說明,程式中設定每隔 10 秒 (10,000 ms) 去讀取 sensors 資料一次。

MPU(MT7688AN) side programming


MPU 程式下載 (.js)

我們複習一下,在這個設定好的故事裡面 MPU 的工作有就只有一件事,把揭開來自 MCU 的 sensors 資料寫入資料庫。

當我們把 MCU 的 sketch 給 upload 後,sensor 所讀到的值經包裝成 JSON 後將會源源不絕的被送到 Serial1。既然我們知道源頭的水進入 Serial1 這條水管後,我就可以在另一頭接水使用了,MPU 的工作就從接水開始。

MPU 端的程式我選擇用 Node.js 來實作,好處就是他已經是出廠就安裝好的開發環境,不用自己去煩心安裝主程式和相關套件的問題。

在 Node.js 中先宣告一個序列阜 serialport 的物件 ==> var com = require(“serialport”);
把這個序列阜物件設定以 Baud Rate = 57600 的速度連到 /dev/ttyS0 這個 port 串口, /dev/ttyS0 就是接水口,水源就是剛剛在 MCU 持續每隔10秒鐘寫入的 JSON 資料。

既然我們在 MCU 端包裝資料就是以 JSON 格式包裝,這裡我們就可以用 Node.js 的內建 JSON 函數把它解(parse)出來。這裡我非常簡單的檢查收到的資料是不是有無效的資料( if (jobj.xxxxx==”undefined”)),如果有這一包資料我就不要了,直接忽略他。 當然你應用更嚴僅的方法去過濾垃圾資料,我這裡只是偷個懶,千萬別學我,不然程式執行過程是會有機會被無緣無故的垃圾操作給中斷的。

寫到這裡,當千辛萬苦的資料都到手了,現在要殺要刮就輕而易舉了,是不?(耶!下課了)在這個階段可以做的事太多了,但是以我的規劃,當MPU把資料拿到手後的下一步是寫進去資料庫存起來,我選用的辦法是,用 HTTP Client 去發動一個 PHP 程式帶必要的資料過去,然後由 PHP 處理資料建檔。

會喜歡 Node.js 的原因是,他剛好有內建 HTTP Server/Client 的服務,我只要把資料以合乎URL規範的格式編輯好再交付給 HTTP Client 去觸發執行即可。

比方說,我們用下的例子當範例:

MPU 當下收到的資料解開如下


[sensor]= PMS3003
[date]= 2016-03-13
[time]= 09:10:07
[pm010_TSI]= 10
[pm025_TSI]= 15
[pm100_TSI]= 18
[pm010_ATM]= 10
[pm025_ATM]= 15
[pm100_ATM]= 18

那我就會利用一隻位在 pm25.com 這部 web server 上面一隻已經編程好的 PHP 程式 cgi_insert_sensor_data.php 幫我做建檔資料,最簡單的 URL 字串可以寫成如下:(資料的傳遞是以 key=value 的方式用一個 & 符號串起組成)


http://pm25.com/cgi_insert_sensor_data.php?input_SID=PMS3003&input_datetime=2016-03-13T09:10:07&pm010_TSI=10&pm025_TSI=15&pm100_TSI=18&pm010_ATM=10&pm025_ATM=15&pm100_ATM=18

而當位在 pm25.com 這部 web server 上的 cgi_insert_sensor_data.php 收到後,我會把資料轉成如下 SQL 語言,然後呼叫資料庫函數寫入資料庫:


SQL Command String =INSERT INTO Resort.Weather(Sensor_Id, Sensor_Datetime, pm010_TSI, pm025_TSI, pm100_TSI, pm010_ATM, pm025_ATM, pm100_ATM) VALUES (‘PMS3003’, ‘2016-03-13T09:10:07’, 10, 15, 18, 10, 15, 18 )

這樣一來,資料建檔就可以被存放在任何有接通資料庫的互聯網主機上了。當然,如果資料庫是在近端的網域內,你可以直接考慮以 Node.js 直接寫入資料庫,而不用再維護一支遠端主機上的 cgi 程式。

實際操作方面,我假設你已經會用 SSH 遠端登錄到你的 7688/Duo ,並且會一些很基本的 Linux 指令,這是因為 7688/Duo 的 OS 是採用 Linux 近親 OpenWrt的緣故,如果你一點都不懂的話會很吃力,先找幾帖 Linux 大補帖惡補一下吧。

待 login root 後,請建立一個目錄例如:
root@mylinkit:~#mkdir app

切換到該目錄:
root@mylinkit:~#cd app

用任何拿手的 text editor 編輯一個新的文字檔如:
root@mylinkit:~/app#vi PM25_7688Duo.js

把範例程式碼貼上去,存檔後離開。
接下來我們要讓這個程式碼發生作用,必須用 node 啟動執行它:
root@mylinkit:~/app#node PM25_7688Duo.js

等個幾秒後,畫面應該就會 prompt 出一些資料,這是我把執行過程中的資料片段丟到畫面來觀測的緣故,當然這個階段程式會佔據你的控制權,您沒辦法做其他的事,事實上您也不需要在這時間做任何事,因為 node 程式正很忠實地幫你一分一秒做你要他做的事,那到底他做了什麼?我們上面的說明已經解釋過了(要終止這隻程式的獨佔模式而回到命令列可以同時按下 [control]+[c] 兩個按鍵,程式就會立即中止了)。

下面是啟動 node 程式執行的畫面截圖,可以供參考。
MPU_screenshot

Data Visualisation

網頁端的資料呈現不是這個題目的範圍,我等有空在講個概念吧!
這裡我就先分享一個我初步弄出來的樣子供大家參考,各位可以構思自己的視覺呈現。

數據視覺化輸出展示

以上簡單的說明,希望對 Linkit Smart 7688 Duo 抱有期待又沒辦法突破的你有所幫助。

Bali Image 2016

Bali Image 2016

[metaslider id=211]

態度

人需要一種來去自如的安詳,一份不求什麼的滿足;
同時需要一份敢於求取的摯情、信念和執著。

依樣畫葫蘆

最近時間多了些,慢慢發現以前總說著沒時間做的事也突然有動起來的機會了。

好久好久前(應該有超過20年了)剛學習寫程式的時候沒那麼多資源,除了用天馬行空式的想像工法去練習,最有效率的方法當算是照著書本或是拿他人的程式來依樣畫葫蘆。而這個方法挺實用的,也可以適用到很多生活上或工作上的事,可以說屢試不爽。

我喜歡在電腦前寫程式帶來的成就感,就如同在廚房裡用著自己一慣的態度和節奏烹煮東西一樣。

這是我第一回親手做餅乾,一直以來總不乏有身邊的親朋好友分享自己揉麵團做出的手工餅乾,也因此躍躍欲試的心情從沒有被中斷過。儘管網路上可以供參考的食譜已是百家爭鳴,有標準版、升級版、終極版...一直到米其林版都可以尋著,真是琳琅滿目,目不暇給,再敢說沒有食譜簡直就是找不到形容詞可以罵了。這段話是說給昨天前的我自己聽的。

雖然沒上過廚藝課程,也沒學過糕點製作,更不用說親赴巴黎藍帶廚藝學校進修這種羨煞人心的機運,罷特(but),依樣畫葫蘆總可以了吧!而,幸運的是竟然瞎貓碰上死耗子給我矇著了,我也辦得到耶!這烘焙成品論口感、味道和賣相試過的人都給予相當的好評,如果說用專業的術語來講評那應該可以掛上個『是完成度頗高的作品』當結論吧。相信現在正在讀我的字的你也感受到我心情的雀躍了!科科。

也許這款餅乾的成功率是趨近於會開火就能煮熟食物的等級,然這個經驗卻是個鼓舞人心的開始,也大大的激勵我再度嘗試不同糕點的信心。

寫在最後,我相信世界上應該沒有一定的最完美的食譜,只有不斷創新的食譜。這個烘焙作品我一共參考了四份從網路收集來的做法,再調以自己的想像和對這個作品的期待,最後再對他呼了一口不確定的運氣才孵化出來。所以九成的功勞是陌生人的貢獻,而滿滿十成的成就感就屬是自己的囉。

{"focusMode":1,"deviceTilt":-0.1070763245224953,"whiteBalanceProgram":0,"macroEnabled":false,"qualityMode":3}

古印第安人諺語

走了太長時間的路,或許已經忘了當初為什麼要出發。

 

『 不要走得太快,等等自己的靈魂。 』

 

讀「自在的旅行」有感。

很久以後發現和另一個寫書人曾經在相彷的時空坐在相同的位置、吃過相同的食物是件很神奇的事,尤其這件事祇是寫書人一次訪遊台北的某朝,在一家營業時間不過幾個月長的店家用餐經驗。

兩千零四、零五年,我才退伍回台北工作的那些年,租屋住在今天金融研訓院後面的巷子內。一向偏愛白天時間的我早也習慣在週末的早晨就早早起床款好自己,然後悠哉的找個理想的地方坐下來用餐。

更常的時間我總是只著短T短褲、踩勃肯鞋、攜一本書和手機就在師大附近找地方吃早餐,那年代早午餐文化還剛萌芽,美而美系列還是最多人的早餐信仰中心。但總是美而美的早餐久了就會開始想試試不一樣的用餐經驗。

我在想,什麼樣的事件是旅行過程中會想記錄下來的?(松浦弥太郎已經在腦海中編織一個要說的故事了嗎?),尤其是對於一個有可能會收錄該篇幅在自己未來出版品的作家。應該是印象深刻的事件吧。那到底印象深刻的事件除了旅遊書上預告的城市地標,我們還會想在一趟旅途中記錄什麼?

有人說沒有計畫的旅行往往能獲得最多的驚喜和意外的收穫,冒一點風險和不便是必須的,也許正是隨心所欲、隨遇而安這樣的心情讓一向都是準備好了再出發的我們不用在旅途中不斷趕進度,然後可以以接近生活的態度來體驗不同的文化,一切的amazing 就會如雨後的蕈菇不約而同的蹦出我們的身邊。

松浦弥太郎在甫出版的「自在的旅行」一書中提到初訪台北即下榻在古亭附近的旅店。一朝他來到一家小而美的咖啡館享用早晨,讚嘆旅途上一場意味的愉悅用餐經驗恰巧和我向來慣訪的巷口小店是同一家,而且我們都喜愛一模一樣的餐點,真是太神奇了。尤其這是他把用餐經驗收錄在他的書裡以母語日文出版,又透過翻譯的中文書輾轉讓我知道這個差曲。

越是讀著他的作品,越是了解這一個寫書人的態度後,我不禁想像這世界上也許真有另一個人,過著以相似的步調、習慣、飲食和我平行的生活著。

京都【INODA COFFEE】三条 本店

書上說:「京都的早晨是從 INODA COFFEE 的香味開始」。

這句話我坐進 INODA 一個小後還悟不出來。不過推開 INODA 大門的那一刻,我就知道這是一家骨灰級的咖啡館,有近一半是你爸媽爺奶的年紀客人。

在日本雖然很多地方都開始禁煙了,但是咖啡(喫茶)館這種文學家、藝術家、政治家、和老人家催生的搖籃要全面禁煙似乎是不可能的,至少會讓你有吸煙區和非吸煙區的選擇,但是多是差異不大。

Vintage。是的,那美好年代所遺留下來的除了歷史還有文化和生活。凡歷經時間萃取過的,它的內函都是值得尊敬的,即使它現在看起來是老態的、單調的。

就如同走在京都的街道上,常常我們會有活在歷史裡的錯覺,但是千百年的歷史依然可以在這裡和摩登現代融合的互不相衝突。

京都【INODA COFFEE】 イノダコーヒー 本店
INODA COFFEE