วันพฤหัสบดีที่ 30 กรกฎาคม พ.ศ. 2558

ความทรงจำ ที่Fibo

เนื่องด้วยการตั้งชื่อโพสต์สรุปว่าความทรงจำที่Fibo คือผมไม่อยากให้ดูว่าเป็นการฝึกงานแต่อย่างใดเพราะผมมาอยู่นี้มีความสุขดี และได้เรียนรู้เรื่องต่างๆ ไม่ว่าทางวิชาการ การเอาตัวรอดกับสิ่งแวดล้อมหรือเรียกอีกอย่างวิชาคน คนสอนคนบอกเล่า ไม่เท่าให้ทำจนเกิดประสบการณ์ ซึ่งผมจะเล่าถึงประสบการณืต่างๆโดยสรุปลงในบล๊อกนี้
      วันแรกที่เข้ามาฝึกงานผมก็ได้ทำความรู้จักกับ อ.สยาม เจริญเสียง หลังจากนั้นก็ได้ศึกษาได้รับการบรรยายจากอาจารย์ ว่า fibo คืออะไร fiboคือสถาบันที่เทียบเท่าคณะ(ไม่ใช่คณะ) ให้ปริญาเฉพาะทางได้ หุ่นยนต์ทีสร้างมีสองประเภท แบบใช้งานกับชีวิต กับหุ่นยนต์ที่สร้างผลงาน
*-เรื่องนี้ผมต้องดอกจันทร์ไว้เลย เพราะผมเป็นคนที่มีความรับผิดชอบน้อย แล้วจะเกี่ยวโยงไปเรื่องวินัย

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

      หลังจากนั้นผมก็ได้รู้จักกับพี่ๆที่แล๊ปสอง แล้วผมก็ได้เข้าไปช่วยงานของพี่ไนท์ โปรเจ็คขอพี่เขาคือ แขนกลเขย่าสาร โดยสามารถถ่ายทอดสดออกทางเว็ปและให้นักเรียนนักศึกษาเข้ามาดูได้ และยังไม่เด่ดพอ ที่เด่ดเลยคือแขนกลตัวนี้น้องๆที่เข้ามาดูแล้วยังสามารถผสมสารเองได้อีกด้วยผมจึงมีความสนใจอยากจะรวมงานกับพี่ไนท์ ผมจึงได้ขอช่วยพี่ไนท์
       การช่วยงานเริ่มจากเขียนโปรแกรมโค้ด arduino แบบ basic ได้ประมาณสองสามสัปดาห์ผมก็ได้เริ่มทำเกี่ยวกับ motor encoder พอผมทดลอง emcoder เสร็จผมก็ได้เริ่มทำ semsor แต่ตอนที่ผมทำ encoderนั้นก็กินเวลาไปนานมาก

                         คลิปการทำงาน encoder 

หลังจากทำเสร็จผมก็ได้เริ่มทำ PH EC ไปพร้อมกันและทดลอง จนทำให้ arduino UNO r3 ที่อาจารย์ได้ให้มาพัง คือไฟย้อนกลับเข้าบอร์ดเพราะผมเล่นกลับ motor ทำให้กระแสไหลกลับได้ พอนี้เสร็จผมก็ได้เขียน sensor PH EC ลงใน arduino MEGA 2560 r3 พอทำได้สำเร็จผมก็ได้เอามารวมกับการทำงาน encoder หลังจากนั้นได้มาทำ motor PID กับencoder พอมาถึงตรงนี้แล้วปัญหาเกิดคือ จะเอาโค้ดมารวมกันแล้ว การcalibrate ไม่ทำงาน แต่motor หมุนทำให้ต้องมาการกรองคำสั่ง

การ calibrate PH

การ calibrate PH EC ด้วย

การต่อสายในบอร์ด

การกรองคำสั่งคือเราต้องวางแผนเราจะส่งคำสั่งไปกี่ตัวผมเลือกที่จะส่งไปหกตัวแล้วเลือกเอาสามตัวกลองมาสั่งคำสั่งให้ไปทำงาน แต่ต่อมาmotor ที่ทำได้เสร็จแล้วไม่ได้ใช้จิงแค่ทดลองการทำงานหรือโค้ดโปรแกรมเท่านั้น จริงๆแล้วต้องใช้ motor 12V DC แล้วใช้ TCST2202 เป็น soensor วัดรอบและหยุดการทำงานของเครื่องเขย่าสาร

การทดลองการใช้ TCST2202 มาทำงาน

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

 เครื่องเขย่าสารทดลองการทำงาน
      สุดท้ายนี้ผมเข้ามาช่วยในด้านควบคุม sensor เครื่องเขย่าสาร  และระหว่างการทำงานก็มีความสุขและได้ความรู้ไม่ใช่แค่เรื่องนี้เท่านั้นแต่ยังคงได้อีกหลายเรื่องกับสิ่งแวดล้อมต่างๆ ผมมีความสุขดีที่ได้มาฝึกงานที่นี้ และยังเป็นความทรงจำดีๆ กับการได้มาอยู่ กทม

สรุปการทำงานในคลิปวีดีโอ
ผลการทำงานทั้งหมด

โค้ดควบคุมจะมี2ส่วนแยกเพื่อความเข้าใจ ส่วนที่2จะเป็นฟังชันก์การทำงานหรือแยกออกไปเป็นฟังชันก์
ส่วนที่1
//___Pin assigned___//
const int pin_Pwm = 8;
String inputstring = "";                                                       //a string to hold incoming data from the PC
int inputstringLength = 0;


//motor interpreter
float time1 = 0.0;
float time2 = 0.0;
float s = 0.0;
float counter = 0.0;
float counterstop = 0.0;
float rpm = 0.0;
//float rpm_set = 0.0;
float err = 0;
float sum_err = 0;
float old_err = 0;
float Kp = 2.8;           //ค่าคงที่ kp
float Ki = 0.01;         //ค่าคงที่ki
float Kd = 0;           //ค่าคงที่kd
float u = 0;
float pwm_set = 0;
unsigned long Cur_time = 0;
unsigned long Prev_time = 0;
int  inputmotor;
bool ismotorON = 0;
bool isprestop = 0;
int prestopcounter =0;
bool inPC = 0;

//inputstring
boolean input_stringcomplete = false;                                          //have we received all the data from the PC

String sensorstringPH = "";                                                      //a string to hold the data from the Atlas Scientific product
boolean sensor_stringcompletePH = false;                                         //have we received all the data from the Atlas Scientific product
String PHout = "";

String sensorstringEC = "";                                                      //a string to hold the data from the Atlas Scientific product
boolean sensor_stringcompleteEC = false;                                         //have we received all the data from the Atlas Scientific product
String ECout = "";


void setup()
{
  Serial.begin(38400);                                                       //Serial with PC to 38400
  Serial2.begin(38400);                                                      //Serial with pH meter to 38400
  Serial3.begin(38400);                                                      //Serial with EC meter to 38400

  attachInterrupt(1, StopMotor, RISING);
  attachInterrupt(0, Millis, RISING);
  pinMode(pin_Pwm, OUTPUT);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  Serial.println("Initialize DONE!!!");
}

void Millis()
{
  counter++;
}

void StopMotor()
{
  counterstop ++;
  if(isprestop)
  {
    //prestopcounter =0;
    
    analogWrite(pin_Pwm, 0);
          digitalWrite(5, LOW);
          digitalWrite(6, LOW);
          isprestop=0;
  }
}

void loop()
{

  //___Receive Command___//
  if (Serial.available() > 0)
  {
    while (Serial.available() > 0)
    {

      inputstring += char(Serial.read());
      inputstringLength += 1;
      delay(1);
    }
    inPC = 1;
  }

  //read PH
  if (Serial3.available() > 0)
  {
    while (Serial3.available() > 0)
    {
      PHout += char(Serial3.read());
      delay(1);
    }
    Serial.print("PH:");
    Serial.print(PHout);
    Serial.print("\t");

  }

  //read EC
  if (Serial2.available() > 0)
  {
    while (Serial2.available() > 0)
    {
      ECout += char(Serial2.read());
      delay(1);
    }
    Serial.print("EC:");
    Serial.print(ECout);
    Serial.print("\t");
    Serial.print("inputmotor");
    Serial.print(inputmotor);
    Serial.print("\t");
    Serial.print("rpm");
    Serial.println(rpm);

  }
  PHout = "";
  ECout = "";
  //___Command Checker___//
  if (inPC)
  {
    Command_Checker();
    inPC = 0;
  } else {}
 
  if (ismotorON)
  {
    if (inputmotor <= 600 )                                                  //send to serial over 50
    {
      Cur_time = millis();                                                   //set Cur_time is millis
      s = Cur_time - Prev_time;
      if (s >= 1000)
      {
        rpm = counter/s*60000/18;  //rpm
        err = inputmotor-rpm;
        sum_err += (err*s);
        double derr = (err - s);
        u = Kp * err + Ki * sum_err + Kd * derr;
        old_err = err;
        Serial.print(u);
        Serial.print("\t");
        if(u >= 255)
        {
          u = 255;
        }
        else if(u<=0)
        {
          u = 0;
        }
        analogWrite(pin_Pwm, u);
        counter = 0;
        Prev_time = Cur_time;
      }
    }
  }else {}
}

ส่วนที่2
void Command_Checker()
{
  if (inputstringLength == 6)
  {
    if ((inputstring[4] == 'Y') && (inputstring[5] == 'U'))
    {
      if (inputstring[0] == 'M')
      {
        Serial.print("Motor Command : ");
        Serial.println(inputstring);
        String temp = "";
        temp.reserve(30);
        for (int i = 1; i < (inputstringLength - 2); i++)
        {
          temp += inputstring[i];
        }
        //Serial.println(temp);
        inputmotor = temp.toInt();
        if(inputmotor == 0)
        {
          ismotorON = 0;
          analogWrite(pin_Pwm, 255);
     delay(1000);
isprestop =1;
        }
        else
        {
          ismotorON = 1;
          digitalWrite(5, HIGH);
          digitalWrite(6, LOW);
          Prev_time = millis();
             
        }
        inputstring = "";
        inputstringLength = 0;
       
      }
      else if (inputstring[0] == 'P')
      {
        Serial.print("PH Command : ");
        Serial.println(inputstring);

        String temp = "";
        temp.reserve(30);
        for (int i = 1; i < (inputstringLength - 2); i++)
        {
          temp += inputstring[i];

        }
        Serial.println(temp);
        if (temp == "C04")
        {

          Serial.println("calibratePH4");
          Serial3.print("cal,low,4\r");
        }
        else if (temp == "C07")
        {
          Serial.println("calibratePH7");
          Serial3.print("cal,mid,7\r");
        }
        else if (temp == "C10")
        {
          Serial.println("calibratePH10");
          Serial3.print("cal,high,10\r");
        }
        else if (temp == "L00")
        {
          Serial.println("Turn off pH LED");
          Serial3.print("L,0\r");
        }
        else if (temp == "L11")
        {
          Serial.println("Turn on pH LED");
          Serial3.print("L,1\r");
        }
        else if (temp == "X00")
        {
          Serial.println("Reset PH");
          Serial3.print("x\r");
        }
        inputstring = "";
        inputstringLength = 0;
      }
      else if (inputstring[0] == 'E')
      {
        Serial.print("EC Command : ");
        Serial.println(inputstring);

        String temp = "";
        temp.reserve(30);
        for (int i = 1; i < (inputstringLength - 2); i++)
        {
          temp += inputstring[i];
        }
        Serial.println(temp);
        if (temp == "12K")
        {
          Serial.println("calibrateEC12K");
          Serial2.print("Cal,low,12880\r");
        }
        else if (temp == "80K")
        {
          Serial.println("calibrateEC80K");
          Serial2.print("Cal,low,80000\r");
        }
        else if (temp == "CLE")
        {
          Serial.println("Clear EC");
          Serial2.print("Cal,clear\r");
        }
        else if (temp == "L00")
        {
          Serial.println("Turn off pH LED");
          Serial2.print("L,0\r");
        }
        else if (temp == "L11")
        {
          Serial.println("Turn on pH LED");
          Serial2.print("L,1\r");
        }
        else if (temp == "X00")
        {
          Serial.println("Reset EC");
          Serial2.print("x\r");
        }
        inputstring = "";
        inputstringLength = 0;
      }
      else
      {
        Serial.print("Command (heading) ERROR!!! : ");
        Serial.println(inputstring);
        inputstring = "";
        inputstringLength = 0;
      }
    }
    else
    {
      Serial.print("Command (ending) ERROR!!! : ");
      Serial.println(inputstring);
      inputstring = "";
      inputstringLength = 0;
    }
  }
  else if (inputstringLength == 0)
  {
    // Do nothing
  }
  else
  {
    Serial.print("Command (overall) ERROR!!! : ");
    Serial.println(inputstring);
    Serial.println(inputstringLength);
    inputstring = "";
    inputstringLength = 0;
  }
}


ท้ายสุดนี้ผมขอบคุณพี่ อาจารย์ และทุกๆคนที่fibo

วันอาทิตย์ที่ 26 กรกฎาคม พ.ศ. 2558

วันที่49 ที่Fibo

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

-โค้ดที่ใช้ในการทดลอง

