Search This Blog

Showing posts with label Microcontroller. Show all posts
Showing posts with label Microcontroller. Show all posts

Thursday, June 5, 2025

Exploring Edge AI with NXP's FRDM-MCXN947

Read this article in English

Auckland မှာ တလောက ကျင်းပတဲ့ NXP ရဲ့ NXP technology day ကို သွားဖြစ် လိုက်သေးတယ်။ သူတို့ရဲ့ နောက်ဆုံးပေါ် microcontroller တွေ၊ i.MX microprocessor တွေနဲ့ semiconductor technologies တွေ အဓိက ပြတာ။ NXP က ထိပ်သီး Dutch semiconductor ကုမ္ပဏီ တစ်ခု။ ပြီးတော့ automotive ၊ industrial ၊ IoT applications နဲ့ ဆိုင်တာတွေ အများဆုံး ထုတ်တယ်။ လက်ဟောင်း Philips နဲ့ Freescale ရဲ့ Kinetis MCU architecture တွေကို ပေါင်းစပ် လိုက်တဲ့ သူ့ ရဲ့ နောက်ဆုံးထွက် MCX microcontroller တွေထဲက MCXN947 ကိုတော့ တော်တော် သဘောကျတယ်။ ပါဝါ အစားနည်းပြီး၊ လုပ်ဆောင်မှု မြင့်မားတယ်။ နောက်ပြီး NPU ဆိုတဲ့ neural processing unit ပါတော့ on-device AI processing တွေ လုပ်ဆောင်နိုင် တယ်တဲ့။ Edge computing တွေ ပို ခေတ်စား လာတဲ့ အချိန်၊ ဒီလို energy-efficient ဖြစ်ပြီး၊ real-time AI ရတဲ့ hardware သေးသေး တွေက တော် တော် စိတ်ဝင်စား ဖို့ ကောင်းတယ်။


Friday, August 10, 2018

DIY Programmable Function Generator Using Arduino Uno

Arduino Uno ကို function generator အနေ နဲ့ သုံးပြီး လိုချင် တဲ့ low frequency waveform တွေကို စိတ်ကြိုက် ထုတ်နိုင် ပါတယ်။ သူ့ရဲ့ အားသာချက် က လိုသလို ပရိုဂရမ် ရေးပြီး စိတ်ကြိုက် customize အမျိုးမျိုး ထုတ်နိုင်၊ အချိန် အလိုက် ပြောင်းနိုင် တာဖြစ်ပြီး၊ အားနည်း ချက်ကတော့ အရမ်း မြင့်တဲ့ frequency တွေကို ထုတ် မပေးနိုင် တာ ဖြစ်ပါတယ်။ Arduino ရဲ့ analog output က pwm သုံးထား တာမို့ ရလဒ် ပိုကောင်းအောင်၊ pwm frequency ကို 8 kHz လောက် ပြောင်းထား ပါတယ်။ ဒီထက် ရလဒ် ပိုကောင်း ချင်ရင် DAC နဲ့ တွဲသုံး လို့လည်း ရပါတယ်။


Figure. Arduino function generator ၏ အထွက်ကို oscilloscope ဖြင့် တိုင်းတာ ရရှိပုံ။


Tuesday, June 6, 2017

Flash content protection for LPC824

LPC824 low cost 32-bit ARM Cortex-M0 microcontroller လေးကို OM13071 LPCXpresso824-MAX Development board သုံးပြီး evaluate လုပ်လို့ရတဲ့ အတွေ့အကြုံလေးကို ပြောချင်ပါတယ်။ Board မှာ သုံးထားတဲ့ MCU အမျိုးအစားက LPC824M201JHI33 ပါ။ အရွယ်အစား က 5 x 5 x 0.85 mm ပဲရှိတဲ့ 33 pins ပါတဲ့ HVQFN package ပါ။

သူ့အတွက် MCUXpresso Integrated Development Environment (IDE) ကို download လုပ်ပြီး၊ install လုပ်ပါမယ်။ အခြား လိုအပ်တဲ့ tools တွေကိုလည်း ဒီမှာ တွေ့နိုင်ပါတယ်။ MCUXpresso ကိုဖွင့် ပြီး workspace သတ်မှတ်ပြီးတဲ့ အခါ ဘယ်ဘက်အောက်နားက Quick Start Paner ထဲက Import projects from file system ... ဆိုတာကိုနှိပ်ပြီး Browse LPC open resources ကိုနှိပ်ပြီး နမူနာ တွေကို ယူနိုင်ပါတယ်။



Wednesday, May 18, 2016

DS1307 Real-time Clock

DS1307 Real-time clock လေးကို အသုံးပြုပုံ အကြောင်း ပြောချင်ပါတယ်။ AliExpress က module လေးဝယ်တာ ၁ ဒေါ်လာလောက်ပဲ ပေးရပါတယ်။ AT24C32 ဆိုတဲ့ 32k EEPROM လေးပါ အဆစ် ပါသေးတယ်။


Figure. Setup.


Thursday, March 24, 2016

Gyroscope L3G4200D

L3G4200D ဆိုတဲ့ STMicroelectronics ကထုတ်တဲ့ MEMS ultra-stable three-axis digital output gyroscope ကို သုံးကြည့်ဖြစ်ပါတယ်။ Aliexpress မှာ ရောင်းတဲ့ L3G4200D Module လေးက ၃ ဒေါ်လာ လောက်ပဲ ပေးရပါတယ်။


