搜尋程式碼

第100課:用手勢控制舵機馬達

第100課:用手勢控制舵機馬達

想像一下,淨係揮一揮手就可以控制一個伺服摩打。呢個項目用APDS-9960手勢感測器嚟偵測手部動作(左、右、上、下、近同遠),然後將佢哋轉換成伺服摩打嘅位置。呢個係一個好玩又直觀嘅方法,可以將手勢控制加入你嘅Arduino項目。你可以用佢嚟整一個免提相機雲台、一個手勢控制嘅機械臂、一個音樂播放器嘅非接觸式音量旋鈕,或者一個會對動作有反應嘅互動藝術裝置。感測器會偵測你隻手嘅方向,然後伺服摩打就會跟住郁,同時序列監視器會即時顯示偵測到嘅手勢。

APDS-9960 gesture sensor -3
APDS-9960手勢感測器 -3

硬件組件

  • Arduino Uno(或者任何兼容嘅板)
  • APDS-9960 RGB同手勢感測器
  • 伺服摩打(例如SG90或者類似型號)
  • 杜邦線

APDS-9960感測器係一個多功能組件,可以偵測手勢、距離同環境光。你手上嘅具體板形狀或者顏色可能唔同,但底層嘅感測器同引腳功能係一樣嘅。喺呢個項目入面,我哋會集中用手勢感測功能,用I2C引腳(SDA同SCL)加中斷引腳同Arduino通訊。感測器一定要用3.3V供電,因為佢唔可以承受5V。伺服摩打係一個標準模擬伺服摩打,我哋會用一個支援PWM嘅引腳嚟控制佢。

接線指南

Arduino接線圖,用APDS9960控制伺服摩打,透過手勢操作

呢度係將APDS-9960感測器同伺服摩打連接到Arduino Uno嘅接線圖。(影片01:45位置)

APDS-9960手勢感測器接線

  • VCC → Arduino 3.3V(感測器唔可以承受5V)
  • GND → Arduino GND
  • SDA → Arduino A4(I2C數據線)
  • SCL → Arduino A5(I2C時鐘線)
  • INT → Arduino Pin 2(一定要用支援中斷嘅引腳)

伺服摩打接線

  • 訊號線(橙色或者白色線) → Arduino Pin 9(支援PWM嘅引腳)
  • 電源線(中間嗰條,通常係紅色) → Arduino 5V
  • 地線(啡色或者黑色線) → Arduino GND

好重要嘅一點係,要將感測器嘅中斷引腳連接到Arduino其中一個中斷引腳(Uno上面嘅pin 2或者pin 3)。咁樣感測器就可以喺偵測到手勢嘅時候即刻通知微控制器,而唔使成日輪詢感測器。至於伺服摩打,你要確保用一個支援PWM嘅引腳(板上會有波浪號「~」標記)。如果將伺服摩打連接到非PWM引腳,例如pin 4,佢就唔會正常運作。(影片02:14位置)

程式碼解釋

喺上載程式碼之前,你需要安裝SparkFun APDS-9960函式庫。喺Arduino IDE入面,去Sketch → Include Library → Manage Libraries,搜尋「APDS9960」,然後安裝SparkFun嘅函式庫。(影片02:38位置)

呢個項目嘅程式碼好直接。主要可以俾用家設定嘅部分係程式碼最上面嘅變數。你可以調整呢啲變數嚟改變伺服摩打嘅行為,而唔使郁其他程式碼。

int servoPin  = 9;          // 伺服摩打訊號線嘅引腳
int downAngle = 135;        // DOWN手勢嘅伺服摩打角度
int upAngle = 45;           // UP手勢嘅伺服摩打角度
int rightAngle = 0;         // RIGHT手勢嘅伺服摩打角度
int leftAngle = 180;        // LEFT手勢嘅伺服摩打角度
int angleStep = 2;          // 掃描伺服摩打時嘅步進大小
int angle = 90;             // 伺服摩打嘅初始角度

呢啲變數定義咗每個手勢對應嘅伺服摩打目標位置。例如,leftAngle設定為180度,所以當你向左揮手嗰陣,伺服摩打就會轉到180度。你可以根據自己嘅機械結構嚟改呢啲數值。angleStep變數控制當偵測到NEAR手勢時伺服摩打掃描嘅速度同平滑度;數值越細,動作就越慢越順。

APDS-9960 gesture sensor -3

nearAction()函式係一個自訂常式,會將伺服摩打由最小角度掃到最大角度,然後再掃返轉頭。當你將隻手移近感測器嗰陣就會觸發呢個函式。farAction()函式係一個預留位置,你可以喺度加入自己嘅程式碼,定義當偵測到FAR手勢嗰陣要做啲乜。

現場項目示範

一旦代碼上傳,感應器就準備好。喺示範入面,當隻手向左掃,伺服馬達會向左轉(180度);向右掃就向右轉(0度)。序列監視器會顯示偵測到嘅手勢。對於向上同向下嘅手勢,伺服馬達會移動到你定義嘅角度。NEAR手勢會觸發由0到180度再返嚟嘅掃動動作,而FAR手勢就係當你隻手移開時偵測到。系統對所有手勢都有可靠嘅反應,係開發更複雜手勢控制項目嘅好起點。(影片03:26位置)

影片章節

  • [00:00] 介紹同項目示範
  • [00:47] 硬件概覽:APDS-9960感應器同伺服馬達
  • [01:45] 感應器同伺服馬達嘅接線指南
  • [02:38] 安裝SparkFun APDS-9960函式庫
  • [03:26] 現場示範同序列監視器輸出
  • [04:27] 結語同支援

