Search This Blog

Thursday, May 5, 2011

Degrees of Freedom of the Human Arm

လူတွေရဲ့ လက်မှာ လှုပ်ရှားနိုင်တဲ့ ပုံစံ (degrees of freedom) ဘယ်နှစ်မျိုး ရှိလဲလို့ စဉ်းစား ဘူးပါသလား။ Saeed Benjamin Niku ရေးတဲ့ စာအုပ် တစ်အုပ် ဖြစ်တဲ့ Introduction to Robotics -Analysis, Control, Applications ထဲမှာ ဖတ်မိတဲ့ ဟာ တစ်ချို့ကို ပြန်ပြီး ထုတ်နုတ် တင်ပြ ချင်ပါတယ်။ လူ့ လက်မှာ ပခုံး၊ တံတောင်ဆစ် နဲ့ လက်ကောက်ဝတ် တွေက ကိုယ်၊ လက်မောင်း၊ လက်ဖျံ၊ လက်ဖဝါး တွေကို ဆက်ထား ပေးတဲ့ အဆက် နေရာတွေပါ။ ပခုံး က သုံးမျိုး လှုပ်နိုင်ပါတယ်။ coronal plane အတိုင်း အပေါ်အောက် လှုပ်လို့ရ သလို၊ transverse plane အတိုင်း ရှေ့နောက် လွှဲလို့ လဲရနိုင်ပြီး၊ လက်မောင်း ဝင်ရိုးမှာ လှည့်လို့ လည်း ရပါတယ်။ လူတွေရဲ့ ခန္ဓာဗေဒ ပြင်ညီ အခေါ်အဝေါ် ကို အောက်က Wikipedia က ပုံမှာ တွေ့နိုင်ပါတယ်။
တံတောင်ဆစ် ကတော့ အကွေး၊ အဆန့် တစ်မျိုးပဲ လှုပ်လို့ရတာပါ။ လက်ကောက်ဝတ် ကလဲ သုံးမျိုး လှုပ်နိုင်ပါတယ်။ အပေါ်အောက် လှုပ်တာ၊ ဘေးတိုက် လှုပ်တာ နဲ့ လက်ဖျံ တလျှောက် လှည့်တာ တွေ ဖြစ်ပါတယ်။ ဒါ့ကြောင့် လက်ချောင်းတွေကို ထည့်မစဉ်းစားဘူးဆိုရင် လူတွေရဲ့ လက်မှာ လှုပ်ရှားနိုင်တဲ့ ပုံစံ (degrees of freedom) ခုနှစ်မျိုး ရှိတယ်လို့ ပြောနိုင်ပါတယ်။

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

Friday, March 4, 2011

Simple 6 DOF Translation and Rotation Stages

ပစ္စည်း တစ်ခု ကို 6 degrees of freedom (DOF) နဲ့ ထိန်းဖို့ လိုအပ်ချက် ပေါ်လာပါတယ်။ နေရာ ရွေ့ ဖို့ မော်တာနဲ့ မောင်းတဲ့ translation stage သုံးခု ရယ်၊ အနေအထား အတွက် မော်တာနဲ့ မောင်းတဲ့ rotary stage သုံးခု ကို သုံးပြီး ထိန်းမှာပါ။ သူ့ကို prismatic joint သုံးခု နဲ့ revolute joint သုံးခု ပါတဲ့ robot arm တစ်ခု အနေနဲ့ စဉ်းစားလို့ ရပေမယ့်၊ သာမန် ရိုးရှင်းတဲ့ ကိရိယာ တစ်ခု အတွက် မသင့်တော် တဲ့ ရှုပ်ထွေးတဲ့ kinematics တွက်ချက်မှု တွေ မပါအောင် တည်ဆောက်ချင် ပါတယ်။ နမူနာ တွက်ချက်မှု တစ်ခု ကို ဒီမှာ တွေ့ နိုင်ပါတယ်။ rotary stage တွေရဲ့ ဝင်ရိုးတွေ ကို အထိန်းခံ ပစ္စည်း မှာ ဖြတ်သွားအောင် စီစဉ် ထားမယ် ဆိုရင်တော့ ရိုးရှင်းတဲ့၊ ဒါရိုက် ထိန်းချုပ်လို့ ရတဲ့ ကိရိယာ တစ်ခုကို ရရှိနိုင်ပါတယ်။ ကျွန်တော် ဒီဇိုင်း လုပ်ကြည့်ထား တဲ့ ပုံတွေကို အောက်မှာတွေ့ နိုင်ပါတယ်။

