DS18B20, пожалуй, один из самых из известных и доступных датчиков температуры. В основном для чтения данных с DS18B20 используется микроконтроллеры, к примеру: ATmega8, ATtiny2313, Arduino и др.. С появлением одноплатных мини-компьютеров стало интересно, как будет работать подключённый датчик температуры DS18B20 к Orange Pi, Banana Pi или Raspberry Pi — самые популярнуе мини-компьютеры.
Для работы с GPIO на Orange Pi и Banana Pi необходимо установить WiringOP и BPI-WiringPi соответственно, и IDE Code::Blocks.
При создании статьи был выбран Banana Pi M3, так как он у меня постоянно включён. Но данный пример программы будет работать и при подключении DS18B20 к Orange Pi или Raspberry Pi.
OneWire библиотека
OneWire.h
#ifndef ONEWIRE_H #define ONEWIRE_H #define CMD_CONVERTTEMP 0x44 #define CMD_RSCRATCHPAD 0xbe #define CMD_WSCRATCHPAD 0x4e #define CMD_CPYSCRATCHPAD 0x48 #define CMD_RECEEPROM 0xb8 #define CMD_RPWRSUPPLY 0xb4 #define CMD_SEARCHROM 0xf0 #define CMD_READROM 0x33 #define CMD_MATCHROM 0x55 #define CMD_SKIPROM 0xcc #define CMD_ALARMSEARCH 0xec #include <stdint.h> class OneWire { private: int pin; uint64_t searchNextAddress(uint64_t, int&); public: OneWire(int); virtual ~OneWire(); int reset(void); int crcCheck(uint64_t, uint8_t); uint8_t crc8(uint8_t*, uint8_t); void oneWireInit(); void writeBit(uint8_t); void writeByte(uint8_t); void setDevice(uint64_t); void searchRom(uint64_t*, int&); void skipRom(void); uint8_t readByte(void); uint8_t readBit(void); uint64_t readRoom(void); }; #endif // ONEWIRE_H
OneWire.cpp
#include "OneWire.h" #include <wiringPi.h> #include <stdexcept> #include <iostream> OneWire::OneWire(int _pin) : pin(_pin) { } OneWire::~OneWire() { } void OneWire::oneWireInit() { if (wiringPiSetup() == -1) { throw std::logic_error("WiringPi Setup error"); } pinMode(pin, INPUT); } /* * сброс */ int OneWire::reset() { int response; pinMode(pin, OUTPUT); digitalWrite(pin, LOW); delayMicroseconds(480); // Когда ONE WIRE устройство обнаруживает положительный перепад, он ждет от 15us до 60us pinMode(pin, INPUT); delayMicroseconds(60); // и затем передает импульс присутствия, перемещая шину в логический «0» на длительность от 60us до 240us. response = digitalRead(pin); delayMicroseconds(410); // если 0, значит есть ответ от датчика, если 1 - нет return response; } /* * отправить один бит */ void OneWire::writeBit(uint8_t bit) { if (bit & 1) { // логический «0» на 10us pinMode(pin, OUTPUT); digitalWrite(pin, LOW); delayMicroseconds(10); pinMode(pin, INPUT); delayMicroseconds(55); } else { // логический «0» на 65us pinMode(pin, OUTPUT); digitalWrite(pin, LOW); delayMicroseconds(65); pinMode(pin, INPUT); delayMicroseconds(5); } } /* * отправить один байт */ void OneWire::writeByte(uint8_t byte) { uint8_t i = 8; while (i--) { writeBit(byte & 1); byte >>= 1; } } /* * получить один байт */ uint8_t OneWire::readByte() { uint8_t i = 8, byte = 0; while (i--) { byte >>= 1; byte |= (readBit() << 7); } return byte; } /* * получить один бит */ uint8_t OneWire::readBit(void) { uint8_t bit = 0; // логический «0» на 3us pinMode(pin, OUTPUT); digitalWrite(pin, LOW); delayMicroseconds(3); // освободить линию и ждать 10us pinMode(pin, INPUT); delayMicroseconds(10); // прочитать значение bit = digitalRead(pin); // ждать 45us и вернуть значение delayMicroseconds(45); return bit; } /* * читать ROM подчиненного устройства (код 64 бита) */ uint64_t OneWire::readRoom(void) { uint64_t oneWireDevice; if (reset() == 0) { writeByte (CMD_READROM); // код семейства oneWireDevice = readByte(); // серийный номер oneWireDevice |= (uint16_t) readByte() << 8 | (uint32_t) readByte() << 16 | (uint32_t) readByte() << 24 | (uint64_t) readByte() << 32 | (uint64_t) readByte() << 40 | (uint64_t) readByte() << 48; // CRC oneWireDevice |= (uint64_t) readByte() << 56; } else { return 1; } return oneWireDevice; } /* * Команда соответствия ROM, сопровождаемая последовательностью * кода ROM на 64 бита позволяет устройству управления шиной * обращаться к определенному подчиненному устройству на шине. */ void OneWire::setDevice(uint64_t rom) { uint8_t i = 64; reset(); writeByte (CMD_MATCHROM); while (i--) { writeBit(rom & 1); rom >>= 1; } } /* * провеска CRC, возвращает "0", если нет ошибок * и не "0", если есть ошибки */ int OneWire::crcCheck(uint64_t data8x8bit, uint8_t len) { uint8_t dat, crc = 0, fb, stByte = 0; do { dat = (uint8_t)(data8x8bit >> (stByte * 8)); // счетчик битов в байте for (int i = 0; i < 8; i++) { fb = crc ^ dat; fb &= 1; crc >>= 1; dat >>= 1; if (fb == 1) { crc ^= 0x8c; // полином } } stByte++; } while (stByte < len); // счетчик байтов в массиве return crc; } uint8_t OneWire::crc8(uint8_t addr[], uint8_t len) { uint8_t crc = 0; while (len--) { uint8_t inbyte = *addr++; for (uint8_t i = 8; i; i--) { uint8_t mix = (crc ^ inbyte) & 0x01; crc >>= 1; if (mix) { crc ^= 0x8c; } inbyte >>= 1; } } return crc; } /* * поиск устройств */ void OneWire::searchRom(uint64_t * roms, int & n) { uint64_t lastAddress = 0; int lastDiscrepancy = 0; int err = 0; int i = 0; do { do { try { lastAddress = searchNextAddress(lastAddress, lastDiscrepancy); int crc = crcCheck(lastAddress, 8); if (crc == 0) { roms[i++] = lastAddress; err = 0; } else { err++; } } catch (std::exception & e) { std::cout << e.what() << std::endl; err++; if (err > 3) { throw e; } } } while (err != 0); } while (lastDiscrepancy != 0 && i < n); n = i; } /* * поиск следующего подключенного устройства */ uint64_t OneWire::searchNextAddress(uint64_t lastAddress, int & lastDiscrepancy) { uint64_t newAddress = 0; int searchDirection = 0; int idBitNumber = 1; int lastZero = 0; reset(); writeByte (CMD_SEARCHROM); while (idBitNumber < 65) { int idBit = readBit(); int cmpIdBit = readBit(); // id_bit = cmp_id_bit = 1 if (idBit == 1 && cmpIdBit == 1) { throw std::logic_error("error: id_bit = cmp_id_bit = 1"); } else if (idBit == 0 && cmpIdBit == 0) { // id_bit = cmp_id_bit = 0 if (idBitNumber == lastDiscrepancy) { searchDirection = 1; } else if (idBitNumber > lastDiscrepancy) { searchDirection = 0; } else { if ((uint8_t)(lastAddress >> (idBitNumber - 1)) & 1) { searchDirection = 1; } else { searchDirection = 0; } } if (searchDirection == 0) { lastZero = idBitNumber; } } else { // id_bit != cmp_id_bit searchDirection = idBit; } newAddress |= ((uint64_t) searchDirection) << (idBitNumber - 1); writeBit(searchDirection); idBitNumber++; } lastDiscrepancy = lastZero; return newAddress; } /* * пропустить ROM */ void OneWire::skipRom() { reset(); writeByte (CMD_SKIPROM); }
Подключение нескольких DS18B20 к Orange Pi на одну шину
При подключение нескольких датчиков DS18B20 к Orange Pi, Banana Pi или Raspberry Pi на одну шину, главное устройство (компьютер) должно определить коды ROM всех подчиненных устройств на шине. Команда SEARCH ROM [F0h] — (ПОИСК ROM) позволяет устройству управления определять номера и типы подчиненных устройств. Устройство управления изучает коды ROM через процесс устранения, которое требует, чтобы Главное устройство исполнил цикл Поиска ROM (то есть, команда ROM Поиска, сопровождаемая обменом данных). Эту процедуру необходимо выполнить столько раз, сколько необходимо, чтобы идентифицировать все из подчиненных устройств. Если есть только одно подчиненное устройство на шине, более простая команда READ ROM [33h] (Чтения ROM) может использоваться место процесса Поиска ROM.
После каждого цикла Поиска ROM, устройство управления шиной должно возвратиться к Шагу 1 (Инициализация) в операционной последовательности.
main.cpp
#include <iostream> #include <wiringPi.h> #include "OneWire.h" using namespace std; double getTemp(OneWire * oneWire, uint64_t ds18b20s) { uint8_t data[9]; do { oneWire->setDevice(ds18b20s); oneWire->writeByte(CMD_CONVERTTEMP); delay(750); oneWire->setDevice(ds18b20s); oneWire->writeByte(CMD_RSCRATCHPAD); for (int i = 0; i < 9; i++) { data[i] = oneWire->readByte(); } } while (oneWire->crc8(data, 8) != data[8]); return ((data[1] << 8) + data[0]) * 0.0625; } int main() { OneWire * ds18b20 = new OneWire(24); try { ds18b20->oneWireInit(); double temperature; int n = 100; uint64_t roms[n]; ds18b20->searchRom(roms, n); cout << "---------------------------------" << endl; cout << "devices = " << n << endl; cout << "---------------------------------" << endl; for (int i = 0; i < n; i++) { cout << "addr T[" << (i + 1) << "] = " << roms[i] << endl; } cout << "---------------------------------" << endl; while (1) { for (int i = 0; i < n; i++) { temperature = getTemp(ds18b20, roms[i]); cout << "T[" << (i + 1) << "] = " << temperature << "°C" << endl; } cout << "---------------------------------" << endl; delay(500); } } catch (exception & e) { cout << e.what() << endl; } } // site: http://micro-pi.ru
double getTemp(OneWire * oneWire, uint64_t ds18b20s)
— возвращает данные температуры в градусах Цельсия.
Результат
Скачать проект Code::blocks
Если есть вопросы, пишите в комментариях, попробуем разобраться.
4095 C ?? ))
Как компилировать скрипт?
Благодарю за статью. Все отлично завелось на OrangePi Zero.
Подскажите, пожалуйста, как скомпилировать скрипт на OrangePi Zero ? Машины с Ubuntu/XServer нет 🙁
Пробую так:
root@orangepizero:~/sensor# sudo g++ OneWire.cpp -o OneWire -lwiringPi -lpthread
Выдает:
/usr/lib/gcc/arm-linux-gnueabihf/4.9/../../../arm-linux-gnueabihf/crt1.o: In function `_start’:
(.text+0x28): undefined reference to `main’
collect2: error: ld returned 1 exit status
При компиляции main.cpp жалуется на отсутствие OneWire.
Вы оказались правы. Именно в этом параметре была загвоздка.
Кто будет подключать Orange PI Zero, на заметку:
11-у пину соответствует значение wPi — 0.
С этим значением программа скомпилировалась, но не запустилась, выдав:
error: id_bit = cmp_id_bit = 1.
То, что диод на этом порту моргал отлично, только сбивает с толку.
У меня заработало так: сигнальный провод датчика на 26-й пин,
строка кода в main.cpp: OneWire * ds18b20 = new OneWire(11);
После этого, я получил температуру с датчика.
Спасибо вам, добрый админ!
Добавка к предыдущему посту (Open Pi Zero):
По предложенной на сайте схеме, когда провод данных подключается к 11-му пину, строчка в программе в main.cpp: OneWire * ds18b20 = new OneWire(0);
программа запускается, и видит датчики. Но иногда (довольно часто) не запускается с выше указанной ошибкой. Что меня и смутило в первый раз. Иногда видит только один датчик. Показания температуры могут улетать в зону 4000 градусов, а могут колебаться в пределах +- 10 градусов на соседних измерениях. При том, что среда так не меняется.
В любом случае, спасибо хозяину этого замечательного места! С вашей помощью датчики завелись. Буду добиваться от них надежной работы. Хочу климатику на них регулировать.
Спасибо огромное автору за эти исходники и вообще за этот бесценный ресурс! Ничего подобного больше нигде найти не смог.
У меня на RPi 3 чтение датчиков завелось со значением пина 7.
Однако запускается не каждый раз. При запуске вначале выдает от нуля до пяти одинаковых ошибок:
error: id_bit = cmp_id_bit = 1
Если ошибок три и менее, то дальше начинается нормальное цикличное вычитывание данных температуры. Если ошибок четыре или пять, то после этого выдает std::exception и дальше не работает. От запуска к запуску число ошибок рандомно. Это вообще чего за ошибки и как с ними бороться? У меня 3 датчика подключено сейчас.
Творчески переработал ваш код в драйвер ядра.
https://github.com/sergey-sh/opi18b20
Использую в проекте мониторинга температуры, считываю с 3х датчиков с периодичностью 20сек. Особой нагрузки на процессор нет. Бывает при первом чтении для первого датчика выдает 85000, потом все нормально.
Sergey-sh! Один вопрос — как правильно настроить параметр KERNEL_TREE. Судя по всему, он привязан к Вашему конкретному компьютеру. Расскажите об этом параметре новичку чуть поподробнее. Как корректно скомпилировать Ваш драйвер на Rasperry PI.
Добрый день!
Подскажите, а как эти данные в файл писать?
ка бы на экране они мне сильно не нужны, нужен файл с датой и значением.
Как-то забыты BANANA роутер-модели. В частности BPI-R3. А это ведь комбайн !
Если установить OpenWRT (v24.10.0) , то вообще, непонятно как сделать w1 шину.
Не могли бы вы просветить население земли в этом плане?
1. Выбор GPIO пина. (26pin GPIO)
2. Установка DT overlay. (привязка w1 шины к пину GPIO)
3. Хотя бы увидеть устройство /sys/bus/w1/devices/….
Acheter Kamagra site fiable: kamagra pas cher — achat kamagra
kamagra 100mg prix Achetez vos kamagra medicaments Acheter Kamagra site fiable
kamagra 100mg prix Acheter Kamagra site fiable kamagra gel
pharmacie en ligne france livraison belgique pharmacie en ligne france livraison belgique Pharmacie Internationale en ligne pharmafst.shop
Pharmacie en ligne Cialis sans ordonnance: Cialis generique prix — cialis generique tadalmed.shop
Pharmacie en ligne Cialis sans ordonnance: Cialis en ligne — cialis generique tadalmed.shop
kamagra en ligne Kamagra Oral Jelly pas cher acheter kamagra site fiable
cialis generique: Tadalafil achat en ligne — Cialis sans ordonnance 24h tadalmed.shop
https://kamagraprix.com/# kamagra oral jelly
Cialis sans ordonnance 24h: Tadalafil 20 mg prix sans ordonnance — cialis prix tadalmed.shop
Achat mГ©dicament en ligne fiable: Meilleure pharmacie en ligne — pharmacies en ligne certifiГ©es pharmafst.com
Tadalafil sans ordonnance en ligne: Cialis sans ordonnance 24h — cialis generique tadalmed.shop
kamagra livraison 24h: Kamagra Commander maintenant — Kamagra pharmacie en ligne
Pharmacie sans ordonnance: pharmacie en ligne — pharmacie en ligne avec ordonnance pharmafst.com
cialis prix: Tadalafil 20 mg prix sans ordonnance — Acheter Cialis 20 mg pas cher tadalmed.shop
pharmacies en ligne certifiГ©es Medicaments en ligne livres en 24h pharmacie en ligne sans ordonnance pharmafst.shop
Cialis sans ordonnance 24h: Tadalafil 20 mg prix sans ordonnance — Tadalafil 20 mg prix sans ordonnance tadalmed.shop
kamagra pas cher: achat kamagra — kamagra gel
mexico pharmacy order online: mexico pharmacy order online — mexican rx online
canadian pharmacy india: Canadian pharmacy shipping to USA — legitimate canadian pharmacy
canadian pharmacy prices: ExpressRxCanada — my canadian pharmacy
legit canadian pharmacy online: Express Rx Canada — canadian pharmacy online
indian pharmacy online shopping: Medicine From India — indian pharmacy online
Rx Express Mexico Rx Express Mexico RxExpressMexico
https://expressrxcanada.com/# canadian pharmacy ed medications
best canadian pharmacy ExpressRxCanada canadian mail order pharmacy
best canadian online pharmacy: ExpressRxCanada — canada cloud pharmacy
https://rxexpressmexico.shop/# mexican online pharmacy
canadapharmacyonline com ExpressRxCanada my canadian pharmacy rx
mexican rx online: Rx Express Mexico — RxExpressMexico
india pharmacy mail order: indian pharmacy online — indian pharmacy
https://medicinefromindia.com/# indian pharmacy online shopping
Medicine From India: MedicineFromIndia — indian pharmacy online
canadian world pharmacy Express Rx Canada canadian pharmacy online store
best canadian pharmacy online: Buy medicine from Canada — reputable canadian pharmacy
pin up az: pinup az — pin up azerbaycan
пин ап вход: pin up вход — пинап казино
https://pinupaz.top/# pin up
http://pinuprus.pro/# пинап казино
маркетплейс аккаунтов соцсетей купить аккаунт с прокачкой
http://pinupaz.top/# pin up az
пин ап казино: пин ап зеркало — пинап казино
пин ап казино пинап казино пинап казино
пин ап казино официальный сайт: пин ап казино официальный сайт — pin up вход
http://pinuprus.pro/# pin up вход
vavada vavada casino вавада зеркало
вавада официальный сайт: вавада казино — vavada casino
вавада вавада зеркало вавада
vavada casino: вавада — vavada
вавада: вавада официальный сайт — vavada
услуги по продаже аккаунтов заработок на аккаунтах
аккаунт для рекламы перепродажа аккаунтов
pin-up casino giris pin up casino pin up casino
http://vavadavhod.tech/# vavada вход
пин ап вход: пин ап вход — пин ап вход
pin up azerbaycan pin up casino pin-up
vavada вход: vavada вход — vavada
pin up casino pin-up casino giris pin-up
пин ап казино: пин ап казино официальный сайт — пин ап зеркало
вавада казино vavada вавада официальный сайт
vavada: вавада казино — вавада официальный сайт
pin up pin-up casino giris pinup az
Account Store Account marketplace
Sell Pre-made Account Account Market
pin-up: pin up az — pin-up casino giris
вавада зеркало: вавада официальный сайт — вавада зеркало
pin up azerbaycan: pin-up — pin-up
pin up casino: pin up az — pin-up
вавада официальный сайт: vavada casino — вавада казино
пин ап зеркало пин ап казино официальный сайт пинап казино
Buy accounts Buy accounts
https://vavadavhod.tech/# vavada вход
vavada вход вавада казино vavada вход
pin up вход: пин ап казино официальный сайт — пин ап казино
Website for Selling Accounts Account Market
Website for Selling Accounts Sell accounts
pin up: pin up azerbaycan — pinup az
pin up az: pin up — pin-up casino giris
pin up вход пин ап зеркало пин ап казино
account trading profitable account sales
pinup az: pin-up casino giris — pinup az
account marketplace account selling service
pin up вход: пин ап зеркало — пинап казино
pin-up: pinup az — pinup az
пинап казино пин ап казино пинап казино
pinup az: pin up — pin up azerbaycan
account trading service buy and sell accounts
social media account marketplace account acquisition
purchase ready-made accounts https://socialaccountsdeal.com/
pin up вход пинап казино пин ап вход
пин ап зеркало: пинап казино — пин ап вход
vavada вход: вавада казино — vavada casino
accounts marketplace account trading platform
пинап казино пин ап зеркало пин ап казино официальный сайт
вавада официальный сайт: вавада зеркало — vavada вход
pin up вход: пин ап казино — пин ап зеркало
sell pre-made account ready-made accounts for sale
account store account acquisition