एक अंतर मोटर ड्राइव को नियंत्रित करने के लिए 2 अक्ष एनालॉग इनपुट के मिश्रण के लिए एल्गोरिदम


9

मैं एक दोहरी अंतर मोटर ड्राइव ("टैंक जैसी" ड्राइव) को नियंत्रित करने के लिए 2 एनालॉग जॉयस्टिक सिग्नल (एक्स ए वाई एक्सिस) के उचित मिश्रण को लागू करने के तरीके के बारे में जानकारी की तलाश कर रहा हूं जो मेरे मामले में एक यूसी (ATMega328p) का उपयोग कर रहा है, लेकिन एक ही लागू होता है एडीसी इनपुट और पीडब्लूएम आउटपुट के साथ कोई यूसी):

मेरे पास एक एनालॉग स्टिक है, जो 2 एनालॉग वैल्यू देता है:

(दिशा) X: 0 से 1023
(थ्रॉटल) Y: 0 से 1023

यहाँ छवि विवरण दर्ज करें

बाकी स्थिति (दिशा और थ्रोटल न्यूट्रल) 512,512
थ्रॉटल आगे / दिशा बाईं ओर 0,0
फुल फॉरवर्ड-फुल राइट 1023,0
आदि है।

मोटरों को 2 एच-ब्रिज ड्राइवरों, प्रत्येक के लिए 2 पीडब्लूएम पिंस (आगे, पीछे) द्वारा नियंत्रित किया जाता है, जैसे:
वाम मोटर: -255 से 255
सही मोटर: -255 से 255
(सकारात्मक मान आगे PWM पिन सक्षम, नकारात्मक सक्षम PWM पिन, 0 दोनों को निष्क्रिय करता है)

लक्ष्य निम्नलिखित प्रतिक्रिया प्राप्त करने के लिए जॉयस्टिक एनालॉग संकेतों को मिलाना है:

क) थ्रॉटल फॉरवर्ड, दिशा न्यूट्रल = व्हीकल आगे बढ़ना
बी) थ्रॉटल फॉरवर्ड, दिशा लेफ्ट = व्हीकल आगे बढ़ना और लेफ्ट
सी मुड़ना ) थ्रॉटल न्यूट्रल, दिशा लेफ्ट = व्हीकल टर्निंग लेफ्ट इन PLACE जो कि राइट मोटर फुल फॉरवर्ड, लेफ्ट फुल रिवर्स

... और इसी तरह अन्य संयोजनों के लिए। बेशक, आउटपुट "एनालॉग" होना चाहिए, अर्थात, यह एक विकल्प से उदाहरण के लिए क्रमिक संक्रमण की अनुमति देना चाहिए ए से बी) से सी)।

अवधारणा है:

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


(1) ध्यान दें कि मेरा मूल एल्गोरिथ्म जॉयस्टिक को पूर्ण पैमाने के% द्वारा छोड़े जाने पर 'टर्न इन प्लेस' की गति नियंत्रण की अनुमति देता है। (२) इस आवश्यकता को अब तक कई बार पुनः हल किया गया होगा। मॉडल समुदाय के पास इसका जवाब होना चाहिए। (३) यदि रिसीवर फीडबैक वेग का उपयोग करते हुए कमांड्स को ट्रैक वेलोसिटी में ट्रांसलेट करता है, तो वाहन उसी के बारे में व्यवहार करेगा जैसे जमीनी हालात बदलते हैं। लेकिन अगर आज्ञाओं का मोटर शक्ति या ड्राइव वोल्टेज आदि में अनुवाद किया जाता है, तो वाहन का प्रदर्शन जमीन की स्थितियों के साथ अलग-अलग होगा। - संभवतः 91) बेहतर है।
रसेल मैकमोहन

रसेल, मैंने awser के लिए बहुत कुछ जाना है और मैंने आरसी रिसीवर से सीधे कनेक्ट होने के लिए मोटर नियंत्रक जाने के लिए बहुत तैयार पाया है लेकिन अंदर एल्गोरिथ्म के बारे में अधिक जानकारी नहीं है।
कामिल ज़दोरा

