Использование onewire. встроенная библиотека

Урок 26. Подключение термодатчиков DS18B20 к Ардуино. Библиотека OneWire. Точный Ардуино термометр-регистратор

В уроке узнаем, как подключать к плате Ардуино датчик температуры DS18B20, как управлять им с помощью библиотеки OneWire, разработаем точный термометр.

Предыдущий урок     Список уроков     Следующий урок

DS18B20 это интегральный датчик температуры с цифровым последовательным интерфейсом 1-Wire. Датчик с уникальными параметрами и функциональными возможностями. Я написал статью о нем.  Сейчас я подчеркну особенности этого устройства, благодаря которым он получил такое широкое распространение. Датчику DS18B20 свойственны:

  • Высокая точностью измерения, погрешность не превышает 0,5 °C. Датчик откалиброван при изготовлении, дополнительной калибровки не требует.
  • Разрешающая способность задается программно и достигает 0,0625 °C при максимальном разрешении 12 бит.
  • Широкий диапазон измерения температуры -55 … + 125 °C.
  • Датчик осуществляет преобразование температуры в цифровой код, т.е. дополнительного АЦП не требует.
  • Передача информации осуществляется по последовательному протоколу 1-Wire, требуется только три провода для подключения термодатчика к микроконтроллеру.
  • Поддерживает режим ”паразитного питания”, в котором датчик получает питание от линии связи. В этом режиме для подключения устройства к микроконтроллеру достаточно двух проводной линии связи.
  • На одну линию связи может быть включено несколько датчиков.

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

Подключение датчика DS18B20 к микроконтроллеру.

Самый распространенный вариант исполнения DS18B20 в корпусе TO-92.

Выводы на схемах подключения указаны для такого варианта. Существуют две стандартные схемы подключения DS18B20 к микроконтроллеру.

Схема питания с внешним источником.

Все просто: земля, питание, сигнал данных. Подтягивающий резистор строго необходим и устанавливается вблизи вывода микроконтроллера.

Схема в режиме ”паразитного питания” позволяет подключить термодатчик к микроконтроллеру всего двумя проводами, что особенно важно при размещении датчика на значительном расстоянии от контроллера.

В этом режиме сигнал шины данных заряжает внутренний конденсатор датчика и за счет энергии на нем происходит питание устройства при низком уровне на шине. У режима ”паразитного питания ” много особенностей. Можно почитать по ссылке. Сейчас скажу главное, что в этом режиме не гарантируется работа датчика при температуре свыше 100 °C. Надо использовать схему с внешним питанием.

Для такого случая я использую следующую схему.

Датчик работает в режиме внешнего питания, которое запасается через диод на дополнительном конденсаторе. В моих устройствах схема работает без проблем, но я не уверен, что такой вариант поддерживает библиотека OneWire. Я использовал эту схему только на PIC контроллерах с собственной библиотекой.

Обмен информацией с термодатчиком по шине интерфейса 1-Wire.

Если кто-то желает узнать подробную информацию по этому вопросу я опять дам ссылку на статью о DS18B20. Сейчас я перечислю необходимые нам операции работы с устройством:

  • Инициализация – последовательность импульсов, с которых начинается любая операция на шине.
  • Запись байта – передача байта данных в устройство DS18B20.
  • Чтение байта – прием данных из устройства DS18B20.

Этих трех операций достаточно для работы с термодатчиком, все они поддерживаются библиотекой OneWire.

Библиотека Ардуино OneWire для работы с интерфейсом 1-Wire.

Загрузить последнюю версию библиотеки OneWire  можно по этой ссылке. Как установить ее можно посмотреть в уроке 9.

Нас интересуют следующие методы.

OneWire( uint8_t pin);

Конструктор, Pin – номер вывода, к которому подключен датчик.

OneWire sensDs (14);  // датчик подключен к выводу 14

uint8_t reset(void);

Инициализация операции на шине. С этой команды должна начинаться любая операция обмена данными. Возвращает:

  • 1 – если устройство подключено к шине (был ответный импульс присутствия);
  • 0 – если устройство отсутствует на шине (ответного импульса не было).

void write(uint8_t v, uint8_t power = 0);

Запись байта. Передает байт в устройство на шине.

  • v – байт;
  • power – признак выбора режима питания;
    • power=0 – питание от внешнего источника
    • power=1 – “паразитное” питание.

uint8_t read(void);

Чтение байта – принимает байт, переданный устройством. Возвращает значение принятого байта.

Этих команд вполне достаточно, чтобы работать с датчиком DS18B20. Можно добавить методы записи и чтения блоков байтов и функцию вычисления контрольной суммы.

void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0);

Запись блока байтов.

  • buf – указатель на массив;
  • count – число байтов;
  • power – признак выбора режима питания.

void read_bytes(uint8_t *buf, uint16_t count);

Чтение блока байтов.

  • buf – указатель на массив;
  • count – число байтов.

static uint8_t crc8(const uint8_t *addr, uint8_t len);

Функция вычисления 8ми разрядной контрольной суммы.

  • addr – указатель на массив данных;
  • len – число байтов.

Возвращает вычисленную сумму.

Последовательность операций работы с DS18B20.

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

  • sensDs.reset() – Инициализация. Выполняет сброс шины, готовит ее для выполнения новой операции.
  • sensDs.write(0xCC, power) – Команда пропуск ROM. У нас только один датчик на шине. Поэтому нет необходимости в поиске устройства с нужным адресом. Мы эту операцию пропускаем.
  • sensDs.write(0x44, power) – Команда инициирует измерение температуры.
  • Пауза 1 сек. Ожидание на время, необходимое для выполнения датчиком преобразования температуры. Это время зависит от выбранной разрешающей способности датчика. Мы используем максимальное разрешение 12 бит.  Это разрешение установлено в датчике по умолчанию. Время преобразования для него – 750 мс. Если необходима другая разрешающая способность, то ее необходимо задать дополнительными командами.
  • sensDs. reset() – Инициализация. Мы собираемся выполнить новую операцию на шине 1-Wire.
  • sensDs.write(0xCC, power) – Команда пропуск ROM.
  • sensDs.write(0xBE, power) – Команда чтения памяти датчика. Команда используется для чтения всех 9ти байтов памяти DS18B20.
