วันศุกร์ที่ 22 มีนาคม พ.ศ. 2562

Multiprocessing Pool


  • เป็นอีกวิธีในการกระจาย process ต่างๆไปยัง CPU Core แต่ละ Core เพื่อช่วยในการประมวลผล
  • มีข้อดีที่สามารถ map function กับจำนวนข้อมูลเพื่อทำการกระจายไปยัง Core ต่างได้
  • สามารถเลือกจำนวนของ CPU Core ที่ต้องการใช้สำหรับทำงานได้
  • สามารถเก็บตัวแปรจากฟังค์ชันได้โดยไม่ต้องใช้ Queue
  • ลำดับของ Output จะเรียงตามลำดับของ Input ที่ป้อนเข้าไป

การปรับใช้ Pool ร่วมกับ Image Processing

  

    เราจะนำภาพที่ได้มาแยกออกเป็น 4 ส่วนเพื่อแบ่งการทำ image processing ไปในแต่ละ core ของ cpu โดย ภายใน image processing จะมีการทำ resize, convert color, Guassian blur, erode, dilate, threshold และ contour

ผลการทดสอบระหว่าง Serial และ Pool

  

     จากกราฟ ถ้าเทียบประสิทธิภาพการทำงานแบบ serial กับ Pool จะเห็นได้ว่า  เวลาในการทำงานแบบ Pool จะเร็วกว่า แบบ Serial 

วันอังคารที่ 12 มีนาคม พ.ศ. 2562

ทดลองการใช้ระบบ IOT ผ่าน esp 32

1.เข้าไปที่ https://netpie.io จากนั้นกดไปที่ Application




2.สร้าง Application ตามลูกศร



3.ตั้งชื่อโปรเจค และกด Create



3.สร้าง Application Key


4.สร้าง device key และ session key

  
 
5.ติดตั้ง library microgear โดยเข้าไปที่ Sketch ->  include library -> Manage Libraries
ค้นหาคำว่า microgear


6.แก้ไขโค้ดของโปรแกรม โดยนำรหัสจาก device key มาใส่ในโค้ด ตั้งชื่อ board และตั้งเป้าหมาย



#include <WiFi.h>
#include <MicroGear.h>
const char* ssid= "wifi_name";
const char* password = "wifi_password";

#define APPID   "tutorial"
#define KEY     "KnBSvq3QiWjJ9uE"
#define SECRET  "g8TmL3ZSeCBMNKyzJQ6coFrIv"
#define ALIAS   "Board1"
#define TARGET   "LivingRoom"
#define LED     D1
WiFiClient client;
int timer = 0;
MicroGear microgear(client);
void onMsghandler(char* topic, uint8_t* msg, unsigned int msglen){
  Serial.print("Incoming message --> ");
  Serial.print(topic);
  Serial.print(" : ");
  char strState[msglen];
  for(int i= 0; i< msglen; i++){
    strState[i]=(char)msg[i];
    Serial.print((char)msg[i]);
  }
  Serial.println();
  String stateStr = String(strState).substring(0, msglen);
  if(stateStr == "CH1ON")
  {
    digitalWrite(LED,HIGH);
    Serial.println("ON LED");
  }
  else if(stateStr == "CH1OFF")
  {
    digitalWrite(LED,LOW);
    Serial.println("OFF LED");
  }
}
void onFoundgear(char* attribute, uint8_t* msg, unsigned int msglen){
  Serial.print("Found new member --> ");
  for(int i=0; i<msglen; i++)
  Serial.print((char)msg[i]);
  Serial.println();
}
void onLostgear(char* attribute, uint8_t* msg, unsigned int msglen){
  Serial.print("Lost member --> ");
  for(int i=0; i<msglen; i++)
  Serial.print((char)msg[i]);
  Serial.println();
}
/*When a microgear is connected, dothis*/
void onConnected(char* attribute, uint8_t* msg, unsigned int msglen){
  Serial.println("Connected to NETPIE...");
  /* Set the alias of this microgearALIAS */
  microgear.setAlias(ALIAS);
}
void setup()
{
  microgear.on(MESSAGE,onMsghandler);
  microgear.on(PRESENT,onFoundgear);
  microgear.on(ABSENT,onLostgear);
  microgear.on(CONNECTED,onConnected);

  Serial.begin(115200);
  Serial.println("Starting...");
  pinMode(LED,OUTPUT);
  digitalWrite(LED,LOW);

  if(WiFi.begin(ssid, password))
  {
    while(WiFi.status() != WL_CONNECTED)
    {
      delay(500);
      Serial.print(".");
    }
  }
  Serial.println("WiFiconnected");
  microgear.init(KEY,SECRET,ALIAS);
  microgear.connect(APPID);
}
void loop()
{
  if(microgear.connected()){
    microgear.loop();
    bool led = digitalRead(LED);
    String status_LED;
    if(led == HIGH){
      status_LED="CH1ON,";
    }
    else{
      status_LED="CH1OFF,";
    }
    String data2freeboard = status_LED ;
    microgear.chat(TARGET,data2freeboard);
    Serial.print("Send message to NetPie: ");
    Serial.println(data2freeboard);
  }
  else{
    Serial.println("connection lost, reconnect...");
    if(timer >= 5000){
      microgear.connect(APPID);
      timer=0;
    }
    else timer += 100;
  }
  delay(1000);
}

