วันอาทิตย์ที่ 30 กันยายน พ.ศ. 2561

งาน สอบแก้ตัว

 



Arduino UNO :  ( MCU )


ใช้ Arduino UNO ขนาด 8 บิต ATMega 328P
ควบคุมส่วนประกอบต่างๆเช่นโมดูลบลูทูธ และ รีเลย์







โมดูลบลูทูธ :  ( INPUT )


โมดูล Bluetooth ที่ใช้คือ HC-05 ดังรูปที่ด้านล่างโมดูลบลูทู ธ นี้มีขา 4
ขาสำหรับ VCC (5V), พื้นดิน, TX และ RX

โมดูลบลูทู ธ มีขา 4 ขา: VCC, TX, RX และ GND VCC และ GND เชื่อมต่อกับ 5V และใช้
Ground จาก Arduino UNO โมดูลบลูทู ธ ทำงานบน 3.3V และมีตัวควบคุม 5V ถึง 3.3V
บนเมนบอร์ด

หมุด TX และ RX ของโมดูลบลูทู ธ ต้องเชื่อมต่อกับ RX และ TX pins ของ Arduino ใน
Arduino UNO เรากำหนดขา 2 และ 4 เป็น RX และ TX โดยใช้ซอฟต์แวร์ ดังนั้น TX ของ
Bluetooth เชื่อมต่อกับขา 4 ของ Arduino

แต่เมื่อเชื่อมต่อ RX ของ Bluetooth ไปยัง TX ของ Arduino (หรือไมโครคอนโทรลเลอร์ตัวใด
ๆ อันที่จริงแล้ว) เราต้องระมัดระวังเนื่องจากขาสามารถทนต่อ 3.3V
เท่านั้น แต่แรงดันไฟฟ้าจาก TX หรือ Arduino จะเป็น 5V

ดังนั้นจึงใช้เครือข่ายเครื่องแบ่งแรงดันไฟฟ้าประกอบด้วยตัวต้านทานแบบ 10K และ 20K
เพื่อลดแรงดันไฟฟ้าลงเหลือ 3.3V







รีเลย์ : ( OUTPUT )


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

โดยทั่วไปรีเลย์ประกอบด้วยขั้ว 5 ขั้ว: ขดลวดขั้วสองขั้วขั้วสามัญ (COMM) เทอร์มินัลที่เปิดอยู่ตามปกติ (NO) และขั้วต่อปิดปกติ (NC)

สัญญาณไฟต่ำจากไมโครคอนโทรลเลอร์จะให้กับขดลวด (โดยปกติจะผ่านทรานซิสเตอร์) และอีก 3 ขั้วคือ NO, NC และ COMM จะเชื่อมต่อกับแหล่งจ่ายไฟแรงสูงพร้อมกับโหลด ข้อมูลเพิ่มเติมเกี่ยวกับการถ่ายทอดและการทำงานของตน  

 ขั้นตอนต่อไปคือการเชื่อมต่อขา I / O ดิจิตอลของ Arduino เข้ากับบอร์ดรีเลย์เชื่อมต่อกับ Pin 9, 10, 11, 12  ของ Arduino)



ซอฟต์แวร์






#include <SoftwareSerial.h>   เรียกใช้ฟังก์ชั่น Bluetooth

  const int rxPin = 4;     Rx PIN  ขา4
     const int txPin = 2;      TX PIN  ขา2        

SoftwareSerial mySerial(rxPin, txPin);       กำหนดค่าลงใน Library Bluetooth

   const int Loads[] = {9, 10, 11, 12};         กำหนด ตัวแปร รีเรย์

     int state = 0;              ตัวแปร State = 0
int flag = 0;                   ตัวแปร Flag = 0

ฟังก์ชั่น พิเศษ

##########################################################################

void setup()
                      {
           for (int i=0;i<4;i++)            ถ้า int เท่ากับ0และน้อยกว่า4 ให้ i+ไปเรื่อยๆ
    {
       pinMode(Loads[i], OUTPUT);          ให้ Load โดยเกHบค่าตัวแปรอาเรย์ i เป็น OUTPUT
    }
     mySerial.begin(9600);           แสดงผล ออกทาง Serial Moniter 9600
   for (int i=0;i<4;i++)                                     ถ้า int เท่ากับ0และน้อยกว่า4 ให้ i+ไปเรื่อยๆ
    {
            digitalWrite(Loads[i], LOW);        ให้Load iเป็นสถานะ ต่ำ
    }
 
}

void loop()
                           {
   
           if(mySerial.available() > 0)             ถ้า MySerial.available() มากกว่า 0
    {
        state = mySerial.read();             State คือ อ่านค่า
      flag=0;                                                Flag คือ 0
    }
   
      switch(state)                        การตรวจสอบตัวแปรว่ามีค่าเท่ากับ case ใด ถ้าตรง                                                                           กับ case ใดก็จะทำงาน
    {
          case '0':digitalWrite(Loads[0], HIGH);            Case 0 แสดงค่า Load อาเรย์ 0  เป็น สูง
               flag=1;                                                   flag เท่ากับ 1
                  break;                                                          หยุดการทำงาน
        case '1':digitalWrite(Loads[0], LOW);        Case1 แสดงค่า Load อาเรย์ 0  เป็น ต่ำ
               flag=1;                                                        flag เท่ากับ 1
                 break;                                                         หยุดการทำงาน
        case '2':digitalWrite(Loads[1], HIGH);          Case2 แสดงค่า Load อาเรย์ 1  เป็น สูง
               flag=1;                                                         flag เท่ากับ 1
                  break;                                                          หยุดการทำงาน
        case '3':digitalWrite(Loads[1], LOW);       Case 3 แสดงค่า Load อาเรย์ 1  เป็น ต่ำ
               flag=1;                                                         flag เท่ากับ 1
                  break;                                                          หยุดการทำงาน
         case '4':digitalWrite(Loads[2], HIGH);       Case 4 แสดงค่า Load อาเรย์ 2  เป็น สูง
               flag=1;                                                         flag เท่ากับ 1
                  break;                                                           หยุดการทำงาน
      case '5':digitalWrite(Loads[2], LOW);        Case 5 แสดงค่า Load อาเรย์ 2  เป็น ต่ำ
                 flag=1;                                                         flag เท่ากับ 1
               break;                                                           หยุดการทำงาน
      case '6':digitalWrite(Loads[3], HIGH);       Case 6 แสดงค่า Load อาเรย์ 3  เป็น สูง
               flag=1;                                                         flag เท่ากับ 1
                  break;                                                           หยุดการทำงาน
      case '7':digitalWrite(Loads[3], LOW);        Case 7 แสดงค่า Load อาเรย์ 3  เป็น ต่ำ
               flag=1;                                                          flag เท่ากับ 1
                   break;                                                            หยุดการทำงาน
        case '8':digitalWrite(Loads[0], LOW);             Case 8 แสดงค่า Load อาเรย์ 0  เป็น ต่ำ
                   digitalWrite(Loads[1], LOW);                      แสดงค่า Load อาเรย์ 1 เป็น สถานะ ต่ำ
                 digitalWrite(Loads[2], LOW);                แสดงค่า Load อาเรย์ 2 เป็น สถานะ ต่ำ
               digitalWrite(Loads[3], LOW);                      แสดงค่า Load อาเรย์ 3 เป็น สถานะ ต่ำ

                  flag=1;            flag เท่ากับ 1
               break;              หยุดการทำงาน
                                                                      }
}