Байт 0 Температура мл. байт
Байт 1 Температура ст. байт
Байт 2 Th регистр порога сигнализации
Байт 3 Tl регистр порога сигнализации
Байт 4 Регистр конфигурации
Байт 5 Зарезервирован
Байт 6 Зарезервирован
Байт 7 Зарезервирован
Байт 8 Циклический код CRC
  • read_bytes(buf, 9) – Чтение 9ти байтов данных.
  • crc8(addr, 8) – Вычисление контрольного кода данных.
  • Сравнение контрольного кода с принятым.

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

Отрицательная температура записывается в дополнительном коде.

Младший разряд имеет вес 0,0625 °C.

Проект Ардуино термометра с использованием датчика DS18B20.

Создадим термометр с функциями, аналогичными устройствам из урока 24 и урока 25. Использование термодатчика DS18B20 позволяет добиться:

  • высокой точности измерения  0,5 °C;
  • высокой разрешающей способности 0,0625 °C:
  • диапазон измерения составляет -55 … +125 °C.

Схема термометра с датчиком DS18B20.

Led индикатор подключен по привычной схеме из предыдущих уроков. Есть два варианта подключения термодатчика: с внешним питанием и ”паразитным питанием.”

На моем макете устройство выглядит так.

Резидентная программа Ардуино термометра.

Структура и большая часть программы из предыдущих уроков 24 и 25. Последовательность операций для DS18B20 подробно описаны выше. Поэтому я сразу приведу скетч программы.

// термометр, датчик DS18B20
#include
#include
#include<\p>

#define POWER_MODE  0 // режим питания, 0 – внешнее, 1 – паразитное

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

OneWire sensDs (14);  // датчик подключен к выводу 14

byte bufData[9];  // буфер данных
float temperature;  // измеренная температура

void setup() {
  MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  Serial.begin(9600); // инициализируем порт, скорость 9600 
}

void loop() { 

  sensDs.reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM
  sensDs.write(0x44, POWER_MODE); // инициализация измерения
  delay(900);  // пауза 0,9 сек
  sensDs.

reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM 
  sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика 
  sensDs.

read_bytes(bufData, 9);  // чтение памяти датчика, 9 байтов

  if ( OneWire::crc8(bufData, 8) == bufData[8] ) {  // проверка CRC
    // данные правильные
    temperature=  (float)((int)bufData[0] | (((int)bufData[1]) = 0) {
      // температура положительная
      disp.print((int)(temperature * 10.

), 4, 1);        
    }
    else {
      // температура отрицательная
      disp.print((int)(temperature * -1 * 10.), 3, 1);        
      disp.digit[3]= 0x40;  // отображается минус
    }
    disp.

digit[1] |= 0x80;  // зажечь точку второго разряда                
       
    // передача температуры на компьютер
    Serial.println(temperature);   
  }
  else { 
    // ошибка CRC, отображается —-
      disp.digit[0]= 0x40;
      disp.

digit[1]= 0x40;
      disp.digit[2]= 0x40;
      disp.digit[3]= 0x40;        
  }   
}

//————————————– обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

Загрузить скетч можно по этой ссылке загрузить . Программа использует библиотеки OneWire, MsTimer2 и Led4Digits.

Не забудьте выбрать в программе режим питания датчика:

#define POWER_MODE  0 // режим питания, 0 – внешнее, 1 – паразитное

Программа верхнего уровня для Ардуино термометра-регистратора.

С этим устройством работает программа Thermometer из урока 24. В уроке можно загрузить программу, получить информацию по установке и применению программы.

Реализация измерения температуры параллельным процессом.

В проекте термометра управление термодатчиком DS18B20 происходит в основном цикле программы. Задержка 0,9 секунд реализована функцией delay(). Программа на это время зависает и никаких других действий производить не может. Хорошо, что нам в термометре больше ничего делать не надо. А если у нас сложная программа с множеством других задач.

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

// термометр, датчик DS18B20
#include
#include
#include<\p>

#define POWER_MODE  0 // режим питания, 0 – внешнее, 1 – паразитное
#define MEASURE_PERIOD 500  // время измерения, * 2 мс

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

OneWire sensDs (14);  // датчик подключен к выводу 14

int timeCount;     // счетчик времени измерения
boolean flagSensReady;  // признак готовности данных с датчика
byte bufData[9];  // буфер данных
float temperature;  // измеренная температура

void setup() {
  MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  Serial.begin(9600); // инициализируем порт, скорость 9600 
}

void loop() { 

  if ( flagSensReady == true ) {
    flagSensReady= false;
    // данные готовы

   if ( OneWire::crc8(bufData, 8) == bufData[8] ) {  // проверка CRC
      // данные правильные
      temperature=  (float)((int)bufData[0] | (((int)bufData[1]) = 0) {
        // температура положительная
        disp.print((int)(temperature * 10.

), 4, 1);        
      }
      else {
        // температура отрицательная
        disp.print((int)(temperature * -1 * 10.), 3, 1);        
        disp.digit[3]= 0x40;  // отображается минус
      }
      disp.

digit[1] |= 0x80;  // зажечь точку второго разряда                
       
      // передача температуры на компьютер
      Serial.println(temperature);   
    }
    else { 
      // ошибка CRC, отображается —-
        disp.digit[0]= 0x40;
        disp.

digit[1]= 0x40;
        disp.digit[2]= 0x40;
        disp.digit[3]= 0x40;        
    }   
  } 
}

//————————————– обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора

  // управление датчиком DS18B20 паралллельным процессом
  timeCount++; if ( timeCount >= MEASURE_PERIOD ) { timeCount=0; flagSensReady=true; }
 
  if (timeCount == 0) sensDs.reset();  // сброс шины  
  if (timeCount == 1) sensDs.write(0xCC, POWER_MODE); // пропуск ROM
  if (timeCount == 2) sensDs.write(0x44, POWER_MODE); // инициализация измерения

  if (timeCount == 480) sensDs.reset();  // сброс шины
  if (timeCount == 481) sensDs.write(0xCC, POWER_MODE); // пропуск ROM 
  if (timeCount == 482) sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика 
   
  if (timeCount == 483 ) bufData[0]= sensDs.

read();  // чтение памяти датчика
  if (timeCount == 484 ) bufData[1]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 485 ) bufData[2]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 486 ) bufData[3]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 487 ) bufData[4]= sensDs.

