Пятница, 29.11.2024
Мой сайт
Меню сайта
Статистика

Онлайн всего: 112
Гостей: 112
Пользователей: 0
Главная » 2022 » Октябрь » 27 » Драйвера радиомодулей (передатчик)
15:30
Драйвера радиомодулей (передатчик)

Драйвера радиомодулей (передатчик)

Напомню, что драйвер это такая программа, которая преобразует нули и единицы устройства в логически цельную информацию, которую может использовать человек.
Например, устройство – мышь нулями и единицами сообщает только куда и насколько оно сместилось в последний раз. А драйвер вначале помещает курсор мыши в середину экрана, а потом, считая суммы перемещений, передвигает по экрану этот курсор и следит за тем, чтобы курсор не уехал за границу экрана.
В данный момент, я считаю, что все устройства этой серии:
https://amperkot.ru/spb/catalog/radiomodul_nrf24l01_pa__lna_s_antennoy-24118355.html

… брак. А сложная настройка c SPI протоколом и прочим нужна только для того, чтобы спрятать этот неприятный факт.
Ниже я попытаюсь объяснить, почему я так думаю.
Разбирать я буду драйвер для этого устройства:
https://amperkot.ru/spb/catalog/radiomoduli_433mhz_peredatchik_mxfs03v_i_priemnik_mx05v-23869814.html

Его минус – очень небольшая дальность, а плюс – простота и естественность работы, которые, в числе прочего, позволяют понять, какие проблемы возникают с физической частью процесса, т.е с передачей информации по воздуху.
Класс – объект, в котором собран список той самой логически доступной информации включает в себя… очень много чего. Потому только часть списка из файла RCSwitch.h:
class RCSwitch {
  public:
    RCSwitch();
    void send(unsigned long Code, unsigned int length); // Отправка данных
    void enableReceive(); // Проверка получения информации
    void disableReceive(); // Обнуление считанного значения
    unsigned long getReceivedValue(); // Получение информации, прочитанной приёмником
    void setPulseLength(int nPulseLength); // Установка длины импульса
    void setRepeatTransmit(int nRepeatTransmit); // Установка кол-во повторов отправки
   // Установка отклонения длины полученного сигнала:
    void setReceiveTolerance(int nPercent);    void setProtocol(int nProtocol);
  private:
    void send0(); // Отправка ”0”
    void send1(); // Отправка “1”
    void sendSync(); /// Отправка паузы после передачи информации
    void transmit(int nHighPulses, int nLowPulses);
    static void handleInterrupt(); // Обработчик прерывания приходя сигнала на приёмник