Flowchart








วันเสาร์ที่ 29 กันยายน พ.ศ. 2561

งานปฏิบัติ 17






#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
int aVal=0,tempaVal=0;
const int SW_ON = 2;
const int led_ON =  13; int CSW_ON = 0; int C_CSW_ON =0;
int Relay1=12,Relay2=11,Relay3=10,Relay4=9;
int sensorPin = A0;
int sensorValue = 0;
void setup() {
  lcd.backlight();
  lcd.begin();
  Serial.begin(9600);
  pinMode(led_ON, OUTPUT);pinMode(SW_ON, INPUT);
  pinMode(Relay1,OUTPUT);pinMode(Relay2,OUTPUT);
  pinMode(Relay3,OUTPUT);pinMode(Relay4,OUTPUT);
//
  digitalWrite(Relay1,HIGH);digitalWrite(Relay2,HIGH);
  digitalWrite(Relay3,HIGH);digitalWrite(Relay4,HIGH);
  lcd.setCursor(0,0);
  lcd.print("Project2017");
  lcd.setCursor(0,1);
  lcd.print("standby");
}
//END Setup
void loop() {
  CSW_ON = digitalRead(SW_ON);
  sensorValue = analogRead(sensorPin);//Serial.println(sensorValue);
  //=======================================================================
  int c_sensorValue1 = map(sensorValue,0,1023,0,255);
  //Serial.print("c_sensorValue1 = ");Serial.println(c_sensorValue1);
  int c_sensorValue2 = map(sensorValue,0,1023,255,0);
  //Serial.print("c_sensorValue2 = ");Serial.println(c_sensorValue2);
  //=======================================================================
  //check SW_ON
  if (CSW_ON == LOW) { delay(1000);
    lcd.clear();
    C_CSW_ON++;
      Serial.print("C_CSW_ON = ");Serial.println(C_CSW_ON);
    //OPEN Project
    digitalWrite(led_ON, HIGH);
  //END check SW_ON
    if(C_CSW_ON == 1){
    lcd.setCursor(0,0);
    lcd.print("Power On ");
    delay(1000);
    lcd.clear();
    lcd.print("Power On ");
    delay(1000);
    lcd.clear();
    }
  }
  if(C_CSW_ON == 1){//OPEN PROJECT
    digitalWrite(led_ON, HIGH);
    //delay(1000);
    digitalWrite(Relay1, HIGH);
    //ตรวจสอบค่า VR================
      //lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(c_sensorValue1);
      lcd.print(" ");
      //==============================
      if(c_sensorValue1 >= 150){
      digitalWrite(Relay2, LOW);
      }else{
        digitalWrite(Relay2, HIGH);
        }
      //=============================
    //RelaySTART();
    }else{//OFF PROJECT
    lcd.setCursor(0,0);
    //lcd.print("Power Off");
    lcd.setCursor(0,1);
    lcd.print("standby");
    digitalWrite(led_ON, LOW); C_CSW_ON = 0;
    RelaySTOP();
    }
  }//END Loop
//======โปรแกรมย่อย==========
void RelaySTOP(){
digitalWrite(Relay1,HIGH);digitalWrite(Relay2,HIGH);
digitalWrite(Relay3,HIGH);digitalWrite(Relay4,HIGH);
  }
void RelaySTART(){
digitalWrite(Relay1,LOW);digitalWrite(Relay2,LOW);
digitalWrite(Relay3,LOW);digitalWrite(Relay4,LOW);
}

วันศุกร์ที่ 28 กันยายน พ.ศ. 2561

งานปฏิบัติ16


#include <Stepper.h>
#include "Keypad.h"
#define STEP_ANGLE_4STEP 32 //360/11.25 degree
#define STEP_OUT_WITH_GEAR 2048 //32*64
Stepper stepper(STEP_ANGLE_4STEP,8,10,9,11);
char keys[4][4]={
  {'7','8','9','A'},
  {'4','5','6','B'},
  {'1','2','3','C'},
  {'*','0','#','D'}};
byte rowPins[] = {7,6,5,4};
byte colPins[] = {3,2,1,0};
int speedmotor = 400;
int dirmotor = 1;
Keypad keypad = Keypad(makeKeymap(keys),rowPins,colPins,4,4);
void setup() 
{
}
void loop() 
{
  char key = keypad.getKey();
  if (key != NO_KEY)
  {
        if (key == '1')
            speedmotor = 400;
        if (key == '2')
            speedmotor = 700;
        if (key == '3')
            speedmotor = 1000;  
        if (key == 'A')
            dirmotor = 1;
        if (key == 'B')
            dirmotor = -1;     
        if (key == 'C')
            dirmotor = 0; 
  }
  stepper.setSpeed(speedmotor);
  stepper.step(dirmotor);
}

งานปฏิบัติ15






#include <LedControl.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float Tfloat;
long Tint;
LedControl lc=LedControl(8,10,9,1); 
// Pin 8->DIN, 10->CLK, 9->CS(LOAD), 1 = No.of devices
void show6digit(long num)
{
  int seg1,seg2,seg3,seg4,seg5,seg6;
  seg6 = (num/100000);
  seg5 = ((num%100000)/10000);
  seg4 = (((num%100000)%10000)/1000);
  seg3 = ((((num%100000)%10000)%1000)/100);
  seg2 = (((((num%100000)%10000)%1000)%100)/10);
  seg1 = (((((num%100000)%10000)%1000)%100)%10);
  lc.setDigit(0,0,seg1,false); 
  lc.setDigit(0,1,seg2,false); 
  lc.setDigit(0,2,seg3,false); 
  lc.setDigit(0,3,seg4,false); 
  lc.setDigit(0,4,seg5,true); 
  if (num>=100000)
      lc.setDigit(0,5,seg6,false);
  delay(300);
}
void setup(void)
{
  sensors.begin();
  lc.shutdown(0,false);  
  lc.setIntensity(0,5); 
  lc.clearDisplay(0);
} 
void loop(void)
{
  sensors.requestTemperatures(); 
  Tfloat = sensors.getTempCByIndex(0);
  Tint = long(Tfloat*10000);
  lc.clearDisplay(0);
  show6digit(Tint);
}


วันพุธที่ 26 กันยายน พ.ศ. 2561

งานปฏิบัติ 14