//___Pin assigned___//
const int pin_Pwm = 9;
String inputstring = ""; //a string to hold incoming data from the PC
int inputstringLength = 0;
//motor interpreter
float time1 = 0.0;
float time2 = 0.0;
float s = 0.0;
float counter = 0.0;
float j = 0.0;
float k = 0.0;
float rpm = 0.0;
float rpm_set = 0.0;
float err = 0;
float sum_err = 0;
float old_err = 0;
float Kp = 1; //ค่าคงที่ kp
float Ki = 0.5; //ค่าคงที่ki
float Kd = 1; //ค่าคงที่kd
float u = 0;
float pwm_set = 0;
unsigned long Cur_time = 0;
unsigned long Prev_time = 0;
int inputmotor;
bool ismotorON = 0;
bool inPC = 0;
//inputstring
boolean input_stringcomplete = false; //have we received all the data from the PC
String sensorstringPH = ""; //a string to hold the data from the Atlas Scientific product
boolean sensor_stringcompletePH = false; //have we received all the data from the Atlas Scientific product
String PHout = "";
String sensorstringEC = ""; //a string to hold the data from the Atlas Scientific product
boolean sensor_stringcompleteEC = false; //have we received all the data from the Atlas Scientific product
String ECout = "";
void setup()
{
Serial.begin(38400); //Serial with PC to 38400
Serial2.begin(38400); //Serial with pH meter to 38400
Serial3.begin(38400); //Serial with EC meter to 38400
attachInterrupt(0, Millis, RISING);
pinMode(pin_Pwm, OUTPUT);
digitalWrite(7, HIGH);
digitalWrite(8, LOW);
Serial.println("Initialize DONE!!!");
}
void Millis()
{
counter++;
}
void loop()
{
//___Receive Command___//
if (Serial.available() > 0)
{
while (Serial.available() > 0)
{
inputstring += char(Serial.read());
inputstringLength += 1;
delay(1);
}
inPC = 1;
}
//read PH
if (Serial3.available() > 0)
{
while (Serial3.available() > 0)
{
PHout += char(Serial3.read());
delay(1);
}
Serial.print("PH:");
Serial.print(PHout);
}
//read EC
if (Serial2.available() > 0)
{
while (Serial2.available() > 0)
{
ECout += char(Serial2.read());
delay(1);
}
Serial.print("\t");
Serial.print("EC:");
Serial.print(ECout);
Serial.print("\t");
Serial.print("inputmotor");
Serial.print(inputmotor);
Serial.print("\t");
Serial.print("rpm");
Serial.println(rpm);
}
PHout = "";
ECout = "";
//___Command Checker___//
if (inPC)
{
Command_Checker();
inPC = 0;
} else {}
if(ismotorON)
{
if (inputmotor <= 200 ) //send to serial over 50
{
Cur_time = millis(); //set Cur_time is millis
s = Cur_time - Prev_time;
if (s >= 50)
{
j = (counter * 20.0) / 360.0;
k = j / (s * 0.001);
rpm = k * 60.0; //rpm
err = inputmotor - rpm / 100;
sum_err += err;
u = Kp * err + Ki * sum_err + Kd * (err - old_err);
old_err = err;
pwm_set = u * 1.2;
analogWrite(pin_Pwm, pwm_set);
pwm_set += 0;
counter = 0;
Prev_time = Cur_time;
pwm_set = 0;
}
}
} else {}
}
void Command_Checker()
{
if (inputstringLength == 6)
{
if ((inputstring[4] == 'Y') && (inputstring[5] == 'U'))
{
if (inputstring[0] == 'M')
{
Serial.print("Motor Command : ");
Serial.println(inputstring);
String temp = "";
temp.reserve(30);
for (int i = 1; i < (inputstringLength - 2); i++)
{
temp += inputstring[i];
}
Serial.println(temp);
inputmotor = temp.toInt();
if(inputmotor == 0)
{
ismotorON = 0;
}
else
{
ismotorON = 1;
}
inputstring = "";
inputstringLength = 0;
}
else if (inputstring[0] == 'P')
{
Serial.print("PH Command : ");
Serial.println(inputstring);
String temp = "";
temp.reserve(30);
for (int i = 1; i < (inputstringLength - 2); i++)
{
temp += inputstring[i];
}
Serial.println(temp);
if (temp == "C04")
{
Serial.println("calibratePH4");
Serial3.print("cal,low,4\r");
}
else if (temp == "C07")
{
Serial.println("calibratePH7");
Serial3.print("cal,mid,7\r");
}
else if (temp == "C10")
{
Serial.println("calibratePH10");
Serial3.print("cal,high,10\r");
}
else if (temp == "L00")
{
Serial.println("Turn off pH LED");
Serial3.print("L,0\r");
}
else if (temp == "L11")
{
Serial.println("Turn on pH LED");
Serial3.print("L,1\r");
}
else if (temp == "X00")
{
Serial.println("Reset PH");
Serial3.print("x\r");
}
inputstring = "";
inputstringLength = 0;
}
else if (inputstring[0] == 'E')
{
Serial.print("EC Command : ");
Serial.println(inputstring);
String temp = "";
temp.reserve(30);
for (int i = 1; i < (inputstringLength - 2); i++)
{
temp += inputstring[i];
}
Serial.println(temp);
if (temp == "12K")
{
Serial.println("calibrateEC12K");
Serial2.print("Cal,low,12880\r");
}
else if (temp == "80K")
{
Serial.println("calibrateEC80K");
Serial2.print("Cal,low,80000\r");
}
else if (temp == "CLE")
{
Serial.println("Clear EC");
Serial2.print("Cal,clear\r");
}
else if (temp == "L00")
{
Serial.println("Turn off pH LED");
Serial2.print("L,0\r");
}
else if (temp == "L11")
{
Serial.println("Turn on pH LED");
Serial2.print("L,1\r");
}
else if (temp == "X00")
{
Serial.println("Reset EC");
Serial2.print("x\r");
}
inputstring = "";
inputstringLength = 0;
}
else
{
Serial.print("Command (heading) ERROR!!! : ");
Serial.println(inputstring);
inputstring = "";
inputstringLength = 0;
}
}
else
{
Serial.print("Command (ending) ERROR!!! : ");
Serial.println(inputstring);
inputstring = "";
inputstringLength = 0;
}
}
else if (inputstringLength == 0)
{
// Do nothing
}
else
{
Serial.print("Command (overall) ERROR!!! : ");
Serial.println(inputstring);
Serial.println(inputstringLength);
inputstring = "";
inputstringLength = 0;
}
}

วันพฤหัสบดีที่ 23 กรกฎาคม พ.ศ. 2558

วันที่48 ที่Fibo

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




PCBที่ทำขึ้นเติมแต่งจากเดิม

PCBตัวเดิมที่ยังคงไม่เติมแต่งหรือเพิ่มเติม

-แค่นั้นยังคงมีอีกเรื่องที่อยากให้ระวังในการทำ คือต้องเช็คให้ละเอียดและวางแผนดีๆ บ้างอย่างอาจแก้ไม่ได้จนต้องได้ทำใหม่

เครื่องเขย่าสาร
-ตรงนี้ที่คิดไว้คือใช้เซ็นเชอร์ 2ตัวตัวหนึ่งจะให้วัดรอบอีกตัวจะให้หยุดการทำงานโดยจะใช้อิเทอร์หลับ สองขา


-ช่วงค่ำก่อนจะกลับก็ได้เปิดไปเจอ ICขยายเสียงหรือทำเป็นวงจรขยายเสียงทำเป็นลำโพงได้โดย กำลังที่ขยายได้น่าจะ 2-3W โดยดูจากวงจรอาจมี noise อยู่มากพอสมควรเพราะดูจากค่า C แล้วน้อยอยู่พอสมคสรแต่อย่าไงรก็ตามก็ดีในระดับหนึ่งเพราะการมี noise ทำให้เสียงมันดีแบบบอกไม่ถูกแต่ถ้ามากไปอาจทำให้เราลำคานก็เป็นได้
-IC ที่ให้ TDA2822

แบบ4ขา



วันพุธที่ 22 กรกฎาคม พ.ศ. 2558

วันที่47 ที่Fibo

-หลักการและการทำงานของ โมดูล HC-SR04


   การทดลองใช้งานโมดูล HC-SR04 วัดระยะห่างด้วยคลื่นอัลตร้าโซนิค
