Вторник, 26.11.2024
Мой сайт
Меню сайта
Статистика

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

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

Приёмник это устройство, на выводе которого появляется напряжение, если антенна что-то выловила на резонансной частоте. Если передаётся человеческий голос, то напряжение будет пропадать и появляться с частотой человеческого голоса. Если провод с так скачущим напряжением положить на магнит, то и сам провод начнёт прыгать с частотой звуковой волны.
В случае же цифровой передачи едёт включение сигнала на какое-то время  а потом его выключение. Провод с этим включающимся и выключающимся сигналом подключается к какому-то пину микроконтроллера. И микроконтроллер должен как-то реагировать на эти включения и выключения. Микроконтроллер, как и компьютер «научен» получать сигналы от периферических устройств и как-то на них реагировать. Получение таких сигналов (об изменении состояний, например, с «выключено» на «включено») называется прерываниями. А действия, которые выполняет после этого компьютер – программами – обработчиками прерываний.
В своё время меня очень озадачил этот термин «прерывание», но пришлось привыкнуть. Видимо, имелось в виду, что если что-то такое случилось, то компьютер должен прерваться на какую-то реакцию на возникшую ситуацию.
Обработчики прерываний можно писать вручную. В компьютерах это делают редко, потому что программы – обработчики – часть уже написанной операционной системы, установленной на компьютер. А микроконтроллеры это маленькие компьютеры без понятных функций. К ним можно подключить что угодно, но и самостоятельно надо писать, как реагировать на поведение подключенного устройства.
При подключении передатчика надо написать такое «заклинание»:
mySwitch.enableReceive(0);  // Receiver on inerrupt 0 => that is pin #2
Русский перевод комментария: «Приёмник на прерывание 0. что соответствует пину №2».
При этом последовательно запускаются две функции:
void RCSwitch::enableReceive(int interrupt) {
  this->nReceiverInterrupt = interrupt;
  this->enableReceive();
}

void RCSwitch::enableReceive() {
  if (this->nReceiverInterrupt != -1) {
    RCSwitch::nReceivedValue = NULL;
    RCSwitch::nReceivedBitlength = NULL;
    attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
  }
}
Внутренней переменной nReceiverInterrupt присваивается номер пина. А потом функцией attachInterrupt к событию изменение состояния CHANGE пина с номером this->nReceiverInterrupt привязываемся обработчик прерывания handleInterrupt.
Теперь при каждом появлении и пропадании сигнала от передатчика (при каждом CHANGE) будет вызываться функция с именем handleInterrupt. Вот её начало и конец:
void RCSwitch::handleInterrupt() {
  static unsigned int duration;
  static unsigned int changeCount;
  static unsigned long lastTime;
  static unsigned int repeatCount;
  long time = micros();
  duration = time - lastTime
;


 

  if (duration > 5000 && duration > RCSwitch::timings[0] - 200 &&
        duration < RCSwitch::timings[0] + 200) {
    repeatCount++;
    changeCount--;
    if (repeatCount == 2) {
      if (receiveProtocol1(changeCount) == false){
        if (receiveProtocol2(changeCount) == false){
          if (receiveProtocol3(changeCount) == false){
            //failed
          }
        }
      }
      repeatCount = 0;
    }

ELSE {

  RCSwitch::timings[changeCount++] = duration;

  lastTime = time;

}
Первое, что делает эта функция – узнает текущее время в микросекундах, сравнивает с временем предыдущего своего запуска и узнаёт, сколько времени длился период включенного или выключенного состояния. Если прошло достаточно много времени, все считанное передаётся функциям  receiveProtocolX(), которые и будут определять похоже это на переданное значение или нет. 
Если времени прошло мало, то в массив временных промежутков timings[] записывается следующий временной промежуток.
Все функции проверки соответствия протоколу одинаковы. Для первого протокола (начало функции):
bool RCSwitch::receiveProtocol1(unsigned int changeCount){
   
      unsigned long code = 0;
      unsigned long delay = 350;
      unsigned long delayTolerance = 350 * 60 * 0.01;   

      for (int i = 1; i<changeCount ; i=i+2) {
     
          if ( // Проверка0” this->transmit(1,3);
             RCSwitch::timings[i] > delay-delayTolerance   // Сигнал д.б = delay
             && RCSwitch::timings[i] < delay+delayTolerance
             && RCSwitch::timings[i+1] > delay*3-delayTolerance // Пауза д.б  = 3* delay
             && RCSwitch::timings[i+1] < delay*3+delayTolerance)
                 {
                  code = code << 1;
                  }
           else if (  ( // Проверка1” this->transmit(3,1);
             RCSwitch::timings[i] > delay*3-delayTolerance     // Сигнал д.б = 3*delay
             && RCSwitch::timings[i] < delay*3+delayTolerance
             && RCSwitch::timings[i+1] > delay-delayTolerance // Пауза д.б  = delay
             && RCSwitch::timings[i+1] < delay+delayTolerance)
                 {
                 code+=1;
                 code = code << 1;
                }
        else {
            // Failed - Ошибка
               i = changeCount;
               code = 0;
               }
      }

delay – базовая длина, delayTolerance – допустимое отклонение длины сигнала. А дальше идёт проверка всей полученной последовательности на соответствие этой длины и этого отклонения. Если что-то вылезло за диапазон, последовательность считается ошибкой. 
Просто для иллюстрации, я отправляла значения 1 (0000 0001) и 2 (0000 0010) и смотрела какие приходили последовательности. Вот такие, например:

7-й бит (=1) в значении «2» все-таки уложился в диапазон, потому двойка опознана.
Сразу, кстати, видно максимальное количество информации на этом дисплее (Поворот картинки дисплея на 180 градусов - display.setRotation(2);)
А это – единица:

… информация о 8-м бите которой на экране уже не поместилась. Но видимо она тоже попала в нужный диапазон.

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

Протухли они за полгода. Не работают. Есть у меня какое-то смутное воспоминаете о том, что год назад полечило последовательное подключение всех пинов к земле, но так это не должно работать.
Почему я думаю, что производители знают, что продают заведомый брак? Потому, что протокол SPI никак не соответствует нуждам такого устройства. Этот протокол не имеет к радиопередаче никакого отношения. По нему передаются данные от модуля микроконтроллеру. Но тут нет ни больших объемов данных ни даже одновременного приёма с передачей (приемник выключается, передача включается и наоборот). А тут даже не SPI. Тут ещё минимум один провод подключить надо. 
Единственное, зачем это все может быть надо – чтобы спрятать за всем этим избыточным барахлом неработающий модуль. Или быстро ломающийся. Или очень нестабильный. Уже не важно.

 

 

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