Автоматизировать солнцезащитный козырек с помощью шагового двигателя Nema17

Я новичок в Arduino (и, пожалуйста, извините за мой плохой макет). Я пытаюсь автоматизировать свой солнцезащитный козырек во внутреннем дворике, в конечном итоге он будет включать фотоэлемент, но сначала я хотел получить подтверждение концепции с помощью кнопок. Первая и последняя кнопки представляют собой концевые выключатели, а средняя кнопка представляет собой тумблер (который в конечном итоге станет фотоэлементом).

Примером того, что я пытаюсь сделать, является; Если переключатель верхнего предела активен, и я нажимаю кнопку переключения, шаговый двигатель работает до тех пор, пока не достигнет переключателя нижнего предела, если переключатель нижнего предела активен, и я нажимаю кнопку переключения, то шаговый двигатель должен работать в другом направлении, пока не достигнет переключателя верхнего предела.

У меня есть последовательные отпечатки, чтобы показать, что происходит, если я удерживаю один из "концевых выключателей", то на последовательном мониторе отображается (скорее, спам) соответствующая строка печати, однако шаговый двигатель движется не так, как я ожидал бы. Я должен держать концевой выключатель и удерживать переключатель, чтобы он двигался в определенном направлении, даже если он движется примерно на 1 шаг в секунду. Если я отпущу концевой выключатель и продолжу удерживать переключатель, то шаговый механизм сделает шаг назад и шаг вперед на то время, пока я нажимаю переключатель. Код, который у меня есть, основан на том, что кто-то пытается сделать то же самое, но с двигателем постоянного тока, я попытался приспособить его к шаговому двигателю, и у меня возникли проблемы.

    // constants won't change. They're used here to set pin numbers:
const int uplimitPin = 9;     // pin number for upper limit switch
const int togglebuttonPin = 10;     // pin number for the toggle switch
const int downlimitPin = 11;     // pin number for the lower limit switch
const int dirPin =  2;      // direction pin for stepper
const int stepPin =  3;      // step pin for stepper

// variables will change:
boolean uplimitState = 0;         // variable for reading the status of the upper limit switch
boolean togglebuttonState = 0;         // variable for reading the toggle switch status
boolean downlimitState = 0;   // variable for reading the status of the lower limit switch


int shadePosition = 2;  // Tells progam what position the shade is in


/**
 *  setup inputs for switches and outs for motor pins
 *  serial begin to read the switches to test for errors
 */
void setup() {
    // initialize the stepper pins as outputs:
    pinMode(dirPin, OUTPUT);
    pinMode(stepPin, OUTPUT);
    // initialize the pushbutton pins as an inputs:
    pinMode(uplimitPin, INPUT);
    pinMode(togglebuttonPin, INPUT);
    pinMode(downlimitPin, INPUT);
    Serial.begin(9600);
}

/**
 * this function turns motor foward 
 */
void shadeDown() {
     // turn motor foward:
    digitalWrite(dirPin, HIGH);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
}

/**
 * this function turns motor backwards
 */
void shadeUp() {
     // turn motor in other direction:
    digitalWrite(dirPin, LOW);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);  
}

/**
 * Stop the motor form moving
 */
void stopShade() {
  digitalWrite(stepPin, LOW);

}


/**
 * 
 */
void loop() {
   // read the state of the pushbutton value:
   uplimitState = digitalRead(uplimitPin);
   togglebuttonState = digitalRead(togglebuttonPin);
   downlimitState = digitalRead(downlimitPin);



   // check if the limit is active. If it is, the limitState is HIGH:
   if (uplimitState == HIGH) {
      shadePosition = 2; 
      Serial.println(F("The shade is up")); 
      stopShade();
   }else if (downlimitState == HIGH) {
      shadePosition = 1;
      Serial.println(F("The shade is down"));        
      stopShade();
  } 

  if (togglebuttonState == HIGH) {
    if( shadePosition  == 1 ){
      shadeUp(); 
      delay(100);      
      shadePosition = 2;
      delay(100);  
    }else if (shadePosition == 2 ) {
      delay(100); 
      shadeDown();
      delay(100); 
      shadePosition = 1;       
    }

  }
}

, 👍1


2 ответа


0

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

Кнопки "отскакивают" (не совсем, но их выходной сигнал выглядит так, как будто они отскакивают). Что касается концевых выключателей, вам на самом деле все равно - первый шаг (и я предполагаю положительную логику, для простоты обсуждения) говорит вам, что оттенок достиг своего предела, и вам не нужно (вероятно, не следует!) Ждать, пока переключатель установится, прежде чем останавливать оттенок. "Обрыв" концевого выключателя неинтересен, за исключением, возможно, подтверждения того, что тень движется, когда вы этого ожидали, и опять же, кого волнуют отскоки? Но отскоки кнопки переключения вполне могут сбить с толку вашу логику, если вы не откажетесь от нее (это можно сделать либо электрически, либо с помощью программного обеспечения - найдите тему). И даже несмотря на то, что конечный фотоэлемент может не отскочить (или может: есть ли в его поле зрения тенистые деревья, f/ex?), Прямо сейчас вы тестируете с помощью кнопки, которая, безусловно, делает это.

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

Диаграммы состояния оказываются одним из лучших инструментов, которые разработчик программного обеспечения должен сообщать детали предлагаемой системы управления между ними и обычно не обученными программному обеспечению людьми, которые являются экспертами в создании и/или использовании автоматизируемых устройств (например, печатные станки, копировальные аппараты, сборочные роботы,....). На картинке все сказано.

,

1

Машина состояния Системы

Как и предполагал Жробер, State Machine сделала бы код намного чище! Ниже приведен некоторый псевдокод (я оставлю отладку на ваше усмотрение ;)) о том, как вы могли бы это настроить.

Когда вы разбиваете свою систему на 4 отдельных состояния, легко понять, что должно происходить в каждом состоянии и что требуется для перехода в следующее состояние. Вы можете нарисовать диаграмму, показывающую это (google "State Machine"), чтобы помочь вам рассуждать.

...

enum SystemState {
    SystemState_Opening,
    SystemState_Closing,
    SystemState_Open,
    SystemState_Closed
};

void main()
{
    // Установить начальное состояние
    SystemState state;
    if (digitalRead(upLimitState))
    {
        state = SystemState_Closed;
    }
    else
    {
        state = SystemState_Open;
    }

    // Запуск state machine
    while (1)
    {
        switch (state)
        {
            case SystemState_Closed:
            {
                if (digitalRead(toggleButtonPin))
                {
                    state = SystemState_Opening;
                }
                break;
            }
            case SystemState_Open:
            {
                // ЗАДАЧА: Реализуйте это сами!
                break;
            }
            case SystemState_Closing:
            {
                if (digitalRead(upLimitState))
                {
                    state = SystemState_Closed;
                }
                shadeUp();
                break;
            }
            case SystemState_Opening:
            {
                // ЗАДАЧА: Реализуйте это сами!
                break;
            }
    }
}

Что Не Так С Вашим Кодом

Фактическая проблема с предоставленным вами кодом заключается в том, что вы вызываете функцию shadeUp() только один раз. Вам нужно вызвать его много раз, чтобы послать шаговому контакту много импульсов для вращения двигателя.

Каждый раз, когда вы посылаете импульс на шаговый вывод (например, shadeUp ()), вы поворачиваете двигатель на один шаг (или микрошаг), что, скорее всего, составляет всего 1,8 градуса!

,