Raspberry pi คุยกับ Arduino ด้วย I2C

หากท่านค้นหาข้อมูลเกี่ยวกับเรื่อง I2C (Integreated Square Circuit) [1]  รับรองได้มาอ่านเป็นตันๆ และหากท่านค้นหาเรื่องราวเกี่ยวกับการสื่อสารระหว่าง Raspberry Pi กับ Arduino ท่านก็จะได้ข้อมูลอีกเป็นตัน ๆ เช่นกัน  แต่หากท่านไม่มีเวลามากพอจะอ่านมันทั่งหมดก็มาอ่านตรงนี้ก็ได้ครับ สั้น ๆ อ่านง่าย ๆ





I2C เป็นวิธีการสื่อสารระหว่างอุปกรณ์พัฒนาโดย Philips [1] ที่สามารถนำมาใช้สื่อสารกันระหว่าง Raspberry Pi กับ Arduino ได้ ข้อดีของการใช้ I2C คือใช้การสื่อสารบน Bus ทำให้เราสามารถสร้างระบบสื่อสารระหว่างสื่อสารระหว่างอุปกรณ์ได้มากกว่า 1 คู่ที่ต่ออยู่บน Bus เดียวกัน โดยแต่ละอุปกรณ์จะแยกกันด้วย address เฉพาะ นึกถึงภาพว่าผู้โดยสารอยู่ในรถบัสคันเดียวกันก็สื่อสารกันได้ ในขณะที่การสื่อสารด้วย USB port หรือการใช้ Tx/Rx จะทำได้ที่ละคู่เท่านั้น






การสร้าง Bus

การสร้าง Bus ศัยเส้นทางสองเส้นทางคือ Serial Data (SDA) และ Serial Clock (SCL)  ท่านต้องตรวจสอบว่าอุปกรณ์แต่ละชิ้นมี PIN ใดเป็น SDA และ SCL เอง เพราะแต่ละรุ่นแต่ละชิ้นจะแตกต่างกันออกไป  การต่ออุปกรณ์แต่ละชิ้นก็ยึดหลักง่าย ๆ คือ
  1. ให้เอา SDA ของแต่ละอุปกรณ์เชื่อมต่อกัน และ 
  2. SCL ของแต่ละอุปกรณ์ก็เชื่อมต่อกัน
  3. อุปกรณ์ทุกชิ้นบน Bus ต้องต่อ Groud ร่วมกัน
  4. อุปกรณ์ทุกชิ้นต้องมีกระไฟฟ้าเลี้ยงที่เหมาะสมของแต่ละอุปกรณ์

ในกรณีของการต่อ Raspberry Pi ควรใช้อุปกรณ์เสริมคือ Bi-directional Logic Level Converter  มาต่อคั่นเพราะ Raspberry Pi ถือว่าเป็นอุปกรณ์ที่รับไฟฟ้าความต่างศักย์ที่ 3.3 V ส่วน Arduino จะเป็น 5 V  แต่ในเอกสารและ Tutorial หลายแห่งอ้างว่าไม่จำเป็นเนื่องจาก Raspberry Pi ได้มีการติดตั้งตัวต้านทานมาแล้ว แต่ก็เพื่อความสบายใจนะ ต่อไว้ก็ดี  ท่านสามารถหาซื้อ Bi-directional Logic Level Converter ได้จากผู้จำหน่ายหลายรายในประเทศไทยครับ ในกรณีของผมจะเป็นดังภาพ





Master and Slaves


บทบาทของอุปกรณ์ใน I2C มีสองบทบาทคือ Master กับ Slave ครับ ทำหน้าที่ต่างกันนิดเดียวคือ

  • Master จะเป็นคนสร้างสัญญาณนาฬิกา และจะเป็นคนเริ่มต้นการสื่อสาร
  • Slave เป็นคนรับสัญญาณนาฬิกา และคอยตอบสนองต่อการติดต่อมาจาก Master
ในโครงงานนี้ผมตั้งให้ Raspberry Pi รับบทเป็น Master เพราะมี OS ทำงานในส่วนงานวิเคราะห์ได้ดี ส่วน Arduino รับบทเป็น Slave 


อุปกรณ์และการต่อสายสัญญาณ


ในโครงงานนี้ผมใช้อุปกรณ์ดังนี้

  1. Raspberry Pi model B 
  2. Bidirectional Logic Level converter
  3. Arduino Pro Micro
  4. Jumping Wires

ผังการต่อสายระหว่างอุปกรณ์

Raspberry Pi

Arduino Pro Micro

