Monday 8 June 2015

[Mini Project]วิทยุ FM อัจฉริยะ : ตอนที่ 6 Code

      สำหรับโค้ดที่ได้นำมาโปรแกรมลงบนบอร์ดในส่วนของ  FM Receiver SPK-TFM-1010 ได้ทำการดัดแปลงมาจาก  AR1010 FM radio module library for Arduino ซึ่งเป็นการแปลงการใช้ Library Wire ของ Arduino มาเป็นการใช้ Library HAL แทน
- สามารถดาวน์โหลด Library  ต้นฉบับได้ ที่นี่

โดยทำการดัดแปลงภายในไฟล์ ar1010lib.cppโดยได้ทำการแก้ส่วน include ซึ่งได้เปลี่ยนจาก
#include <Wire.h> (สำหรับโค้ดนี้จะเป็น  Library  ที่ใช้ในการควบคุม  I2C )และ #include "WProgram.h"(Librar  คำสั่งพื้นฐานของ  Arduino) เหลือเพียง  #include "stm32f4xx_hal.h"
และทำการแก้ไข 2  ฟังก์ชันหลักดังนี้

       1. ฟังก์ชัน writeToRegister(uint8_t address, uint16_t data)
       

  ฟังก์ชัน writeToRegister จาก  Library ต้นฉบับ

ฟังก์ชัน writeToRegister  ที่ได้ทำการดัดแปลงแล้ว

   จากโค้ดด้านบนจะเห็นได้ว่าคำสั่ง  Wire.beginTransmission(-> เป็นคำสั่งที่ใช้ในการเริ่มต้นการเชื่อมต่อแบบ  I2C โดยจะส่งค่า Address  ของ  Slave ที่ต้องการติดต่อไป) , Wire.send(->เป็นคำสั่งที่ใช้ในการส่งข้อมูล) และ Wire.endTransmission (-> เป็นคำสั่งที่ระบุว่าสิ้นสุดการส่งข้อมูล )ได้ถูกรวมเหลือเพียงคำสั่งเดียวซึ่งก็คือคำสั่ง HAL_I2C_MASTER_Transmit() ซึ่งจะมีพารามิเตอร์ทั้งหมด  5 พารามิเตอร์ดังนี้
    1. I2c_HandleTypeDef* hi2c (ไว้ระบุว่าเราใช้  I2C  ตัวใด)
    2. uint16_t DevAddress (พารามิเตอร์ที่มีไว้ระบุ  Address  ของ  Slave ที่เราจะติดต่อ)
    3. uint8_t* pData (pointer  ของข้อมูลที่ส่ง)
    4.uint16_t size  (ขนาดของข้อมูลที่ส่ง)
   5. uint32_t Timeout
ซึ่งคำสั่งนี้จะทำการส่งข้อมูลในรูปแบบ I2C  ให้โดยอัตโนมัติ


       2. ฟังก์ชัน readFromRegister(uint8_t address)

                                        
ฟังก์ชัน readFromRegister จาก  Library ต้นฉบับ


ฟังก์ชัน  readFromRegister ที่ได้ทำการดัดแปลงแล้ว


   จากโค้ดด้านบนจะเห็นได้ว่าคำสั่ง  Wire.beginTransmission , Wire.send และ Wire.endTransmission ได้ถูกรวมเหลือเพียงคำสั่งเดียวซึ่งก็คือคำสั่ง HAL_I2C_MASTER_Transmit() เช่นเดียวกับฟังก์ชัน  WriteToRegister และในส่วนของการอ่านข้อมูลจากรีจีสเตอร์ซึ่งใน Library  เดิมจะใช้คำสั่ง  Wire.RequestFrom(DevAddress,size) และคำสั่ง  Wire. recieve() ได้ถูกแปลงเป็นคำสั่งHAL_I2C_MASTER_Recieve() ซึ่งจะมีพารามิเตอร์ทั้งหมด  5 พารามิเตอร์ดังนี้
    1. I2c_HandleTypeDef* hi2c (ไว้ระบุว่าเราใช้  I2C  ตัวใด)
    2. uint16_t DevAddress (พารามิเตอร์ที่มีไว้ระบุ  Address  ของ  Slave ที่เราจะติดต่อ)
    3. uint8_t* pData (pointer  ของข้อมูลที่จะรับ)
    4.uint16_t size  (ขนาดของข้อมูลที่จะรับ)
   5. uint32_t Timeout
