Почистил скетч примера работы с DS18B20 из библы OneWire..
- Войдите на сайт для отправки комментариев
Сб, 18/04/2015 - 20:15
А то уж больно захламлён, смотреть неприятно. И положил в прерывание вотчдога, егойный простецкий таймер в самый раз для таких дел :) Теперь всё компактно, наглядно и красиво :)
#include <OneWire.h> OneWire ds(2); byte addr[8]={0x28,0x04,0x13,0x80,0x06,0x00,0x00,0xF8}; float celsius; void setup(void) { Serial.begin(9600); WDTCSR=B00011000; //установить биты WDCE WDE (что б разрешить запись в другие биты WDTCSR=B01000110; // разрешение прерывания + выдержка 1 секунда(55 страница даташита) } // можно выбрать от 16мс до 8 с void loop(void) { } ISR (WDT_vect){ static boolean n=0; n=~n; if (n) {ds.reset(); ds.select(addr); ds.write(0x44); } else {ds.reset(); ds.select(addr); ds.write(0xBE); celsius = (ds.read() | (ds.read()<<8))/16.0; Serial.print(" Temperature = "); Serial.println(celsius); } } Автодетекта адреса ds18b20 нет, так что нужно адрес указать вручную. Работает в дефолтовом 9-бит режиме.
Немного критики, если хотите.
Вобщем, дело, конечно, хозяйское.
kisoft, ну по поводу недостатка комментариев -и "магических" чисел полностью согласен :) А вывод в сериал из ISR чисто для проверки.
Даташит дефолтовый http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf
... А вы , батенька ЭСТЭТ ;)
Издание второе, исправленное и дополненное ) Вставил возможность включить максимальную точность (12-бит режим), дописаны комментарии. В сериал гонит результат только для теста, данные обновляются 1 раз в 2 секунды.
Вариант с 1м датчиком
Вариант с 2-мя датчиками
Пара "приколов" - отсутствие volatile для celsius и использование float.
Остальное так, ворчание :)
И лично я бы использовал условную компиляцию вместо закомментаренного куска в setup, потому что там не совсем очевидно, нужно ли все строки раскомментаривать, либо только часть. Честно говоря не юзал на ардуине DS18B20, но наверняка уже кто то все команды в виде define описал. А вот нашел, библиотека DallasTemperature вроде код культурный.
kisoft, спасибо, "приколы" исправил. Условную компиляцию -да, наверно грамотнее бы. Было-бы.. Но я уж и так это вставил несмотря на то, что мне не нужно, так что оставлю как есть ) Этот кусок нужно выполнить один раз для перешивания конфига еепром. В даллосовской библе чисто визуально всё культурно, но в её коде висит delay на 750мс, вот такой "привет" от разработчиков :)
Я не усмотрел, но это нужный delay для библиотеки, ну тогда можно спереть их дефайны команд ;)
Ну как чайнику не влезть? Вместо строк 36-40 можно ds.write(0xCC); - дает команду на преобразование для всех датчиков на линии.
bwn, век живи... Поправил :)
dimax , спасибо за такой труд, а то я в строках битности преобразования увяз.
Как вариант опроса одного ds18b20 без ввода адреса (при смене датчика не переписывать код) и работа с целыми числами.
Чтобы всем было понятно, что возвращает функция tempProcess().
t>>4; -делим целое двубайтное t на 16 (делим на 2 четыре раза или делим на 2 в степени 4).
(t+8)>>4 это тоже, что (t+16/2)/16 - получаем целые градусы с округлением. Всё это когда не требуются десятые доли градуса.
(t*10)>>4 = (t*10)/16 - получаем целое число равное температуре в десятых градуса, сотые отбрасываются: число 214 соответствует температуре 21,4 *С
Pyotr, вся задумка была в чём? Что б полностью отказаться от delay(), а у вас он стоит в loop(), и если его убрать то будут глюки, т.к. по даташиту между запросом температуры и её чтением должно пройти от 100 до 750мс в зависимости от разрядности. Поэтому я и повесил обработчик на таймер.
Извините, а как в примере с двумя датчиками выводить целое число?
>>Pyotr, вся задумка была в чём? Что б полностью отказаться от delay(),
Я так и указал в скетче:
delay(1000); //только для примера
А вызывать функцию
tempProcess() можно через таймер, millis(), по какому то событию-это кому как нравится.И функция tempProcess() возвращает целое число в градусах Цельсия, а не просто 2 байта, которые ещё нужно перевести в градусы. Думаю, для начинающих это понятнее.
itehno, это проще чем просто :) в выводе температуры где temp/16.0 напишите temp/16
Спасибо. А Вы не могли бы подробнее описать этот участок кода? Почему 16?
itehno, данные "после запятой" записываются дополнительными 4-мя битами, что даёт общее 16-кратное умножение того целого числа, что записано в регистрах температуры.
itehno, данные "после запятой" записываются дополнительными 4-мя битами, что даёт общее 16-кратное умножение того целого числа, что записано в регистрах температуры.
Спасибо
Я вот только не пойму как после получения 16 бит числа
идёт декодирование допустим вот этих, выделенных мной, измерений в табличке из документации:
TEMPERATURE DIGITAL OUTPUT (BINARY) DIGITAL OUTPUT(HEX)
+125 0000 0111 1101 0000 07D0h
+85 0000 0101 0101 0000 0550h
+25.0625 0000 0001 1001 0001 0191h
+10.125 0000 0000 1010 0010 00A2h
+0.5 0000 0000 0000 1000 0008h
0 0000 0000 0000 0000 0000h
-0.5 1111 1111 1111 1000 FFF8h
-10.125 1111 1111 0101 1110 FF5Eh
-25.0625 1111 1110 0110 1111 FE6Fh
-55 1111 1100 1001 0000 FC90h
trembo, дык это мозговзрывательный счёт отрицательных чисел. Если в старшем бите единица, значит всё слово инвертируется, и к нему ещё прибавляется единица ) Т.е. ~ FF5Eh == (0xA1h + 1) = 162(dec) А 162/16 = то самое число
Прошу прощения. Может Вы подскажете. Не получается объединить Ваш код, с моим так, что бы одновременно можно было управлять яркостью светодиода. Помогите разобраться, пожалуйста.
itehno, с потенциометра вы считываете, а куда дальше это знание деваете?
Точно. Забыл про analogWrite(led, x);
Что-то сегодня мозги к вечеру плавится начали. Теперь работает.
Можно ещё вопрос? Как записать данные температурных датчиков в переменные? К примеру temper1 и temper2. С использованием библиотеки <DallasTemperature.h> я делал так:
А чем вас не устраивают temp1 и temp2? По религиозным соображениям, можно так: temper1=temp1; )))))
Да, на 16 поделить не забудьте.
Прошу, не судите строго. Я только постигаю азы.
Если я Вас правильно понял, то должно быть так?
СПАСИБО, СПАСИБО, СПАСИБО!
ВСЁ РАБОТАЕТ!
ОГРОМНОЕ СПАСИБО ЗА ВАШЕ РЕШЕНИЕ!
А вот не выходит каменный цветок:
Ставил напрямую
byte t1= 0xff;
byte t2= 0x5e;
t = t1 | t2;
00A2 результат 10.1 (+10.125) ОК
FF5E результат 15.9 (-10.125) не ОК
http://mcucpu.ru/index.php/pdevices/datchiki/110-preobrazovanie-koda-tsifrovykh-datchikov-temperatury
trembo, не надо так допозна засиживаться, с утра голова лучше считает :). Отбросим старшие байты, они в очевидной инверсии. Итого имееем A2 и 5E
Добрый день!А подскажите пожалуйста,я использовал даный скетч на 3 датчика,с записью данных каждую секунду на карту памяти и выводом через I2C на дисплей 16х2.Проблема в том,что по прошествии некоторго времени дисплей начинает отображать всякие иероглифы,приходится всю систему перегружать дабы вернуть читаемые показания на дисплее,но на карту данные пишутся корректно.Может быть глюк экрана связан с использованием в данном скетче прирываний?Когда использовал библиотеку даласс такого глюка не было.Все смонтированно пока на макетке в связке с ардуино уно.Или может быть в схему надо добавить конденсатор для более стабильной работы дисплея?
Надеюсь все понятно описал ))
скажите, а этот скетч работает при паразитном подключении нескольких датчиков?
у меня чето пока вот так
В 19 строке скетча из первого поста попробуйте изменить 0х44 на 0х44 , 1.
И почитайте это , сразу станет понятнее.
спасибо. я пользуюсь кодом для двух датчиков, поэтому добавил подключение питания на время преобразования (,1) в 36 строку для Варианта с двумя датчиками
чуть получше..
Судя по 85гр, похоже не хватает питания для преобразования. Это значение записывается в регистр в момент подключения. Проверьте все соединения, возможно нужен конденсатор на последний датчик. Датчики подключаем на один шлейф (не звездой).
да оба датчика подключены на один и тот же бредборд рядом.
тем более даже если он один то все равно показывает 85.
странно вот еще что - если в коде меняю порядок вывода данных, то есть сначала
ds.select(addr2);
а потом
ds.select(addr1);
то ОБА и ПО ОДНОМУ показывают нормальную температуру.
такой же эффект был и на DallasTemperature.. Поэтому думаю, что чтото не так с этим сенсором.. или фиг его уже знает, почему ему хочется быть первым..
Предлагаю у Dimax не флудить, а вернуться в вашу тему. К коду это точно отношения не имеет.
Здравствуйте! Меня заинтересовала идея использования сторожевого таймера для генерации прерываний по времени, думаю, для Ардуино это актуально. Посмотрел стр55 даташита (по ссылке) и обнаружил, что WDE и WDIE подняты (что должно не только вызывать прерывание, но и ресетить контроллер. Ресета не происходит, потому что он не разрешен фьюзами? Я просто этот способ с таймером хочу взять на вооружение. Какие могут быть грабли?
Тарас Петрович, ресета нет потому, что биты WDE и WDIE не поднимаются одновременно. Граблей никаких нет, я использую этот таймер давно.
Теперь понял.
Значение регистра из первой строчки не переносится во вторую. Благодарю за код для датчика, а особенно за идею с WDT, уже опробовал))
При использовании внешнего питания 18В20 считывать температуру можно даже в процессе конвертирования. Если разрешение 11 бит, то max время преобразования будет 375ms, т.е. опрос и преобразование можно вести каждые 0,5 сек (со скоростью моргания точки часов) с точностью 0,125 градуса. (т.е. данные температуры будем получать каждую секунду)
При линии более 20м на датчике получил слишком зашумлённую паразитную линию. Это привело к получению некорректных данных (когда раз в 5 мин, когда через 30сек) - в логе считывалась не правильная температура. Добавил проверку контрольной суммы:
if (OneWire::crc8(data_DS_out, 8) != data_DS_out[8]) { Serial.println ("OUTPUT CRC is not valid!"); goto read_ds;
Это избавило от ложных срабатываний. Рекомендую.
А в четвёртый байт конфигурации правильнее будет писать так:
ds.write(0x5F); // точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F
emserg, при опросе каждую секунду, вы реально можете получить плюс пару градусов к фактической температуре (не успевает он мощность рассеивать). Смысл в таком опросе?
20 метров для них вполне комфортно (здесь у кого то более 100метров и датчиков вагон), проверьте аппаратную часть (резисторы и соответствие питания на конце линии).
emserg, при опросе каждую секунду, вы реально можете получить плюс пару градусов к фактической температуре (не успевает он мощность рассеивать). Смысл в таком опросе?
20 метров для них вполне комфортно (здесь у кого то более 100метров и датчиков вагон), проверьте аппаратную часть (резисторы и соответствие питания на конце линии).
Да, и 305 метров на корбке витой пары проверял, но только не на паразитном питании
Да, и 305 метров на корбке витой пары проверял, но только не на паразитном питании
Ну, паразитное питание это уже от безысходности.(((( ИМХО.
Я использую такой быстрый опрос в газовом котле BAXI для тёплого пола. Т.к. это неграмотный котёл (зато дешёвый, скорость нагрева воды в 3 раза быстрее прокачки насосом 70л/мин) скорость нагрева воды очень быстрая и за 1сек у меня обновляется полность вода в контуре. Нагрев дачика при НЕПРЕРЫВНОЙ конвертации составляет 0,5 грдуса, и в чём разница между моим опросом и конвертацией каждую секунду при 12 битах? Любое непрерывное преобразование вызывает лишь разницу на собственный нагрев, так скомпенсируйте его просто вычитая этот нагрев (например 0,5 сравните с ртутным если это актуально и принципиально) из считанного с датчика. Большинству людей в обычной обстановке достаточно точности 0,5 градуса, но иногда, если нужно, то скорость нарастания от 30 до 40 градусов за 20 сек с такой дискретностью вычислить сложно.
ПРОВЕРКА на бухте в 305м и РЕАЛЬНАЯ работа с ГАРАНТИЕЙ КАЧЕСТВА - разные вещи.
По поводу контрольной суммы: при отладке одного проекта возникли сложности (рядом работало несколько Danfoss приводов) при нормальном питании (по тестеру) обычная китайская ЭКРАНИРОВАННАЯ витая пара (UTP5E) работала как антена. На КАЖДОМ из всех трёх датчиков сразу на выводах висели безкорпусные КЕРАМИЧЕСКИЕ конденсаторы по 0,01; 0,22; 10,0 мкф (от материнских плат); питание ATMEGA328 и DS18B20 через свой БП с UPS СИНУСОИДАЛЬНОЙ формой - НЕ СПАСЛО!!! Резисторы подбирались от 5,1К до 560 Ом (осциллографом DSO8060 разглядывали форму). Одевали всякие ферритовые колечки, добавляли дроссели, НО, как только добавили проверку контрольной суммы, проблема решилась.
У каждого человека в голове свои тараканы. (К примеру, у меня вместо батарей 10 петлей тёплого пола. Все петли подключены через электромагнитные клапана. Котёл думает, что работает только на один контур, а arduino UNO ему постоянно мозги пудрит играя клапанами в зависимости от температуры в каждой комнате).
Поэтому, мне в моём "умном доме" к примеру, включение котла на 1 сек из-за случайного сбоя передачи данных, (по МЕДНОМУ FTP 5E кабелю) который показал +5 или -29 в КОМНАТЕ один раз в сутки (или один раз в 5 мин) НЕНАДО! А вот использование CRC (которая уже реализована в этом протоколе) просто добавляет надёжности. Каждый волен выбирать сам, лишь бы был выбор. Я предложил, а не навязывал. Потеря в скорости сомнительна, т.к. нового опроса по шине нет (при отсутствии подпора резистором считываются 00000 и контрольная сумма считывается правильная =0 (для этого я просто добавил проверку на 0 в помещении и 0 CRC; хотя этого НИКОГДА не будет в помещении, но ведь у меня ещё есть и уличные датчики)), а вот надёжность гарантирована, даже если будет сбой один раз за сто лет.
огромное спасибо! действительно очень классная тема!
возник только глупый вопрос.
зачем указвается void setup(void), если можно писать просто void setup()??
trembo, дык это мозговзрывательный счёт отрицательных чисел. Если в старшем бите единица, значит всё слово инвертируется, и к нему ещё прибавляется единица ) Т.е. ~ FF5Eh == (0xA1h + 1) = 162(dec) А 162/16 = то самое число
допКод ?
А если WDT в проекте уже занят по прямому назначению, то надо использовать другой таймер?
А если WDT в проекте уже занят по прямому назначению, то надо использовать другой таймер?
Берите с бабушкой millis().
Вызов из loop - dallRead(flagDallRead*1000);
Эээээ..... а бабушка причем?
это мама всех проггеров , кому 50+
:)-
тибе - бабушка точьно
"Момент истины" - бабушка приехала !!!!!!
у америкосов аналоги - орёл вылетел , птичька в гнезде и т.д.
миллис() - "бабушка" всем другим операторам :)
....базовая , старшая
это мама всех проггеров , кому 50+
:)-
тибе - бабушка точьно
"Момент истины" - бабушка приехала !!!!!!
у америкосов аналоги - орёл вылетел , птичька в гнезде и т.д.
миллис() - "бабушка" всем другим операторам :)
....базовая , старшая
Ну ты летчик завернул. Это из Di Halta: "Бабушка Миллис постоянно в лупе вяжет носки....."