одновременное выполнение кода


Люди, подскажите на каком нибудь примере как запрограммировать робота чтоб он ехал и одновременно зондировал расстояние ик-дальномером закреплённым на серво-машинке? Т.е. — чтоб не останавливался перед препятствием а заранее принимал решение и не останавливаясь поворачивал. При этом ещё хочу чтоб крутил датчиком освещённости на другой серве и поворачивал солнечную батарею в наиболее освещённую сторону (на солнце). А то у меня никак не получается… Надо использовать «прерывание»? Или ещё как то?


15 комментариев на «“одновременное выполнение кода”»

  1. зачем прерывания?

    простой конечный автомат + система сообщений + таймер.

    а вопрос немного странный, ведь когда работают двигатели, процессор ничем не занят — ничто ему не мешает отдавать команды сервам, опрашивать дальномеры и т.д.

    • так в том то и дело что я не знаю как это сделать(запрограммировать) в программе как написано по порядку — так по порядку и выполняется — движение затем опрос дальномера потом опрос солнечной батареи. я не профи по программированию 🙁

    • вы, наверное, функцией delay злоупотребляете — не стоит, лучше привязать все события к счетчику времени, а текущее состояние двигателей, серв и прочей периферии хранить хотя бы в отдельных переменных.

      т.е. вместо

      void loop()
      {
      move_forward();
      delay( 1000 );
      move_right()
      delay( 1000 );
      move_backward()
      delay( 1000 );
      stop();
      }

      писать хотя бы так
      #define STOP 0
      #define FORWARD 1
      #define LEFT 2
      #define RIGHT 3
      #define BACKWARD 4
      int STATE = STOP;
      void loop()
      {
      if ( 0 == STATE && millis() > 0 )
      {
      move_forward();
      STATE = FORWARD;
      }
      if ( FORWARD == STATE && millis() > 1000 )
      {
      move_left();
      STATE = LEFT;
      }
      if ( LEFT == STATE && millis() > 2000 )
      {
      move_backward();
      STATE = BACKWARD;
      }
      if ( BACKWARD == STATE && millis() > 3000 )
      {
      stop();
      STATE = STOP;
      }
      }

    • Ошибочно советуете использовать millis(). Значение будет всегда только увеличиваться, а значит в данном примере после того как выполнится последнее сравнение(millis() > 3000) оно всегда будет millis() > 3000.

      Чтобы пользоваться таймером надо объявить переменные типа long, скажем
      long proshloevremy;//Эти две переменные определяют время
      long tekusheevremy;//Вернее разница между ними
      int ZNACHENIEms=3000;//Это значение с которым сравнивают

      tekusheevremy=millis();//присваиваем прошедшее время переменной текущего времени
      if (BACKWARD == STATE && (tekusheevremy-proshloevremy)>ZNACHENIEms)
      {
      proshloevremy=tekusheevremy;//то что было текущим теперь в прошлом
      //дальше выполняются необходимые команды
      stop();
      STATE = STOP;
      }

      Хотя я ни в таймере, ни в delay не вижу необходимости.
      Какой именно дальномер не знаю, допустим самый примитивный определитель препятствия на светодиоде+фотодиоде (отражение попало на фотодиод -есть препятствие, значение HIGH) Реализовать можно примерно так:

      int ZNDATCHIK;//здесь храним значение датчика
      
      //содаем функции движения
      void VPERED()
      {
       //здесь указываем действие для езды вперед
      }
      void OSTANOVKA()
      {
       //здесь указываем действие для остановки
      }
      void PRAVO()
      {
       //действия поворота
      }
      void LEVO()
      {
       //действия поворота
      }
      //содаем функции проверки датчиком вокруг
      //допустим центральное положение сервы 90о право 0о левое 180о
      void DatcikPered()
      {
      //повернуть серве на 90о
      }
      void DatcikPravo()
      {
      //повернуть серве на 0о
      }
      void DatcikLevo()
      {
      //повернуть серве на 180о
      }
      
      void setup(){
      //стандартный сетап с объявлениями и тд
      }
      
      void loop()
      {
        DatcikPered();//датчик по умолчанию смотрит всегда вперед
      if (ZNDATCHIK==1) //если не равен 0 в переди преграда
      {
        DatcikPravo();// Посмотрим направо
        if (ZNDATCHIK==0)//если нет преграды
        {  
         PRAVO();Повернем направо
         break;//Прервем проверки и вернемся в цикл петлю
        }  
        DatcikLevo();// Посмотрим направо
        if (ZNDATCHIK==0)//если нет преграды
        {  
         LEVO();//повернем налево
         break;//Прервем проверки и вернемся в цикл петлю
        }  
      OSTANOVKA();  //ну если везде преграда то встанем и не поедем никуда
      }
      else {VPERED();}//если нет сигнала о препятствии - выполняем функцию вперед   
      }
      
      
      
    • добавляете еще одно деление по модулю — будет вам закольцованный цикл

    • Зачем? Ардуино иде это не С, loop и так перля (в дословном переводе тоже). Да и в с для создания закольцованного цыкла проще всего в main добавить while или for.

    • ну расскажите, как вы будете стандартными инструкциями для циклов организовывать 2 _частично_ пересекающихся цикла.

      или, например, с некратным вложением ( т.е. одна инструкция выполняется в 1.6576 раз чаще другой )

    • Вопрос про деление по модулю поставлен не верно, надо спрашивать не что это, а зачем оно здесь. AVR это не просто процессор — это микроконтроллер. Конечно возможно тут просто сказывается мое образование, и учись я на программиста а не на радиомонтажника, я предпочитал бы все решать программно а не возможностями железа.

      В даташите на мегу168 в разделе о прерываниях Interrupt Vectors in ATmega168 описаны 3 таймера.

    • Таймер можно повесить и на внешние прерывания, но смысл вопроса понятен.
      Попробую правильно составить тех. задание. Если не хватает возможностей железа, то возможно не то железо выбрано.
      Хотя не против посмотреть и на программную реализацию. Возможно это окажется действительно удобнее.

    • как написанно по поярдку-так и выполняется. все верно. Но такая штука как микроконтроллер намного умнее нашего мозга и может сосчитать квадратный корень из 234567 и почесать попу… и это за менее чем секунду. думаю понятно описал ситуацию.
      Вы, простите в ардуину код заливали, тестировали. Чем вызван сей вопрос то?

    • сей вопрос вызван незнанием и неумением программировать — но я учусь и пока вроде успешно

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение