2016年1月30日 星期六

在raspberry 上面設定固定ip


編輯  /etc/network/interfaces

Change iface wlan0 inet dhcp into iface wlan0 inet static

輸入  route 


可以觀察出   ,  

Gateway :  192.168.1.1  
genmask :  255:255:255:0

並且增加下面這三行

address 192.168.1.3 # Static IP you want 
netmask 255.255.255.0 
gateway 192.168.1.1   # IP of your router

address 就是你要固定的ip.....  你可以先用動態ip 找到之後...再把他存進去

最後整個檔案就是這樣


你可以用  

sudo ifdown wlan0 and sudo ifup wlan0,

來手動測試....如果測試沒問題... 就可以重新開機...

sudo reboot


2016年1月26日 星期二

用Raspberry 來玩 blue tooth programming PyBluez



先安裝好blue-tooth 的套件

sudo apt-get update

sudo apt-get install bluetooth bluez-utils blueman bluez python-gobject python-gobject-2

sudo apt-get install python-bluez


sudo hciconfig hci0 piscan [make your device discover-able]
sudo hciconfig hci0 name 'Device Name' 
接下來這個動作很重要....因為bluetooth有bug... 需要用一個workaround的方式
 Disable bluetooth pnat support as there seems to be a bug which stops proper operation with pnat enabled. Full details can be found here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=6907492A workaround is to add the following to /etc/bluetooth/main.conf:
   DisablePlugins = pnat
    如果上面的事情沒有做...就會產生下面的error message


(111, 'Connection refused')

接著開始啟動藍牙:

確認作業系統是否有抓到藍牙裝置。
lsusb




確認藍牙裝置接收器已被啟動。
hciconfig


可以看得出來目前的藍芽裝置只有一個, 就是 hci0....

dev_addr 為 00:1A:7D:DA:71:04


一些小工具....hcitool scan...可以掃描附近的藍芽裝置




接下來就是重頭戲...開始來寫programming...


請參考ref 1.. Chapter 3

It is written for the Windows XP (Microsoft Bluetooth stack) and GNU/Linux (BlueZ stack)

Bluetooth programming with Python - PyBluez

chapter 3.1

 findmyphone.py

import bluetooth

target_name = "chifc iphone"
target_address = None

nearby_devices = bluetooth.discover_devices()

for bdaddr in nearby_devices:
    print bluetooth.lookup_name( bdaddr ) # for debug used
    if target_name == bluetooth.lookup_name( bdaddr ):
        target_address = bdaddr
        break

if target_address is not None:
    print "found target bluetooth device with address ", target_address
else:
    print "could not find target bluetooth device nearby"

從上面的例子來看....他使用了 bluetooth 的library...

呼叫  bluetooth.discover_devices() 來找到最近的  devices....

接著用一個for loop.....來找名字是 "My Phone" 的target...

最後判斷  target_address是不是NULL....如果不是...代表找到了


我用我的手機打開藍芽... 手機名稱為 chifc iphone.....掃到第二個裝置就找到了 ....

同時印出target address

至於iphone怎麼修改名稱   .... 設定>一般>關於本機>名稱





chapter 3.2 Communicating with RFCOMM

Example 3-2. rfcomm-server.py
import bluetooth

server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )

port = 1
server_sock.bind(("",port))
server_sock.listen(1)

client_sock,address = server_sock.accept()
print "Accepted connection from ",address

data = client_sock.recv(1024)
print "received [%s]" % data

client_sock.close()
server_sock.close()




Example 3-3. rfcomm-client.py
import bluetooth

bd_addr = "01:23:45:67:89:AB"  # here need to modify. use hciconfig to get address

port = 1

sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
sock.connect((bd_addr, port))

sock.send("hello!!")

sock.close()

這邊有兩個 code...一個是server...一個是client..

在server 端呼叫 server_sock.accept()

來得到client_socket 和 address

然後再由client_socket來得到傳送的data   

data = client_sock.recv(1024)

在client端就是寫一個傳送的test code...

首先先指定對方的address ..."01:23:45:67:89:AB"

然後呼叫下面的function 來建立連線
sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
sock.connect((bd_addr, port))

接下來就是傳送資料
sock.send("hello!!")



3.3. Communicating with L2CAP

Example 3-4. l2cap-server.py
import bluetooth

server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP )

port = 0x1001
server_sock.bind(("",port))
server_sock.listen(1)

client_sock,address = server_sock.accept()
print "Accepted connection from ",address

data = client_sock.recv(1024)
print "received [%s]" % data

client_sock.close()
server_sock.close()

Example 3-5. l2cap-client.py
import bluetooth

