Algoritma untuk mencampur input analog 2 sumbu untuk mengendalikan drive motor diferensial

9

Saya mencari informasi tentang bagaimana menerapkan pencampuran yang tepat dari 2 sinyal joystick analog (sumbu X dan Y) untuk mengontrol drive motor diferensial ganda (drive "tank like") menggunakan uC (ATMega328p dalam kasus saya, tetapi hal yang sama berlaku untuk setiap UC dengan input ADC dan output PWM):

Saya memiliki stik analog, yang memberikan 2 nilai analog:

(arah) X: 0 hingga 1023
(throttle) Y: 0 hingga 1023

masukkan deskripsi gambar di sini

Posisi istirahat adalah (arah dan throttle netral) 512,512
Throttle maju / arah kiri adalah 0,0
Penuh ke depan-kanan penuh adalah 1023,0
dll.

Motor dikontrol oleh 2 driver H-bridge, 2 pin PWM untuk masing-masing (Maju, mundur), seperti:
Kiri Motor: -255 ke 255
Motor Kanan: -255 hingga 255
(nilai positif memungkinkan pin PWM maju, negatif memungkinkan mundur Pin PWM, 0 menonaktifkan keduanya)

Tujuannya adalah untuk mencampur sinyal analog joystick untuk mencapai respons berikut:

a) Throttle maju, arah netral = kendaraan bergerak maju
b) Throttle maju, arah kiri = kendaraan bergerak maju dan belok kiri
c) Throttle netral, arah kiri = kendaraan belok kiri DI TEMPAT yaitu motor kanan maju penuh, motor kiri mundur penuh

... dan juga untuk kombinasi lainnya. Tentu saja, outputnya harus "analog" yaitu, ia harus memungkinkan transisi bertahap dari misalnya dari opsi a) ke b) ke c).

Konsepnya adalah:

http://www.lynxmotion.com/images/html/build123.htm

Kamil Zadora
sumber
(1) Perhatikan bahwa algoritma dasar saya memungkinkan kontrol kecepatan 'giliran di tempat' ketika joystick didorong misalnya ditinggalkan oleh% dari skala penuh. (2) Persyaratan ini pasti telah dipecahkan berkali-kali sekarang. Komunitas model harus memiliki jawaban untuk ini. (3) Jika penerima menerjemahkan perintah ke dalam kecepatan lintasan menggunakan umpan balik, kendaraan akan berperilaku sama seperti kondisi tanah berubah. TETAPI jika perintah diterjemahkan ke dalam daya motor atau tegangan penggerak, dll. Performa kendaraan akan bervariasi sesuai kondisi tanah. - mungkin 91) lebih disukai.
Russell McMahon
Russell, saya banyak googled untuk anwser dan saya telah menemukan banyak pengendali motor yang siap untuk terhubung langsung ke penerima RC tetapi tidak banyak informasi tentang algoritma di dalamnya.
Kamil Zadora
Selamat siang! renho sepupu yang telah mencoba kelumpuhan kekanak-kanakan dan pembangunan kursi roda pemrograman mereka bekerja dengan baik, tetapi tegangan output terlalu rendah! tolong aku! Saya menggunakan arduino uno.
@Johnny selamat datang di Electronics.Stackexchange! Silakan lihat FAQ untuk memahami cara kerja situs ini, dan jika Anda memiliki pertanyaan untuk ditanyakan, gunakan tombol spesifik di sudut kanan atas halaman.
clabacchio
Apa itu bekerja ???
Russell McMahon

Jawaban:

4

Pencampuran "Proper" terbuka untuk diperdebatkan :-).