โมดูลสำหรับวัดระยะห่างด้วยคลื่นอัลตราโซนิค มีให้เลือกใช้งานแตกต่างกันไปแล้วแต่ผู้ผลิต คุณภาพ และราคา มีราคาถูกไม่กี่ร้อยบาท ไปจนถึงราคาเป็นพันบาท สามารถนำไปใช้ประยุกต์ใช้งานได้ เช่น การตรวจจับสิ่งกีดขวางสำหรับหุ่นยนต์เคลื่อนที่ บทความนี้จะกล่าวถึง การทดลองใช้งานโมดูล HC-SR04 วัดระยะห่างด้วยคลื่นอัลตร้าโซนิค ร่วมกับบอร์ด Arduino
หลักการทำงานของโมดูลวัดระยะห่างด้วยคลื่นอัลตร้าโซนิค
โมดูล HC-SR04 เป็นอุปกรณ์อิเล็กทรอนิกส์ราคาถูก สำหรับวัดระยะห่างด้วยคลื่นอัลตราโซนิค (ใช้คลื่นเสียงความถี่ ประมาณ 40kHz) มีสองส่วนหลักคือ ตัวส่งคลื่นที่ทำหน้าที่สร้างคลื่นเสียงออกไปในการวัดระยะแต่ละครั้ง ("Ping") แล้วเมื่อไปกระทบวัตถุหรือสิ่งกีดขวาง คลื่นเสียงถูกสะท้อนกลับมายังตัวรับแล้วประมวลผลด้วยวงจรอิเล็กทรอนิกส์ภายในโมดูล ถ้าจับเวลาในการเดินทางของคลื่นเสียงในทิศทางไปและกลับ และถ้าทราบความเร็วเสียงในอากาศ ก็จะสามารถคำนวณระยะห่างจากวัตถุกีดขวางได้

รูปภาพอุปกรณ์ HC-SR04

โมดูล HC-SR04 ทำงานที่แรงดันประมาณ +5V (4.5V ถึง +5.5V) โดยป้อนให้ขา VCC และ GND โมดูลนี้ มีขาสัญญาณดิจิทัล TRIG (อินพุต) และ ECHO (เอาต์พุต) ที่นำไปเชื่อมต่อกับไมโครคอนโทรลเลอร์ได้ อย่างเช่น Arduino ในการวัดระยะห่างแต่ละครั้ง จะต้องสร้างสัญญาณแบบ Pulse ที่มีความกว้าง (Pulse Width) อย่างน้อย 10 usec ป้อนให้ขา TRIG และหลังจากนั้นให้วัดความกว้างของสัญญาณช่วง HIGH จากขา ECHO ถ้าวัตถุอยู่ใกล้ ความกว้างของสัญญาณ Pulse ที่ได้ก็จะน้อย แต่ถ้าวัตถุอยู่ไกลออกไป ก็จะได้ค่าความกว้างของสัญญาณ Pulse ที่มากขึ้น
การเลือกใช้งานโมดูลประเภทนี้ มีประเด็นที่สำคัญ เช่น ช่วงระยะห่างของการวัด ความกว้างของมุมเมื่อคลื่นเสียงเดินทางออกไปจากตัวส่ง (เรียกว่า Beam Angle) นอกจากนั้น การสะท้อนกลับของคลื่นเสียงที่วัตถุกีดขวาง ขนาดและรูปทรงของวัตถุ และการสะท้อนกลับของเสียงจากหลายทิศทาง หรือต่างระยะกัน ก็มีผลต่อความถูกต้องหรือความผิดพลาดในการวัดค่าระยะห่างได้เช่นกัน

ข้อมูลเชิงเทคนิคของโมดูล HC-SR04

  • ใช้แรงดันประมาณ +5V
  • กินกระแสประมาณ 15mA
  • ช่วงการวัดระยะทาง (measurement range): ประมาณ 4cm ถึง 4m
  • ความกว้างเชิงมุมในการวัด (measuring angle): 15 องศา
  • ความกว้างของสัญญาณ Pulse สำหรับ Trigger: 10 usec
  • ระดับแรงดันลอจิกสำหรัขา TRIG และ ECHO: 5V TTL