Figure. L3G4200 Gyroscope module


Thursday, January 21, 2016

Mesh Bee - JN5168

Mesh Bee က NXP ကထုတ်တဲ့ JN516x wireless chip ကိုသုံးပြီး seeed studio ထုတ်တဲ့ 2.4GHz wireless transceiver ပါ။ ကောင်းတာ တခုက သူက လုံးဝ open hardware, open source ပါ။ NXP ကပေးတဲ့ development environment နဲ့ tools တွေကလည်း free ရပါတယ်။

Thursday, November 26, 2015

DAC - Digital to Analog Converter

PWM (Pulse Width Modulation) တွေကို analog output တွေအနေနဲ့ အသုံးများပေမယ့် သူတို့က high frequency, high accuracy, hard real-time တွေအတွက်တော့ မသင့်တော်ဘူးလို့ ထင်ပါတယ်။ Analog signal အစစ်မထွက်တဲ့ အတွက် RC low pass filter ခံ သုံးပြန်ရင်လည်း ရလာမယ့် phase lag က hard real-time system တွေမှာ ပြဿနာ အကြီးကြီးပါ။ စျေးပေါ၊ သေးငယ်တဲ့ AD5641 လို DAC လေးတွေက သုံးရလွယ်ကူပြီး အဆင်ပြေတဲ့ solution ပါ။ AD5641 က 3 mm x 2 mm အရွယ်လေးပဲရှိပြီး၊ SPI interface ပါတဲ့ 14 bit DAC ပါ။ Power supply voltage က 2.7 V ကနေ 5.5 V အထိသုံးနိုင်ပါတယ်။ နမူနာ ဆက်သွယ် မှုတခုကို အောက်မှာ ပြထားပါတယ်။

ဒါကတော့ AD5641 တွေကို သုံးထားတဲ့ channel ၃ ခုပါတဲ့ digital to analog converter လေးပါ။ LPC54102 dual core ARM microcontroller ကိုသုံးပြီး AD5641 သုံးခုကို ပြိုင်တူ control လုပ်တဲ့ နမူနာ code ပါ။

Wednesday, November 25, 2015

CC2531 Zigbee USB Dongle

CC2531 USB Evaluation Module Kit ကိုသုံးပြီး wireless communication လုပ်ကြည့်တဲ့ အကြောင်းလေးပါ။ သူ့ရဲ့ website ကိုသွားပြီး CC USB Firmware Library and Examples ဆိုတဲ့ zip ဖိုင်ကို download လုပ်လိုက်ပါတယ်။ ဖိုင်ကိုဖြည်ပြီးတဲ့ အခါ Doc folder ထဲက CC USB Software Examples User’s Guide ထဲမှာ နမူနာပြထားတဲ့ USB RF Modem Example ကို စမ်းကြည့်ခဲ့ပါတယ်။

CC2531 Zigbee Wireless USB Dongle

Tuesday, November 24, 2015

Wireless Communication using CC2530 Zigbee Wireless MCU

CC2530 က IEEE 802.15.4 နဲ့ Zigbee တွေအတွက် RF transceiver နဲ့ 8051 MCU ကို ပေါင်းစပ်ထားတဲ့ system-on-chip (SoC) solution တခုပါ။ သူ့ကို သုံးပြီး wireless module စမ်းလုပ်ဖို့ အတွက် CC2530EM Evaluation Modules နှစ်ခု၊ SmartRF05EB Evaluation Boards နှစ်ခု၊ နဲ့ CC2531 USB Dongle တခုပါတဲ့ CC2530DK devolopment kit ကို ဝယ်တာ USD 400 လောက်ပေးရပါတယ်။ သူတို့နဲ့ သုံးဖို့အတွက် TI ရဲ့ ဝက်ဘ်ဆိုက်မှာ အလကားပေးတဲ့ SmartRF Studio ကို စက်ထဲမှာ install လုပ်ပါတယ်။

CC2530DK

Tuesday, November 17, 2015

Driving 28BYJ-48-5V Stepper Motor with ULN2003A Transistor Arrays on Arduino

28BYJ-48-5V Stepper Motor နဲ့ ULN2003A driver တွေက တော်တော် အသုံးများပုံရပြီး အလွယ်တကူ ဝယ်နိုင်ရုံတင်မက စျေးလည်း တော်တော်ပေါ ပါတယ်။ Stepper Library ကို မသုံးပဲ Arduino ရဲ့ Port B ကို သုံးပြီး Stepper motor ကို ထိန်းတဲ့ ရိုးရှင်းတဲ့ နမူနာလေး ဖော်ပြချင်ပါတယ်။


Figure. Driving 28BYJ-48-5V Stepper Motor with Arduino UNO using USB power.


28BYJ-48-5V Stepper Motor က 5V နဲ့ တိုက်ရိုက်မောင်းနိုင်ပြီး၊ unipolar stepper motor အမျိုးအစားပါ။ သူ့ရဲ့ schematic ကို အောက်မှာပြထားပါတယ်။


Figure. 28BYJ-48-5V Stepper Motor.