sock=bluetooth.BluetoothSocket(bluetooth.L2CAP)

bd_addr = "01:23:45:67:89:AB"
port = 0x1001

sock.connect((bd_addr, port))

sock.send("hello!!")

sock.close()
===============================================================

sample code 和 chapter 3.2差不多...只差在指定傳輸的方式



3.4. Service Discovery Protocol

Dynamically allocating port numbers and using the Service Discovery Protocol (SDP) to search for and advertise services is a simple process in PyBluez

動態地配置port number 和 使用 service Dsicovery Protocol 去尋找和配置服務在PyBluez 是一個很簡單的過程

luetooth.get_available_port( protocol )

 The get_available_port method finds available L2CAP and RFCOMM ports

bluetooth.advertise_service( sock, name, uuid )
bluetooth.stop_advertising( sock )
bluetooth.find_service( name = None, uuid = None, bdaddr = None )

advertise_service advertises a service with the local SDP server, and find_service searches Bluetooth devices for a specific service.

The UUID must always be a string of the form ``xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" or ``xxxxxxxx" or ``xxxx", where each 'x' is a hexadecimal digit

find_service looks for a service with name and UUID that match name and uuid, at least one of which must be specified

 In the special case that ``localhost" is used for bdaddr


直接看範例吧...

Example 3-6. rfcomm-server-sdp.py
import bluetooth

server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )

port = bluetooth.get_available_port( bluetooth.RFCOMM )
server_sock.bind(("",port))
server_sock.listen(1)
print "listening on port %d" % port

uuid = "1e0ca4ea-299d-4335-93eb-27fcfe7fa848"
bluetooth.advertise_service( server_sock, "FooBar Service", uuid )

client_sock,address = server_sock.accept()
print "Accepted connection from ",address

data = client_sock.recv(1024)
print "received [%s]" % data

client_sock.close()
server_sock.close()

Example 3-7. rfcomm-client-sdp.py
import sys
import bluetooth

uuid = "1e0ca4ea-299d-4335-93eb-27fcfe7fa848"
service_matches = bluetooth.find_service( uuid = uuid )

if len(service_matches) == 0:
    print "couldn't find the FooBar service"
    sys.exit(0)

first_match = service_matches[0]
port = first_match["port"]
name = first_match["name"]
host = first_match["host"]

print "connecting to \"%s\" on %s" % (name, host)

sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
sock.connect((host, port))
sock.send("hello!!")
sock.close()
==========================================================
在執行這個範例... 需要先找到你的UUID...
從Ref 5可以得知
vi get_uuid.py
get_uuid.py 的內容如下:
#!/usr/bin/python
import sys,uuid
print uuid.uuid4().hex
執行後的結果如下
所以要把內文中的uuid 改成你執行後所得到的值.....
在執行/rfcomm-server-sdp.py 會遇到下面的問題
查了一下 google...從ref 6 可以得知...
原來 
get_available_port(protocol)
deprecated. bind to port zero instead.
get_available_port 函式已經被放棄了
請改用 port 0來代替...
所以修改你的code
 #port = bluetooth.get_available_port( bluetooth.RFCOMM )
port = 0
在client 端使用  find_service...來尋找 service...他指定了uuid ..
藉由找到的service_match[0]來得到 port 和 name 和 host...
然後再用 
sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
sock.connect((host, port))

來產生連線....執行結果如下:






3.5. Advanced usage

 They don't return until the requests are complete, which can often taken a long time . During this time, the controlling thread blocks and can't do anything else....
PyBluez provides the DeviceDiscoverer class for asynchronous device discovery and name lookup.
Example 3-8. asynchronous-inquiry.py
import bluetooth
import select

class MyDiscoverer(bluetooth.DeviceDiscoverer):
    
    def pre_inquiry(self):
        self.done = False
    
    def device_discovered(self, address, device_class, name):
        print "%s - %s" % (address, name)

    def inquiry_complete(self):
        self.done = True

d = MyDiscoverer()
d.find_devices(lookup_names = True)

readfiles = [ d, ]

while True:
    rfds = select.select( readfiles, [], [] )[0]

    if d in rfds:
        d.process_event()

    if d.done: break

To asynchronously detect nearby bluetooth devices, create a subclass of DeviceDiscoverer and override the pre_inquirydevice_discovered, and inquiry_complete methods.


Reference  1: https://people.csail.mit.edu/albert/bluez-intro/

Reference  2 : http://cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pi-40ibeacon.html

Reference  3 : https://github.com/karulis/pybluez

Reference  4 : http://forum.erlerobotics.com/t/working-with-bluetooth/453