read();  // чтение памяти датчика
  if (timeCount == 488 ) bufData[5]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 489 ) bufData[6]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 490 ) bufData[7]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 491 ) bufData[8]= sensDs.

read();  // чтение памяти датчика    
}

После получения данных с датчика DS18B20 формируется признак о готовности данных и в основном асинхронном процессе они могут быть использованы.

В обработчике прерываний все операции с датчиком выполняются по принципу – одна операция с байтом за один цикл прерывания.  Во время паузы 0,9 сек, вообще ничего не делается. Так что в основном цикле может выполняться другая задача без значительной задержки.

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

Предыдущий урок     Список уроков     Следующий урок

Источник: http://mypractic.ru/urok-26-podklyuchenie-termodatchikov-ds18b20-k-arduino-biblioteka-onewire-tochnyj-arduino-termometr-registrator.html

Arduino и 1-Wire – эмуляция ведомого устройства с помощью библиотеки OneWireSlave

Библиотека позволяет использовать на линии в качестве ведомого устройства. Подробнее о OneWire можно прочитать . Теоретически на линии может быть до 2^48 или 281 триллионов ведомых устройств.

С помощью этой библиотеки на одну линию совместно с датчиками температуры и прочими устройствами, использующими протокол 1-Wire, можно подключить несколько ардуин.OneWireSlave(uint8_t pin);— конструктор, параметром указывается пин ардуины для OneWire линии.
void setRom(char rom[8]);— устанавливает тип и адрес устройства.

Если библиотека скомпилирована с поддержкой расчета контрольной суммы crc8, то она подсчитывается и заносится в последний байт rom.
bool waitForRequest(bool ignore_errors);— функция блокирует выполнение программы и ожидает обращения к текущему устройству.

Функция возвращает управление программе, если ведущее устройство отправило команду MATCH ROM с адресом текущего устройства или команду SKIP ROM. Во время ожидания функция принимает участие в поисковых запросах ведущего устройства и отвечает на команду READ ROM. Таким образом обеспечивается поддержка базового протокола.

Если параметр ignore_errors установлен, то функция будет игнорировать ошибки чтения/записи, иначе вернет FALSE.
bool waitReset(uint16_t timeout_ms);— функция ждет RESET импульса на линии, после чего возвращает управление программе. Параметр timeout_ms устанавливает время в миллисекундах, по истечение которого функция принудительно вернет управление программе.

Если timeout_ms равен 0, то программа будет вечно ожидать RESET импульс, пока не дождется. Стандартное значение timeout_ms — 1000. Возвращает TRUE, если принят сигнал RESET, в случае слишком короткого или слишком длинного сигнала или по истечение времени ожидания вернет FALSE.
bool presence(uint8_t delta);— функция посылает сигнал PRESENCE согласно протоколу.

Если в конце передачи сигнала на линии по какой-либо причине будет низкий уровень сигнала, функция вернет FALSE.
bool search();— функция участвует в процедуре поиска устройств, описанной в документации протокола OneWire. Возвращает TRUE, если при поиске было найдено текущее устройство, иначе FALSE.
uint8_t sendData(char buf[], uint8_t len);— отсылает на линию указанный объем данных.

Возвращает количество отосланных байт данных.
uint8_t recvData(char buf[], uint8_t len);— считывает с линии указанный объем данных и заносит их в указанный буфер. Возвращает количество успешно считанных байт данных.
void send(uint8_t v);— отсылает на линию один байт данных.
uint8_t recv(void);— считывает с линии один байт данных.

void sendBit(uint8_t v);— отсылает на линию один бит данных.
uint8_t recvBit(void);— считывает с линии один бит данных.
static uint8_t crc8(char addr[], uint8_t len);— функция подсчитывает контрольную сумму по алгоритму crc8 указанного объема данных.
uint8_t errno;Если выполнение функции закончилось неудачей, то она занесет номер ошибки в эту переменную.

Ошибки:

ONEWIRE_NO_ERROR при выполнении функции не возникло никаких исключений.
ONEWIRE_READ_TIMESLOT_TIMEOUT истекло время ожидания таймслота от ведомого устройства при чтении с линии. Устанавливается функциями recv*.
ONEWIRE_WRITE_TIMESLOT_TIMEOUT истекло время ожидания таймслота от ведомого устройства при записи на линию. Устанавливается функциями send*.
ONEWIRE_WAIT_RESET_TIMEOUT истекло время ожидания импульса RESET на линии. Устанавливается функцией waitReset.
ONEWIRE_VERY_LONG_RESET импульс RESET принят, но оказался слишком длинным (возможно это не RESET, а что-то другое). Устанавливается функцией waitReset.
ONEWIRE_VERY_SHORT_RESET импульс RESET оказался слишком коротким. Такая ошибка может появиться, если при ожидании RESET сигнала другое устройство начало передачу данных.
ONEWIRE_PRESENCE_LOW_ON_LINE по окончании передачи PRESENCE сигнала на линии оказывается низкий уровень сигнала. Согласно протоколу все устройства в момент считывания сигнала с линии должны были прекратить передачу импульса PRESENCE.