Masalahnya adalah Anda harus membuat keputusan tentang seberapa cepat trek bergerak di bawah sinyal murni dari pot tunggal dan apa yang harus dilakukan ketika sinyal dari pot lain dimasukkan. Misalnya, jika Anda mendorong pot FB (Maju-Mundur ke depan sepenuhnya ke depan, dan jika kedua motor kemudian berlari dengan kecepatan penuh di depan, bagaimana Anda menangani penambahan sejumlah kecil pot LR (Kiri-Kanan) yang ditambahkan. dapatkan rotasi, Anda harus memiliki satu trek lebih cepat dari yang lain. Jadi, jika Anda sudah berjalan pada kecepatan maju maksimum pada kedua motor Anda harus mengurangi satu atau kecepatan trek lain untuk berputar. Tapi, jika Anda telah berdiri diam Anda akan mempercepat satu atau trek lain untuk mencapai hasil yang sama.

Jadi, semua yang dikatakan, inilah solusi awal yang sederhana dari kepala saya yang sepertinya merupakan awal yang baik.

Jika pot independen secara mekanis maka keduanya dapat 100% secara bersamaan.
Jika keduanya pada pengaturan jenis joystick, jika Yaxis = 100% dan Xaxis = 0%, maka menambahkan beberapa B biasanya akan mengurangi A. Joystick dapat dibangun di mana hal di atas tidak benar, tetapi ini tidak biasa.
Asumsikan bahwa joystick adalah tipe yang meningkatkan Y% ketika X = 100% akan mengurangi X. Asumsi lain dapat dibuat.

FB = pot depan-belakang. Pusat nol, + Ve untuk gerakan maju pot

LR = Pot kanan kiri. Center nol. + Ve untuk pot di sebelah kanan.

K adalah faktor skala awalnya 1.
Jika ada hasil melebihi 100% maka sesuaikan K sehingga hasilnya = 100% dan menggunakan nilai K yang sama untuk motor lain juga.

  • misal jika hasil motor kiri = 125 dan hasil motor kanan = 80 maka.
    Karena 125 x 0,8 = 100, atur K = 0,8. Kemudian.
    Kiri = 125 x 0,8 = 100%. Kanan = 80 x 0,8 = 64%.

Kemudian:

  • Motor kiri = K x (Front_Back + Left_Right)

  • Motor kanan = K x (Front_Back - Kiri_Right)

Cek kesehatan:

  • LR = 0 (tengah), FB = fwd penuh -> Kedua motor berjalan penuh ke depan.

  • LR = kiri penuh, FB = 0 ->
    Motor kiri berjalan penuh mundur,
    Motor kanan berjalan penuh ke depan.
    Kendaraan berputar berlawanan arah jarum jam.

  • FB adalah 100%, Lr = 0%. Tambahkan 10% LR ke kanan.
    L = FB + LR = 100% - + 10% R = FB-LR = 100% - - 10%

Jika sumbu terbesar <100%, skala hingga = 100%.
Kemudian skala sumbu lainnya dengan jumlah yang sama.

Russell McMahon
sumber
Terima kasih Russell - Saya akan mencoba menerapkan ini pada pengaturan model saya. BTW, Joystick saya dapat tetap maju penuh sementara menggesernya dari kiri ke kanan dan sebaliknya, sangat mirip dengan ini: static.sparkfun.com/images/products/09032-03-L_i_ma.jpg
Kamil Zadora
1
Saat ini saya bertugas menyelesaikan masalah yang sama di tempat kerja. Saya punya wii nunchuk 2-axis controller, dan perlu mengendalikan 2 motor persis seperti yang dijelaskan dalam pertanyaan. Saya mengalami sedikit kesulitan memahami logika di sini. Apa sebenarnya yang dimaksud dengan k1 / K1? Satu huruf kecil dan satu huruf besar - apakah mereka berbeda? Apa itu + Ve?
Tal
1
Keren - terima kasih atas klarifikasi. Saya membutuhkan ini ditulis dengan Python, jadi jika saya mengerti dengan benar, ini harus dilakukan: pastebin.com/sWDakvLp . Apakah sepertinya saya kehilangan sesuatu? Tampaknya bekerja di lingkungan pengujian saya - saya harus benar-benar menghubungkannya ke motor akhir yang akan saya gunakan untuk mengetahui dengan pasti.
Tal
1
1) Kecepatan motor dikendalikan oleh PWM, yang hanya mengambil nilai dari 0 - 100, itulah sebabnya saya menggunakan 100 sebagai nilai maksimal. 2) Saya menggunakan abs untuk menemukan apakah penskalaan diperlukan (seperti yang Anda katakan) dan untuk mendapatkan scale_factor. Jika saya berakhir dengan faktor skala 0,8 misalnya, dan menggunakannya pada angka negatif, -125 * 0,8 = -100. Arah dipertahankan. Saya pikir itu berhasil, kecuali saya kehilangan sesuatu. Saya masih belum memiliki kesempatan untuk mencobanya pada motor terakhir - bos saya akan membangun platform uji dengan motor terpasang yang saya akan dapat mengujinya.
Tal
1
Saya tidak yakin apakah kode saya benar-benar berfungsi, jadi saya mengatur tautan pastebin sebelumnya agar berakhir setelah seminggu. Karena tampaknya berfungsi, inilah tautan yang lebih permanen dengan beberapa komentar lagi jika ada yang menemukan masalah lagi: pastebin.com/EKguJ1KP . Saya telah memasukkan ini ke dalam jawaban, tetapi ternyata saya tidak memiliki cukup perwakilan untuk mengirim jawaban. Semua kode didasarkan pada jawaban Russel McMahon - kredit diberikan kepadanya - terima kasih Russel.
Tal
5

