Topic 1: การต่อวงจร Microcontroller และการเขียนโปรแกรมควบคุมเบื้องต้น


จุดประสงค์

  • เข้าใจองค์ประกอบพื้นฐานของวงจรสมองกลฝังตัว
  • ทดลองต่อวงจรไมโครคอนโทรเลอร์อย่างง่ายโดยใช้ชิพไมโครคอนโทรเลอร์ตระกูล PIC หมายเลข 16F886 เป็นกรณีศึกษา
  • เข้าใจหลักการติดตั้ง Firmware ลงในไมโครคอนโทรล์เลอร์ผ่าน Hardware Programmer และผ่าน Bootloader
  • ได้ทดลองเขียนโปรแกรมภาษา C ในการควบคุมการทำงานของวงจรในเบื้องต้น

การทดลอง

อุปกรณ์ที่ใช้

  1. โปรโตบอร์ด – ใช้ต่อวงจร
  2. USB2Serial converter – ใช้เชื่อมต่อวงจรเข้ากับคอมพิวเตอร์ เพื่อการสื่อสาร และใช้เป็นแหล่งพลังงานสำหรับวงจร (ไฟที่ได้จาก USB นี้ไม่ควรนำไปขับมอร์เตอร์หรืออุปกรณ์อื่นที่กินไฟเกิน 500 mA)
  3. สาย USB
  4. PIC16F886 – ไมโครคอนโทรเลอร์ ทำหน้าที่เป็นสมองกลของวงจร
  5. SW1 – ปุ่มกด
  6. LED1, LED2 – ไฟ LED ควบคุมโดยโปรแกรมใน MCU ใช้แสดงสถานะต่างๆ
  7. LED3 – ไฟ LED ใช้แสดงสถานะว่ามีไฟเข้าวงจรหรือไม่
  8. R1,R2,R4 – ตัวต้านทาน 1 K Ohm ใช้จำกัดกระแสที่ไหลผ่าน LED
  9. R3 – ตัวต้านทาน 3.3 K Ohm ใช้ดึงสถานะของขา RB7 บน PIC ให้เป็น High ในขณะที่ไม่ได้กดปุ่ม
  10. C1 – ตัวเก็บประจุ 100 uF ใช้ทำให้ไฟในวงจรนิ่ง
  11. C2 – ตัวเก็บประจุ 0.1 uF เรียกว่า decoupling capacitor ใช้กำจัดสัญญาณรบกวนในระบบไฟก่อนเข้า CMU

LAB 1.1: ต่อวงจรไมโครคอนโทรเลอร์ และติดตั้ง Firmware

ไมโครคอนโทรเลอร์เป็น IC ที่มีองค์ประกอบของคอมพิวเตอร์ที่ค่อนข้างครบถ้วนสมบูรณ์อยู่ภายใน (CPU, RAM, ROM, ฯลฯ) และการจะทำให้ไมโครคอนโทรเลอร์ เริ่มทำงานนั้นก็ไม่ใช่เรื่องยาก อุปกรณ์อิเล็กทรอนิกส์ที่ต้องเสริมเข้าไปมีเพียงไม่กี่ชิ้นตามที่จะได้เห็นในการทดลองต่อไปนี้

ขอให้นักศึกษาต่อวงจรไมโครคอนโทรเลอร์ตามแบบต่อไปนี้