pin 3 (SDA)  -->D2 (SDA)
pin 5 (SCL)  -->D3 (SDL)
pin 6 (GRD) -->GRD
หมายเหตุ
ในกรณีมีการต่อ Logic level converter คั่น ต้องตรวจสอบการต่อสายสัญญาณให้ถูกต้องตามคู่มือ หรือศึกษาการต่อโดยไม่มี Logic converter จาก [3]

ขั้นตอนการเตรียม Raspberry Pi

1. เอารายการ blacklist ออก 

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

ใส่ # ไว้ข้างหน้าสองบรรทัดนี้ (เดิมไม่มี # )

#blacklist spi-bcm2708
#balcklist i2c-bcm2708

แล้วบันทึก

2. load Module
sudo nano /etc/modules

แล้วเติมบรรทัดนี้เข้าไป
i2c-dev

แล้วบันทึก

3. ติดตั้ง I2C-tools

sudo apt-get install i2c-tools

** หากมีปัญหาในการติดตั้งอาจใช้คำสั่งนี้แล้วติดตั้งใหม่อีกครั้ง

sudo apt-get update --fix-missing


4. เพิ่ม user ให้กับ i2c

sudo adduser pi i2c

** ท่านอาจ user รายอื่นได้อีกนอกจาก pi (default user)

5. restart Raspberry Pi แล้ว login ด้วย user ที่ add ไว้ตามข้อ 4

6. ตรวจสอบ

 ls /dev/i2c*

Raspberry Pi รุ่นใหม่ จะกำหนดให้ i2c ใช้ port เป็น 1 ซึ่งท่านควรจะเห็น

/etc/i2c-1

ขึ้นบนหน้าจอ ลองใช้คำสั่ง

   sudo i2cdetect -y 1



จะได้ภาพที่คล้ายแบบนี้ ตัวเลขก็อาจแตกต่างกันไป

หมายเหตุ ตอนทดสอบท่านต้องต่อสาย Bus และให้ไฟฟ้าเลี้ยง Arduino ไว้เลยนะครับ



การเตรียม Arduino

การเตรียม Arduino ก็คือการสร้าง Sketch ขึ้นมาเพื่อทำงานตามปรกติ เพียงแต่ต้องใช้ Wire.h และกำหนด Address ของตัวเองขึ้นมา ผมยกตัวอย่าง Sketch ที่เขียนขึ้นเพื่อรับ-ส่งตัวเลขจำนวนเต็มระหว่าง Raspberry Pi กับ Arduino ให้ดูพอเป็นแนวทางสร้างความเข้าใจนะครับ



เขียน Sketch เสร็จแล้ว compile แล้วก็ upload ไว้ใน Arduino ตอนที่ทำไม่จำเป็นต้องต่อ I2C  Bus ก็ได้นะครับ

การเขียนโปรแกรมสื่อสารบน Raspberry Pi


เราสามารถใช้ภาษาใด ๆ ก็ได้ที่สนับสนุน I2C และทำงานบน Raspberry Pi ได้ เช่น Python, Java , C++ เป็นต้น ตัวอย่างของผมจะใช้ Python โดยเราต้องติดตั้ง python-smbus [2] ด้วยคำสั่ง

 sudo apt-get install python-smbus


ตัวอย่าง Python Code

import smbus
import time

ard_addr = 0x04 #design in arduino sketch

bus = smbus.SMBus(1) # 1 : i2c bus port you can see in /dev/i2c-1

def writeNumber(val):
   # to send a number to arduino
   bus.write_byte(ard_addr,val)
   return -1

def readNumber():
   number = bus.read_byte(ard_addr)
   print number
   return number

snd_num = 0
rcv_num = 0
stop_flag = False

while not stop_flag :
   writeNumber(snd_num)
   print "Send %d to Arduino" % snd_num
   rcv_num = readNumber()
   print "Recieved %d from Arduino" % rcv_num
   time.sleep(0.5)
   if snd_num == 10 :
     stop_flag=True
   else :
     snd_num = snd_num + 1



ทดสอบการทำงาน

1. ต่อสายต่าง ๆ ให้เรียบร้อย
2. ป้อนกระแสไฟเลี้ยง Arduino แล้ว start up Raspberry Pi
3. เรียกใช้ Python code บน Raspberry Pi ก็ได้ผลออกมาดังภาพ แสดงว่าเรารับ-ส่งข้อมูลระหว่าง Arduino กับ Raspberry Pi ผ่าน I2C Bus สำเร็จด้วยดี







---------------------------------------
เอกสารอ้างอิง
[1] http://en.wikipedia.org/wiki/I%C2%B2C
[2] http://www.acmesystems.it/i2c
[3] http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/

ความคิดเห็น