Прерывания

Тема в разделе "Arduino & Shields", создана пользователем Kosss, 19 ноя 2013.

  1. Kosss

    Kosss Нерд

    Собрал я машинку с 2мя датчиками линии. И заливаю вот такую прогу:
    Код (Text):
    int value;
    int linel=0;
    int liner=1;

    void FORWARD()
    {
    digitalWrite(4,LOW);
    digitalWrite(7,LOW);
    analogWrite(6,0);
    analogWrite(5,0);
    }

    void LINE()
    {
    digitalWrite(4,HIGH);//остановились
    digitalWrite(7,HIGH);
    analogWrite(6,0);
    analogWrite(5,0);
    delay(30);
    digitalWrite(4,HIGH);//отъехали назад
    digitalWrite(7,HIGH);
    analogWrite(6,255);
    analogWrite(5,255);
    delay(300);
    digitalWrite(4,LOW);//развернулись
    digitalWrite(7,HIGH);
    analogWrite(6,255);
    analogWrite(5,255);
    delay(500);
    }

    void setup()
    {
    pinMode(4,OUTPUT);
    pinMode(7,OUTPUT);
    attachInterrupt(linel,LINE,LOW);
    attachInterrupt(liner,LINE,LOW);
    }

    void loop()
    {
    FORWARD;
    }
    Ну а машинка крутится на месте. Подозреваю, что дело в прерываниях.
     
  2. fr0ster

    fr0ster Гик

    Попробуйте цикл написать так
    void loop()
    {
    FORWARD();
    }
     
  3. Kosss

    Kosss Нерд

    Неа все равно крутит не в ту сторону
    Но функция Forward описана правильно. Если только ее запустить, то он едет вперед
     
  4. Megakoteyka

    Megakoteyka Оракул Модератор

    Так ведь обработчик прерывания один и тот же на оба пина.
    Какой бы пин не выдал прерывание, поворот всегда в одну и ту же сторону будет.
    Не в этом ли дело?
     
  5. Kosss

    Kosss Нерд

    И еще вопрос. delay не работает. Чем его заменить в прерываниях?
     
  6. Megakoteyka

    Megakoteyka Оракул Модератор

    Функция delay() в обработчиках прерывания вообще работать не должна, т.к. в прерывании не происходит увеличение значения счетчика таймера. Нужно в прерывании только флаги ставить, а всю обработку производить в основном цикле программы.
     
  7. fr0ster

    fr0ster Гик

    поставьте _delay_ms() не забудьте только инклюд добавить <util/delay.h>
     
  8. fr0ster

    fr0ster Гик

    Если обработка не сильно тактоедная и нагружающая, то в основном цикле лучше в спячку уводить МК, а обработку в прерывании производить. А если обработка длинная, то в начале обработки прерывания запрещать, в конце снова разрешать.
     
  9. Megakoteyka

    Megakoteyka Оракул Модератор

    Можно же в основном цикле делать обработку, затем засыпать, а просыпаться по прерыванию.
    А так да, сильно зависит от конкретной задачи и вкуса программиста :)
    Если часто приходят разные прерывания - то работать нужно по флагам, иначе можно и не успеть или пропустить.
     
  10. fr0ster

    fr0ster Гик

    Если обработка не особо сложная и запускаема по одному прерыванию, то да, а если нужно несколько прерываний отследить, то начинается свистопляска с бубном. ИМХО если нет необходимости делать иначе, писать нужно проще для понимания, а понять код с прерываниями мне кажется проще, чем длинную процедуру обработки.
     
  11. Megakoteyka

    Megakoteyka Оракул Модератор

    Опять же, зависит от личных предпочтений и условий конкретной задачи.
    Часто бывает необходимо поймать прерывание, но обработать его только в определенный момент.
    Но делать в прерывании задержки я бы точно не стал, это противоречит всем моим внутренним убеждениям и опыту :)
     
  12. fr0ster

    fr0ster Гик

    Тут таки да, все от задачи и от личных предпочтений.
    Если отлов прерывания и обработка разнесена по времени, то нужно состояния хранить и тп и тд.
    То есть уже можно не изобретать велосипед, а пользоваться классическими подходами.
     
  13. Kosss

    Kosss Нерд

    Вот что в итоге получилось(я там еще дальномер добавил)
    Код (Text):
    #include <SoftwareSerial.h>

    #include <URMSerial.h>




    URMSerial urm;

    int value;
    int linel=0;
    int liner=1;
    volatile int state = LOW;

    int getMeasurement()
    {
        // Request a distance reading from the URM37
        switch(urm.requestMeasurementOrTimeout(DISTANCE, value)) // Find out the type of request
        {
            case DISTANCE: // Double check the reading we recieve is of DISTANCE type
                //    Serial.println(value); // Fetch the distance in centimeters from the URM37
                return value;
                break;
            case TEMPERATURE:
                return value;
                break;
            case ERROR:
                Serial.println("Error");
                break;
            case NOTREADY:
                Serial.println("Not Ready");
                break;
            case TIMEOUT:
                Serial.println("Timeout");
                break;
        }

    }

    void FORWARD()
    {
    digitalWrite(4,LOW);
    digitalWrite(7,LOW);
    analogWrite(6,255);
    analogWrite(5,255);
    }

    void LINE()
    {
    state=HIGH;
    digitalWrite(4,HIGH);
    digitalWrite(7,LOW);
    analogWrite(6,200);
    analogWrite(5,255);

    }

    void setup()
    {
    urm.begin(11,10,9600);
    pinMode(4,OUTPUT);
    pinMode(7,OUTPUT);
    attachInterrupt(linel,LINE,LOW);
    attachInterrupt(liner,LINE,LOW);
    }

    void loop()
    {
    if (state==HIGH)
    {
      state=LOW;
      delay(500);
    }
    while (getMeasurement()>40)
    {
      FORWARD();
    }
    while (getMeasurement()<40)
    {
      digitalWrite(4,LOW);
    digitalWrite(7,HIGH);
    analogWrite(6,255);
    analogWrite(5,255);
    }
    }
     
     
  14. Megakoteyka

    Megakoteyka Оракул Модератор

    Осталось только код отформатировать и откомментировать, а также заменить магические числа переменными с понятными именами. Тогда другие пользователи смогут понять Ваш код, а не строить догадки.
    Кстати, почему while, а не if?