Thuật toán trộn đầu vào tương tự 2 trục để điều khiển ổ đĩa vi sai


9

Tôi đang tìm kiếm thông tin về cách thực hiện trộn đúng 2 tín hiệu cần điều khiển tương tự (trục X và Y) để điều khiển ổ đĩa vi sai kép (ổ "như xe tăng") bằng cách sử dụng uC (ATMega328p trong trường hợp của tôi, nhưng cũng nên áp dụng cho bất kỳ uC nào với đầu vào ADC và đầu ra PWM):

Tôi có một thanh tương tự, cung cấp 2 giá trị tương tự:

(hướng) X: 0 đến 1023
(ga) Y: 0 đến 1023

nhập mô tả hình ảnh ở đây

Vị trí nghỉ là (hướng và bướm ga trung tính) 512,512 Van tiết lưu
tiến / hướng trái là 0,0
Toàn chuyển tiếp đầy đủ phải là 1023,0,
v.v.

Các động cơ được điều khiển bởi 2 trình điều khiển cầu H, 2 chân PWM cho mỗi (Chuyển tiếp, lùi), như vậy:
Động cơ trái: -255 đến 255
Động cơ phải: -255 đến 255
(giá trị dương cho phép chuyển tiếp chân PWM, đảo ngược âm tính Chân PWM, 0 vô hiệu hóa cả hai)

Mục tiêu là trộn các tín hiệu tương tự cần điều khiển để đạt được phản hồi sau:

a) Van tiết lưu về phía trước, hướng trung tính = phương tiện di chuyển về phía trước
b) Điều tiết về phía trước, hướng trái = phương tiện di chuyển về phía trước và rẽ trái
c) Điều tiết trung lập, hướng trái = phương tiện rẽ trái IN PLACE là động cơ bên phải hoàn toàn về phía trước, động cơ bên trái hoàn toàn ngược lại

... và tương tự cho các kết hợp khác. Tất nhiên, đầu ra phải là "tương tự", nghĩa là nó sẽ cho phép chuyển dần từ ví dụ từ tùy chọn a) sang b) sang c).

Khái niệm này là:

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


(1) Lưu ý rằng thuật toán cơ bản của tôi cho phép kiểm soát tốc độ 'quay tại chỗ' khi phím điều khiển được đẩy, ví dụ như còn lại bởi% của toàn thang đo. (2) Yêu cầu này phải được giải quyết lại nhiều lần cho đến nay. Cộng đồng người mẫu nên có câu trả lời cho điều này. (3) Nếu người nhận chuyển các lệnh thành vận tốc theo dõi bằng phản hồi, xe sẽ hành xử giống như điều kiện mặt đất thay đổi. NHƯNG nếu các lệnh được chuyển thành công suất động cơ hoặc điện áp ổ đĩa, vv hiệu suất của xe sẽ thay đổi theo điều kiện mặt đất. - có lẽ là 91) là thích hợp hơn.
Russell McMahon

Russell, tôi đã googled rất nhiều cho anwser và tôi đã tìm thấy rất nhiều bộ điều khiển động cơ sẵn sàng để kết nối trực tiếp với máy thu RC nhưng không có nhiều thông tin về thuật toán bên trong.
Kamil Zadora

ngày tốt! renho một người anh em họ đã cố gắng làm tê liệt trẻ sơ sinh và xây dựng một chiếc xe lăn, chương trình của họ hoạt động tốt, nhưng điện áp đầu ra quá thấp! giúp tôi! Tôi đang sử dụng một arduino uno.

@ John chào mừng bạn đến với Electronics.Stackexchange! Vui lòng xem Câu hỏi thường gặp để hiểu cách trang web này hoạt động và nếu bạn có câu hỏi muốn hỏi, hãy sử dụng nút cụ thể ở góc trên bên phải của trang.
clabacchio

Nó có hoạt động không ???
Russell McMahon

Câu trả lời:


4

Trộn "đúng" là mở để tranh luận :-).