Reference  5 : http://www.wadewegner.com/2014/05/create-an-ibeacon-transmitter-with-the-raspberry-pi/
Reference 6 : https://www.raspberrypi.org/forums/viewtopic.php?f=32&t=113987

如何在兩台RPI用wifi互相傳資料..... MQTT


先了解一下甚麼是MQTT

MQTT設計構想是採開放、簡單、輕量、易於實現同時支援離線訊息及訊息保留的功能。適用於受限制的環境,例如小頻寬、不穩定的網路或是資源有限的嵌入設備。其協定的特點如下:
1.使用發佈(Publish)/訂閱(Subscribe)訊息模式,提供一對多的訊息發佈。
2.使用 TCP/IP 提供網路連接。
3.具有多重QOS訊息傳輸,有三種用於訊息傳遞的服務品質::
4.使用網路頻寬小(2 bytes at minimum),減少通訊協定交換量。
5.使用 Last Will 和 Testament (最後留言)特性,可通知訂閱者用戶端與 MQTT 伺服器的連線異常中斷。




由上述的關係圖中,我們明白發佈者與訂閱者的中間需要一個平台,而這個平台最簡單的方式就是採用MQTT Broker

常見的MQTT Broker大致有Apache Apollo、HiveMQ、Mosca、Mosquitto、RabbitMQ、RSMB、...其比較如下表所示:
本篇文章的MQTT Broker則是採用Mosquitto,Mosquitto是一個實現了MQTT3.1協議的開源(BSD許可證)代理服務器,由MQTT協議創始人之一的Andy Stanford-Clark開發,它為我們提供了輕量級數據交換的解決方案。其官網為:http://mosquitto.org/,至目前為止他的最新版本為1.4。


先把兩台rpi 都燒錄好OS....這邊我發覺mosquitto 不支援  raspiban-jessie...

所以我改用  raspiban wheezy

接上wifi....

安裝必要的套件....

sudo apt-get install software-properties-common python-software-properties
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt-get install mosquitto mosquitto-clients python-mosquitto

先來個 Hello  的例子吧

接收端的RPI輸入
mosquitto_sub -d -t hello/world

傳輸端的RPI輸入
mosquitto_pub -d -t hello/world -m "Hello, MQTT. This is my first message."

然後你在接收端的RPI就會看到....."Hello, MQTT This ...."

接下來就是寫python 程式

先安裝必要的套件 screen

git clone git://git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.python.git
cd org.eclipse.paho.mqtt.python
sudo python3 setup.py install
sudo python setup.py install
cd
sudo nano test3.py


寫一個 python 程式 test3.py.... run在接收端

import paho.mqtt.client as mqtt

def on_connect(client,userdata,flags,rc):
       print("connect with result code"+ str(rc))
       client.subscribe("hello world")

def on_message(client,userdata,msg):
      print(msg.topic+" "+str(msg.payload))
      message = str(msg.payload)
      if(message=="b'led")
             print("LED Yaaay")

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost",1883,60)
client.publish("hello/world","online")
client.loop_forever()

=======================================
sudo python3 test3.py


然後在傳輸端RPI 輸入
mosquitto_pub -d -t hello/world  "Led"

就會在接收端的RPI出現

LED Yaaay





[Create Screen Session]
sudo screen ­S [NAME]
[Re­attach/list Screen Session]
sudo screen ­r
[Re­attach to id Screen Session]
sudo screen ­r [id]








Reference : http://learn.linksprite.com/pcduino/linux-applications/how-to-install-mosquitto-mqtt-on-pcduino-ubuntu/
Reference : https://www.youtube.com/watch?v=OHEsy9oJEi0
Reference : http://mqtt.org/
Reference : http://cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pimqtt-android.html
Reference : http://blog.maxkit.com.tw/2014/01/mqtt.html

2016年1月25日 星期一

用iphone和你的Raspberry溝通


國外有神人寫了一個apple 的app...用app來遙控你的 raspberry cam....

berrycam

然後還有更猛的.....有人弄了一個siriProxy...run 在raspberry....然後用iphone

的siri下命令....然後把指令傳給Raspberry....用GPIO來turn on Relay...打開車庫的大門

影片如下

SiriProxy on the Raspberry Pi

siriProxy 的github的連結在下面

https://github.com/plamoni/SiriProxy

Reference : http://sourceforge.net/p/siriproxyrpi/wiki/Home/

Reference : https://gist.github.com/elvisimprsntr/4409751






用Raspberry 來玩遙控汽車





Reference : 用鍵盤透過無線網路控制智能車

Reference : https://www.raspberrypi.com.tw/3839/1501/

raspberry i2c 的研究


先快速check 一下你的i2c device有沒有連接上


