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

code โปรเจค หุ่นยนต์หลบสิ่งกีดขวาง Arduino V2


หุ่นยนต์หลบสิ่งกีดขวาง Arduino V2

โดยเราจะเอา หุ่นยนต์หลบสิ่งกีดขวาง Arduino จกา เวอร์ชั่น 1 มาปรับปรุงดังนี้

หุ่นยนต์หลบสิ่งกีดขวาง เวอร์ชั่น 1 อุปกรณ์ที่ต้องใช้ก็คือ

     1. 4WD Smart Robot Car Chassis Kits

     2. Arduino UNO R3 - Made in italy

     3. Arduino Sensor Shield V5.0

     4. เซนเซอร์ Ultrasonic Module HC-SR04

     5. Mounting Bracket for HC-SR04 Ultrasonic Module แบบสั้น

     6. Motor Drive Module L298N

     7. สาย Jumper Female to Male ยาว 20cm.

     8. สาย Jumper Femalet to Female ยาว 20cm.

     9. รางถ่านแบบ 18650 ใส่ถ่าน 2 ก้อน

     10. แบตเตอรี่ลิเธียม 18650 จำนวน 2 ก้อน

     11. เสารองแผ่นพีซีบีโลหะแบบเหลี่ยม 6 mm 12 ชิ้น

     12. สกรูหัวกลมน็อตตัวเมีย ขนาด 3มม ยาว12มม. 10 ตัว

มาปรับปรุงเป็น เวอร์ชั่น 2 ดังนี้

หุ่นยนต์หลบสิ่งกีดขวาง เวอร์ชั่น 2 อุปกรณ์ที่ต้องเพิ่มเติม จาก เวอร์ชั่น 1 ก็คือ

13. Infrared Remote Control Kit

14. Servo Motor Servo Pro SG90 หรือ เซอร์โวมอเตอร์ MG996R พร้อมกับอุปกรณ์เสริม

ถ้าเลือกใช้ Servo Motor  Pro SG90 มีอุปกรณ์เสริม คือ Mounting Bracket for Servo SG90


เริ่มด้วยแก้ไข การเชื่อมต่อ บอร์ด Motor Drive Module L298N ดังรูป
ที่ขา ENA และ ENB ไม่ต้องเชื่อมต่อใดๆ และ ให้เอา Jumper ที่ถอดออกไป ใส่คืน สภาพเดิม
หมายเหตุ : ตรวจสอบการใส่ Jumper ให้ถูกต้องตามรูปด้วย



เพิ่ม Infrared Remote Control Kit เข้าไปดังรูป



และ ทดสอบการทำงาน การต่อวงจร ตามลิงค์นี้

http://robotsiam.blogspot.com/2016/09/infrared-remote-control-kit.html

จากนั้นเพิ่ม Servo Motor  "Pro SG90" หรือ "เซอร์โวมอเตอร์ MG996R" ความแตกต่างหลักๆของ 2 ตัวนี้ คือ รุ่น MG996R  จะเป็น เฟืองโลหะ ส่วน Pro SG90 จะเป็น เฟืองพลาสติก


ประกอบเข้ากับ เซนเซอร์ Ultrasonic Module HC-SR04 ตามรูป


จากการทดสอบ เมื่อเลือกใช้ รุ่น MG996R เซอร์โวมอเตอร์จะเป็น เฟืองโลหะ ต้องต่อ แหล่งจ่ายไฟให้กับ ซัพพลาย ของ Arduino UNO R3 ดังรูปด้วย







จากนั้นทดสอบ หุ่นยนต์หลบสิ่งกีดขวาง ได้โดย  Upload โค้ดนี้ ไปยัง บอร์ด Arduino UNO R3



#include "IRremote.h"
#include <Servo.h>

//Pins for motor A 
const int MotorA1 = 6;
const int MotorA2 = 7; 
//Pins for motor B 
const int MotorB1 = 8;
const int MotorB2 = 9;
//Pins for ultrasonic sensor
const int trigger=10;
const int echo=11;

int leftscanval, centerscanval, rightscanval, ldiagonalscanval, rdiagonalscanval;
char choice;
  
//Pin for IR control
int receiver = 12; // pin 1 of IR receiver to Arduino digital pin 12
IRrecv irrecv(receiver);           // create instance of 'irrecv'
decode_results results; 
char contcommand;
int modecontrol=0;
int power=0;

const int distancelimit = 27; //Distance limit for obstacles in front           
const int sidedistancelimit = 12; //Minimum distance in cm to obstacles at both sides (the robot will allow a shorter distance sideways)

int distance;
int numcycles = 0;
char turndirection; //Gets 'l', 'r' or 'f' depending on which direction is obstacle free
const int turntime = 900; //Time the robot spends turning (miliseconds)
int thereis;
Servo head;