7.จัดการกับ FreeBoard เริ่มโดยการเข้าไปในเมนู FreeBoard


8.กดปุ่มบวกเพื่อเพิ่ม Dash Board จากนั้นตั้งชื่อ โดยไม่ให้ซ้ำ และกดปุ่ม Create

 

9.กดปุ่มประแจ และ กดปุ่ม Add

 

10. ใส่ชื่อ Data Source และ Key ที่เราได้มา( Session Key)

 

11.เมื่อเสร็จ เราจะเห็นเวลาเดินอยู่ แปลว่า Freeboard ได้เชื่อมกับตัว ESP32 แล้ว


12.จากนั้นกดที่ Add pane และเลือก Data Sorce  ตาม Data Source ไปตามปัจุบัน

 

13. ซึ่งเลือกให้เป็น datasources["FreeBoard1"]["/SmartMirror/gearname/LivingRoom"] และกดเข้าไปที่ .js editor


14. เพื่อตัดคำเพื่อตรวจสอบต่อท้ายเป็น .split(",")[0] == 'CH1ON' เนื่องจากบอร์ดส่งข้อความ เมื่อ LED สว่าง CH1ON คือข้อความที่ส่งไป NETPIE 


15. ใส่คำสั่งเมื่ออยู่ในสถานะ ON และ OFF ดังนี้
microgear["FreeBoard1"].chat("Board1","CH1ON")
microgear["FreeBoard1"].chat("Board1","CH1OFF")


16.คลิ้กเข้าไปที่ add pane และเลือก Indicator light


17.เลือก Data source 


18. ตัดคำสั่งตอ่ท้าย .split(",")[0] == 'CH1ON'


19*

วันศุกร์ที่ 8 มีนาคม พ.ศ. 2562

ผลทดสอบการใช้ Multithreaded และ Multiprocessing ในการเรียกใช้ฟังค์ชันแยก

แบ่งการเรียกใช้ออกเป็น 6 แบบ คือ

1. เรียกใช้ฟังค์ชัน key mapping โดยไม่มีการใช้ Thread หรือ Multiprocessing



2. เรียกใช้ฟังค์ชัน key mapping โดยใช้ Thread




3. เรียกใช้ฟังค์ชัน key mapping โดยใช้ Multiprocessing



4. เรียกใช้ Multiprocessing กับฟังค์ชัน key mapping และใช้ Thread ในฟังค์ชันเก็บข้อมูลและประมวลผลภาพ





5. เรียกใช้ฟังค์ชัน key mapping ปกติ แต่ภายในฟังค์ชันเก็บข้อมูลและประมวลผลภาพนั้น จะถูกเรียกใช้แบบ Thread





6. เรียกใช้ฟังค์ชัน key mapping ปกติ แต่ภายในฟังค์ชันเก็บข้อมูลและประมวลผลภาพนั้น จะถูกเรียกใช้แบบ Multiprocessing