    // Проверка полученных данных на соответствие какому-то протоколу:
    static bool receiveProtocol1(unsigned int changeCount);
    static bool receiveProtocol2(unsigned int changeCount);
    static bool receiveProtocol3(unsigned int changeCount);
    int nTransmitterPin;
    int nPulseLength; // Базовая длина сигнала
    int nRepeatTransmit; // Сколько раз отправлять информацию
    char nProtocol; // Номер протокола передачи
    static int nReceiveTolerance; // Допустимое отклонение длины полученного сигнала
    static unsigned long nReceivedValue; // Полученное приёмником значение
    // Массив задержек между включением и выключением сигнала на приёмнике:
    static unsigned int timings[RCSWITCH_MAX_CHANGES];
};
Поскольку тут приём и передача данных, то основные используемые тут функции отправки (send()) и получения информации (getReceivedValue()). Понятно и то, что внутри отправляемое десятичное число преобразуется в его двоичный вид. И эти нули с единицами будут последовательно отправляться в эфир функциями send0() и send1().
Но вначале напишу про 4 параметра настройки внутренней работы.
nPulseLength – базовая длина сигнала. Для первого протокола она 350 микросекунд.
nRepeatTransmit – сколько раз в эфир передавать информацию. По – умолчанию 10. Т.е 10 раз будет послана цифра в надежде на то, что хотя бы один раз приёмник сможет её опознать в фоновых шумах.
nProtocol – номер протокола. В этом драйвере их три. Зачем они не очень понятно. Скорость передачи у них одинаковая. Хотя обычно замедляют передачу для того чтобы увереннее идентифицировать полученные данные. Может быть, так можно различать сигналы от разных устройств.
nReceiveTolerance – процент допустимого отклонения пришедшего сигнала от того, что было послано. По – умолчанию – 60%. Т.е если нулём считается длительность сигнала в 350 микросекунд, то программа решит, что получен ноль, если придёт сигнал длительностью от 140 до 560 микросекунд. Такая дикая неточность компенсируется отправкой кучи нулей и единиц и промежутков между ними. Минимум 12 цифр последовательных промежутков времени должны соответствовать этой погрешности в 60%.
Я подключила к приемнику светодиод и обнаружила, что он мигает почти постоянно. Можно перевернуть приёмник и уже из-за этого он выловит какие-то шумы. Вся очистка информации тут переложена на программный уровень.   Приёмники могут быть лучше или хуже, но у всех возникает необходимость какой-то чистки информации. Т.е этим на каком-то уровне (электронном, программном) будут заниматься приёмник любого радиомодуля)
Несколько функций из RCSwitch.cpp:
Установка протокола:
void RCSwitch::setProtocol(int nProtocol) {
  this->nProtocol = nProtocol;
  if (nProtocol == 1){
    this->setPulseLength(350);
  }
  else if (nProtocol == 2) {
    this->setPulseLength(650);
  }
  else if (nProtocol == 3) {
    this->setPulseLength(100);
  }
}
Присваивается значение внутренней переменной номер протокола (this->nProtocol) и задаётся величина базового импульса.
Передача сигнала:
void RCSwitch::send(char* sCodeWord) {
  for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
    int i = 0;
    while (sCodeWord[i] != '\0') {
      switch(sCodeWord[i]) {
        case '0':
          this->send0();
        break;
        case '1':
          this->send1();
        break;
      }
      i++;
    }
    this->sendSync();
  }
}
Тоже все просто. В цикле последовательно отправляются в эфир биты информации до пока не встретиться символ конца строки ('\0'). Только повторюсь, что отправка обычно идёт 10 раз (цикл по nRepeat).
Отправка «0»:
void RCSwitch::send0() {
    if (this->nProtocol == 1){
        this->transmit(1,3);
    }
    else if (this->nProtocol == 2) {
        this->transmit(1,2);
    }
    else if (this->nProtocol == 3) {
        this->transmit(4,11);
    }
}
Тут видно, чем отличаются протоколы – разными параметрами функции  transmit(), которая использует эти значения для длительности сигнала и его отсутствия:
void RCSwitch::transmit(int nHighPulses, int nLowPulses) {

        digitalWrite(this->nTransmitterPin, HIGH);

        delayMicroseconds( this->nPulseLength * nHighPulses);

        digitalWrite(this->nTransmitterPin, LOW);

        delayMicroseconds( this->nPulseLength * nLowPulses);

}
Вот и вся работа с передатчиком. Его надо включить, подождать какое-то количество микросекунд (базовый импульс * параметр функции), потом выключить и опять подождать сколько-то микросекунд. Когда передатчик включен, в эфир идут радиоволны, когда выключен – не идут. Длительность того и другого будет оценивать приёмник.
Отправка ”1”:
void RCSwitch::send1() {
      if (this->nProtocol == 1){
        this->transmit(3,1);
    }
    else if (this->nProtocol == 2) {
        this->transmit(2,1);
    }
    else if (this->nProtocol == 3) {
        this->transmit(9,6);
    }
}
Для первого протокола «0» это сигнал 350*1 микросекунд и его отсутствие 350*3 микросекунд, а единица это сигнал 350*3 микросекунд и пауза 350*1 микросекунд. Для остальных протоколов другие длительности, но действия (включить и выключить) те же

 

 

 

Просмотров: 98 | Добавил: akostina76 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Форма входа
Поиск
Календарь
«  Октябрь 2022  »
ПнВтСрЧтПтСбВс
     12
3456789
10111213141516
17181920212223
24252627282930
31
Архив записей
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Copyright MyCorp © 2024
    Бесплатный конструктор сайтов - uCoz