ขั้นตอนการต่อ

  1. ขอให้ตรวจสอบว่ากลุ่มตนมีอุปกรณ์ครบตามรายการที่รวบรวมไว้ในหัวข้อ “อุปกรณ์ที่ใช้” ข้างต้น
  2. อ่านหัวข้อ “คำแนะนำการต่อวงจร” ล่วงหน้าให้ดี
  3. ทำการต่อวงจร โดยภาพต่อไปนี้แสดงตัวอย่างของวงจรที่่ต่อเสร็จแล้ว

    การต่อวงจรข้างต้นใช้สายไฟมากกว่าที่จำเป็นเพื่อให้เห็นภาพได้ชัดภายใต้ข้อจำกัดของภาพสองมิติ  การต่อวงจรจริงไม่จำเป็นต้องตามแบบข้างต้น เช่น ขา GND ของ LED สามารถปักลงในแถบ GND ด้านบนของโปรโตบอร์ดได้เลย เป็นต้น

  4. เมื่อต่อวงจรเสร็จแล้วลองเสียบสาย USB แล้วดูว่าไฟ LED 3 ซึ่งบ่งบอกว่ามีไฟเข้านั้นติดหรือไม่ หากไม่ติดแสดงว่าน่าจะมีการลัดวงจรเกิดขึ้น หรือบอร์ดยังไม่ได้รับไฟ
  5. ให้นำ PIC ของกลุ่มตนไปอัดโปรแกรมทดสอบชื่อ

          hello world.hex  (คลิกขวาแล้วเลือก download)

    โดยวิธีการอัดโปรแกรมให้ดูจากหน้า “วิธีเขียนโปรแกรมลง PIC โดยใช้ PIC Burner

  6. ทดสอบการทำงานของระบบ นักศึกษาควรเห็นไฟ LED ดวงหนึ่งบนวงจรกระพริบทุก 1 วินาที
  7. ต่อวงจรเพื่อทดลองใช้ Bootloader ในการเขียน firmware ลงใน PIC แทนการใช้ PIC Burnerรายละเอียดของ Bootloader และวิธีการติดตั้งให้ศึกษาตามที่อธิบายไว้ในหัวข้อ “แนะนำหลักการ Bootloader และวิธีการติดตั้ง“การที่จะใช้ Bootloader ได้นั้นจะต้องเพิ่มวงจรเข้าไปสองส่วนคือ (1) ส่วนติดต่อสื่อสารกับคอมพิวเตอร์ ซึ่งทำโดยเชื่อมสัญญาณ Rx, Tx ของ USB to Serial เข้ากับ PIC  และ (2) เพิ่มวงจรปุ่มกดเข้าไป เพราะ Bootloader จะถูกกระตุ้นให้ทำงานเมื่อกดปุ่มSchematic ของวงจรจะมีรายละเอียดดังภาพ
    ภาพต่อไปนี้แสดงวงจรที่ต่อสำเร็จแล้ว โดยสายที่เพิ่มขึ้นจากเดิมคือเส้นสีแดง
  8. ทดลองโหลด Firmware ลง PIC ผ่าน Bootloaderต่อไปนี้เป็นขั้นตอนคร่าวๆ หากต้องการรายละเอียดให้ศึกษาที่ “แนะนำหลักการ Bootloader และวิธีการติดตั้ง
    8.1 เปิดโปรแกรม firmware downloader
    8.2 จ่ายไฟให้กับ PIC พร้อมกับกดปุ่ม SW1 ค้างไว้ จะเห็นไฟ LED ดวงหนึ่งสว่างขึ้น และติดค้าง
    8.3 ในโปรแกรม firmware downloader ให้โหลดโปรแกรม hello world.hex ที่เคยโหลดไว้
    8.4 เลือกเลข serial port ของตัว usb to serial (ต้องไปดูใน device manager) แล้วกดปุ่ม download
    8.5 หากสำเร็จ ให้เปิดปิดบอร์ดใหม่ และเปิด serial port ขึ้นมา (คลิกที่กล่อง Enable Terminal ในโปรแกรม Firmware Downloader) ซึ่ง นศ. ควรจะเห็นไฟ LED กระพริบ และมีข้อความ Hello World พิมพ์ออกมาบนหน้าจอคอมพิวเตอร์

คำแนะนำการต่อวงจร

ขอให้ต่อวงจรอย่างระมัดระวัง นักศึกษาจำนวนมากเสียเวลาในการแก้ไขวงจรเพราะต่อไม่ตรงตามแบบตั้งแต่แรก ต่อไปนี้เป็นข้อแนะนำที่อาจช่วยให้ทำงานได้ดีขึ้น

  • ใช้สายไฟให้น้อยที่สุด – อุปกรณ์บางอย่างที่ปักลงไปที่ขา PIC ได้โดยตรงโดยไม่ต้องใช้สายได้แก่ C1 ส่วนประกอบอื่นๆ ก็มักมีขาอุปกรณ์อย่างน้อย 1 ด้านที่ต่อเข้ากับขา PIC ได้โดยตรง
  • เลือกความยาวสายให้เหมาะสม – การใช้สายยาวเกินไปมักทำให้บอร์ดยุ่งเหยิง สายหลุดง่าย จัดเก็บลำบาก

