Có cách nào để ngăn chặn những người nô lệ khỏi rung lắc không?


20

Rất đơn giản, tôi đang kiểm soát các servo (9g Micro Servos) dựa trên một số dữ liệu được đọc từ nơi khác. Tất cả mọi thứ hoạt động tốt, ngoại trừ rằng các servo sẽ liên tục "rung chuyển". Đó là, chúng rung trở lại với các chuyển động rất tinh tế (với các chuyển động không liên tục là 1/2 -> 1cm hoặc hơn).

Tôi đã cố gắng khắc phục vấn đề này trong phần mềm bằng cách làm một cái gì đó như:

  do{
    delay(DTIME);
    positionServo();
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("X position: ");
    lcd.print(xRead);
    lcd.setCursor(0,1);
    lcd.print("Y position: ");
    lcd.print(yRead);
  }while( readChange() ); //while there has been change

Trong trường hợp cần thiết là khởi tạo các biến lưu trữ giá trị servo được ánh xạ (sử dụng thư viện servo arduino).

Hàm readChange () được định nghĩa là:

int readChange(){
  int x_Temp, y_Temp;

  x_Temp = map(analogRead(x_axisReadPin), 0, 1023, 0, 179);
  y_Temp = map(analogRead(y_axisReadPin), 0, 1023, 0, 179);

  if( abs(x_Temp - xRead) < DEG && abs(y_Temp - yRead) < DEG ) return 0; // no change 
  else return 1; //change
}

Trong đó xRead là giá trị được khởi tạo (đầu ra servo đầu tiên được ánh xạ).

Mặc dù, đây thực sự không phải là một cách tiếp cận tốt. Nó yêu cầu các giá trị BÓNG không được thay đổi theo hệ số DEG (~ 10 độ hoặc ~ 0,28V trong trường hợp của tôi). Nếu tôi viết hàm sao cho HOẶC nhỏ hơn DEG, thì nếu tôi chỉ thay đổi một servo mỗi lần thì sao? Vì vậy, có một sự phân định ..

Đây có phải chỉ đơn giản là một tài sản của servo (có lẽ là giá rẻ?) Hoặc có một cách giải quyết?


Nó sẽ đơn giản hơn nhiều để bao gồm một liên kết pastie. Đây là mã đầy đủ: http://pastie.org/8191459

Tôi đã gắn hai động cơ servo cùng với một con trỏ laser để cho phép hai bậc tự do (X, Y). Có các tùy chọn, dựa trên trạng thái của một số nút, để điều khiển các servo theo nhiều cách khác nhau. Đầu tiên là "Chuyển động" nơi tôi có hai bộ phát quang, dựa trên mức độ tiếp xúc với ánh sáng, ảnh hưởng đến vị trí của các servo. Tôi chưa triển khai mã để điều khiển các servo bằng bộ điều khiển Xbox. Và lựa chọn thứ ba chỉ là chuyển động ngẫu nhiên.

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


4
Bạn rõ ràng có một chút bất ổn hoặc tiếng ồn trong bộ điều khiển servo của bạn. Tuy nhiên, bạn đi sâu vào nhiều chi tiết có vẻ như không liên quan gì đến bộ điều khiển servo, ngoại trừ dòng không có giấy tờ "locationServo ();", mà chúng ta chỉ có thể đoán là nơi chôn giấu các chi tiết. Bộ điều khiển servo có đóng trong micro không? Đóng cửa bên ngoài? Analog hay kỹ thuật số? Nếu kỹ thuật số, độ phân giải của nó được đo ở mức nào? Hiển thị sơ đồ của toàn hệ thống.
Olin Lathrop

Bao nhiêu tải bạn đang đặt trên các servo?
Chris Laplante

4
@OlinLathrop - (S) Anh ấy đang sử dụng các mô hình động cơ điều khiển vô tuyến tiêu chuẩn, có toàn bộ vòng lặp servo được nướng vào thiết bị. sherrellbc - "Servo" là một thuật ngữ rất, rất chung chung. Thật không may, các nhà sản xuất thành phần mô hình RC đã chọn về thuật ngữ mô tả ít nhất cho các thiết bị sản xuất. Vì chúng tôi xử lý hầu hết các loại động cơ servo và hệ thống servo khác nhau ở đây, việc chỉ định rằng "động cơ servo" của bạn là các mô hình điều khiển vô tuyến có lẽ là một ý tưởng tốt.
Sói Connor

