เมนู

วันอังคารที่ 5 กรกฎาคม พ.ศ. 2559

Pinguino สื่อสารผ่าน USB และ Com Port

               บทความนี้จะเขียนถึงการสื่อสารระหว่าง Pinguino บอร์ดกับคอมพิวเตอร์ โดยเรามีตัวเลือกว่าจะใช้ USB โมดูลในตัว PIC18F45K50 emulate เป็น com port สื่อสารกับคอมพิวเตอร์ผ่านทางโปรแกรมเทอร์มินอลต่างๆ  หรือจะใช้โมดูล USART ในตัวไมโครคอนโทลเลอร์สื่อสารแทนก็ทำได้ นอกจากนี้หากต้องการ USART มากกว่าหนึ่งโมดูลก็สามารถใช้ Software USART ที่มีเตรียมไว้ให้กับขา I/O อื่นๆได้อีก เดี๋ยวเรามาลองดูกันทีละโมดูลกันนะครับ

                USB CDC (Communication Device Class) คือการให้ USB ทำตัวเป็นตัวเชื่อมต่อสื่อสารแบบต่างๆ(https://en.wikipedia.org/wiki/USB_communications_device_class) แต่ที่ส่วนใหญ่เข้าใจกันก็คือ USB จำลองเป็น com port เมื่อเชื่อมต่อกับคอมพิวเตอร์ โดยใน Pinguino จะมีฟังก์ชันที่ช่วยในการใช้งาน USB CDC อยู่พอสมควร สิ่งที่เราต้องทำคือแค่เรียกใช้งานเท่านั้น ลองดูตัวอย่างโค้ดดังต่อไปนี้นะครับ

1:  void setup() {  
2:    // put your setup code here, to run once:  
3:    pinMode(USERLED,OUTPUT);    
4:  }  

5:  void loop() {  
6:    // put your main code here, to run repeatedly:  
7:     digitalWrite(USERLED, HIGH);  
8:     CDC.printf("On\n\r");  
9:     delay(1000);  

10:    digitalWrite(USERLED,LOW);  
11:    CDC.printf("Off\n\r");  
12:    delay(1000);  
13:  }  

               ตัวอย่างโค้ดนี้จะเหมือนกับในบทความที่ผ่านมาโดยสั่งให้ USER LED ติด และ ดับ ทุกๆ 1 วินาทีแล้วผมทำการเพิ่มให้มีการส่งข้อความว่า “On” เมื่อ USER LED ติดสว่าง และคำว่า “Off” เมื่อ USER LED ดับ จากบอร์ด Pinguino ไปยังคอมพิวเตอร์ผ่านทางสาย USB ที่เชื่อต่อนะแหละครับ โดยทางฝั่งคอมพิวเตอร์ผมก็ใช้โปรแกรมเทอร์มินอลมาอ่านหรือรับค่าแสดงข้อความ โดยสามารถกำหนด baud rate เท่าไหร่ก็ได้เพราะตัว USB จะจัดการให้เอง สังเกตนะครับว่าผมเพียงแต่เรียกใช้ฟังกชัน CDC.printf() เท่านั้นไม่จำเป็นต้องเซ็ทอัพโมดูล USB ใดๆก่อนเลยค่อนข้างสะดวกมากครับ ลองดูวิดีโอประกอบด้านล่างได้ครับ



               USART ( Universal Synchronous Asynchronous Receiver Transmitter ) เป็นโมดูลสื่อสารแบบอนุกรมที่นิยมมากแบบหนึ่งสำหรับไมโครคอนโทรลเลอร์ ใช้ติดต่อสื่อสารกับอุปกรณ์หรือเครื่องมือต่างๆได้มากมาย เช่น Bluetooth, RF, และอื่นๆ รวมถึงใช้สื่อสารกับคอมพิวเตอร์ได้อีกด้วย โดยก่อนเริ่มสื่อสารนั้นจำเป็นต้องกำหนด baud rate หรือความเร็วในการสื่อสารให้ตรงกันทั้งสองฝ่ายเสียก่อน โดยในตัวอย่างต่อไปนี้จะเซ็ทอัพให้ Pinguino สื่อสารกับคอมพิวเตอร์ที่ baud rate เท่ากับ 9600 bits per second ไม่มี hardware flow control ดาต้าบิทเท่ากับ 8 ไม่มี parity และมีเพียง 1 stop bit. โดยสามารถดูได้จากตัวอย่างข้างล่างนี้ครับ


1:  void setup() {  
2:    // put your setup code here, to run once:  
3:    pinMode(USERLED, OUTPUT);  
4:    Serial.begin(9600);  
5:  }  
6:  void loop() {  
7:    // put your main code here, to run repeatedly:  
8:     digitalWrite(USERLED, HIGH);  
9:     Serial.printf("LED On\n\r");  
10:    delay(1000);  

11:    digitalWrite(USERLED, LOW);  
12:    Serial.printf("LED Off\n\r");  
13:    delay(1000);  
14:  }  
              
              จากโค้ดตัวอย่างจะเห็นว่าเราเพียงจำเป็นต้องเซ็ท baud rate ที่เราต้องการในส่วน setup() ก่อนเริ่มใช้งาน USART โดยเรียกใช้ฟังก์ชัน Serial.begin() หลังจากนั้นเราก็สามารถใช้งานฟังก์ชัน Serial.printf() ในการส่งข้อความขึ้นไปยังคอมพิวเตอร์ผ่านทาง USART ได้แล้ว ตัวอย่างนี้จะเหมือนกับตัวอย่างแรกเกือบทั้งหมดเพียงเปลี่ยนมาใช้ USART แทน CDC เท่านั้น  ในการทดสอบเราจำเป็นต้องมี usb-to-serial มาต่อเข้ากับขา Tx และ Rx ของบอร์ด Pinguino ดังแสดงในรูปข้างล่างนี้นะครับ แล้วเราก็ใช้โปรแกรมเทอร์มินอล connect เข้ากับ com port ของ usb-to-serial นั้นๆก็จะสามารถเห็นข้อความ “LED On” และ “LED Off” สลับกันตามจังหวะการติด ดับ ของ USER LED  ลองดูวิดีโอดูครับ


รูป บอร์ด Pinguino เชื่อมต่อกับ USB-to-Serial



               Software Serial เป็นการใช้ขา I/O ของไมโครคอนโทลเลอร์มาทำงานให้เหมือนขา Tx และ Rx ของ USART บางครั้งก็เรียกว่า Bit Bang Serial  โดยทั่วไปในไมโครคอนโทลเลอร์ตัวเล็กๆ หรือไมโครคอนโทลเลอร์รุ่นเก่าๆ จะมี USART เพียงแค่ตัวเดียว แต่บางครั้งงานที่เรากำลังทำอยู่นั้นจำเป็นต้องใช้ USART มากกว่าหนึ่ง จะเปลี่ยนไมโครคอนโทลเลอร์เป็นตัวที่ใหญ่ขึ้นก็เปลืองและไม่ง่ายนัก Software Serial จึงเป็นทางออกที่น่าจะเหมาะสมกว่า แต่มันก็มีข้อจำกัดของมันเช่น ใช้กับการสื่อสารที่ baud rate สูงมากไม่ค่อยได้ ต้องคำนวณคาบเวลาของแต่ละบิต ครึ่งบิต ให้แม่นยำและเขียนโปรแกรมให้ถูกต้องด้วย ซึ่งก็ค่อนข้างยากและเสียเวลามากพอสมควร
                ใน Pinguino นี้ได้จัดเตรียมไลบรารี่ Software Serial ไว้ให้เราเรียกใช้งานได้อย่างง่ายดาย เราเพียงแค่ต้องกำหนดว่าจะใช้ PORT ใด และขาไหนให้เป็นขา Tx และ Rx รวมถึงค่า baud rate ที่ต้องการไว้ที่ส่วนบนของโปรแกรมที่เรากำลังจะเขียนดังตัวอย่างต่อไปนี้ ที่จะใช้ PORTB ขา RB4 เป็น Tx และขา RB5 เป็น Rx โดยกำหนด baud rate ไว้ที่ 9600 bits per second ดังตัวอย่างข้างล่างนี้

 #define SWBAUDRATE 9600// or 57600, 38400, 19200, 9600, 4800  
 // other baudrates 115200 2400 1200 were tried but did not work perfectly   
 #define _SW_PORT _PORTB // Transmit pin port and pin  
 #define TXDpin 4   
 #define RXDpin 5   
 #define SW_PORT_TXDpin PORTBbits.RB4   
 #define SW_TRIS_TXDD TRISBbits.TRISB4   
 #define SW_PORT_RXDpin PORTBbits.RB5   
 #define SW_TRIS_RXDD TRISBbits.TRISB5   
               
              ถัดมาก็จำเป็นต้องกำหนดให้ขา Tx เป็นเอ้าพุตเพื่อให้สามารถ on/off (bit bang) pin เพื่อให้สามารถส่งดาต้าออกไปจากไมโครคอนโทลเลอร์ได้ และกำหนดค่าเริ่มต้นของทั้งขา Tx และ Rx ให้เป็น high( 1 ) ก่อนดังตัวอย่างข้างล่างนี้ครับ ซึ่งเซ็ทอยู่ใน setup() ฟังก์ชัน


 SW_TRIS_TXDD = 0;  
 SW_PORT_TXDpin = 1;  
 SW_TRIS_RXDD = 1;  

หลังจากนั้นเราก็สามารถเรียกใช้งานฟังก์ชันของ Software Serial ได้อย่างง่ายดายเหมือนฟังก์ชัน Serial ในตัวอย่างที่สองที่ผ่านมาได้ ลองดูตัวอย่างโค้ดทั้งหมดได้ครับ


1:  #define SWBAUDRATE 9600// or 57600, 38400, 19200, 9600, 4800  
2:  // other baudrates 115200 2400 1200 were tried but did not work perfectly   
3:  #define _SW_PORT   _PORTB      // Transmit pin port and pin  
4:  #define TXDpin   4  // or 0, 2, 6  
5:  #define RXDpin   5  // or 1, 3, 7  
6:  #define SW_PORT_TXDpin   PORTBbits.RB4  // or 0, 2, 6  
7:  #define SW_TRIS_TXDD    TRISBbits.TRISB4 // or 0, 2, 6  
8:  #define SW_PORT_RXDpin   PORTBbits.RB5  // or 1, 3, 7  
9:  #define SW_TRIS_RXDD    TRISBbits.TRISB5 // or 1, 3, 7  

10:  void setup() {  
11:    SW_TRIS_TXDD = 0;  
12:    SW_PORT_TXDpin = 1;  
13:    SW_TRIS_RXDD = 1;  
14:    pinMode(USERLED, OUTPUT);  
15:  }  

16:  void loop() {   
17:    digitalWrite(USERLED, HIGH);  
18:    SwSerial.printf("USER LED On\n\r");  
19:    delay(1000);  
20:    digitalWrite(USERLED, LOW);  
21:    SwSerial.printf("USER LED Off\n\r");  
22:    delay(1000);  
23:  }  


USB-to-Serial ต่อเข้ากับขา 4,5 (Pinguino) หรือขา 8,9(Arduino)







ไม่มีความคิดเห็น:

แสดงความคิดเห็น