22 พฤษภาคม 2555

22 พฤษภาคม 2555(PresentการทดสอบรถBluetoothแบบมีGripperด้วย)





22 พฤษภาคม 2555 (เพิ่ม Gripperในรถ Bluetooth)

โดยติดไว้ที่ส่วนด้านหน้าของรถสามารถยกขวดน้ำสิ่งของขนาดเล็กทั่วไปได้
โดยต่อบอร์ดIC293 เพิ่มอีกหนึ่งบอร์ด
โดยต่อกับarduinoดังนี้

enable1 : 36   enable2 : 40
motor3 : 38 39
motor4 : 42 43
และแก้โค๊ดโดยเพิ่มตัวแปร และฟังก์ชันดังนี้


//BluetoothCar Project
//author krit
//Date 11/4/2012


int pwm1=9;       int pwm2=8;
int m1D1=22;      int m1D2=23;
int m2D1=32;      int m2D2=33;
int enable1=36;   int enable2=40;
int m3D1=38;      int m3D2=39;
int m4D1=42;      int m4D2=43;
int in;
int total=0;
char state=0;

void countSec();
void go(int speedM);
void back(int speedM);
void tLeft(int speedM);
void tRight(int speedM);
void stopM();
void clip();
void un_clip();
void up();
void down();

void setup()
{
  pinMode(m1D1,OUTPUT);
  pinMode(m1D2,OUTPUT);
  pinMode(m2D1,OUTPUT);
  pinMode(m2D2,OUTPUT);
  pinMode(m3D1,OUTPUT);
  pinMode(m3D2,OUTPUT);
  pinMode(m4D1,OUTPUT);
  pinMode(m4D2,OUTPUT);
  pinMode(enable1,OUTPUT);
  pinMode(enable2,OUTPUT);
  Serial.begin(9600);
  Serial.print("Start\n");
}
void loop()
{
  total=0;
  state=0;
  if(Serial.available()>0){
    state=Serial.read();
    while(Serial.available()==0 && state!='S'&& state!='C'&& state!='N'&& state!='U'&& state!='D');
    if(Serial.available()>0 && state!='S'&& state!='C'&& state!='N'&& state!='U'&& state!='D'){
      total=(Serial.read());
      //total=(total-66)*10;
    }
  }
  if(state!=0){
    switch(state){
      case 'C':  clip();       break;
      case 'N':  un_clip();    break;
      case 'U':  up();         break;
      case 'D':  down();       break;
      case 'G':  go(total);    break;
      case 'B':  back(total);  break;
      case 'L':  tLeft(total); break;
      case 'R':  tRight(total);break;
      case 'S':  stopM();    break;
      default:  stopM();
    }
  }
}

void go(int speedM){
  Serial.print("Go!\t");
  Serial.print(speedM);
  Serial.print("\n");
  analogWrite(pwm1, speedM);
  digitalWrite(m1D1,HIGH);
  digitalWrite(m1D2,LOW);
  analogWrite(pwm2, speedM);
  digitalWrite(m2D1,HIGH);
  digitalWrite(m2D2,LOW);
}

void back(int speedM){
  Serial.print("Back!\t");
  Serial.print(speedM);
  Serial.print("\n");
  analogWrite(pwm1, speedM);
  digitalWrite(m1D2,HIGH);
  digitalWrite(m1D1,LOW);
  analogWrite(pwm2, speedM);
  digitalWrite(m2D2,HIGH);
  digitalWrite(m2D1,LOW);
}

void tLeft(int speedM){
  Serial.print("turnLeft!\t");
  Serial.print(speedM);
  Serial.print("\n");
  analogWrite(pwm1, speedM);
  digitalWrite(m1D2,HIGH);
  digitalWrite(m1D1,LOW);
  analogWrite(pwm2, speedM);
  digitalWrite(m2D2,LOW);
  digitalWrite(m2D1,HIGH);
}

void tRight(int speedM){
  Serial.print("turnRight!\t");
  Serial.print(speedM);
  Serial.print("\n");
  analogWrite(pwm1, speedM);
  digitalWrite(m1D2,LOW);
  digitalWrite(m1D1,HIGH);
  analogWrite(pwm2, speedM);
  digitalWrite(m2D2,HIGH);
  digitalWrite(m2D1,LOW);
}

void stopM(){
  Serial.print("Stop!\n");
  digitalWrite(pwm2, HIGH);
  digitalWrite(pwm1, HIGH);
  digitalWrite(m1D2,HIGH);
  digitalWrite(m1D1,HIGH);
  digitalWrite(m2D2,HIGH);
  digitalWrite(m2D1,HIGH);
  digitalWrite(enable1,HIGH);
  digitalWrite(m3D2,LOW);
  digitalWrite(m3D1,LOW);
  digitalWrite(enable2,HIGH);
  digitalWrite(m4D2,LOW);
  digitalWrite(m4D1,LOW);
}
void clip(){
  digitalWrite(enable2,HIGH);
  digitalWrite(m4D2,LOW);
  digitalWrite(m4D1,HIGH);

}
void un_clip(){
  digitalWrite(enable2,HIGH);
  digitalWrite(m4D2,HIGH);
  digitalWrite(m4D1,LOW);
}
void up(){
  digitalWrite(enable1,HIGH);
  digitalWrite(m3D2,LOW);
  digitalWrite(m3D1,HIGH);

}
void down(){
  digitalWrite(enable1,HIGH);
  digitalWrite(m3D2,HIGH);
  digitalWrite(m3D1,LOW);
}