Thursday, March 3, 2011

Capacitor selection for a Crystal Oscillator

ပုံမှန် crystal oscillator တစ်ခု နဲ့ နမူနာ layout design တစ်ခုကို ပုံတွေမှာ ဖော်ပြထားပါတယ်။ Crystal ထုတ်လုပ်သူ တွေက crystal တစ်ခု အတွက် ရှိသင့်တဲ့ CL (load capacitance) ကို သူ့အတွက် datasheet မှာ ဖော်ပြထားလေ့ ရှိပါတယ်။ အဲဒီ တန်ဖိုးဟာ crystal ကမြင်ရမယ့် C1 ၊ C2 နဲ့ pin ၊ board ၊ PCB trace တို့ရဲ့ ရှိသမျှ စုစုပေါင်း capacitance ( Cstray ) တို့ကို တန်းဆက် (series ဆက်) ထားတဲ့ တန်ဖိုးပါ။ Cstray ရဲ့ ပုံမှန် တန်ဖိုးက 2 pF နဲ့ 7 pF ကြားမှာ ရှိတတ်ပါတယ်။ သူတို့ ရဲ့ ဆက်သွယ်မှု ကို အောက်ပါ ညီမျှခြင်း နဲ့ ဖော်ပြနိုင် ပါတယ်။

CL=(C1 * C2)/(C1 + C2) + Cstray

C1 နဲ့ C2 တို့ကို ရွေးချယ်တဲ့ အခါ ပုံမှန်အား ဖြင့် တန်ဖိုးတူ တာကို သုံးကြပါတယ်။ ဒါကြောင့်

C1 = C2=2 * (CL - Cstray)

ဖြစ်ပါတယ်။ ဥပမာ Cstray က 4 pF နဲ့ CL က 18 pF ဖြစ်မယ်ဆိုရင် C1 နဲ့ C2 က 28 pF ဖြစ်သင့်ပါတယ်။ ဒါဆို ဝယ်လို့ရမယ့် normalized တန်ဖိုး 30 pF ကို သုံးနိုင်ပါတယ်။

Tuesday, February 22, 2011

Denavit-Hartenberg Representation of Robots

D-H model ဟာ robot links နဲ့ joints တွေကို ဖော်ပြဖို့ အတွက် ရိုးရှင်းတဲ့ ပုံစံ တစ်ခု ဖြစ်ပြီး ဘယ်လို robot ပုံစံ မျိုး အတွက် မဆို သုံးလို့ရပါတယ်။ လက်တံ (link) တစ်ခုစီ အတွက် z ဝင်ရိုးနဲ့ x ဝင်ရိုး တို့ကို သတ်မှတ်ပေးဖို့ လိုပါတယ်။ D-H representation မှာ y ဝင်ရိုးကို သုံးစရာ မလိုပါဘူး။ Lk ကို link k အတွက် frame လို့ သတ်မှတ်ကြမယ် ဆိုပါစို့။



၁။ Joint အားလုံး အတွက် Z ဝင်ရိုးကို သတ်မှတ်ပါ

Joint k+1 ရဲ့ ဝင်ရိုးကို zk လို့ သတ်မှတ်ပါ။ အကယ်၍ လည်တဲ့ revolute joint မျိုးဆိုရင် z axis ကို လည်တဲ့ဖက် အတိုင်း right hand rule သုံးပြီး သတ်မှတ်ပါ။ အကယ်၍ ဆန့်ထွက်တဲ့ prismatic joint မျိုးဆိုရင် z-axis ကို ဆန့်ထွက်တဲ့ ဖက် အတိုင်း သတ်မှတ်ပါ။

၂။ Origin များကို သတ်မှတ်ပါ

zk နဲ့ zk-1 တို့ အချင်းချင်း ဖြတ်သွားတဲ့ နေရာကို Lk ရဲ့ origin လို့ သတ်မှတ်ပါ။ အကယ်၍ မဖြတ်ခဲ့ ရင် zk ရော zk-1 ကိုပါ ထောင့်မတ်ကျတဲ့ common normal နဲ့ zk နဲ့ ဖြတ်တဲ့နေရာကို ယူပါ။ လိုင်း နှစ်လိုင်း ဟာ ဘယ်လိုပဲ ရှိ ရှိ နှစ်လိုင်း စလုံးကို ထောင့်မတ်ကျတဲ့ common normal လို့ ခေါ်တဲ့ လိုင်းတစ်လိုင်းတော့ အမြဲရှိပြီး အဲဒီနှစ်လိုင်း ရဲ့ အနီးဆုံး အကွာအဝေး လည်း ဖြစ်ပါတယ်။

