Arduino+PIR+Motor Shield+Мотор-редуктор

Тема в разделе "Arduino & Shields", создана пользователем exposity, 14 сен 2014.

  1. exposity

    exposity Нуб

    Здраствуйте.

    Не могу найти примера для того, чтобы на его базе написать скетч. Может, кто-то поможет советом.
    Я хочу сделать следующее: подключаем к ардуино датчик движения, мотор-шилд и мотор-редуктор к мотор-шилду. Когда датчик улавливает движение, он отдает команду шилду, что мотор должен вращаться (допустим 2000сек по ч.с.).

    Как управлять моторами с помощью шилда я использую такой код:

    #define SPEED_LEFT 6
    #define SPEED_RIGHT 5
    #define DIR_LEFT 7
    #define DIR_RIGHT 4

    void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight, int duration)
    {
    analogWrite(SPEED_LEFT, speedLeft);
    analogWrite(SPEED_RIGHT, speedRight);
    digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH);
    digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH);
    delay(duration);
    }

    void setup()
    {

    for(int i = 5; i <= 8; i++)
    pinMode(i, OUTPUT);
    }

    void loop()
    {

    go(255, 0, true, false, 2000);
    }

    а вот как написать скетч для PIR сенсора, чтобы он включал мотор... Можно ли управляющий скетч вписать в голове моего скетча управления моторами? Pir-сенсор подключается при этом к ардуино или к шилду?
    И еще вопрос: можно ли вместо времени вращения для мотора указать градусы поворота? Как это сделать...
     
  2. vvr

    vvr Инженерище

    PIR сенсор подключается к ардуине.
    Полазив по форумам найдёте кучу примеров работы с ним.
    Когда всё слепите и будут непонятки - тогда вопросы в студию.
    Для поворота моторов на градусы нужен или шаговый двигатель или dc мотор с энкодером высокого разрешения плюс программа для считывания данных с энкодера и перевод в градусы.
    С шаговиком проще - там легче оперировать с шагами и к ним привязать градусы.
     
  3. geher

    geher Гуру

    Градусы поворота можно задать для шагового двигателя (через количество шагов) или сервы (которая обычная, 0-180 градусов). Для обычного коллекторного двигателя даже с энкодером не хватит реакции системы, чтобы точно его остановить.
    Pir сенсор подключается к пину ардуины. Если подключен шилд, то транзитом через шилд. Главное, не использовать пины, задействованные шилдом (в случае мотора 4, 5, 6, 7), чтобы не мешать шилду.
    Pir лучше проверять через прерывание (т.е. подклбючать к пину 2 или 3). В теории прерывание
    Соответственно, в прерывании устанавливать значение переменной, а в loop реагировать на это значение, делать дело, сбрасывать значение.
    Что-то вроде такого:
    Код (Text):


    volatile int motionsensoron=1; // 1-ожидание, 0-пауза, 2-сработало
    unsigned long int motionsensorontime=0;
    #define SPEED_LEFT 6
    #define SPEED_RIGHT 5
    #define DIR_LEFT 7
    #define DIR_RIGHT 4

    // задержка на 2000 с= 2000000 мс
    #define MOTO_DURATION 2000000

    void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight)
    {
       analogWrite(SPEED_LEFT, speedLeft);
       analogWrite(SPEED_RIGHT, speedRight);
       digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH);
       digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH);
    }
    void stop()
    {
       go(0, 0, true, false);
    }

    void setup()
    {
       Serial.begin(9600)l;
       pinMode(3, INPUT); // сенсор к третьему пину, прерывание1
       attachInterrupt(1, MotionSensorInterrupt, RISING);
    }
    void loop()
    {
       if (motionsensoron==2) {
          motionsensoron=0;
          Serial.println("Motion Sensor ON!");
          go(255, 0, true, false);
          Serial.println("Motion sensor sleep");
          motionsensorontime=millis();
       }
       if (motionsensoron==0) {
          if ((millis()-motionsensorontime)>=MOTO_DURATION) {
             motionsensoron=1;
             stop();
             Serial.println("Motion sensor ready");
          }
       }
    }

    void MotionSensorInterrupt()
    {
      if (motionsensoron==1) motionsensoron=2;
    }
     
     
  4. exposity

    exposity Нуб

    Спасибо за ответы. Скажите , пожалуйста, в даном коде если я подключу действие второго мотора таким образом:
    volatile int motionsensoron=1; // 1-ожидание, 0-пауза, 2-сработало
    unsigned long int motionsensorontime=0;
    #define SPEED_LEFT 6
    #define SPEED_RIGHT 5
    #define DIR_LEFT 7
    #define DIR_RIGHT 4

    // задержка на 2000 с= 2000000 мс
    #define MOTO_DURATION 2000000

    void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight, int duration)
    {
    analogWrite(SPEED_LEFT, speedLeft);
    analogWrite(SPEED_RIGHT, speedRight);
    digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH);
    digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH);
    }
    void stop()
    {
    go(0, 0, true, false);
    }

    void setup()
    {
    Serial.begin(9600)l;
    pinMode(3, INPUT); // сенсор к третьему пину, прерывание1
    attachInterrupt(1, MotionSensorInterrupt, RISING);
    }
    void loop()
    {
    if (motionsensoron==2) {
    motionsensoron=0;
    Serial.println("Motion Sensor ON!");
    go(255, 0, true, false, 10000);
    go(0, 255, true, true, 10000);
    go(0, 255, true, true, 10000);
    go(255, 0, false, true, 10000);
    Serial.println("Motion sensor sleep");
    motionsensorontime=millis();
    }
    if (motionsensoron==0) {
    if ((millis()-motionsensorontime)>=MOTO_DURATION) {
    motionsensoron=1;
    stop();
    Serial.println("Motion sensor ready");
    }
    }
    }

    void MotionSensorInterrupt()
    {
    if (motionsensoron==1) motionsensoron=2;
    }


    Таким образом, по моей задумке, последовательность действий такая: срабатывает датчик движения, он дает команду первому мотору вращаться 10сек, после этого первый мотор отключается, вращается второй мотор 10сек., потом второй мотор вращается 10сек. в обратном направлении, останавливается, вращается первый мотор 10сек в обратном направлении. Правильно? Работать будет, как вы думаете?
     
  5. exposity

    exposity Нуб

    тут я ошыбочку допустил будет так:
    go(255, 0, true, false, 10000);
    go(0, 255, true, true, 10000);
    go(0, 255, true, false, 10000);
    go(255, 0, false, true, 10000);
     
  6. geher

    geher Гуру

    В данном варианте кода передавать длительность в go бессмысленно.
    Нужно или обрабатывать длительности и переходы между состояниями в блоке
    if (motionsensoron==0)
    или вернуть delay(duration); в go и выкинуть все, что связано с обработкой состояний.
    Если самый простой вариант, то получится примерно так:
    Код (Text):
    volatile int motionsensoron=1; // 1-ожидание, 0-пауза, 2-сработало
    #define SPEED_LEFT 6
    #define SPEED_RIGHT 5
    #define DIR_LEFT 7
    #define DIR_RIGHT 4
    // задержка на 2000 с= 2000000 мс
    #define MOTO_DURATION 2000000
    void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight, int duration)
    {
      analogWrite(SPEED_LEFT, speedLeft);
      analogWrite(SPEED_RIGHT, speedRight);
      digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH);
      digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH);
      delay(duration);
      analogWrite(SPEED_LEFT, 0);
      analogWrite(SPEED_RIGHT,0);
    }
    void stop()
    {
      go(0, 0, true, false);
    }
    void setup()
    {
      Serial.begin(9600);
      pinMode(3, INPUT); // сенсор к третьему пину, прерывание
      attachInterrupt(1, MotionSensorInterrupt, RISING);
    }
    void loop()
    {
      if (motionsensoron==2) {
          motionsensoron=0;
          Serial.println("Motion Sensor ON!");
          Serial.println("Motion sensor sleep");
          go(255, 0, true, false, 10000);
          go(0, 255, true, true, 10000);
          go(0, 255, true, false, 10000);
          go(255, 0, false, true, 10000);
          motionsensoron=1;
      }
    }
    void MotionSensorInterrupt()
    {
      if (motionsensoron==1) motionsensoron=2;
    }
     
    Последнее редактирование: 14 сен 2014
  7. exposity

    exposity Нуб

    В этом месте проверка кода требует добавить значение duration
    void stop()
    {
    go(0, 0, true, false);
    }

    Нужно ли здесь указать время остановки? Например, 2сек.
    void stop()
    {
    go(0, 0, true, false, 2000);
    }


    И, насколько правильно я понял код, теперь у нас должна быть последовательность: сенсор сработал, переключился в режим паузы, закрутился первый мотор в одну сторону 10сек., остановился, закрутился второй мотор в одну сторону 10сек., закрутился второй мотор 10сек. в обратную сторону, остановился, закрутился первый мотор в обратную сторону, остановился, сенсор перешел в режим ожидания движения.
     
  8. geher

    geher Гуру

    Во втором варианте кода stop можно совсем выкинуть, поскольку он вообще не используется (я просто забыл выкинуть).

    В первом варианте stop был нужен для того, чтобы остановить двигатели потом, за пределами функции go.
    В принципе так же можно было бы реализовать и управление двумя двигателями, добавив количество промежуточных состояний между 0 и 1, соответствующих точкам между остановками и запусками двигателей по заданному алгоритму (). Данный вариант позволяет "нагрузить" программу "параллельными задачами", которые будут выполняться мелкими порциями независимо от того, сработал ли Pir, работают ли двигатели, или нет.
    Примерно так получаем третий вариант (возможны ошибки, набрасывал без проверки):
    Код (Text):


    volatile int motionsensoron=1; // 1-ожидание, 2-сработало 0- первый 3-второй 4-второй назад 5-первый назад
    // 3,4,5 между 0 и 1
    unsigned long int motionsensorontime=0;
    #define SPEED_LEFT 6
    #define SPEED_RIGHT 5
    #define DIR_LEFT 7
    #define DIR_RIGHT 4

    // задержка на 2000 с= 2000000 мс
    #define MOTO_DURATION 10000

    void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight)
    {
       analogWrite(SPEED_LEFT, speedLeft);
       analogWrite(SPEED_RIGHT, speedRight);
       digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH);
       digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH);
    }
    void stop()
    {
       go(0, 0, true, false);
    }

    void setup()
    {
       Serial.begin(9600)l;
       pinMode(3, INPUT); // сенсор к третьему пину, прерывание1
       attachInterrupt(1, MotionSensorInterrupt, RISING);
    }
    void loop()
    {
       if (motionsensoron==2) {
          motionsensoron=0;
          Serial.println("Motion Sensor ON!");
          go(255, 0, true, false);
          Serial.println("Motion sensor sleep");
          motionsensorontime=millis();
       }
       if (motionsensoron==0) {
          if ((millis()-motionsensorontime)>=MOTO_DURATION) {
             motionsensoron=3;
             go(0, 255, true, true);
            motionsensorontime=millis();
          }
       }
       if (motionsensoron==3) {
          if ((millis()-motionsensorontime)>=MOTO_DURATION) {
             motionsensoron=4;
             go(0, 255, true, false);
             motionsensorontime=millis();
          }
       }
       if (motionsensoron==4) {
          if ((millis()-motionsensorontime)>=MOTO_DURATION) {
             motionsensoron=5;
             go(255, 0, false, false);
             motionsensorontime=millis();  
          }
       }
       if (motionsensoron==5) {
          if ((millis()-motionsensorontime)>=MOTO_DURATION) {
             motionsensoron=1;
             stop();
             Serial.println("Motion sensor ready");
          }
       }
    }

    void MotionSensorInterrupt()
    {
      if (motionsensoron==1) motionsensoron=2;
    }
     
    Во втором варианте в реакции на присваивание двойки переменной состояния реализован полный цикл отработки двигателей по алгоритму с задержками. При этом выполнение программы тормозится, и выполнение любых "параллельных задач" во время отработки двигателей становится невозможным.
    Достоинством второго варианта является то, что он проще.
     
  9. vladis energy

    vladis energy Нуб

    Привет я написал такой скетч для мотор шилд и датчик движения. все работает. если захочешь что то поменять например разворот или движения прямо то в моем скетче все есть.

    #define LED 13
    #define PIR 2
    #define SPEED_LEFT 6
    #define SPEED_RIGHT 5
    #define DIR_LEFT 7
    #define DIR_RIGHT 4

    void go(int speed, bool reverseLeft, bool reverseRight, int duration)
    {
    // Для регулировки скорости `speed` может принимать значения от 0 до 255,
    // чем болше, тем быстрее.
    analogWrite(SPEED_LEFT, speed);
    analogWrite(SPEED_RIGHT, speed);
    digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH);
    digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH);
    delay(duration);
    }
    void setup()
    {
    pinMode(PIR, INPUT);
    pinMode(LED,OUTPUT);
    for(int i = 5; i <= 8; i++)
    pinMode(i, OUTPUT);
    }
    void loop()
    {
    delay(1000);
    int pirVal = digitalRead(PIR);
    if (digitalRead(pirVal) == HIGH)

    if (pirVal == HIGH)
    {
    digitalWrite(LED, HIGH);
    // Задержка 1 секунда после включения питания
    delay(1000);
    // Две секуды вперёд
    go(80, false, false, 1000);

    // Разворот на 180 градусов
    go(125, true, false, 1350);

    // Две секуды вперёд
    go(80, false, false, 1000);

    // Разворот на 180 градусов в другую сторону
    go(125, false, true, 1300);

    // Две секуды вперёд
    go(80, false, false, 1000);

    // Поворот на 90 градусов
    go(125, true, false, 680);

    // Медленно назад полторы секунды
    go(80, true, true, 1000);

    // Две секуды вперёд
    go(80, false, false, 1000);

    // Поворот на 90 градусов
    go(125, true, false, 680);

    // Две секуды вперёд
    go(80, false, false, 1000);

    // Медленно назад полторы секунды
    go(80, true, true, 1000);

    // Остановка до ресета или выключения питания
    go(0, false, false, 0);

    digitalWrite (LED, LOW);

    delay(1000);
    }
    }

    20170127_201606.jpg
     
    Последнее редактирование: 28 янв 2017