Главная » Arduino
Призовой фонд
на август 2020 г.
1. 1500 руб
Сайт Паяльник
2. Регулируемый паяльник 60 Вт
Сайт Паяльник

Похожие статьи:


Сложно о простом: цифровой термометр

Предыстория

После карантина захотелось потренироваться в разводке плат в Easy EDA и их изготовлению методом ЛУТ, да и особого желания делать сразу что-то сложное не было. Поэтому на роль "подопытного кролика" выступил проект цифрового термометра. К тому же это был отличный шанс попрактиковаться в написании программ для МК на C++.

Немного теории

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

Теоретический практикум

Для проекта был подобран следующий терморезистор (рис. 1). Данный артефакт ещё советских времён ( штекер "СШ-5"), но несмотря на свой возраст, работает отлично.

терморезистор
Рисунок 1 - терморезистор

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

После первичного осмотра необходимо снять зависимость сопротивления от температуры. Для этого нам понадобится образцовый термометр и мультиметр (рис. 2).

необходимые инструменты
Рисунок 2 - необходимые инструменты

План замеров таков:

  1. Замеряем температуру и сопротивление датчика при комнатной температуре.
  2. Записываем результаты замеров.
  3. Замеряем температуру и сопротивление датчика при различной температуре (В горячей, холодной, тёплой воде и тд).
  4. Записываем результаты замеров.
  5. Повторяем пункты 3 - 4 до тех пор, пока значений будет не менее 3-х.

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

  1. Определить ТКС (Температурный Коэффициент Сопротивления). Если ТКС < 0, то расчёты производятся по уравнению Стейнхарта-Харта, если ТКС > 0, то зависимость на некотором участке диапазона близка к линейной. В моём случае ТКС > 0, а зависимость линейная (Значит терморезистор изготовлен из какого-то металла). 
  2. Для положительного ТКС: вбиваем показания в Excel и строим график. Далее добавляем линию тренда и выводим полученное уравнение (рис. 3).

получение прогноза температуры от сопротивления
Рисунок 3 - получение прогноза температуры от сопротивления

T = 17.173R - 130.82,

где T - температура в градусах Цельсия, а R - сопротивление в килоомах. Данная функция понадобится позже, а именно при написании скетча.

P.s. Данный практикум больше служит для выяснения типа датчика, нежели для получения итоговой функции (Т.к. проще составить прямую зависимость значения АЦП от температуры).

Схема электрическая принципиальная

схема электрическая принципиальная
Рисунок 4 - схема электрическая принципиальная

Да, опять я не пользуюсь сдвиговыми регистрами или драйверами семисегментников... С другой стороны, проект простенький и поэтому особого смысла в экономии выводов ATMEGA328 я не видел. Датчик подключается в разъём H1, который вместе с резистором R1 образуют делитель напряжения. Напряжение с делителя напрямую поступает на аналоговый вывод МК. Данный узел необходим для измерения сопротивления терморезистора. 

Печатная плата и 3D модель устройства

Так как изначальной идеей проекта была тренировка в разводке ПП в Easy EDA, то и делать плату мы будем в этой программе (рис. 5). Итоговый размер платы 90x63 мм.

рисунок ПП в Easy EDA
Рисунок 5 - рисунок ПП в Easy EDA

Также для статьи была подготовлена 3D модель устройства (рис. 6).

3D модель устройства
Рисунок 6 - 3D модель устройства

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

Перед печатью необходимо экспортировать плату в .pdf из программы (Верхний и нижний слои) в чёрно-белом варианте без шелкографии (Это легко настраивается в окне экспортирования (рис. 7)). Нижний слой экспортируется без изменений, а верхний зеркально!

настройки экспортирования для верхнего слоя 
 Рисунок 7 - настройки экспортирования для верхнего слоя 