၃။ X ဝင်ရိုးများကို သတ်မှတ်ပါ

xk ကို zk နဲ့ zk-1 ကြားက common normal ရဲ့ ဦးတည်ရာ အတိုင်း သတ်မှတ်ပါ။ အကယ်၍ z ဝင်ရိုး အချင်းချင်း ဖြတ်နေရင် xk ကို zk နဲ့ရော zk-1 နဲ့ပါ ထောင့်မတ်ကျ အောင် သတ်မှတ်ပါ။ (z ဝင်ရိုး တွေရဲ့ cross-product ဦးတည်ရာ အတိုင်း လို့ လည်းပြောလို့ ရပါတယ်)။ အကယ်၍ zk နဲ့ zk-1 တွေက ပြိုင်နေရင် xk ကို zk-1 နဲ့ ဝေးရာကို ဦးတည်ပါ။ အရင် ရှေ့က common normal ရဲ့ ဦးတည်ရာ အတိုင်း ဖြစ်နိုင်ရင် သတ်မှတ်ပါ။

၄။ Y ဝင်ရိုးများကို သတ်မှတ်ပါ

yk ကို right-handed frame Lk ဖြစ်အောင် သတ်မှတ်ပါ။

၅။ Kinematic Parameter လေးခု ကို ရှာပါ

*θk က xk-1 နဲ့ xk ကြားက zk-1 ဝင်ရိုးပေါ်က ထောင့်ပါ။ *dk က xk-1 နဲ့ xk ကြားက zk-1 ဝင်ရိုး တစ်လျှောက် အကွာအဝေး ပါ။ *ak က zk-1 နဲ့ zk ကြားက xk ဝင်ရိုး တစ်လျှောက် အကွာအဝေး ပါ။ *αk က zk-1 နဲ့ zk ကြားက xk ဝင်ရိုးပေါ်က ထောင့်ပါ။

၆။ Frame k-1 မှ Frame k သို့ ပြောင်းခြင်း

*Lk-1 ကို zk-1 ဝင်ရိုး ပေါ်မှာ θk လှည့်လိုက်ရင် xk-1 နဲ့ xk နဲ့ အပြိုင်ဖြစ် သွားပါမယ်။ ဘာ့ကြောင့်လဲ ဆိုတော့ common normals တွေ ဖြစ်တဲ့ ak-1 နဲ့ ak နှစ်ခုစလုံးက zk-1 ဝင်ရိုးနဲ့ perpendicular ဖြစ်နေလို့ပါ။ *Lk-1 ကို zk-1 ဝင်ရိုး တစ်လျှောက် dk ရွှေ့ရင် xk-1 နဲ့ xk က တစ်တန်းတည်း ဖြစ်သွားပါမယ်။ *Lk-1 ကို xk ဝင်ရိုး တစ်လျှောက် ak ရွှေ့ရင် Lk-1 နဲ့ Lk တို့ရဲ့ origin တွေဟာ တစ်ထပ်တည်း ဖြစ်သွား ပါမယ်။ *Lk-1 ကို xk ဝင်ရိုး ပေါ်မှာ αk လှည့်လိုက်ရင် zk-1 နဲ့ zk ဝင်ရိုး တွေဟာ အပြိုင်ဖြစ် သွားပါမယ်။ ဒီအချိန်မှာ frames Lk-1 နဲ့ Lk တို့ဟာ တထပ်တည်း ကျသွားပါပြီ။


simulation လုပ်ကြည့်မယ် ဆိုရင် Robotassist ဆိုတဲ့ free software လေးက အဆင်ပြေမယ် ထင်ပါတယ်။
Ref:
Introduction to Robotics -Analysis, Control, Applications; Second Edition, Saeed Benjamin Niku
Fundamental of Robotics -Analysis & Control, Robert J. Schilling

Thursday, December 30, 2010

Inkscape

