реализация конечного автомата для серводвигателей

Я создал FSM для своего сервопривода. Он имеет два состояния. Я использую структуру переключатель/корпус, но в первом случае мотор «застревает», и я не знаю, почему.

Это мой код:

#include <Servo.h>

#define one 1
#define two 2


Servo myservo1; //projector platform servo

unsigned long Timer1; //define timer variable for state 1 if statement

void setup()
{
    myservo1.attach(9);
}

void loop(){

    static int state = one; // initial state is one.

    switch(state)
    {
    case one:
        myservo1.writeMicroseconds(1374); // servo is moving cw
        delay(5000);
        myservo1.writeMicroseconds(1474); // servo is stationary
        Timer1 = millis();
        if (millis() - Timer1 > 5000)
        {
            state = two;
        }
        break;

    case two:
        for(int speedv1 = 0; speedv1 <= 100; speedv1 += 2) // loop to ramp up speed of servos
        {
            myservo1.writeMicroseconds(1474 + speedv1); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (ACW)
            delay(40); // delay between loop iterations
        }
        delay(5000);
        for(int speedv2 = 0; speedv2 <= 100; speedv2 += 2) // loop to ramp down servo speed
        {
            myservo1.writeMicroseconds(1574 - speedv2); // speed decrease by 2 each iteration (servo 1) until servo stops
            delay(40); //delay between loop iterations 
        }
        delay(2000);
        state = one;
        break;
    }
} 

Мотор как будто глохнет

myservo1.writeMicroseconds(1374);

на первой строке case 1.

Под застрявшим я подразумеваю, что двигатель просто продолжает вращаться по часовой стрелке и не переходит к следующему оператору writeMicroseconds() после задержки. Цените помощь.


person user3478004    schedule 30.03.2014    source источник
comment
Я не понимаю, как вы ожидаете, что millis() - Timer1 когда-либо будет чем-то отличным от 0. Поскольку между установкой Timer1 и проверкой того, прошло ли 5 ​​секунд, не прошло времени.   -  person Chris Desjardins    schedule 30.03.2014


Ответы (1)


С этим фрагментом кода в состоянии один:

Timer1 = millis();
if (millis() - Timer1 > 5000)
{
    state = two;
}

невероятно маловероятно, что таймер продвинется на пять секунд вперед между первой и второй строкой. Следовательно, поскольку вы изменяете Timer1 каждый раз, когда запускаете этот фрагмент кода, он всегда будет оставаться в состоянии один.

Хотя неясно, чего именно вы пытаетесь достичь (я не уверен ни в том, что делают вызовы writeMicroSeconds(), ни в вашей потребности в явных задержках внутри самих состояний), давайте пока предположим, что вы хотите оставаться в состоянии один в течение пять секунд, но в это время займитесь чем-нибудь другим. Это означает, что вам нужно инициализировать время начала как часть перехода в состояние 1, а не в самом коде состояния 1.

Например, следующий код показывает один из способов сделать это, непрерывно вращая сервопривод по часовой стрелке в течение пяти секунд, а затем против часовой стрелки в течение четырех (с некоторыми мифическими вызовами для запуска сервопривода):

void loop() {
    static int state = zero;
    static unsigned long timer1;

    switch (state) {
        case zero: {
            timer1 = millis();
            state = one;
            servo.startClockwise();
            break;
        }
        case one: {
            if (millis() - timer1 >= 5000) {
                servo.stop();
                servo.startAntiClockwise();
                timer1 = millis();
                state = two;
            } else {
                doSomethingElse();
            }
            break;
        }
        case two: {
            if (millis() - timer1 >= 4000) {
                servo.stop();
                servo.startClockwise();
                timer1 = millis();
                state = one;
            } else {
                doSomethingElse();
            }
            break;
        }
    }
}
person paxdiablo    schedule 12.01.2015