#include <LedControl.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float Tfloat;
long Tint;
LedControl lc=LedControl(8,10,9,1);
// Pin 8->DIN, 10->CLK, 9->CS(LOAD), 1 = No.of devices
void show6digit(int num)
{
  int seg1,seg2;
  seg2 = (((((num%100000)%10000)%1000)%100)/10);
  seg1 = (((((num%100000)%10000)%1000)%100)%10);
  lc.setDigit(0,0,seg1,false);
  if (num>=10)
      lc.setDigit(0,1,seg2,false);
  delay(300);
}
void setup(void)
{
  sensors.begin();
  lc.shutdown(0,false);
  lc.setIntensity(0,5);
  lc.clearDisplay(0);
}
void loop(void)
{
  sensors.requestTemperatures();
  Tfloat = sensors.getTempCByIndex(0);
  Tint = int(Tfloat);
  lc.clearDisplay(0);
  show6digit(Tint);
}

งานปฏิบัติ 13





#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
int PIRpin = 8;
void setup()
{
  lcd.begin();
  pinMode(PIRpin,INPUT);
  lcd.home();
  lcd.print("Waiting for PIR");
  delay(10000);      
  lcd.clear();
}
void loop()
{
  int x = digitalRead(PIRpin);
  lcd.home();
  lcd.print("PIR = ");
  lcd.print(x);
  delay(100);
}

งานปฏิบัติ 12







#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
int triggerPin = 13;
int echoPin = 12;
long duration,distCM,temp_distCM=0;
void setup()
{
  lcd.begin();
  lcd.setCursor(0,0);
  lcd.print("Dist =      cm");
  pinMode(triggerPin,OUTPUT);
  pinMode(echoPin,INPUT);
}
void loop()
{
  digitalWrite(triggerPin,LOW);
  delayMicroseconds(2);
  digitalWrite(triggerPin,HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin,LOW);
  duration = pulseIn(echoPin,HIGH);
  distCM = duration/58;
  if (temp_distCM != distCM)
  {
    lcd.setCursor(7,0);
    lcd.print("    ");
  }
  lcd.setCursor(7,0);
  lcd.print(distCM);
  temp_distCM = distCM;
  delay(300);
}

งานปฏิบัติ 11





#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
int x=48;
int y=-79;
float z=8.74586;
void setup()
{
lcd.begin();
}
void loop()
{
  lcd.setCursor(0,0);
  lcd.print("x = ");
  lcd.print(x);
  lcd.setCursor(8,0);
  lcd.print("y = ");
  lcd.print(y);
  lcd.setCursor(0,1);
  lcd.print("z = ");
  lcd.print(z,4);
}

งานปฏิบัติ 10






#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
int aVal=0,tempaVal=0;
void setup()
{
  lcd.begin();
}
void loop()
{
  aVal = analogRead(A0);

  if (tempaVal != aVal)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("LDR");
    lcd.setCursor(0,1);
    lcd.print(aVal);
    delay(300);
  }
  tempaVal = aVal;
}


งานปฏิบัติ 9






#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
void setup()
{
  lcd.backlight();
  lcd.begin();//LiquidCrystal_I2C
}
void loop()
{
  lcd.setCursor(0,0);
  lcd.print("Hello LCD I2C");
  lcd.setCursor(0,1);
  lcd.print("Pattayatech");
}

งานปฏิบัติ 8






#include "LedControl.h"
#include "Keypad.h"
#define C4  262
#define D4  294
#define E4  330
#define F4  349
#define G4  392
#define A4  440
#define B4  494
#define C5  523
char keys[4][4]={
  {7,8,9,0},
  {4,5,6,0},
  {1,2,3,0},
  {0,0,0,0}};
byte rowPins[] = {7,6,5,4};
byte colPins[] = {3,2,1,0};
Keypad keypad = Keypad(makeKeymap(keys),rowPins,colPins,4,4);
int melody[] = {C4,D4,E4,F4,G4,A4,B4,C5};
int dl = 300;
int buzzerpin = 11;
LedControl lc=LedControl(8,10,9,1);
// Pin 8->DIN, 10->CLK, 9->CS(LOAD), 1 = No.of devices
void setup()
{
  lc.shutdown(0,false);
  lc.setIntensity(0,5);
  lc.clearDisplay(0);
  pinMode(buzzerpin,OUTPUT);
  digitalWrite(buzzerpin,HIGH);
}
void loop()
{
  char key = keypad.getKey();
  if ((key != NO_KEY) && (key < 9))
  {
    lc.setDigit(0,0,key,false);
    tone(buzzerpin, melody[key-1],dl);
    delay(dl);
    digitalWrite(buzzerpin,HIGH);
  }
}

งานปฏิบัติ 7






#include "LedControl.h"
#define C4  262
#define D4  294
#define E4  330
#define F4  349
#define G4  392
#define A4  440
#define B4  494
#define C5  523
int melody[] = {C4,D4,E4,F4,G4,A4,B4,C5};
float beats[] ={1,1,1,1,1,1,1,1};
int buzzerpin = 11;
int timestop = 70;
LedControl lc=LedControl(8,10,9,1);
// Pin 8->DIN, 10->CLK, 9->CS(LOAD), 1 = No.of devices
void setup()
{
  lc.shutdown(0,false);
  lc.setIntensity(0,5);
  lc.clearDisplay(0);
  int dl = 500;
  pinMode(buzzerpin,OUTPUT);
  int numnote;
  numnote = sizeof(melody)/2;
  for (int i=0;i<numnote;i++)
  {
    lc.setChar(0,7-i,'-',false);
    tone(buzzerpin, melody[i],dl*beats[i]);
    delay(dl*beats[i]);
    digitalWrite(buzzerpin,HIGH);
    delay(timestop);
  }
}
void loop()
{
}

งานปฏิบัติ 6






#include "LedControl.h"
#include "Keypad.h"
char keys[4][4]={
  {'7','8','9','A'},
  {'4','5','6','B'},
  {'1','2','3','C'},
  {'E','0','F','D'}};
byte rowPins[] = {7,6,5,4};
byte colPins[] = {3,2,1,0};
Keypad keypad = Keypad(makeKeymap(keys),rowPins,colPins,4,4);
LedControl lc=LedControl(8,10,9,1);
// Pin 8->DIN, 10->CLK, 9->CS(LOAD), 1 = No.of devices
void setup()
{
  lc.shutdown(0,false);
  lc.setIntensity(0,5);
  lc.clearDisplay(0);    
}
void loop()
{
  char key = keypad.getKey();
  if (key != NO_KEY)
  {
    lc.setChar(0,0,key,false);
  }
}

งานปฏิบัติ 5






int led = 10;
void setup()
{
  Serial.begin(9600);
  pinMode(led,OUTPUT);    
}
void loop()
{
  int x,y;
  x = analogRead(A0);
  y = map(x,0,1023,0,255);
  Serial.print("x = ");Serial.println(x);
  Serial.print("y = ");Serial.println(y);
  analogWrite(led,y);
}

งานปฏิบัติ 4





int led = 11;
void setup()
{
  Serial.begin(9600);
  pinMode(led,OUTPUT);    
}