ULN2003A Transistor Arrays ကတော့ inductive load တွေကို drive လုပ်ဖို့ ဒီဇိုင်းလုပ်ထားတာမို့ အထဲမှာ free wheeling diode ပါ ပါ ပါတယ်။ Darlington pair သုံးထားတာမို့ အဝင် ဗို့ 1.4V လောက်ကနေ 30V အထိ ကြိုက်တဲ့ ဗို့နဲ့ တိုက်ရိုက်ဆက်ပြီး ထိန်းနိုင်ပါတယ်။


Figure. ULN2003A.


Wave drive, Full step drive နဲ့ Half step drive တွေကို သုံးပြထားတဲ့ နမူနာ ပရိုဂရမ် လေးကို အောက်မှာ ပြထားပါတယ်။


//Driving 28BYJ-48-5V Stepper Motor using ULN2003A Transistor Arrays
//Author: Yan Naing Aye
//Website: http://www.cool-emerald.com/

#include "StepperPortB.h"
//----------------------------------------------------------
void setup() {    
  StepperInit();//setup pins
  //StepperMode(WAVE);
  //StepperMode(FULL);
  StepperMode(HALF);
  //Serial.begin(9600);
}
void loop() {
  Step(4096,2500); //turn 4096 steps forward with 2500 us period for each step
  Step(-4096,2500);//turn 4096 steps backward with 2500 us period for each step
  //Serial.println(CS);
}


//File: StepperPortB.h
//Author: Yan Naing Aye
//Website: http://www.cool-emerald.com/

//Driving 28BYJ-48 – 5V Stepper Motor using ULN2003A Transistor Arrays
//----------------------------------------------------------
#ifndef StepperPortB_h
  #define StepperPortB_h
  #include "Arduino.h"
byte* S; //Stepping sequence

//Wave drive
//Step          0 | 1 | 2 | 3 | 0 |...

//Blue   = A :  1 | 0 | 0 | 0 | 1 | ...
//Pink   = B :  0 | 1 | 0 | 0 | 0 | ...
//Yellow = C :  0 | 0 | 1 | 0 | 0 | ...
//Orange = D :  0 | 0 | 0 | 1 | 0 | ...
byte Wave[4] = {0x01,0x02,0x04,0x08};

//Full Step drive
//Step          0 | 1 | 2 | 3 | 0 |...

//Blue   = A :  1 | 1 | 0 | 0 | 1 | ...
//Pink   = B :  0 | 1 | 1 | 0 | 0 | ...
//Yellow = C :  0 | 0 | 1 | 1 | 0 | ...
//Orange = D :  1 | 0 | 0 | 1 | 1 | ...  
byte FullStep[4] = {0x09,0x03,0x06,0x0C};

//Half Step drive
//Step          0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 |...

//Blue   = A :  1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |...
//Pink   = B :  0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |...
//Yellow = C :  0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |...
//Orange = D :  1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |...
byte HalfStep[8] = {0x09,0x01,0x03,0x02,0x06,0x04,0x0C,0x08};
int CS=0;//Current step
int N;
//----------------------------------------------------------
//Mode definition
#define HALF 0
#define FULL 1
#define WAVE 2
//Define the mode to drive the stepper motor
void StepperMode(int Mode) {  
  if(Mode==WAVE) {S=Wave; N=4;}
  else if(Mode==FULL) {S=FullStep; N=4;}
  else {S=HalfStep; N=8;}
}
//----------------------------------------------------------
//Turn stepper motor n steps
//with t microseconds period for each step
//positive n for forward dir and negative n for backward dir
void Step(int n,int t) {
  int CD=1; 
  if(n<0) {n*=-1; CD=-1;}
  for(int i=0;i<n;i++) {
    CS=(CS+(N+CD))%N;
    PORTB=S[CS];
    delayMicroseconds(t);
  }
}
//----------------------------------------------------------
//Initialize
void StepperInit() {
  //Setup port B (digital pin 8 to 13)
  //The two high bits (6 & 7) map to the crystal pins and are not usable
  //only 4 pins - 8 to 11 are used in this program
  //where Blue - pin 8 (LSB), Pink -pin 9, Yellow -pin 10, Orange -pin 11
  DDRB=0xff;
  PORTB = 0x00;  
}
//----------------------------------------------------------
#endif

Friday, September 25, 2015

Adafruit CC3000 WiFi for Arduino

WiFi သုံးပြီး microcontroller နဲ့ ဆက်သွယ်တဲ့ ဟာကို Arduino Uno နဲ့ Adafruit CC3000 WiFi Shield ကိုသုံးပြီး စမ်းကြည့်ထားတာပါ။ သူက Arduino ရဲ့ standard WiFi shield မဟုတ်တဲ့ အတွက် WiFi.h library ကို သုံးလို့မရပါဘူး။ ဒါ့ကြောင့် Adafruit CC3000 library ကို ဒေါင်းလုပ်လုပ်၊ un-zip လုပ်ပြီး C:\Program Files (x86)\Arduino\libraries folder ထဲမှာ ထည့်ဖို့လိုပါတယ်။


Figure. Adafruit CC3000 WiFi shield stacked with Arduino Uno.


Saturday, September 19, 2015

Controlling Your Hardware from the Web Using Arduino