breadboard-wiring-examples

  • อุปกรณ์บางชนิดมีขั้ว ต้องต่อให้ถูกด้าน – เช่น LED, C2 (100 uF), PIC, SW1 วิธีดูขั้วของอุปกรณ์โดยทั่วไปขาที่ยาวกว่าจะเป็นขาบวก ถ้าดูจากความยาวขาไม่ได้ก็ต้องอ้างอิงคู่มือ
  • ขา PIC จะเริ่มนับจากด้านบนซ้าย วนไปด้านล่างแล้วย้อนกลับขึ้นมาดังแสดงให้ภาพ PIC ด้านที่มีรอยบากตรงกลางคือด้านบน (ขอให้เทียบกับขาใน Schematic ให้ดี เพราะใน Schematic การนับขามักต่างกันไป)
    16f886 PIN overview
  • ปุ่มกด SW1 นั้นมี 4 ขา ซึ่งมีการเชื่อมต่อภายในดังนี้
    tact switch connection
  • กลุ่มใดที่ได้รับ protoboard รุ่น Wish 104  สายสัญญาณไฟและ Ground บน proto board ที่วิ่งอยู่บนล่างจะแยกเป็นฝั่งซ้ายและขวา (สังเกตุดูมีตัวอักษร W ขั้นกลาง) ถ้าจะใช้งานทั้งสองฝั่งต้องมีสายเชื่อมเสมอ (ข้อนี้พลาดกันบ่อย)
  • การต่อสายสัญญาณสื่อสาร UART นั้น เนื่องจากเป็นการต่อแบบ point-to-piont ดังนั้นขา Tx บนฝั่ง PIC จะต้องต่อเข้ากับขา Rx บนฝั่ง USB2Serial เพื่อให้ข้อมูลที่ออกจาก PIC ไปเข้าที่ฝั่งรับของวงจร USB2Serial ขา Rx บน PIC ก็ต้องไปเข้าขา Tx ของ USB2Serial ด้วยเหตุผลเดียวกัน

LAB 1.2 เขียนโปรแกรมควบคุม I/O พื้นฐาน

ให้นักศึกษาเขียนโปรแกรม PIC-C เพื่อควบคุมการทำงานของ GoGo Board ตามโจทย์ทั้งสามข้อต่อไปนี้

1. ควบคุม User LED  ให้กระพริบ ทุก 1 วินาที และส่งคำว่า hello world มายังคอมพิวเตอร์

แบบฝึกหัดแรกนี้ให้เขียนพฤติกรรมที่ทดลองไปแล้วใน Lab 1.1 นั่นเอง โดยในการเขียนโปรแกรมภาษา C สำหรับไมโครคอนโทรเลอร์นั้นจะต้องเข้าใจโครงสร้างและคำสั่ง ซึ่งจะเฉพาะเจาะจงสำหรับไมโครคอนโทรเลอร์ที่ใช้ และอาจต่างกันไปสำหรับ compiler แต่ละตัวอีกด้วย PIC-C จะมีรูปแบบพื้นฐานตามไฟล์ตัวอย่างต่อไปนี้

    โหลดตัวอย่างโปรแกรม helloworld.c

// ใช้ระบุหมายเลข PIC ที่ต้องการใช้
#include <16F886.h>

// กำหนดคุณสมบัติและความสามารถต่างของของ PIC ที่ต้องการเปิดหรือปิดการใช้งาน
#device ADC=10 *=16  

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES PUT                      //Power Up Timer
#FUSES NOMCLR                   //Master Clear pin not enabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOCPD                    //No EE protection
#FUSES BROWNOUT                 //Brownout reset
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOWRT                    //Program memory not write protected
#FUSES BORV40                   //Brownout reset at 4.0V
#FUSES RESERVED                 //Used to set the reserved FUSE bits
#FUSES INTRC_IO 