void loop()
{
  int x,z;
  x = analogRead(A0);
  z = map(x,0,1023,100,800);
  Serial.print("x = ");Serial.println(x);
  Serial.print("z = ");Serial.println(z);
  delay(1000);
  digitalWrite(led,HIGH);
  delay(z);
  digitalWrite(led,LOW);
  delay(z);
}

งานปฏิบัติ 3






#include "LedControl.h"
LedControl lc=LedControl(5,7,6,1);
int num = 0,seg1,seg2;
void setup()
{
  lc.shutdown(0,false);
  lc.setIntensity(0,5);
  lc.clearDisplay(0);    
}
void loop()
{
  seg1=num%10;
  seg2=num/10;
  lc.setDigit(0,0,seg1,false);
  lc.setDigit(0,1,seg2,false);
    delay(1000);
   num=num+1;
    if (num > 99)
    {
      num = 0;
    }
}

งานปฏิบัติ 2






int redPin = 11;int greenPin = 10;int bluePin = 9;

void setup()
{
    pinMode(redPin,OUTPUT);pinMode(greenPin,OUTPUT);pinMode(bluePin,OUTPUT);
}


void loop()
{
    analogWrite(redPin,255);analogWrite(greenPin,0);analogWrite(bluePin,0);
    delay(1000);
    analogWrite(redPin,0);analogWrite(greenPin,255);analogWrite(bluePin,0);
    delay(1000);
    analogWrite(redPin,0);analogWrite(greenPin,0);analogWrite(bluePin,255);
    delay(1000);
    analogWrite(redPin,255);analogWrite(greenPin,255);analogWrite(bluePin,0);
    delay(1000);
    analogWrite(redPin,255);analogWrite(greenPin,0);analogWrite(bluePin,255);
    delay(1000);
    analogWrite(redPin,0);analogWrite(greenPin,255);analogWrite(bluePin,255);
    delay(1000);
}

วันอังคารที่ 18 กันยายน พ.ศ. 2561

โปรเจครถติดตามวัตถุ (CAR TRACKING)

โปรเจครถติดตามวัตถุ (CAR TRACKING) งานที่14

โปรเจครถติดตามวัตถุ (Car Tracking)
พัฒนาโดยโมดูลกล้อง Pixy CMUcam5 และบอร์ด Arduino Mega 2560
01

         ในบทความ โปรเจครถติดตามวัตถุ (Car Tracking) พัฒนาโดยโมดูลกล้อง Pixy CMUcam5 และบอร์ด Arduino Mega 2560 นี้ วัตถุประสงค์คือการประยุกต์การใช้งานกล้อง Pixy CMUcam5 เชื่อมต่อกับไมโครคอนโทรลเลอร์เพื่อทำแอพพลิเคชั่นเป็นรถติดตามวัตถุ ศึกษาเรียนรู้การทำงานของกล้อง Pixy CMUcam5 เชื่อมต่อสื่อสารกับไมโครคอนโทรลเลอร์ โดยผู้ใช้ต้องกำหนดลักษณะสีที่ต้องการตรวจจับจากคอมพิวเตอร์ให้กับกล้องก่อน แล้วเมื่อกล้องทำงานจะส่งผลลัพธ์ไปยังไมโครคอนโทรลเลอร์เพื่อควบคุมการทำงานของมอเตอร์ที่ควบคุมการเคลื่อนที่ของรถ รวมทั้งตัวกล้องเองก็จะส่งคำสั่งไปควบคุมมอเตอร์ในการหมุนซ้าย-ขวาและปรับก้ม-เงยตัวกล้องด้วย

อุปกรณ์ที่ใช้ในบทความนี้ประกอบด้วย (คลิกที่ชื่อสินค้า เพื่อลิงค์ไปดูรายละเอียดสินค้า)
>> ราคารวมอุปกรณ์ตามรายการด้านล่างนี้ อยู่ประมาณ 6,040.15 บาท (รวม VAT) <<
(เป็นเพียงตัวอย่างการประยุกต์ใช้งาน หากลูกค้าสนใจรบกวนสั่งซื้อสินค้าแยกชิ้นนะคะ (ไม่มีจัดชุดสำเร็จรูปค่ะ))
1. Pixy CMUcam5 (EFDV347) จำนวน 1 pcs ราคา 2,850 บาท กล้องที่ใช้เป็นเซ็นเซอร์ในการทำตรวจจับและหาตำแหน่งของสีที่ต้องการเพื่อส่งข้อมูลไปสั่งงานมอเตอร์ต่อไป
022. FPV Nylon Head (EFDV341) จำนวน 1 pcs ราคา 95 บาท ขาตั้ง 2 แกน ใช้งานคู่กับ Servo 9g, 12g สามารถเคลื่อนที่ได้ทั้ง 2 แกนนำไปประยุกต์ใช้งานเป็นขาตั้งกล้อง Webcam ที่สามารถหมุนและปรับทิศทางได้
033. Tower Pro Micro Servo Motor SG90 (EFDV242) จำนวน 2 pcs ราคาต่อชิ้น 90 บาท มอเตอร์ปรับทิศทางหันกล้องใช้งานคู่กับขาตั้ง
044. Arduino Mega 2560 (EADN015) จำนวน 1 pcs ราคา 1,650 บาท โมโครคอนโทรลเลอร์ที่ใช้ในการควบมอเตอร์ขับเคลื่อนตัวรถ
055. Ardumoto Motor Driver Shield L298P (EFDV278) จำนวน 1 pcs ราคา 450 บาท Shield สำหรับขับกระแสให้มอเตอร์
066. Smart Car with Battery Case (EFDV396) ราคา 420 บาท ชุดโครงรถอะคริลิคใสพร้อมอุปกรณ์ จำนวน 1 pcs ตรงนี้ผู้ใช้สามารถทำขึ้นเองได้ ใช้มอเตอร์กระแสตรง 2 ตัว
07
         จากบทความที่แล้ว Unboxing preview Pixy CMUcam5 คือกล้องจากทาง CMUcam ที่มีการคิดค้นและพัฒนาอย่างต่อเนื่อง Pixy CMUcam5 เป็นตัวล่าสุดที่เพิ่งออกจำหน่ายเมื่อไม่นานนี้ โดยเพิ่มความสามารถในการประมวลผลภาพที่ได้เข้าไปด้วยทำให้มีความสามารถเพิ่มมากขึ้นและใช้งานง่ายขึ้น สามารถเอาผลลัพธ์ของการทำงานไปใช้ได้ทันที สิ่งที่ Pixy CMUcam5 ทำได้ก็คือ
  • การสื่อสารกับไมโครคอนโทรลเลอร์ต่างๆ ผ่านทาง UART Serial, SPI, I2C, USB, etc..
  • ตรวจจับวัตถุสีต่างๆ ได้จำนวนหลายชิ้นในเวลาเดียวกัน
  • ควบคุมการทำงานด้วย LPC4330 ARMCortex-M4 เป็น Processor หลักในการทำ Digital Signal Processing ยังสามารถควบคุม Servo ได้ในตัวด้วย
         ขั้นตอนในการเริ่มต้นใช้งานและเชื่อมต่อ Pixy CMUcam5 สามารถดูได้จากบทความที่แล้ว Unboxing preview Pixy CMUcam5 สำหรับในบทความนี้ เราจะอธิบายเริ่มต้นตั้งแต่ส่วนประกอบต่างๆบนโมดูลกล้อง, การประกอบขาตั้งกล้องที่สามารถแพนได้ และการตั้งค่า Configure ต่างๆในการใช้งานกับไมโครคอนโทรลเลอร์ Arduino Mega 2560
         ลำดับแรกในการเริ่มต้นเราจะมาทดสอบเจ้ากล้อง Pixy กันครับ ให้เราต่อกล้องเข้ากับคอมพิวเตอร์ก่อนเพื่อทำการทดสอบการทำงาน