अच्छा दिन! रेनो एक चचेरा भाई है जो शिशु पक्षाघात की कोशिश कर रहा है और व्हीलचेयर का निर्माण उनकी प्रोग्रामिंग अच्छी तरह से काम करती है, लेकिन आउटपुट वोल्टेज बहुत कम है! मेरी मदद करो! मैं एक arduino uno का उपयोग कर रहा हूं।

@ जॉनी का स्वागत है Electronics.tackexchange में! कृपया यह देखने के लिए कि यह साइट कैसे काम करती है, यह समझने के लिए अक्सर पूछे जाने वाले प्रश्न देखें और यदि आपसे कोई प्रश्न पूछना है तो कृपया पृष्ठ के शीर्ष-दाएं कोने पर स्थित विशिष्ट बटन का उपयोग करें।
clabacchio

काम किया ???
रसेल मैकमोहन

जवाबों:


4

"उचित" मिश्रण बहस के लिए खुला है :-)।

एक मुद्दा यह है कि आपको इस बारे में निर्णय लेना है कि एक पॉट एक एकल पॉट से शुद्ध संकेतों के तहत कितनी तेजी से आगे बढ़ रहा है और दूसरे पॉट से सिग्नल शामिल होने पर क्या करना है। उदाहरण के लिए, यदि आप FB (फॉरवर्ड-बैकवर्ड पॉट को पूरी तरह से आगे की ओर धकेलते हैं, और यदि दोनों मोटरें आगे पूरी गति से चलती हैं, तो आप LR (लेफ्ट-राईट) पॉट की एक छोटी मात्रा को जोड़ने के साथ कैसे व्यवहार करते हैं। रोटेशन प्राप्त करने के लिए आपके पास एक ट्रैक है जो तेजी से चल रहा है, दूसरे। इसलिए, यदि आप पहले से ही दोनों मोटर्स पर अधिकतम फॉरवर्ड गति से चल रहे हैं, तो आपको चालू करने के लिए एक या अन्य ट्रैक गति को कम करना होगा। लेकिन, अगर आप अभी भी खड़े थे। एक ही परिणाम प्राप्त करने के लिए एक या दूसरे ट्रैक को तेज किया होगा।

तो, यह सब कहा, यहाँ मेरे सिर से बाहर एक सरल ऑफ-कफ शुरुआती समाधान है जो अच्छी शुरुआत की तरह लगता है।

यदि यंत्रवत् रूप से स्वतंत्र हैं, तो दोनों एक साथ 100% हो सकते हैं।
यदि दोनों एक जॉयस्टिक प्रकार की व्यवस्था पर हैं, यदि याक्सिस = 100% और Xaxis = 0% है, तो कुछ बी को जोड़ने से आमतौर पर ए। कम हो जाएगा। एक जॉयस्टिक का निर्माण किया जा सकता है जहां ऊपर सच नहीं है, लेकिन ये असामान्य हैं।
मान लें कि जॉयस्टिक उस प्रकार का है जो Y% को बढ़ाता है जब X = 100% X को कम कर देगा। अन्य धारणाएं बनाई जा सकती हैं।

एफबी = फ्रंट-बैक पॉट। पॉट की आगे की गति के लिए केंद्र शून्य, + वे

LR = बायां दायां बर्तन। केंद्र शून्य। + सही पर बर्तन के लिए।

K शुरू में एक पैमाना कारक है।
यदि कोई परिणाम 100% से अधिक है तो K को परिणाम = 100% समायोजित करें और अन्य मोटर के लिए भी समान K मान का उपयोग करें।

  • जैसे अगर लेफ्ट मोटर परिणाम = 125 और राइट मोटर परिणाम = 80 तो।
    125 x 0.8 = 100 के रूप में, K = 0.8 सेट करें। फिर।
    वाम = 125 x 0.8 = 100%। दायां = 80 x 0.8 = 64%।

फिर:

  • वाम मोटर = K x (Front_Back + Left_Right)

  • दायां मोटर = K x (Front_Back - Left_Right)

स्वच्छता की जाँच:

  • एलआर = 0 (केंद्रित), एफबी = पूर्ण एफडब्ल्यूडी -> दोनों मोटर्स पूर्ण फॉरवर्ड चलाते हैं।

  • LR = फुल लेफ्ट, FB = 0 ->
    लेफ्ट मोटर फुल बैकवर्ड चलती है,
    राइट मोटर फुल फॉरवर्ड चलती है।
    वाहन एंटी क्लॉक वाइज घूमता है।

  • FB 100%, Lr = 0% था। राइट से 10% LR जोड़ें।
    L = FB + LR = 100% - + 10% R = FB-LR = 100% - - 10%

यदि सबसे बड़ी धुरी <100%, पैमाने = 100% तक।
फिर उसी मात्रा से अन्य अक्ष को स्केल करें।


धन्यवाद रसेल - मैं इसे अपने मॉडल सेटअप पर लागू करने का प्रयास करूंगा। BTW, मेरा जॉयस्टिक इसे दाएं से बाएं और दूसरे तरीके से पैन करते समय पूरा आगे रखने में सक्षम है, यह बहुत समान है: static.sparkfun.com/images/products/09032-03-L_i_ma_jpg
कामिल

1
वर्तमान में मुझे काम में इसी समस्या को हल करने का काम सौंपा गया है। मेरे पास एक wii nunchuk 2-अक्ष नियंत्रक है, और इसे 2 मोटर्स को नियंत्रित करने की आवश्यकता है जैसा कि प्रश्न में वर्णित है। मुझे यहाँ तर्क समझने में थोड़ी परेशानी हो रही है। वास्तव में k1 / K1 क्या दर्शाता है? एक लोअरकेस है और एक अपरकेस है - क्या वे अलग हैं? + वी क्या है?
ताल

1
कूल - स्पष्टीकरण के लिए धन्यवाद। मुझे पायथन में यह लिखा हुआ चाहिए, इसलिए अगर मैं सही तरीके से समझूं, तो यह करना चाहिए: pastebin.com/sWDakvLp । क्या ऐसा लगता है कि मुझे कुछ याद आ रहा है? मेरे परीक्षण वातावरण में काम करने लगता है - मुझे वास्तव में इसे अंतिम मोटर्स से जोड़ने की आवश्यकता होगी जिसे मैं निश्चित रूप से जानने के लिए उपयोग कर रहा हूं।
ताल

1
1) मोटर गति को पीडब्लूएम द्वारा नियंत्रित किया जाता है, जो केवल 0 - 100 से मान लेता है, यही कारण है कि मैंने अधिकतम मूल्य के रूप में 100 का उपयोग किया। 2) अगर स्केलिंग की जरूरत है (जैसे आपने कहा) और स्केल_फैक्टर प्राप्त करने के लिए मैं एब्स का उपयोग करता हूं। यदि मैं उदाहरण के लिए 0.8 के पैमाने कारक के साथ समाप्त होता हूं, और इसे एक नकारात्मक संख्या पर उपयोग करता है, -125 * 0.8 = -100। दिशा बनी रहती है। मुझे लगता है कि यह काम करता है, जब तक कि मुझे कुछ याद नहीं है। मुझे अभी भी अंतिम मोटर्स पर इसे आज़माने का मौका नहीं मिला है - मेरा बॉस एक परीक्षण मंच का निर्माण करेगा जिसमें संलग्न मोटरें होंगी जिन्हें मैं परीक्षण कर पाऊंगा।
ताल