Inilah solusi yang tidak memerlukan rumit jika / selain itu rantai, tidak mengurangi daya saat bergerak penuh ke depan atau berputar di tempat, dan memungkinkan kurva dan transisi yang mulus dari pindah ke berputar.

Idenya sederhana. Asumsikan nilai joystick (x, y) adalah koordinat kartesius pada bidang persegi. Sekarang bayangkan sebuah pesawat persegi yang lebih kecil diputar 45º di dalamnya.

contoh pesawat

Koordinat joystick memberi Anda titik di kotak yang lebih besar, dan titik yang sama ditumpangkan di kotak yang lebih kecil memberi Anda nilai motorik. Anda hanya perlu mengubah koordinat dari satu kotak ke kotak lainnya, membatasi nilai (x, y) yang baru ke sisi kotak yang lebih kecil.

Ada banyak cara untuk melakukan konversi. Metode favorit saya adalah:

  1. Ubah koordinat awal (x, y) menjadi koordinat kutub.
  2. Putar 45 derajat.
  3. Ubah koordinat kutub kembali ke cartesian.
  4. Ubah skala koordinat baru menjadi -1.0 / + 1.0.
  5. Jepit nilai baru ke -1.0 / + 1.0.

Ini mengasumsikan koordinat awal (x, y) berada dalam kisaran -1.0 / + 1.0. Sisi dari kotak bagian dalam akan selalu sama dengan l * sqrt(2)/2, jadi langkah 4 hanya tentang mengalikan nilai dengan sqrt(2).

Berikut ini contoh implementasi Python.

import math

def steering(x, y):
    # convert to polar
    r = math.hypot(x, y)
    t = math.atan2(y, x)

    # rotate by 45 degrees
    t += math.pi / 4

    # back to cartesian
    left = r * math.cos(t)
    right = r * math.sin(t)

    # rescale the new coords
    left = left * math.sqrt(2)
    right = right * math.sqrt(2)

    # clamp to -1/+1
    left = max(-1, min(left, 1))
    right = max(-1, min(right, 1))

    return left, right

Ide asli untuk metode ini - dengan metode transformasi yang jauh lebih rumit - berasal dari artikel ini .

Pedro Werneck
sumber
0

Di bawah ini adalah contoh implementasi algoritma pencampuran seperti yang dijelaskan oleh Russel McMahon jawaban:

http://www.youtube.com/watch?v=sGpgWDIVsoE

//Atmega328p based Arduino code (should work withouth modifications with Atmega168/88), tested on RBBB Arduino clone by Modern Device:
const byte joysticYA = A0; //Analog Jostick Y axis
const byte joysticXA = A1; //Analog Jostick X axis

const byte controllerFA = 10; //PWM FORWARD PIN for OSMC Controller A (left motor)
const byte controllerRA = 9;  //PWM REVERSE PIN for OSMC Controller A (left motor)
const byte controllerFB = 6;  //PWM FORWARD PIN for OSMC Controller B (right motor)
const byte controllerRB = 5;  //PWM REVERSE PIN for OSMC Controller B (right motor)
const byte disablePin = 2; //OSMC disable, pull LOW to enable motor controller

int analogTmp = 0; //temporary variable to store 
int throttle, direction = 0; //throttle (Y axis) and direction (X axis) 

int leftMotor,leftMotorScaled = 0; //left Motor helper variables
float leftMotorScale = 0;

int rightMotor,rightMotorScaled = 0; //right Motor helper variables
float rightMotorScale = 0;

float maxMotorScale = 0; //holds the mixed output scaling factor

int deadZone = 10; //jostick dead zone 

void setup()  { 

  //initialization of pins  
  Serial.begin(19200);
  pinMode(controllerFA, OUTPUT);
  pinMode(controllerRA, OUTPUT);
  pinMode(controllerFB, OUTPUT);
  pinMode(controllerRB, OUTPUT);  

  pinMode(disablePin, OUTPUT);
  digitalWrite(disablePin, LOW);
} 