ผลการทดสอบ


ผลของการเรียกใช้ฟังค์ชัน key mapping โดยไม่มีการใช้ Thread หรือ Multiprocessing


ผลของการเรียกใช้ฟังค์ชัน key mapping โดยใช้ Thread


ผลของการเรียกใช้ฟังค์ชัน key mapping โดยใช้ Multiprocessing


ผลของการเรียกใช้ Multiprocessing กับฟังค์ชัน key mapping และใช้ Thread ในฟังค์ชันเก็บข้อมูลและประมวลผลภาพ


ผลของการเรียกใช้ฟังค์ชัน key mapping ปกติ แต่ภายในฟังค์ชันเก็บข้อมูลและประมวลผลภาพนั้น จะถูกเรียกใช้แบบ Thread


ผลของการเรียกใช้ฟังค์ชัน key mapping ปกติ แต่ภายในฟังค์ชันเก็บข้อมูลและประมวลผลภาพนั้น จะถูกเรียกใช้แบบ Multiprocessing


ตารางสรุปค่า FPS


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

วันจันทร์ที่ 4 มีนาคม พ.ศ. 2562

Control YouTube's Video Player with JavaScript


Initializing the player

<div id="video-placeholder"></div>
<script src="https://www.youtube.com/iframe_api"></script>