Далее печатаем на лазерном принтере или несём PDFки в ближайший копицентр, где просим печать на лазерном принтере на глянцевой бумаге (Единственное, что надо учесть: Easy EDA экспортирует одну картинку на целый лист. Мне в копицентре из одиночной картинки на лист сделали лист с 4 копиями обеих сторон, но это могут делать не везде).

Изготовление печатной платы

После печати трафаретов их необходимо перенести на текстолит методом ЛУТ (Не принципиально, просто я им пользуюсь, да и многие тоже). 
Небольшая инструкция по изготовлению двусторонней платы ЛУТом:
  1. Необходимо вырезать трафареты с запасом (по 5 мм с каждой стороны).
  2. Потом их необходимо совместить на просвет так, чтобы все отверстия совпали.
  3. Когда отверстия совпадут, скрепляем шаблоны по краям степлером (Аккуратно и не спеша). Лучше скреплять стороны по очереди, следя за отверстиями.
  4. После соединения шаблонов подготавливаем кусок текстолита по размерам платы и собираем "бутерброд".  
  5. После выравнивания текстолита и шаблонов фиксируем "бутерброд" степлером.

Далее "бутерброд" необходимо разгладить с обеих сторон - тут нужен опыт, у меня так и не получается всё сделать идеально. После хорошо отмываем, так чтобы не осталось белого налёта на медном слое (Тут главное не перегреть плату при переносе рисунка утюгом, иначе налёт будет очень трудно снять), и получаем результат (рис. 8.1 и рис. 8.2).


Рисунок 8.1 - нижняя сторона ПП


Рисунок 8.2 - верхняя сторона ПП

Результат неидеален, но приемлем. Полученную "плату" кидаем в ваш любимый раствор для травления (Я пользуюсь медным купоросом) и вытравливаем плату. Потом отмываем, сверлим отверстия, паяем... Итоговый результат сборки представлен на рисунке 9.1 и рисунке 9.2.


Рисунок 9.1 - верх


Рисунок 9.2 - низ

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

результат совмещения слоёв
Рисунок 10 - результат совмещения слоёв

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

Практика

Когда дело доходит до практики, то начинаются проблемы с теорией... Основной причиной проблем стала плохая пайка аналогового входа МК, поэтому пришлось перелопатить весь делитель (рис. 11), чтобы понять где была проблема (Совет: Всегда проверяйте пайку мультиметром - это поможет избежать различных проблем). Поэтому все прошлые расчёты можно смело забыть (Но закон Ома забывать не советую) ;).


Рисунок 11 - окончательная схема

Изменения в схеме в основном коснулись делителя, а также был отвязан вывод AREF от +5 В. Теперь R1 притягивает пин PC0 к земле, и номинал резистора был изменён с 10 кОм до 8.1 кОм

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

прогноз температуры от значения АЦП
Рисунок 12 - прогноз температуры от значения АЦП

Итоговой формулой для моего датчика (Напомню, он обладает положительным ТКС и имеет линейную характеристику) стало следующее выражение:

T = -0.7309*X + 378.49, 

где T - температура в градусах Цельсия, а X - значение АЦП. Данная формула оказалась вполне рабочей и показания контрольного и самодельного термометров совпадают +- погрешность округления (обрезки дробной части =) ) (рис. 13).

 
Рисунок 13 - первое включение и тесты (Затемнение на фото вызвано высокой яркостью индикатора)

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

Скетч

Помимо проблем с пайкой были ещё и проблемы с самой ATMEGA328PU: экземпляр, который я купил в радиомагазине тактируется исключительно от 1 МГц (брак какой-то), поэтому всеми любимый ардуино код пришлось переделать в гибридный вариант. Изменения в основном коснулись динамической индикации, так как при тактовой частоте 1 МГц ардуино код вызывал сильное мерцание сегментов. Поэтому пришлось писать динамическую индикацию на прямом обращении к регистрам портов (рис. 14).

порты ATMEGA328P
Рисунок 14 - порты ATMEGA328P