先安裝必要的套件

sudo apt-get install python-smbus
sudo apt-get install i2c-tools

然後確定你的i2c port  有被打開

如果你 run的是  Raspiban ...請check

/etc/modprobe.d/raspi-blacklist.conf

並且把    blacklist i2c-bcm2708 這行給Mark

如果你用的os  是 Whzeezy 或是不同於  Occidentali...你還需要在 /etc/modules

裡面加入下列兩行
 i2c-dev
i2c-bcm2708

輸入
sudo i2cdetect -y 1 

就會得到下列這些資料



這是一個快速查詢你的i2c device有沒有連接上去....也check 腳位有沒有接錯


i2c 一些基本操作


Hipi::Device::I2C 提供和i2c 裝置溝通

你也可以動態的載入i2c device driver


modprobe i2c_bcm2708
modprobe i2c_dev

這樣的好處是不是root 的使用者也可以使用這個裝置...

/dev/i2c-1  是預設的device 裝置...使用的是 GPIO PAD1 pins.....
/dev/i2c-0  是使用 GPIO PAD5 pins
/dev/i2c-0 /dev/i2c-1

如果你想改變i2c 的baudrate..你可以用 modprobe 的時候來指定


modprobe i2c_bcm2708 baudrate=32000

然後你可以查看  /etc/modprobe.d  ....你會看到有多了這一行

options i2c_bcm2708 baudrate=32000



bcm2835 i2c hw  

 下面這張圖是bcm2835 i2c 的主要register map...看得出來register 不多...大概只有七個
首先來看看i2c device driver ...連結如入
首先來看看這幾行
建立了一個 名字為 bcm2835_i2c_driver 的 platform_drvier struct..
其中 probe -> bcm2835_i2c_probe
remove -> bcm2835_i2c_remove
比較重要...
接下來先來看 bcm2835_i2c_remove
最主要的就是把 irq給 release..... 然後把 i2c delete...
接下來再來看 bcm2835_i2c_probe
由於行數太多...我就不一一的貼出來....
用google 查了一下 devm_kzalloc...他的意思如下
Memory allocated with this function is automatically freed on driver detach
     意思是說用這種function 配置出來的memory會被自動地釋放當device 拔除時...
   所以這行的意思是說...就是去要求一段核心的記憶體...其大小是  sizeof(*i2c_dev)
 接下來是
把設備的相關信息放到設備結構裡,需要使用的時候可以方便的拿出來
大概就類似這樣
static inline void dev_set_drvdata(struct device *dev, void *data) { dev->driver_data = data; }
接下來就是要求 i2c 的register base... 放在變數 i2c_dev->regs
i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
                                    &bus_clk_rate);
divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate);
接下來就是 寫入硬體的reg.....
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
從 bcm2835.c 可以查到
#define BCM2835_I2C_DIV         0x14
從HW 的datasheet來看....
就是把  Clock Divider的值存進去....
公式為  SCL = core clock/ CDIV
再來看  bcm2835_i2c_writel 的實作
static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev,
                                       u32 reg, u32 val)
 {
         writel(val, i2c_dev->regs + reg);
 }
就是把 divider的值寫入到   BCM2835_I2C_DIV所指的register....
接下來就是去要irq.....
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,
                           dev_name(&pdev->dev), i2c_dev);
當i2c 產生中斷時....會跳到  bcm2835_2ic_isr 的function 去執行
adap = &i2c_dev->adapter;
i2c_set_adapdata(adap, i2c_dev);
adap->algo = &bcm2835_i2c_algo;
static const struct i2c_algorithm bcm2835_i2c_algo = {
         .master_xfer    = bcm2835_i2c_xfer,
         .functionality  = bcm2835_i2c_func,
 };
跟系統告知說..當要執行  
master_xfer -> bcm2835_i2c_xfer
functionality -> bcm2835_i2c_func
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
#define BCM2835_I2C_C           0x0
其用意就是先全部disable....
ret = i2c_add_adapter(adap);
查了一下google....大概就是把adapter 加進去
   這些大概就是 i2c_probe 的 主要code....