Inkscape က Illustrator တို့၊ CorelDraw တို့ လိုမျိုး vector graphic editor တစ်ခုပါ။ ပိုကောင်းတာ တစ်ခုကတော့ Inkscape က အလကား ရနိုင်တဲ့ free software ဖြစ်တာပါပဲ။ Open source software လည်း ဖြစ်ပါတယ်။ သူ့ကို http://inkscape.org/ မှာ ယူလို့ရပါတယ်။ သူ့ကို ကြိုက်တာ တစ်ခုကတော့ graphics တွေကို pdf format အနေနဲ့ save လုပ်လို့ရတာပါပဲ။ အဲဒါ​ကြောင့် pdflatex သုံးပြီး pdf ဖိုင်တွေ ထုတ်တဲ့ အခါ image ဖိုင်တွေ သုံးတာနဲ့ စာရင် ပိုကောင်းတဲ့ graphic quality ကို ရနိုင်ပါတယ်။ သူတို့ဟာ Scalable Vector Graphics ဖြစ်တာမို့ magnify လုပ်ကြည့် ရင် တောင် bitmap image တွေလို ပြဿနာ မရှိပါဘူး။
အောက်မှာ နမူနာ အနေနဲ့ Inkscape ကို သုံးပြီး မြားခေါင်း ပါတဲ့ မျဉ်းကြောင်း တစ်ကြောင်း ဆွဲ ကြည့် ထားပါတယ်။ ၁။ Bezier Curves ကိုရွေးပါ။ မျဉ်းကြောင်းကို စဆွဲ ဖို့ ကလစ် နှိပ်ပြီး၊ မျဉ်းကြောင်း ကို အဆုံးသတ်ဖို့ double click နှိပ်ပါ။ (click တစ်ချက်ပဲ နှိပ်ပြီး enter key နှိပ်လည်း ရပါတယ်။) ၂။ Object menu မှာ ရှိတဲ့ Fill and Stroke... command ကိုနှိပ်ပါ။ (ဒါမှမဟုတ် ဘယ်ဘက်အောက်နားက Fill: သို့ Stroke: ကို နှိပ်လို့လည်း ရပါတယ်။) နောက် Stroke style tab ထဲက End Markers ကို arrow ပြောင်းပါ။ ၃။ မျဉ်းကြောင်း ရဲ့ အရောင် ကို Stroke paint tab ထဲမှာ ပြောင်းနိုင်ပါတယ်။ မြားခေါင်း ရဲ့ အရောင် ကို ပါ ပြောင်းဖို့ အတွက် Extensions->Modify Path->Color Markers to Match Stroke ကို နှိပ် နိုင် ပါတယ်။ သင်္ချာ သင်္ကေတ တွေ ထည့် ချင်ရင်တော့ ctrl+u ကို နှိပ်ပြီး ထည့်ချင်တဲ့ သင်္ကေတရဲ့ hexadecimal Unicode code point ကို ရိုက်ပြီး enter ကိုနှိပ်ပါ။

http://wiki.inkscape.org/wiki/index.php/FAQ
http://www.unicode.org/charts/PDF/U0370.pdf


Monday, July 12, 2010

Random Password Generator

ကျွန်တော့ computer user account အချို့က password ပြောင်းဖို့ ပုံမှန် နားပူနားဆာ လုပ်လေ့ ရှိပါတယ်။ ကျောင်းက အီးမေးလ် လို တစ်ချို့ ကောင်တွေဆို သုံးပြီးသား password history ကို ဆယ်ခုလောက် ထိ မှတ်ထား တတ်တော့ သုံးပြီးသား ကို ပြန်သုံးလို့ မရ ပါဘူး။
အဲဒီတော့ ကျွန်တော့မှာ password အသစ် တွေကို ထပ်ကာ ထပ်ကာ စဉ်းစား ရတဲ့ ဒုက္ခ ပိုလာ ပါတယ်။ နောက် တော့ Internet မှာ အလကား ရတဲ့ random password generator တွေကို သုံးပါတယ်။ အရင်နေ့ က တော့ စာဖတ်ရင်း ပျင်းလာတာနဲ့ random password generator တစ်ခုကို ကိုယ့် ဟာကိုယ် အပျော်သဘော နဲ့ ရေးကြည့်ထားပါတယ်။ အောက်က လင့်ခ် မှာကြည့်နိုင်ပါတယ်။

Source PHP file

Ref: http://en.wikipedia.org/wiki/Password_generator

Friday, June 18, 2010