Пример скетча, эмулирующего работу ключа ibutton с микросхемой

#include “WProgram.h” #include “OneWireSlave.h” char rom[8] = {0x01, 0xAD, 0xDA, 0xCE, 0x0F, 0x00, 0x00, 0x00}; OneWireSlave ds(8); void setup() { ds.setRom(rom); } void loop() { ds.waitForRequest(false); }

В данном случае функция waitForRequest вернет FLASE с ошибкой ONEWIRE_READ_TIMESLOT_TIMEOUT, т.к. домофон (или его эмулятор) не выбирает устройство, а только считывает его адрес.

В случае обрыва линии, на выводе может возникнуть неопределенное состояние, поэтому рекомендуется вывод ардуины подключить к земле через резистор 220к.

Заметка: с реальным домофоном без дополнительной обвязки ардуина работать не будет, т.к. в современные домофоны устанавливаются защиты от копированных ключей.

Защита срабатывает на основе некоторых электрических и возможно временных параметров.

Скачать библиотеку:

Источник: http://robocraft.ru/blog/arduino/302.html

Arduino: осваиваем цифровой термодатчик и 1-Wire – «Хакер»

Моргания лампочки и замыкание контактов — дело интересное и полезное для первых шагов. Но, как все мы помним со школы, чем нагляднее эксперимент, тем он интереснее.

Я продолжу развивать проект из предыдущих серий, и сегодня мы прикрутим термодатчик 1-Wire для того, чтобы контролировать температуру в твоем многострадальном холодильнике.

Того и гляди, скоро у тебя появится «умный» холодильник :).

В предыдущих сериях

Так как я продолжаю повествование с некоей точки, а не с самого начала, то пройдусь по тому, что уже имеется. В нашем арсенале Arduino mega2560 с поднятой ОСРВ scmRTOS.

Прошивка позволяет моргать светодиодом L на плате в разных последовательностях в зависимости от «аварийного» или «нормального» состояния, а также «плеваться» в консоль грязными ругательствами (ведь ты именно такие выбрал?) в качестве уведомления об изменении состояния.

«Нормальность» состояния определяется замкнутостью контактного датчика. Последовательность можно менять из консоли. Исходники проекта выложены на GitHub.

Вдохнем новизны

Идея прикрутить термодатчик зародилась у меня еще до того, как я начал делать этот проект. Последовательность действий (а именно так и нужно действовать — последовательно и не пытаться забегать вперед) оттягивала этот момент, и я особо не забивал себе голову деталями. Но вот время пришло.

Так в чем проблема? А вот в чем: можно было взять обычный резистивный термодатчик и использовать встроенный АЦП микропроцессора.

Но! Я взялся за этот проект с правилом: минимум паяльника и дополнительного нестандартного оборудования, все из коробки.

При использовании же резистивного термодатчика необходимо городить делитель напряжения, а значит, требуется минимальное, но погружение в схемотехнику. Так что этот вариант отпал.

Остался второй вариант — цифровой термодатчик. Правда, с ним тоже беда. Цифровой термодатчик подключается по интерфейсу 1-Wire, а такого интерфейса на плате нет. Зато есть вариант минимальными усилиями сделать программную эмуляцию этого интерфейса.

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

Немного о самом 1-Wire

1-Wire — это так называемый однопроводный интерфейс. Примечателен он тем, что для обмена данными с устройствами по этому интерфейсу требуется всего один сигнальный провод и один провод «земли».

Что еще более примечательно, устройства спроектированы таким образом, что по этому же сигнальному проводу они и «кормятся» (то есть для питания устройства используется все тот же сигнальный провод), такой режим называется «паразитным питанием».

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

Для того чтобы начать сессию обмена данными, необходимо сформировать сигнал «сброс». Для этого мастер передает в линию данных 0 на время не менее 480 мкс. После чего мастер отпускает линию данных и начинает слушать линию.

За счет резистора подтяжки линия данных установится в 1. Если на линии присутствует устройство (датчик), то он передаст мастеру подтверждение сброса, для этого он удерживает линию данных в 0 на время 60–240 мкс.

Считав состояние линии, мастер узнает о присутствии на шине устройств, готовых к обмену.

Старт обмена данными

1-Wire обладает еще одной особенностью: передача битов осуществляется не уровнями сигнала, а временными задержками.

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

Чтобы передать 0, необходимо установить в линии 0 на 15 мкс, а затем держать 0 на линии еще 60–120 мкс.

Передача данных 1-Wire

Честный 1-Wire

Предложенный вариант реализации интерфейса 1-Wire обладает одним недостатком. Точнее, двумя.

  1. Он жрет ресурсы (как любая программная эмуляция).
  2. Он неустойчив к помехам.

С первым недостатком можно еще как-то мириться, хотя по мере роста проекта ресурсов остается все меньше. Со вторым недостатком в боевом софте надо бороться семплированием сигнала. Что такое семплирование? Допустим, бит 1 передается 6 мкс.

Для того чтобы точно быть уверенным, что это 1, а не какая-то наводка, необходимо несколько раз в течение этих 6 мкс измерить состояние входного сигнала. Чем больше измерений ты проведешь, тем точнее будет твой результат и уверенность в правильности принятия данных. Однако 6 мкс — это ооочень мало, тут возникает вопрос разумности и аппаратных возможностей.

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