08  09
         หลังจากนั้นทำการเปิดโปรแกรม PixyMon ที่ลงไว้ก่อนหน้านี้ขึ้นมาดังภาพด้านล่าง
10
         ให้เราเปิดภาพขึ้นมาดูก่อนโดยเลือกที่เมนู Action > Raw Video
11         หลังจากนั้นให้ทำการปรับโฟกัสที่เลนส์หน้ากล้องเพื่อใช้ในการตรวจจับวัตถุที่แม่นยำมากขึ้น
12         ลำดับต่อมาทดสอบการตรวจจับวัตถุกันเลย โดยเลือกที่ Action> Set Signature 1… กำหนดวัตถุที่ต้องการตรวจจับวัตถุที่ 1
13         หลังจากภาพหยุดนิ่ง ให้เราเลือกบริเวณสีที่เราต้องตรวจจับดังภาพด้านล่าง
14         เมื่อทำการเลือกสีที่ต้องการ กล้องจะทำการตรวจจับทันที จากภาพด้านล่างจะเห็นได้ว่ามีกอบสีขาวเมื่อตรวจพบสีที่กำหนดไว้ S=1
15         ทดสอบขยับวัตถุเพื่อตรวจสอบว่ากล้องสามารถใช้งานได้ปกติ
16         ทำการทดสอบเสร็จสิ้นถือว่ากล้องใช้งานได้ ขั้นตอนต่อมาเราจะทำการนำไปใช้กับไมโครคอนโทรลเลอร์ แต่ก่อนอื่นเราต้องทำความรู้จักกับส่วนต่างๆ ของกล้องและการประกอบขาตั้งกล้องซะก่อน
         ด้านหลังของกล้องมีส่วนที่ใช้ในการควบคุมและเชื่อมต่อไปยังอุปกรณ์อื่นๆ
1. Button คือ ปุ่มที่ใช้เลือกวัตถุที่ต้องการตรวจจับ ตามรูปแบบที่บันทึกไว้ 1-7 และเป็นปุ่มที่ใช้เริ่มและหยุดการตรวจจับอีกด้วย
2. USB คือ พอร์ตที่ใช้ในการเชื่อมต่อไปยังคอมพิวเตอร์หรืออุปกรณ์อื่นๆ เพื่อกำหนดค่าต่างๆ
3. I/O Port (UART, SPI, I2C etc.) คือ พอร์ตที่ใช้ในการเชื่อมต่อกับไมโครคอนโทรเลอร์ในรูปแบบต่างๆ สามารถดูลายละเอียดจากภาพด้านล่าง
4. RC Servo(2) คือ พอร์ตที่ใช้ในการเชื่อมต่อกับ Servo สามารถต่อได้สูงสุดถึง 2 Servo
5. Power In(6-10V) คือ พอร์ตสำหรับจ่ายไฟเลี้ยง 6-10V เราสามาใช้จ่ายไฟเลี้ยงได้หลายช่องทางทั้ง USB และ I/O Port
17 18
พอร์ตเชื่อมต่อกับ Servo สามารถเชื่อมต่อได้ถึง 2 Servo และมีฟังก์ชั่นในการควบคุมให้อีกด้วย
19
การประกอบขาตั้ง Servo อุปกรณ์ที่ใช้มีดังนี้
20
Step 1: ตัดแขนของ Servo ให้ได้ขนาดดังภาพด้านล่าง
21Step 2: เริ่มประกอบส่วนแรก ส่วนของฐานดูได้จากภาพด้านล่าง
22Step 3: ประกอบแขนของ Servo เข้ากับช่องที่กำหนดไว้ดังภาพด้านล่าง
23Step 4: ประกอบ Servo ตัวที่ 2 เข้ากับแขนที่ประกอบไว้ก่อนหน้านี้ตามภาพด้านล่าง
24Step 5: ประกอบส่วนบนสุดเข้ากับ Servo ตัวที่ 2
25Step 5.1: ประกอบส่วนบนสุดเข้ากับ Servo ตัวที่ 2 ถูกต้องจะเป็นดังภาพด้านล่าง
26
Step 6: ประกอบขาตั้งส่วนฐานล่างสุดเข้ากับแขนของ Servo
27Step 7: ประกอบขาตั้งส่วนฐานล่างสุดเข้ากับ ชุดส่วนบนที่ประกอบเสร็จแล้ว
28Step 8: ทำการตัดพลาสติกส่วนด้านบนออก พร้อมทั้งเจาะรูสำหรับยึดน็อต
29Step 9: ทำการประกอบกล้องเขากับขาตั้งดังภาพด้านล่าง
30  31
Step 10: ทำการต่อสาย Servo เข้ากับกล้อง Pixyดังนี้
  • Servo ตัวฐานต่อเข้ากับ >>> ช่อง RC-Servo PWM0
  • Servo ตัวบนต่อเข้ากับ >>> ช่อง RC-Servo PWM1
32
         ลำดับต่อมาทำการตั้งค่าเจ้า Pixy ของเราเพื่อเตรียมเชื่อมต่อเข้ากับไมโครคอนโทรลเลอร์โดยเลือกที่เมนู File > Configure…
33         จากนั้นจะเห็นหน้าต่างใหม่ที่ใช้ในการตั้งค่าส่วนต่างๆ สามารถดูลายละเอียดการตั้งค่าได้จากข้อมูลด้านล่าง
34
  • Max blocks (กำหนดจำนวนวัตถุที่ตรวจพบสูงสุดในหนึ่งเฟรม) (ต้องตั้งค่าตามความเหมาะสมขึ้นอยู่กับจำนวนวัตถุที่ต้องการตรวจจับ)
    • Sets the maximum total blocks sent per frame.
    • default: 1000
  • Max blocks per signature (กำหนดจำนวนวัตถุที่ตรวจพบสูงสุดต่อ 1 สี) (ต้องตั้งค่าตามความเหมาะสมขึ้นอยู่ดับความต้องการข้อมูล)
    • Sets the maximum blocks for each color signature sent for each frame.
    • default: 1000
  • Min block area (กำหนดขนาดของวัตถุที่ตรวจพบเล็กที่สุดและจะไม่ถูกส่งข้อมูลออก)
    • Sets the minimum required area in pixels for a block. Blocks with less area won't be sent.
    • default: 20
  • Default program (กำหนดหมายเลขโปรแกรมเมื่อทำการเปิดขึ้น)
    • Selects the program number that's run by default upon power-up.
    • default: 0
  • Brightness (กำหนดค่าความสว่าง) (ต้องตั้งค่าตามความเหมาะสมขึ้นอยู่กับสถานที่)
    • Sets the average brightness of the camera, can be between 0 and 255.
    • default: 80