ศึกษาข้อมูลเพิ่มเติมได้จากเอกสารต่อไปนี้
Datasheet: http://elecfreaks.com/store/download/HC-SR04.pdf (local copy)
ตัวอย่างโคด Arduino ใช้งาน โมดูลวัดระยะทาง Ultrasonic Module Distance Measuring Transducer Sensor
const int pingPin = 13; int inPin = 12; void setup() { Serial.begin(9600); } void loop() { long duration, cm; pinMode(pingPin, OUTPUT); digitalWrite(pingPin, LOW); delayMicroseconds(2); digitalWrite(pingPin, HIGH); delayMicroseconds(5); digitalWrite(pingPin, LOW); pinMode(inPin, INPUT); duration = pulseIn(inPin, HIGH); cm = microsecondsToCentimeters(duration); Serial.print(cm); Serial.print("cm"); Serial.println(); delay(100); } long microsecondsToCentimeters(long microseconds) { // The speed of sound is 340 m/s or 29 microseconds per centimeter. // The ping travels out and back, so to find the distance of the // object we take half of the distance travelled. return microseconds / 29 / 2; }


-หลักการเกี่ยวกับลวดสลิง ช่วยเรียวดูสลิงที่ใช้ดึงแขนกลของพี่สอง
ลวดสลิง (Wire Rope Sling)
ลวดสลิง (wire rope) เป็นเชือกประเภทหนึ่งซึ่งประกอบไปด้วยมัดของเส้นลวดโลหะ ที่บิดเป็นเกลียว ในสมัยก่อนนั้นใช้เหล็กคาร์บอนต่ำ เหล็กอ่อน (wrought iron) ในการผลิต ต่อมาในปัจจุบันลวดสลิงเปลี่ยนมาผลิตจากเหล็กกล้า ลวดสลิงนั้นพัฒนามาจากโซ่เหล็กซึ่งมีปัญหาเรื่องการขาดของข้อโซ่ซึ่งทำให้เกิดอุบัติเหตุร้ายแรงมากมาย ในขณะที่การขาดของเส้นลวดที่ใช้ทำสายลวดสลิงนั้นมีผลน้อยกว่าเนื่องจากยังมีลวดเส้นอื่นที่สามารถรับน้ำหนักได้ แรงเสียดทานระหว่างลวดแต่ละเส้นและมัดเส้นลวดซึ่งเป็นผลมาจากการบิดเกลียว ก็ยังช่วยชดเชยความเสียหายที่เกิดขึ้น 

โครงสร้างของลวดสลิง (wire rope construction)

ลวดเหล็ก
เส้นลวดเหล็กของลวดสลิงนั้นผลิตจากเหล็กคาร์บอน 0.4-0.95% สามารถรับน้ำหนักได้ดี 



มัดเกลียว (strand)
มัดเกลียวหรือที่เรียกว่า cross lay strand ซึ่งลวดในหลายชั้นไขว้สลับซึ่งกันและกัน โดยทั่วไปจะใช้มัดเกลียวแบบขนาน ซึ่งทุกชั้นของลวดมีความยาวเท่ากัน และลวดในทุกๆ ชั้นที่ซ้อนทับนั้นก็ขนานกัน ทำให้มี หน้าสัมผัสแบบเส้นตรง ลวดของชั้นนอกนั้นรองรับโดยลวดสองเส้นในชั้นในตลอดความยาวของมัด เกลียวขนานนั้นทำในครั้งเดียวกัน ลวดสลิงแบบเกลียวขนานมีความทนทานมากกว่าแบบมัดเกลียวไขว้ ลวดสลิงแบบเกลียวขนานมีโครงสร้างแบบ Filler, Seale และ Warrington 


ลวดสลิงแบบ spiral ropes (non-rotating)
ลวดสลิงแบบ spiral ropes มีเกลียวเชือกแบบกลมซึ่งประกอบไปด้วยชั้นของลวดซึ่งมัดเกลียวรอบศูนย์กลางที่เป็นลวดอย่างน้อยหนึ่งชั้นในทิศทางตรงกันข้ามของลวดชั้นนอก ลวดสลิง spiral rope มีคุณสมบัติคือ จะ ไม่หมุนเมื่อได้รับแรงดึงด้วยแรงบิด (torque) นั้นมีค่าใกล้ศูนย์ 

ลวดสลิง (Strande ropes)
ลวดสลิงแบบที่ใช้งานทั่วไปทำจากเกลียวลวดหลายเกลียวตั้งแต่ 1 ชั้นขึ้นไปพันรอบแกน โดยแบ่งตามไส้ (แกนตรงกลาง) ได้ 3 ประเภท 1) ลวดสลิงไส้เชือก (Fiber core) ไส้ตรงกลางทำจากเชือก ซึ่งอาจจะเป็นเชือกที่ผลิตจากเส้นใยธรรมชาติหรือสังเคราะห์ ลวดสลิงไส้เชือกนั้นมีความยืดหยุ่น แต่มีข้อเสียคือขาดได้ง่าย2) ลวดสลิงไส้เกลียวลวด (Wire Strand core) ไส้ตรงกลางเป็นเกลียวลวดอีกมัดหนึ่งซึ่งใช้สำหรับรับแรงกระแทก 3) ลวดสลิงไส้เกลียวลวดอิสระ (Independent wire rope core - IWRC) ซึ่งมีความแข็งแรงสูงที่สุด 
ลวดสลิงโดยส่วนมากจะมีเพียงลวดอีกชั้นหนึ่งนอกเหนือไปจากไส้ (ไส้เหล็กหรือไส้เชือก) ทิศของมัดเกลียวในลวดสลิงอาจจะเป็นทิศขวา (แบบตัว Z) หรือทางซ้าย (แบบตัว S) และทิศของลวดในแต่ละเกลียว อาจจะเป็นทางขวาหรือทางซ้ายเช่นเดียวกัน
หากทิศทางของเกลียวของลวดในแต่ละเกลียวและทิศของมัดเกลียวในลวดสลิงตรงกันข้ามกันจะเรียกว่า ordinary/regular lay rope (ลวดวางตัวในแนวที่ขวางกับทิศทางการตีเกลียว) การเรียงตัวแบบนี้ทำให้มีโอกาสเกิดรอยแตก (kiln) น้อย และมีโอกาสที่จะเกิดความเสียหายจากแรงกระชาก หรือการบิดตัวก็จะน้อยด้วย เชือกลวดเหล็กกล้าแบบนี้ถูกนำไปใช้งานหลากหลายที่สุด โดยจะมีความสามารถต้านทานต่อแรงกระแทก (crushing) มากกวางแบบแลงส์ และจะไม่มีการบิดตัวในขณะที่ใช้งานภายใต้แรงกระทำที่รุนแรง เมื่อปลายข้างหนึ่งของเชือกลวดเหล็กกล้าไม่ได้ถูกยึดให้อยู่กับที่
แต่หากทิศของลวดในเกลียว และทิศของเกลียวนั้นมีการบิดเกลียวในทิศทางเดียวกันจะเรียกว่า lang lay rope (มาจาก Albert's lay หรือ Lang's lay) ลวดจะเรียงตัวทำมุมขวางกับแนวตามยาวของเชือกลวดเหล็กกล้า (ลวดวางในแนวเดียวกับทิศทางของการตีเกลียว) เชือกลวดเหล็กกล้าแบบนี้มีข้อได้เปรียบที่สำคัญ 2 ประการ คือ จะมีความต้านทานต่อความล้า และการสึกหรอจากจากเสียดสีในขณะใช้งานที่ดีกว่าเชือกลวดเหล็กกล้าแบบธรรมดา (regular lay) และเนื่องจากบริเวณพื้นที่ผิวของลวดเหล็กแต่ละเส้นมีมากกว่า ดังนั้นเวลาที่อยู่ภายใต้สภาวะการใช้งานที่เชือกลวดเหล็กกล้าต้องถูกดัดโค้ง จึงมีแรงดัดโค้งมากระทำน้อยกว่า ดังนั้นจะพบว่าเชือกลวดเหล็กกล้าแบบแลงส์จะมีความยืดหยุ่นดีกว่า และมีอายุการใช้งานภายใต้สภาวะที่มีแรงดัดโค้งมากระทำเป็นหลัก ได้นานกว่าแบบธรรมดา (regular lay) ได้ประมาณ 15-20% แต่มีโอกาสที่เกิดรอยแตก (kiln) มากกว่า และทนต่อแรงกระแทกได้น้อยกว่าแบบธรรมดา
ลวดสลิงที่มีหลายมัดเกลียวนั้นจะมีแรงต้านการหมุนและมีมัดลวดอย่างน้อย 2 ชั้น บิดเกลียวอยู่รอบไส้ ทิศทางของมัดลวดข้างนอกนั้นอย่ตรงข้ามกันกับมัดลวดขั้นถัดไป ลวดสลิงที่มีมัดลวด 3 ชั้น นั้นถือได้ว่าเกือบจะเป็น non-rotating ส่วนลวดสลิงที่มี 2 ชั้นนั้นจะเป็นเพียงแค่ low-rotating 


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

วันอังคารที่ 21 กรกฎาคม พ.ศ. 2558

วันที่46 ที่Fibo

-การใช้งาน Matrix Switch (Keypad)
ทฤษฎีและหลักการ
   คีย์แพดหมายถึง อุปกรณ์อ่านค่าอินพุตต่อเข้ากับปุ่มกดจำนวนของคีย์แพด จะเท่ากับ ขาพอร์ตของที่ใช้งานซึ่งเป็นการสิ้นเปลืองขาพอร์ตจึงมีการต่อใช้สวิตช์จำนวนมากนี้แบบรูปของ “เมตริกสวิตช์” (Metrix Switch) จึงทำให้ลดการใช้พอร์ตได้อย่างดี 
     การต่อใช้งานคีย์แพดเมตริกสวิตช์จะต่อใช้งานแบบพูลอัพ ดังนั้นสถานะของสวิตช์จะมีสถานะเป็น “.1” ทั้งหมด เมื่อต้องการอ่านค่าของคีย์แพด เราจะต้องกำหนดค่าของหลัก (Column) ให้สถานะเป็น “0” เพราะ หลัก (Column) นั้นจะเป็นการควบคุมสัญญาณ หากสวิตช์แถวไหน มีการเปลี่ยนแปลงแสดงว่าแถวนั้นมีการกดสวิตช์ 