Common Interrupt Pitfalls

SDCC Compiler User Guide ထဲမှာ ပါတဲ့ စိတ်ဝင်စား စရာ အချက်တချို့ကို ပြန်ပြော ချင်ပါတယ်။ ကျွန်တော့် အတွေ့အကြုံ အရ အဲဒီ အချက်တွေဟာ အရမ်းအရေး ကြီးပြီး firmware programmer တွေအတွက် အမြဲခေါင်းထဲမှာ ရှိနေဖို့ လိုတယ် လို့ ထင်ပါတယ်။ တစ်ခါက ကျွန်တော့် ပရိုဂရမ် မှာ ဘာ အမှားမှ မရှိပဲ သူ့ကို သုံးတဲ့အခါ တလွဲတွေပဲ လုပ်နေပါတယ်။ Stack overflow ဖြစ်နိုင်တာ ကို ရုတ်တရက် သတိရ ပြီး Stack အရွယ်အစား ပြင်လိုက်တဲ့ အခါ ကောင်းသွားတာ မျိုး မကြာခဏ ကြုံဖူးပါတယ်။

Variable not declared volatile

တစ်ခြား function တွေက သုံးနေတဲ့ variable တွေကို interrupt service routine တစ်ခု ခုကနေ ပြောင်းလဲပေး နေတဲ့ အခါမျိုးမှာ အဲဒီ variable တွေကို volatile လို့ ကြေငြာပေးရပါမယ်။ အသေးစိတ်ကို http://en.wikipedia.org/wiki/Volatile_variable မှာ ကြည့်နိုင်ပါတယ်။

Non-atomic access

အကယ်၍ variable ကို သုံးတာ instruction တစ်ခုမက လိုပြီး သူ့ကို သုံးနေချိန်မှာ interrupt ဝင်လာနိုင်ရင် ဒေတာ အမှား ဖြစ်မသွားဖို့ interrupt ကို disabled လုပ်ထားဖို့ လိုပါတယ်။ အဲဒီလို Bug မျိုးဟာ ပြန်တွေ့အောင် reproduce လုပ်ဖို့ခက်ပြီး ဒုက္ခ တော်တော် ပေးနိုင်ပါတယ်။ ကျွန်တော်တော့ Real time and embedded systems ဆရာက အတန်းထဲမှာ mutual exclusion... mutual exclusion နဲ့ ခဏ ခဏ ပြောတာ ကို ကောင်း ကောင်း မှတ်မိ နေ ခဲ့ ပေမယ့် အဲဒီ ပြဿနာ မျိုး တစ်ခါ တက်ဖြစ်အောင် ပြန်တက်ဖူးပြီး သင်ခန်းစာ ကောင်းကောင်း ပြန်ရဘူး ပါတယ်။

Stack overflow

ခေါ်ထားတဲ့ address တွေရယ်၊ သုံးလက်စ register တန်ဖိုး တွေ ကို stack ပေါ်မှာ တင်သိမ်းထားပြီး၊ stack အရွယ်အစား မလုံလောက်ရင် နဂို နေရာဆီ ပြန်မရောက်ပဲ တစ်ခြား မထင်မှတ်တဲ့ နေရာ တွေဆီ ရောက်သွားပြီး ဒုက္ခ တွေ့နိုင် ပါတယ်။

Use of non-reentrant functions

ဖြစ်နိုင်ရင် interrupt ထဲမှာ တစ်ခြား function တွေကို မခေါ်ပဲ တတ်နိုင်သမျှ ရှောင်ကျဉ် ပါ။ အကယ်၍ interrupt က active ဖြစ်နိုင်တဲ့ အခြေအနေ မျိုးမှာ nonreentrant function တွေကို main program ကနေ မခေါ်သင့်ပါဘူး။ Good luck with your programming!

Friday, June 11, 2010

Circular Buffered UART Com Module for 8051 Microcontroller

Embedded system အများစု မှာ UART communication ကို သုံးကြပါတယ်။ ဒါကြောင့် ကျွန်တော် ရေးထားတဲ့ circular buffered UART comm module လေးကို ဒီမှာ ဖော်ပြချင်ပါတယ်။ သူ့ကို 8051 microcontroller အတွက် ရေးထားတာ ဖြစ်ပေမယ့် တစ်ခြား microcontroller တွေ အတွက်ဆိုရင် လဲ အလွယ်တစ်ကူ ပြောင်းသုံးလို့ ရပါတယ်။