35
  • Min saturation (กำหนดขั้นต่ำค่าความอิ่มตัวของสีขณะกำหนด Signatures)
    • Sets the minimum allowed color saturation for when generating color signatures. Applies during teaching.
    • default: 10.0
  • Hue spread (กำหนดการรวมตัวของจุดสี)
    • Sets how inclusive the color signatures are with respect to hue. Applies during teaching.
    • default: 1.0
  • Saturation spread (กำหนดการรวมตัวของการอิ่มตัว)
    • Sets how inclusive the color signatures are with respect to saturation. Applies during teaching.
    • default: 1.0
36
  • Data out port (กำหนดพอร์ตสำหรับใช้ในการสื่อสาร) (ต้องตั้งค่าตามความเหมาะสม)
    • Selects the port that's is used to output data. 0=SPI, 1=I2C, 2=UART, 3=analog/digital x, 4=analog/digital y
    • default: 0
  • I2C address (กำหนดหมายเลขที่อยู่สำหรับการสื่อสารรูปแบบ I2C) (ต้องตั้งค่าตามความเหมาะสม)
    • Sets the I2C address if you are using I2C data out port.
    • default: 0x54
  • UART baudrate (กำหนดความเร็วการสื่อสารในรูปแบบ UART) (ต้องตั้งค่าตามความเหมาะสม)
    • Sets the UART baudrate if you are using UART data out port.
    • default: 19200
37
  • Pan P gain , Pan D gain , Tilt P gain , Tilt D gain (กำหนดขอบเขตการเคลื่อนที่ของการแพน Servo)
         เมื่อทำการตั้งค่าส่วนต่างๆ เสร็จแล้ว (ตั้งตามค่าเดิมของโรงงานก่อน) เราต้องทำการทดสอบการประกอบกล้องกับขาตั้งนั้นใช้งานได้หรือไม่ โดยไปที่เมนู Action >Run pan/tilt demo (กำหนดสีที่ต้องการตรวจจับไว้ก่อนหน้านี้คือสีแดง)
38



         การเชื่อมต่อระหว่างไมโครคอนโทรลเลอร์และกล้อง Pixy CMUcam5 ซึ่งในบทความนี้เราจะต่อกับ Arduino Mega 2560 เป็นไมโครคอนโทรลเลอร์เบอร์ Atmel ATmega2560 จัดเป็น MCU AVR อีกหนึ่งรุ่นที่มี I/O มาให้เยอะพอสมควรสามารถต่ออุปกณ์ภายนอกได้มากขึ้น
         พอร์ตที่ใช้ในการเชื่อมต่อก็คือ I/O Port (SPI) ของกล้อง Pixy ลำดับแรกให้ทำการต่อสายที่บรรจุอยู่ภายในกล่องของ Pixy เข้ากับตัวกล้องทางพอร์ต I/O Port เชื่อมต่อไปยัง Arduino โดยการนำสายอีกฝั่งไปต่อกับกับ Arduino Mega 2560 ทางพอร์ต ICSP ดังภาพด้านล่าง
39 40
         ต่อไปให้โหลด LibraryPixyFor Arduino และแตกไฟล์ไปยังโฟล์เดอร์ libraries ของ Arduino IDE ที่ได้ทำการลงไว้ ตัวอย่างเช่น C:\Program Files (x86)\Arduino\libraries
         ตั้งค่าการเชื่อมต่อระหว่าง Arduino กับ Pixy โดยทำการเปิดโปรแกรม PixyMon > File > Configure… : Data out port= 0 (SPI) รายละเอียดการตั้งค่าสามารถดูได้จากข้อมูลด้านล่างของภาพ
41
  • 0: SPI - this is the default port that uses 3 wires (pins 1, 3, and 4 of the I/O connector) and is used to communicate with Arduino
  • 1: I2C - this is a multi-drop 2-wire port (pins 5 and 9 of the I/O connector) that allows a single master to communicate with up to 127 slaves (up to 127 Pixys).
  • 2: UART - this is the common "serial port" (pins 1 and 4 of the I/O connector). Pixy receives data via pin 1 (input) and transmits data via pin 4 (output).
  • 3: analog/digital x - this will output the x value of the largest detected object as an analog value between 0 and 3.3V      (pin 3). It also outputs whether an object is detected or not as a digital signal (pin 1 of the I/O connector).
  • 4: analog/digital y - this will output the y value of the largest detected object as an analog value between 0 and 3.3V       (pin 3). It also outputs whether an object is detected or not as a digital signal (pin 1 of the I/O connector).
         ทำการทดสอบการเชื่อมต่อระหว่าง Pixy และ Arduino โดยทำการเปิดโปรแกรม Arduino เลือกที่เมนู File > Example > Pixy > hello_world ทำการอัพโหลดไปยัง Arduino พร้อมทั้งเปิด Serial Monitor ไว้ดังภาพด้านล่าง
42
         หลังจากนั้นไปยังหน้าจอ PixyMon ทำการกำหนดสีที่ต้องการตรวจจับและเลือกที่เมนู Action > Run default program ดังภาพด้านล่าง
43         กลับไปยังหน้าต่าง Serial Monitor ของ Arduino เราจะได้ข้มูลจากกล้อง Pixy ดังภาพด้านล่างสรุปได้ว่าการเชื่อมต่อสำเร็จ
44รายละเอียดของข้อมูลที่ได้ออกมาประกอบไปด้วย
Detected 1:
block 0: sig: 1 x: 159 y: 109 width: 61 height: 61
  • Detected 1 คือ จำนวนที่ตรวจพบ จำนวน 1 กรอบ
  • block 0 คือ กรอบที่ 0
  • sig 1 คือ Signature ที่ 1
  • x คือ ตำแหน่งที่ตรวจพบในแนวแกน x
  • y คือ ตำแหน่งที่ตรวจพบในแนวแกน y
  • width คือ ความกว้างของสิ่งที่ตรวจพบ
  • height คือ ความสูงของสิ่งที่ตรวจพบ
         จากข้อมูลด้านบนเราสามารถนำข้อมูลที่ได้มานั้นมาประยุกต์ใช้งานได้ในรูปแบบอื่นๆ ได้ต่อไป ในบทความนี้เราจะนำข้อมูลไปทำการเขียนโปรแกรมควบคุมรถให้ทำการติดตามวัตถุที่เราต้องการ