Настроить-то можно, но толку от этого не будет, так как надо учитывать накладные расходы на «проваливание» в прерывание, сохранение регистров, выход из прерывания. Другой вариант — мотание в цикле, но опять вопрос во времени. Такт процессора на частоте 16 МГц длится 1/16 мкс, то есть у тебя есть всего 16 тактов.

За это ничтожное время тебе надо прокрутить счетчик (цикл же), снять состояние сигнала, перейти к следующей итерации. С учетом оптимизации и прочих накладных расходов на СИ сделать это практически нереально. Выход один — использовать аппаратную микросхему интерфейса 1-Wire, подключаемую, например, по SPI-интерфейсу.

Железо

Итак, выбор пал на термодатчик компании Maxim, модель DS18S20 (что под рукой оказалось). Если ты полез гуглить, сразу предупреждаю: подавляющее количество примеров применения термодатчиков с Arduino построено на базе DS18B20. Он немного отличается, но в рамках нашего проекта разницы никакой.

Работа термометра

Для работы с термометром по 1-Wire необходимо выполнить (по крайней мере для знакомства с ним) всего три действия:

  • запустить измерение;
  • подождать время, необходимое АЦП термометра, чтобы зафиксировать показание;
  • считать показание из памяти термометра.

Как и с обычными АЦП, чем выше точность, тем больше времени требуется для проведения измерения, тем дольше нужна задержка перед попыткой чтения показаний.

Термодатчик имеет два режима работы: постоянное питание или паразитное питание. Я буду использовать режим паразитного питания. В этом режиме термодатчик кушает через подтягивающий резистор (4,7 кОм) линии 1-Wire, когда линия «свободна» или передается высокий уровень. Как раз это вторая деталь, которую необходимо найти, резистор 4,7 кОм.

WARNING

Будь внимателен при подключении термодатчика, при ошибке подключения ты можешь его сжечь. Если сам не силен, попроси умеющего товарища спаять тебе проводки, ничего зазорного в этом нет :).

Схема подключения термодатчикаФото подключения термодатчика

Теперь, когда с подключением ты более или менее разобрался, приступим ко второй части нашего остросюжетного боевика. Нужно писать софт. Я, как и большинство программистов, создание ленивое, поэтому я вопросил у Всезнающего Гугла, что уже придумано до нас и надо ли изобретать велосипед.

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

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

Ось зла

Начал я с простого — заставил хотя бы собираться библиотеки. Обе библиотеки используют ардуиновские функции, поэтому пришлось внести некоторые изменения. Для начала добавим файл OneWire_Port.h в проект (он будет портом библиотеки OneWire для проекта) и приинклюдим его в файл OneWire.h, а затем начнем причесывание. А именно:

  • OneWire построена таким образом, что ей при создании экземпляра объекта скармливается номер ноги, на которой у тебя будет линия 1-Wire. Это тащит за собой кусочек мрака из недр библиотек Ардуино, поэтому я пошел простым путем и зашил хардкодом в конструктор класса OneWire нужные мне ноги. Да, теряем универсальность, но я пока не вижу применения с двумя шинами 1-Wire (хотя… ну да не сейчас). Исходя из схемы платы, я выбрал ногу PA6, которая выходит на колодку DIGITAL пин 28. PORTA &= ~_BV(PA6); DDRA &= ~_BV(PA6); bitmask = _BV(PA6); baseReg = &PINA;
  • OneWire использует задержки в микросекундах для реализации протокола 1-Wire, подсунем библиотечную функцию _delay_us() в файл OneWire_Port.h #define delayMicroseconds(usec) _delay_us(usec)
  • OneWire любит отключать прерывания во время выполнения очень маленьких задержек (несколько микросекунд), и я ее понимаю. Но сразу же оглянемся и подумаем о том, что у нас все-таки будет ось. А значит, включение прерываний разумнее проредить немного, чтобы случайно не потерять контекст выполнения на неопределенное время. Библиотека использует ардуиновские функции работы с прерываниями, подсунем ей стандартные через файл OneWire_Port.h: #define noInterrupts() __builtin_avr_cli() #define interrupts() __builtin_avr_sei()
  • В драйвере термодатчика используется задержка, измеряемая в миллисекундах. Тут разумнее использовать вызов функции ОС, особенно учитывая размер этих задержек. Для замены sleep на вызов функции ОС пришлось немного погородить макросов в OneWire_Port.h, комментарии в коде. // Количество «тиков» операционной системы (переключений контекстов) в секунду #define __CLOCKS_PER_SEC 1000 //Период системного таймера операционной системы #define PERIOD_TIMER_MS ( 1000UL / __CLOCKS_PER_SEC ) // Макрос перевода миллисекунд в количество тиков операционной системы #define MSEC_TO_TICK( X ) ( X / PERIOD_TIMER_MS ) #define delay(msec) OS::sleep( MSEC_TO_TICK(msec))

Внедрение агента в банду

Теперь либы собираются, настал черед вкрутить их в код проекта. Как удостовериться, что оно заработало? Элементарно: создаем экземпляр класса OneWire, затем DallasTemperature с параметром шины, на которую подключены термодатчики, и начинаем все это активно использовать.

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

Для удобства я добавил еще одну команду — поиск термодатчиков, по этой команде опрашивается линия, ответившие термодатчики заносятся в «кеш» библиотеки, после чего для найденных термодатчиков можно получить адреса и вывести их в терминал.

Отмечу отдельно алгоритм поиска устройств на линии, очень увлекательный процесс, описан подробно в документации к iButton в разделе Network Capabilities.

Первый запуск

Выносим в отдельный поток

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

Немного подумав, я решил, что лучше сделать целый класс — движок работы с термодатчиками, унаследовав его от класса process, чтобы все собрать в одну кучку: сделать имплементацию функции-потока, дать этой функции доступ к членам класса, выставить наружу основные функции работы с термодатчиками.

