Яндекс.Метрика

Система Orphus

Arduino - Термометр на DS1621.

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

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

Arduino & DS1621

И так. Термометр. В качестве базовой платформы используем плату Duemilanove + щит LCD Keypad (которую я уже представлял). Термометр DS1621 распаян безо всякой обвески. За основу описания работы Ардуино с устройствами по шине I2C, и даже более конкретно - с данным термометром был взят алгоритм представленный тут (четвертый пост) ... Там описанна лишь самая "вершинка" того, что можно "взять" от этого датчика (температура с точностью до целого градуса). Руководствуясь документацией можно (и нужно) считывать показания с точностью до половины градуса цельсия. Прибегая же к чтению дополнительных коэффициентов с термометра, расчетным путем можно достигнуть более высокой точности - а именно величины в 1/16 градуса цельсия (все по документации). Оба варианта представлены в моем исходном коде ниже и максимально детально прокомментированы. На этом нюансы работы с термометром DS1621 при помощи Ардуины (да и в целом) можно считать раскрытыми.

// Simple DS1621 Higher resolutions mode// Пример считывания и декодирования показаний термометра DS1621// -- by MiGeRA (migera.ru)// -- 28 NOV 2011// Схема подключения проста ...// SDA pin is Analog4// SCL pin is Analog5// DS1621 has A2, A1, and A0 pins connected to GND// Библиотека по работе с шиной I2C#include <Wire.h>// Библиотека по работе с ЖК экранами#include <LiquidCrystal.h>// Конфигурируем способ подключения экрана ...LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // В нашем случае это "LCD Keypad Shield"// Описываем начертание символа "t-штрих"byte T1[8] = {   B00001,   B00001,   B01000,   B01000,   B11100,   B01000,   B01110,   B00000, };// Описываем начертание символа "t-два штриха"byte T2[8] = {   B00101,   B00101,   B01000,   B01000,   B11100,   B01000,   B01110,   B00000, };#define DEV_ID 0x90 >> 1                    // сдвиг требуемый wire.h// Описываем используемые переменныеfloat cpc = 0; // для хранения "COUNT_PER_C" - см. документацию на DS1621float cr = 0; // для хранения "COUNT_REMAIN" - см. документацию на DS1621float temp = 0; // первый (основной) байт показания температуры с термометраfloat temp2 = 0; // "довесок" - наличие которого добавляет полградусаfloat result = 0; // результат посчитанный по формуле (более точный)float result2 = 0; // результат считанный непосредственно, с учетом довеска (менее точный)float tempF = 0; // результат посчитанный по формуле, переведенный в фарингейтыfloat mintemp = 125; // инициализация переменной для хранения минимумаfloat maxtemp = -55; // инициализация переменной для хранения максимума// Инициализацияvoid setup(){// Записываем в ЖКИ новые символы lcd.createChar(0, T1); lcd.createChar(1, T2);// Конфигурируем количество строк и символов в строке  lcd.begin(16, 2); lcd.clear();// Инициализируем термометр Wire.begin(); Wire.beginTransmission(DEV_ID); // обращаемся к термометру по его идентификатору на шине I2C Wire.send(0xAC); // адресуемся для следующего обращения к регистру конфигурации Wire.send(0x01); // конфигурируем дальнейшее преобразование результата по запросу// Wire.send(0x02);                          // как вариант - конфигурируем автоматическое преобразование результата Wire.beginTransmission(DEV_ID); Wire.send(0x22); // временно приостановить преобразование данных термометром// Wire.send(0xEE);                          // для альтернативного варианта - запустить преобразование Wire.endTransmission();}// Основная частьvoid loop(){// Запускаем преобразование ... (не требуется в случае, если запустили раньше)   Wire.beginTransmission(DEV_ID); Wire.send(0xEE); Wire.endTransmission();  // Даем передышку термометру для преобразования delay(750); // Читаем результаты ...// Сначала значение корректирующего коэффициента COUNT_PER_C Wire.beginTransmission(DEV_ID); Wire.send(0xA9); Wire.endTransmission(); Wire.requestFrom(DEV_ID, 1); cpc = Wire.receive(); // Теперь значение корректирующего коэффициента COUNT_REMAIN Wire.beginTransmission(DEV_ID); Wire.send(0xA8); Wire.endTransmission(); Wire.requestFrom(DEV_ID, 1); cr = Wire.receive();// Теперь основное значение термометра и "довесок" Wire.beginTransmission(DEV_ID); Wire.send(0xAA); Wire.endTransmission(); Wire.requestFrom(DEV_ID, 2); temp = Wire.receive(); temp2 = Wire.receive(); // Приостанавливаем преобразования (в альтернативном варианте - не делаем этого) Wire.beginTransmission(DEV_ID); Wire.send(0x22); Wire.endTransmission(); // Считаем результат по формуле: result = temp - 0.25 + ((cpc-cr) / cpc);// Или только учитываем довесок - получаем альтернативный, менее точный, результат (зато без расчетов) if (temp2 == 128) result2 = temp + 0.5; else result2 = temp; // Переводим в фарингейты tempF = result * 9 / 5 + 32; // Фиксируем возможные минимум и максимум if (mintemp>=result) mintemp=result; if (maxtemp<=result) maxtemp=result;// Теперь отрисовваем результат на ЖКИ lcd.clear(); lcd.home(); // Первая строка отображает температуру в цельсиях:// * первое показание t' - посчитано по формуле из документации и имеет более точное (хотя и дискретное) значение// * второе показание t'' - считано непосредственно и имеет дискретное значение с точностью до полградуса цельсия lcd.write(0); // Спецсимвол t' lcd.print(result); lcd.print("C "); lcd.write(1); // Спецсимвол t'' lcd.print(result2); lcd.print("C"); lcd.setCursor(0, 1); // Вариант 1 - Вторая строка отображает расчетные коэффициенты lcd.write(0); lcd.print(tempF); lcd.print("F "); lcd.print(temp,0); // "0" - не отображается дробная часть в виду ее отсутствия lcd.print(" "); lcd.print(cpc,0); // "0" - не отображается дробная часть в виду ее отсутствия lcd.print(" "); lcd.print(cr,0); // "0" - не отображается дробная часть в виду ее отсутствия// Вариант 2 - Вторая строка отображает минимальное и максимальное значение/* lcd.setCursor(0, 1); lcd.print("l"); lcd.print(mintemp); lcd.print("C h"); lcd.print(maxtemp); lcd.print("C");*/}

MiGeRA (ноябрь 2011)



Заглавная » Радиоэлектроника » Arduino - Высокоуровневая платформа устройств на микроконтроллерах » Arduino - Термометр на DS1621