ซึ่งคำสั่งนี้จะเป็นคำสั่งที่ใช้ในการอ่านข้อมูลในรูปแบบ I2C  

คำอธิบายฟังก์ชันการใช้งานในแต่ละส่วน

    ส่วนที่ 1 : ส่วนเชื่อมต่อของบอร์ด STM32-NUCLEO F401RE กับ FM Receiver SPK-TFM-1010
และ Ethernet module ENC28J60

Class main.cpp
 


 
     สำหรับใน Class main นี้เป็นส่วนของการเรียกใช้งานทั้งระบบโดยเริ่มแรกจะเป็นการกำหนดค่าเริ่มต้นให้กับ Peripheral ทั้งหมดและสร้าง object ขึ้นมาสอง object คือ radio เพื่อเรียกใช้คลาส AR1010 ในการควบคุมโมดูล FM Receiver และ object Udp เพื่อใช้ควบคุมโมดูล Ethernet ถัดมาจะทำการเชื่อมต่อเซิฟเวอร์แบบ UDP ระหว่างบอร์ด Nucleo กับ แอนดรอยด์แอพพลิเคชันโดยผ่านโมดูล Ethernet เมื่อเชื่อมต่อเสร็จแล้วจะรอรับแพคเกจซึ่งจะส่งค่าสตริงCommand กับ Value มาให้ หาก Command ที่ส่งมาเป็นคำว่า Frequency จะเรียกใช้คำสั่ง radio.setFrequency(value) เพื่อทำการเปลี่ยนคลื่นสัญญาณวิทยุ FM โดยที่เปลี่ยนไปตามค่า Value ที่รับเข้ามา หาก Command ที่ส่งมาเป็นคำว่า SeekUp จะเรียกใช้คำสั่ง radio.seek(‘u’) ซึ่งเป็นฟังก์ชันที่ใช้การค้นคลื่นสัญญาณ FM ใหม่ โดยเป็นการหาคลื่นที่มี่ความถี่สูงกว่า และServer จะส่งค่าสัญญาณความถี่ FM ใหม่ที่ได้กลับไปยังแอพพลิเคชั่น มา หาก Command ที่ส่งมาเป็นคำว่า SeekDown จะเรียกใช้คำสั่ง radio.seek(‘d’) ซึ่งเป็นฟังก์ชันที่ใช้การค้นคลื่นสัญญาณ FM ใหม่ โดยเป็นการหาคลื่นที่มี่ความถี่ต่ำกว่า และServer จะส่งค่าสัญญาณความถี่ FM ใหม่ที่ได้กลับไปยังแอพพลิเคชั่น หาก Command ที่ส่งมาเป็นคำว่า Volume จะเรียกใช้คำสั่งradio.setVolume(value) เพื่อทำการเปลี่ยนระดับเสียงโดยที่เปลี่ยนไปตามค่า Value ที่รับเข้ามา และหากCommand ที่ส่งมาเป็นคำว่า Android_Init จะทำการส่งค่าสัญญาณความถี่ของวิทยุ FM กลับไปเพื่อแสดงบนหน้าแอพพลิเคชั่น และ Command นี้



