Arduino Leonardo + Rover 5(4WD) + 2A Motor Shield

Тема в разделе "Глядите, что я сделал", создана пользователем Sand, 14 мар 2013.

  1. Sand

    Sand Нерд

    Сделано:
    1. Ручное управление. Через Bluetooth shield
    2. Автоматическое управление. По сигналу с 1го ультразвукового дальномера.
    3. Сделать управление с андроид планшета 7"

    В планах:
    1. Добавить еще датчиков для более точного обхода препятствий
    2. Сделать светодиодное освещение, головное + кормы, включающееся по сигналу с фоторезистора или из Android приложения
    3. Добавить лазер

    Всем привет! Поигрался с Ардуинкой, мигание диодов и мини погодная станция с дисплеем 20x4 и датчиком DHT11- пройденный этап. Джереми Блюма всего посмотрел. Решил на этом не останавливаться.
    Собрал потихоньку вот такой комплект: Arduino Leonardo + Rover 5(4 мотора 4 энкодера) + 2A Motor Shield.

    [​IMG]

    [​IMG]
    Подключил, все заработало, не с первого раза, конечно =) Моторы крутятся кто в лес, кто по дрова... один назад, другие вперед. Сняв гусеницы и изменив полярность на одном из моторов удалось синхронизировать. Появилось несколько вопросов.
    1. Мотор шилд идет на 2 мотора(они все обычно идут на 2 мотора, фридуино на 4 уже особо не найти в продаже, да и судя по отзывам, есть в нем баги, или в библиотеке для него). В телеге их - 4. Я так понимаю, просто так за собой таскать заблокированный мотор нельзя. Соответственно нужно просто подключить к контактам М1 последовательно моторы передний левый + задний левый и к М2 передний правый + задний правый? Чем чревато? Или так допускается подключать моторы? Питание внешнее в родном отсеке, 6 батарей по 1,5В
    2. Что за микросхема справа от L298P? L298P это, как я понял, и есть H-мост. Слева от нее группы по 2 - диоды?
    3. Не маловато ли питания для моторов? Скорость выставляется через ШИМ, значения от 0 до 255 с шагом 5, ну как то думал побыстрее будет, не гоночный болид...
    4. Энкодеры - просто обратная связь, можно не подключать по началу?
    5. Джереми Блюм везде говорит - используйте одну землю для всего, свой плюс на ардуинку, свой на моторы, а земля должна быть общая, в описании motor shield тоже написано NOTE: When the motor shield is powered by external power source, make sure the external power source and Arduino have the same GND.
    [​IMG]

    Дык плюс от батарейки на 5 в колодку и минус соответственно. Как тут убедиться, что общая земля у всех?

    Спасибо заранее всем...
    Вот что получилось собрать за вечер наспех(прохлопал, что у телеги нет крышки для крепления электроники, придется где то дозаказывать):
    [​IMG]

    [​IMG]

    Ссылки:
    http://shieldlist.org/dfrobot/2a-motor
    http://www.dfrobot.com/wiki/index.php?title=Arduino_Motor_Shield_(L298N)_(SKU:DRI0009)
    Схема шилда: http://www.dfrobot.com/image/data/DRI0009/Arduino L298 Shield Sch.pdf
    Тележка: http://www.dfrobot.com/index.php?route=product/product&filter_name=rover 5&product_id=470#.UUDv9qWYXjA
     
    HighDigital и nailxx нравится это.
  2. nailxx

    nailxx Официальный Нерд Администратор

    Классно!

    Так и предполагается подключать. К одному каналу — пара с одной стороны.

    Не H-мост — это как раз L298, а микросхема — это стандартная логика, которая позволяет сэкономить количество занятых пинов для контроля самой L298.

    А чёрные квадратики, да, flyback-диоды

    Не, самый раз. Самый «правильный» режим — 7,2 вольта из отсека в котором установлены 6 AA NiMH-аккумуляторов по 1,2 В

    Всё верно

    И снова верно. Минус внешнего источника (батареек) должен быть соединён с GND Arduino. Плата Motor Shield делает это за вас.
     
    Megakoteyka и Sand нравится это.
  3. Sand

    Sand Нерд

    nailxx, Благодарю за разъяснение непонятных мне пока моментов.
    Вообщем оно поехало. Почитал вчера про прерывания и решил повесить на них кнопку. Вроде все получилось, единственное кнопка срабатывает не всегда, похоже на дребезг контактов. Вот думаю, программно решать или замутить кондер + инвертирующий триггер шмитта(Джереми Блюм рекомендует :) ) Ну и надоедает за ним бегать, поворачивать, надо дальномер покупать.




    Один момент непонятен, в дебаге если смотреть, выводы 5 и 6 находятся в нестабильных состояниях, похоже:
    Вот что пишет analogRead(E1) и analogRead(E2)
    Debug Mode
    207
    255
    btnStatu
    202
    255
    btnStatus = LOW
    Debug Mode
    204
    255
    btnStatus = LOW
    Debug Mode
    205
    255
    btnStatus = LOW

    Их, видимо, тоже надо к земле резисторами притягивать... Или здесь что то другое?
    Т.е. данный код в setup ничего не дает:
    Код (Text):
      // Задаем стартовые значения скорости
      analogWrite(E1, 0);
      analogWrite(E2, 0);
    Скетч(телега просто едет вперед):
    Комментарил сам, как понял те или иные моменты. Надеюсь более опытные товарищи поправят, если я где ошибся.
    Код (Text):

    // Переменная, установленная в true
    // используется для отладки алгоритма
    boolean g_debug = true;
     
    int M1 = 4;
    int E1 = 5;
    int E2 = 6;                  
    int M2 = 7;  
     
    int value = 0;
     
    // Один вывод кнопки цепляем к 3му DIGITAL пину,
    // другой к GND
    int btnPin = 3;
     
    // Ключевое слово volatile было разработано для отключения компиляторной оптимизации,
    // которая могла бы привести к неверной работе кода в мультипоточном окружении.
    // К примеру: если переменная базового типа объявлена как volatile, то компилятору не разрешается кэшировать ее в регистре -
    // распостраненная оптимизация, которая может привести к непредсказуемым результатам,
    // если данная переменная используется в нескольких потоках.
    volatile boolean btnStatus = LOW;
     
    void setup()
    {
      if (g_debug)
      {
        Serial.begin(9600);
      }
      pinMode(M1, OUTPUT);
      pinMode(M2, OUTPUT);
      pinMode(E1, OUTPUT);
      pinMode(E2, OUTPUT);
     
      // Задаем направление вращения
      digitalWrite(M1,HIGH);
      digitalWrite(M2, HIGH);
     
      // Задаем стартовые значения скорости
      analogWrite(E1, 0);
      analogWrite(E2, 0);
     
      // INPUT_PULLUP - Притягивает вывод к +5V через внутреннее сопротивление,
      // чтобы зафиксировать стабильный сигнал на выводе
      // В разомкнутом состоянии кнопки фиксируем 1
      pinMode(btnPin, INPUT_PULLUP);
      // Цепляем прерывание на ногу 3(int.0), в моем случае(плата - Leonardo)
      // Режим прерывания - по фронту на спад (когда 1 переходит в 0),
      // используем этот режим, т.к. при замыкании кнопки вывод притягивается к земле(INPUT_PULLUP выше)
      attachInterrupt(0, btn, FALLING);
    }
     
    void loop()
    {
      delay(31);
      if (g_debug)
      {
        Serial.println("Debug Mode");
        Serial.println(map(analogRead(E1), 0, 1023, 0,255));
        Serial.println(map(analogRead(E2), 0, 1023, 0,255));
        if (btnStatus)
        {
          Serial.println("btnStatus = HIGH");
        }
        else
        {
          Serial.println("btnStatus = LOW");
        }
        delay(1000);
      }
      else
      {
        if(btnStatus == LOW && analogRead(E1) > 0)
        {
          analogWrite(E1, 0);  //PWM Speed Control
          analogWrite(E2, 0);  //PWM Speed Control
        }
        else
        if (btnStatus == HIGH)
        // Разгоняем телегу с 0 до макс скорости
        for(value = 0 ; value <= 255; value+=5)
        {
          analogWrite(E1, value);  //PWM Speed Control
          analogWrite(E2, value);  //PWM Speed Control
        }
       
      }
     
    }
     
    void btn()
    {
      btnStatus = !digitalRead(btnPin);
    }
     
  4. nailxx

    nailxx Официальный Нерд Администратор

    `analogRead` — функция для считывания аналогового сигнала с пинов A0-A5. Поэтому в вашем случае вы отлаживаете совершенно не то, что предполагали.
     
  5. Sand

    Sand Нерд

    О как! Я думал, установив значение через ШИМ, можно его считать. Надо внимательно перечитать описание функций. Кстати, обратил внимание, что arduino.ru отстает от arduino.cc. На ру версии нет INPUT_PULLUP, например...

    А не подскажете еще момент, мне тут дребез контактов покоя не дает. Я повесил кнопку на прерывание 0. Пробовал разные варианты программно, никак не выходит. Delay в прерываниях не используется... millis() тоже не работает. Судя по описанию на оф сайте, значение не увеличивается. Соответственно, попытки в while подождать, когда пройдет 100 миллисек или больше ни к чему не приводят. Ардуина просто перезагружается постоянно и все...
    Inside the attached function, delay() won't work and the value returned by millis() will not increment. Serial data received while in the function may be lost. You should declare as volatile any variables that you modify within the attached function.
    Почитал разную инфу на эту тему. Еще раз посмотрел Блюма про кондер и триггер шмитта. Брат подогнал какой то старый кондер на 4,7 мФ 50V, ноги у него по длине одинаковые, но с одного бока стрелка, указывающая на ногу, это минус, если я не ошибаюсь. Воткнул его к кнопке, ногу со стрелкой к ноге кнопки, которая идет на минус, другую ногу соответственно ко второму выводу кнопки. Теперь получаю стабильно то, что нужно. Правильно ли подключил и нужно ли все таки триггер шмитта поставить? Для чего он, из видео Блюма понятно, но работает и так...

    Тестовое подключение кондера, в реальном проекте надо делать по человечески, конечно
    [​IMG]
     
  6. semenko

    semenko Нерд

    прикольно получилось;)
     
    Sand нравится это.
  7. Megakoteyka

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

    Можно и без триггера, кондер сам по себе сглаживает пульсации сигнала.
    А использовать функции задержки в прерывании даже не пытайтесь - это неправильно и вообще зло. Лучше совсем отказаться от использования delay() в программе, есть более красивые способы.
    Чтобы давить дребезг программно, нужно вешать сигнал на обычный цифровой вход, а не на прерывание, и использовать библиотеку Bounce.
     
    nailxx и Sand нравится это.
  8. Sand

    Sand Нерд

    Тоже самое мне сказал товарищ, который давно занимается строительством радиоуправляемых моделей. Никаких delay в рабочем коде, только для отладки. Правда, еще посоветовал забить на ардуинку и переходить на stm32 -))

    Т. Е. Делать надо что то типа этого? Вместо простоя проверяем, прошло ли указанное кол-во времени, при этом делаем что то еще
    Код (Text):
    void loop()
    {
      currentTime = millis();                          // считываем время, прошедшее с момента запуска программы
      if(currentTime >= (loopTime + 1000)){           // сравниваем текущий таймер с переменной loopTime + 1 секунда
        digitalWrite(ledPin, !digitalRead(ledPin));  // включаем/выключаем LED
        loopTime = currentTime;                      // в loopTime записываем новое значение
      }
      // Здесь могут быть другие команды
    }
     
     
  9. Megakoteyka

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

    Именно так, все верно. К чему молотить пустые циклы?
    У СТМ32 есть свои плюсы, есть минусы. Лучший контроллер - тот, которым Вы лучше всего владеете при условии, что он удовлетворяет требованиям задачи (количество ножек, наличие необходимых внутренних модулей, размер памяти, производительность, энергопотребление, стоимость, исполнение в копусе, который можно запаять самостоятельно и т.д.).
    Просто так ни на что забивать не надо, должна быть причина, обоснование выбора.
    Еще немаловажный в некоторых случаях фактор - отлаженность камня. Контроллер, выпускаемый не первое десятилетие, вылечен от всех детских болезней и в целом более надежен, чем свежевывалившийся на рынок продукт. NASA, например, в свое время не просто так искало i386, давно снятые с производства (не ручаюсь за 100% достоверность, но слышал такую историю не раз).
     
  10. Sand

    Sand Нерд

    Вот именно... Все зависит от задачи. А в случае с ардуино немаловажные факторы как простота освоения, наличие библиотек(оптимизация их - вопрос времени, ругают за большие объемы кода на выходе), куча информации, сообщества, примеры кода для работы с реальными устройствами. Да и Arduino Due появился, будет чем заняться после построения танка для дочери на Leonardo =)
     
    Megakoteyka нравится это.
  11. Sand

    Sand Нерд

    Собственно с последнего сообщения трактор(как прозвала его доча) так больше и не ездил, ибо просели батарейки, а затем пришел Bluetooth Shield от Seeedstudio, который вызвал немало вопросов. Впрочем, все проблемы были решены здесь же. По совету nailxx в амперке были куплены аккумуляторы AA ROBITON в количестве 6 штук(сначала знатно пошутили и привезли 6 аккумов типа крона ;-) ), а так же одноименный зарядник к ним. Там же заказал релейный модуль побаловаться, ультразвуковой дальномер и датчик движения, оба последних датчика как раз пригодятся для трактора. По сигналу с датчика движения трактор, по идее, должен будет от меня сваливать, но там видно будет =)
    Пока ехало питалово и датчики, была написана прога для управления роботом на Objective C в XCode под Mac OS. Вчера приехали аккумы и я их установил. Танк поехал, но как то вяленько, как и на батарейках. Почитав в инете, что Rover 5 шасси сами по себе не быстрые, уже было опустил руки и подумал забить на трактор(мысли о свинцовом 12V аккуме появлялись, но это уже перебор), но после ночной зарядки аккумов, сегодня трактор я не узнал... Он лихо разворачивается на месте и с легкостью перелетает через детские тапочки и прочие препятствия, что мне и надо было, на гусеничном ходу проходимость самая высокая + 4 мотора все же... Но все упирается в питание, жрут моторы много. Кстати, напруга на входе в motor shield - >8 В.

    Детальки:
    [​IMG]

    [​IMG]

    Теперь, собственно, программа для управления роботом по Bluetooth. Выглядит это так:
    [​IMG]

    [​IMG]

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

    Видео в движении(лаги при смене направления движения и повороты - недостатки управления с компа, нужен в идеале планшет с сенсорным экраном)

     
  12. nailxx

    nailxx Официальный Нерд Администратор

    Слава батарейкам! :) Отличный трактор у вас вышел.
     
  13. Sand

    Sand Нерд

    Спасибо! Прикручиваем глазки теперь... Я так подозреваю, что одним сенсором я не обойдусь? надо 2-3 где то? Наверное, придется у вас еще пару инфракрасных заказать =)
    [​IMG]
     
    sqr93 и Megakoteyka нравится это.
  14. Sand

    Sand Нерд

    Какая то странная проблема с вращением левого и правого борта в разные стороны. Идея - не просто подтормозить сторону для поворота, а сделать разворот на месте. Если крутить оба борта в одну или другую сторону, один борт в одну или другую сторону - все отлично, но как только пытаюсь сделать разворот на месте, т.е. один борт крутит в одну сторону, а другой борт в противоположную, то наблюдается какая то странность, как будто что то мешает, крутятся стороны еле еле. Используется DFRobot Motor Shield

    Демо код(проблема в последнем блоке, где крутим борта в разные стороны):
    Код (Text):

    //Arduino PWM Speed Control:
    int E1 = 5;
    int M1 = 4;
    int E2 = 6;                
    int M2 = 7;                  
     
    void setup()
    {
        pinMode(M1, OUTPUT);
        pinMode(M2, OUTPUT);
        pinMode(E1, OUTPUT);
        pinMode(E2, OUTPUT);
    }
     
    void run()
    {
      for(value = 0 ; value <= 255; value+=5)
      {
        analogWrite(E1, value);  //PWM Speed Control
        analogWrite(E2, value);  //PWM Speed Control
      }
    }
     
    void loop()
    {
     
      int value;
     
      // Едем вперед
      digitalWrite(M1, HIGH);
      digitalWrite(M2, HIGH);
      run();
      delay(3000);
      analogWrite(E1, 0);  //PWM Speed Control
      analogWrite(E2, 0);  //PWM Speed Control
     
      // Едем назад
      digitalWrite(M1, LOW);
      digitalWrite(M2, LOW);
      run();
      delay(3000);
      analogWrite(E1, 0);  //PWM Speed Control
      analogWrite(E2, 0);  //PWM Speed Control
     
      // Крутим одну сторону
      digitalWrite(M1, LOW);
      run();
      delay(3000);
      analogWrite(E1, 0);  //PWM Speed Control
      analogWrite(E2, 0);  //PWM Speed Control
     
      // Крутим другую сторону
      digitalWrite(M2, LOW);
      run();
      delay(3000);
      analogWrite(E1, 0);  //PWM Speed Control
      analogWrite(E2, 0);  //PWM Speed Control
     
      // Крутим в разные стороны левый и правый борт
      digitalWrite(M2, LOW);
      digitalWrite(M1, HIGH);
      run();
      delay(3000);
      analogWrite(E1, 0);  //PWM Speed Control
      analogWrite(E2, 0);  //PWM Speed Control
     
    }
     
  15. Megakoteyka

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

    А задержка в функции run() разве не нужна? Иначе функция отрабатывает почти мгновенно и не дает никакого эффекта.
    Если танк оторвать от земли - гусеницы все равно в разные стороны не крутятся?
     
  16. Sand

    Sand Нерд

    По поводу задержки, это из примера с сайта - разработчика шилда dfrobot.com. Как я понял, нельзя сразу выставить 255 на выводе, поэтому и используется постепенное увеличение скорости, но по идее, да, почти мгновенно. Я с моторами никогда не работал, поэтому точно не знаю как правильно их запускать...

    Функция - run, это скорость, направление выставляется через HIGH или LOW на выводах M1 и M2.
    Они крутятся, но, такое ощущение, что с огромным трудом. Как будто что то мешает или подтормаживает... Но только в одном случае, если борта крутятся в разные стороны
     
  17. Sand

    Sand Нерд

    Наконец то дописал прогу на Java для планшета на Андроиде, реализована пакетная передача данных(основа - пример, приведенный Megakoteyka):
    Процесс установки соединения и управление:
    [​IMG]

    [​IMG]

    [​IMG]

    [​IMG]

    [​IMG]

    [​IMG]

    [​IMG]
    PS: Планшет - уже древний мамонт: Samsung Galaxy Tab 7" P1000, Версия ведроида - 2.3.3. Другие больше не доступны для этого старья, зато для разработки и отладки данный девайс подходит отлично. Все, что мне было нужно - это Bluetooth SPP и возможность заливать приложения в обход магазина, что не позволяют делать планшеты производства известной яблочной компании

    Пакет - Заголовок, длина данных, сами данные, контрольная сумма

    Скоро выложу видео, как это все добро коннектится и управляется.

    Сделано:
    1. Ручное управление. Через Bluetooth shield
    2. Автоматическое управление. По сигналу с 1го ультразвукового дальномера.
    3. Сделать управление с андроид планшета 7"

    В планах:
    1. Добавить еще датчиков для более точного обхода препятствий
    2. Сделать светодиодное освещение, головное + кормы, включающееся по сигналу с фоторезистора или из Android приложения

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

    После реализации пунктов 1 и 2 будет выложен код приложения управления и скетч для Ардуины
     
  18. Sand

    Sand Нерд