1
Hệ thống của bạn quá phức tạp để chúng tôi có thể khắc phục sự cố cho bạn. Đơn giản hóa nó, và xem nếu bạn vẫn có vấn đề. Khi bạn có một hệ thống tối thiểu tái tạo vấn đề và bạn vẫn không thể tự khắc phục, thì nó sẽ trở nên phù hợp để yêu cầu trợ giúp.
Phil Frost

12
Lưu ý chung cho việc thiết kế các hệ thống định hướng bằng laser: đặt gương trên các động cơ servo, sau đó hướng từng cái khác. Bằng cách đó, bạn không cần phải có một servo được gắn trên cái kia, cũng không phải là laser được gắn trên các servo, và sau đó bạn có thể bắt vít chúng xuống một cách chắc chắn.
pjc50

Câu trả lời:


27

Khi sử dụng thư viện Servo trên Arduino, một nguồn phổ biến của tiếng ồn servo là các thói quen servo điều khiển ngắt thực sự không tạo ra xung đầu ra rất ổn định. Bởi vì AVR bị gián đoạn để phục vụ đồng hồ millis () và những thứ khác trong thời gian chạy Arduino, jitter trong thư viện Servo theo thứ tự vài micrô giây, chuyển thành rất nhiều chuyển động trong servo.

Cách khắc phục cho việc này là ghi xung của riêng bạn. Một cái gì đó như thế này:

cli();
long start = micros();
digitalWrite(PIN, HIGH);
while (micros() - start < duration)
  ;
digitalWrite(PIN, LOW);
sei();

Điều này sẽ tắt các ngắt khác và tạo ra xung PWM sạch hơn nhiều. Tuy nhiên, nó sẽ làm cho bộ đếm thời gian "millis () bỏ lỡ một số tích tắc đồng hồ. (Hàm" micros () "có thể được gọi là cái gì khác - tôi quên chính xác những gì.)

Nói chung, để xác định thời gian mã quan trọng, bạn muốn loại bỏ hoàn toàn thời gian chạy Arduino và tự viết bằng trình biên dịch avr-gcc và thư viện avr-libc cung cấp năng lượng cho môi trường Arduino. Sau đó, bạn có thể thiết lập bộ hẹn giờ để đánh dấu 4 lần mỗi micro giây hoặc thậm chí 16 lần mỗi micro giây và có được độ phân giải tốt hơn nhiều trong chế độ PWM của bạn.

Một nguyên nhân khác gây ra tiếng ồn trong các servo là các servo giá rẻ với các cảm biến rẻ tiền, trong đó các cảm biến bị nhiễu hoặc khi vị trí chính xác được yêu cầu với xung thực sự không thể được mã hóa bởi cảm biến. Servo sẽ thấy "di chuyển đến vị trí 1822" và cố gắng thực hiện, nhưng kết thúc bằng cảm biến đọc 1823. Sau đó, servo sẽ nói "di chuyển trở lại một chút" và kết thúc bằng cảm biến đọc 1821. Lặp lại! Cách khắc phục cho vấn đề này là sử dụng các bản servo chất lượng cao. Lý tưởng nhất, không phải là sở thích của tất cả, mà là các servo thực sự với bộ mã hóa tuyệt đối quang học hoặc từ tính.

Cuối cùng, nếu các servo không có đủ năng lượng hoặc nếu bạn cố gắng điều khiển công suất của chúng từ đường ray 5V trên Arduino, điều này sẽ tạo ra tiếng ồn điện áp gây ra trong các servo, như đề xuất ở trên. Bạn có thể sửa nó bằng các tụ điện điện phân lớn (dù sao cũng là một ý tưởng tốt để lọc chung) nhưng bạn có thể muốn chắc chắn rằng nguồn điện servo của bạn thực sự có thể cung cấp một vài dòng điện ở điện áp servo.


1
Tín hiệu điều khiển servo R / C là PWM. Độ rộng xung thường là 1-2 mili giây, khoảng thời gian lặp lại xung là từ 20 đến 50 mili giây. Tôi mong đợi hơn 10 micro giây biến thiên về độ rộng xung để khiến cho servo bị giật. Jitter trong PRI thường sẽ không thành vấn đề nếu độ rộng xung ổn định. (Bộ điều khiển 555 đơn giản bẩn của tôi đã thay đổi độ rộng xung và PRI bằng cùng một mức: servo không quan tâm.)
John R. Strohm