Class ar1010.h


   สำหรับ Class ar1010.h นั้นจะเป็น Class หลักที่ใช้ในการควบคุมโมดูล FM Receiverโดยมีส่วนที่เป็น Public ดังนี้
       1. Constructor รับค่า I2C_HandleTypeDef* I2C(ตัวจัดการ I2C ของ HAL)
       2. ฟังก์ชัน writeToRegister เป็นฟังก์ชันที่ใช้ส่งข้อมูลแบบ I2C ไปยังโมดูล FM Receiver โดยรับพารามิเตอร์เข้ามาสองอย่างคือ address ซึ่งเป็นแอดเดรสของรีจีสเตอร์ที่จะส่งและรับพารามิเตอร์ Dataคือข้อมูลที่จะส่งไป
       3. ฟังก์ชัน readFromRegister เป็นฟังก์ชันที่ใช้รับข้อมูลแบบ I2C ไปยังโมดูล FM Receiver โดยรับพารามิเตอร์ address ซึ่งเป็นแอดเดรสของรีจีสเตอร์ที่จะรับข้อมูลเข้ามา
      4. ฟังก์ชัน setSeekThreshold เป็นฟังก์ชันที่ไว้เซตค่า Threshold โดยจะมีพารามิเตอร์Threshold
      5. ฟังก์ชัน setFrequency เป็นฟังก์ชันที่มีไว้กำหนดค่าคลื่นวิทยุ โดยจะรับพารามิเตอร์ Frequency ซึ่งคือค่าคลื่นความถี่วิทยุที่เรากำหนด
      6. ฟังก์ชัน setVolume เป็นฟังก์ชันที่มีไว้กำหนดระดับเสียงซึ่งมีตั้งแต่ระดับ 0-18 โดยจะรับพารามิเตอร์ Volume ซึ่งคือค่าระดับเสียงที่เราต้องการกำหนด
      7. ฟังก์ชัน frequency เป็นฟังก์ชันที่ส่งค่าความถี่ของสัญญาณวิทยุในขณะนั้นกลับออกไป
      8. ฟังก์ชัน seek เป็นฟังก์ชันที่มีไว้หาคลื่นวิทยุโดยอัตโนมัติโดยจะมีพารามิเตอร์ direction ในการ       กำหนดว่าจะค้นหาคลื่นวิทยุที่มีความถี่สูงกว่าหรือต่ำกว่า หากต้องการให้หาขึ้นที่มีความถี่สูงกว่าให้ใส่ค่าพารามิเตอร์นี้เป็น ‘u’ หากต้องการให้ต่ำกว่าต้องกำหนดเป็น’d’และเมื่อค้นหาจบแล้วจะทำการส่งค่าความถี่ของสัญญาณวิทยุในขณะนั้นกลับออกไป

ส่วนที่เป็น Private มีดังนี้
      1. ฟังก์ชัน setBitInregister เป็นฟังก์ชันที่มีไว้กำหนดค่าบิตในรีจีสเตอร์ที่เราต้องการโดยจะรับพารามิเตอร์สามตัวคือ address คือแอดเดรสของรีจีสเตอร์นั้น,bit คือตำแหน่งของบิตที่เราต้องการเซต และ bitstate คือการกำหนดว่าบิตนั้นจะเป็น 0 หรือ 1
       2. ฟังก์ชัน setSeekDirection เป็นฟังก์ชันที่มีไว้กำหนด seek บิต ในรีจีสเตอร์โดยจะรับพารามิเตอร์ที่ชื่อว่า direction
       3. ฟังก์ชัน readLOInjection เป็นฟังก์ชันที่ใช้ในการอ่าน LO/HI INJECTION โดยรับพารามิเตอร์ lohi เป็นพารามิเตอร์การกำหนดว่าจะอ่านด้าน High หรือ Low โดยฟังก์ชันนี้จะส่งค่า RSSI กลับออกมา
      4. ฟังก์ชัน tuneWithAutoHiLo เป็นฟังก์ชันในการจูนหาคลื่นสัญญาณ