Arduino Ethernet shield 2 ကိုသုံးပြီး အင်တာနက်ကနေ သင့်ရဲ့ hardware တွေကို လှမ်းပြီး ထိန်းတဲ့အကြောင်း ဆွေးနွေးချင်ပါတယ်။ Arduino Ethernet 2 Library ကိုသုံးပြီး server အနေနဲ့ နမူနာတခု၊ client အနေနဲ့ တမျိုး စမ်းကြည့်ပါမယ်။ နောက်ဆုံး version Arduino IDE ကို သုံးဖို့လိုပါတယ်။ ဒီနမူနာမှာတော့ Arduino IDE 1.7.6 ကိုသုံးထားပါတယ်။ Arduino Uno ကို Ethernet shield 2 တပ်ထားတဲ့ပုံကို အောက်မှာ ပြထားပါတယ်။


Figure. Arduino Uno paired with Arduino Ethernet shield 2.


Wednesday, September 16, 2015

Testing Dual-Core Microcontroller - LPC54102

LPC54102J512 MCU မှာ Cortex M4 Master တစ်ခုနဲ့ Cortex M0+ Slave ဆိုပြီး core နှစ်ခုပါပါတယ်။ LPCXpresso IDE v7.9.0 ကိုသုံးပြီး multicore systems တစ်ခုကို ဖန်တီးတာ၊ debug လုပ်တာတွေကို နမူနာ တစ်ခုရေးပြီး စမ်းကြည့်တဲ့ အတွေ့အကြုံကို ပြောချင်ပါတယ်။ LPCOpen ကို ဒေါင်းလုပ်လုပ်ထားပြီး Quickstart -> Import project(s) ကို နှိပ်ပြီး import လုပ် ထားဖို့လိုပါတယ်။


Thursday, September 10, 2015

Accelerometer LIS3DSH

LIS3DSH က STMicroelectronics ထုတ်တဲ့ 3-axis MEMS accelerometer တခု ဖြစ်ပါတယ်။ Full scale ကို &pm;2g ကနေ &pm;16g ထိ အမျိုးမျိုးရွေးလို့ ရပါတယ်။ အရွယ်အစားက လည်း 3mm x 3mm ပဲမို့ သေးသေးလေးပါ။ Digital output ကို SPI ဒါမှမဟုတ် I2C ကြိုက်တာသုံးလို့ရပါတယ်။ Supply voltage က 1.71 V ကနေ 3.6 V ထိပေးလို့ ရပါတယ်။ STEVAL-MKI134V1 adapter board လေး တခုဝယ်ပြီး စမ်းကြည့်ထားတဲ့ အတွေ့အကြုံ လေးအကြောင်း ပြောချင်ပါတယ်။


Figure. STEVAL-MKI134V1 - LIS3DSH adapter board for standard DIL24 socket.

Tuesday, August 4, 2015

Bluetooth Module to be Used with Microcontroller

HC-05 Master/Slave Bluetooth Module လေးက စျေးသက်သာပြီး (~SGD 16) သံုးရလွယ်တဲ့ Bluetooth module တစ်ခုဖြစ်ပြီး UART interface သံုးပါတယ်။ အဲဒီ HC-05 နဲ့ Arduino Uno microcontroller ကိုသံုးပြီး LED မီးလံုးကို ဖုန်းနဲ့ Bluetooth communication သံုးပြီး အဖွင့်၊ အပိတ် ထိန်း တဲ့ နမူနာတစ်ခု ကို ဆွေးနွေးပါမယ်။ တကယ်တော့ UART interface ပါတဲ့ ဘယ် မိုက်ကရိုကွန်ထရိုလာ မဆို သံုးလို့ရပါတယ်။


Figure. HC-05 Bluetooth module with Arduino Uno.

Thursday, March 6, 2014

Reading Rotary Encoder Using Microcontroller

Rotary encoder တွေကို ထောင့်ဘယ်လောက်လှည့်သွားသလဲ (angular position) နဲ့ ဘယ်လောက်ဘီးလည်ပြီး ရွေ့သွားလဲ (motion sensing) ဆိုတာတွေကို တိုင်းတာဖို့ သုံးလေ့ရှိပါတယ်။ Optical rotary encoder တွေမှာ အပေါက်လေးတွေ ပုံဖော်ပြီး ဖောက်ထားတဲ့ အချပ်ကလေး ပါလေ့ရှိပြီး၊ အလင်းထုတ်ပေးတဲ့ LED နဲ့ အလင်းကို အာရုံခံနိုင်တဲ့ photo detector ကြားမှာ အဲဒီ အဝိုင်းလေး လည်တဲ့အခါ၊ အလင်းကျသွား၊ အလင်းကွယ်သွားတဲ့ ပေါ်မူတည်ပြီး ဗို့အား အနိမ့်အမြင့် digital waveform တွေထွက်လာပါတယ်။


VEX Robotics Design System ကထုတ်လုပ်တဲ့ optical encoder တခု

Encoder တွေမှာ glitch တွေ မဖြစ်အောင် ပုံမှန် binary code အစား Gray code ကို သုံးလေ့ပါတယ်။ Gray code မှာ ကပ်ရပ်နံပါတ် တစ်ခုနဲ့ တစ်ခု အကြား ပြောင်းလဲတဲ့ bit အရေအတွက်က တစ်ခု ထက် မပိုတဲ့အတွက် glitch တွေ ဖြစ်မယ့် ပြဿနာကနေ ကာကွယ်ပေးပါတယ်။ Gray code 0 ကနေ 3 အထိကို အောက်က ဇယားမှာ ပြထားပါတယ်။

