Diferansiyel motor sürücüsünü kontrol etmek için 2 eksenli analog girişi karıştırmak için algoritma


9

Bir uC (ATMega328p) kullanarak bir çift diferansiyel motor sürücüsünü ("tank benzeri" sürücü) kontrol etmek için 2 analog joystick sinyalinin (X ve Y ekseni) uygun şekilde karıştırılması hakkında bilgi arıyorum, ancak aynı durum benim için de geçerli olmalı ADC girişleri ve PWM çıkışları olan herhangi bir uC):

Ben 2 analog değerleri veren bir analog sopa var:

(yön) X: 0 ila 1023
(gaz kelebeği) Y: 0 ila 1023

resim açıklamasını buraya girin

Dinlenme konumu (yön ve gaz kelebeği nötr) 512,512
Gaz kelebeği ileri / sol yönü 0,0
Tam ileri-tam sağ 1023,0
vb.

Motorlar 2 H-köprü sürücüsü, her biri için 2 PWM pimi (İleri, geri) tarafından kontrol edilir, şöyle:
Sol Motor: -255 ila 255
Sağ Motor: -255 ila 255
(pozitif değerler ileri PWM pinini etkinleştirir, negatif geri etkinleştirir PWM pin, 0 her ikisini de devre dışı bırakır)

Amaç, aşağıdaki yanıtı elde etmek için joystick analog sinyallerini karıştırmaktır:

a) Gaz kelebeği ileri, yön nötr = araç ileri hareket ediyor
b) Gaz kelebeği ileri, sol yön = araç hareket ediyor ve sola dönüyor
c) Gaz kelebeği nötr, sol yön = sağ motor tam ileri, sol motor tam geri olan YERDE sola dönüyor

... ve benzer şekilde diğer kombinasyonlar için. Elbette, çıktı "analog" olmalıdır, yani örneğin a) ila b) ila c) arasında kademeli geçişe izin vermelidir.

Konsept:

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


(1) Temel algoritmamın, joystick'e örneğin tam ölçeğin% 'si kadar sola basıldığında' yerinde dönüş 'hız kontrolüne izin verdiğini unutmayın. (2) Bu gereklilik şimdiye kadar birçok kez yeniden çözülmüş olmalıdır. Model topluluğunun buna cevapları olmalıdır. (3) Alıcı, komutları geri bildirim kullanarak parça hızına çevirirse, araç, zemin koşulları değişikliğiyle aynı şekilde davranacaktır. AMA komutlar motor gücüne veya sürücü voltajına vb. Çevrilirse, araç performansı zemin koşullarına göre değişir. - muhtemelen 91) tercih edilir.
Russell McMahon

Russell, anwser için çok şey yaptım ve doğrudan RC alıcısına bağlanmak için motor kontrol cihazlarına çok fazla hazır buldum, ancak içindeki algoritma hakkında fazla bilgi yok.
Kamil Zadora

iyi günler! İnfantil felç ve tekerlekli sandalyenin inşasını deneyen bir kuzen, programlamaları iyi çalıştı, ancak çıkış voltajı çok düşük! bana yardım et! Arduino uno kullanıyorum.

@ Johnny Electronics.Stackexchange'e hoş geldiniz! Bu sitenin nasıl çalıştığını anlamak için lütfen SSS bölümüne bakın ve sormak istediğiniz bir sorunuz varsa lütfen sayfanın sağ üst köşesindeki ilgili düğmeyi kullanın.
clabacchio

İşe yaradı mı ???
Russell McMahon

Yanıtlar:


4

"Düzgün" karıştırma tartışmaya açık :-).