เขียนโค้ดโปรแกรมดังนี้
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <SPI.h>  
#include <Pixy.h>
#define X_CENTER    160L 
#define Y_CENTER    100L
#define RCS_MIN_POS     0L
#define RCS_MAX_POS     1000L
#define RCS_CENTER_POS  ((RCS_MAX_POS-RCS_MIN_POS)/2)
  
#define Forward  1
#define Backward 0
#define MOTOR_A 0
#define MOTOR_B 1
const byte PWMA = 3;  // PWM control (speed) for motor A
const byte PWMB = 11; // PWM control (speed) for motor B
const byte DIRA = 12; // Direction control for motor A
const byte DIRB = 13; // Direction control for motor B
         ในส่วนแรกเป็นส่วนที่เราเรียกใช้ Library และกำหนดค่าเริ่มต้นต่างๆ ที่จำเป็นต้องใช้ในโปรแกรมรวมไปถึงขาที่ใช้เชื่อมต่อ โดยในที่นี้เราจะเรียกใช้ Library ด้วยกัน 2 ส่วน คือ ส่วนของ SPI และ Pixy หลังจากนั้นทำการกำหนดค่าและขาต่างๆ ที่นำไปใช้งาน
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//---------------------------------------
// Servo Loop Class
// A Proportional/Derivative feedback
// loop for pan/tilt servo tracking of
// blocks.
// (Based on Pixy CMUcam5 example code)
//---------------------------------------
class ServoLoop
{
public:
    ServoLoop(int32_t proportionalGain, int32_t derivativeGain);
  
    void update(int32_t error);
  
    int32_t m_pos;
    int32_t m_prevError;
    int32_t m_proportionalGain;
    int32_t m_derivativeGain;
};
  
// ServoLoop Constructor
ServoLoop::ServoLoop(int32_t proportionalGain, int32_t derivativeGain)
{
    m_pos = RCS_CENTER_POS;
    m_proportionalGain = proportionalGain;
    m_derivativeGain = derivativeGain;
    m_prevError = 0x80000000L;
}
  
// ServoLoop Update
// Calculates new output based on the measured
// error and the current state.
void ServoLoop::update(int32_t error)
{
    long int velocity;
    char buf[32];
    if (m_prevError!=0x80000000)
    {  
        velocity = (error*m_proportionalGain + (error - m_prevError)*m_derivativeGain)>>10;
  
        m_pos += velocity;
        if (m_pos>RCS_MAX_POS)
        {
            m_pos = RCS_MAX_POS;
        }
        else if (m_pos<RCS_MIN_POS)
        {
            m_pos = RCS_MIN_POS;
        }
    }
    m_prevError = error;
}
// End Servo Loop Class
//---------------------------------------
         ส่วนต่อมาคือส่วนที่ใช้ในการควบคุม Servo เป็นส่วนที่ใช้ในการคำณวนและควบคุมตำแหน่งของ Servo สามารถดูข้อมูลได้ที่ Example > Pixy > pantilt
?
1
2
3
4
Pixy pixy;  // Declare the camera object
  
ServoLoop panLoop(200, 200);  // Servo loop for pan
ServoLoop tiltLoop(200, 200); // Servo loop for tilt
         ในส่วนนี้เป็นประกาศชื่อ Object เข้ากับ Library และกำหนดขอบเขตการ Pan Servo