Class UIPEthernet.h




     สำหรับ Class UIPEthernetClass นั้นจะเป็น Class หลักที่ใช่ในการควบคุม ENC28J60 Ethernet Module ซึ่งต้นฉบับมาจาก mbed.org ซึ่งการดัดแปลงส่วนใหญ่ ดัดแปลงในไฟล์ Enc28J60Network.cpp โดยเป็นการเปลี่ยนจากการใช้ Library SPI ของ mbed มาเป็นของ HAL แทนและแก้ไขการ include standard library บางตัวเพื่อให้สามารถ Compile ผ่านได้ ซึ่งมีส่วนที่เป็น Public ดังนี้

      1. Constructor รับค่า SPI_HandleTypeDef* spi(ตัวจัดการ SPI ของ HAL), GPIO_TypeDef* cs(ตัวจัดการ GPIO ของ Pin CS), uint16_t cs_num(เลข Pin ที่ใช้เป็นขา CS)
      2. begin ทำหน้าที่ในการกำหนดค่า MAC Address, IP Address, DNS IP, Gateway IP, Subnet IP โดยสามารถเลือกได้ว่าจะค่า MAC Address เพียงอย่างเดียวหรือ กำหนดค่าอื่นๆเพิ่มได้
      3. maintain ใช้สำหรับการขอ IP ใหม่ในกรณีที่มีการใช้ DHCP ในการกำหนด IP
      4. localIP บอกค่า IP Address ปัจจุบัน
      5. subnetMask บอกค่า Subnet Mask Address ปัจจุบัน
      6. gatewayIP บอกค่า Gateway IP Address ปัจจุบัน
      7. dnsServerIP บอกค่า DNS IP Address ปัจจุบัน
      8. network เป็น object ของ Class Enc28J60Network ใช้ในการควบคุม Module

ส่วนของ Private

      1. in_packet, uip_packet, uip_hdrlen, packetstate, _dnsServerAddress, _dhcp, periodic_timer เป็นตัวแปรที่เอาไว้เก็บค่าที่ใช้ภายใน Object
      2. init ใช้ในการกำหนดค่าของ MAC Address ไปยัง ENC28J60
      3. configure ใช้ในการกำหนดค่า IP Address, DNS IP, Gateway IP, Subnet IP
      4. network_send ใช้ในการส่ง packet ผ่าน ENC28J60
     5. UIPServer, UIPClient, UIPUDP ประกาศ friend class
     6. chksum, ipchksum, upper_layer_chksum, uip_ipchksum, uip_tcpchksum, uip_udpchksum เป็นการทำ Checksum

ส่วนที่ 2 : ส่วนของสมาร์ทโฟนบนระบบปฏิบัติการแอนดรอยด์