Bir sorun, bir parçanın tek bir pottan saf sinyaller altında ne kadar hızlı hareket ettiği ve diğer pottan sinyaller dahil edildiğinde ne yapılacağı konusunda karar vermenizdir. Örneğin, FB (İleri-Geri potunu tamamen ileri doğru iterseniz ve her iki motor da tam hızda ilerlerse, az miktarda LR (Sol-Sağ) potun eklenmesiyle nasıl başa çıkabilirsiniz. dönme elde etmek için bir parkurun diğerinden daha hızlı gitmesi gerekir.Bu nedenle, eğer her iki motorda da maksimum ileri hızda çalışıyorsanız, dönüş yapabilmek için bir veya diğer parkur hızını düşürmeniz gerekir. aynı sonucu elde etmek için bir veya başka pisti hızlandırabilirdi.

Yani, tüm bunlar, başımdan iyi bir başlangıç ​​gibi görünen basit bir kelepçeli başlangıç ​​çözümü.

Kaplar mekanik olarak bağımsız ise, her ikisi de aynı anda% 100'de olabilir.
Her ikisi de joystick tipi bir düzenlemede ise, Yaxis =% 100 ve Xaxis =% 0 ise, biraz B eklemek genellikle A'yı azaltır. Yukarıdakilerin doğru olmadığı yerlerde bir joystick yapılabilir, ancak bunlar olağandışıdır.
Joystick'in X =% 100 olduğunda Y değerini artıran X'i azaltacağı türde olduğunu varsayalım. Diğer varsayımlar yapılabilir.

FB = ön arka kap. Merkez sıfır, potun ileri hareketi için + Ve

LR = Sol sağ kap. Merkez sıfır. + Ve pot için sağda.

K başlangıçta bir ölçek faktörü 1'dir.
Herhangi bir sonuç% 100'ü aşarsa K değerini sonuç =% 100 olarak ayarlayın ve diğer motor için de aynı K değerini kullanın.

  • örneğin Sol motor sonucu = 125 ve Sağ motor sonucu = 80 ise.
    125 x 0.8 = 100 olarak, K = 0.8 olarak ayarlayın. Sonra.
    Sol = 125 x 0.8 =% 100. Sağ = 80 x 0.8 =% 64.

Sonra:

  • Sol motor = K x (Ön_Geri + Sol_Sağ)

  • Sağ motor = K x (Ön_Geri - Sol_Sağ)

Sağlık kontrolleri:

  • LR = 0 (ortalanmış), FB = full fwd -> Her iki motor da tam ileri çalışır.

  • LR = sol tam, FB = 0 ->
    Sol motor tam geri çalışıyor,
    Sağ motor tam ileri çalışıyor.
    Araç saat yönünün tersine döner.

  • FB% 100, Lr =% 0 idi. Sağa% 10 LR ekleyin.
    L = FB + LR =% 100 - +% 10 R = FB-LR =% 100 - -% 10

En büyük eksen <% 100 ise, =% 100'e kadar ölçeklendirin.
Ardından diğer ekseni aynı miktarda ölçeklendirin.


Teşekkür ederim Russell - Bunu model kurulumuma uygulamaya çalışacağım. BTW, Joystick'im soldan sağa ve tam tersi yönde kaydırırken
Kamil Zadora

1
Şu anda işte aynı problemi çözmekle görevlendirildim. Bir wii nunchuk 2 eksenli denetleyicim var ve tam olarak soruda açıklandığı gibi 2 motoru kontrol etmesi gerekiyor. Buradaki mantığı anlamakta biraz zorlanıyorum. K1 / K1 tam olarak ne anlama geliyor? Biri küçük harf, diğeri büyük harf - farklı mı? + Ve nedir?
Tal

1
Serin - açıklama için teşekkürler. Python ile yazılmış buna ihtiyacım vardı, bu yüzden doğru anlarsam , bunu yapmalı: pastebin.com/sWDakvLp . Bir şey eksikmişim gibi mi görünüyor? Test ortamımda çalışıyor gibi görünüyor - emin olmak için kullanacağım son motorlara bağlamam gerekecek.
Tal

1
1) Motor hızı, yalnızca 0 - 100 arasındaki değerleri alan PWM tarafından kontrol edilir, bu yüzden 100 değerini maksimum değer olarak kullandım. 2) Ölçeklemenin gerekli olup olmadığını (dediğin gibi) bulmak ve scale_factor'u almak için abs kullanıyorum. Örneğin 0.8'lik bir ölçek faktörü ile sonuçlanır ve negatif bir sayı, -125 * 0.8 = -100 kullanılırsa. Yön korunur. Sanırım bir şey eksik olmadıkça işe yarıyor. Hala son motorlarda denemek için bir şansım olmadı - patronum test edebileceğim motorlarla bağlı bir test platformu inşa edecek.
Tal