?
1
2
3
4
5
6
7
8
9
10
//---------------------------------------
// Setup - runs once at startup
//---------------------------------------
void setup()
{
    Serial.begin(9600);
    Serial.print("Starting...\n");
    pixy.init();
      setupArdumoto(); //ฟังก์ชั่นกำหนด Pin และโหมดการทำงานของ Motor
}
         ส่วนของ Setup เป็นส่วนที่ใช้ในกำหนดการทำงานต่างๆ เช่น กำหนดโหมดการทำงานให้เป็น Input/output เป็นต้น พร้อมทั้งสั่งเริ่มต้นการทำงาน
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
uint32_t lastBlockTime = 0;
//---------------------------------------
// Main loop - runs continuously after setup
//---------------------------------------
void loop()
{
    uint16_t blocks;
    blocks = pixy.getBlocks();
  
    // If we have blocks in sight, track and follow them
    if (blocks)
    {
        int trackedBlock = TrackBlock(blocks);
        FollowBlock(trackedBlock);
        lastBlockTime = millis();
    
    else if (millis() - lastBlockTime > 100)
    {
            stopArdumoto(MOTOR_A);
            stopArdumoto(MOTOR_B);
        ScanForBlocks();
    }
}
         ในส่วนของ Loop เป็นส่วนในการทำงานวนซ้ำแบบไม่รู้จบ เราเขียนโปรแกรมในส่วนที่ต้องการทำงานวนซ้ำไว้ในส่วนนี้หรือเรียกว่าส่วน Main ของโปรแกรมก็ว่าได้ จากโปรแกรมนี้จะทำการอ่านค่าจากกล้อง นำข้อมูลที่ได้ส่งไปยังฟังก์ชั่นในการติดตามวัตถุเมื่อพบสิ่งที่ต้องการ แต่ถ้าไม่พบจะทำการเรียกฟังก์ชั่น Scan หาต่อไป
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int oldX, oldY, oldSignature;
  
//---------------------------------------
// Track blocks via the Pixy pan/tilt mech
// (based in part on Pixy CMUcam5 pantilt example)
//---------------------------------------
int TrackBlock(int blockCount)
{
    int trackedBlock = 0;
    long maxSize = 0;
    Serial.print("blocks =");
    Serial.println(blockCount);
    for (int n = 0; n < blockCount; n++)
    {
        if ((oldSignature == 0) || (pixy.blocks[n].signature == oldSignature))
        {
            long newSize = pixy.blocks[n].height * pixy.blocks[n].width;
            if (newSize > maxSize)
            {
                trackedBlock = n;
                maxSize = newSize;
            }
        }
    }
    int32_t panError = X_CENTER - pixy.blocks[trackedBlock].x;
    int32_t tiltError = pixy.blocks[trackedBlock].y - Y_CENTER;
    panLoop.update(panError);
    tiltLoop.update(tiltError);
    pixy.setServos(panLoop.m_pos, tiltLoop.m_pos);
    oldX = pixy.blocks[trackedBlock].x;
    oldY = pixy.blocks[trackedBlock].y;
    oldSignature = pixy.blocks[trackedBlock].signature;
    return trackedBlock;
}
         ฟังก์ชั่นในการตรวจสอบวัตถุ เป็นฟังก์ชั่นที่รับข้อมูลมาจากฟังก์ชั่น main และนำข้อมูลที่ได้มาทำการตรวจสอบว่าข้อมูลที่ได้รับมานั้นมีอะไรบ้าง หลังจากตรวจสอบก็ทำการคำนวณและส่งข้อมูลไปยังฟังก์ชั่นในการควบคุม Servo และมอเตอร์ขับเคลื่อนต่อไป
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//---------------------------------------
// Follow blocks
// This code makes the robot base turn
// and move to follow the pan/tilt tracking
// of the head.
//---------------------------------------
int32_t size = 500;
void FollowBlock(int trackedBlock)
{
    int32_t followError = RCS_CENTER_POS - panLoop.m_pos;  // How far off-center are we looking now?
  
    // Size is the area of the object.
    // We keep a running average of the last 8.
    size += pixy.blocks[trackedBlock].width * pixy.blocks[trackedBlock].height;
    size -= size >> 3;
  
    // Forward speed decreases as we approach the object (size is larger)
    int forwardSpeed = constrain(500 - (size/256), -250, 250); 
         
    // Steering differential is proportional to the error times the forward speed
    int32_t differential = (followError + (followError * forwardSpeed))>>8;
    // Adjust the left and right speeds by the steering differential.
    int leftSpeed = constrain(forwardSpeed + differential, -250, 250);
    int rightSpeed = constrain(forwardSpeed - differential, -250, 250);
    // And set the motor speeds
        if(leftSpeed > 0)
        {
          driveArdumoto(MOTOR_A, Backward, leftSpeed);
        }
        if(rightSpeed > 0)
        {
          driveArdumoto(MOTOR_B, Backward, rightSpeed);
        }
        if(leftSpeed < 0)
        {
          driveArdumoto(MOTOR_A, Forward, (leftSpeed*-1));
        }
        if(rightSpeed < 0)
        {
          driveArdumoto(MOTOR_B, Forward, (rightSpeed*-1));
        }
}
         ฟังก์ชั่นในการติดตาม เป็นฟังก์ชั่นที่รับข้อมูลมาจากฟังก์ชั่นตรวจสอบวัตถุและนำข้อมูลที่ได้มาทำการคำนวณขนาด พร้อมทั้งเปรียบเทียบค่าต่างๆที่นำไปสั่งงานมอเตอร์หรือบอร์ดไดร์ฟเพื่อใช้งานการขับเคลื่อนรถให้ติดตามวัตถุ
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//---------------------------------------
// Random search for blocks
//
// This code pans back and forth at random
// until a block is detected
//---------------------------------------
int scanIncrement = (RCS_MAX_POS - RCS_MIN_POS) / 150;
uint32_t lastMove = 0;
  
void ScanForBlocks()
{
    if (millis() - lastMove > 20)
    {
        lastMove = millis();
        panLoop.m_pos += scanIncrement;
        if ((panLoop.m_pos >= RCS_MAX_POS)||(panLoop.m_pos <= RCS_MIN_POS))
        {
            tiltLoop.m_pos = random(RCS_MAX_POS * 0.6, RCS_MAX_POS);
            scanIncrement = -scanIncrement;
            if (scanIncrement < 0)
            {
                                driveArdumoto(MOTOR_A, Backward, 150);
                                driveArdumoto(MOTOR_B, Forward, 150);
            }
            else
            {
                                driveArdumoto(MOTOR_A, Forward, 150);
                                driveArdumoto(MOTOR_B, Backward, 150);
            }
            delay(random(250, 500));
        }
  
        pixy.setServos(panLoop.m_pos, tiltLoop.m_pos);
    }
}
         ฟังก์ชั่นในการค้นหาวัตถุ เป็นฟังก์ชั่นที่ใช้ในการสั่งงาน Servo และมอเตอร์เมื่อไม่พบวัตถุจะทำการสุ่มการเคลื่อนไหวและเคลื่อนที่เพื่อตรวจหาวัตถุที่ต้องการต่อไป
?
1
2
3
4
5
6
7
8
9
10
11
12
13
void driveArdumoto(byte motor, byte dir, byte spd)
{
  if (motor == MOTOR_A)
  {
    digitalWrite(DIRA, dir);
    analogWrite(PWMA, spd);
  }
  else if (motor == MOTOR_B)
  {
    digitalWrite(DIRB, dir);
    analogWrite(PWMB, spd);
  
}
         ฟังก์ชั่นควบคุมบอร์ดไดร์ฟหรือมอเตอร์ เป็นฟังก์ชั่นที่ใช้ในการสั่งงานและควบคุมความเร็วของมอเตอร์
?
1
2
3
4
void stopArdumoto(byte motor)
{
  driveArdumoto(motor, 0, 0);
}
         ฟังก์ชั่นที่ใช้ในการหยุดมอเตอร์
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void setupArdumoto()
{
  // All pins should be setup as outputs:
  pinMode(PWMA, OUTPUT);
  pinMode(PWMB, OUTPUT);
  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);
  // Initialize all pins as low:
  digitalWrite(PWMA, LOW);
  digitalWrite(PWMB, LOW);
  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, LOW);
}
         ฟังก์ชั่นที่ใช้ในการกำหนดขาและโหมดในการทำงานของส่วนที่ใช้ในการควบคุมมอเตอร์
วิธีการทดสอบ
ให้ทำการประกอบส่วนต่างๆเข้าด้วยกันดังนี้
1. ประกอบโครงรถ
2. นำ Shield Motor L298 ต่อเข้ากับ Arduino Mega2560 
3. ต่อมอเตอร์ล้อขวาต่อเข้ากับ Shield ทางช่อง Motor A 
4. ต่อมอเตอร์ล้อซ้ายต่อเข้ากับ Shield ทางช่อง Motor B
5. ต่อกล้อง Pixy + ขาตั้ง เข้ากับ Arduino Mega2560 ทางพอร์ต ICSP ดังภาด้านล่าง
45         จากโค้ดด้านบนเราจะเห็นได้ว่าการทำงานของโค้ดนี้คือ เมื่อทำการ Set signature ที่ต้องการตัวกล้อง Pixy นั้นจะส่งข้อมูลออกมาก็ต่อเมื่อมีการเรียกใช้ข้อมูล เมื่อได้ข้อมูลมานั้นเราต้องทำการตรวจสอบเพื่อหาขนาดและตำแหน่งของวัตถุที่พบ พร้อมทั้งสั่งงานให้ส่วนของ Servo และมอเตอร์ให้เคลื่อนที่ตามที่ได้รับข้อมูลมา 
         วิธีการทดสอบ ให้ทำการอัพโหลดโค้ดด้านบนไปยัง Arduino Mega2560 พร้อมทั้งเชื่อมต่อกล้องไปยังคอมพิวเตอร์และเปิดโปรแกรม PixyMon หลังจากนั้นทำการ Set signature และเลือกไปที่เมนู Run default program เมื่อกล้องทำงานให้ทำการถอดสายกล้องและ Arduino ออก พร้อมทั้งหาแหล่งจ่ายไฟมาจ่ายเข้ายังช่องด้านบนของ Shield ตัวรถก็พร้อมทำงาน ดูวิธีการได้จาก VDO ด้านล่าง

งานที่ 5

การบริหารงานคุณภาพเทคโนโลยีและสารสนเทศคือ   ISO 9001-2000  ในด้านคุณภาพการผลิตและบริการ ซึ่งเป็นมาตราฐานสากลที่องค์กรธุรกิจทั่วโลกให้คว...