Tuesday, July 9, 2013

CAN bus

CAN Bus (controller area network) ဆိုသည်မှာ ဆက်သွယ်ရေး စနစ် တစ်ခုဖြစ်ပြီး မိုက်ခရိုကွန်ထရိုလာများ နှင့် အခြား အီလက်ထရွန်းနစ် ကိရိယာများကို ကွန်ပျူတာ မလိုအပ်ဘဲ အချင်းချင်း ဆယ်သွယ် နိုင်ရန် ပြုလုပ်ထားသော စနစ်ဖြစ်ပါတယ်။ CAN Bus ဟာ မက်ဆေ့ (message) အပေါ်တွင် အခြေခံသော ပရိုတိုကောလ်ဖြစ်ပြီး မော်တော်ယာဉ်များတွင် အဓိက အသုံးပြုလေ့ ရှိပေမယ့် စက်ရုံများနှင့် ဆေးဘက်ဆိုင်ရာ ကိရိယာများတွင်လည်း အသုံးပြုလေ့ ရှိပါတယ်။

Saturday, June 29, 2013

Using Analog to Digital Converter of AT89C51CC01 Microcontroller

AT89STK-06 starter kit ကိုသုံးပြီး 8051 microcontroller တစ်ခုဖြစ်တဲ့ AT89C51CC01 အတွက် analog to digital converter (ADC) အဝင် ကိုဖတ်တဲ့ C ကုဒ် တစ်ချို့ကို ရေးထားပါတယ်။ အဲဒီ မိုက်ခရို ကွန်ထရိုလာ မှာ 10 bit resolution ရှိတဲ့ multiplexed လုပ်ထားတဲ့ အဝင် ၈ ခုရှိပါတယ်။ ဒီနမူနာမှာ variable resister နဲ့ ဆက်ထားတဲ့ အဝင် ပင်နံပါတ် ၇ ကို ဖတ်ကြည့်ထား ပါတယ်။

Sunday, January 13, 2013

Changing sampling rate using quadratic regression

signal တစ်ခုရဲ့ sampling rate ကို 333Hz ကနေ 5000Hz ကို ပြောင်းဖို့ အတွက် လုပ်ကြည့်ထားပါတယ်။ ပိုမို ချောမွေ့တဲ့ ရလာဒ် ရချင်တာမို့ ပုံမှန် zero order hold (ZOH) ကို သုံးမယ့်အစား second order hold ကို သုံးကြည့်ထားတာပါ။ ဒီမှာ sampling rate ကို တင်ဖို့လုပ်ထားပေမယ့်၊ ဒီနည်းကို down sampling လုပ်ဖို့လည်း သုံးလို့ရပါတယ်။ အခြား ဖြစ်နိုင်ချေတွေကတော့ noise ကို phase delay မရှိပဲ filter လုပ်တဲ့ဟာမျိုးတွေ အတွက်လည်း သုံးလို့ ရနိုင်ပါတယ်။ real-time application တွေအတွက်ပေါ့။
Approach 1: Quadratic regression
Quadratic ဖန်ရှင်တစ်ခုကို အောက်ပါအတိုင်း သတ်မှတ်နိုင်ပါတယ်။

$$f=w_0+w_1 x + w_2 x^2$$

အနည်းဆုံး ဖြစ်အောင် လုပ်မယ့် cost function ကို အောက်ကလို သတ်မှတ်မှာပါ။

$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-f_i)^2$$
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)^2$$

ဒါဆို Optimal weights တွေကို differentiate လုပ်ပြီးသုည ညီလိုက်ပြီး ရှာနိုင်ပါတယ်။

$$\frac{\partial J(w)}{\partial w_0}=0$$
$$-\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)=0$$
$$w_0\sum_{i=1}^{n}1+w_1\sum_{i=1}^{n}x_i+w_2\sum_{i=1}^{n}x_i^2=\sum_{i=1}^{n}y_i$$

w1 နဲ့ w2 ကိုလည်း အဲဒီလိုပဲ ရှာလိုက်မယ် ဆိုရင် အောက်အတိုင်း ထပ်ရလာပါမယ်။

$$w_0\sum_{i=1}^{n}x_i+w_1\sum_{i=1}^{n}x_i^2+w_2\sum_{i=1}^{n}x_i^3=\sum_{i=1}^{n}y_i x_i$$
$$w_0\sum_{i=1}^{n}x_i^2+w_1\sum_{i=1}^{n}x_i^3+w_2\sum_{i=1}^{n}x_i^4=\sum_{i=1}^{n}y_i x_i^2$$

အဲဒီ equation သုံးခုကို မေ့ထရစ် ပုံစံ နဲ့ အောက်ပါအတိုင်း ရေးလို့ရပါတယ်။

$$ \begin{bmatrix} \sum_{i=1}^{n}1 & \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 \\ \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 \\ \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 & \sum_{i=1}^{n}x_i^4 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^{n}y_i \\ \sum_{i=1}^{n}y_i x_i \\ \sum_{i=1}^{n}y_i x_i^2 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$

Approach 2: Three equations
တကယ်တော့ ဒီကိစ္စမှာ နောက်ဆုံး အမှတ် ၃ ခုကိုပဲ သုံးလိုက်ရင်ရတဲ့ အတွက်၊ ညီမျှခြင်း သုံးကြောင်း ကို အောက်က အတိုင်း တစ်ခါတည်း ချရေးလို့လည်း ရပါတယ်။