1
Kodum gerçekten işe yarayacaktı, bu yüzden bir hafta sonra sona erecek önceki pastebin bağlantı ayarlamak emin değildi. Çalıştığı göründüğünden, bir kez daha sorunla karşılaşırsa, birkaç yorum içeren daha kalıcı bir bağlantı: pastebin.com/EKguJ1KP . Bunu bir yanıta koyardım, ama görünüşe göre bir cevap göndermek için yeterli temsilcim yok. Tüm kod Russel McMahon'un cevabına dayanıyor - kredi ona gidiyor - teşekkürler Russel.
Tal

5

Burada, eğer zincir zincirleri / zincirleri karmaşık değilse, tam ileri hareket ederken veya yerinde dönerken gücü azaltmaz ve yumuşak eğrilerin ve geçişlerin dönmeden dönmeye geçişine izin veren bir çözüm.

Fikir basit. (X, y) joystick değerlerinin kare bir düzlemde kartezyen koordinatlar olduğunu varsayalım. Şimdi içinde 45º döndürülmüş daha küçük bir kare düzlem düşünün.

örnek uçak

Kumanda kolu koordinatları size daha büyük karede bir nokta verir ve daha küçük karede üst üste binen aynı nokta size motor değerlerini verir. Yeni (x, y) değerlerini küçük karenin kenarlarıyla sınırlandırarak koordinatları bir kareden diğerine dönüştürmeniz yeterlidir.

Dönüştürmeyi yapmanın birçok yolu vardır. En sevdiğim yöntem:

  1. Başlangıç ​​(x, y) koordinatlarını kutupsal koordinatlara dönüştürün.
  2. Onları 45 derece döndürün.
  3. Kutupsal koordinatları tekrar kartezyen'e dönüştürün.
  4. Yeni koordinatları -1.0 / + 1.0 olarak yeniden ölçeklendirin.
  5. Yeni değerleri -1.0 / + 1.0 değerine sıkıştırın.

Bu, başlangıç ​​(x, y) koordinatlarının -1.0 / + 1.0 aralığında olduğunu varsayar. İç karenin kenarı her zaman eşit olacaktır l * sqrt(2)/2, bu nedenle adım 4 sadece değerleri çarpmakla ilgilidir sqrt(2).

Aşağıda bir Python uygulaması örneği verilmiştir.

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

Bu yöntemin orijinal fikri - çok daha karmaşık bir dönüşüm yöntemi ile - bu makaleden geldi .


0

Aşağıda Russel McMahon cevabı tarafından tarif edildiği gibi karıştırma algoritması uygulamasına bir örnek verilmiştir:

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);

}

İlginç, bu kod 2 farklı motor kontrolörüne 2 analog pim besliyor gibi görünüyor. Kodu uyarlamaya ve ayarlarım için değiştirmeye çalışacağım. Arduino Uno + 1 Sabertooth sürücü kartı. 1 kumanda kolundan analog pinA0 (x) pinA1 (y) 'ye okuma ve değerleri Sabertooth'un S1 & S2'sine giden PWM pin 10 ve 3'e iletme. Sanırım yakınım ama Sabertooth kartında dip anahtarının nasıl kurulacağı konusunda kafam karışıyor. Şimdilik analog girişi almak için anahtar kurulumuyla dalga geçiyorum, anahtar 4 hala diferansiyel sürücü için pozisyonda ancak daha sonraki testler için daha sonra bağımsız moda geri döndürecek. Bence bu orig

@ user20514 electronics.stackexchange'e hoş geldiniz! Gördüğünüz gibi, bu bir forum değil bir Soru-Cevap sitesi, bu nedenle cevapların alanı tartışma amaçlı değildir. Lütfen sormak istediğiniz bir şey varsa yeni bir soru sormaktan çekinmeyin veya mevcut sorular ve cevaplar hakkında yorum yapmak için (gerçekten) yorum kullanın.
clabacchio

1
@Kamil - Video özel olarak gösteriliyor. Hala kullanılabilir mi? youtube.com/watch?v=sGpgWDIVsoE
Russell McMahon

@RussellMcMahon yeniden etkinleştirildi :)
Kamil Zadora
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.