Một vấn đề là bạn phải đưa ra quyết định về việc một bản nhạc đang di chuyển nhanh như thế nào dưới các tín hiệu thuần túy từ một nồi duy nhất và phải làm gì khi bao gồm các tín hiệu từ nồi khác. Ví dụ: nếu bạn đẩy FB (Chuyển tiếp lùi về phía trước hoàn toàn về phía trước và nếu cả hai động cơ đều chạy hết tốc lực về phía trước, làm thế nào để bạn đối phó với việc thêm một lượng nhỏ nồi LR (Trái phải) được thêm vào. để quay vòng, bạn phải có một đường đua đi nhanh hơn đường kia. Vì vậy, nếu bạn đang chạy ở tốc độ tối đa về phía trước trên cả hai động cơ, bạn phải giảm một hoặc một tốc độ theo dõi khác để quay. Nhưng, nếu bạn đã đứng yên thì bạn sẽ tăng tốc một hoặc một bài hát khác để đạt được kết quả tương tự.

Vì vậy, tất cả những gì đã nói, đây là một giải pháp khởi đầu đơn giản ra khỏi đầu tôi có vẻ như là một khởi đầu tốt.

Nếu chậu là độc lập cơ học thì cả hai có thể ở mức 100% cùng một lúc.
Nếu cả hai đều được sắp xếp theo kiểu phím điều khiển, nếu Yaxis = 100% và Xaxis = 0%, thì việc thêm một số B thường sẽ giảm A. Một phím điều khiển có thể được xây dựng trong trường hợp không đúng, nhưng những điều này là không bình thường.
Giả sử rằng cần điều khiển thuộc loại tăng Y% khi X = 100% sẽ giảm X. Có thể đưa ra các giả định khác.

FB = nồi trước. Trung tâm số 0, + Ve cho chuyển động về phía trước của nồi

LR = nồi phải trái. Trung tâm số không. + Ve cho nồi bên phải.

K là hệ số tỷ lệ ban đầu 1.
Nếu bất kỳ kết quả nào vượt quá 100% thì điều chỉnh K sao cho kết quả = 100% và sử dụng cùng một giá trị K cho động cơ khác.

  • ví dụ: nếu kết quả động cơ bên trái = 125 và kết quả động cơ phải = 80 thì.
    Khi 125 x 0,8 = 100, đặt K = 0,8. Sau đó.
    Còn lại = 125 x 0,8 = 100%. Phải = 80 x 0,8 = 64%.

Sau đó:

  • Động cơ bên trái = K x (Front_Back + Left_Right)

  • Động cơ phải = K x (Front_Back - Left_Right)

Kiểm tra vệ sinh:

  • LR = 0 (chính giữa), FB = full fwd -> Cả hai động cơ đều chạy hoàn toàn về phía trước.

  • LR = đầy trái, FB = 0 ->
    Động cơ trái chạy ngược hoàn toàn,
    Động cơ phải chạy đầy đủ về phía trước.
    Xe quay ngược chiều kim đồng hồ.

  • FB là 100%, Lr = 0%. Thêm 10% của LR vào bên phải.
    L = FB + LR = 100% - + 10% R = FB-LR = 100% - - 10%

Nếu trục lớn nhất <100%, tỷ lệ cho đến = 100%.
Sau đó quy mô trục khác bằng số tiền tương tự.


Cảm ơn bạn Russell - Tôi sẽ cố gắng thực hiện điều này trên thiết lập mô hình của tôi. BTW, Cần điều khiển của tôi có thể tiếp tục tiến về phía trước trong khi xoay từ trái sang phải và ngược lại, nó rất giống với điều này: static.sparkfun.com/images/products/09032-03-L_i_ma.jpg
Kamil Zadora

1
Tôi hiện đang được giao nhiệm vụ giải quyết vấn đề tương tự trong công việc. Tôi có bộ điều khiển 2 trục wii nunchuk và nó cần điều khiển 2 động cơ chính xác như được mô tả trong câu hỏi. Tôi có một chút rắc rối để hiểu logic ở đây. Chính xác thì k1 / K1 đề cập đến điều gì? Một là chữ thường và một là chữ hoa - chúng có khác nhau không? + Ve là gì?
Tal

1
Tuyệt - cảm ơn đã làm rõ. Tôi cần cái này được viết bằng Python, vì vậy nếu tôi hiểu chính xác, thì nó nên làm điều đó: pastebin.com/sWDakvLp . Có vẻ như tôi đang thiếu bất cứ thứ gì? Có vẻ như hoạt động trong môi trường thử nghiệm của tôi - Tôi thực sự cần phải kết nối nó với các động cơ cuối cùng mà tôi sẽ sử dụng để biết chắc chắn.
Tal

1
1) Tốc độ động cơ được điều khiển bởi PWM, chỉ lấy các giá trị từ 0 - 100, đó là lý do tại sao tôi sử dụng 100 làm giá trị tối đa. 2) Tôi sử dụng abs để tìm xem có cần chia tỷ lệ không (như bạn đã nói) và để lấy scale_factor. Nếu tôi kết thúc với hệ số tỷ lệ là 0,8 chẳng hạn, và sử dụng nó cho số âm, -125 * 0.8 = -100. Hướng được duy trì. Tôi nghĩ rằng nó hoạt động, trừ khi tôi đang thiếu một cái gì đó. Tôi vẫn chưa có cơ hội dùng thử trên các động cơ cuối cùng - ông chủ của tôi sẽ xây dựng một nền tảng thử nghiệm với các động cơ được gắn mà tôi có thể thử nghiệm.
Tal