Однако тут я уткнулся в жадность. Мне хотелось оставить возможность опроса термодатчиков из консоли и иметь сигнализацию. Сразу же возникает необходимость разделять общие ресурсы, так как теперь два потока будут дергать один термодатчик (а точнее, шину 1-Wire). Лезь в класс OneWire и добавляй ему приватного мембера OS::TMutex _mutex;.

Здесь начинается интересное. Мьютекс мы завели, но пользоваться им внутри класса неразумно, так как библиотека работы с термодатчиком написана очень сильно интегрировано и на лету дергает функции байтовой, а не пакетной приема-передачи по 1-Wire. Для локализации массовых вызовов я создал два метода: open и close для шины 1-Wire.

void OneWire::open() { _mutex.lock(); } void OneWire::close() { _mutex.unlock(); }

Затем пришлось прошерстить всю библиотеку DallasTemperature и обернуть вызовы функций работы с шиной 1-Wire в оболочку _wire->open() -> _wire->close().

Реализация функции потока обработки показаний термодатчика совсем проста.

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

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

float val; AnalogState new_state; if (!TemperatureEngine::temperature_get(0, &val)) { if (state != lost && ++ lost_cntr > 10 ) { state = lost; TAlarmMessage msg; msg.state = state; msg.src = TAlarmMessage::AI_ALARM; AlarmMessageBox.push(msg); } continue; } lost_cntr = 0; if (val < low_value) new_state = low; else if (val > high_value) new_state = high; else new_state = normal; if (new_state != state) { TAlarmMessage msg; msg.state = new_state; msg.src = TAlarmMessage::AI_ALARM; AlarmMessageBox.push(msg); } state = new_state;

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

Тут-то я и наступил на грабли. Я забыл про функцию инициации процесса измерения DallasTemperature::requestTemperatures. В ней стоят задержки для того, чтобы подождать, пока термодатчик производит измерение. Но я поставил _wire->close() перед этими задержками.

В итоге я получил странную картину: при запросе из терминала начинали скакать показания термодатчика.

А случалось вот что: поток движка термодатчиков запускал измерение, одновременно приходил я со своим запросом по терминалу, и в итоге мы оба читали какие-то неинициализированные значения.

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

Остается лишь добавить в поток обработки аварийных сообщений кейсы нового источника аварий.