// กำหนดความเร็วการทำงานของ PIC โดย PIC แต่ละรุ่นจะมีความเร็วสูงสุดไม่เท่ากัน
// เช่น PIC 16F886 ที่ใช้นี้หากไม่มีตัวกำหนดสัญญาณนาฬิกาภายนอกก็จะทำงานได้
// เร็วที่สุด 8 MHz 
#use delay(clock=8M)

// เปิดใช้ port RS232 ซึ่งใช้ในการรับส่งค่าระหว่าง PIC กับคอมพิวเตอร์
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

// ฟังก์ชันหลักของโปรแกรม
void main()
{
   int i=0;

   while(1) {
      printf("hello world - %u\r\n", i++);  // พิมพ์ค่าออกมาทาง rs232 ไปยังคอมพิวเตอร์
      output_toggle(PIN_B6);  // สลับสถานะติดดับของขาที่ชื่อ B6
      delay_ms(1000);     // หน่วงเวลา 1000 ms (1 วินาที)
   }
}

โดยปกติแล้วการเขียนโปรแกรมทำได้โดยการแก้ไขฟังก์ชัน main() โดยไม่ต้องไปยุ่งกับคำสั่งก่อนหน้า ยกเว้นแต่ว่าต้องการปรับเปลี่ยนความสามารถของ PIC ซึ่งมักเป็นสิ่งที่ทำหลังจากมีความเข้าใจการทำงานของ PIC มากขึ้นแล้ว

ให้นักศึกษาลอง Compile โปรแกรมนี้ ผลที่ได้คือไฟล์ไบนารีที่มีนามสกุลเป็น .HEX ที่สามารถโหลดลงไปใส่ PIC ผ่านทาง bootloader ได้เช่นเดียวกับการทดลองที่ 1.1

2. ควบคุม User LED ให้ติดเฉพาะเวลาที่ผู้ใช้กดปุ่ม Run ค้างไว้ (กดติด ปล่อยดับ)

จุดประสงค์ของโจทย์ข้อนี้คือให้ทดลองแก้ไขฟังก์ชัน main() จากโจทย์แรก โดยมีคำสั่งที่จะเป็นประโยชน์ดังนี้

input(PIN_NAME);

ใช้อ่านค่าสถานะของขาไมโครคอนโทรเลอร์ที่ต้องการ  เช่น หากต้องการทราบว่าขาของปุ่มกด (ดูใน Schematic จะเห็นว่าคือ PIN_B7) มีสถานะสูงหรือต่ำก็เขียนโปรแกรมได้ดังนี้

if (input(PIN_B7)) {   
  // actions for logic high
} else {
 // actions for logic low
}

output_high(PIN_NAME) และ output_low(PIN_NAME);

จะกำหนดสถานะของขาให้เป็น high ให้ Low ตามลำดับ เช่น

output_high(PIN_B6);  // PIN_B6 becomes high

output_low(PIN_B6);  // PIN_B6 becomes low

3. นับจำนวนครั้งที่กดปุ่ม และพิมพ์ค่าออกมาทาง Firmware Downloader

ทุกครั้งที่กดปุ่มให้เพิ่มการนับขึ้น 1 และพิมพ์ค่านั้นออกมาทางหน้าจอของ Firmware downloader

ข้อนี้แม้ไม่ต้องใช้คำสั่งใหม่ แต่ให้ระวังการนับและพิมพ์ค่ารัวเมื่อกดปุ่มค้าง  การแก้ไขปัญหานี้จะต้องเขียนโปรแกรมเพื่อให้นับค่าแค่ครั้งเดียวต่อการกดหนึ่งครั้ง เช่น หลังจากที่พบว่ามีการกดปุ่ม ก็เขียนโปรแกรมให้รอจนกว่าจะปล่อยปุ่มถึงจะทำงานต่อ เป็นต้น

เอกสารที่เกี่ยวข้อง

แนะนำการใช้ PIC-C