8 พฤษภาคม 2555

2-9 พฤษภาคม 2555 (การนำUNO32ควบคุมมอเตอร์4)

ตัวอย่าง flow chart แสดงการทำงานของโปรแกรมควบคุมมอเตอร์ด้วย PID

2-8 พฤษภาคม 2555 (การนำUNO32ควบคุมมอเตอร์3)

แต่ใน arduno นั้นมี library สำเร็จรูปของ PID อยู่แล้วด้วยโดยสามารถ download ได้ที่ http://arduino.cc/playground/Code/PIDLibrary
โดยเราแต่ปรับค่าตัวแปรบางอย่างภายในก็พอ ส่วนสมการคำสั่ง library จะจัดการคำนวนค่าoutputให้เอง แล้วเราก็จะสามารถนำค่า output ที่ได้ไปควบคุมมอเตอร์ได้ทันทีซึ่งเท่าที่ผู้เขียนเคยใช้ก็ใช้ได้ดีนะ สะดวกกว่าที่เราจะเขียนโค๊ดของสมการขึ้นเองอีก แค่เราอ่านค่า analog input จาก encoder แล้วใส่ใน input แล้วสามารถใช้ค่า output กับมอเตอร์ได้ทันทีโดยฟังก์ชันหลักได้แก่ฃ


PID(double* Input, double* Output, double* Setpoint,double Kp, double Ki, double Kd, int ControllerDirection)
ตามที่เข้าใจเป็นการสร้าง object PID ขึ้นโดย Input คือ พอย์เตอร์ของค่าที่ encoderอ่านได้ Output คือพอย์เตอร์ของค่าที่จะนำไปขับมอเตอร์ Setpoint คือ พอย์เตอร์ของค่าเป้าหมายที่จะให้มอเตอร์หมุน ControllerDirectionคือทิศทางของมอเตอร์ Kp,Ki,Kd คือค่าPID
ตัวอย่าง

PID myPID(&double_Input, &double_Output, &double_Setpoint,double_consKp, double_consKi, double_consKd, DIRECT);


Compute()
คือฟังก์ชันหาค่าPWMที่จะไปหมุนมอเตอร์
ตัวอย่าง
myPID.Compute();


SetOutputLimits(double Min, double Max)
คือฟังก์ชันที่ใช้ในการกำหนดค่า outputไม่ให้เกินกำหนด
ตัวอย่าง
myPID.SetOutputLimits(-max_limit, max_limit);

และฟังก์ชันGetค่าต่างๆภายใน object

double GetKp()

double GetKi()

double GetKd()

int GetMode()

int GetDirection()

6 พฤษภาคม 2555

2-7 พฤษภาคม 2555 (การนำUNO32ควบคุมมอเตอร์2)

เมื่อรู้องศาปัจจุบันของมอเตอร์แล้วก็จะต้องหมุนมอเตอร์ไปยังองศาที่ต้องการโดย หลักการ PID
โดยผู้เขียนไม่สันทัดด้านนี้มากนักจึงขอยืมข้อความจาก wikipedia มาแล้วกันว่ามันคือ " ระบบควบคุมแบบป้อนกลับที่ใช้กันอย่างกว้างขวาง ซึ่งค่าที่นำไปใช้ในการคำนวณเป็นค่าความผิดพลาดที่หามาจากความแตกต่างของตัวแปรในกระบวนการและค่าที่ต้องการ ตัวควบคุมจะพยายามลดค่าผิดพลาดให้เหลือน้อยที่สุดด้วยการปรับค่าสัญญาณขาเข้าของกระบวนการ ค่าตัวแปรของ PID ที่ใช้จะปรับเปลี่ยนตามธรรมชาติของระบบ"หลักการ "วิธีคำนวณของ PID ขึ้นอยู่กับสามตัวแปรคือค่าสัดส่วน, ปริพันธ์ และ อนุพันธ์ ค่าสัดส่วนกำหนดจากผลของความผิดพลาดในปัจจุบัน, ค่าปริพันธ์กำหนดจากผลบนพื้นฐานของผลรวมความผิดพลาดที่ซึ่งพึ่งผ่านพ้นไป, และค่าอนุพันธ์กำหนดจากผลบนพื้นฐานของอัตราการเปลี่ยนแปลงของค่าความผิดพลาด น้ำหนักที่เกิดจากการรวมกันของทั้งสามนี้จะใช้ในการปรับกระบวนการ" อ่านเพิ่มเติมได้ที่ http://th.wikipedia.org/wiki/%E0%B8%A3%E0%B8%B0%E0%B8%9A%E0%B8%9A%E0%B8%84%E0%B8%A7%E0%B8%9A%E0%B8%84%E0%B8%B8%E0%B8%A1%E0%B8%9E%E0%B8%B5%E0%B9%84%E0%B8%AD%E0%B8%94%E0%B8%B5