$$y_1=w_0+w_1 x_1 + w_2 x_1^2$$
$$y_2=w_0+w_1 x_2 + w_2 x_2^2$$
$$y_3=w_0+w_1 x_3 + w_2 x_3^2$$
$$ \begin{bmatrix} 1 & x_1 & x_1^2 \\ 1 & x_2 & x_2^2 \\ 1 & x_3 & x_3^2 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$

Approach 3: Two equations အကယ်၍ x1=-1, x2=0, နဲ့ x3=1 လို့ သတ်မှတ်လို့ ရတယ်ဆိုရင် y2 က w0 နဲ့ ညီသွားပါမယ်။ နောက်ကျန်တဲ့ အမှတ် ၂ ခုကနေ ညီမျှခြင်း နှစ်ကြောင်းပဲ ရှင်းဖို့ လိုပါတော့တယ်။

$$y_1=y_2-w_1+ w_2$$
$$y_3=y_2+w_1+ w_2$$
$$ \begin{bmatrix} -1 & 1 \\ 1 & 1 \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
$$ \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} -0.5 & 0.5 \\ 0.5 & 0.5 \end{bmatrix} \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$

နောက် အောက်ကအတိုင်းရလာပါမယ်။

$$w_0=y_2$$
$$w_1=-0.5(y_1-y_2)+0.5(y_3-y2)$$
$$w_2=0.5(y_1-y_2)+0.5(y_3-y2)$$

အထက်ကနည်းတွေကို MatLab နဲ့စမ်းကြည့်ထားတာကို အောက်က ကုဒ်တွေမှာ တွေ့နိုင်ပါတယ်။
%-------------------------------------------------------------------------
clc;
close all;
clear all;
%-------------------------------------------------------------------------
% y= w0 + w1*x + w2* x^2;
%-------------------------------------------------------------------------
%Got x and y
x=[-1 0 1]';
Wo=[4 3 2]';
y=Wo(1)+Wo(2)*x+Wo(3).*x.*x;

%-------------------------------------------------------------------------
%Approach 1
%Polynomial regression of order 2
%For n=3
S1=3;
Sx=sum(x);
Sx2=sum(x.*x);
Sx3=sum(x.*x.*x);
Sx4=sum(x.*x.*x.*x);
Sy=sum(y);
Syx=sum(y.*x);
Syx2=sum(y.*x.*x);

P=[S1 Sx Sx2; Sx Sx2 Sx3; Sx2 Sx3 Sx4];
B=[Sy Syx Syx2]';
%P1=P^(-1);
W1=P\B

%-------------------------------------------------------------------------
%Approach 2
%Linear equations
A=[1 x(1) x(1)*x(1);1 x(2) x(2)*x(2); 1 x(3) x(3)*x(3)];
W2=A\y
%-------------------------------------------------------------------------
%Approach 3
%Only 2 linear equations
w0=y(2);
w1=-0.5*( y(1)- y(2))+0.5*( y(3)- y(2));
w2=0.5*( y(1)- y(2))+0.5*(y(3)- y(2));
W3=[w0 w1 w2]'
%-------------------------------------------------------------------------
အောက်ကပုံမှာ ဒီနည်းကို သုံးလို့ရတဲ့ ရလဒ် (အပြာ) နဲ့ ပုံမှန် zero order hold သုံးရင် ရမယ့် ရလဒ် (အနက်) တို့ကို ယှဉ်ပြထားပါတယ်။ ဒီနည်းက ပိုပြီး ညက်ညော ချောမွေ့တဲ့ ရလဒ်ကို ရပေမယ့် one sample delay ရှိသွားတာကိုတော့ သတိထားဖို့ လိုပါတယ်။
ဒီနည်းလမ်းကို LabVIEW မှာ C code သုံးပြီး လုပ်ထားတာကို အောက်ကပုံမှာ တွေ့နိုင်ပါတယ်။
ပထမ နှစ်ခုမှာ 3x3 matrix ကို inverse ရှာဖို့ လိုတဲ့အတွက် inverse ရှာတဲ့ C program လေးတစ်ခုကို ရေးပြီး စမ်းကြည့်ထားပါတယ်။
#include
#include
main()
{
    float M[3][3]={{3,0,2},{0,2,0},{2,0,2}}; //initialize a 3x3 matrix
    float N[3][3]={{0,0,0},{0,0,0},{0,0,0}}; //allocate for inverse
    int i,j;
    float d;
    //-------------------------------------------------------------------------
    N[0][0]=(M[1][1]*M[2][2]-M[2][1]*M[1][2]);
    N[1][0]=-(M[1][0]*M[2][2]-M[2][0]*M[1][2]);
    N[2][0]=(M[1][0]*M[2][1]-M[1][1]*M[2][0]);
    d=M[0][0]*N[0][0]+M[0][1]*N[1][0]+M[0][2]*N[2][0];
    N[0][0]/=d;
    N[1][0]/=d;
    N[2][0]/=d;
    N[0][1]=-(M[0][1]*M[2][2]-M[0][2]*M[2][1])/d;
    N[1][1]=(M[0][0]*M[2][2]-M[0][2]*M[2][0])/d;
    N[2][1]=-(M[0][0]*M[2][1]-M[0][1]*M[2][0])/d;
    N[0][2]=(M[0][1]*M[1][2]-M[0][2]*M[1][1])/d;
    N[1][2]=-(M[0][0]*M[1][2]-M[0][2]*M[1][0])/d;
    N[2][2]=(M[0][0]*M[1][1]-M[0][1]*M[1][0])/d;
    //-------------------------------------------------------------------------
    //print 3x3 matrix
    for(i=0;i<3;i++)
    {
        for(j=0;j<3;j++) printf("%3.4f ",N[i][j]);
        printf("\n");
    }
    getch();
    return 0;
}

