Powered by Drupal, an open source content management system

การประยุกต์ใช้งาน Embedded Linux Computer (ตอนที่ 12 - i2c in action)

พักเขียนไปหลายวัน ได้ไปเดินบ้านหม้อซื้อฮาร์ดแวร์ I2C มาเตรียมกันไว้แล้วใช่ไม๊ครับ ฮาร์ดแวร์และไดรเวอร์พร้อมแล้ว มาตอนนี้จะกล่าวถึงการทดสอบกันครับ
โปรแกรมที่เราจะใช้ในการทดสอบคือชุดโปรแกรมของ i2ctools พัฒนาโดยผู้พัฒนาไดรเวอร์สำหรับ I2C นี่แหละครับ(http://www.lm-sensors.org/wiki/I2CTools) ซึ่งจะช่วยให้เราสามารถใช้งานอุปกรณ์ I2C โดยไม่ต้องเขียนโปรแกรมเอง ก่อนอื่นก็ทำการติดตั้งโปรแกรมเข้าไปเป็นส่วนหนึ่งของ Image ของเราก่อนครับ ซึ่ง OpenWrt ได้เตรียมส่วนนี้ให้เราพร้อมแล้ว ขั้นตอนเป็นดังนี้ครับ
 
1. เปิดโปรแกรม VirtualBox แล้ว start Ubuntu แล้วไปยัง Terminal Program
 
$ cd ~/openwrt/kamikaze   ไปยังDirectoryที่ใช้ Make
$ mkdir package/i2c-tools   สร้าง package ใหม่ที่จะรวมเข้าไปใน Image
$ wget --no-check-certificate https://dev.openwrt.org/browser/packages/utils/i2c-tools/Makefile?format=txt -O package/i2c-tools/Makefile   ดึง Make file มาจากคลังโปรแกรมของ OpenWrt
$ vi pakage/i2c-tools/Makefile   แก้ไข Makefile ให้เหมาะสมกับ kernel 2.4 ที่ใช้ในระบบของเรา
 
2. คงคุ้นเคยแล้วนะครับว่าต้องเปลี่ยน DEPENDS:=@LINUX_2_6 เป็น DEPENDS:=@LINUX_2_4 เสียก่อน
 
 
3. Config การสร้าง Image ของเราเสียก่อนด้วย
$ make menuconfig
ไปยัง Utilities แล้วไปยัง i2c-tools (ตัวใหม่ที่เราเพิ่มเข้าไปในระบบจากการทำในข้อ 1 และ 2) กด Space Bar จนกระทั่งเปลี่ยนเป็นเครื่องหมาย * เพื่อเลือกให้ติดตั้ง Package เข้าไปใน Image ที่เราสร้าง
หลังจากนั้นให้ exit จาก make menuconfig แล้วเลือก save configuration
 
 
4. หลังจากทุกอย่างเรียบร้อยก็
$ make V=99
 
5. ตรวจสอบด้วยคำสั่ง
$ ls staging_dir/target-mipsel_uClibc-0.9.30.1/root-brcm-2.4/usr/sbin
จะเห็นไฟล์ i2cdetect, i2cdump, i2cget และ i2cset ซึ่งเป็นชุดคำสั่งของ i2c-tools ที่จะไปอยู่ใน /usr/bin ของ image ใหม่ของเรา
 
มาถึงจุดนี้เราได้อะไร
1. Image files (ภายใต้ ~/openwrt/kamikaze/bin) ที่รวมทุกอย่างที่จำเป็นในการใช้งาน i2c (Drivers + i2c-tools) พร้อมที่จะใช้ flash เข้าไปยัง ELC ของเรา
2. นอกจากจะได้ image ที่รวม i2c drivers และ i2c-tools ในข้อ 1 แล้ว ระบบยังสร้าง packages แยกต่างหากให้เราไปติดตั้งเพิ่มเข้ากับระบบที่มีอยู่เดิมโดยไม่ต้อง Flash Image ทั้งอันได้ด้วย โดย packages ที่ว่าจะอยู่ภายใต้Directory  ~/openwrt/kamikaze/bin/packages/brcm-2.4_uClibc-0.9.30.1 ดังนี้
 
kmod-broadcom-i2c_2.4.37.5+0.3-1_brcm-2.4.ipk
kmod-i2c-algo-bit_2.4.37.5-1_brcm-2.4.ipk
kmod-i2c-core_2.4.37.5-1_brcm-2.4.ipk
i2c-tools_3.0.2-1_brcm-2.4.ipk
 
ดังนั้นท่านมีทางเลือกสองทางที่จะเพิ่มความสามารถด้าน i2c ให้กับระบบ
1. Flash Image ใหม่ที่รวมความสามารถ i2c ให้กับ ELC
2. ติดตั้งเฉพาะ packages สี่ตัวที่จำเป็นเข้าไปยังระบบที่มีอยู่แล้วโดยย้าย file ทั้ง 4 ไปยัง web server ที่ท่านมีอยู่แล้วใช้คำสั่ง opkg install ตามด้วยURLของPackageนั้นๆ
 
หมายเหตุ
ผมเลือกวิธีแรกเพราะ i2c จะเป็นความสามารถฐาวรที่ผมต้องการให้มีใน ELC ของผม
 
มาถึงจุดนี้ทุกคนคงคล่องกับการแฟลช ELC ของท่านแล้วนะครับ ถ้ายังไม่คล่องกลับไปดูตอนก่อนๆที่ผมเขียนไว้ได้ครับ
Tips
ทุกครั้งที่ Flash Imageใหม่ท่านอาจจะรำคาญว่าต้องมานั่งแก้ไฟล์ /etc/config/network และ /etc/config/wireless พร้อมทั้งปิด dnsmasq ให้ทำดังนี้ครับ สร้างไฟล์ที่บรรจุข้อความ setup ของท่านเอาไว้ดังนี้ แล้วตัดแปะไปยัง console เวลา flash image ใหม่ก็จะประหยัดเวลาในการ setup ครับ
 
nvram set boot_wait=on
nvram set wait_time=10
nvram commit
uci set network.lan.ipaddr=192.168.1.111
uci set network.lan.gateway=192.168.1.1
uci set network.lan.dns=192.168.1.1
uci set wireless.wl0.channel=10
uci set wireless.wl0.disabled=0
uci set
wireless.@wifi-iface[0].mode=sta
uci set wireless.@wifi-iface[0].ssid=yourssid
uci set wireless.@wifi-iface[0].encryption=wep
uci set wireless.@wifi-iface[0].key=1234567890
uci commit
echo nameserver 192.168.1.1 >> /etc/resolv.conf
/etc/init.d/dnsmasq disable
reboot
 
 
ผมสมมติเลยนะครับว่าคุณได้เพิ่มความสามารถ i2c ไม่ว่าทางใดทางหนึ่งในสองทางที่กล่าวมาเรียบร้อยแล้ว บูทเครื่องใหม่แล้วให้ใช้คำสั่งดังนี้ครับ
 
$ lsmod
จะเห็นว่า i2c drivers ที่เกี่ยวข้องทั้งหมดถูกโหลดเข้าไปในระบบหมดแล้ว และ i2c-dev ยังได้ทำการสร้างไฟล์เทียมสำหรับใช้ในการติดต่อฮาร์ดแวร์จริงไว้ที่ /dev/i2c/0 ซึ่ง 0 จะเป็นหมายเลขของ i2c bus ที่เราจะใช้ในการใช้งาน i2c-tools ของเรา
 
i2c-tools
 
มารู้จักกับ tools ตัวแรกก่อนนะครับนั่นคือ i2cdetect ตัวนี้ใช้ในการตรวจสอบดูว่ามีอุปกรณ์ที่ต่ออยู่บนบัสของเราด้วย address อะไรบ้าง การใช้งานก็ใช้คำสั่ง i2cdetect แล้วตามด้วย bus number ซึ่งเท่ากับ 0 (/dev/i2c/0)
 
 
จากรูปจะเห็นว่า i2cdetect ตรวจสอบจากบัสเจอว่ามีอุปกรณ์ address 0x38 (pcf8574) และ 0x68 (RTC ds1307) อยู่ในระบบ เห็นแบบนี้ก็มีชัยไปกว่าครึ่งแล้วครับ
ขอยกวงจรมาอีกครั้งนะครับ
 
 
 
ยังมีอีกสามคำสั่งจากชุด i2c-tools ที่จะแนะนำครับคือ i2cset, i2cget, i2cdump โดยจะใช้ ds1307 RTC เป็นตัวอย่าง ดังนั้นมาทำความรู้จักกับ ds1307 กันสักนิดนะครับ
ds1307 เป็นชิพที่มี memory จำนวน 64 bytes โดย 8 bytes ล่างเป็น RTC และ 56 bytes บนเป็น RAM ที่สามารถใช้แบคอัพข้อมูลเอาไว้ได้ด้วยแบตเตอรี่ 3 V โดยการติดต่ออ่านหรือเขียนข้อมูลทำโดยผ่าน i2c interface และมี Address ประจำตัว 0x68
 
 
 
 
จะเป็นคำสั่งที่ใช้ในการ อ่านชุดของข้อมูลที่มีลักษณะคล้าย Memory มาลองดูกันนะครับ
 
 
 
$ i2cdump 0 0x68 b เป็นการอ่านค่าจาก i2c bus 0 โดยอ่านจากอุปกรณ์ Address 0x68 แล้วให้แสดงผลเป็น byte
 
โปรแกรมจะทำการติดต่อกับ i2c device address 0x68 ซึ่งก็คือ DS1307 แล้วแสดงค่าจากที่เก็บไว้ภายใน DS1307 จาก data address 0 ถึง 0xff  โปรดสังเกตุว่าเนื่องจาก DS1307 มี memory แค่ 0x3f ดังนั้น ค่า data addressที่เกินจากนั้นไปตั้งแต่ 0x40 ถึง 0xff ก็เปรียบเสมือนกับการอ่าน 0-0x3f ซ้ำกันอีกสามหนดังที่ได้ตีกรอบไว้
 
จากdatasheet เราสนใจข้อมูลใน 7 bytes แรกที่เกี่ยวกับ RTC สำหรับ byte ที่ 0 มีค่าเป็น 0x80 โดยบิทที่ 7 คือ ch ระบุไว้ใน datasheet ดังนี้
"Bit 7 of register 0 is the clock halt (CH) bit. When this bit is set to a 1, the oscillator is disabled. When cleared to a 0, the oscillator is enabled.
 
เริ่มต้น clear bit ด้วยคำสั่ง i2cset กันเลยครับ (อ้างอิง http://manpages.ubuntu.com/manpages/karmic/man8/i2cset.8.html)
 
 
$ i2cset -y 0 0x68 0 0
 
paramters ที่เรียงกันตามกลัง i2cset มีความหมายเป็นลำดับดังนี้ครับ
-y  ไม่ต้องถาม yes หรือ no ให้ลุยเลย
0 ใช้ i2c bus # 0 (/dev/i2c/0)
0x68 ติดต่อกับ DS1307
ให้ register ตำแหน่งที่ 0
มีค่าเท่ากับ 0
หลังจากนั้นใช้ i2cdump ตรวจสอบอีกครั้งจะสังเกตุว่า RTC เริ่มทำงาน เนื่องจาก 7 bit หลังของ register0 เป็นวินาที ดังนั้นจะสังเกตุได้ว่าข้อมูลที่อ่านซ้ำในรอบหลังๆตรงที่วงกลมไว้จะเริ่มมีค่าเพิ่มขึ้น
 
ด้วยวิธีการที่กล่าวข้างต้น เราสามารถใช้ i2cset ตั้งเวลาให้กับ RTC ของเราดังนี้ครับ
 
i2cset -y 0 0x68 1 0x46  ตั้งนาที = 46
i2cset -y 0 0x68 2 0x1    ตั้งชั่วโมง = 1
i2cset -y 0 0x68 3 0x06  ตั้งวัน = 6 (เสาร์)
i2cset -y 0 0x68 4 0x04  ตั้งวันที่ = 4
i2cset -y 0 0x68 5 0x10  ตั้งเดือน = 10
i2cset -y 0 0x68 6 0x09  ตั้งปี = 09
 
 
 
สำหรับคำสั่ง i2cget คงไม่ใช่เรื่องยากแล้วใช่ไม๊ครับ
ลองอ่านค่าของเดือนด้วยคำสั่ง
i2cget -y 0 0x68 5 b
ก็จะได้ค่า 0x10 กลับคืนมาครับ
 
หวังว่าคงสนุกกับ i2ctools นะครับ จากจุดนี้จะเห็นว่ามี Application มากมายที่เอาไปประยุกต์ใช้งานได้เช่น ถ้าเราหา Temperature sensor ที่เป็น i2c มาต่อกับ ELC ของเรา เราก็จะได้ wireless temperature data logger อย่างดีไว้ใช้งานเลยใช่ไม๊ครับ
 
i2ctools เหมาะสำหรับใช้ตรวจสอบการทำงานเบื้องต้นของ i2c bus และ i2c devices ซึ่งถ้าหากเราจะพัฒนาโปรแกรมเฉพาะเพื่อใช้งาน i2c bus ก็สามารถทำได้โดยติดต่อกับ /dev/i2c/0 โดยตรง ซึ่งจะกล่าวถึงในบทต่อไปนะครับว่าด้วยเรื่อง cross compile และ remote debugging ครับผม โดยเราจะมาว่ากันถึงวิธี compile โปรแกรมบน PC host แล้วเอาไปวิ่งบน ELC ที่เป็น mips พร้อมกับวิธีการ debug program ที่วิ่งอยู่บน mips ผ่าน PC Host ของเรา โปรดติดตามครับ