***Download ไฟล์ได้จาก***
http://cid-c0a6064779796550.skydrive.live.com/browse.aspx/.Public





การต่อ keypad


-โค้ดการทำงาน Keypad โดยการใส่ password
  -การนำไปใช้คือ เอาไปใช้กับล็อคห้องหรือใช้ในการที่ต้องใส่ password แล้วมีการปล้ดล็อค

#include <Keypad.h>
int  counter = 0;
int Delay1;
char* secretCode = "21010704";
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','4','7','*'},
  {'2','5','8','0'},
  {'3','6','9','#'},
  {'A','B','C','D'}
};
byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

void setup(){
  Serial.begin(9600);
  pinMode(13,OUTPUT);
}

void loop()
{
  char customKey = customKeypad.getKey();
  if (customKey)
  {
    Serial.print(customKey);
  }
  if (customKey == secretCode[counter])
  {
    counter++;
    delay(5);
    if(counter == 8)
    {
      digitalWrite(13,HIGH);
      counter=0;
  }
  if(customKey == '*'||customKey == '#')
  {
     counter = 0;
     digitalWrite(13,LOW);
  }
  delay(50);
}



-ปัญหาที่จะเจอเวลาที่เขียนคือ หาlibraly ของ keypad ไม่ได้และการที่จะใส่passwordได้เราต้องรู้จักเรียกใช้ตัวแปลให้ถูก การใช้char* คือจะใส่อักษรได้แบบยาวๆ

-ในช่วงบ่าย น้องนักศึกษใหม่ได้เข้ามาแล๊ปเพื่อศึกษาในแต่ละแล๊ปและเรียนรู้เบื้องต้นในแล๊ปนั้นๆโดยพี่ๆที่อยู่ห้องแล๊ปได้แนะนำและเสนอแนะ พีเซ็นโปรเจ็คของแต่ละคน
     -พี่กอฟจะได้รับความสนใจจากน้องๆ เป็นอันดับ1เลยก็ว่าได้เพราะน้องๆเขาสนใจเกียบกับคลื่นสมอง และสงสัยว่าทำได้ไงเพราะสมองเรามีความซับซอนมาก


วันจันทร์ที่ 20 กรกฎาคม พ.ศ. 2558

วันที่45 ที่Fibo

-การทดลอง sensor TCST2202 ทำงานได้และจะนำไปใช้กับการควบคุมมอเตอร์ที่จะนำไปเขย่าสาร เพื่อจะวัดความเร็วรอบและจะได้ไปควบคุมPID
  -หลังจากทดลองข้างต้นได้ทำการต่อตรงโดยไม่มีการลดแรงดันทำให้ เซ็นเชอร์ตัวหนึ่งไหม้จนทำให้รู้ว่าอาจเป็นอัตรายต่อบอร์ดได้หากต่อตรงโดยไม่ผ่านตัวต้านทาน


-ต่อตามวงจรนี้แล้วผลที่ได้ยังคงทำงานไม่ได้ ส่วนที่จะแก้คือ R 100ohm แล้วใช้ 370ohm แทนถึงจะทำงานได้ 
-สาเหตุที่ใช้ R 100ohm ไม่ได้เพราะแรงดันตกลงต่ำมากทำให้ไม่สามารถส่งแรงอินพุตท์ไปทำง่นไม่ได้
     -ถ้าใช้ R 100ohm วัดแรงดันตกคร่อม R ได้ 0.78V
     -ถ้าใช้ R 370ohm  วัดแรงดันตกคร่อม R ได้ 3.5V


-แต่ละขาของ เซ็ฯเชอร์ TCST 2202


ผลการทดลอง

-โค้ดทดลองการทำงาน

#define inputTCST  7
#define LED  13

void setup() 
{
pinMode(LED,OUTPUT);
pinMode(inputTCST,INPUT);
Serial.begin (9600);
}

void loop() 
{
  if(digitalRead(inputTCST) == LOW)
  {
    digitalWrite(LED,LOW);
    Serial.println(0);
  }
  else
  {
    digitalWrite(LED,HIGH);
    
    Serial.println(1);
  }
  delay(100);
}

-การทกงานอธิบายตามคริปเลย
-ส่วน dstasheet หาได้ง่ายๆ เพียงแค่ค้นหาคำว่า "datasheet TCST 2202"
-โค้ดก่อนหน้านี้ที่ทำงานไม่ได้ เพราะ ลืมให้อ่านค่า input sensor ทำให้ไม่มีการอ่านค่าจนอ่านมาเจอโค้ดตัวเองเลยได้ทำการแก้ไข จนทำงานได้

วันอาทิตย์ที่ 19 กรกฎาคม พ.ศ. 2558

วันที่44 ที่Fibo

-PLC ของน้องๆ น้องๆมีทักษะที่เก่งแล้วแนวความคิดในการควบคุมPLC นั้นเก่งมากๆ แล้วผมได้ให้คะแนนแก่ กลุ่มที่ทำงานเป็นเครื่องแยกขนาดกล่อง คือการทำงานจะใช้เซ็นเชอร์ วัด2ตัวถ้าขนาดเลยตัวที่1ไปจนทำให้ตัวที่2ทำงานแสดงว่ายาวทำให้แยกได้โดย คริปเปอร์หรือมือจับจะจับแล้วแยกลงสายพานแต่ละช่อง
-PLC อีกตัวที่ได้ให้คะแนนนั้นคือ เครื่องผสมน้ำอัตโนมัติ ติดใจที่เราสามารถผสมน้ำเองได้โดยเราใช้แค่ปลายนิ้วกดแค่นั้น

-tcst 2202 ลองเขียนควบคุมเซ็นเชอร์tcst 2202 แล้วผลที่ได้คือถ้าจ่ายไฟ5Vจะทำงานได้โดย LEDจะติดแต่ถ้าจ่ายต่ำกว่านี้การทำงานจะไม่ทำงานไฟจะไม่ติดแต่พอดีว่าลองอ่านใน datasheet แล้วการต่อวงจรนั้นยังคงไม่ตรงตามที่ในเว็ปที่ได้ไปเปิดอ่านแต่ยังไหร่ก็ตามการทำงานนั้นทำได้ตามปกติ




การต่อวงจร

อธิบายขาของเซ็นเชอร์


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


วันพฤหัสบดีที่ 16 กรกฎาคม พ.ศ. 2558

วันที่43 ที่Fibo

-ดูข้อมูลแขนกล และหลักการของแขนกลโดยศึกษาเบื้องต้น

ทฤษฎีที่เกี่ยวข้อง
2.1 โครงสร้างทางกายภาพ
หุ่นยนต์อุตสาหกรรม (Industrial Robot)
             การทำงานของหุ่นยนต์อุตสาหกรรมจะเลียนแบบร่างกายของมนุษย์โดยจะเลียนแบบเฉพาะส่วนของร่างกายที่นำไปใช้ประโยชน์ ในอุตสาหกรรมเท่านั้น นั่นคือช่วงแขนของมนุษย์ ดังนั้น บางคนอาจจะเคยได้ยินคำว่าแขนกล ซึ่งก็หมายถึงหุ่นยนต์อุตสาหกรรม
              การทำงานของแขนกลอุตสาหกรรมเปรียบเทียบกับแขนมนุษย์ แสดงดังรูปที่ 2.1

2.2 นิยามของหุ่นยนต์ (Robotics definition)  
หุ่นยนต์ คือ เครื่องจักรที่ถูกควบคุมอัตโนมัติ สามารถเขียนโปรแกรมใหม่ได้ ใช้งานเอนกประสงค์ โปรแกรมการเคลื่อนที่ต้องสามารถโปรแกรมให้เคลื่อนที่ได้อย่างน้อย 3 แกนหรือมากกว่า หุ่นยนต์อาจยึดอยู่กับที่หรือย้ายตำแหน่ง (Mobile) เพื่อใช้ในงานอุตสาหกรรม

2.3 การแบ่งชนิดของหุ่นยนต์      
            โดยทั่วไปการแบ่งชนิดของหุ่นยนต์จะแบ่งตามลักษณะรูปทรงของพื้นที่ทำงาน (Envelope Geometric) ซึ่งการทำงานของจุดต่อ (Joint) ของหุ่นยนต์หรือแขนกลแต่ละชนิดแตกต่างกันออกไปซึ่งจุดต่อ (Joint) ของหุ่นยนต์หรือแขนกลในโรงานอุตสาหกรรมนั้น สามารถแบ่งออกเป็น 2 ชนิดดังนี้................................................................

2.4 หลักการทำงานของระบบมอเตอร์ไฟฟ้ากระแสตรง
มอเตอร์คือ  เครื่องใช้ไฟฟ้าประเภทเครื่องกล ที่ใช้งานกันอยู่โดยทั่วไปภายในอาคารบ้านเรือนและโรงงานอุตสาหกรรม ได้แก่ พัดลม เครื่องบด เครื่องปั่น เครื่องซักผ้า ปั๊มน้ำ เครื่องกลึง เครื่องไส เครื่องเจาะ เครื่องคว้าน เครื่องเลื่อย เครื่องเจียระไน แขนกล  เป็นต้น ต่างก็ทำงานด้วยการหมุนขับของมอเตอร์  ดังนั้นมอเตอร์จึงเป็นเครื่องกลฟ้าที่ให้กำเนิดพลังงานกลที่จำเป็นและสำคัญยิ่งประเภทหนึ่ง
2.4.1  หลักการเบื้องต้นของมอเตอร์
2.4.2 การสูญเสียในมอเตอร์แบ่งออกได้ดังนี้
การออกแบบ และการสร้างแขนกล
4.1 อุปกรณ์ในการทดลอง
ในการทดลองควบคุมแขนกลนี้ โดยใช้วงจรควบคุมทิศทางการหมุนของมอเตอร์ เป็นตัวควบคุมแขนกลให้เคลื่อนที่ตามมุมองศาที่ต้องการ และให้มีความคลาดเคลื่อนน้อยที่สุดในการทำโครงงานจะเป็นส่วนโครงสร้างของแขนกล ซึ่งเป็นแบบ Articulated Arm (Revolute) โดย ไม่รวมถึงการเขียนโปรแกรมควบคุมด้วย

มอเตอร์คือเครื่องกลไฟฟ้าที่เปลี่ยนพลังงานไฟฟ้า  ให้เป็นพลังงานกล 
....................................
ตัวนำที่ให้กระแสไฟฟ้าไหลผ่านเมื่อวางไว้ใกล้กันจะให้แรงดูดและแรงผลักต่อกัน
     -  ตัวนำที่ให้กระแสไหลทางเดียวกัน จะให้แรงดูดต่อกัน
     -  ตัวนำที่ให้กระแสไหลสวนทางกัน  จะให้แรงผลักต่อกัน
แรงดูดและแรงผลักระหว่างตัวนำที่ให้กระแสไฟฟ้าไหลผ่าน คำนวณได้ตามสมการไฟฟ้าต่อไปนี้

F = 2×10-7×I1×I2×/a [N]

เมื่อ       F   =  แรงดูดและแรงผลักต่อกันระหว่างตัวนำ (นิวตัน  :N)
             I1     กระแสไฟฟ้าที่ให้ไหลผ่านตัวนำ  (แอมแปร์ : A)
             I2    =   กระแสไฟฟ้าที่ให้ไหลผ่านตัวนำ  (แอมแปร์ : A)
               =  ความยาวตัวนำ (เมตร : m)
             a    =  ระยะห่างระหว่างตัวนำ (เมตร : m)
...........................................................

1.  การสูญเสียในขดลวดทองแดง
                        -  การสูญเสียในขดลวดอาร์เมเจอร์
                        -  การสูญเสียในขดลวดสนามแม่เหล็ก
...................................................

2.5 การควบคุมทิศทางการหมุนของ DC Motor
1.  วงจร H-Bridge Switching โดยใช้ สวิตช์
วงจร H-Bridge Switching ประกอบด้วยสวิตช์ 4 ตัว คือ S1  S2  S3 และ S4 และมีมอเตอร์
ไฟฟ้ากระแสตรง (DC Motor) เป็นภาระต่ออยู่ดังรูปที่ 2.9................................................
2.6  องค์ประกอบอื่นๆที่เกี่ยวข้อง
2.6.1 ระบบโซ่และล้อโซ่ (Chain And Sprocket)
การขับด้วยโซ่มีใช้อยู่มากเหมือนกันทางด้านเครื่องจักรกล  ทั้งนี้เนื่องมาจากมีลักษณะคล้ายกับการขับด้วยสายพาน  ..............................................
 
2.6.2 เซ็นเซอร
ระบบควบคุมที่ดีมีความแมนยําและทํางานอยางอัตโนมัตินั้นไมไดเกิดจากการควบคุมเพียง
อยางเดียวคงตองพึ่งพาอุปกรณตรวจจับ (Sensor Element) ..................................
ในบทนี้จะกล่าวถึงการออกแบบแขนกลเป็นแบบ  Articulated Arm (Revolute)  ซึ่งแขนกลแบบ Articulated Arm (Revolute)  ................................
3.1  การออกแบบโครงสร้างแขนกล
ในการศึกษา และเก็บข้อมูลได้เลือกการออกแบบแขนกลเป็นแบบ  Articulated Arm (Revolute)   ทุกแกนการเคลื่อนที่เป็นแบบหมุน (Revolute) รูปแบบการเคลื่อนที่คล้ายกับแขนคน ซึ่งประกอบด้วยช่วงเอว ท่อนแขนบน ท่อนแขนล่าง และข้อมือ การเคลื่อนที่ทำให้ได้พื้นที่การทำงาน ดัง รูป 3.1
3.2  วงจรไฟฟ้าควบคุมทิศทางทางหมุนของมอเตอร์กระแสตรง
ในการศึกษาเก็บข้อมูลวงจรไฟฟ้าควบคุมทิศทางทางหมุนของ DC Motor ได้เลือกใช้
ไอซี 7279P  ดังรูปที่ 3.6  
3.3  เซ็นเซอร์ (Sensor)
ในการออกแบบแขนกล เซ็นเซอร์ที่ใช้เป็นแบบ Through – beam type เปนแบบที่ตัวรับและตัวสงแสงแยก กันอยูคนละด้าน และใหวัตถุที่ตรวจจับเคลื่อนผานระหวางกลางดังรูปที่ 3.7    
............................ 
3.4  ลิมิตสวิตช์ (limit switch)
            ลิมิตสวิตช์ ภายในประกอบไปด้วย 2 ชุด ซึ่งทำหน้าที่กำหนดขอบเขตการหมุนของมอเตอร์และป้องกันการกระแทกของแขนกล
...................
3.5   วงจรการควบคุมการกลับทางหมุนของมอเตอร์ 
3.6  ไดอะแกรมการทำงานของมอเตอร์แขนกล 
การทดลองและวิเคราะห์
การทดลองและข้อมูลที่กล่าวถึงในบทนี้  เป็นส่วนที่เกี่ยวกับการควบคุมการเคลื่อนที่ของแขน ให้มีความผิดพลาดน้อยที่สุด  โดยทั่วไปแล้วแขนกลอุตสหกรรมนั้นจะมีอุปสรรคในการที่จะป้อนข้อมูลเข้าสู่หน่วยความจำของแขนกล  ทำให้สามารถรู้ตำแหน่งของแขนกลในขณะต่างๆ
1.  แขนกล
2.  อุปกรณ์ควบคุมเชื่อมต่อกับ PLC
วงจรไฟฟ้าควบคุมทิศทางทางหมุนของ มอเตอร์ไฟฟ้ากระแสตรง (DC Motor)
-  เซ็นเซอร์
-  ลิมิตสวิตช์
3.   แหล่งจ่ายไฟขนาด12 โวลต์
แหล่งที่มา http://www.duinothumb.com/showcases/diy-robot-arm 

 -key pad ศึกษาและหาความรู้เรื่อง keypad เพราะว่าเห็นมันว่างอยู่บนโต๊ะเลยลองเอามาหาความรู้ดู

โค้ดตัวอย่าง 
#include <Password.h> //http://www.arduino.cc/playground/uploads/Code/Password.zip
#include <Keypad.h> //http://www.arduino.cc/playground/uploads/Code/Keypad.zip
Password password = Password( "1234" );
const byte ROWS = 4; // Four rows
const byte COLS = 4; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {13, 12, 11, 10};
byte colPins[COLS] = {9, 8, 7, 6};
// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup(){
  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
}
void loop(){
  keypad.getKey();
}
//take care of some special events
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
Serial.print("Pressed: ");
Serial.println(eKey);
switch (eKey){
 case '*': checkPassword(); break;
 case '#': password.reset(); break;
 default: password.append(eKey);
     }
  }
}
void checkPassword(){
  if (password.evaluate()){
    Serial.println("Success");
    //Add code to run if it works
  }else{
    Serial.println("Wrong");
    //add code to run if it did not work
  }
}
 Arduino with 4x4 Keypad membrane and 4 Channel Relay
   วันนี้จะว่ากันด้วยเรื่องของ 4x4 Keypad membrane นะครับ โดยรุ่นที่นิยมใช้กับ Arduino ก็จะเป็นแบบ 4 x 4  ซึ่งมีตัวเลข 0 - 9  และ ตัวอักษรอีกนิดหน่อย
  มาดูหลักการทำงานของ Keypad membrane กันนิดหน่อยนะครับ  4x4 Keypad membrane แบบ 4 x 4  ชนิดนี้ก็ประกอบไปด้วยปุ่ม 16 ปุ่ม ที่เรียงต่อกันเป็นเมตริกซ์แบบ 4 Row และ 4 Column  ถ้าใครเคยได้สัมผัสแล้วก็คงพอจะเดาออกว่าปุ่มแต่ละปุ่ม  เป็นการกดเพื่อให้หน้าสัมผัสที่เป็นชั้นสีแดงในรูปด้านล่าง ไปแตะกันทำให้เป็นการเชื่อมต่อกันทางไฟฟ้าไปอีกด้านหนึ่งของสวิตช์
   ทีนี้หลักการในการตรวจสอบว่าผู้ใช้กำลังกดปุ่มอะไรอยู่นั้นก็ใช้วิธีการ scan ไปทีละ Column ครับจบครบทุก Column แล้วนำมาตีความว่ามีการตอบสนองออกมาเป็นแบบใดบ้าง  เช่น ถ้ามีการกดเลข 1  อยู่  ในขณะที่เราจ่ายแรงดัน 5 โวลต์ไปที่ Column ที่ 1  จะมีเพียง Row แรกเท่านั้นที่จะอ่านค่า แรงดันได้ High นอกนั้นจะเป็น Low     หรือ ถ้ามีการกดปุ่ม # อยู่ ขณะที่ Scan ไปแต่ละ Column นั้นจะไม่เจอแรงดัน High ที Row ใดเลย จนกว่าจะ Scan ไปถึง Column ที่ 3 ซึ่งจะพบว่ามีการตอบสนองกลับมาจาก Row ที่ 4 นั้นเอง  ดังนั้นเมือพบว่าเป็นการ Scan Column ที่ 3 และมี Row 4 ตอบสนอง ก็คือปุ่ม '#' นั่นเอง
  อ่านแล้วก็รู้สึกว่าไม่ซับซ้อนมานักใช่มั้ยครับ  แต่มันมีมากกว่านั้นอีกตรงที่ว่าจังหวะการกดของคนแต่ละคน กดด้วยช่วงเวลาสั้นยาวไม่เท่ากัน  ทำให้ต้องมีการตรวจสอบโดยมีระยะเวลาเข้ามาเกี่ยวข้อง  ไม่อย่างนั้นจะสับสนระหว่างการกดแช่ หรือ การกดแบบซ้ำปุ่ม   นอกจากนั้นยังต้องมี debouncing ด้วยครับ เพื่อป้องกันการรับค่าผิดจากการ bounce ของสวิตช์  (ถ้าใครเคยเรียน Digital Design อาจจะเข้าใจได้ทันที ถ้าไม่รู้จักก็ไม่เป็นไรนะครับ)    แถมยังต้องมีการจดจำปุ่มที่กดไปแล้วอีกว่ากดอะไรไปบ้าง  กี่ครั้งแล้ว ก่อนที่จะมาประมวลผล ตรวจสอบค่าที่ใส่ เปรียบเทียบกับค่าที่ตั้งไว้เป็นรหัส  

 

Keypad Membrane wIki
-แหล่งที่มา http://www.arduitronics.com/article/arduino-with-keypad-and-4-channel-relay

 -หลังจากนั้นช่วงบ่ายๆก็ได้ช่วยงานพี่ๆเข้ามเล่มหนังสือ หลายๆรายวิชาก็เป็นอีกแบบหนึ่งที่ได้ทำสนุกดีทำผิดพลาดไปก็เยอะ นี้คืองานเอกสารที่ได้ทำ(วิศวทำงานเอกสารก็ต้องผิดพลาดบ้าง) นี้ก็เป็นของพี่เปียวที่ได้ทำช่วยก็ได้เปิดดูและดูข้างนิดนิดหน่อยไม่มาก คือจะมีหลักการการเคลื่อนที่ของสัตว์แล้วนำมาประยุกค์กับการเคลื่อนไหวหุ่นยนต์ก็เป็นได้เท่าที่เปิดผ่านไป