หน้าเว็บ

วันจันทร์ที่ 9 สิงหาคม พ.ศ. 2553

ใช้ printf library กับ TinyOS ผ่าน SerialForwarder

วันนี้ผมลองใช้ MoteLab ของ Harvard เพื่อจะทำการทดลองโปรแกรม TinyOS บนอุปกรณ์จริงจำนวนมาก ซึ่งผมลองดูตัวอย่างโค้ดของทาง MoteLab นั้นจะแสดงวิธีการเรียกค่าเก็บไว้ใน Message ที่ส่งผ่าน Master Serial Port ของทาง MoteLab

แต่ปัญหาต่อมาของผมคือตัวอย่างเหล่านั้นเป็นการส่งค่าประเภทที่เป็นตัวเลข ไม่ใช่ array และไม่ใช่ string ซึ่งที่ผมต้องการนั้นผมอยากจะใช้ library printf ของ TinyOS เพื่อแสดง String (ซึ่งเป็น array ของ char) แล้วส่งผ่านออกมาทาง Serial Port

ดังนั้นวิธีการของผมคือลองแกะโค้ดตัวอย่างของเค้าก่อนว่ามันต้องใช้ utility อะไรมาช่วยบ้าง ซึ่งโค้ดเค้านั้นเป็นภาษา python และมีการเรียกใช้ TestSerialMsg.py ซึ่งเป็น class ที่เก็บโครงสร้าง Message ที่ต้องการเอาไว้ ดังนั้นทำให้ผมพอจะเดาได้ว่าเราต้องมีการสร้าง PrintfMsg.py ขึ้นมาเพื่อใช้จัดการกับ Message ของไลบรารี printf ที่จะถูกส่งออกมา

ผมลองดู TestSerialMsg.py แล้วพบว่า class นั้นถูกสร้างมาจาก MIG ซึ่งใช้ในการ generate คลาสสำหรับโครงสร้าง Message นั้น แต่ว่าที่ผมเคยลองทำคือเอามา generate ออกมาเป็น .class ของภาษา java เท่านั้น ซึ่งตอนนั้นทำใน Makefile

ผมเลยลองสั่ง mig ดิบๆใน shell ดูก็พบว่ามันมี option ที่รองรับภาษา python ด้วย ดังนั้นผมจึงเริ่มไปไฟล์ที่เป็น structure ของ Message เริ่มต้นที่เป็นภาษา nesC ก่อน ก็พบว่ามันอยู่ที่ $(TOSROOT)/tos/lib/printf/printf.h

ดังนั้นก็ให้ไปที่ $(TOSROOT)/tos/lib/printf แล้วสั่งคำสั่งดังนี้

mig python -python-classname=PrintfMsg printf.h printf_msg -o PrintfMsg.py

จะได้ไฟล์ PrintfMsg.py ซึ่งไฟล์คลาสที่เก็บโครงสร้างของ Message แบบภาษา python ออกมา

ซึ่ง String นั้น Message นี้จะเก็บอยู่ตัวแปรอาเรย์ที่ชื่อ buffer ดังนั้นผมจึงลองไปดูที่ฟังก์ชัน getString_buffer() ที่ generate ออกมา และพบว่ามัน generate ผิด ไม่สามารถเรียกใช้ได้เพราะจะเกิด index out of bound นอกจากนั้นค่าที่ได้ยังไม่ใช่ String อีกด้วย โดยผมทำการแก้ไข 3 จุด คือ 1. เปลี่ยนขอบเขตเป็น 28 (จริงๆแล้วขึ้นค่า PRINTF_MSG_LENGTH ที่ define ไว้ใน printf.h) 2. ทำการจัดรูปเป็นเลขฐาน 16 แบบ 2 หลัก 3. ทำการแปลงเลขฐาน 16 ให้เป็น ascii character ซึ่งสุดท้ายแล้วฟังก์ชัน getString_buffer จะได้เป็นแบบนี้

import tinyos.message.Message
import binascii
...
...
def getString_buffer(self):
carr = "";
#for i in range(0, 4000):
for i in range(0, 28):
if self.getElement_buffer(i) == chr(0):
break
c = "%x" % (self.getElement_buffer(i) & 0xFF)
if (len(c) < 2):
carr += "0" + c
else:
carr += c
return binascii.unhexlify(carr)

*หมายเหตุ blog ผม indent มันเพี้ยน เวลาใช้จริงอย่าลืมจัด indent ให้ถูกต้อง

คราวนี้เวลานำไปใช้ก็ให้ลองดูตามตัวอย่าง TestSerial.py ของเค้า แล้วให้เพ่ิม

import PrintfMsg

แล้วเพิ่ม

self.mif.addListener(self, PrintfMsg.PrintfMsg)

และเวลาเรียกค่าออกมาให้ใช้

s = m.getString_buffer()

ก็จะได้ String ที่เกิดจากไลบรารี printf แล้วครับ แต่ว่าจะมีปัญหาเล็กน้อยคือถึงแม้เรา printf ออกมาเป็น String ยาวๆ แต่ว่าการส่งข้อมูลออกมาแต่ละครั้งจะเท่ากับความยาวที่กำหนดไว้เท่านั้น (ค่า default คือ 28) ดังนั้นมันจะตัดส่งออกมาทีละ 28 ตัวอักษร ถ้าต้องการให้มากกว่านั้นก็ลองไป compile ไลบรารี Printf กันใหม่ได้ครับ

ถ้าใครยังไม่เคยใช้ MoteLab เดี๋ยวว่างๆผมจะมาเขียนวิธีไว้ด้วยครับ

ระบบที่ทดสอบ
OS: Ubuntu 10.04
TinyOS: 2.1.1
Device: Harvard MoteLab

1 ความคิดเห็น:

chonnnn กล่าวว่า...

ขอบคุณสำหรับความรู้คับพี่