void setup(){
  head.attach(5);
  head.write(80);
  irrecv.enableIRIn(); // Start the IR receiver
  pinMode(MotorA1, OUTPUT); 
  pinMode(MotorA2, OUTPUT); 
  pinMode(MotorB1, OUTPUT); 
  pinMode(MotorB2, OUTPUT);
  pinMode(trigger,OUTPUT);
  pinMode(echo,INPUT);
  //Variable inicialization
  digitalWrite(MotorA1,LOW);
  digitalWrite(MotorA2,LOW);
  digitalWrite(MotorB1,LOW);
  digitalWrite(MotorB2,LOW);
  digitalWrite(trigger,LOW);
}

void go(){ 
   digitalWrite (MotorA1, HIGH);                              
   digitalWrite (MotorA2, LOW); 
   digitalWrite (MotorB1, HIGH); 
   digitalWrite (MotorB2, LOW);
}

void backwards(){
  digitalWrite (MotorA1 , LOW);                              
  digitalWrite (MotorA2, HIGH); 
  digitalWrite (MotorB1, LOW); 
  digitalWrite (MotorB2, HIGH);
}

int watch(){
  long howfar;
  digitalWrite(trigger,LOW);
  delayMicroseconds(5);                                                                              
  digitalWrite(trigger,HIGH);
  delayMicroseconds(15);
  digitalWrite(trigger,LOW);
  howfar=pulseIn(echo,HIGH);
  howfar=howfar*0.01657; //how far away is the object in cm
  return round(howfar);
}

void turnleft(int t){
  digitalWrite (MotorA1, LOW);                              
  digitalWrite (MotorA2, HIGH); 
  digitalWrite (MotorB1, HIGH); 
  digitalWrite (MotorB2, LOW);
  delay(t);
}

void turnright(int t){
  digitalWrite (MotorA1, HIGH);                              
  digitalWrite (MotorA2, LOW); 
  digitalWrite (MotorB1, LOW); 
  digitalWrite (MotorB2, HIGH);
  delay(t);
}  

void stopmove(){
  digitalWrite (MotorA1 ,LOW);                              
  digitalWrite (MotorA2, LOW); 
  digitalWrite (MotorB1, LOW); 
  digitalWrite (MotorB2, LOW);
}  

void watchsurrounding(){ //Meassures distances to the right, left, front, left diagonal, right diagonal and asign them in cm to the variables rightscanval, 
                         //leftscanval, centerscanval, ldiagonalscanval and rdiagonalscanval (there are 5 points for distance testing)
  centerscanval = watch();
  if(centerscanval<distancelimit){stopmove();}
  head.write(120);
  delay(100);
  ldiagonalscanval = watch();
  if(ldiagonalscanval<distancelimit){stopmove();}
  head.write(160); //Didn't use 180 degrees because my servo is not able to take this angle
  delay(300);
  leftscanval = watch();
  if(leftscanval<sidedistancelimit){stopmove();}
  head.write(120);
  delay(100);
  ldiagonalscanval = watch();
  if(ldiagonalscanval<distancelimit){stopmove();}
  head.write(80); //I used 80 degrees because its the central angle of my 160 degrees span (use 90 degrees if you are moving your servo through the whole 180 degrees)
  delay(100);
  centerscanval = watch();
  if(centerscanval<distancelimit){stopmove();}
  head.write(40);
  delay(100);
  rdiagonalscanval = watch();
  if(rdiagonalscanval<distancelimit){stopmove();}
  head.write(0);
  delay(100);
  rightscanval = watch();
  if(rightscanval<sidedistancelimit){stopmove();}

  head.write(80); //Finish looking around (look forward again)
  delay(300);
}

char decide(){
  watchsurrounding();
  if (leftscanval>rightscanval && leftscanval>centerscanval){
    choice = 'l';
  }
  else if (rightscanval>leftscanval && rightscanval>centerscanval){
    choice = 'r';
  }
  else{
    choice = 'f';
  }
  return choice;
}