Tất cả những gì bạn nói là đúng, ngoại trừ jitter - servo sẽ jitter trước khi độ rộng xung bị "tắt" bởi 10 chúng tôi. Và jitter ngắt cho Arduino đơn giản (trước khi bạn thêm thư viện) có thể lên tới 10 us! Mã tôi đã dán được dự định để tạo ra một xung ổn định đá trong môi trường Arduino, thường không tốt cho các xung servo ổn định đá như một mạch 555 chuyên dụng.
Jon Watte

4
Tôi vừa viết một bài báo cho thấy cách tạo xung chính xác trên Arduino như đoạn mã trên, ngoại trừ nó sử dụng phần cứng Timer - và không cần tắt ngắt và làm rối thời gian chạy của Arduino.
bigjosh

Lưu ý rằng Arduino chỉ hỗ trợ đầu ra bộ định thời trên một vài chân (chân PWM) và bạn không thể sử dụng chân Timer0 cho phương pháp này. Do đó, chỉ có 4 chân này thực sự hoạt động trên một Arduino UNO thông thường. Nếu bạn cần lái xe 4 hoặc ít hơn và không cần bộ hẹn giờ cho thứ khác, đó là một lựa chọn tốt.
Jon Watte

21

Điều này được gọi là "buzz".

Có một vài điều sẽ gây ra nó. Sự không ổn định trong nguồn điện cho servo là một nguyên nhân phổ biến. Các động cơ R / C có thể rút ra một số gai LỚN khi lần đầu tiên đưa động cơ vào chuyển động.

Cách đây nhiều năm, tôi đã chơi với một chiếc servo Sở thích Tiêu chuẩn Hoàng gia Titan, điều khiển nó từ một biến tần 555 và một bóng bán dẫn. Mạch điều khiển chết đơn giản. Tôi đã học được rằng động cơ servo đã thu hút 250 mA từ nguồn cung cấp 5V trong khi chuyển động liên tục. Ù, nó dễ dàng rút ra các gai nửa amp. (Có thể nhiều hơn: Tôi chỉ theo dõi đồng hồ hiện tại trên nguồn cung cấp băng ghế dự bị của mình, không tìm kiếm một shunt cảm biến hiện tại.)

Phải mất 220 uF trực tiếp trên servo của tôi để chế ngự nó.

Hãy thử đặt một tụ điện điện phân, ít nhất 100 uF, trực tiếp trên nguồn cung cấp cho servo, càng gần điện với servo càng tốt, và xem điều đó có giúp ích gì không.

Dựa trên những thí nghiệm đó, tôi sẽ không bao giờ xem xét sử dụng các động cơ R / C cho BẤT CỨ NÀO mà không cần thêm tụ điện. Điều đó bao gồm các mô hình điều khiển vô tuyến.

Điều này cũng có thể được gây ra bởi bụi bẩn trong nồi servo bên trong servo. Hãy thử các tụ điện đầu tiên.


6

Có phải tiếng ù / rung của bạn chỉ xảy ra khi ở hoặc gần với giới hạn của servo (0 độ hoặc 180 độ) không? Nếu vậy, có thể có một sửa chữa đơn giản cho bạn. Tôi đã phát hiện ra rằng những chiếc servo giá rẻ không biết cách giữ giới hạn chuyển động của chúng rất tốt, điều này có thể gây ra tiếng ù / rung bạn đang đề cập. Tuy nhiên, nếu bạn chỉ giới hạn phạm vi của chúng ở mức 10 ~ 170 độ, vấn đề sẽ được khắc phục.

Nếu điều đó không đủ tốt cho bạn, bạn có thể thực hiện theo các bản sửa lỗi phức tạp hơn được đề cập trong các câu trả lời khác, như công suất tốt hơn, cảm biến servo tốt hơn, v.v.


Có, đối với SG90 của tôi, các giá trị này là 18 đến 162. Nó thực sự không thể thực hiện được 32 độ, có thể chỉ bằng một nửa.
Maxim Kachurovskiy

