Радио управляемая машинка

Тема в разделе "Проводная и беспроводная связь", создана пользователем Evgeniy2017, 1 июл 2018.

  1. Evgeniy2017

    Evgeniy2017 Нерд

    Помогите я нуб но имею базовые знания
    У меня есть покачто arduino nano и arduino uno но потом приедет еще нанка и будет все на двух нанках
    Да кстати приемник передатчик на 433 мега герцах
    Нужно помочь с кодом
    Вот передатчик
    Код (C++):
    #include <VirtualWire.h>

    char *controller;
    int button_left = 4;
    int button_right = 5;
    int button_forward = 6;
    int button_nazad = 7;

    void setup() {
      pinMode(13,OUTPUT);
      pinMode(12,OUTPUT);
      vw_set_ptt_inverted(true); //
      vw_set_tx_pin(11);
      vw_setup(4000);// скорость передачи данных в Kbps
      digitalWrite(12,1);
    }

    void loop(){
    boolean left = digitalRead(button_left);
    boolean right = digitalRead(button_right);
    boolean forward = digitalRead(button_forward);
    boolean nazad = digitalRead(button_nazad);
    if(left == 1){
    controller="1" ;
      vw_send((uint8_t *)controller, strlen(controller));
      vw_wait_tx(); // ждем, пока отправится все сообщение
      delay(100);
    }
    if(right == 1){
    controller="2" ;
      vw_send((uint8_t *)controller, strlen(controller));
      vw_wait_tx(); // ждем, пока отправится все сообщение
      delay(100);
    }
    if(forward == 1){
    controller="3" ;
      vw_send((uint8_t *)controller, strlen(controller));
      vw_wait_tx(); // ждем, пока отправится все сообщение
      delay(100);
    }
    if(nazad == 1){
    controller="4" ;
      vw_send((uint8_t *)controller, strlen(controller));
      vw_wait_tx(); // ждем, пока отправится все сообщение
      delay(100);
    }  
    }
    Вот приемник
    Код (C++):
    #include <VirtualWire.h>

    void setup(){
      vw_set_ptt_inverted(true); // необходимо для модуля DR3100
      vw_set_rx_pin(9);
      vw_setup(4000); // бит в секунду
      pinMode(13, OUTPUT);
      pinMode(10, OUTPUT);
      Serial.begin(9600);
      digitalWrite(10,1);
      vw_rx_start(); // запуск фазовой автоподстройки частоты (ФАПЧ)
    }

    void loop(){
      uint8_t buf[VW_MAX_MESSAGE_LEN];
      uint8_t buflen = VW_MAX_MESSAGE_LEN;
      if (vw_get_message(buf, &buflen)) //
      {
        if(buf[0]=='1'){
    //      digitalWrite(13,1);
          Serial.println("Left");
        }
        if(buf[0]=='2'){
    //      digitalWrite(13,0);
          Serial.println("Right");
        }
        if(buf[0]=='3'){
    //      digitalWrite(13,0);
          Serial.println("Forward");
        }
        if(buf[0]=='4'){
    //      digitalWrite(13,0);
          Serial.println("Nazad");
        }
      }
    }
    Может подскажите другую библиотеку
    А вопрос: Как сделать чтобы когда я отпустил кнопку допустим на 4 пине то дальше уж не приходили
    2 2 2 2 2 2 22 у меня вышло так что после от жатия кнопки у меня еще штук 5-7 пишет последнее направление что делать ? я вот думал может есть команда тип сброса буфера передатчика ?
     
  2. Evgeniy2017

    Evgeniy2017 Нерд

    Буду рад любой помощи!
     
  3. Airbus

    Airbus Оракул

    Сделай в передатчике в loop общий delay(500) внизу между нижними фигурными скобками.Либо delay(100) поменяй на 500.Это самый простой способ или вставить функцию отлавливания нажатия чтоб символ передавлся разово.
     
  4. Evgeniy2017

    Evgeniy2017 Нерд

    Хорошо спасибо я попробую с задержкой внизу loop и если не сложно можно ету функцию разового отправления ?
     
  5. Airbus

    Airbus Оракул

    Можно.Разрешаю.
     
    BAR__MEN нравится это.
  6. Evgeniy2017

    Evgeniy2017 Нерд

    Ну кароч не задержка в лупе не помогла надо делать фильтр на приемнике завтра буду что-то варганить
    И можно пример разового отправления
     
  7. Evgeniy2017

    Evgeniy2017 Нерд

    Есть кто живой?
     
  8. Mitrandir

    Mitrandir Гуру

    Подобное поведение не может быть вызвано дребезгом кнопок?
     
  9. Evgeniy2017

    Evgeniy2017 Нерд

    Ну дребизг отправилоб 2-4 сообщения ну не 6-10
     
  10. SergeiL

    SergeiL Гуру

    Дребезг на кнопках будет точно.

    Поэтому в передатчике сначала убираем дребезг и формируем одну байтовую переменную, где четыре младших бита соответствуют четырем кнопкам.
    Кнопка нажата - бит в 1, отпущена - бит в 0.

    Если состояние всех кнопок в одном байте, то отправлять можно только 1 байт, и в нем будет полное состояние.

    Далее сравниваем переменную (с битовым состоянием кнопок) полученную на текущем цикле, после устранения дребезга, с последим, отправленным состоянием.
    Если не равны - отправляем немедленно, и запоминаем время отправки через millis()
    Если равны предыдущему отправленному значению, смотрим на время.
    Если период отправки, к примеру 100-200 миллисекунд (для надежности доставки, чтобы не потерять команду) превышен, отправляем снова, запоминаем время отправки.

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

    И никаких буферов, никаких delay(). ;)
     
    Evgeniy2017, ИгорьК и Mitrandir нравится это.
  11. Evgeniy2017

    Evgeniy2017 Нерд

    Ок ну если не сложно можно в коде я же говорил Я нуб. И прям не владею ардуино поэтому прошу помощи Я бы не просил помощи если бы знал. Можно в коде ?
     
  12. Evgeniy2017

    Evgeniy2017 Нерд


    Ок ну если не сложно можно в коде я же говорил Я нуб. И прям не владею ардуино поэтому прошу помощи Я бы не просил помощи если бы знал. Можно в коде ?
     
  13. Evgeniy2017

    Evgeniy2017 Нерд

    Ок ну если не сложно можно в коде я же говорил Я нуб. И прям не владею ардуино поэтому прошу помощи Я бы не просил помощи если бы знал. Можно в коде ?
     
  14. parovoZZ

    parovoZZ Гуру

    прозвучало как заклинание. Теперь надо жертвоприношение сделать и заклинание обязательно исполнится.
     
  15. koliyr

    koliyr Нуб

    Сопротивление 10К стоит на кнопке?
    избавление от дребезга:
    https://uscr.ru/drebezg-kontaktov-i-sposoby-podavleniya-drebezga/
    INPUT_PULLUP - с использованием внутреннего сопротивления
    Код (C++):

    void setup(){
      pinMode(13,OUTPUT);
      pinMode(12,OUTPUT);
    pinMode(button_left ,INPUT_PULLUP);
    ...
     
  16. Evgeniy2017

    Evgeniy2017 Нерд

    :)
     
  17. Evgeniy2017

    Evgeniy2017 Нерд

    Да стоит 10к на землю
     
  18. SergeiL

    SergeiL Гуру

    Так может стоит попробовать разобраться??? :)
    Что такое дребезг, как его убрать...
    Что такое байт, как в нем выставлять сбрасывать биты.

    Иначе не понимаю смысла. Если нужен результат, наверное проще готовое управление купить. :)

    Мне то не сложно, тут скетч передатчика, с комментариями и пропусками строк, для наглядности, не больше трех экранов получится.
    Я же все пошагово объяснил, вот все так и пишется.:)
    А то, сами мы не местные... Надо пробовать, не получится - люди подскажут! ;)
     
  19. SergeiL

    SergeiL Гуру

    Ну что, кода нет - интерес пропал, желания разбираться нет? :)
     
  20. SergeiL

    SergeiL Гуру

    Пропал ТС. :), поглотила пучина.
    Ну да ладно, ради прикола, и нашего внутреннего спора, в начале недели, за обеденный перерыв (в 1 час), были написаны сие два скетча. Работу не проверял, пожалуйста, отпишитесь, если кто-то проверит.;)

    Как и предлагал по передатчику:
    • все по шагам,
    • два экрана, менее 100 строк. (с пропусками и комментариями.)
    Приемник еще проще.
    Для надежности вставлена простейшая проверка посылки.

    Вот передатчик:
    Код (C++):
    #include <VirtualWire.h>

    #define PIN_IN_0 4      // Left
    #define PIN_IN_1 5      // Right
    #define PIN_IN_2 6      // Forward
    #define PIN_IN_3 7      // Backward

    #define PIN_IN_NUMB 4  // количество используемых входов значение от 1 до 8.
                           // Если входов больше 8 ходов - меняем размер переменных участвующих в хранении результатов с byte на unsigned int или long

    uint8_t InputPins[PIN_IN_NUMB] = { PIN_IN_0,PIN_IN_1,PIN_IN_2,PIN_IN_3};  // заносим номера пинов в массив, для обработки через for

    #define PIN_READ_TO  10L             // 10 ms  периодичность проверки входов. Оптимальным является интервал 5-10мс. соответственно в результате сигнал о нажатии будет получен через 20-40мс  (в данном случае 40мс)
    #define STATE_SND_TO 200L            // 200 ms  периодичность отправки сообщения, если не было изменений

    //------------------ Чтение цифровых входов --------------------------------------
    uint8_t Input_Read(void)
    {
          uint8_t result = 0;                           // копим побитовое состояние входов
          uint8_t i,j;
          for (i=1,j=0; j < PIN_IN_NUMB; j++,i=i<<1)    // пробежимся по всем входам
          {                          
                                                        // Если при нажатии кнопки на входе появляется VCC - в if оставляем == HIGH.
              if ( digitalRead(InputPins[j]) == HIGH )  // Если при нажатии кнопки на входе появляется GND - заменить HIGH на LOW
                result |= i;                            // Дальше всегда будем считать, что если бит в 1 - это кнопка нажата или на входе ON.
          }                                             //                                             0 - это кнопка отпущена или на входе OFF.
                                                        // в result "1" взводится в соответствующем бите.
                                                        // например, если на входе 2 (считаем с 0, в define в самом верху определено, что это цифровой пин 6),
                                                        // присутсвует 1 - в result добавится "1"  в 2-ом от нуля бите.  00000100
          return(result);
    }

    //------------------ ФУНКЦИЯ УСТР. ДРЕБЕЗГА  для всех входов --------------------------------------
    uint8_t vc_debounce(uint8_t SWKEYS)        // Verical_Couners_debounce, вызывается каждые 10 мсек, можно из таймера
    {                                           // в SWKEYS состояние вводов

        static uint8_t SLATCH = 0;              // текущее устоявшееся значение входов после устранения дребезга
        static uint8_t VCBIT0 = 0;              // счетчик бит 0
        static uint8_t VCBIT1 = 0;              // счетчик бит 1
        uint8_t        vcmask = 0;              // Маска

        vcmask = SWKEYS ^ SLATCH;                    // скинем счетчики для установившихся и неактивных значений
        VCBIT0 &= vcmask;
        VCBIT1 &= vcmask;
                                                 
        SLATCH ^= (vcmask & VCBIT0 & VCBIT1);       //  Каждая '1' в SLATCH представляет установившееся значение, каждый '0' установившееся нулевое значение        

        VCBIT1 ^= (vcmask & VCBIT0);                // инкрементируем счетчик.
        VCBIT0 ^= (vcmask);

      return (SLATCH);                              // текущее, устоявшееся значение входов
    }

    void setup()
    {
        byte j;
        for (j=0; j < PIN_IN_NUMB; j++)        // настроим  порты, ккотрым подключены кнопоки, как входы. Резистор подтяжки - внешний.
            pinMode(InputPins[j], INPUT);  

        pinMode(13,OUTPUT);             // ИЗ скетча TC, не менял
        pinMode(12,OUTPUT);             // ИЗ скетча TC, не менял
        vw_set_ptt_inverted(true);      // ИЗ скетча TC, не менял
        vw_set_tx_pin(11);              // ИЗ скетча TC, не менял
        vw_setup(4000);                 // ИЗ скетча TC, не менял, скорость передачи данных в Kbps
        digitalWrite(12,1);             // ИЗ скетча TC, не менял
    }
    void loop()
    {
       static uint32_t    LastPinReadMs = 0 ;      // переменная для сохранения времени, когда были считаны значения с цифорвых входов
       static uint32_t    LastSndMs = 0 ;          // переменная для сохранения времени, когда было отправлено состояние
       static uint8_t     LastSendState=99;        // переменная для сохранения последнего отправленного состояния
       uint8_t            current_state;           // переменная для текущего состояние по кнопкам
       uint8_t            snd_command;             // переменная для формирования отправляемой команды

       uint32_t           cur_millis = millis();            // переменная для сохранения текущего времени, дабы не вызывать millis() несколько раз

       if ((cur_millis - LastPinReadMs) > PIN_READ_TO)      // выполняется каждые 10мс (PIN_READ_TO)
       {
          current_state = Input_Read();                     //  1) прочитаем и загрузим в переменную значения входов: 0-й бит - первый вход, 1-й бит - второй вход, 2-й бит - третий вход, 3-й бит - четвертый вход.
       
          current_state=vc_debounce(current_state);         //  2) отбросим дребезг по всем входам, на основании предыдущих проверок (игнорируем состояния, держащиеся на входе менее 4 проверок подряд)
       
          LastPinReadMs = cur_millis;                       // запомним время опроса кнопок
       
          if (LastSendState != current_state || ((cur_millis - LastSndMs) > STATE_SND_TO))  // 3) если изменилось состояние кнопок или пора повторно отправить состояние
          {
            snd_command=((current_state^0xFF)<<4) | (current_state & 0x0F);                 // для контроля получаемой посылки на приемной стороне, в старшие 4 разряда запишем состояние (младшие 4 разряда) но с проинвертированными битами.
         
            vw_send((uint8_t *) &snd_command, 1);                                           // 4) отправим состояние
            LastSndMs = cur_millis;                                                         //    запомним время отправки
            LastSendState = current_state;                                                  //    запомним последнее состояние
            vw_wait_tx();                                                                   //  ИЗ скетча TC, не менял, ждем, пока отправится все сообщение
          }
       }
    }
    Вот приемник:

    Код (C++):
    #include <VirtualWire.h>

    void setup()
    {
          // ИЗ скетча TC, не менялось-----------------------------------------------
      vw_set_ptt_inverted(true); // необходимо для модуля DR3100
      vw_set_rx_pin(9);
      vw_setup(4000); // бит в секунду
      pinMode(13, OUTPUT);
      pinMode(10, OUTPUT);
      digitalWrite(10,1);
      vw_rx_start(); // запуск фазовой автоподстройки частоты (ФАПЧ)

      Serial.begin(9600);
    }

    void loop()
    {
      static uint8_t  last_state=99;          // переменная для хранения последнего обработанного состояния кнопок
      uint8_t         cmd_val;                // переменная для полученного состояния кнопок
      uint8_t         tst_val;  

      uint8_t buff[VW_MAX_MESSAGE_LEN];       // ИЗ скетча TC, не менял
      uint8_t bufflen = VW_MAX_MESSAGE_LEN;   // ИЗ скетча TC, не менял

      if (vw_get_message(buff, &bufflen))     // ИЗ скетча TC, не менял
      {
        cmd_val = buff[0];                    // загрузим полученный байт
     
        tst_val =  (cmd_val^0xFF)>>4;         // подготовим проверочное значение (проинвертируем биты и сдвинем на 4 разряда  вправо)
        cmd_val &= 0x0F;                      // обнулим старшие 4 разряда
                                              // если полученный байт подготовлен нашим передатчиком, tst_val и cmd_val должны быть равны
                                              // но в принципе, это можно убрать, а в case занести костанты со сташими проинвертированными битами типа 0b11100001 для Left
                                           
        if (cmd_val==tst_val && cmd_val != last_state )             // если это команда нашего передатчика и состояние кнопок изменилось - обработаем новое состояние
        {
          switch( cmd_val )                                         // выберем действие для комбинации кнопок
          {
            case  0b00000000:
                  Serial.println("Stop");
            break;
            case  0b00000001:
                  Serial.println("Left");
            break;
            case  0b00000101:
                  Serial.println("Forward - Left");
            break;
            case  0b00000010:
                  Serial.println("Right");
            break;
            case  0b00000110:
                  Serial.println("Forward - Right");
            break;
            case  0b00000100:
                  Serial.println("Forward");
            break;
            case  0b00001000:
                  Serial.println("Backward");
            break;
            case  0b00001001:
                  Serial.println("Backward - Left");
            break;
            case  0b00001010:
                  Serial.println("Backward - Right");
            break;
            default:
                  Serial.println("Incorrect command ... unassigned behaviour");
          }
          last_state=cmd_val;                               // запомним последнюю обработанную комбинацию кнопок
        }
      }
    }
    Как всегда, критика, комментарии приветствуются ;)