Передача данных базовой станции Misol Arduino в локальную сеть и Интернет (Народный мониторинг)

Первичной целью разработки базовой станции Misol Arduino было расширение возможностей по передаче получаемых данных пользователям, находящимся в произвольных точках пространства. Современные сетевые технологии предоставляют удобные возможности для передачи необходимых данных в требуемом объеме на любое расстояние. С точки зрения сетевых технологий местонахождение пользователей можно разделить на локальное (в пределах области действия локальной сети) и внешнее (в пределах области действия сети Интернет). Буду считать, что локальным пользователям будут доступны данные в полном объеме, а внешним пользователям перечень передаваемых данных будет ограничен их требованиями. В рассматриваемом случае под внешним пользователем будет считаться сервер интернет ресурса народного мониторинга.

Программное обеспечение, позволяющее перехватывать пакеты данных блока внешних датчиков метеостанции Misol разработано ранее. В этой публикации речь пойдет о том, как полученные данные передать в локальную сеть и в Интернет. Для передачи данных в локальную сеть и Интернет необходимо подключить Arduino Mega к локальной сети. Такое подключение выполняется с помощью сетевой платы, например, Ethernet Shield W5100.

Ethernet Shield W5100 Arduino

Представляет собой плату расширения, устанавливаемую поверх базовой платы Arduino, например, Mega или Uno. Для удобства подключения штыревые контакты снизу удлиненные и дублируются сверху гребенкой, что обеспечивает доступ к контактам базовой платы, даже при подключении платы расширения. Кроме сетевого контроллера W5100, обеспечивающего взаимодействие с сетевым интерфейсом, на плате дополнительно разведен разъем для подключения SD карт памяти. Таким образом, на плате собраны два разных устройства. Выбор доступа к требуемому устройству осуществляется через сигналы CS (Chip Select — выбор микросхемы), в качестве которых используются цифровые сигналы базовой платы. Сигналы CS аппаратно разведены на плате расширения и назначаются в библиотеках. Подключается плата Ethernet Shield W5100 к плате Arduino Mega установкой сверху.

Протоколы передачи данных

Базовым понятием передачи данных является сетевая модель OSI. Она представляет процесс передачи данных, разделенным на различные уровни. В зависимости от уровня, на котором планируется обеспечить передачу данных обратнопропорционально меняются требования к аппаратному и программному обеспечению. Если использовать простые аппаратные средства, то придется разрабатывать объемное программное обеспечение. Если использовать сложные аппаратные средства, то пользовательское программное обеспечение может быть минимальным. Как в большинстве случаев, для решения конкретной задачи целесообразно использовать некий компромиссный вариант. Таким решение является использование транспортного уровня модели OSI, а именно протоколов TCP и UDP.

Протокол TCP

Механизм TCP предоставляет поток данных с предварительной установкой соединения, осуществляет повторный запрос данных в случае потери данных и устраняет дублирование при получении двух копий одного пакета, гарантируя тем самым, в отличие от UDP, целостность передаваемых данных и уведомление отправителя о результатах передачи. TCP осуществляет надёжную передачу потока байтов от одного процесса к другому. TCP реализует управление потоком, управление перегрузкой, рукопожатие, надёжную передачу.

Протокол UDP

UDP (англ. User Datagram Protocol — протокол пользовательских датаграмм) — один из ключевых элементов набора сетевых протоколов для Интернета. С UDP компьютерные приложения могут посылать сообщения (в данном случае называемые датаграммами) другим хостам по IP-сети без необходимости предварительного сообщения для установки специальных каналов передачи или путей данных. UDP использует простую модель передачи, без неявных «рукопожатий» для обеспечения надёжности, упорядочивания или целостности данных. Таким образом, UDP предоставляет ненадёжный сервис, и датаграммы могут прийти не по порядку, дублироваться или вовсе исчезнуть без следа. UDP подразумевает, что проверка ошибок и исправление либо не нужны, либо должны исполняться в приложении. 

Оба эти протокола могут быть использованы. Однако, протокол UDP является более простым с точки зрения требуемой программной поддержки и не требует большого объема программной памяти, что является важным требованием при его реализации на аппаратной платформе с ограниченными ресурсами, например, такой как Arduino. В то же время он не обеспечивает гарантированной доставки сообщения. Это необходимо всегда помнить при его использовании. В качестве базового протокола выбирается протокол UDP.

Программная поддержка передачи данных

Разработка программного обеспечения функционирования Arduino основывается на широком использовании библиотек, реализующих различные функции. Для решения поставленных задач потребуются следующие библиотеки:

Для работы с контроллером W5100 разработана библиотека. Её требуется загрузить и установить в среде программирования Arduino. В примерах к библиотеке есть необходимый скетч, который послужит базой. Пример «слушает» заданный порт. Когда на этот порт приходит сообщение, Arduino формирует ответное сообщение. Данный алгоритм работы отличается от требуемого. Для метеостанции нет необходимости ожидать входящего сообщения. В зависимости от потребителя информации (локальный или глобальный (народный мониторинг) требуется посылать пакет с метеоданными с заданной периодичностью. Локальным потребителям данные должны передаваться каждую минуту, а серверу народного мониторинга — каждые пять минут. Кроме того, состав (формат) данных локальному и глобальному потребителю отличается. С учетом этих требований пример был модифицирован.

/*
   https://github.com/arduino-libraries/Ethernet
   https://github.com/arduino-libraries/Ethernet/tree/master/examples/UDPSendReceiveString
  Этот скетч конфигурирует контроллер W5100 Arduino для работы с протоколом UDP и передает строку широковещательным пакетом в локальную сеть.
*/

#include <Ethernet.h>
#include <EthernetUdp.h>

// ----- ***** ----- ***** ----- NET DATA ----- ***** ----- ***** -----
// ----- ***** ----- LOCAL DATA ----- ***** -----
byte MyMAC[] = { 0x3A, 0xF1, 0x7F, 0xA4, 0x56, 0x7E };  // MAC для идентификации устройства 
                                                        // сервером народного мониторинга
IPAddress MyIP ( 192, 168, 0, 199 );
IPAddress MyDNS  ( 192, 168, 0, 1 );
IPAddress MyGateway ( 192, 168, 0, 1 );
IPAddress MySubnet ( 255, 255, 255, 0 );
unsigned int localPort = 9999;            // Порт для приема пакетов UDP
IPAddress NMDNS;
// ----- End LOCAL DATA -----

// ----- ***** ----- Broadcast udp message ----- ***** -----
IPAddress IPBC( 192, 168, 0, 255 );
const unsigned int PORTBC = 8887;         // Порт для отправки пакетов UDP
// ----- End Broadcast -----

// ----- ***** ----- NM ----- ***** -----
byte IPNMDNS[4];    //Для DNS
byte IPNM[] = { 185, 245, 187, 136 };     // IP сервера народного мониторинга.
                                          // Не требуется при включении DNS
int portNM = 8283;
String mac, mac_d;
// ----- End NM -----
// ----- ***** ----- End NET DATA ----- ***** -----


EthernetUDP Udp;            // Определение UDP


#define LUTime 30000;       // Периодичность передачи пакетов локальным пользователям миллисекунды (30 сек)
#define NMTime 300000;      // Периодичность передачи пакетов на народный мониторинг миллисекунд (55 минут)
long TxLUTime, TxNMTime;



// ----- ***** ----- ***** ----- Setup ----- ***** ----- ***** -----
void setup() {

  Ethernet.begin(MyMAC, MyIP);          // Инициализация контроллера W5100 с заданными параметрами

  Serial.begin(115200);                 // Инициализация последовательного порта
  while (!Serial) {                     // Ожидание инициализации последовательного порта
    ;
  }

  if (Ethernet.hardwareStatus() == EthernetNoHardware) {    // Проверка наличия контроллера W5100
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1);                 // Остановка исполнения при отсутствии контроллера W5100
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  Udp.begin(localPort);         // Запуск службы UDP
}   // ----- End Setup -----


// ----- ***** ----- ***** ----- Loop ----- ***** ----- ***** -----
void loop() {

  //  ----- ***** ----- Отправка пакета локальным пользователям ----- ***** -----
  if (TxLUTime < millis()) {    // Передача пакета локальным пользователям

    //  ----- ***** ----- Формирование строки ----- ***** -----
    String strlip = "MeteoData Local User";           // Строка сообщения локальным пользователям
    strlip += ' ';
    strlip += millis();
    strlip += "; ";
    Serial.print("StrLip=: ");
    Serial.print(strlip);
    //  ----- Конец Формирование строки -----

    //  ----- ***** ----- Преобразование строки в массив символов ----- ***** -----
    uint16_t lenBClip = strlip.length();
    Serial.print("\tLen LIP=: ");
    Serial.println(lenBClip);
    char ttsBClip[lenBClip + 1];
    strcpy(ttsBClip, strlip.c_str());
    // ----- Конец Преобразование строки в массив символов -----

    //  ----- ***** ----- Отправка пакета (массива символов) ----- ***** -----
    Udp.beginPacket(IPBC, PORTBC);
    Udp.write(ttsBClip);
    Udp.endPacket();
    // ----- Конец Отправка пакета (массива символов) -----

    //  ----- ***** ----- Задание времени отправки очередного пакета ----- ***** -----
    TxLUTime += LUTime;
    // ----- Конец Задание времени отправки очередного пакета -----

  }  // ---- Конец Передача пакета локальным пользователям ---- -
  //  ----- Конец Отправка пакета локальным пользователям -----


  //  ----- ***** ----- Отправка пакета серверу народного мониторинга ----- ***** -----
  /*
    if (TxNMTime < millis()) {
      Udp.beginPacket(IPNM, portNM);
      Udp.write(ttsNM);
      Udp.endPacket();

      TxNMTime += NMTime;
    }
  */
  // ----- Конец Отправка пакета серверу народного мониторинга -----

}   // ----- Конец Loop -----

Разбор содержания скетча

Назначение скетча

Скетч конфигурирует контроллер W5100 Arduino для работы с протоколом UDP и передают тестовую строку широковещательным пакетом в локальную сеть.

Используемые библиотеки

Для работы потребуются две библиотеки.

Используемые библиотеки.

Сетевые установочные данные

Установочные данные в основном касаются информации, необходимой для работы в локальной (глобальной) сети.

Сетевые установочные данные.

Установочные данные контроллера W5100. Для самого контроллера задаются: MAC (MyMAC), IP (MyIP). IP контроллера W5100 должен быть уникальными для локальной сети, а MAC должен быть уникальным во Вселенной. Но, можно его задать и случайным образом или установить равным МАС устройству, вышедшего из применения, например, не используемой сетевой карте. Кроме того, с помощью MAC производится идентификация устройства на сервере народного мониторинга.
Установочные данные локальной сети. Для взаимодействия с локальной сетью задаются: IP локального сервера DNS (MyDNS); IP шлюза Internet (MyGateway); маска локальной подсети (MySubnet); номер локального порта UDP (localPort); переменная для хранения IP адреса сервера народного мониторинга (NMDNS), полученного от службы DNS.

Широковещание. Следующим блоком идут установки для широковещательных пакетов UDP. В большинстве случаев, данные в локальной сети передаются от источника IP(Tx) к приемнику IP(Rx). Но существует возможность передавать пакеты нескольким пользователям одновременно, несмотря на имеющиеся у них уникальные IP. Такой способ называется широковещанием (broadcast). Реализуется он заданием специального широковещательного адреса. Особенностью этого адреса является задание четвертого октета IP равным 255 (bin = 1111 1111). В данном случае адрес для широковещательной передачи будет: IPAddress IPBC ( 192, 168, 0, 255 ). Пакеты, отправляемые на такой адрес, будут приниматься всеми устройствами в локальной сети. Пакеты будут адресоваться на порт PORTBC = 8887 принимающих устройств. Этот порт должен быть указан для всех устройств, в качестве UDP порта входящих сообщений.

Данные сервера народного мониторинга. Включают IP адрес byte IPNM[] = { 185, 245, 187, 136 }. Его можно получить через любую службу доменных имен или через командную строку.

Запрос IP сервера народного мониторинга.

Зеленым маркером отмечен запрос. Желтым маркером — ответ.

И порт int portNM = 8283.

Порт сервера народного мониторинга.

Настройка и запуск (Setup)

В модуле настройки и запуска производится задание параметров и запуск контроллера W5100, последовательного порта, проверка наличия контроллера W5100 и сетевого подключения, запускается служба UDP.

Рабочий цикл (Loop)

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

Проверка времени очередной отправки пакета осуществляется с использованием управляющего оператора if сравнением заданного времени отправки TxLUTime с текущим временем millis(). Если при проверке millis() превышает заданное время отправки, то процедура формирования и отправки пакета выполняется.

Формирование пакета производится в два этапа.
Первый этап. Формируется строка сообщения strlip (string local IP).
Для примера она состоит из строковой константы «MeteoData Local User» и текущего времени в миллисекундах millis(). Для удобства восприятия строка завершается признаком окончания строки с пробелом «; «.
Второй этап. Строка strlip преобразуется в массив символов ttsBClip (transmit text string broadcast local IP) . Преобразование строки в массив обусловлено посимвольной передачей данных.

Отправка сообщения производится заданием контроллеру IP получателя (IPBC) и порта (PORTBC); передачей контроллеру отправляемого сообщения (ttsBClip). При получении отправляемого сообщения контроллер посимвольно передает его в локальную сеть по протоколу UDP. После завершения передачи сообщения контроллер завершает сеанс связи.

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

Для подтверждения правильности передаваемых данных формируемая строка strlip и ее длина lenBClip выводятся в последовательный порт.

Процедура отправки сообщения на сервер народного мониторинга аналогична рассмотренной процедуре и в данной публикации не рассматривается.

Проверить отправку сообщения в локальную сеть возможно с помощью программы TCP/IP Builder.

Если в TCP/IP Builder пакеты получены, то задача, поставленная в данной публикации, выполнена. Широковещательные пакеты могут быть приняты любым устройством в локальной сети. Следующими этапами развития проекта домашней метеостанции являются: подключение базовой станции и требуемых датчиков; формирование и отправка данных потребителям в локальной сети и на сервер народного мониторинга; получение актуального IP адреса сервера народного мониторинга через службу DNS; разработка устройства приема широковещательных пакетов и отображение принимаемых данных.

Проверка отправки UDP пакетов в локальную сеть (TCP/IP Builder)

Проверить отправку UDP пакетов в локальную сеть можно с помощью программы TCP/IP Builder, установленной на локальный компьютер.

При запуске программы у меня появляется окно

Ошибка TCP/IP Builder.

Эта ошибка возникает из-за невозможности получить IP адрес компьютера, на котором открывается программа. С этим фактом надо смириться и нажать «OK». Откроется главное окно программы.

Рабочее окно TCP/IP Builder.

Для получения пакетов необходимо произвести настройку. Для настройки требуется указать:

  • Собственный IP адрес (Local IP);
  • Собственный порт;
  • IP адрес корреспондента (IP);
  • Порт корреспондента;
  • Протокол соединения (TCP/UDP).

Получение собственного IP адреса

Для получения собственного IP адреса необходимо:

  • открыть окно «Выполнить» (Win+R);
  • в окне набрать команду «cmd» (откроется cmd.exe);
  • в командной строке набрать команду «ipconfig»;
  • в выведенных данных найти IPv4 адрес.
Определение собственного IP адреса.

Это значение — 192.168.0.139 и есть локальный IP адрес. Это значение не является постоянным. Как правило, для устройств в локальной сети IP адреса, при включенной службе DHCP, определяются роутером. При выключении устройства IP адрес освобождается и при следующем включении ему может быть назначен другой свободный IP адрес.

Собственный порт

Номер собственного порта соответствует заданному в скетче.

Порт UDP локального IP.

IP адрес корреспондента

IP адрес корреспондента соответствует заданному в скетче.

IP адрес корреспондента.

Порт корреспондента

Порт корреспондента, так же задан скетче.

Порт корреспондента.

Протокол соединения

В качестве протокола соединения выбирается UDP.

Выбор протокола UDP.

Установление соединения

После задания всех данных требуется установить соединение. Для этого необходимо нажать на кнопку «Create Socket».

Получение данных

После установления соединения, при включенном сервере, на экране раз в тридцать секунд (как задано в скетче) начнут появляться пересылаемые данные.

Приём данных.

Если данные не принимаются, то причин может быть много: ошибка в скетче, неисправный контроллер W5100, отсутствие соединения с локальной сетью, неполадки в локальной сети, неправильное задание данных для TCP/IP Builder и т.д. Есть где развернуться творческой личности! Будем надеяться, что все срослось и данные приходят. 🙂

Перехват данных от метеостанции Misol Arduino

Человек непрерывно взаимодействует с внешней средой. Наиболее актуальными характеристиками внешней среды являются метеопараметры (температура, давление влажность, скорость и направление ветра и др.). Для измерения их значений были разработаны различные средства измерения (термометр, барометр, гигрометр, анемометр). Измеренные значения отображаются на различного вида экранах и табло. Объединение средств измерений и средств отображения в одном устройстве я буду называть метеостанцией.

Китайские друзья выпускают метеостанции марки Misol, которые состоят из комплекта (блока) внешних датчиков с термо-гидро передатчиком

Блок внешних датчиков метеостанции Misol.

и дисплея, на котором отображаются измеренные значения

Модуль дисплея метеостанции Misol.

Передача данных от внешних датчиков на дисплей осуществляется по радиоканалу на частоте 433 МГц. Технические характеристики определяют дальность передачи данных не более 100 метров (на открытой местности). Если передача данных происходит через радиопоглощающие препятствия, то дальность передачи данных значительно сокращается. Для повышения дальности передачи данных требуется использовать другие способы передачи, для чего требуется перехватывать данные от внешних датчиков.

Подключение к модулю передатчика Misol

Все данные с внешних датчиков собираются в термо-гидро передатчике

Термо-гидро передатчик метеостанции Misol.

Для подключения к нему необходимо три провода: Земля (черная метка — черный провод); +3,3 (синяя метка — зеленый провод); Сигнал (желтая метка — желтый провод).

Подключение к термо-гидро передатчику метеостанции Misol.

Подключение сигнала выполнено через резистор 220 Ом (в кембрике). Для подключения использовался мягкий телефонный четырехпроводный кабель. Одна жила (красная) остается свободной. Кабель выпускается наружу через приоткрытый отсек питания. К Arduino Mega сигнал подключается к выводу D2 (Interrupt 0). Остальные провода по предназначению (земля, +3,3 В).

Временные параметры пакета импульсов

Данные между модулем термо-гидро передатчика и дисплеем передаются пакетами. В пакете необходимо было определить параметры импульсов и размерность пакетов (число импульсов). Измерения производились по экрану осциллографа.

Временные параметры импульсов пакетов метеостанции Misol.

В результате анализа временных диаграмм и сравнения с известными способами кодирования информации в радиотехнических системах было установлено, что 0 кодируется импульсом 500 мкс, 1 – 1500 мкс, а пауза составляет 1000 мкс.

 Для декодирования при приеме достаточно отслеживать нарастающий фронт передаваемого импульса и измерять его длительность (интегрировать принимаемый сигнал) и принимать решение о принимаемом символе.

Отслеживать нарастающий фронт импульсов удобно через механизм прерываний микроконтроллера Atmel (МК), на базе которого построена плата Arduino Mega.

Алгоритм декодирования символа следующий: отслеживается изменение (перепад) входного сигнала (или нарастание или спад). В случае нарастания (начало импульса) запускается измерение длительности импульса. В случае спада (конец импульса) измерение длительности останавливается. По длительности импульса принимается решение о принятом символе 0 или 1.

Дальнейший анализ проводился по результатам приема пакета Arduino.

Программа приема пакета импульсов метеостанции Misol Arduino

//  Программа декодирования последовательности передаваемых импульсов метеостанции Misol
byte bitmas[8];
byte bytemas[255];
byte rxpin = 2;              //Пин подключения выхода приемника. Вход Int0
byte RxPinStateOld, RxPinStateNew;     //Значения входа
byte rxb;                    //Принятый бит
byte nbit = 0;               //Количество принятых бит в байте
byte nbyte = 0;              //Количество принятых байт
byte vbyte;                  //Десятичное значение байта
byte errorx;                 //Ошибка приема
volatile unsigned long timpb, timpe, timp, tpause;   //Время начала, конца, длительность импульса, паузы
byte EndPacket = 1;         //Флаг окончания передачи пакета
byte impulse = 0;           //Флаг импульса: 0 - пауза, 1 - импульс
byte Int0was = 0;           //Флаг прерывания

// ***** Бит в байт *****
void BitToByte() {
  byte k = 128;
  vbyte = 0;
  for (int i = 0; i < 8; i++) {
    vbyte = vbyte + bitmas[i] * k;
    k = k / 2;
  }
} // *****

// ***** Прием импульса (Прерывание) *****
void int0rxreceive() {                //
  RxPinStateOld = RxPinStateNew;      //Сохранение предшествующего состояния
  RxPinStateNew = digitalRead(rxpin);  //Получение нового значения

  //Анализ состояний
  if (RxPinStateOld == LOW && RxPinStateNew == HIGH) { //Фронт импульса
    //Старт приема импульса
    timpb = micros(); //Фиксация времени начала импульса
    impulse = 1;      // Установка флага импульса

  }

  else if (RxPinStateOld == HIGH && RxPinStateNew == LOW) //Спад импульса
  { //Окончание приема импульса
    timpe = micros();  //Фиксация времени окончания импульса
    impulse = 0;       //Сброс флага импульса
  }

  Int0was = 1;
}      // *** Окончание приема импульса

// *** Setup ***
void setup() {
  // put your setup code here, to run once:
  attachInterrupt(0, int0rxreceive, CHANGE);    //Подпрограмма обработки принимаемого импульса на 2 (Int0) DPIN
  Serial.begin(230400);
}// *** End setup


// *** Loop ***
void loop() {

  if (Int0was == 1) {     //Обработка прерывания
    if (impulse == 0) {   //Декодирование импульса
      timp = timpe - timpb;
      if (timp > 4500 && timp < 5500) {
        rxb = 0;
      }
      else if ( timp > 12500 && timp < 15500) {
        rxb = 1;
      }        //Окончание принятия решения
      else {
        goto noimp;
      }
      bitmas[nbit] = rxb;   //Присвоение значения биту
      nbit++;               //Определение позиции следующего бита
      if (nbit == 8) {      //Проверка завершения приема байта
        nbit = 0;           //Завершение приема байта
        BitToByte();
        bytemas[nbyte] = vbyte;
        ++nbyte;
        EndPacket = 0;      //Сброс флага окончания обработки пакета
        if (nbyte == 255) {
        }
      }

noimp: {                    //Ошибка приема.

      }

    } //End Прием импульса

    //Подготовка к приему пакета
    nbit = 0;
  } // *** Окончание обработки прерывания


  // *** Определение длительности паузы
  tpause = micros() - timpe;
  if ( tpause > 10500 && EndPacket == 0 ) {  //Признак паузы
    //Пауза

    //Вывод пакета в паузе
    Serial.println (" End data packet: ");
    Serial.print(" Tpause = ");   //Отображение принятых байт
    Serial.println(tpause);
    Serial.print("RxByte(");      
    Serial.print(nbyte);
    Serial.print(") = ");
    for (byte i = 0 ; i < nbyte; i++) {
      Serial.print(bytemas[i]);
      Serial.print(", ");
    }
    Serial.println();
    Serial.println (" ***** ");
    Serial.println();
  } // *** Окончание определения длительности паузы

}//End loop

Обработка пакета данных метеостанции Misol

Для выделения необходимых данных из пакета необходимо производить его декодирование. Неоценимую помощь в этом оказал неизвестный герой. К сожалению ссылка на его работу была утрачена в веках, а полнотекстный поиск не дал результатов. Благодарность ему всегда будет жить моем сердце.

Пакет может содержать 11 (короткий) или 22 (длинный) байт данных. Длинный пакет состоит из двух коротких. Поэтому рассматриваться будет только короткий пакет. Пакет состоит из одного синхробайта и десяти информационных байт. Каждый байт (восемь бит) разделяется на четверки (тетрады (англ. — nibbles) битов.

Информационное содержание пакета данных метеостанции Misol.

Требуемое значение, в зависимости от требуемого числа значений кодируется одной, двумя или тремя тетрадами:

  • abc: Серийный номер (device identifier (SN — serial number))
  • def: Температура (temperature)
  • gh: Влажность (humidity (H %))
  • ij: Скорость ветра средняя (average wind speed (low byte) (AW))
  • kl: Скорость ветра в порыве (gust wind speed (low byte) (GW))
  • m:  Неизвестное назначение (unknown (UK))
  • n: Счетчик дождя (старшая тетрада) (rainfall counter (RC))
  • op: Счетчик дождя (младшие тетрады) (rainfall counter)
  • q: Уровень заряда батареи (battery-low indicator (LB))
  • r: Направление ветра (wind direction (DW))
  • st: Контрольная сумма (checksum (CRC))

Пример пакета данных:

Пример пакета данных с разбивкой на тетрады и привязки к значениям.

Одной тетрадой можно закодировать 16 значений; двумя — 256 значений; тремя — 4096 значений. Каждое значение представляет собой целое число, которое требуется преобразовать в заданную величину. Для преобразования применяются формулы пересчета.

Температура в градусах Цельсия (тетрады 5, 6 7) T = (Nh – 400) / 10
Пример: 2-10-3 = 2*16**2 + 10*16**1 + 3*16**0 = 512 + 160 + 3 = 675
T = (675 – 400)/10 = 27.5

Влажность H % (тетрады 8, 9) отображается непосредственными значениями. Например, 3-10 = 3*16**1 + 10*16**0 = 48 + 10 = 58 %

Средняя скорость ветра AW м/с (тетрады 10, 11) Naw*0,34

Скорость ветра в порыве GW м/с (тетрады 12, 13) Ngw*0.34

Счетчик осадков RC мм (тетрады 15, 16, 17) Nrc*0.3 (значение только накапливается! Для определения дифференциальной величины, например, за час, необходимо в начале каждого часа находить разницу между предшествующим и текущим значением).

Заряд батареи LB (тетрада 18) (значение не определено).

Направление ветра DW (градусы) (тетрада 19)

Определение направления ветра.

N — noth (север); E — eath (восток); S — south (юг); W — west (запад).

В пакете отсутствует величина давления. Она измеряется в модуле дисплея.

Программа декодирования пакета данных метеостанции Misol

// Программа декодирования пакетов данных метеостанции Misol
volatile byte bitmas[528];
volatile byte tetramas[132];
byte rxb;                    // Значение принятого бита
volatile int nbit = 0;
byte nbyte = 0;
byte rxpin = 2;              // Назначен пин 2 ExtInt0
volatile byte rxpinold, rxpinnew;     // Значения входа

volatile unsigned long timpb, timpe, timp, tpause, timpem ;   //Время начала, конца импульса, паузы
volatile byte imprx;

#define CRC3B   40  // Контрольная сумма первых трех байт. Отличается для каждого устройства! Считается по строке приема.


// ***** Подпрограммы *****

// ***** Прием импульса *****
void int0rxreceive() {
  rxpinold = rxpinnew;      //Сохранение предшествующего состояния
  rxpinnew = digitalRead(rxpin);  //Получение нового значения

  //Анализ состояний
  if (rxpinold == LOW && rxpinnew == HIGH) { // *** Фронт импульса
    //Старт приема импульса
    timpb = micros();
  }

  else if (rxpinold == HIGH && rxpinnew == LOW) // *** Спад импульса
  { //Окончание приема импульса
    timpe = micros();
    timpem = millis();
    timp = timpe - timpb;


    if (timp > 450 && timp < 550) {
      rxb = 1;
    }
    else if ( timp > 1250 && timp < 1550) {
      rxb = 0;
    } //Окончание принятия решения

    else {
      Serial.print("/ \n");
      goto noimp;
    }
    bitmas[nbit] = rxb; //Присвоение значения бита элементу массива
    nbit++;             //Определение позиции следующего бита
    imprx = 1;          // Флаг вывода данных

noimp: {
    }
  }
} // End Прием импульса *****

// Окончание подпрограмм


// ***** Setup *****
void setup() {

  attachInterrupt(0, int0rxreceive, CHANGE);    //Подпрограмма обработки принимаемого импульса на 2 DPIN (Interrupt 0)

  Serial.begin(115200);

  //Разметка для экранного вывода данных
  Serial.println("  Sync__  Serial__ Tempera_  Humid  AvWin GstWn UK RC_____ LB DW  CRC__");
} // End setup *****


// ***** Loop *****
void loop() {

  // *** Count Pause ***
  tpause = millis() - timpem;

  if (imprx == 1 && tpause > 200) {

    //****** Вывод пакета данных по тетрадам
    Serial.print(": ");

    //Сброс массива байтов
    for (int i = 0; i < 132; i++) {
      tetramas[i] = 0;
    }

    // *** Преобразование массива бит в массив тетрад
    byte nbyte = 0;
    byte j = 0;
    byte l = 0;
    byte k = 8;
    for (int i = 0; i < nbit; i++ ) {
      tetramas[l] = tetramas[l] + bitmas[i] * k;
      k = k / 2;
      j++;
      if (j == 4) {
        j = 0;
        l++;
        k = 8;
        Serial.print(tetramas[l - 1]);
        Serial.print(", ");
      }
    }
    Serial.println("***** ");
    //***

    //Контрольная сумма первых трех тетрад
    int sum = 0;
    for (byte i = 0; i < 3; i++) {
      sum = sum + tetramas[i];
    }

    //***** Рабочий цикл
    if ( sum == CRC3B) {
      //Преобразование тетрадных значений в float
      //Температура Temp
      int q = 256;
      byte s = 5;
      float Temp = 0;
      for (byte i = 0; i < 3; i++) {
        Temp = Temp + q * tetramas[i + s];
        q = q / 16;
      }
      Temp = (Temp - 400) / 10;
      Serial.print("Temperature = ");
      Serial.print(Temp);
      Serial.println(" *C");

      //Влажность Hum
      q = 16;
      s = 8;
      float Hum = 0;
      for (byte i = 0; i < 2; i++) {
        Hum = Hum + q * tetramas[i + s];
        q = q / 16;
      }
      Serial.print("Humidity    = ");
      Serial.print(Hum);
      Serial.println(" %");

      //Средняя скорость ветра AW
      q = 16;
      s = 10;
      float AW = 0;
      for (byte i = 0; i < 2; i++) {
        AW = AW + q * tetramas[i + s];
        q = q / 16;
      }
      AW = AW * 0.34;
      Serial.print("AW          = ");
      Serial.print(AW);
      Serial.println(" mps");

      //Скорость ветра в порыве GW
      q = 16;
      s = 12;
      float GW = 0;
      for (byte i = 0; i < 2; i++) {
        GW = GW + q * tetramas[i + s];
        q = q / 16;
      }
      GW = GW * 0.34;
      Serial.print("GW          = ");
      Serial.print(GW);
      Serial.println(" mps");

      //Счетчик осадков Rn
      q = 256;
      s = 15;
      float RnC = 0;
      for (byte i = 0; i < 3; i++) {
        RnC = RnC + q * tetramas[i + s];
        q = q / 16;
      }
      RnC = RnC * 0.3;
      Serial.print("Rain        = ");
      Serial.print(RnC);
      Serial.println(" mm");

      //Направление ветра
      byte DW = tetramas[19];
      Serial.print("DW          = ");
      Serial.print(DW);
      Serial.println("  N");

    } //*** Окончание рабочего цикла

    //Подготовка нового цикла приема пакета данных
    nbit = 0;
    imprx = 0;
  }
} // End loop *****

Полученные из пакета данных значения метеопараметров:

  • Temp — температура (0С, float);
  • Hum — влажность (%, float);
  • AW — средняя скорость ветра (м/с, float);
  • GW — скорость ветра в порыве (м/с, float);
  • RnC — уровень осадков (мм, float);
  • DW — направление ветра (номер направления, byte)

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

Объединение блока наружных датчиков с термо-гидро передатчиком метеостанции Misol с Arduino Mega будет называться базовой станцией.

Направлений развития проекта два:

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

Общая характеристика цифровых устройств

Совокупность логических элементов, выполняющих заданную логическую функцию, называется цифровым устройством.

Цифровые устройства классифицируются

По функциональной сложности:

  • логические элементы (и, и-не, или и др.);
  • функциональные узлы (триггеры, сумматоры, дешифраторы и т.д.);
  • радиоэлектронные средства Цифровые автоматы, микро ЭВМ и т.д.).

По конструктивной сложности:

  • интегральные микросхемы;
  • узлы;
  • платы;
  • устройства.

По принципам функционирования цифровые устройства подразделяются на устройства:

комбинационного типа. Устройством комбинационного типа называется такие устройства, состояние выхода (выходов) Y {Yi} которых однозначно определяется значениями входных переменных {Xi}.

Y(Y2,Y3..Yi) = f(X1, X2..)

накапливающего типа (устройства с памятью). Накапливающими устройствами называются такие устройства, состояние выхода (выходов) Y {Yi} которых однозначно определяется значениями входных переменных {Xi} и предшествующим состоянием Y(t-1).

Y (Yi) = f ({Xi} & Y(t-1))

Цели цифровой схемотехники

Предметом изучения цифровой схемотехники является широкий круг устройств, основанных на элементах, которые могут находиться лишь в двух состояниях: включено/выключено; которым соответствуют несовместные, значительно различающиеся уровни напряжения или токов, условно обозначаемые логическими понятиями 1 и 0. Изучение этой дисциплины сопряжено с необходимость использования аппарата дискретной математики для описания переменных и выполняемых над ними операциями с аналитической точки зрения и физических принципов действия различных электронных приборов при рассмотрении реальных образцов построения цифровых элементов и функциональных узлов на их основе.

В результате изучения цифровой схемотехники необходимо

ЗНАТЬ:

  • Основные типы цифровых элементов (назначение, принципы построения, основы функционирования, реализацию в интегральном исполнении, достоинства и недостатки);
  • правила анализа функционирования устройств, построенных с использованием цифровых элементов.

УМЕТЬ:

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

Логические переменные и физические значения

Вся цифровая схемотехника основывается на теоретических положениях, сформулированных в Булевой алгебре, которая в качестве объектов использует логические переменные.
Логическим переменным могут даваться различные имена. Чаще всего такими именами являются буквы латинского алфавита, например переменные A, B, C.

В качестве обозначений значений входных и выходных логических переменных также используют, принятые в алгебре обозначения: X — входная переменная, Y — выходная переменная. Если входных и выходных переменных несколько, то они будут отличаться индексами, например, X2, X1, X0 или Y2, Y1, Y0.

Значения логических переменных обозначают вербально, как правда (true) и ложь (false). Вербальные значения неудобны в многократном использовании, поэтому их замещают бинарными (логическими) значениями 0 (false) и 1 (true).

Над логическими переменными определяются логические операции. В качестве входных и выходных значений логических операций могут быть только логические (бинарные) значения.

При переходе от алгебраической реализации логических операций к схемотехнической возникает задача: каким образом закодировать входные и выходные значения логических переменных и каким образом реализовать логические операции?

В настоящее время наиболее распространена реализация логических операций на электронных схемах. Это обусловливает и электрический характер кодирования значений логических переменных. Наиболее распространенным способом кодирования значений логических переменных является потенциальное кодирование, когда значениям логических переменных 0 (false) и 1 (true) ставится в соответствие уровень напряжения U0 и U1. Все было бы хорошо, если бы цифровые схемы были бы идеальными. Однако это не так. Изготовить абсолютно идентичные логические элементы, поместить их в одни условия, запитать их одинаковым напряжением невозможно. Это приводит к тому, что для значений U0 и U1 невозможно задать какое-то точечное значение, например, U0 = 0 В, U1 = 5 В. Поэтому, для физических эквивалентов значений логических переменных задают интервальные значения.

Для цифровых схем с однополярным положительным значением напряжения питания, равным 5 В, к которым относится большинство современных цифровых схем:

(U0min = 0 В) < U0 < (U0max = 0,4 В),

(U1min = 2,4 В ) < U1 < (U1max = 5 В).

Графически предельные уровни напряжений для 0 и 1 показаны на рисунке.

Правильное соответствие физических значений логическим гарантируется при попадании физических значений в допустимые интервалы. При попадании физических значений в интервал неопределенности функционирование цифровой схемы будет непредсказуемым. Для логических элементов, выполняющих простейшие логические операции, существует так называемая передаточная характеристика, по которой можно точнее определить пределы физических значений U0 и U1 и напряжение переключения (Uпор.вх, Uпор.вых).

Помимо потенциального кодирования, в соответствии с физическими принципами функционирования цифровых схем, может применяться токовое кодирование. При токовом кодировании в качестве значений 0 и 1 может, например, использоваться направление протекания тока: втекающий ток — 1; вытекающий ток — 0, или значение такого тока.

В частности, при потенциальном кодировании также существует разнонаправленный ток 0 и 1.

Для логического 0 (левый рисунок) выходной ток управляющего логического элемента (ЛЭ) (DD1) будет втекающим, а входной ток управляемого ЛЭ (DD2) будет вытекающим.

Для логической 1 (правый рисунок) ситуация будет обратной: выходной ток управляющего логического элемента (DD1) будет вытекающим, а входной ток управляемого логического элемента (DD2) — втекающим.

Причем значения токов 0 и 1 будут отличаться в разы (миллиамперы и микроамперы соответственно).

Третьим параметром, который широко используется для кодирования логических значений, является время. Временное кодирование используется в системах передачи данных в видимом оптическом, инфракрасном, радио диапазоне. Логическое значение может кодироваться не только длительностью импульса излучения, но и его фазой.

Также логические значения могут кодироваться и любыми другими физическими величинами, например, освещенностью (включение/выключение осветительных приборов), емкостью (датчики приближения), частотой (сопряженная величина со временем) и т.д.

В большинстве случаев требуемая физическая величина первично преобразуется в напряжение/ток/время, а потом уже обрабатывается стандартными цифровыми схемами.