5

Tôi đã khắc phục sự cố của mình bằng cách "tắt servo" sau khi tôi di chuyển nó. Thí dụ:

pinMode(PIN, OUTPUT);
myservo.write(degree);
//give servo time to move
delay(5000);
pinMode(PIN, INPUT);

PINlà chân PWM được kết nối với servo của bạn. bằng cách chuyển nó sang chế độ Nhập liệu tôi có thể tắt rung. Đây không phải là giải pháp tối ưu và tôi khuyên bạn nên thử các giải pháp khác trước.


Tôi đã thử các giải pháp khác, đây là giải pháp duy nhất hoạt động, +1. Ý tưởng tuyệt vời khi tất cả những thứ khác thất bại!
Snappawapa

3

Tôi gặp vấn đề tương tự với MG90S servo (jittering), các đường tín hiệu của tôi tương đối dài (60 ~ 70cm), đặt tụ 103 (10nF) trên tín hiệu và các đường dây đất đã khắc phục sự cố cho tôi (Tôi đặt tụ điện ở đâu đó trong ở giữa, tại điểm mà cáp servo gốc kết nối với cáp bên trong của tôi).

Ngoài ra, tôi không thể sử dụng thư viện Servo tiêu chuẩn vì bộ định thời đầu tiên mà nó lấy trên Arduino Mega là Timer-5 và tôi cần điều đó để đo tần số. Khi tôi chỉ sử dụng 10 servo, tôi đã trích xuất mã khóa từ thư viện Servo và đổi nó thành sử dụng Timer-1 (mỗi bộ định thời hỗ trợ tối đa 12 servo trên Mega).

Mã độc lập ở dưới để tham khảo, nếu bạn muốn đưa nó vào dự án của riêng mình thì bạn chỉ có thể sử dụng phần trên cùng, phần dưới là để kiểm tra phần trên cùng (nó lắng nghe trên cổng nối tiếp, bạn có thể cung cấp cho sX và các lệnh vX, trong đó sX chọn một servo, s0 sẽ chọn servo đầu tiên, vX đặt vị trí servo trong chúng ta, vì vậy v1500 sẽ đặt servo0 ở vị trí chính giữa, giả sử bạn đã đưa ra lệnh trước tiên).

//----------------------------------------------------------------
// This is the actual servo code extracted from the servo library
//----------------------------------------------------------------

#include <avr/pgmspace.h>

//----converts microseconds to tick (assumes prescale of 8)
#define usToTicks(_us)    (( clockCyclesPerMicrosecond()* _us) / 8)

#define MIN_PULSE_WIDTH     544     // the shortest pulse sent to a servo  
#define MAX_PULSE_WIDTH     2400    // the longest pulse sent to a servo 
#define DEFAULT_PULSE_WIDTH 1500    // default pulse width when servo is attached
#define REFRESH_INTERVAL    20000   // minumim time to refresh servos in microseconds

#define TRIM_DURATION       2       // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009

struct s_servar {
    //----counter for the servo being pulsed for each timer (or -1 if refresh interval)
    int8_t  channel;
};
static volatile struct s_servar gl_vars;

//----maximum number of servos controlled by one timer 
#define SERVOS_PER_TIMER    12
//----this can not be higher than SERVOS_PER_TIMER
#define SERVO_AMOUNT        6

struct s_servo {
    volatile unsigned int   ticks;
    unsigned char           pin;
};
struct s_servo  gl_servos[SERVO_AMOUNT] = {
    { usToTicks(DEFAULT_PULSE_WIDTH), 22 },
    { usToTicks(DEFAULT_PULSE_WIDTH), 23 },
    { usToTicks(DEFAULT_PULSE_WIDTH), 24 },
    { usToTicks(DEFAULT_PULSE_WIDTH), 25 },
    { usToTicks(DEFAULT_PULSE_WIDTH), 26 },
    { usToTicks(DEFAULT_PULSE_WIDTH), 27 },
};

ISR(TIMER1_COMPA_vect) {
    unsigned char       servooff;
    if(gl_vars.channel < 0 ) {
        //----channel set to -1 indicated that refresh interval completed so reset the timer
        TCNT1 = 0;
    }
    else{
        servooff = gl_vars.channel;
        if(servooff < SERVO_AMOUNT) {
            //----end the pulse
            digitalWrite(gl_servos[servooff].pin, LOW);
        }
    }
    //----increment to the next channel
    gl_vars.channel++;
    servooff = gl_vars.channel;
    if(servooff < SERVO_AMOUNT) {
        //----set timer interrupt for pulse length
        OCR1A = TCNT1 + gl_servos[servooff].ticks;
        //----start the pulse
        digitalWrite(gl_servos[servooff].pin, HIGH);
    }
    else {
        // finished all channels so wait for the refresh period to expire before starting over
        //----allow a few ticks to ensure the next OCR1A not missed
        if(((unsigned)TCNT1) + 4 < usToTicks(REFRESH_INTERVAL)) {
            OCR1A = (unsigned int)usToTicks(REFRESH_INTERVAL);
        }
        else {
            //----at least REFRESH_INTERVAL has elapsed
            OCR1A = TCNT1 + 4; 
        }
        //----this will get incremented at the end of the refresh period to start again at the first channel
        gl_vars.channel = -1;
    }
}

void InitServoISR() {
    unsigned char   ct;
    gl_vars.channel = -1;
    //----init timer 1
    TCCR1A = 0;             // normal counting mode
    TCCR1B = _BV(CS11);     // set prescaler of 8
    TCNT1 = 0;              // clear the timer count
    TIFR1 |= _BV(OCF1A);    // clear any pending interrupts;
    TIMSK1 |= _BV(OCIE1A);  // enable the output compare interrupt
    //----set all servo pins to output
    for(ct = 0; ct < SERVO_AMOUNT; ct++) {
        pinMode(gl_servos[ct].pin, OUTPUT); 
    }
}

void SetServoMicroSecs(unsigned char servooff, unsigned short value) {
    uint8_t oldSREG;
    if(servooff < SERVO_AMOUNT) {
        //----ensure pulse width is in range
        if(value < MIN_PULSE_WIDTH) { value = MIN_PULSE_WIDTH; }
        else {
            if(value > MAX_PULSE_WIDTH) { value = MAX_PULSE_WIDTH; }
        }
        value -= TRIM_DURATION;
        value = usToTicks(value);
        oldSREG = SREG;
        cli();
        gl_servos[servooff].ticks = value;
        SREG = oldSREG;
    }
}

//------------------------------------------------
// This is code to test the above servo functions
//------------------------------------------------

#define ERR_OK          0
#define ERR_UNKNOWN     1
#define ERR_OUTOFRANGE  2

#define SERDEBUG_CODE
#define MAX_SER_BUF     12

void setup() { 
    InitServoISR();

    #ifdef SERDEBUG_CODE
    Serial.begin(9600);
    Serial.println(F("Start"));
    #endif
}


void loop() {
    #ifdef SERDEBUG_CODE
    uint8_t         ct, chr;
    char            buf[MAX_SER_BUF];
    ct = 0;
    #endif   
    //----main while loop
    while(1) {
        #ifdef SERDEBUG_CODE
        //--------------------
        // Serial Port
        //--------------------
        while (Serial.available() > 0) {
            chr = Serial.read();
            if(chr == '\n') {
                ProcSerCmd(buf, ct);
                ct = 0;
            }
            else {
                //----if for some reason we exceed buffer size we wrap around
                if(ct >= MAX_SER_BUF) { ct = 0; } 
                buf[ct] = chr;
                ct++;
            }
        }
        #endif
    }
}

//------------------------------
// Serial Port Code
//------------------------------

#ifdef SERDEBUG_CODE
uint16_t RetrieveNumber(char *buf, uint8_t size) {
    //--------------------------------------------------------------
    // This function tries to convert a string into a 16 bit number
    // Mainly for test so no strict checking
    //--------------------------------------------------------------
    int8_t  ct;
    uint16_t    out, mult, chr;
    out = 0;
    mult = 1;
    for(ct = size - 1; ct >= 0; ct--) {
        chr = buf[ct];
        if(chr < '0' || chr > '9') { continue; }
        chr -= '0';
        chr *= mult;
        out += chr;
        mult *= 10;
    }
    return(out);
}