สรุปก็คือมีสูตรมาแล้วมีตัวแปร Kp Ki Kd แล้วเราปรับไปจะทำให้ output ของสมาการเปลี่ยนไปแล้วเรานำ output นี้ไปควบคุมมอเตอร์ให้หมุนได้แม่นยำโดยหลักการหา PID มีสองแบบแต่ผู้เขียนขอยกมาเฉพาะ จูนด้วยมือจาก wikipedia "การปรับจูนด้วยมือ ถ้าระบบยังคงทำงาน ขั้นแรกให้ตั้งค่า K_i และ K_d เป็นศูนย์ เพิ่มค่า K_p จนกระทั่งสัญญาณขาออกเกิดการแกว่ง (oscillate) แล้วตั้งค่า K_p ให้เหลือครึ่งหนึ่งของค่าที่ทำให้เกิดการแกว่งสำหรับการตอบสนองชนิด "quarter amplitude decay" แล้วเพิ่ม K_i จนกระทั่งออฟเซตถูกต้องในเวลาที่พอเพียงของกระบวนการ แต่ถ้า K_i มากไปจะทำให้ไม่เสถียร สุดท้ายถ้าต้องการ ให้เพิ่มค่า K_d จนกระทั่งลูปอยู่ในระดับที่ยอมรับได้ แต่ถ้า K_d มากเกินไปจะเป็นเหตุให้การตอบสนองและโอเวอร์ชูตเกินยอมรับได้ ปกติการปรับจูน PID ถ้าเกิดโอเวอร์ชูตเล็กน้อยจะช่วยให้เข้าสู่จุดที่ต้องการเร็วขึ้น แต่ในบางระบบไม่สามารถยอมให้เกิดโอเวอร์ชูตได้ และถ้าค่า K_pน้อยเกินไปก็จะทำให้เกิดการแกว่ง"

ผลของการเพิ่มค่าตัวแปรอย่างอิสระ
ตัวแปรช่วงเวลาขึ้น
(Rise time)
โอเวอร์ชูต
(Overshoot)
เวลาสู่สมดุลย์
(Settling time)
ความผิดพลาดสถานะคงตัว
(Steady-state error)
เสถียรภาพ[1]
K_pลดเพิ่มเปลี่ยนแปลงเล็กน้อยลดลด
K_iลด[2]เพิ่มเพิ่มลดลงอย่างมีนัยสำคัญลด
K_dลดลงเล็กน้อยลดลงเล็กน้อยลดลงเล็กน้อยตามทฤษฏีไม่มีผลดีขึ้นถ้า K_d มีค่าน้อย


2-7 พฤษภาคม 2555 (การนำUNO32ควบคุมมอเตอร์1)

หากเราต้องการจะควบคุมมอเตอร์ให้หมุนได้อย่างแม่นยำเราจะใช้ encoderควบคู่กับมอเตอร์ในการระบุตำแหน่งองศาของมอเตอร์โดยนำ encoderติดที่แกนของมอเตอร์แล้วให้มอเตอร์หมุน encoderนั้นซึ่ง encoder คือ อุปกรณ์ทางไฟฟ้าชิ้นหนึ่งที่มีแกนกลางหมุนได้รอบทิศ และมีขั้วสามขั้วเหมือนตัวต้านทางปรับค่าได้สามขั้วที่ว่าจะมีvcc gnd และ voutput ซึ่งvที่outputนี้จะทำให้เรารู้ตำแหน่งองศาที่มอเตอร์หมุนไป และจะได้ควบคุมให้มอเตอร์หมุนได้ถูกตำแหน่ง โดยบอร์ดUNO 32 ก็สามารถรู้ค่าvที่outputจากการอ่านค่าanalogซึ่งใช้คำสั่ง analogRead(ขาที่จะใช้);
โดยคำสั่งนี้จะอ่านค่าanalogจากขาที่จะใช้(ดูได้จากสี่เหลี่ยมสีส้มในรูป)แล้วค่าที่อ่านได้จะมีค่าเป็นเลขจำนวนเต็มตั้งแต่ 0 - 1024 คือATODนี่เอง โดย 1024คือค่าv ref ของวงจรหลังจากนั้นเราก็แบ่ง 0 - 1024 ให้เป็น 0 - 360 องศาแล้วสามารถใช้ หลักการ PID ในการควบคุมให้มอเตอร์หมุนไปในองศาที่ต้องการ
ส่วน PID ติดตามในตอนหน้าแล้วกันครับ