Tuesday, May 3, 2011

Byte Stuffing

ပစ္စည်း တစ်ခု ကနေ တစ်ခု data bytes တွေကို ပို့ဖို့ နဲ့၊ လက်ခံဖို့ အတွက် program တွေကို မကြာခဏ ရေးရပါတယ်။ ဒါနဲ့ပဲ ရိုးရှင်းတဲ့ byte stuffing မူကွဲ တစ်ခု ကို ရွေးပြီး data bytes တွေကို frame ဆောက် ပြီး ပို့ဖို့ နဲ့၊ လက်ခံဖို့ အတွက် လုပ်ရပါတယ်။ ပထမဆုံး အနေနဲ့ Frame ရဲ့ အစ နဲ့ အဆုံးကို သတ်မှတ်ဖို့ အတွက် control characters တွေ အနေနဲ့ 0x02 နဲ့ 0x03 ကို start of text (STX) ရယ်၊ end of text (ETX) ရယ် လို့ ထားလိုက် ပါမယ်။ လက်ခံရရှိတဲ့ ဒေတာ မှာ အမှား ပါမပါ စစ်ဖို့ အတွက် data bytes တွေရဲ့ exclusive-or တန်ဖိုးကို ETX နောက်မှာ အဆုံးသတ် checksum အနေနဲ့ ထည့်လိုက်ပါမယ်။ ပိုကောင်းတဲ့ error detection အတွက်တော့

CRC Calculation in VB and C

မှာဖော်ပြထားသလို CRC ကို သုံးလို့ ရပါတယ်။
ဥပမာ data byte နှစ်လုံး
0x30 0x31
ကို ပို့ဖို့ ဆိုရင်၊ ပို့ရမယ့် frame က
0x02 0x30 0x31 0x03 0x01
ဖြစ်ပါတယ်။ အစက 0x02 က STX အနေနဲ့ ထည့်ထားပြီး၊ data bytes တွေကို ပို့ပါမယ်။ ဘိတ်ရှေ့ က 0x03 က ETX အနေနဲ့ ထည့်ထားတာပါ။ data byte တွေရဲ့ exclusive-or (0x02^0x03) ဖြစ်တဲ့ 0x01 ကို checksum အနေနဲ့ နောက်ဆုံးက နေ ထည့်ထားတာပါ။ အကယ်၍ ပို့ရမယ့် ဒေတာမှာ control characters တွေ အနေနဲ့ သုံးထားတဲ့ 0x02 တို့၊ 0x03 တို့ ပါလာရင် ဘယ်လို လုပ်မလဲ လို့ မေးစရာရှိ ပါတယ်။ အဲဒီ အတွက် နောက်ထပ် control character 0x10 ကို Data Link Escape (DLE) အနေနဲ့ သတ်မှတ်ဖို့ လိုပါတယ်။ နောက်ထပ် ဥပမာ အနေနဲ့ data byte ငါးလုံး ဖြစ်တဲ့
0x30 0x02 0x65 0x10 0x03
အတွက် frame တစ်ခု ဆောက်ကြည့် ပါမယ်။ ဒေတာထဲမှာ STX တို့၊ ETX တို့၊ DLE တို့ ကိုတွေ့တိုင်း control character မဟုတ်ကြောင်း သိအောင် ရှေ့မှာ DLE တစ်လုံးကို အပို ထည့်ပေး မှာပါ။ ဒါဆို ပို့ရမယ့် frame က
0x02 0x30 0x10 0x02 0x65 0x10 0x10 0x10 0x03 0x03 0x44
ဖြစ်ပါတယ်။ C တို့၊ LabVIEW တို့ နဲ့ ပရိုဂရမ် တချို့ ရေးကြည့်ထားပါတယ်။ Example programs တွေကို အောက်က link မှာ တွေ့နိုင်ပါတယ်။

Byte Stuffing on GitHub


အောက်ကဟာက ပို့ဖို့ အတွက် frame ဆောက်တဲ့ C++ code ဖြစ်ပါတယ်။
// Byte stuffing- sending and receiving frames
// Author: Yan Naing Aye

#ifndef  FRAME_H
#define FRAME_H

#include 
#define STX 0x02
#define ETX 0x03
#define DLE 0x10