void ProcSerCmd(char *buf, uint8_t size) {
    //-----------------------------------------------------------
    // supported test commands
    // sX   X = 0 to SERVO_AMOUNT       Sets the servo for test
    // vX   X = MIN to MAX PULSE WIDTH  Sets the test servo to value X
    //-----------------------------------------------------------
    static unsigned char    lgl_servooff = 0;
    uint8_t                 chr, errcode;
    uint16_t                value;
    errcode = 0;
    while(1) {
        chr = buf[0];
        //----test commands (used during development)
        if(chr == 's') {
            value = RetrieveNumber(buf + 1, size - 1);
            if(value < 0 || value >= SERVO_AMOUNT) { errcode = ERR_OUTOFRANGE; break; }
            lgl_servooff = (unsigned char)value;
            break;
        }
        if(chr == 'v') {
            value = RetrieveNumber(buf + 1, size - 1);
            if(value < MIN_PULSE_WIDTH || value > MAX_PULSE_WIDTH) { errcode = ERR_OUTOFRANGE; break; }
            SetServoMicroSecs(lgl_servooff, value);
            break;
        }
        errcode = ERR_UNKNOWN;
        break;
    }
    if(errcode == 0) {
        Serial.println(F("OK"));
    }
    else {
        Serial.write('E');    
        Serial.println(errcode);
    }
}
#endif

2

Tùy chọn tốt nhất của tôi trong trường hợp này là gắn và tách Servos trong mỗi thao tác.

servo1.attach(pinServo1);
for (pos = 0; pos <= servoMax; pos += 1) {
    servo1.write(pos);
    delay(10);
}
servo1.detach(pinServo1);

Tái bút Điều này thực sự không có chất lượng, chỉ là một cách giải quyết.


1

Trong khi những người khác đã đề xuất các giải pháp khác nhau cho vấn đề ù servo này, trong chủ đề này và các diễn đàn Arduino khác, cụ thể là:

  • Tạo xung riêng
  • Cung cấp nguồn 5V riêng
  • Tránh đẩy đến giới hạn của nó (ví dụ: sử dụng 10-170 thay vì 0-180)
  • Chạy một tụ điện trên
  • Tháo ra sau khi di chuyển

Trong trường hợp của tôi, tôi thấy rằng tiếng ù đã dừng khi nguồn điện 9V / 2A được cắm vào bo mạch Arduino. Nhưng giải pháp cuối cùng dễ dàng nhất chỉ đơn giản là di chuyển servo chậm:

for (pos = servo.read(); pos < 180; pos += 2) {
  servo.write(pos);
  delay(40);
}

YMMV.


1
#include <Servo.h>             //Servo library
Servo servo_test;        //initialize a servo object for the connected servo  

int angle = 0;
int sw1 = 7;   // pushbutton connected to digital pin 7
int val=0;

void setup()
{
   servo_test.attach(2);     // attach the signal pin of servo to pin2 of arduino
   pinMode(sw1, INPUT_PULLUP);
}

void loop()
{
    val = digitalRead(sw1);
    if (val == LOW)
    {  
        servo_test.attach(2);     // attach the signal pin of servo to pin2 of arduino
        for(angle = 0; angle < 90; angle += 1)   // command to move from 0 degrees to 90 degrees 
        {                                  
            servo_test.write(angle);                 //command to rotate the servo to the specified angle
            delay(5);                     
        } 
    }
    else
    {
        servo_test.detach();// After servo motor stops we need detach commmand to stop vibration
    }
}

0

Đối với tôi, điều này trông giống như lỗi hoặc điều chỉnh sai của vòng phản hồi. Hệ thống điều khiển servo cao cấp có một số kiến ​​thức về các đặc tính của động cơ (độ tự cảm, mô-men xoắn, dòng điện cực đại, số cực), tải (mô-men quán tính) và các điều kiện tức thời (vị trí, vòng / phút, back-emf, dòng điện). Với thông tin này, chương trình điều khiển động cơ có thể đưa ra dự đoán về những gì servo sẽ làm để đáp ứng với đầu vào đã cho từ bộ điều khiển (tức là đầu vào hiện tại / điện áp) và trên cơ sở đó tạo ra đầu vào tối ưu để đạt được đầu ra mong muốn.

Như bạn có thể tưởng tượng, đây là một thứ hơi phức tạp, nhưng một tìm kiếm trên internet về phản hồi servo sẽ giúp bạn bắt đầu.

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.