1
मुझे यकीन नहीं था कि अगर मेरा कोड वास्तव में काम करेगा, तो मैंने एक सप्ताह के बाद समाप्त करने के लिए पिछले pastebin लिंक को सेट किया। जब से यह काम करने लगता है, यहाँ कुछ और टिप्पणियों के साथ एक और स्थायी लिंक है अगर किसी को फिर से समस्या आती है: pastebin.com/EKguJ1KP । मैं इसे एक उत्तर में डालूंगा, लेकिन जाहिर तौर पर मेरे पास उत्तर पोस्ट करने के लिए पर्याप्त प्रतिनिधि नहीं है। सभी कोड रसेल मैकमोहन के उत्तर पर आधारित है - इसका श्रेय उन्हें जाता है - धन्यवाद रसेल।
ताल

5

यहां एक समाधान है जिसे जटिल होने की आवश्यकता नहीं है अगर / अन्यथा जंजीरों, पूरी तरह से आगे बढ़ने या जगह में घूमने पर शक्ति कम नहीं होती है, और चिकनी घटता और संक्रमण से कताई तक की अनुमति देता है।

विचार सरल है। मान लें कि (x, y) जॉयस्टिक मान एक वर्गाकार तल पर कार्टेशियन निर्देशांक हैं। अब कल्पना कीजिए कि एक छोटा सा वर्गाकार विमान इसके अंदर 45º घुमाया गया।

