feat: initialize PlatformIO project and implement robotic arm controller using Bluepad32 and servos

This commit is contained in:
Ümit Tunç
2026-05-23 18:27:48 +03:00
commit 2158454ba0
7 changed files with 444 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
.pio
+79
View File
@@ -0,0 +1,79 @@
# 🦾 4-Axis Robot Arm & Bluetooth Gamepad Control System
Bu proje, **ESP32** geliştirme kartı kullanarak **Gen Game New S7 Bluetooth Gamepad** ile 4 servo motorlu bir robot kolun otonom ve hassas kontrolünü sağlar.
Yazılım altyapısı kurulmuş, derlenmiş ve ESP32 kartınıza başarıyla yüklenmiştir. Projeyi hemen test etmek için aşağıdaki adımları sırasıyla uygulayabilirsiniz.
---
## 🚀 Şu Anda Yapmanız Gerekenler (Adım Adım)
### 1️⃣ Adım: Donanım Bağlantılarını Yapın (Wiring)
Servo motorların sinyal kablolarını (genellikle turuncu veya sarı) ESP32'nin aşağıdaki ilgili GPIO pinlerine bağlayın:
| Servo Motor | ESP32 GPIO Pini | Gamepad Kontrolü |
| :--- | :---: | :--- |
| **Taban (Base)** | **GPIO 13** | Sol Analog Çubuk (Sağ / Sol - X Ekseni) |
| **Omuz (Shoulder)** | **GPIO 12** | Sol Analog Çubuk (Yukarı / Aşağı - Y Ekseni) |
| **Dirsek (Elbow)** | **GPIO 14** | Sağ Analog Çubuk (Yukarı / Aşağı - Y Ekseni) |
| **Kıskaç (Gripper)**| **GPIO 27** | **A Butonu** (Aç - 180°), **B Butonu** (Kapat - 0°) |
> ⚠️ **ÖNEMLİ GÜÇ UYARISI:**
> Servo motorlar yüksek akım çeker. ESP32'nin zarar görmemesi ve servoların titrememesi (jitter) için:
> * Servoların **kırmızı (VCC)** ve **kahverengi/siyah (GND)** kablolarını harici bir **5V - 6V (en az 2A - 3A)** güç kaynağına bağlayın.
> * **ÇOK ÖNEMLİ:** Harici güç kaynağının **GND (-)** kutbunu, ESP32'nin **GND** pinine mutlaka ortaklayın (birleştirin).
---
### 2️⃣ Adım: Seri Port Monitörünü Açın
ESP32'nin durumunu izlemek ve bağlantıyı doğrulamak için PlatformIO Seri Monitörünü açın:
1. VS Code'da en alttaki mavi barda yer alan **Fiş (Serial Monitor)** ikonuna tıklayın veya terminale şu komutu yazın:
```bash
python -m platformio device monitor
```
2. Haberleşme hızı kodda **115200 baud** olarak ayarlanmıştır. Monitör açıldığında şu mesajı görmelisiniz:
```text
Sistem Baslatildi. Gamepad baglantisi bekleniyor...
```
---
### 3️⃣ Adım: Gamepad'i Eşleştirin (Pairing)
**Gen Game New S7** gamepad'inizi ESP32 ile eşleştirmek oldukça basittir. ESP32 şu an sürekli Bluetooth taraması yapmaktadır:
1. Gamepad kapalıyken, eşleştirme moduna almak için:
* **`X` + `HOME (GEN GAME)`** butonlarına aynı anda basın ve birkaç saniye basılı tutun.
* Gamepad üzerindeki LED'ler hızlıca yanıp sönmeye başlayacaktır (bu, arama modunda olduğunu gösterir).
2. ESP32, gamepad'i algıladığında otomatik olarak eşleşecek ve bağlanacaktır.
3. Bağlantı kurulduğunda:
* Gamepad'in üzerindeki LED **sabit yanmaya** başlayacaktır.
* Seri Monitör ekranında **`Gamepad Baglandi`** yazısını göreceksiniz.
---
### 4️⃣ Adım: Robot Kolu Test Edin!
Bağlantı kurulduktan sonra aşağıdaki kontrolleri kullanarak robot kolunuzu hareket ettirebilirsiniz:
* 🕹️ **Sol Çubuğu Sola/Sağa itin:** Taban motoru döner. Bıraktığınızda motor o anki açısında kalır.
* 🕹️ **Sol Çubuğu Yukarı/Aşağı itin:** Omuz motoru aşağı/yukarı hareket eder.
* 🕹️ **Sağ Çubuğu Yukarı/Aşağı itin:** Dirsek motoru aşağı/yukarı hareket eder.
* 🔴 **A Butonuna basın:** Kıskaç tamamen açılır (180 derece).
* 🟢 **B Butonuna basın:** Kıskaç tamamen kapanır (0 derece).
---
## 🛠️ Olası Sorun Giderme (Troubleshooting)
* **Servolar hiç hareket etmiyor veya titriyor:**
* Harici güç kaynağınızın gücü yetersiz olabilir veya harici güç kaynağının GND kutbu ile ESP32'nin GND pini birleştirilmemiştir. Bağlantıları kontrol edin.
* **Gamepad eşleşmiyor veya bağlanmıyor:**
* Gamepad'i kapatıp tekrar `X + HOME` kombinasyonu ile açın.
* ESP32'yi üzerindeki **EN (Reset)** butonuna basarak yeniden başlatın.
* **Hareketler çok hızlı veya çok yavaş:**
* `src/main.cpp` dosyasındaki `const float SPEED_SCALE = 0.3;` değerini değiştirerek hareket hızını hassas bir şekilde ayarlayabilirsiniz (Örn: daha yavaş ve hassas hareket için `0.1` yapın).
---
### 📂 Proje Dosyalarınızın Konumu
* 📄 **PlatformIO Yapılandırması:** [platformio.ini](file:///d:/Works/2026/robotkol/platformio.ini)
* 📄 **C++ Kod Dosyası:** [src/main.cpp](file:///d:/Works/2026/robotkol/src/main.cpp)
+37
View File
@@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
+46
View File
@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
+26
View File
@@ -0,0 +1,26 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
platform_packages =
framework-arduinoespressif32@https://github.com/maxgerhardt/pio-framework-bluepad32/archive/refs/heads/master.zip
monitor_speed = 115200
lib_deps =
madhephaestus/ESP32Servo
ricardoquesada/Bluepad32 for NINA-W10 boards
lib_ignore =
Bluepad32 for NINA-W10 boards
+218
View File
@@ -0,0 +1,218 @@
#include <Arduino.h>
#include <Bluepad32.h>
#include <ESP32Servo.h>
// Gamepad'lerin listesini tutmak için dizi (Bluepad32 birden fazla cihaz destekler)
ControllerPtr myControllers[BP32_MAX_GAMEPADS];
// Servo motor nesnelerimiz
Servo baseServo; // Taban (GPIO 13)
Servo shoulderServo; // Omuz (GPIO 12)
Servo elbowServo; // Dirsek (GPIO 14)
Servo gripperServo; // Kıskaç (GPIO 27)
// Pin tanımlamaları
const int BASE_PIN = 13;
const int SHOULDER_PIN = 12;
const int ELBOW_PIN = 14;
const int GRIPPER_PIN = 27;
// Başlangıç açıları (Genel olarak orta konumlarda başlatıyoruz)
float baseAngle = 90.0;
float shoulderAngle = 90.0;
float elbowAngle = 90.0;
float gripperAngle = 0.0; // Kıskaç kapalı veya açık başlangıç açısı
// Joystick deadzone (ölü bölge) eşiği
const int DEADZONE = 50;
// Yumuşak ve kontrollü hareket için açı değişim katsayısı (Hız)
const float SPEED_SCALE = 0.3;
// Gamepad bağlandığında tetiklenecek callback fonksiyonu
void onConnectedController(ControllerPtr ctl) {
bool foundEmptySlot = false;
for (int i = 0; i < BP32_MAX_GAMEPADS; i++) {
if (myControllers[i] == nullptr) {
myControllers[i] = ctl;
foundEmptySlot = true;
Serial.println("Gamepad Baglandi");
break;
}
}
}
// Gamepad bağlantısı koptuğunda tetiklenecek callback fonksiyonu
void onDisconnectedController(ControllerPtr ctl) {
for (int i = 0; i < BP32_MAX_GAMEPADS; i++) {
if (myControllers[i] == ctl) {
myControllers[i] = nullptr;
Serial.println("Gamepad Baglantisi Kesildi");
break;
}
}
}
// Gamepad verilerini işleyen fonksiyon
void processGamepad(ControllerPtr ctl) {
// Sol ve Sağ analog çubuk değerlerini alıyoruz
// Bu değerler tipik olarak -512 ile 512 arasındadır
int lx = ctl->axisX();
int ly = ctl->axisY();
int ry = ctl->axisRY();
// Buton basış durumlarını takip etmek için static değişkenler
static bool prevA = false;
static bool prevB = false;
static bool prevX = false;
static bool prevY = false;
static int prevLx = 0;
static int prevLy = 0;
static int prevRy = 0;
bool curA = ctl->a();
bool curB = ctl->b();
bool curX = ctl->x();
bool curY = ctl->y();
// Buton A Loglaması
if (curA != prevA) {
if (curA) {
Serial.println("[INPUT] A Butonuna Basildi -> Kiskac Aciliyor (180 derece)");
} else {
Serial.println("[INPUT] A Butonu Birakildi");
}
prevA = curA;
}
// Buton B Loglaması
if (curB != prevB) {
if (curB) {
Serial.println("[INPUT] B Butonuna Basildi -> Kiskac Kapatiliyor (0 derece)");
} else {
Serial.println("[INPUT] B Butonu Birakildi");
}
prevB = curB;
}
// Buton X Loglaması
if (curX != prevX) {
if (curX) {
Serial.println("[INPUT] X Butonuna Basildi");
} else {
Serial.println("[INPUT] X Butonu Birakildi");
}
prevX = curX;
}
// Buton Y Loglaması
if (curY != prevY) {
if (curY) {
Serial.println("[INPUT] Y Butonuna Basildi");
} else {
Serial.println("[INPUT] Y Butonu Birakildi");
}
prevY = curY;
}
// Joystick hareketlerini loglama (terminali kirletmemek icin sadece bariz degisimlerde log atar)
if (abs(lx - prevLx) > 30 || abs(ly - prevLy) > 30 || abs(ry - prevRy) > 30) {
if (abs(lx) > DEADZONE || abs(ly) > DEADZONE || abs(ry) > DEADZONE) {
Serial.printf("[JOYSTICK] lx: %d, ly: %d, ry: %d | Aci -> Taban: %.1f, Omuz: %.1f, Dirsek: %.1f\n",
lx, ly, ry, baseAngle, shoulderAngle, elbowAngle);
}
prevLx = lx;
prevLy = ly;
prevRy = ry;
}
// 1. TABAN (GPIO 13) - Sol Analog X ekseni ile kontrol edilir
if (abs(lx) > DEADZONE) {
baseAngle += (lx / 512.0) * SPEED_SCALE;
}
// 2. OMUZ (GPIO 12) - Sol Analog Y ekseni ile kontrol edilir
// Joystick'i yukarı ittiğimizde (ly negatif değer aldığında) açının artmasını istiyoruz,
// bu yüzden çıkarma işlemi yapıyoruz.
if (abs(ly) > DEADZONE) {
shoulderAngle -= (ly / 512.0) * SPEED_SCALE;
}
// 3. DİRSEK (GPIO 14) - Sağ Analog Y ekseni ile kontrol edilir
if (abs(ry) > DEADZONE) {
elbowAngle -= (ry / 512.0) * SPEED_SCALE;
}
// 4. KISKAÇ (GPIO 27) - Gamepad A ve B butonları ile kontrol edilir
// A butonu kıskaçı tamamen açsın (180 derece), B butonu tamamen kapatsın (0 derece)
if (ctl->a()) {
gripperAngle = 180.0;
} else if (ctl->b()) {
gripperAngle = 0.0;
}
// Servoların fiziksel sınırlarını (0 - 180 derece arası) constrain ile garanti altına alıyoruz
baseAngle = constrain(baseAngle, 0.0, 180.0);
shoulderAngle = constrain(shoulderAngle, 0.0, 180.0);
elbowAngle = constrain(elbowAngle, 0.0, 180.0);
gripperAngle = constrain(gripperAngle, 0.0, 180.0);
// Güncel açıları servolara yazıyoruz
baseServo.write((int)baseAngle);
shoulderServo.write((int)shoulderAngle);
elbowServo.write((int)elbowAngle);
gripperServo.write((int)gripperAngle);
}
void setup() {
// Seri haberleşmeyi başlat (115200 baud)
Serial.begin(115200);
while (!Serial) {
delay(1); // Seri portun hazır olmasını bekle
}
// ESP32'nin donanımsal PWM zamanlayıcılarını tahsis et
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
// Servoların frekansını ayarla (Standart servo motorlar 50 Hz'de çalışır)
baseServo.setPeriodHertz(50);
shoulderServo.setPeriodHertz(50);
elbowServo.setPeriodHertz(50);
gripperServo.setPeriodHertz(50);
// Servoları ilgili GPIO pinlerine ata (Standart pulse aralıkları: 500-2400 mikrosaniye)
baseServo.attach(BASE_PIN, 500, 2400);
shoulderServo.attach(SHOULDER_PIN, 500, 2400);
elbowServo.attach(ELBOW_PIN, 500, 2400);
gripperServo.attach(GRIPPER_PIN, 500, 2400);
// İlk konumlarına (başlangıç açılarına) getir
baseServo.write((int)baseAngle);
shoulderServo.write((int)shoulderAngle);
elbowServo.write((int)elbowAngle);
gripperServo.write((int)gripperAngle);
// Bluepad32 kütüphanesini başlat ve callback fonksiyonlarını bağla
BP32.setup(&onConnectedController, &onDisconnectedController);
Serial.println("Sistem Baslatildi. Gamepad baglantisi bekleniyor...");
}
void loop() {
// Bluetooth bağlantı durumunu ve gamepad verilerini günceller (Zorunlu)
BP32.update();
// Bağlı olan tüm gamepad'leri işle
for (int i = 0; i < BP32_MAX_GAMEPADS; i++) {
ControllerPtr myController = myControllers[i];
if (myController && myController->isConnected()) {
processGamepad(myController);
}
}
// Servo hareketlerinin kararlı ve yumuşak olması için küçük bir gecikme (~60Hz güncelleme hızı)
delay(15);
}
+37
View File
@@ -0,0 +1,37 @@
🦾 ROBOT KOL PROJESİ HIZLI BAŞLANGIÇ KILAVUZU
==========================================
Tebrikler! Robot kol kontrol yazılımınız başarıyla derlendi ve ESP32 kartınıza (COM3 portu üzerinden) yüklendi.
Şu anda yapmanız gereken adımlar sırasıyla şunlardır:
1. DONANIM BAĞLANTILARI (WIRING)
--------------------------------
Servo sinyal kablolarını (genellikle sarı/turuncu) ESP32'nin şu pinlerine bağlayın:
* TABAN SERVO --> GPIO 13
* OMUZ SERVO --> GPIO 12
* DİRSEK SERVO --> GPIO 14
* KISKAÇ SERVO --> GPIO 27
* ÖNEMLİ: Servolar için harici 5V-6V (en az 2A) güç kaynağı kullanın ve güç kaynağının eksisini (GND) ESP32'nin GND pini ile birleştirin.
2. GAMEPAD EŞLEŞTİRME (PAIRING)
--------------------------------
1. Gamepad kapalıyken X ve HOME (GEN GAME) butonlarına aynı anda basılı tutarak gamepad'i arama moduna alın (LED'ler hızlıca yanıp sönmelidir).
2. ESP32 otomatik olarak bağlanacaktır. Bağlantı sağlandığında gamepad LED'i sabit kalacaktır.
3. KONTROL ŞEMASI
-----------------
* SOL ANALOG (Sola/Sağa): Taban Servo (GPIO 13)
* SOL ANALOG (Yukarı/Aşağı): Omuz Servo (GPIO 12)
* SAĞ ANALOG (Yukarı/Aşağı): Dirsek Servo (GPIO 14)
* A BUTONU: Kıskaçı Aç (180 derece) (GPIO 27)
* B BUTONU: Kıskaçı Kapat (0 derece) (GPIO 27)
4. İZLEME (MONITOR)
-------------------
Seri monitörü açarak (115200 baud) bağlantı loglarını izleyebilirsiniz:
"Gamepad Baglandi" uyarısını ekranınızda göreceksiniz.
Detaylı rehber, görsel tablolar ve sorun giderme adımları için ana dizindeki README.md dosyasını inceleyebilirsiniz:
--> d:\Works\2026\robotkol\README.md