У ATMEGA328P всего 3 порта: PORTB, PORTC, PORTD, из которых PORTC - аналоговый (Содержит АЦП). Как видно из рисунка 15 выводы кварца и даже "Reset" являются частью портов и могут быть сконфигурированы для работы с помощью фьюзов,как и обычные пины ("Reset" трогать не советую ;) ). 

Для конфигурации порта необходимо использовать регистр DDR + "Имя порта" (B,C или D и тд.). Пример:

void setup()
{
DDRC = B111110; //Количество бит = количеству пинов от 0 до максимального. В данном случае: от PC0 до PC5. ​DDRD = B11111100; // Данный вариант аналогичен пачке pinMode(), но при этом выполняется гораздо быстрее и занимает меньше памяти.
DDRB = B00111111; // Но в отличии от pinMode() данный метод не имеет защит, поэтому нужно быть внимательным.
}

Нумерация битов идёт справа налево - это нужно помнить!"1" соответствует режиму выхода, "0" - входу. 

Теперь краткий экскурс по правильному управлению большим количеством пинов. Пример:
 

 int data[4] = {0,0,0,0};
   double T = 0;
   bool negative = false;
   const bool chisla[10][8] = { { 0,0,0,0,0,0,1,1 },{ 1,0,0,1,1,1,1,1 },{ 0,0,1,0,0,1,0,1 },{ 0,0,0,0,1,1,0,1 },{ 1,0,0,1,1,0,0,1 },{ 0,1,0,0,1,0,0,1 },{ 0,1,0,0,0,0,0,1 },{ 0,0,0,1,1,1,1,1 },{ 0,0,0,0,0,0,0,1 },{ 0,0,0,0,1,0,0,1 } };

void show()
{
   for (int i = 0; i < 4; i++)
   {
   unsigned long sec = micros();
   while (micros() - sec < 500)
   {   PORTC = 32 * chisla[data[i]][0];   if ((i == 3) && negative)
   {
   PORTC = B100010;
   PORTD = B01111100;
   }
   else
   {
   PORTD = 4 * chisla[data[i]][1] + 8 * chisla[data[i]][2] + 16 * chisla[data[i]][3] + 32 * chisla[data[i]][4] + 64 * chisla[data[i]][5] + 128 * chisla[data[i]][6];
   }
   PORTC |= 1 << (4 - i);
   }   }   }

Данный метод выводит значение, записанное по цифрам в массив data[]. В отличии от варианта на ардуино коде эта реализация более компактная и оптимизированная, но гораздо сложнее для понимания и отладки (Я потратил на отладку 2 дня).

И так. в массиве chisla[][] записаны коды чисел для семисегментного индикатора с общим анодом. Цикл for перебирает цифры в массиве data[] и подставляет их в один из индексов массива chisla[][], тем самым получая код нужной цифры. Далее массив из 0 и 1 необходимо преобразовать в двоичное число для регистра... На первый взгляд задача сложная, но на самом деле всё гораздо проще.

Для перевода кода цифры необходимо воспользоваться школьными познаниями в информатике: вспомнить перевод числа из десятичной системы счисления в двоичную. Умножая 0 и 1 на 2 в нужной степени мы получим необходимый двоичный код. Пример: для того чтобы "потушить" сегмент "А" необходимо на  сегмент "А" подать 5В. Для этого согласно схеме необходимо подать "1" на вывод PC5, т.е. сформировать вот такое двоичное число: "B100000" или умножить 1 на 25 или на 32 (В двоичном виде 32 представляет собой как раз "B100000") =). Код на С++: 

PORTC = 32 * chisla[data[i]][0];

В данном случае "0" или "1" берутся из массива chisla[][]. По такому же принципу работают и другие сегменты.   

Теперь поговорим о переключении разрядов. Тут всё элементарно - побитовый сдвиг. Т.к. индикатор с общим анодом, то двигаем мы "1". Код на С++:

PORTC |= 1 << (4 - i);

Цикл while в этом методе нужен для "удержания" цифры, чтобы всё случайно не смешалось во едино.

Питание

Для корректной работы АЦП вход AREF необходимо обеспечить стабильным источником опорного напряжения. Т.к. в режиме "DEFAULT" AREF притянут к AVCC, а AVCC питается у нас от 5 В, то для корректной работы АЦП необходим ИОН на 5 В. Чтобы не городить огород с кучей проводов питания - объединим AVCC и VCC, а весь прибор запитаем от DC-DC преобразователя на 5 В (Только необходимо помнить о возможных шумах преобразователя, всё же это китайский модуль).

Итоги

предфинальный результат (Показывает температуру в комнате)
Рисунок 15 - предфинальный результат (Показывает температуру в комнате)

Чтобы не растягивать статью покажу предфинальный результат (Без корпуса, DC-DC преобразователя и немного сыроватым скетчем (Я кнопочку так пока и не задействовал)). Также прибору необходима калибровка, но это последний этап и выполняется он в случае необходимости, а пока меня всё устраивает, но пару слов по данной теме я скажу:

  1. Для калибровки понадобятся 2 ёмкости: с кипящей водой и с почти замёрзшей (Чтобы плавал лёд). Кипящая вода имеет температуру в 100 °C, а почти замёрзшая - 0 °C. 
  2. Далее необходимо зафиксировать значения АЦП в этих 2-х точках и добавить их на график (в таблицу) (рис. 12,).

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

Теперь собственно итоги:

  • Цифровой термометр - это не такой простой прибор, как кажется, если подойти к вопросу не со стороны готовых модулей и ардуинки.
  • Проектирование даже простых устройств начинается с теории и расчётов, даже если потом они не понадобятся ;).
  • Сделать двустороннюю плату в домашних условиях ЛУТом можно и это относительно просто, но муторно. 
  • "Заливка" платы земляным полигоном - хорошо и удобно, но с зазором нужно быть внимательным, так как при изготовлении платы ЛУТом можно поиметь много неприятных сюрпризов.
  • Ардуино код - удобно, но не эффективно. При работе с большим количеством пинов рекомендуется напрямую работать с регистрами.

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

Также, для тех кому будет интересно, прикрепил для всех исходники с Easy EDA и скетч.

Прикрепленные файлы:

Теги:

Опубликована: 0 0
Я собрал 0 1
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 5 Проголосовало: 1 чел.

Комментарии (6) | Я собрал (0) | Подписаться

0
Публикатор #
На форуме автоматически создана тема для обсуждения статьи.
Ответить
0
AMatroskin #
Интересно, ещё бы больше подробностей по скетчу и логике его работы, именно такие проекты и ценны, но почему то почти все кто хорошо знает МК, всегда опускают этот момент.
Ответить
0

[Автор]
Radio Engineer #
Логика простая: замеряем значение через analogRead() (Вызывается он раз в полсекунды, так что пофиг).Тут же считаем значение температуры по формуле. В промежутках между замерами крутим функцию вывода числа на дисплей - всё. А вот правильная реализация динамической индикации - это сложно.
Отредактирован 15.07.2020 22:22
Ответить
0
likita #
Есть кривая сопротивления резистора или термопары от температуры ... Раньше через чуть ли не градус кривую снимали .
Ответить
0
Андрей #
При выводе из EeasyEda в "зеркале" необходимо три нижних галки поставить в положение "Mirror", иначе возможен неверный результат. Я такое не раз ловил, а разработчики посоветовали делать именно так, как я написал.
Ответить
0

[Автор]
Radio Engineer #
Кстати, я опечатался, надо ещё галочку "Hole" снять, а вот остальное подбором настраивается... В принципе я так и делал.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическое сопротивление?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Arduino UNO
Arduino UNO
Конструктор УНЧ 60 Вт на LM3886 Сатфайндер
вверх