उदाहरण विमान

जॉयस्टिक निर्देशांक आपको बड़े वर्ग में एक बिंदु देते हैं, और छोटे वर्ग में एक ही बिंदु को सुपरपाइंट आपको मोटर मान देता है। आपको बस छोटे वर्ग के पक्षों में नए (x, y) मूल्यों को सीमित करते हुए निर्देशांक को एक वर्ग से दूसरे वर्ग में बदलने की आवश्यकता है।

रूपांतरण करने के कई तरीके हैं। मेरी पसंदीदा विधि है:

  1. प्रारंभिक (x, y) निर्देशांक को ध्रुवीय निर्देशांक में परिवर्तित करें।
  2. उन्हें 45 डिग्री से घुमाएं।
  3. ध्रुवीय निर्देशांक को कार्टेसियन में बदलें।
  4. नए निर्देशांक को -1.0 / + 1.0 पर पुनर्विक्रय करें।
  5. नए मानों को -1.0 / + 1.0 पर क्लैंप करें।

यह मानता है कि प्रारंभिक (x, y) निर्देशांक -1.0 / + 1.0 रेंज में हैं। आंतरिक वर्ग का पक्ष हमेशा के बराबर होगा l * sqrt(2)/2, इसलिए चरण 4 केवल मानों को गुणा करने के बारे में हैsqrt(2)

यहाँ एक उदाहरण पायथन कार्यान्वयन है।

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

इस विधि के लिए मूल विचार - बहुत अधिक जटिल परिवर्तन विधि के साथ - इस लेख से आया है ।


0

नीचे रसेल मैकमोहन उत्तर द्वारा वर्णित एल्गोरिथ्म कार्यान्वयन का उदाहरण दिया गया है:

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

}

दिलचस्प है, यह कोड ऐसा दिखता है कि यह 2 एनालॉग पिन को 2 अलग-अलग मोटर नियंत्रक को खिला रहा है। मैं कोड को अनुकूलित करने और अपनी सेटिंग्स के लिए संशोधित करने का प्रयास करूंगा। Arduino Uno + 1 Sabertooth ड्राइवर बोर्ड। 1 जॉयस्टिक से एनालॉग pinA0 (x) pinA1 (y) पीडब्लूएम पिन 10 और 3 को पढ़ने और पासिंग मानों को Sert और Sert के S1 & S2 में जाना। मुझे लगता है कि मैं करीब हूं, लेकिन मुझे इस बात पर भ्रम हो रहा है कि सबवर्थ बोर्ड पर डिप्सविच को कैसे सेटअप किया जाए। अभी के लिए मैं एनालॉग इनपुट प्राप्त करने के लिए स्विच सेटअप के साथ टेटिंग कर रहा हूं, स्विच 4 अभी भी अंतर ड्राइव के लिए स्थिति में है लेकिन बाद में इसे आगे के परीक्षण के लिए स्वतंत्र मोड में डाल देगा। मुझे लगता है कि यह उत्पत्ति

@ user20514 आपका स्वागत है Electronics.stackexchange में! जैसा कि आप देख सकते हैं, यह एक मंच नहीं है, बल्कि एक प्रश्नोत्तर स्थल है, इसलिए उत्तर 'स्थान चर्चा के लिए नहीं है। कृपया एक नया प्रश्न पूछने के लिए स्वतंत्र रहें यदि आपके पास मौजूदा प्रश्नों और उत्तरों के बारे में टिप्पणी (वास्तव में) टिप्पणी करने के लिए कुछ है या उपयोग करने के लिए है।
clabacchio

1
@ कामिल - वीडियो को निजी दिखाया गया है। यह अभी भी उपलब्ध है? youtube.com/watch?v=sGpgWDIVsoE
रसेल मैकमोहन

@RussellMcMahon ने पुन: सक्रिय किया :)
कामिल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.