ต่อมา เราจะสร้างฟังก์ชัน ภายในจะมี youtube player อยู่ argument แรก เราจะใส่ Id ของ HTML element ที่เราจะใส่ตัว player ลงไป ของเราก็จะใส่คำว่า video-placeholder ต่อมาจะเป็น object ที่เก็บข้อมูลของ player
    - ขนาดของตัว player
    - id ของ video ที่ได้จากลิ้งค์ youtube เป็นรหัสที่อยู่ข้างหลัง "?v=" (https://www.youtube.com/watch?v=TslY0Tg1O5s)
    - PlayerVars objectใช้เก็บ available properties จาก โค้ดเราใส่ใช้กำหนด สี กับ playlist
    - events object ประกอบด้วย listener และ function API จะส่ง event object เป็น attribute ทีมี target กับ data อยู่
var player;

function onYouTubeIframeAPIReady() {

    player = new YT.Player('video-placeholder', {
        width: 600,
        height: 400,
        videoId: 'Xa0Q0J5tOP0',
        playerVars: {
            color: 'white',
            playlist: 'taJ60kskkns,FG0fTKAqZ5g'
        },
        events: {
            onReady: initialize
        }
    });

}

initialize() จะมีถูกเรียกใช้เมื่อ player โหลดมาเต็มแล้ว มันจะเริ่ม update เรื่อยๆตามวินาที

function initialize(){

    // Update the controls on load
    updateTimerDisplay();
    updateProgressBar();

    // Clear any old interval.
    clearInterval(time_update_interval);

    // Start interval to update elapsed time display and
    // the elapsed part of the progress bar every second.
    time_update_interval = setInterval(function () {
        updateTimerDisplay();
        updateProgressBar();
    }, 1000)


}


Displaying current time and video duration

    updateTimerDisplay() ใช้บอกถึงความยาวของวิดีโอ Method จะถูกเรียกใช้โดย player object เราสามารถดึงค่าวิดีโอที่เล่นไปปแล้วจาก getCurrentTime() และคสามยาวของวิดีโอจะได้จาก
     
// This function is called by initialize()
function updateTimerDisplay(){
    // Update current time text display.
    $('#current-time').text(formatTime( player.getCurrentTime() ));
    $('#duration').text(formatTime( player.getDuration() ));
}

function formatTime(time){
    time = Math.round(time);

    var minutes = Math.floor(time / 60),
    seconds = time - minutes * 60;

    seconds = seconds < 10 ? '0' + seconds : seconds;

    return minutes + ":" + seconds;

}


Progress Bar

    เราใช้ player.seekTo(sec) ในการไปยังจุดที่เราต้องการเล่น video

$('#progress-bar').on('mouseup touchend', function (e) {

    // Calculate the new time for the video.
    // new time in seconds = total duration in seconds * ( value of range input / 100 )
    var newTime = player.getDuration() * (e.target.value / 100);

    // Skip video to new time.
    player.seekTo(newTime);


});

Playback Controls

ใช้ควบคุมเพื่อเลือกเพลงถัดไป หรือเพลงก่อนหน้า

    $('#play').on('click', function () {

       player.playVideo();

    });

    $('#pause').on('click', function () {

        player.pauseVideo();

    });


Sound Options

$('#mute-toggle').on('click', function() {
    var mute_toggle = $(this);

    if(player.isMuted()){
        player.unMute();
        mute_toggle.text('volume_up');
    }
    else{
        player.mute();
        mute_toggle.text('volume_off');
    }

});

$('#volume-input').on('change', function () {
    player.setVolume($(this).val());

});

Changing Playback Speed

$('#speed').on('change', function () {
    player.setPlaybackRate($(this).val());

});


Changing Video Quality

    ทำให้สามารถเปลี่ยนคูณภาพวิดีโอได้

$('#quality').on('change', function () {    
    player.setPlaybackQuality($(this).val());
});


Playlists

    ทำให้สามารถดูวิดีโอถัดไป และวิดีโอก่อนหน้าได้


$('#next').on('click', function () {

    player.nextVideo()

});



$('#prev').on('click', function () {

    player.previousVideo()

});

วันเสาร์ที่ 2 มีนาคม พ.ศ. 2562

ผลทดสอบการติดตั้งกล้องในตำแหน่งต่างๆ

เนื่องจากการเปลี่ยนหน้าจอแสดงผลนั้นส่งผลต่อการติดตั้งกล้อง Kinect ซึ่งเป็น Sensor สำหรับรับภาพเพื่อนำมาทำการประมวลผลจึงได้มีการทดสอบการติดตั้งในจุดต่างๆดังนี้


จากภาพข้างต้นจะเป็นการทดลองติดตั้งกล้องบริเวณด้านล่าง โดยที่กระดาษเป็นตัวแทนขนาดของหน้าจอ



ผลจากการทดสอบพบว่ายังสามารถตรวจสอบมือได้ชัดเจนแต่เนื่องจากตัวกล้องอยู่ต่ำ ถึงทำให้การตรวจจับเลื่อนไปอยู่ด้านบน อาจเกิดปัญหาในการใช้งานได้



ต่อไปเป็นการทดสอบการติดตังจากด้านบนของจอแทน



จะพบว่าภาพที่ตรวจจับได้นั้นผิดเพี้ยนจากรูปมือพอสมควรเนื่องจากตำแหน่งของการตรวจจับอยู่สูง ทำให้ภาพที่ได้มานั้นไม่ออกมาเป็นรูปมือ

อีกปัญหาที่พบคือ หากไม่ติดตั้งกล้องให้แนบกับกระจก จะส่งผลทำให้เกิดการสะท้อนกลับของแสง Infrared ภายในกระจก ทำให้การตรวจจับผิดเพี้ยนได้

วันศุกร์ที่ 1 มีนาคม พ.ศ. 2562

ผลการตรวจวันอุณหภูมิของ CPU

จากการทดลองรันโค้ดการทำงานของ Serial, Multithread และ Multiprocessing เพื่อตรวจสอบอุณหภูมิของ CPU ตั้งแต่ก่อนแหละหลังทำงาน พบว่า

  • อุณหภูมิในตอนที่บอร์ดเริ่มต้นทำงานอยู่ที่ 39.7 องศาเซลเซียส
  • ก่อนทำงาน CPU มีอุณหภูมิที่ 41.9 องศาเซลเซียส
  • หลังการทำงาน Serial, Multithread และ Multiprocessing แบบเรียกฟังค์ชันครั้งเดียว CPU มีอุณหภูมิที่ 56.4 องศาเซลเซียส
  • ก่อนทำงานรอบที่ 2 CPU มีอุณหภูมิที่ 49.4 องศาเซลเซียส
  • หลังการทำงาน Serial, Multithread และ Multiprocessing แบบเรียกฟังค์ชันที่มีการทำซ้ำ 10000 ครั้ง CPU มีอุณหภูมิที่ 62.8 องศาเซลเซียส