Using Circular Buffered UART Com Module

သူ့ကို သုံးချင်တဲ့ module မှာ ထုံးစံ အတိုင်း header file ကြေငြာဖို့ လိုပါတယ်။ ကျွန်တော့် နမူနာ မှာတော့ header အားလုံးကို 'headers.h' ဖိုင်ထဲမှာ စုထားတဲ့ အတွက် အဲဒီဖိုင်ကို ထည့်လိုက်ရုံ ပါပဲ။
ပို့ဖို့၊ လက်ခံဖို့ အတွက် buffer အရွယ်အစားတွေကို ComConfig.h မှာ သတ်မှတ် နိုင်ပါတယ်။ အဲဒီမှာပဲ ဒေတာ လက်ခံရရှိတဲ့ အခါ ခေါ်ချင်တဲ့ function ကို သတ်မှတ်နိုင်ပါတယ်။
main function ထဲမှာ buffer ထဲမှာ ဒေတာ တွေ ရောက်နေ မနေ စစ်ဖို့ ComChkRx() function ကို poll လုပ် နိုင်ပါတယ်။
နမူနာ source code ကို

UART-Timer-8051 on GitHub

မှာရယူ နိုင်ပါတယ်။

Thursday, June 10, 2010

Soft-Timer Module for 8051 Microcontroller

Embedded system အားလုံးလိုလို မှာ timer တွေကို သုံးကြပါတယ်။ 8051 microcontroller မှာ hardware timer နှစ်ခု၊ သုံးခု ပဲ ပါတဲ့ အတွက် ပုံမှန် system တစ်ခု အတွက် လိုအပ်တဲ့ timer အားလုံးကို hardware timer တွေပဲ သုံးပြီး ရေးမယ် ဆိုရင် လုံလောက်မှာ မဟုတ်ပါဘူး။ ဒါကြောင့် သိပ်ပြီး တိကျဖို့ မလိုတဲ့ timer တွေကို ရေးတဲ့အခါ software ကိုပဲ သုံးပါတယ်။ ဒီမှာ ကျွန်တော် ရေးထားတဲ့ soft-timer module လေး တစ်ခု အကြောင်း ကို ပြောချင်ပါတယ်။ သူ့ကို 8051 microcontroller အတွက် ရေးထားတာ ဖြစ်ပေမယ့် တစ်ခြား microcontroller တွေ အတွက်ဆိုရင် လဲ အလွယ်တစ်ကူ ပြောင်းသုံးလို့ ရပါတယ်။
နမူနာ source code ကို

UART-Timer-8051 on GitHub

မှာရယူ နိုင်ပါတယ်။

Using soft-timer module

သူ့ကို သုံးချင်တဲ့ module မှာ ထုံးစံ အတိုင်း header file ကြေငြာဖို့ လိုပါတယ်။ ကျွန်တော့် နမူနာ မှာတော့ header အားလုံးကို 'headers.h' ဖိုင်ထဲမှာ စုထားတဲ့ အတွက် အဲဒီဖိုင်ကို ထည့်လိုက်ရုံ ပါပဲ။
Timer က သတ်မှတ်ချိန် ကုန် လို့ time out ဖြစ်ရင် လုပ်ချင်တဲ့ function ရယ်၊ timer ရဲ့ အချိန် သတ်မှတ်ဖို့၊ timer စတင်ဖို့ အတွက် function များကိုရေးပါ။ ကျွန်တော့် နမူနာ မှာတော့ SysSBYLEDTmrTO() နဲ့ SysSBYLEDInit() တို့ကို System.c module ထဲမှာ ရေးထားပါတယ်။
TmrConfig.h ဖိုင်ကို ဖွင့်ပြီး အဲဒီမှာ ရှိတဲ့ အဆင့် သုံးဆင့် ကို လုပ်ဖို့ လိုပါတယ်။ သင့် compiler က function pointers တွေကို သုံးလို့ မရရင် switch structure နဲ့ ပြောင်းသုံး နိုင်ပါတယ်။
main function ထဲမှာ initialize လုပ်ဖို့ TmrInit() နဲ့ ပုံမှန် poll လုပ်နေဖို့ TmrTask() တွေကို ခေါ်ဖို့ လို့ပါတယ်။ သူတို့ကို Tmr.c ထဲမှာ ရေးထားပါတယ်။