template<> OS_PROCESS void TAlarmTask::exec() { for(;;) { TAlarmMessage msg; // Тут мы уснем до получения аварийного сообщения AlarmMessageBox.pop(msg); // Получили сообщение, теперь обработаем его if (TAlarmMessage::DI_ALARM == msg.src) { // Обработка аварий цифрового датчика }else if(TAlarmMessage::AI_ALARM == msg.src) { // Здесь вставляем код обработки аварий аналогового (термо)датчика } } }

Испытания огнем

Конечно же, огонь применять никто не собирается, пожаров нам только не хватает. Но полевые испытания провести стоит. Так как датчик достаточно инертный, то я решил извлечь хоть какую-то пользу от выделяемого компьютером тепла и засунул термодатчик под поток воздуха от процессорного кулера. Ура, температура поползла вверх!

Как только значения температуры перешагнули пороговое значение, тут же в терминал пришло ругательное сообщение. Следующим шагом была проверка на возврат в нормальное состояние.

Проверка срабатывания аварии

Заключение

Вот мы и сделали еще один сложный шаг к защите содержимого твоего холодильника не только от врагов, но и от разморозки. Теперь в твоем арсенале есть термодатчик, а так как используется линия 1-Wire, то ты уже самостоятельно можешь навесить и два, и три, и более термодатчиков.

Надеюсь, что материал этой статьи раскрыл для тебя новые и интересные возможности, казалось бы, игрушечного Arduino и подогрел интерес к программированию встраиваемых систем. Помни, что только написание кода даст тебе знание и умение. Тренируйся, больше практики, старайся воплощать самые свои сумасшедшие идеи, и знание придет.

Пиши, пиши, пиши! Железный привет, RESET :).

DANGER

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

WARNING

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

WARNING

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

Источник: https://xakep.ru/2015/05/10/arduino-digital-temp-wire/

Библиотеки Ардуино

В этой статье мы сделали попытку собрать в одном месте ссылки на все самые популярные библиотеки Ардуино, а также подготовили подборку наиболее популярных библиотек.

Рано или поздно, любой ардуинщик сталкивается с необходимостью использования той или иной библиотеки. Ведь использование готового кода сильно сокращает время на программирование.

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

Что такое библиотеки в Arduino?

Библиотека ардуино – это некий программный код, хранящийся не в скетче, а во внешних файлах, которые можно подключить к вашему проекту.

В библиотеке хранятся различные методы и структуры данных, которые нужны для упрощения работы с датчиками, индикаторами, модулями и другими компонентами.

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

Сегодня создано огромное количество библиотек, которые можно легко найти и скачать в интернете.  Подавляющее большинство библиотек распространяются по свободной лицензии, поэтому необходимости в поиске «пиратских» версий нет. Главное, это научиться искать нужные библиотеки, подходящие к вашей Arduino IDE, подключать их и правильно использовать.

Стандартные библиотеки Ардуино

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

Список встроенных библиотек (они поставляются вместе с дистрибутивом Arduino IDE):

  • EEPROM
  • Ethernet / Ethernet 2
  • Firmata
  • GSM
  • LiquidCrystal
  • SD
  • Servo
  • SPI
  • SoftwareSerial
  • Stepper
  • TFT
  • WiFi
  • Wire

Официальная страница на сайте Arduino

Подборка библиотек в одном архиве

Библиотеки для экранов, индикаторов и дисплеев

Библиотека I2C

Скачать: https://github.com/g4lvanix/I2C-master-lib

Библиотека, предназначенная для работы периферийного устройства по протоколу I2C.

Пример использования:

#ifndef I2C_MASTER_H

#define I2C_MASTER_H

void I2C_init (void) – создание объекта, настройка на правильную частоту для шины.

uint8_t I2C_start () – установка соединения с новым устройством.

uint8_t I2C_write() – запись данных на текущее устройство.

uint8_t I2C_read_ack() – считывание байта с устройства, запрос следующего байта.

Библиотека  LiquidCrystal

Скачать: https://github.com/mk90/LiquidCrystalRus

Стандартная библиотека, установленная в Arduino IDE. Предназначена для управления жидкокристаллическими дисплеями LCD.

Пример использования:

#include . Также, чтобы не ошибиться при написании, можно подключить через меню Sketch — Import Library – LiquidCrystal.

Конструктор класса —  LiquidCristal(…). Аргументами являются rs, rw, en, do…d7. Первые 3 соответствую выводам сигналов RS, RW и Enable. Выводы d соответствуют номерам шин данных, к которым подключен дисплей.

void begin(cols, rows) – метод, который инициализирует интерфейс дисплея. Аргументами являются количество знаков в строке (cols) и число строк (rows). Этот метод должен задаваться первым.

void createChar(num, data) – метод, необходимый для создания пользовательских символов.

Библиотека UTFT

Скачать: https://github.com/amperka/UTFT

Стандартная библиотека, необходимая для работы Ардуино с TFT экранами разных типов. Все поддерживаемые дисплеи представлены в сопроводительном документе с библиотекой.

Пример использования:

#include<\p>

UTFT(); — создание экземпляра UTFT.

textRus(char*st, int x, int y); — метод, позволяющий выводить строку из указателя. Например, char *dht = «Температура,С»;

textRus(string st, int x, int y); — вывод строки с указанием в параметре. Например, g.textRus(«Температура, С», 0, 20);

Библиотека LedControl

Скачать: https://github.com/wayoda/LedControl

Позволяет управлять семисегментными дисплеями, объединять массив из светодиодов в одну матрицу.

Пример использования:

#include<\p>

LedControl  lc1= LedControl( );

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

writeArduinoOn7Segment() – отображение на дисплее всех чисел от 0 до 15. Использует функции setChar() для символов a и d и setRow() для создания макета пропущенных символов.

LedControl.shutdown() – отключение изображения.

setIntensity() – контроль яркости.

Библиотеки для работы с датой и временем ардуино

Библиотека RTClib

Скачать: https://github.com/adafruit/RTClib

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

Пример использования:

#include<\p>

RTC_DS1307 RTC; — выбор датчика (в данном случае DS1307).

rtc.adjust(DateTime( Date, Time)); — настройка времени и календаря.

dayOfTheWeek () – вывод дня недели. Аргумент от 0 до 6, 0 – воскресенье.

Библиотека Timelib

Скачать: https://github.com/PaulStoffregen/Time

Позволяет Ардуино получать информацию о дате и времени в данный момент.

Пример использования:

#include<\p>

Time(); — создание экземпляра.

setTime (t); — установка времени. Аргумент t – час, минута, секунда, день, месяц и год.

timeStatus(); — показывает, установлено ли время.

adjustTime(adjustment); — настройка времени.

Библиотека Ds1307

Скачать: https://github.com/PaulStoffregen/DS1307RTC

Библиотека для удобного взаимодействия часов DS1307 с Ардуино c использованием библиотеки Wire.

Пример использования:

#include<\p>

class DS1307RTC – создание объекта DS1307.

SetTime() – установка времени.

get() – считывает RTC, возвращает полученную дату в формате POSIX.

Set(time_t t) – запись даты в RTC

Библиотека DS 3231

Скачать: https://github.com/rodan/ds3231

Предназначена для управления датой и временем в модуле ds3231.

#include «ds3231.h»

DS3231  Clock(SDA, SCL); — создание объекта DS3231, подключение к линии тактирования и линии данных.

getTime(); — считывание даты и времени с часов.

setDate(date, mon, year); — установка даты.

Системные библиотеки ардуино

Библиотека EEPROM

Скачать: https://github.com/aterentiev/EEPROM2

Стандартная библиотека. Предназначена для работы с энергонезависимой памятью (запись данных, их чтение).

Пример использования:

#include<\p>

EEPROM.read(); — создание объекта, считывание байта по адресу из энергонезависимой памяти.

EEPROM.write(address, value)– запись байта в энергонезависимую память.

EEPROM.put() – запись строк чисел с плавающей запятой.

EEPROM.get() – чтение строк и чисел с плавающей запятой.

Библиотека SoftwareSerial

Скачать: https://github.com/PaulStoffregen/SoftwareSerial

Библиотека, которая позволяет реализовывать последовательные интерфейсы с любых цифровых пинов. Также позволяет создавать несколько последовательных портов, которые работают на скорости до 115200 бод.

#include<\p>

SoftwareSerial mySerial(RX, TX) – создание объекта, аргументы — выводы, к которым подключены RX и TX.

Serial.begin( ); — устанавливает скорость порта для связи ардуино и компьютера.

mySerial.overflow() – проверка входного буфера на переполнение.

Библиотека Math

Скачать: http://www.nongnu.org/avr-libc/user-manual/group__avr__math.html

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

Пример использования:

#include<\p>

Math(); — создание экземпляра Math.

Serial.print(«cos num = «); — возвращает косинус числа.

Serial.println (fmod (double__x, double__y)); — возвращает числа по модулю.

Библиотека Scheduler

Скачать: https://www.arduino.cc/en/Reference/Scheduler

Предназначена для работы с Arduino Due, позволяет работать в режиме многозадачности. Пока является экспериментальной библиотекой.

Пример использования:

#include<\p>

Scheduler; — создание экземпляра.

Scheduler.startLoop() – позволяет добавить функцию, которая будет выполняться вместе с loop().

yield() – позволяет передать управление другим задачам.

Библиотеки серво моторов и шаговых двигателей

Библиотека Servo

Скачать: https://github.com/netlabtoolkit/VarSpeedServo

Стандартная библиотека. Необходима для управления серводвигателями  и часто используется в робототехнических проектах с манипуляторами.

Пример использования:

#include<\p>

Servo myservo; — создание объекта для серводвигателя..

myservo.attach(); — номер выхода, к которому подключен серводвигатель.

myservo.write(180, 30, true); — движение на 180 градусов, скорость 30, ожидание окончания движения.

Библиотека Stepper

Скачать: https://www.arduino.cc/en/Reference/Stepper?from=Tutorial.Stepper

Небходима для управления шаговым униполярным и биполярным двигателем.

#include<\p>

const int stepsPerRevolution =  ; — количество шагов, за которое двигатель проходит полный поворот.

Stepper myStepper = Stepper(steps, pin1, pin2) – создает экземпляр класса с указанным количеством шагов и выводами, к которым подключается двигатель.

Библиотеки датчиков ардуино

Библиотека DHT

Скачать: https://github.com/adafruit/DHT-sensor-library

Библиотека, которая позволяет считать данные с температурных датчиков DHT-11 и DHT-22.

#include < DHT.h>

DHT dht(DHTPIN, DHT11); — инициализирует датчик (в данном случае DHT11).

dht.begin(); — запуск датчика.

float t = dht.readTemperature(); — считывание текущего значения температуры в градусах Цельсия.

Библиотека DallasTemperature

Скачать: https://github.com/milesburton/Arduino-Temperature-Control-Library

Предназначается для работы с датчиками Dallas. Работает совместно с библиотекой OneWire.

#include<\p>

DallasTemperature dallasSensors(&oneWire); — передача объекта oneWire для работы с датчиком.

requestTemperatures() – команда считать температуру с датчика и

положить ее в регистр.

printTemperature(sensorAddress); — запрос получить измеренное значение температуры.

Библиотека Ultrasonic

Скачать: https://github.com/JRodrigoTech/Ultrasonic-HC-SR04

Обеспечивает работу Ардуино с ультразвуковым датчиком измерения расстояния HC-SR04.

#include<\p>

Ultrasonic ultrasonic (tig , echo) – объявление объекта, аргументы – контакт Trig и контакт Echo.

dist = ultrasonic.distanceRead(); — определение расстояния до объекта. Агрумент – сантиметры(СМ) или дюймы (INC).

Timing() – считывание длительности импульса на выходе Echo, перевод в необходимую систему счисления.

Библиотека ADXL345

Скачать: https://github.com/adafruit/Adafruit_ADXL345

Предназначается для работы с акселерометром ADXL345.

Пример использования:

#include<\p>

ADXL345_ADDRESS – создание объекта, указание его адреса.

ADXL345_REG_DEVID  — идентификация устройства.

ADXL345_REG_OFSX – смещение по оси Х.

ADXL345_REG_BW_RATE – управление скоростью передачи данных.

Библиотека BME280

Скачать: https://github.com/adafruit/Adafruit_BME280_Library

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

Пример использования:

#include<\p>

BME280_ADDRESS  — создание объекта BME280, указание его адреса.

begin(uint8_t addr = BME280_ADDRESS); — начало работы датчика.

getTemperature – получение измеренной температуры.

getPressure – получение измеренного давления.

Библиотека BMP280

Скачать: https://github.com/adafruit/Adafruit_BMP280_Library

Требуется для работы с датчиком атмосферного давления BMP280.

Пример использования:

#include<\p>

BMP280_CHIPID – создание экземпляра, указание его адреса.

getTemperature(float *temp); — получение измеренной температуры.

getPressure(float *pressure); — получение измеренного значения давления.

Библиотека BMP085

Скачать: https://github.com/adafruit/Adafruit-BMP085-Library

Требуется для работы с датчиком давления BMP085.

Пример использования:

#include<\p>

Adafruit_BMP085 bmp; — создание экземпляра BMP085.

dps.init(MODE_ULTRA_HIGHRES, 25000, true); — измерение давления, аргумент 25000 – высота над уровнем моря (в данном случае 250 м. над уровнем моря).

dps.getPressure(&Pressure); — определение давления.

Библиотека FingerPrint

Скачать: http://iarduino.ru/file/263.html

Требуется для работы со сканером отпечатков пальцев.

Пример использования:

#include<\p>

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); — объявление объекта Finger. Параметр – ссылка на объектр для работы с UART, кокторому подключен модуль.

finger.begin();  – инициализация модуля отпечатков пальцев.

Func_sensor_communication(); — вызов модуля отпечатков пальцев.

Библиотеки коммуникации

Библиотека Wire

Скачать: https://github.com/czukowski/Wire.h

Требуется для работы с двухпроводным интерфейсом I2C.

Пример использования:

#include<\p>

Wire.begin() – инициализация библиотеки, подключение к шине I2C.

Wire.requestFrom() – запрос мастером байтов от ведомого устройства.

Wire.beginTransmission() – начало передачи на ведомое устройство.

Библиотека Irremote

Скачать: https://github.com/z3t0/Arduino-IRremote

Требуется для работы ардуино с ИК приемником.

Пример использования:

#include<\p>

IRrecv irrecv(RECV_PIN); — пин, к которому подключен ИК приемник.

SetPinAndButton(int ir1,int ir2,int pin) – позволяет настроить определенный выход на срабатывание при заданных значениях ir1, ir2.

Библиотека GSM

Скачать: https://github.com/jt5/GSM

Источник: https://ArduinoMaster.ru/biblioteki-arduino/skachat-biblioteki-arduino/

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}