void loop()  { 
  //aquire the analog input for Y  and rescale the 0..1023 range to -255..255 range
  analogTmp = analogRead(joysticYA);
  throttle = (512-analogTmp)/2;

  delayMicroseconds(100);
  //...and  the same for X axis
  analogTmp = analogRead(joysticXA);
  direction = -(512-analogTmp)/2;

  //mix throttle and direction
  leftMotor = throttle+direction;
  rightMotor = throttle-direction;

  //print the initial mix results
  Serial.print("LIN:"); Serial.print( leftMotor, DEC);
  Serial.print(", RIN:"); Serial.print( rightMotor, DEC);

  //calculate the scale of the results in comparision base 8 bit PWM resolution
  leftMotorScale =  leftMotor/255.0;
  leftMotorScale = abs(leftMotorScale);
  rightMotorScale =  rightMotor/255.0;
  rightMotorScale = abs(rightMotorScale);

  Serial.print("| LSCALE:"); Serial.print( leftMotorScale,2);
  Serial.print(", RSCALE:"); Serial.print( rightMotorScale,2);

  //choose the max scale value if it is above 1
  maxMotorScale = max(leftMotorScale,rightMotorScale);
  maxMotorScale = max(1,maxMotorScale);

  //and apply it to the mixed values
  leftMotorScaled = constrain(leftMotor/maxMotorScale,-255,255);
  rightMotorScaled = constrain(rightMotor/maxMotorScale,-255,255);

  Serial.print("| LOUT:"); Serial.print( leftMotorScaled);
  Serial.print(", ROUT:"); Serial.print( rightMotorScaled);

  Serial.print(" |");

  //apply the results to appropriate uC PWM outputs for the LEFT motor:
  if(abs(leftMotorScaled)>deadZone)
  {

    if (leftMotorScaled > 0)
    {
      Serial.print("F");
      Serial.print(abs(leftMotorScaled),DEC);

      analogWrite(controllerRA,0);
      analogWrite(controllerFA,abs(leftMotorScaled));            
    }
    else 
    {
      Serial.print("R");
      Serial.print(abs(leftMotorScaled),DEC);

      analogWrite(controllerFA,0);
      analogWrite(controllerRA,abs(leftMotorScaled));  
    }
  }  
  else 
  {
  Serial.print("IDLE");
  analogWrite(controllerFA,0);
  analogWrite(controllerRA,0);
  } 

  //apply the results to appropriate uC PWM outputs for the RIGHT motor:  
  if(abs(rightMotorScaled)>deadZone)
  {

    if (rightMotorScaled > 0)
    {
      Serial.print("F");
      Serial.print(abs(rightMotorScaled),DEC);

      analogWrite(controllerRB,0);
      analogWrite(controllerFB,abs(rightMotorScaled));            
    }
    else 
    {
      Serial.print("R");
      Serial.print(abs(rightMotorScaled),DEC);

      analogWrite(controllerFB,0);
      analogWrite(controllerRB,abs(rightMotorScaled));  
    }
  }  
  else 
  {
  Serial.print("IDLE");
  analogWrite(controllerFB,0);
  analogWrite(controllerRB,0);
  } 

  Serial.println("");

  //To do: throttle change limiting, to avoid radical changes of direction for large DC motors

  delay(10);

}
Kamil Zadora
sumber
Menarik, kode ini seperti memberi makan 2 pin analog ke 2 pengontrol motor yang berbeda. Saya akan mencoba untuk mengadaptasi kode dan memodifikasi pengaturan saya. Arduino Uno + 1 papan driver Sabertooth. 1 joystick ke analog pinA0 (x) pinA1 (y) membaca dan meneruskan nilai ke PWM pin 10 & 3 menuju S1 & S2 dari Sabertooth. Saya pikir saya sudah dekat tetapi saya semakin bingung tentang cara mengatur dipswitch pada papan Sabertooth. Untuk saat ini saya teting dengan pengaturan switch untuk menerima input analog, switch 4 masih dalam posisi untuk drive diferensial tetapi akan mengembalikannya ke mode independen nanti untuk pengujian lebih lanjut. Saya pikir ini orig
@ user20514 selamat datang di electronics.stackexchange! Seperti yang mungkin Anda perhatikan, ini bukan forum tetapi situs tanya jawab, oleh karena itu ruang jawaban tidak dimaksudkan untuk diskusi. Harap bebas untuk mengajukan pertanyaan baru jika Anda memiliki sesuatu untuk ditanyakan, atau menggunakan komentar untuk (memang) mengomentari pertanyaan dan jawaban yang ada.
clabacchio
1
@Kamil - Video ditampilkan sebagai pribadi. Apakah masih tersedia? youtube.com/watch?v=sGpgWDIVsoE
Russell McMahon
@RussellMcMahon diaktifkan kembali :)
Kamil Zadora