1 Class ของ Android App จะเชื่อมกับหน้าต่างเพียงหน้าเดียวเท่านั้น ซึ่ง App นี้มีเพียงหน้าเดียวจึงมี Class เพียง Class เดียว โดยตัวแปรต่างๆเก็บค่าดังนี้
      1. my_port เก็บค่า port ของ Android ที่จะใช้ในการติดต่อ UDP
      2. send_port เก็บค่า port ของ STM32 ที่จะใช้ในการติดต่อ UDP
      3. ip_send เก็บค่า IP Address ของ STM32 ในรูปของ String
      4. ip เก็บค่า IP Address ของ STM32 ในรูปของ InetAddress
      5. datagramSocket เป็น Object ที่ใช้ในการจัดการ UDP Packet
      6. frequencyControl, volumeControl ใช้ชี้ไปยัง SeekBar ที่อยู่ในหน้า UI สำหรับควบคุมความถี่ FM และระดับเสียงของวิทยุ
      7. frequencyBox ใช้ชี้ไปยัง EditText ที่เอาไว้พิมรับค่าความถี่ที่จะฟังและแสดงค่าความถี่ปัจจุบัน
      8. minimum เป็นค่าความถี่ต่ำสุดที่กำหนดไว้
      9. oldBox เก็บค่า String เริ่มต้นสำหรับ frequencyBox
      10. progressChanged, volumeChanged ใช้เก็บค่าของ process bar ของ SeekBar frequencyControl, volumeControl ตามลำดับ

       ประกาศ Thread recv_udp ไว้เพื่อใช้ในการทำ Multithread ซึ่ง Thread นี้จะทำงานในการรับค่า UDP Packet ที่ส่งมาจาก STM32 ซึ่งเช็คว่ามีการส่งค่า ความถี่มาให้รึเปล่า ถ้ามีก็จะทำการอัพเดทค่าของ UI ให้ frequencyControl และ frequencyBox

 

   
      1. onCreate method นี้จะถูกเรียกตอนที่มีการเปิดแอพขึ้นซึ่งจะอ่านค่าของ ip port ต่างๆที่เซฟไว้มาและใส่ลงไปในตัวแปรที่ได้ประกาศไว้ พร้อมทั้งสร้าง object datagramSocket เพื่อใช้ในการส่ง UDP กำหนดค่าเบื้องต้นให้ UI และเริ่ม Thread recv_udp
      2. onDestroy จะถูกเรียกเมื่อมีการปิดแอพ โดยจะทำหน้าที่ในการสั่งปิด datagramSocket และ หยุด Thread recv_udp
      3. onCreateOptionsMenu ทำหน้าที่ในการสร้างเมนู option ซึ่งมี 3 เมนูคือ Set your Port, Set your destination ip, Set your destination port ตอนเริ่มเปิดแอพ
      4. onOptionsItemSelected ทำหน้าที่ในการจัดการเมื่อมีการกดใช้งาน option ใดๆซึ่งจะกำหนดไปเรียก show_popup โดยส่งค่า Arguments ต่างกันตามแต่ option ที่กล่าวไว้ในข้อ 3
      5. show_popup จะแสดงหน้าต่าง popup ขึ้นมาและถามค่าจากผู้ใช้ โดยค่าที่ถามจะขึ้นกับ option ที่กดเลือกมาซึ่งค่าจะถูกส่งมาจากข้อ 4
      6. send_freq ทำหน้าที่ในการส่ง UDP Packet ของความถี่ FM ที่ต้องการเปลี่ยนไปยัง STM32
      7. send_seekup ทำหน้าที่ในการส่ง คำสั่ง seekup ออกทาง UDP ไปยัง STM32
      8. send_seekdown ทำหน้าที่ในการส่ง คำสั่ง seekdown ออกทาง UDP ไปยัง STM32
      9. send_init ทำหน้าที่ในการส่งคำสั่ง Android_Init ไปยัง STM32 เพื่อรับค่าความถี่ที่ตั้งไว้กลับไปแสดงผล และกำหนดค่าเสียงเริ่มต้น
     10. onKeyDown ทำหน้าที่ Handle การกดปุ่มเพิ่มลดเสียงของตัวเครื่องให้ไปจัดการกับ SeekBar volumeControl ให้เพิ่มลดตามปุ่มกดได้



คุณสามารถดาวน์โหลด Code และไฟล์เอกสารของมินิโปรเจคได้ที่นี่









บทความนี้เป็นส่วนหนึ่งของรายวิชา 010123120 Embedded System Design Lab 
คณะวิศวกรรมศาสตร์ ภาควิชาวิศวกรรมไฟฟ้าและคอมพิวเตอร์
 มหาวิทยาลัยเทคโนโลยีพระจอมเกล้าพระนครเหนือ


1 comment:

  1. Playtech Launches New Casino For Android - JTM Hub
    Playtech, a leading supplier 아산 출장마사지 of high-end software 충주 출장안마 and 수원 출장샵 services, has partnered with leading 제주도 출장샵 operators 광주 출장마사지 in the global online gambling industry to create

    ReplyDelete