圖片

SG90 Mini Servo Motor
SG90 Mini Servo Motor
Arduino wiring of APDS9960 to control Servo motor using hand gesture
Arduino wiring of APDS9960 to control Servo motor using hand gesture
APDS-9960 gesture sensor -3
APDS-9960 gesture sensor -3
SG90 servo
SG90 servo
414-Lesson 100: Control a Servo Motor with Your Hand Gestures
語言: C++
/*
 * Arduino Step by Step Course by Robojax 
 * Lesson 100: Control Servo Motor with your hand gesture 
 * Using hand gesture RIGHT, LEFT, UP, DOWN, FAR, NEAR we control the motor in any way we want
 * video details: https://youtu.be/BUSqppjNw-Y
 * Code written based on sample from this code https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
 * on February 13, 2022 by Ahmad Shamshiri.
 * 
 * This code is part of Arduino Step by Step Course which starts here:  https://youtu.be/-6qSrDUA5a8
 * 
 * for library of this code visit http://robojax.com/
 * 
If you found this tutorial helpful, please support me so I can continue creating 
content like this. Make a donation using PayPal by credit card https://bit.ly/donate-robojax
  
 * This code is "AS IS" without warranty or liability. Free to be used as long as you keep this note intact.* 
 * This code has been downloaded from Robojax.com
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
May 30, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor

Tests the gesture sensing abilities of the APDS-9960. Configures
APDS-9960 over I2C and waits for gesture events. Calculates the
direction of the swipe (up, down, left, right) and displays it
on a serial console. 

To perform a NEAR gesture, hold your hand
far above the sensor and move it close to the sensor (within 2
inches). Hold your hand there for at least 1 second and move it
away.

To perform a FAR gesture, hold your hand within 2 inches of the
sensor for at least 1 second and then move it above (out of
range) of the sensor.

Hardware Connections:

IMPORTANT: The APDS-9960 can only accept 3.3V!
 
 Arduino Pin  APDS-9960 Board  Function
 
 3.3V         VCC              Power
 GND          GND              Ground
 A4           SDA              I2C Data
 A5           SCL              I2C Clock
 2            INT              Interrupt

Resources:
Include Wire.h and SparkFun_APDS-9960.h

This code is beerware; if you see me (or any other SparkFun 
employee) at the local, and you've found our code helpful, please
buy us a round!

Distributed as-is; no warranty is given.
****************************************************************/

#include <Wire.h>
#include <Servo.h>
#include <SparkFun_APDS9960.h>
//see details in this video: https://youtu.be/BUSqppjNw-Y
int servoPin  =9;
int downAngle =135;
int upAngle = 45;
int rightAngle = 0;
int leftAngle = 180;

int angleStep =2;
int angle =90; //initial Angle

const int minAngle = 0;
const int maxAngle = 180;
Servo myservo;  // create servo object to control a servo

// Pins
#define APDS9960_INT    2 // Needs to be an interrupt pin

// Constants

// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;

void setup() {
 myservo.attach(servoPin);  // attaches the servo on pin 9 to the servo object
  // Set interrupt pin as input
  pinMode(APDS9960_INT, INPUT);

  // Initialize Serial port
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("--------------------------------"));
  Serial.println(F("SparkFun APDS-9960 - GestureTest"));
  Serial.println(F("--------------------------------"));
  
  // Initialize interrupt service routine
  attachInterrupt(0, interruptRoutine, FALLING);

  // Initialize APDS-9960 (configure I2C and initial values)
  if ( apds.init() ) {
    Serial.println(F("APDS-9960 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during APDS-9960 init!"));
  }
  
  // Start running the APDS-9960 gesture sensor engine
  if ( apds.enableGestureSensor(true) ) {
    Serial.println(F("Gesture sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during gesture sensor init!"));
  }
}

void loop() {
  if( isr_flag == 1 ) {
    detachInterrupt(0);
    handleGesture();
    isr_flag = 0;
    attachInterrupt(0, interruptRoutine, FALLING);
  }
}

void interruptRoutine() {
  isr_flag = 1;
}

void handleGesture() {
    if ( apds.isGestureAvailable() ) {
    switch ( apds.readGesture() ) {
      case DIR_UP:
        Serial.println("UP");
        myservo.write(upAngle); 
        break;
      case DIR_DOWN:
        Serial.println("DOWN");
        myservo.write(downAngle);  
        break;
      case DIR_LEFT:
        Serial.println("LEFT");
        myservo.write(leftAngle);  
        break;
      case DIR_RIGHT:
        Serial.println("RIGHT");
        myservo.write(rightAngle);  
        break;
      case DIR_NEAR:
        Serial.println("NEAR");
        nearAction();
        break;
      case DIR_FAR:
        Serial.println("FAR");
        farAction();
        break;
      default:
        Serial.println("NONE");
    }
  }
}

void nearAction()
{

  for (angle = minAngle; angle <= maxAngle; angle += angleStep) { 
    // in steps of angleStep degree
    myservo.write(angle); 
    delay(15);                   
  }
  for (angle = maxAngle; angle >= minAngle; angle -= angleStep) { 
    myservo.write(angle);              
    delay(15);                      
  }  
}//nearAction() ends


 void farAction()
{

 //do something here
}//farAction() ends

資源與參考資料

暫時冇資源。

文件📁

其他文件