1
Tôi không chắc liệu mã của mình có thực sự hoạt động hay không, vì vậy tôi đã đặt liên kết pastebin trước đó hết hạn sau một tuần. Vì nó có vẻ hoạt động, đây là một liên kết lâu dài hơn với một vài bình luận nếu có ai gặp lại vấn đề này: pastebin.com/EKguJ1KP . Tôi sẽ đặt câu trả lời này vào câu trả lời, nhưng dường như tôi không có đủ đại diện để đăng câu trả lời. Tất cả các mã được dựa trên câu trả lời của Russel McMahon - tín dụng thuộc về anh ta - cảm ơn Russel.
Tal

5

Đây là một giải pháp không yêu cầu các chuỗi if / khác phức tạp, không làm giảm sức mạnh khi di chuyển hoàn toàn về phía trước hoặc xoay tại chỗ, và cho phép các đường cong và chuyển tiếp mượt mà từ chuyển sang xoay tròn.

Ý tưởng rất đơn giản. Giả sử các giá trị cần điều khiển (x, y) là tọa độ cartesian trên mặt phẳng vuông. Bây giờ hãy tưởng tượng một mặt phẳng hình vuông nhỏ hơn quay 45 độ bên trong nó.

máy bay ví dụ

Các tọa độ cần điều khiển cung cấp cho bạn một điểm trong hình vuông lớn hơn và cùng một điểm được đặt chồng lên trong hình vuông nhỏ hơn cung cấp cho bạn các giá trị động cơ. Bạn chỉ cần chuyển đổi tọa độ từ hình vuông này sang hình vuông khác, giới hạn các giá trị (x, y) mới sang các cạnh của hình vuông nhỏ hơn.

Có nhiều cách để thực hiện chuyển đổi. Phương pháp yêu thích của tôi là:

  1. Chuyển đổi tọa độ ban đầu (x, y) sang tọa độ cực.
  2. Xoay chúng 45 độ.
  3. Chuyển đổi tọa độ cực trở lại cartesian.
  4. Thay đổi tọa độ mới thành -1.0 / + 1.0.
  5. Kẹp các giá trị mới thành -1.0 / + 1.0.

Điều này giả sử tọa độ ban đầu (x, y) nằm trong phạm vi -1.0 / + 1.0. Cạnh của hình vuông bên trong sẽ luôn bằng nhau l * sqrt(2)/2, vì vậy bước 4 chỉ là nhân các giá trị với sqrt(2).

Đây là một ví dụ về triển khai 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

Ý tưởng ban đầu cho phương pháp này - với phương pháp biến đổi phức tạp hơn nhiều - xuất phát từ bài viết này .


0

Dưới đây là ví dụ về triển khai thuật toán trộn như được mô tả bởi câu trả lời của Russel McMahon:

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

}

Thật thú vị, mã này trông giống như đang cung cấp 2 pin analog cho 2 bộ điều khiển động cơ khác nhau. Tôi sẽ cố gắng điều chỉnh mã và sửa đổi các cài đặt của mình. Bảng điều khiển Arduino Uno + 1 Sabertooth. 1 phím điều khiển cho pin tương tựA0 (x) pinA1 (y) đọc và chuyển các giá trị sang chân PWM 10 & 3 đi tới S1 & S2 của Sabertooth. Tôi nghĩ rằng tôi đang ở gần nhưng tôi đang bối rối về cách thiết lập dipswitch trên bảng Sabertooth. Hiện tại tôi đang chỉnh sửa thiết lập công tắc để nhận đầu vào tương tự, công tắc 4 vẫn ở vị trí cho ổ đĩa vi sai nhưng sẽ đưa nó trở lại chế độ độc lập sau để kiểm tra thêm. Tôi nghĩ nguồn gốc này

@ user20514 chào mừng bạn đến với thiết bị điện tử.stackexchange! Như bạn có thể nhận thấy, đây không phải là một diễn đàn mà là một trang web Hỏi & Đáp, do đó, không gian của câu trả lời không dành cho thảo luận. Vui lòng đặt câu hỏi mới nếu bạn có điều gì muốn hỏi hoặc sử dụng nhận xét để (thực sự) nhận xét về các câu hỏi và câu trả lời hiện có.
clabacchio

1
@Kamil - Video được hiển thị là riêng tư. Nó vẫn còn tồn tại? youtube.com/watch?v=sGpgWDIVsoE
Russell McMahon

@RussellMcMahon đã kích hoạt lại :)
Kamil Zadora
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.