void translateIR() { //Used when robot is switched to operate in remote control mode
  switch(results.value)
  {
  case 0xFF629D: //Case 'FORWARD'
    go();
    break;
  case 0xFF22DD: //Case 'LEFT'
    turnleft(turntime); 
    stopmove();  
    break;
  case 0xFF02FD: //Case 'OK'
    stopmove();   
    break;
  case 0xFFC23D: //Case 'RIGHT'
    turnright(turntime);
    stopmove(); 
    break;
  case 0xFFA857: //Case 'REVERSE'
    backwards();
    break;
  case 0xFF42BD:  //Case '*'
    modecontrol=0; stopmove(); // If an '*' is received, switch to automatic robot operating mode
    break;
  default: 
    ;
  }// End Case
  delay(500); // Do not get immediate repeat

void loop(){
  
  if (irrecv.decode(&results)){ //Check if the remote control is sending a signal
    if(results.value==0xFF6897){ //If an '1' is received, turn on robot
      power=1; }
    if(results.value==0xFF4AB5){ //If a '0' is received, turn off robot
      stopmove();
      power=0; }
    if(results.value==0xFF42BD){ //If an '*' is received, switch operating mode from automatic robot to remote control (press also "*" to return to automatic robot mode)
      modecontrol=1; //  Activate remote control operating mode
      stopmove(); //The robot stops and starts responding to the user's directions
    }
    irrecv.resume(); // receive the next value
  }
  
  while(modecontrol==1){ //The system gets into this loop during the remote control mode until modecontrol=0 (with '*')
    if (irrecv.decode(&results)){ //If something is being received
      translateIR();//Do something depending on the signal received
      irrecv.resume(); // receive the next value
     }
  }
  if(power==1){
  go();  // if nothing is wrong go forward using go() function above.
  ++numcycles;
  if(numcycles>130){ //Watch if something is around every 130 loops while moving forward 
    watchsurrounding();
    if(leftscanval<sidedistancelimit || ldiagonalscanval<distancelimit){
      turnright(turntime);
    }
    if(rightscanval<sidedistancelimit || rdiagonalscanval<distancelimit){
      turnleft(turntime);
    }
    numcycles=0; //Restart count of cycles
  }
  distance = watch(); // use the watch() function to see if anything is ahead (when the robot is just moving forward and not looking around it will test the distance in front)
  if (distance<distancelimit){ // The robot will just stop if it is completely sure there's an obstacle ahead (must test 25 times) (needed to ignore ultrasonic sensor's false signals)
      ++thereis;}
  if (distance>distancelimit){
      thereis=0;} //Count is restarted
  if (thereis > 25){
    stopmove(); // Since something is ahead, stop moving.
    turndirection = decide(); //Decide which direction to turn.
    switch (turndirection){
      case 'l':
        turnleft(turntime);
        break;
      case 'r':
        turnright(turntime);
        break;
      case 'f':
        ; //Do not turn if there was actually nothing ahead
        break;
    }
    thereis=0;
  }
 }
}

ทดสอบการทำงาน ที่รีโมท ด้วยการกด 0 และตามด้วย กด 1 ถ้าต่อวงจรได้ถูกต้อง หุ่นยนต์หลบสิ่งกีดขวาง Arduino เวอร์ชั่น 2 ของเราจะเริ่มทำงานครับ


วีดีโอผลลัพธ์การทำงานของ หุ่นยนต์หลบสิ่งกีดขวาง Arduino เวอร์ชั่น 2 




code โปรเจค หุ่นยนต์หลบสิ่งกีดขวาง Arduino V1


หุ่นยนต์หลบสิ่งกีดขวาง  V1

หุ่นยนต์หลบสิ่งกีดขวาง อุปกรณ์ที่ต้องใช้ก็คือ

     1. 4WD Smart Robot Car Chassis Kits

     2. Arduino UNO R3 - Made in italy

     3. Arduino Sensor Shield V5.0

     4. เซนเซอร์ Ultrasonic Module HC-SR04

     5. Mounting Bracket for HC-SR04 Ultrasonic Module แบบสั้น

     6. Motor Drive Module L298N

     7. สาย Jumper Female to Male ยาว 20cm.

     8. สาย Jumper Femalet to Female ยาว 20cm.

     9. รางถ่านแบบ 18650 ใส่ถ่าน 2 ก้อน

     10. แบตเตอรี่ลิเธียม 18650 จำนวน 2 ก้อน

     11. เสารองแผ่นพีซีบีโลหะแบบเหลี่ยม 6 mm 12 ชิ้น

     12. สกรูหัวกลมน็อตตัวเมีย ขนาด 3มม ยาว12มม. 10 ตัว

เริ่มด้วย ต่อสายไฟสำหรับมอเตอร์ ทั้ง 4 ตัว ที่ 4WD smart car chassis ให้มา โดยให้ ขั้วลบ สายไฟสีดำ อยู่ด้านบน เหมือนกันทั้ง 4 ตัว


ประกอบเข้ากับ โครง ชิ้นที่ 1 ของ 4WD smart car chassis ดังรูป



ประกอบ น็อต 6 จุด สำหรับ วาง โครง ชิ้นที่ 2


ประกอบ บอร์ด Motor Drive Module L298N ลงที่ โครง ชิ้นที่ 1


เชื่อมสายไฟ ของ มอเตอร์ ด้านบน สายสีดำ ขั้ว -  ของมอเตอร์ ตัวที่1 เข้า กับมอเตอร์ ตัวที่2 และ สายสีแดง ขั้ว+  ของมอเตอร์ ตัวที่1 เข้า กับมอเตอร์ ตัวที่2 และ เช่นกันทำที่ มอเตอร์ คู่ด้านล่างด้วย เพื่อให้เหมือนมีมอเตอร์ จาก 4 ตัว เหลือ 2 ตัว

จากนั้น ประกอบสายไฟ ของมอเตอร์ ทั้ง 2 ตัว เข้ากับ บอร์ด L298N ดังรูป



ประกอบ โครงชิ้นที่ 2 เข้าที่ ด้านบนของ โครงชิ้นที่ 1 และ ประกอบ บอร์ด Arduino UNO R3 ลงที่โครงชิ้นที่ 2 ซึ่งอยู่ชั้นบน


ประกอบ บอร์ด Arduino Sensor Shield V5.0 ลงที่ บอร์ด Arduino UNO R3



ประกอบ รางถ่านแบบ 18650 และ เชื่อมต่อ วงจรตามรูป



หมายเหตุ : ถ้ามี Jumper อยู่ที่ขา ENA และ ENB ของ บอร์ด L298N  ให้ถอดออก

การเชื่อมต่อระหว่าง บอร์ด Arduino Sensor Shield V5.0 กับ บอร์ด L298N  


.เชื่อมต่อ เซ็นเซอร์ HC-SR04 กับ Sensor Shield V5.0 ดังรูป



ประกอบ HC-SR04  เข้ากับ Mounting Bracket for HC-SR04 Ultrasonic Module แบบสั้น และ ประกอบ Bracket  เข้ากลับ โครงรถ2 ตามรูป





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

http://robotsiam.blogspot.com/2016/09/hc-sr04-sensor-shield-v50.html


หลังจากนั้นให้ทดสอบการเชื่อมต่อ ระหว่าง บอร์ด Arduino Sensor Shield V5.0 กับ บอร์ด L298N  และ การหมุนของล้อถูกต้องหรือไม่ โดย

เปิดโปรแกรม Arduino (IDE) และ Upload โค้ดนี้ ไปยัง บอร์ด Arduino UNO R3



// Motor A pins (enableA = enable motor, pinA1 = forward, pinA2 = backward)
int enableA = 3;
int pinA1 = 6;
int pinA2 = 7;

//Motor B pins (enabledB = enable motor, pinB2 = forward, pinB2 = backward)
int enableB = 5;
int pinB1 = 8;
int pinB2 = 9;

//This lets you run the loop a single time for testing
boolean run = true;

void setup() {
 pinMode(enableA, OUTPUT);
 pinMode(pinA1, OUTPUT);
 pinMode(pinA2, OUTPUT);

 pinMode(enableB, OUTPUT);
 pinMode(pinB1, OUTPUT);
 pinMode(pinB2, OUTPUT);
}
void loop() {
  if (run) {
    delay(2000);
    enableMotors();
    //Go forward
    forward(200);
    //Go backward
    backward(200);
    //Turn left
    turnLeft(400);
    coast(200);
    //Turn right
    turnRight(400);
    coast(200);
    //This stops the loop
    run = false; 
  }
}

//Define high-level H-bridge commands

void enableMotors()
{
 motorAOn();
 motorBOn();
}

void disableMotors()
{
 motorAOff();
 motorBOff();
}

void forward(int time)
{
 motorAForward();
 motorBForward();
 delay(time);
}

void backward(int time)
{
 motorABackward();
 motorBBackward();
 delay(time);
}

void turnLeft(int time)
{
 motorABackward();
 motorBForward();
 delay(time);
}

void turnRight(int time)
{
 motorAForward();
 motorBBackward();
 delay(time);
}

void coast(int time)
{
 motorACoast();
 motorBCoast();
 delay(time);
}

void brake(int time)
{
 motorABrake();
 motorBBrake();
 delay(time);
}
//Define low-level H-bridge commands

//enable motors
void motorAOn()
{
 digitalWrite(enableA, HIGH);
}

void motorBOn()
{
 digitalWrite(enableB, HIGH);
}

 //disable motors
void motorAOff()
{
 digitalWrite(enableB, LOW);
}

void motorBOff()
{
 digitalWrite(enableA, LOW);
}

 //motor A controls
void motorAForward()
{
 digitalWrite(pinA1, HIGH);
 digitalWrite(pinA2, LOW);
}

void motorABackward()
{
 digitalWrite(pinA1, LOW);
 digitalWrite(pinA2, HIGH);
}

//motor B controls
void motorBForward()
{
 digitalWrite(pinB1, HIGH);
 digitalWrite(pinB2, LOW);
}

void motorBBackward()
{
 digitalWrite(pinB1, LOW);
 digitalWrite(pinB2, HIGH);
}

//coasting and braking
void motorACoast()
{
 digitalWrite(pinA1, LOW);
 digitalWrite(pinA2, LOW);
}

void motorABrake()
{
 digitalWrite(pinA1, HIGH);
 digitalWrite(pinA2, HIGH);
}

void motorBCoast()
{
 digitalWrite(pinB1, LOW);
 digitalWrite(pinB2, LOW);
}

void motorBBrake()
{
 digitalWrite(pinB1, HIGH);
 digitalWrite(pinB2, HIGH);
}

ถอดสาย USB ระหว่าง Arduino กับ คอมพิวเตอร์ออก และ หาอุปกรณ์ที่สามารถยกตัวรถ 4WD smart car chassis ขึ้นแล้ว ล้อไม่แตะพืน เพือทดสอบการหมุนของล้อว่าถูกต้องหรือไม่



ใส่ แบตเตอรี่ลิเธียม 18650 จำนวน 2 ก้อน ไปที่ รางถ่าน และ ตรวจสอบขั้วของแบตเตอรี่ ใส่ถุกต้องหรือไม่



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

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

ทดสอบ หุ่นยนต์หลบสิ่งกีดขวาง ได้โดย  Upload โค้ดนี้ ไปยัง บอร์ด Arduino UNO R3

#include <NewPing.h>

//Tell the Arduino where the sensor is hooked up
NewPing sonar(10, 11);

int enableA = 3;
int pinA1 = 6;
int pinA2 = 7;

int enableB = 5;
int pinB1 = 8;
int pinB2 = 9;

long inches;

void setup() {
pinMode(enableA, OUTPUT);
pinMode(pinA1, OUTPUT);
pinMode(pinA2, OUTPUT);

pinMode(enableB, OUTPUT);
pinMode(pinB1, OUTPUT);
pinMode(pinB2, OUTPUT);
}

void loop() {

//Run the motors at slightly less than full power
analogWrite(enableA, 200);
analogWrite(enableB, 200);

//Ping the sensor and determine the distance in inches
inches = sonar.ping_in();

//If the robot detects an obstacle less than four inches away, it will back up, then turn left; if no obstacle is detected, it will go forward
if (inches < 4) {
analogWrite(enableA, 255);
analogWrite(enableB, 255);
backward(600);
coast(200);
turnLeft(600);
coast(200);}
else {
forward(1);

}
}

//Define high-level H-bridge commands

void enableMotors()
{
motorAOn();
motorBOn();
}

void disableMotors()
{
motorAOff();
motorBOff();
}

void forward(int time)
{
motorAForward();
motorBForward();
delay(time);
}

void backward(int time)
{
motorABackward();
motorBBackward();
delay(time);
}

void turnLeft(int time)
{
motorABackward();
motorBForward();
delay(time);
}

void turnRight(int time)
{
motorAForward();
motorBBackward();
delay(time);
}

void coast(int time)
{
motorACoast();
motorBCoast();
delay(time);
}

void brake(int time)
{
motorABrake();
motorBBrake();
delay(time);
}
//Define low-level H-bridge commands

//enable motors
void motorAOn()
{
digitalWrite(enableA, HIGH);
}

void motorBOn()
{
digitalWrite(enableB, HIGH);
}

//disable motors
void motorAOff()
{
digitalWrite(enableB, LOW);
}

void motorBOff()
{
digitalWrite(enableA, LOW);
}

//motor A controls
void motorAForward()
{
digitalWrite(pinA1, HIGH);
digitalWrite(pinA2, LOW);
}

void motorABackward()
{
digitalWrite(pinA1, LOW);
digitalWrite(pinA2, HIGH);
}

//motor B controls
void motorBForward()
{
digitalWrite(pinB1, HIGH);
digitalWrite(pinB2, LOW);
}

void motorBBackward()
{
digitalWrite(pinB1, LOW);
digitalWrite(pinB2, HIGH);
}

//coasting and braking
void motorACoast()
{
digitalWrite(pinA1, LOW);
digitalWrite(pinA2, LOW);
}

void motorABrake()
{
digitalWrite(pinA1, HIGH);
digitalWrite(pinA2, HIGH);
}

void motorBCoast()
{
digitalWrite(pinB1, LOW);
digitalWrite(pinB2, LOW);
}

void motorBBrake()
{
digitalWrite(pinB1, HIGH);
digitalWrite(pinB2, HIGH);
}


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


By : http://www.robotsiam.com/

code โปรเจครถบังคับ 2WD Arduino

โปรเจครถบังคับ ขับเคลื่อน 2 ล้อ Arduino กับ แอพแอนดรอยด์ อุปกรณ์ที่ต้องใช้ก็คือ

     1. 2WD Smart Car Robot Chassis Kits

     2. Arduino UNO R3 - Made in italy

     3. Motor Drive Module L298N

     4. HC-05 Bluetooth Master Slave

     5. สาย Jumper Female to Male ยาว 20cm.

     6. สาย Jumper Male to  Male ยาว 20cm.

     7. รางถ่านแบบ 18650 ใส่ถ่าน 3 ก้อน

     8. แบตเตอรี่ลิเธียม 18650 จำนวน 3 ก้อน

     9. เสารองแผ่นพีซีบีโลหะแบบเหลี่ยม 6 mm 12 ชิ้น

เริ่มต้นด้วยการ ประกอบ Smart Robot Car Chassis Kit 







เริ่มด้วย ต่อวงจร Arduino  UNO กับ L298N  Motor Driver ตามรูปการต่อวงวงจร




เรียนรู้เพิ่มเติมตามลิงค์นี้  http://robotsiam.blogspot.com/2016/08/l298n-motor-driver-connect-arduino-r3.html


ต่อวงจร Arduino  UNO กับ HC-05 Bluetooth ตามรูปการต่อวงวงจร



เรียนรู้เพิ่มเติมตามลิงค์นี้  http://robotsiam.blogspot.com/2016/08/hc-05-bluetooth-module.html


จะได้รูปการต่อวงจรทั้งหมดดังนี้



เปิดโปรแกรม Arduino (IDE)  เขียน โค้ด และ Upload  ไปยังบอร์ด Arduino UNO ดังนี้

#include <SoftwareSerial.h>
SoftwareSerial BTSerial(9, 10);

int dir1PinA = 2;

int dir2PinA = 3;
int speedPinA = 6;
int dir1PinB = 4;
int dir2PinB = 5;
int speedPinB = 7;

void setup() 

{   

  Serial.begin(9600);

  pinMode(dir1PinA,OUTPUT);
  pinMode(dir2PinA,OUTPUT);
  pinMode(speedPinA,OUTPUT);
  pinMode(dir1PinB,OUTPUT);
  pinMode(dir2PinB,OUTPUT);
  pinMode(speedPinB,OUTPUT);
  pinMode(8,OUTPUT);
  digitalWrite(8, HIGH);
  Serial.begin(9600);
  BTSerial.begin(9600); 
}


void loop() 

{  
  if (BTSerial.available())
    Serial.write(BTSerial.read());

  if (Serial.available())

    BTSerial.write(Serial.read());

  if (BTSerial.available() > 0) {


    int inByte = BTSerial.read();

    int speed;
    switch (inByte) {

    case 'F':


      analogWrite(speedPinA, 500);

      analogWrite(speedPinB, 500);
      digitalWrite(dir1PinA, LOW);
      digitalWrite(dir1PinB, HIGH);
      digitalWrite(dir2PinA, HIGH);
      digitalWrite(dir2PinB, LOW);
      Serial.println("Motor 1 Forward");
      Serial.println("Motor 2 Forward");
      Serial.println("   "); 

      break;




    case 'S': 


      analogWrite(speedPinA, 0);

      digitalWrite(dir1PinA, LOW);
      digitalWrite(dir2PinA, HIGH);
      Serial.println("Motor 1 Stop");
      analogWrite(speedPinB, 0);
      digitalWrite(dir1PinB, LOW);
      digitalWrite(dir2PinB, HIGH);
      Serial.println("Motor 2 Stop");
      Serial.println("   ");

      break;


    case 'B':


      analogWrite(speedPinA, 500);

      digitalWrite(dir1PinA, HIGH);
      digitalWrite(dir2PinA, LOW);
      Serial.println("Motor 1 Back");
      analogWrite(speedPinB, 500);
      digitalWrite(dir1PinB, LOW);
      digitalWrite(dir2PinB, HIGH);
      Serial.println("Motor 2 Back");
      Serial.println("   ");

      break;


    case 'L':


      analogWrite(speedPinA, 0);

      digitalWrite(dir1PinA, LOW);
      digitalWrite(dir2PinA, HIGH);
      Serial.println("Motor 1 Left");
      analogWrite(speedPinB, 500);
      digitalWrite(dir1PinB, HIGH);
      digitalWrite(dir2PinB, LOW);
      Serial.println("Motor 2 Left");
      Serial.println("   ");

      break;


    case 'R':


      analogWrite(speedPinA, 500);

      digitalWrite(dir1PinA, LOW);
      digitalWrite(dir2PinA, HIGH);
      Serial.println("Motor 1 Right");
      analogWrite(speedPinB, 0);
      digitalWrite(dir1PinB, LOW);
      digitalWrite(dir2PinB, HIGH);
      Serial.println("Motor 2 Right");
      Serial.println("   ");

      break;


    case 'I':


      analogWrite(speedPinA, 150);

      digitalWrite(dir1PinA, LOW);
      digitalWrite(dir2PinA, HIGH);
      Serial.println("Motor 1 Forward L");
      analogWrite(speedPinB, 500);
      digitalWrite(dir1PinB, HIGH);
      digitalWrite(dir2PinB, LOW);
      Serial.println("Motor 2 Forward L");
      Serial.println("   ");

      break;


    case 'G':


      analogWrite(speedPinA, 500);

      digitalWrite(dir1PinA, LOW);
      digitalWrite(dir2PinA, HIGH);
      Serial.println("Motor 1 Forward R");
      analogWrite(speedPinB, 150);
      digitalWrite(dir1PinB, HIGH);
      digitalWrite(dir2PinB, LOW);
      Serial.println("Motor 2 Forward R");
      Serial.println("   ");

      break;


    case 'J':


      analogWrite(speedPinA, 200);

      digitalWrite(dir1PinA, HIGH);
      digitalWrite(dir2PinA, LOW);
      Serial.println("Motor 1 Back L");
      analogWrite(speedPinB, 500);
      digitalWrite(dir1PinB, LOW);
      digitalWrite(dir2PinB, HIGH);
      Serial.println("Motor 2 Back L");
      Serial.println("   ");

      break;


    case 'H':


      analogWrite(speedPinA, 500);

      digitalWrite(dir1PinA, HIGH);
      digitalWrite(dir2PinA, LOW);
      Serial.println("Motor 1 Back R");
      analogWrite(speedPinB, 200);
      digitalWrite(dir1PinB, LOW);
      digitalWrite(dir2PinB, HIGH);
      Serial.println("Motor 2 Back R");
      Serial.println("   ");

      break;



    default:




      for (int thisPin = 2; thisPin < 11; thisPin++) 


      {


        digitalWrite(thisPin, LOW);


      }


    }


  }


}




เพิ่มเติมการเรียนรู้ ภาษา C

นอกจากการใช้คำสั่ง if เพื่อกำหนดเงื่อนไขเพื่อให้โปรแกรมเลือกที่จะทำงานสายงานใดแล้ว ในภาษา C ยังมีคำสั่ง switch อีกคำสั่งหนึ่ง เพื่ออำนวยความสะดวกแก่ผู้เขียนโปรแกรม ในการที่นำมาใช้แทนคำสั่ง if ที่ซ้อนกันหลาย ๆ ชั้น โดยที่คำสั่ง switch จะนำค่าของตัวแปรที่อยู่หลังคำสั่ง switch มาเปรียบเทียบกับค่าที่อยู่หลัง case แต่ละคำสั่ง ถ้าตรงกัน ก็จะทำสายงานที่อยู่ใน case นั้น ๆ แต่ถ้าไม่ตรงกับ case ใด ๆ เลย จะทำหลังคำสั่ง default โดยมีรูปแบบประโยคคำสั่งดังนี้


ประโยค switch หนึ่งประโยคจะมีกี่ case ก็ได้ หรือไม่มีเลยก็ได้ และอาจมี default เป็นตัวเลือกเสริม

 ประโยคคำสั่ง break 

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


 switch (inByte) {

    case 'F':

      analogWrite(speedPinA, 500);
      analogWrite(speedPinB, 500);
      digitalWrite(dir1PinA, LOW);
      digitalWrite(dir1PinB, HIGH);
      digitalWrite(dir2PinA, HIGH);
      digitalWrite(dir2PinB, LOW);
      Serial.println("Motor 1 Forward");
      Serial.println("Motor 2 Forward");
      Serial.println("   "); 

      break;

  case 'H':

      analogWrite(speedPinA, 500);
      digitalWrite(dir1PinA, HIGH);
      digitalWrite(dir2PinA, LOW);
      Serial.println("Motor 1 Back R");
      analogWrite(speedPinB, 200);
      digitalWrite(dir1PinB, LOW);
      digitalWrite(dir2PinB, HIGH);
      Serial.println("Motor 2 Back R");
      Serial.println("   ");

      break;


    default:

 การนำคำสั่ง break มาซ้อนไว้ใน case ต่าง ๆ ของคำสั่ง switch จะช่วยให้โปรแกรมไม่ล่วงล้ำเข้าไปทำใน case ที่อยู่ถัดไป แต่ถ้าไม่มีประโยคคำสั่ง break เมื่อทำ case ใด ๆ เสร็จเรียบร้อยแล้ว คอมไพล์เลอร์ก็จะให้ไปทำใน case ที่อยู่ถัดไปเรื่อย ๆ จนกว่าจะจบบล๊อกของประโยคคำสั่ง switch จากนั้นจะทำงานต่อไป ในประโยคคำสั่งที่อยู่ถัดไป

ทำการประกอบ บร์อด เชื่อมต่อสาย ต่างๆ ลงไปใน Smart Robot Car Chassis Kit ที่ประกอบเสร็จแล้ว  ต่อสาย ใส่แบตเตอรี่ ตามรางถ่านที่ชุด Kit ให้มา คือ ขนาด AA แรงดันไฟเฉลี่ย 1.5V (2800 mAh) จำนวน 4 ก้อน จะได้แรงดันไฟ 6 โวลต์  โดยต่อเข้าที่ พอร์ต Power Supply ของ บอร์ด Arduino  UNO R3 ได้ตามรูป

รถสามารถวิ่งได้ แต่ทำความเร็วได้ไม่ดีเท่าที่ควร (ช้ามาก) และทดลองนำไฟ 6 โวลต์ ต่อกับ บร์อด L298N  Motor Driver โดยตรง มอเตอร์ก็ไม่สามารถหมุนได้




จึง ปรับปรุง เปลี่ยนแบตเตอรี่ เป็น แบตเตอรี่ลิเธียม 18650 (ขนาดใหญ่กว่า แบตเตอรี่ ขนาด AA ปรกติ) แรงดันไฟเฉลี่ย 3.7V  (3400 mAh)  จำนวน 3 ก้อน ได้ไฟรวมประมาณ 11.1 โวลต์  และ ก็ต้องเปลี่ยน รางถ่าน เป็นแบบ 18650 ใส่ถ่านได้ 3 ก้อน แบบวงจรอนุกรม ด้วย

V คือ Volt (โวลต์)  
เป็นค่าความต่างศักดิ์ไฟฟ้า คล้ายๆแรงดันไฟ นึกภาพถึง แรงดันน้ำ แรงดันลม ความดันเลือด (เป็นแรงดันไฟ หรือ แรงดันไฟฟ้า)

mAh คือ m = มิลลิ , A = แอมป์ , h = ชั่วโมง หมายถึง ถ่านก้อนนี้สามารถจ่ายกระแสได้ กี่มิลิแอมป์ ใน 1 ชั่วโมง (เป็นความจุไฟ หรือ กระแสไฟฟ้า)

รุูจัก : Li-ion (ลิเธี่ยมไอออน) และ Li-Mn (ลิเธี่ยมแมงกานีส หรือเรียกอีกอย่างว่า High Drain) ขนาดของตัวจะมาเป็นรหัสครับเช่น 18650 ข้อดี คือ สามารถชาร์จได้ แต่ ไม่ควรใช้จนไฟหมดหรือแรงดันต่ำกว่าที่กำหนดเอาไว้เพราะจะทำให้เซลล์แบตฯ เสียหายไม่สามารถนำมาใช้ได้อีก

รถบังคับสามารถ วิ่งทำความเร็วได้เพิ่มมากขึ้น แต่ก็ยังเร็วไม่เท่าที่ควร และ บร์อด Arduino  UNO R3 จะรับไฟมากเกินไปด้วย ซึ่งปรกติจะใช้เพียง  5 โวลต์ เท่านั้น





จึง ทดลองแก้ไขการต่อ แบตเตอรี่  นำไฟจากแบตเตอรี่ลิเธียม 18650 ไปต่อตรงกับ L298N  Motor Driver (ไม่ต่อกับ พอร์ต Power Supply ของ บอร์ด Arduino  UNO R3  ) และ นำไฟ 5 โวลต์ ที่ออกจาก L298N ต่อออกไปเลี้ยง บอร์ด Arduino  UNO R3 ตามรูปการต่อวงวงจร



 


รถบังคับสามารถ วิ่งทำความเร็วได้ดีทีขึ้น แรงขึ้นมาก ถึงมากที่สุด ซึ่งน่าจะเป็นเพราะ แรงดัน และ กระแสไฟฟ้า ที่เพิ่มมากขึ้นนั่นเอง

จากนั้น ทดลองนำ โทรศัพท์มือถือ แอนดรอยด์  เปิด บลูทูธ  แล้ว ดาวน์โหลดและติดตั้ง โปรแกรม Arduino Bluetooth RC Car ดังนี้






สังเกตุ เมื่อเปิดขึ้นมา รูปวงกลมซ้ายมือ จะเป็นสีแดง



คลิกที่ ไอคอนเฟือง ขวามือสุด แล้ว เลือก Connect to car




เลือก HC-05




สังเกตุ รูปวงกลมซ้ายมือเป็นสีเขียวแสดงว่า โปรแกรมสามารถใช้งานได้แล้ว ทดลองควบคุมดูเลยครับ




วีดีโอผลลัพธ์การทำงานของ โปรเจครถบังคับ ขับเคลื่อน 2 ล้อ Arduino กับ แอพแอนดรอยด์



By : http://www.robotsiam.com/

Code โปรเจค Arduino เปิดปิดไฟ ด้วย Wireless Joystick

PS2 Joystick Playstation Adapter for Arduino อะแดปเตอร์แปลงหัว PS2 เป็นขาต่อแบบ DIP สำหรับ Arduino คอนเนคเตอร์สำหรับแปลงจาก PS2 เป็นขา DI...