接下來看當中斷發生時會處理甚麼事情 bcm2835_i2c_isr()
static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
 {
         struct bcm2835_i2c_dev *i2c_dev = data;
         u32 val, err;
 
         val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
         val &= BCM2835_I2C_BITMSK_S;
         bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
 
         err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
         if (err) {
                 i2c_dev->msg_err = err;
                 complete(&i2c_dev->completion);
                 return IRQ_HANDLED;
         }
 
         if (val & BCM2835_I2C_S_RXD) {
                 bcm2835_drain_rxfifo(i2c_dev);
                 if (!(val & BCM2835_I2C_S_DONE))
                         return IRQ_HANDLED;
         }
 
         if (val & BCM2835_I2C_S_DONE) {
                if (i2c_dev->msg_buf_remaining)
                         i2c_dev->msg_err = BCM2835_I2C_S_LEN;
                 else
                         i2c_dev->msg_err = 0;
                 complete(&i2c_dev->completion);
                 return IRQ_HANDLED;
         }
 
         if (val & BCM2835_I2C_S_TXD) {
                 bcm2835_fill_txfifo(i2c_dev);
                 return IRQ_HANDLED;
        }
 
         return IRQ_NONE;
 }
第一步 先 check register BCM2835_I2C_S(0x4)
val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
         val &= BCM2835_I2C_BITMSK_S;
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
把status 讀出來放在  val...接著把 Register BCM2835_I2C_S reset
   #define BCM2835_I2C_BITMSK_S    0x03FF


接下來就是check 各個 bit
val & BCM2835_I2C_S_RXD -> bcm2835_drain_rxfifo(i2c_dev);
val & BCM2835_I2C_S_TXD -> bcm2835_fill_txfifo(i2c_dev);
  val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR) -> error
  val & BCM2835_I2C_S_DONE -> complete(&i2c_dev->completion);
  
接下來看怎麼傳送資料 bcm2835_fill_txfifo()
static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
 {
         u32 val;
  
         while (i2c_dev->msg_buf_remaining) {
                 val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
                  if (!(val & BCM2835_I2C_S_TXD))
                          break;
                  bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_FIFO,
                                     *i2c_dev->msg_buf);
                  i2c_dev->msg_buf++;
                  i2c_dev->msg_buf_remaining--;
          }
  }
 
  用一個while loop來check 要傳送的msg還有沒有....
   一開始先呼叫   bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); 
   #define BCM2835_I2C_S           0x4
   #define BCM2835_I2C_S_TXD       BIT(4)
   然後取出  I2C_TXD 的bit  -> val & BCM2835_I2C_S_TXD
   從下圖的datasheet可以看出....bit 4 的意思是Fifo can accepts data
   0 -> fifo full....  1 -> FiFo has space to accept data
  
                                     *i2c_dev->msg_buf);
#define BCM2835_I2C_FIFO        0x10
 
   然後就把資料寫到 BCM2835_I2C_FIFO register裡面
接下來看怎麼接收資料 bcm2835_drain_rxfifo()
static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev)
 99 {
100         u32 val;
101 
102         while (i2c_dev->msg_buf_remaining) {
103                 val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
104                 if (!(val & BCM2835_I2C_S_RXD))
105                         break;
106                 *i2c_dev->msg_buf = bcm2835_i2c_readl(i2c_dev,
107                                                       BCM2835_I2C_FIFO);
108                 i2c_dev->msg_buf++;
109                 i2c_dev->msg_buf_remaining--;
110         }
111 }
     一樣是看i2c_dev-> msg_buf_remaining 的數值...
如果不為零...代表有值...去i2c register讀出來...
讀data之前...要先check  BCM2835_I2C_S_RXD
#define BCM2835_I2C_S_RXD       BIT(5)
0 -> fifo is empty....  1-> Fifo contains at least one byte...
然後read BCM2835_I2C_FIFO register....
去把data 讀出來...

接下來看function bcm2835_i2c_func()

static u32 bcm2835_i2c_func(struct i2c_adapter *adap)
 {
         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
   回傳系統預設得  I2C_FUNC_I2CI2C_FUNC_SMBUS_EMUL
  

接下來看master_xfer bcm2835_i2c_xfer()

static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
                             int num)
 {
         struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
         int i;
         int ret = 0;
 
         for (i = 0; i < num; i++) {
                 ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
                 if (ret)
                         break;
         }
 
         return ret ?: i;
 }
 其實就是呼叫   bcm2835_i2c_xfer_msg 去check message...



Reference : https://learn.adafruit.com/adafruit-16-channel-servo-driver-with-raspberry-pi/configuring-your-pi-for-i2c
Reference : http://skpang.co.uk/blog/archives/575

Reference : http://raspberrypi.znix.com/hipidocs/topic_i2cdev.htm

Reference : Reading I2C Inputs using C

Reference : https://learn.sparkfun.com/tutorials/raspberry-pi-spi-and-i2c-tutorial

Reference : http://www.airspayce.com/mikem/bcm2835/

Reference : https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
Reference : bcm2835.h
Reference : i2c-bcm2835.c
Reference : http://mark0522.blogspot.tw/2014/08/i2c1.html