#define TX_BUF_SIZE 128
#define RX_BUF_SIZE 128
enum RX_STATE { IGNORE,RECEIVING,ESCAPE,RXCRC1,RXCRC2 };
//-----------------------------------------------------------------------------
class Frame {    
    RX_STATE rState;
protected:
    int TxN;//number of transmitting bytes
    int RxN;//number of receiving bytes
    char tb[TX_BUF_SIZE];//transmit buffer
    char rb[RX_BUF_SIZE];//receiving data
public:
    Frame();
    int setTxFrame(char* d,int n);
    unsigned int CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc);
    int getTxN();
    int getRxN();
    int receiveRxFrame(char c);//get receiving frame from received char
    char* getTxBuf();
    char* getRxBuf();
};
//-----------------------------------------------------------------------------
Frame::Frame():TxN(0),RxN(0),rState(IGNORE){}
//-----------------------------------------------------------------------------
char* Frame::getTxBuf(){
    return tb;
}
//-----------------------------------------------------------------------------
char* Frame::getRxBuf(){
    return rb;
}
//-----------------------------------------------------------------------------
//Prepare transmitting frame
int Frame::setTxFrame(char* d,int n)
{
    unsigned int txcrc=0xFFFF;//initialize crc
    char c;
    int i=0,j=0;
    tb[i++]=STX;//start of frame
    for(j=0;j < n;j++) {
        c=d[j];
        if((c==STX)||(c==ETX)||(c==DLE)) tb[i++]=(DLE);
        tb[i++]=c;
    }
    tb[i++]=(ETX);//end of frame

    txcrc=CRC16CCITT_Calculate(d,n,txcrc);//calculate crc
    tb[i++]=txcrc & 0xFF;
    tb[i++]=(txcrc >> 8) & 0xFF;
    TxN=i;
    return TxN;
}
//-----------------------------------------------------------------------------
//Inputs
//s : pointer to input char string
//len: string len (maximum 255)
//crc: initial CRC value

//Output
//Returns calculated CRC
unsigned int Frame::CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc)
{
    //CRC Order: 16
    //CCITT(recommendation) : F(x)= x16 + x12 + x5 + 1
    //CRC Poly: 0x1021
    //Operational initial value:  0xFFFF
    //Final xor value: 0
    unsigned char i,j;
    for(i=0;i < len;i++,s++) {
        crc^=((unsigned int)(*s) & 0xFF) << 8;
        for(j=0;j<8;j++) {
            if(crc & 0x8000) crc=(crc << 1)^0x1021;
            else crc <<=1;
        }
    }
    return (crc & 0xFFFF);//truncate last 16 bit
}
//-----------------------------------------------------------------------------
//get number of transmitting bytes
int Frame::getTxN()
{
    return TxN;
}
//-----------------------------------------------------------------------------
//get number of transmitting bytes
int Frame::getRxN()
{
    return RxN;
}
//-----------------------------------------------------------------------------
//process receiving char
int Frame::receiveRxFrame(char c)
{
    static char b;
    unsigned int crc;
    unsigned int rxcrc=0xFFFF;//initialize CRC
    switch(rState){
        case IGNORE:
            if(c==STX) { rState=RECEIVING;RxN=0;}
            break;
        case RECEIVING:
            if(c==STX) { rState=RECEIVING;RxN=0;}
            else if(c==ETX){rState=RXCRC1;}
            else if(c==DLE){ rState=ESCAPE; }
            else { rb[RxN++]=c; }
            break;
        case ESCAPE:
            rb[RxN++]=c; rState=RECEIVING;
            break;
        case RXCRC1:
            b=c; rState=RXCRC2;
            break;
        case RXCRC2:
            rState=IGNORE;
            crc=( (int)c << 8 | ((int)b & 0xFF) ) & 0xFFFF;//get received crc
            rxcrc=CRC16CCITT_Calculate(rb,RxN,rxcrc);//calculate crc
            //printf("crc: %x  rxcrc:%x \n",crc,rxcrc);
            if(rxcrc==crc){return RxN;}//if crc is correct            
            else {RxN=0;}//discard the frame

            break;
    }
    return 0;
}

//-----------------------------------------------------------------------------

//#############################################################################

class Frame2:public Frame {
    char Dt[20];//transmitting data
public:
    Frame2();
    void printTxFrame();
    void printRxFrame();
    void printRxData();
    void setTxData(float x,float y,float z,float b,float t);
};
//-----------------------------------------------------------------------------
Frame2::Frame2():Frame(),Dt(""){}
//-----------------------------------------------------------------------------
//Print out frame content
void Frame2::printTxFrame()
{
    printf("Tx frame buffer: ");
    for(int j=0;j < TxN;j++) printf("%02X ",(unsigned char)tb[j]);
    printf("\n");
}
//-----------------------------------------------------------------------------
//Print out frame content
void Frame2::printRxFrame()
{
    printf("Rx data buffer: ");
    for(int j=0;j < RxN;j++) printf("%02X ",(unsigned char)rb[j]);
    printf("\n");
}
//-----------------------------------------------------------------------------
//Set transmitting data
void Frame2::setTxData(float x,float y,float z,float b,float t)
{
    *(float*)(Dt)=x;
    *(float*)(Dt+4)=y;
    *(float*)(Dt+8)=z;
    *(float*)(Dt+12)=b;
    *(float*)(Dt+16)=t;
    Frame::setTxFrame(Dt,20);
}
//-----------------------------------------------------------------------------
//Print out received data
void Frame2::printRxData()
{
    float x,y,z,b,t;
    x=*(float*)(Dt);
    y=*(float*)(Dt+4);
    z=*(float*)(Dt+8);
    b=*(float*)(Dt+12);
    t=*(float*)(Dt+16);
    printf("Rx data: %f %f %f %f %f \n",x,y,z,b,t);
}
//-----------------------------------------------------------------------------

#endif // FRAME_H