Урок о подключении к контроллеру Ардуино интегральных датчиков температуры с аналоговым выходом. Приводится рабочий проект термометра, рассказывается о программной обработке информации с термодатчиков.
Предыдущий урок Список уроков Следующий урок
Этой публикацией я начинаю цикл уроков об измерении температуры в системе Ардуино. Всего планируется 4 урока посвященных различным типам датчиков температуры:
- интегральным термодатчикам с аналоговым выходом - LM35, TMP35, TMP36, TMP37;
- кремниевым термодатчикам серии KTY81;
- интегральным датчикам с цифровым интерфейсом 1-Wire – DS18B20;
- термопарам (термоэлектрическим преобразователям).
В каждом уроке я расскажу:
- коротко о принципе работы и параметрах термодатчиков;
- о схемах подключения термодатчиков к микроконтроллерам;
- расскажу о программной обработке информации с термодатчиков;
- приведу схему термометра на базе платы Ардуино и программное обеспечение для него.
В каждом уроке будет рассмотрен проект термометра на базе контроллера Ардуино работающий :
- в автономном режиме с выводом информации на LED индикатор;
- в режиме связи с компьютером, позволяющем не только отображать текущую температуру, но и регистрировать изменение температуры с выводом данных в графическом виде.
Интегральные датчики температуры с аналоговым выходом по напряжению.
При всем разнообразии этих устройств, им присущи следующие общие качества:
- напряжение на выходе линейно пропорционально температуре;
- датчики имеют калиброванный масштабный коэффициент зависимости выходного напряжения от температуры, дополнительной калибровки не требуют.
Попросту говоря для измерения температуры с помощью датчиков такого типа необходимо измерить напряжение на выходе и через масштабный коэффициент пересчитать его в температуру.
Существует множество термодатчиков, которые можно отнести к этой категории. Я бы выделил следующие типы датчиков температуры:
- LM35;
- TMP35;
- TMP36;
- TMP37.
Это самые распространенные, достаточно точные, недорогие устройства. Я писал статьи об этих датчиках. Можно посмотреть по ссылкам LM35 и TMP35, TMP36, TMP37. Там подробно описаны все параметры, технические характеристики устройств, типовые схемы включения.
Подключение термодатчиков к микроконтроллеру.
Удобнее всего использовать датчики в корпусе TO-92.
Схема подключения для устройств в корпусе TO-92 выглядит так.
По этой схеме будут работать все перечисленные датчики. Информацию о других схемах включения термодатчиков можно посмотреть по ссылкам LM35 и TMP35, TMP36, TMP37.
Основные параметры, различия датчиков.
Принципиальные отличия перечисленных датчиков друг от друга заключается в том, что:
- TMP36 – единственный из перечисленных термодатчиков, способен измерять отрицательную температуру.
- Датчики имеют различные диапазоны измерения температуры.
Речь идет о термодатчиках, подключенных по приведенной выше схеме. Например, есть схема включения LM35, позволяющая измерять отрицательные температуры. Но она сложнее в реализации и требует дополнительного питания. Лучше для отрицательных температур использовать TMP36.
Основные параметры термодатчиков LM35, TMP35, TMP36, TMP37 для этой схемы я свел в таблицу.
Тип | Диапазон измерения температуры, °C |
Смещение напряжения на выходе, мВ |
Масштабный коэффициент, мВ/°C |
Напряжение на выходе при +25 °C, мВ |
LM35, LM35A | 0 … + 150 | 0 | 10 | 250 |
LM35C, LM35CA | 0 … + 110 | 0 | 10 | 250 |
LM35D | 0 … + 100 | 0 | 10 | 250 |
TMP35 | + 10 … + 125 | 0 | 10 | 250 |
TMP36 | - 40 … + 125 | 500 | 10 | 750 |
TMP37 | + 5 … + 100 | 0 | 20 | 500 |
У всех термодатчиков напряжение на выходе может быть только положительным, но за счет смещения TMP36 способен измерять отрицательную температуру. Нулевое напряжение на его выходе соответствует температуре – 40 °C, а при выходном напряжении 0,5 В температура будет равна 0 °C. Я считаю TMP36 самыми удобными из аналоговых интегральных датчиков температуры и использую их достаточно широко.
Проект Ардуино термометра на датчиках температуры LM35, TMP35, TMP36, TMP37.
Разработаем термометр, который будет:
- В автономном режиме отображать значение температуры на четырех разрядном семисегментном светодиодном (LED) индикаторе.
- Передавать текущее значение температура на компьютер. Наблюдать его можно с помощью монитора последовательного порта Arduino IDE.
- С помощью специальной программы верхнего уровня (я ее написал):
- отображать измеренную температуру на мониторе компьютера.
- регистрировать изменение температуры и отображать его в графическом виде.
Схема термометра на базе платы Arduino UNO R3.
К плате Ардуино необходимо подключить:
- четырех разрядный семисегментный LED индикатор в мультиплексированном режиме;
- датчик температуры TMP36 или подобный.
Я выбрал светодиодный индикатор типа GNQ-3641BUE-21. Он яркий, оптимальных для этой задачи размеров. Мы подключали его к плате Ардуино в уроке 20. В этом уроке можно посмотреть документацию на индикатор, схемы подключения. Там же есть описание библиотеки управления семисегментными LED индикаторами.
Схема термометра на базе платы Arduino UNO R3 выглядит так.
LED индикатор подключен к контроллеру в мультиплексированном режиме ( урок 19, урок 20).
Датчик температуры подключен к аналоговому входу A0. Конденсатор C1 – блокирующий питание датчика, R1 и C2 – простейший аналоговый фильтр. Если термодатчик установлен вблизи микроконтроллера, то фильтр можно исключить из схемы.
TMP35, TMP36, TMP37 допускают работу на нагрузку емкостью до 10 нФ, а LM35 – не более 50 пкФ. Поэтому, если датчик соединяется с контроллером длинной линией имеющей значительную емкость, то резистор R1 должен быть установлен со стороны датчика, а конденсатор C2 – со стороны контроллера. Блокировочный конденсатор C1 всегда устанавливается рядом с термодатчиком.
В любом случае в программе контроллера будет реализована цифровая фильтрация сигнала с датчика.
Для проверки я собрал устройство на макетной плате.
Вычисление температуры.
Принцип простой. Для вычисления температуры датчиков LM35, TMP35, TMP37 необходимо:
- Считать код АЦП.
- Вычислить напряжение на выходе датчика как
- Uвых = N * Uион / 1024, где
- Uвых – напряжение на выходе термодатчика;
- N – код АЦП;
- Uион – напряжение источника опорного напряжения (для нашей схемы 5 В);
- 1024 – максимальное число градаций АЦП (10 разрядов).
- Разделить напряжение на выходе датчика на масштабный коэффициент.
- Для датчика TMP36 необходимо перед делением на масштабный коэффициент вычесть напряжение смещения (0,5 В).
Формулы вычисления температуры для разных датчиков при опорном напряжении 5 В выглядят так.
Тип датчика | Формула вычисления температуры T (°C), при опорном напряжении 5 В, из кода АЦП - N. |
LM35, TMP35 | T = ( N * 5 / 1024 ) / 0.01 |
TMP36 | T = ( N * 5 / 1024 – 0.5 ) / 0.01 |
TMP37 | T = ( N * 5 / 1024 ) / 0.02 |
Если используется цифровая фильтрация, то необходимо еще учесть коэффициент для нее. Также надо понимать, что формулы расписаны в виде удобном для понимания. В реальной программе лучше рассчитать постоянную часть формулы заранее и использовать как коэффициент. Об этом подробно написано в уроке 13. Там же информация о чтении и цифровой фильтрации аналогового сигнала.
Программа Ардуино термометра.
Программа должна выполнять следующие функции:
- считывать значения кодов АЦП;
- усреднять их (цифровая фильтрация) для повышения помехозащищенности;
- вычислять температуру из кода АЦП;
- выводить значение температуры на четырех разрядный LED индикатор в формате:
- знак;
- десятки;
- единицы;
- десятые доли °C.
- передавать раз в секунду значение температуры на компьютер в символьном формате.
Разработка программы строится по привычному принципу:
- реализовано прерывание от таймера с периодом 2 мс;
- в нем параллельным процессом происходит:
- регенерация LED индикатора;
- чтение кодов АЦП и усреднение их значений;
- программные таймеры.
- В основном асинхронном процессе происходит:
- синхронизация от программного таймера 1 сек;
- вычисление температуры;
- передача значения температуры на компьютер.
Если Вы читали предыдущие уроки, то все будет понятно.
Должны быть подключены библиотеки MsTimer2.h и Led4Digits.h. Загрузить библиотеки можно из урока 10 и урока 20. Там же есть подробное описание и примеры. По поводу измерения напряжения аналоговых входов можно посмотреть урок 13.
Я сразу приведу скетч программы.
// термометр, датчики LM35, TMP35, TMP36, TMP37
#include <MsTimer2.h>
#include <Led4Digits.h>
#define MEASURE_PERIOD 500 // время измерения, * 2 мс
#define ADC_RESOLUTION 4.8828125 // разрешающая способность АЦП, мВ (5000 мВ / 1024)
#define OFFSET 500. // смещение выходного напряжения, мВ (для TMP36)
#define SCALE_FACTOR 10. // масштабный коэффициент, мВ (для TMP36)
int timeCount; // счетчик времени измерения
long sumA0; // переменная суммирования кодов АЦП
long avarageTemp; // среднее значение температуры (сумма кодов АЦП, среднее значение * 500)
boolean flagTempReady; // признак готовности измерения температуры
float temperature; // рассчитанная температура, °C
// тип индикатора 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);
void setup() {
MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
MsTimer2::start(); // разрешаем прерывание по таймеру
Serial.begin(9600); // инициализируем порт, скорость 9600
}
void loop() {
if ( flagTempReady == true ) {
flagTempReady= false;
// данные готовы
// вычисление температуры
temperature = ( avarageTemp * ADC_RESOLUTION / 500. - OFFSET ) / SCALE_FACTOR;
// вывод температуры на индикатор
if (temperature >= 0) {
// температура положительная
disp.print((int)(temperature * 10.), 4, 1);
}
else {
// температура отрицательная
disp.digit[3]= 0x40; // отображается минус
disp.print((int)(temperature * -1 * 10.), 3, 1);
}
disp.digit[1] |= 0x80; // зажечь точку второго разряда
// передача температуры на компьютер
Serial.println(temperature);
}
}
//-------------------------------------- обработчик прерывания 2 мс
void timerInterrupt() {
disp.regen(); // регенерация LED индикатора
// измерение среднего значения темпрературы
timeCount++; // +1 счетчик выборок усреднения
sumA0+= analogRead(A0); // суммирование кодов канала A0 АЦП
// проверка числа выборок усреднения
if ( timeCount >= MEASURE_PERIOD ) {
timeCount= 0;
avarageTemp= sumA0; // перегрузка среднего значения
sumA0= 0;
flagTempReady= true; // признак готовности результата
}
}
Можете загрузить скетч по этой ссылке:
Загружаем, проверяем. Запускаем монитор последовательного порта и проверяем данные на компьютере.
Программа разработана для датчиков TMP36, но ее легко адаптировать под другие типы датчиков. Для этого достаточно изменить значения масштабного коэффициента и смещения, заданные в начале программы операторами #define.
Тип датчика | Коэффициент и смещение |
LM35, TMP35 | #define OFFSET 0. #define SCALE_FACTOR 10. |
TMP36 | #define OFFSET 500. #define SCALE_FACTOR 10. |
TMP37 | #define OFFSET 0. #define SCALE_FACTOR 20. |
Разрешающая способность и точность термометра.
Разрешающая способность АЦП в нашей схеме 5 В / 1024 = 4,88 мВ.
Разрешающая способность термометра:
- при масштабном коэффициенте 10 мВ/°C (датчики LM35, TMP35, TMP36) равна менее 0,5 °C;
- при масштабном коэффициенте 20 мВ/°C (датчик TMP37) равна менее 0,25 °C.
Вполне приличные параметры.
Что касается погрешности измерения – несколько хуже.
Погрешность измерения самих датчиков составляет:
- не более 0,5 °C для LM35;
- не более 1 °C для TMP35, TMP36, TMP37.
Погрешность измерения АЦП платы Ардуино.
В нашем устройстве мы использовали опорное напряжение 5 В,т.е. напряжение источника питания. В платах Arduino UNO R3 напряжение 5 В формируется на линейном стабилизаторе NCP1117ST50. Характеристики в формате PDF можно посмотреть по этой ссылке NCP117.pdf. Стабильность выходного напряжения этой микросхемы довольно высокая – 1%.
Т.е. общая погрешность измерения термометра составляет не более 2%.
Несколько повысить ее можно измерив напряжение 5 В на плате и задав в параметр разрешение АЦП не 5 В, а более точное значение. У меня на плате напряжение оказалось равным 5,01 В. В моей программе надо исправить:
#define ADC_RESOLUTION 4.892578 // разрешающая способность АЦП, мВ (5010 мВ / 1024)
Применение внешнего источника опорного напряжения для платы Ардуино.
Но есть радикальный способ улучшить, как точность измерения АЦП, так и разрешающую способность. Это применение внешнего источника опорного напряжения.
Самым распространенным источником стабильного напряжения являются микросхемы LM431, TL431 и т.п. Я собираюсь написать статью об этой микросхеме. Пока дам ссылку на информацию – LM431.pdf.
Приведу схему включения LM431 в качестве источника опорного напряжения 2,5 В для платы Ардуино.
В программе надо изменить строку определяющую разрешение АЦП:
#define ADC_RESOLUTION 2.44140625 // разрешающая способность АЦП, мВ (2500 мВ / 1024)
И в setup() подключить внешний источник опорного напряжения:
analogReference(EXTERNAL); // внешнее опорное напряжение
В результате разрешающая способность уменьшится в 2 раза, а стабильность – на порядок. Только все равно, для повышения точности необходимо измерить вольтметром реальное напряжение LM431 и подкорректировать его в программе.
Такая доработка термометра абсолютно необходима, если устройство питается от нестабилизированного источника питания напряжением близким к 5 В, например, от гальванических батарей или аккумулятора. В этом случае о стабильности источника питания говорить не приходится и без стабилизации источника опорного напряжения измерение будет весьма условное.
Программа верхнего уровня для термометра.
Смотреть на бегущие строки чисел в окне монитора Arduino IDE, быстро надоедает. Хочется просто видеть значение температуры. К тому же для практического использования термометра с компьютером должно быть установлено программное обеспечение Arduino IDE. Не на всех компьютерах оно есть. Также людей часто интересует изменение температуры, процесс нагрева или охлаждения в динамике. Хочется иметь возможность регистрировать изменение температуры и отображать его в графическом виде.
Для этого я написал простую программу верхнего уровня, которая:
- отображает текущее значение температуры;
- регистрирует изменение температуры с дискретностью 1 сек;
- выводит информацию об изменении температуры в графическом виде.
Эта программа может быть использована как с термометром из этой статьи, так и для термометров последующих уроков с другими типами датчиков.
Программа работает под управлением операционных систем Windows 95, 98, XP, 7. С остальными - не пробовал.
Установка приложения.
- Загрузите архивный файл Thermometer.zip:
- Распакуйте его в рабочую папку. Можно оставить папку из архива Thermometer.
Приложение состоит из двух файлов:
- Thermometer.exe – исполняемый файл;
- Conf.txt – файл конфигурации.
Устанавливать программу не надо, просто запускается файл Thermometer.exe.
Подключение термометра к компьютеру.
Обмен данными между компьютером и контроллером осуществляется через COM порт. Порт может быть реальным или виртуальным.
Удобнее всего использовать виртуальный порт, который создает драйвер платы Ардуино. Порт появляется при подключении платы к компьютеру. Запускать Arduino IDE не надо. Номер порта можно посмотреть: Панель управления -> Система -> Диспетчер устройств -> Порты (COM и LPT)
У меня COM5.
Можно подключить компьютер через какой-нибудь мост USB-UART. Я использую модули PL2303 USB UART Board. Как подключить написано в статье о программе Монитор холодильника на элементе Пельтье.
Если на компьютере есть штатный COM порт (интерфейс RS232), то никаких драйверов устанавливать не надо. Для подключения контролера в этом случае необходимо использовать преобразователь уровней RS232 – TTL, микросхемы ADM232, SP232, MAX232 и им подобные.
Вариантов подключения много. Главное, чтобы на компьютере был сформирован COM порт, виртуальный или реальный.
Первый запуск программы.
Перед запуском программы виртуальный COM порт должен быть уже создан на компьютере. А так как порт создается при подключении к разъему платы Ардуино, то это означает, что сначала необходимо подключить плату к компьютеру.
Дальше запускаете программу Thermometer.exe. В файле конфигурации программы записан какой-то COM порт. Программа попытается открыть его при запуске. Если не получится, то она выдаст сообщение с номером ошибочного порта.
Нажмите OK и откроется окно программы. Вместо температуры будут прочерки. Нет данных.
Выберете в меню (сверху) режим выбор порта. Откроется окно выбора.
Задайте номер порта для Вашей платы. У каждого порта написано его состояние. Естественно, необходимо выбирать из портов с надписью “свободен”.
Закройте окно. Выбранный COM порт сохранится в файле конфигурации, и всегда будет вызываться при запуске программы. Задавать порт при каждом запуске программы не надо.
Если плата включена, программа загружена, все работает правильно, то раз в секунду должен мигать кружок-светодиод перед значением температуры. Он мигает при поступлении новых данных.
Регистратор.
В программе существует регистратор, который позволяет наблюдать динамику изменения температуры. Регистратор включается автоматически при запуске программы. Он записывает значения температуры с дискретностью по времени 1 секунда. Максимальное время регистрации 30 000 сек или 8,3 часов.
Чтобы посмотреть результаты записи необходимо нажать закладку меню ”Регистратор”.
Это я паяльником нагрел датчик.
Увеличить фрагмент можно выбором прямоугольной области с нажатой правой кнопкой мыши. Область надо выбирать слева-направо, сверху-вниз .
Выбор мышью области слева-направо, снизу-вверх вернет отображение всей графической информации. Все просто.
Эта программа будет использоваться в следующих трех уроках с проектами измерения температуры датчиками других типов.
В следующем уроке будем измерять температуру с помощью кремниевых датчиков серии KTY81.
Здравствуйте Эдуард! Скажите, пожалуйста, в какой программе Вы писали верхний уровень?
Здравствуйте!
В интегрированной среде разработки Borland C++ Builder.
Спасибо за Вашу РАБОТУ!!!
Спасибо за отзыв.
Здравствуйте, Эдуард! Спасибо за урок, он поможет мне определится с глюком моей стиральной машины. Супруга утверждает — машинка на программе 30 градусов портит вещи. Вещи садятся, как-будто вместо 30 идет нагрев до 90 (максимум). И сейчас я проверяю этот вариант. Удобнее смотреть лог через монитор порта, а не через программу, т.к. она глючит — при вызове регистратора и его закрытии и снова открытии идет всплеск по шкале температура 250 градусов, и так при каждом вызове регистратора; на стареньком нетбуке, который я поставил на кухне, вообще идет загрузка процессора на 50% и при вызове регистратора видны и всплески до 250 и провалы до 0. Хотелось бы, конечно, пользоваться программой из-за наглядности, если возможно — допилите ее, она того стоит!
p.s. стиралка пока не глючила, нагревается до установленных температур, может все-таки ошибка «оператора»!
Здравствуйте! У меня программа работает идеально. Может у Вас совсем старый компьютер. Обратите внимание появляется ли у Вас ошибка обмена. Светодиод ОБМЕН красным или серым становится? Программа написана на Borland C++ Builder. У меня много подобных программ, работающих на разных компьютерах. Все работает замечательно. Даже не знаю, что «допиливать».
Исправьте плиз баг в программе чтобы выше 10 порта можно было опрашивать. А то я через USB концентратор подключаюсь а это как правило 20 порт.
Выше 9го порта сделать не просто. А Вы переправьте порт в настройках оборудования. В статье про установку драйвера PL2303 написано как это сделать.
Здравствуйте! А исходниками программы не поделитесь?
Вот решил насесть на это чудо инженерной мысли. Есть пара задумок. Так что штудирую ваши уроки. Большое вам спасибо за труд.
Может я не разглядел. Хотелось бы увидеть работу встроенного аналогова компоратора.
дай ссылку на библиотеку #define MEASURE_PERIOD 500
Это не библиотека. Это псевдооператор, который присваивает константе MEASURE_PERIOD значение 500.
Привет дорогой автор! Я собрал термометр как у вас и я хотел кое что спросить. как ускорить передачу данных датчика или сделать так чтобы индикатор обновлялся чаще чем одна секунда? У меня термометр меняет цифры через каждую секунду в зависимости от температуры, но хочу чтобы он обновлялся хотя бы раз в полсекунды. Что нужно сделать??
Здравствуйте!
Попробуйте изменить время измерения в строке
#define MEASURE_PERIOD 500 // время измерения, * 2 мс
на 250. Это будет пол секунды.
И еще надо изменить строку вычисления температуры
temperature = ( avarageTemp * ADC_RESOLUTION / 500. — OFFSET ) / SCALE_FACTOR;
на строку
temperature = ( avarageTemp * ADC_RESOLUTION / 250. — OFFSET ) / SCALE_FACTOR;
Спасибо!!
блин нет таких строк. у меня другой скетч и датчик 18В20
А почему комментарий к статье об аналоговых датчиках.
У DS18B20 время преобразования зависит от точности измерения. При максимальной точности оно составляет 750 мс. Увеличить частоту измерения можно только за счет уменьшения точности термометра.
Доброго вечера! Что-то не работает у меня программа термометра. Нет обмена данными. При включении один раз виртуальный светодиод мигнёт, ему в такт на ардуино Леонардо желтый RX. И всё, горят синие прочерки. Вин-10, СОМ-3 свободен, там висит плата. При этом монитор порта выдаёт данные в окне исправно.
Здравствуйте!
Посмотрите в комментариях к уроку 10. Там пишут:
Наверное стоит упомянуть в тексте урока что указанная библиотека MsTimer2 не будет работать Mega2650. Я уж думал что начал косячить от бессоницы, полез искать оригинальные библиотеки — а там оказывается есть варианты. Для Atmega2560 или Teensy надо использовать FlexiTimer2. Скачать можно здесь: http://playground.arduino.cc/Main/FlexiTimer2
Аааа, забыл, что программу взял из примера OneWire, датчик DS18B20.
Здравствуйте Эдуард,
Самым распространенным источником стабильного напряжения являются микросхемы LM431, TL431 и т.п. Я собираюсь написать статью об этой микросхеме. Пока дам ссылку на информацию – LM431.pdf.
Скажите пожалуйста когда примерно ждать статьи об источниках стабилизированного напряжения. Очень руки чешутся. В часности SIM800 требует 3.3В и пока могу только от батареек её юзать. Хочется в 5В линию от блока питания телефона(2А) через понижающее устройство включить. Но пока не работает и с китайскими переходниками DC-DC тоже не хочет…
Здравствуйте!
LM431, TL431 это параллельные стабилизаторы с низким выходным током. Скорее это источники опорного напряжения. Использовать их для подобных целей невозможно.
Существует огромное количество стабилизаторов с выходным напряжением 3,3 В. Например, LD1117V33. Достаточно включить их по стандартной схеме.
Здравствуйте Эдуард,
в Атмеге уже есть внутренний источник опорного напряжения. Достаточно произвести запись в регистр, поэтому внешние TL431 будут лишние. Можно измерить температуру кристалла (считав регистр температуры) и внести коррекцию. В pdf всё расписано.
А как сделать подобное но на 4 датчика? Что бы на пк выводились показания с нескольких датчиков.
Здравствуйте!
В программе для Ардуино надо 4 раза считывать АЦП разных датчиков и производить с данными те же действия. А программу верхнего уровня надо писать другую.
Не компилируется программа, в чём может быть дело?
пишет такое:
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::set(unsigned long, void (*)())’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::msecs’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::func’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::tcnt2′
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::start()’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::count’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::overflowing’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::stop()’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `MsTimer2::_overflow()’
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\MsTimer2-master\MsTimer2.cpp.o (symbol from plugin): In function `MsTimer2::set(unsigned long, void (*)())’:
(.text+0x0): multiple definition of `__vector_9′
sketch\MsTimer2.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:
(.text+0x0): multiple definition of `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’
sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:
(.text+0x0): multiple definition of `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’
sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:
(.text+0x0): multiple definition of `Led4Digits::regen()’
sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:
(.text+0x0): multiple definition of `Led4Digits::tetradToSegCod(unsigned char, unsigned char)’
sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here
libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:
(.text+0x0): multiple definition of `Led4Digits::print(unsigned int, unsigned char, unsigned char)’
sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1
Ошибка компиляции для платы Arduino/Genuino Uno.
Здравствуйте!
А вы библиотеки установили в Arduino IDE?
Здравствуйте!
Если Вы про MSTimer и Led4Digits, то да, установил как библиотеку ZIP.
Добрый день. Может это библиотека не совместима с моей версией IDE?
Здравствуйте!
Посмотрите информацию в интернете по этой ошибке. Возможно действительно версия IDE не подходит, особенно если у вас Windows XP. В комментариях к уроку 18 похожая проблема упоминается.
Спасибо за урок!
Что-то у меня индикатор показывает «кашу»… чётких цифр нет…
Схему проверил! В чём может быть причина?
Добрый вечер!
Наверняка аппаратная ошибка: замыкание между сигналами или обрыв. Прозвоните провода связи между собой. Можете проверить индикацию программами из урока 20.
Есть ли вариант программы верхнего уровня для работы с digispark (usb tiny85 + ds18b20) — usb без присутствия виртуальных портов в win10?
Здравствуйте!
У меня такой программы нет.
Здравствуйте, Эдуард.
Имеется информация, что запись во флеш память имеет ограниченное количество раз.
Как сделать, чтобы при включении платы происходила проверка наличии данных во флеш памяти, чтобы запись туда была только один раз, а не каждый раз при включении устройства?
Здравствуйте!
О какой информации идет речь? Приведите пример.
Вопрос про «блокирующий» конденсатор. Если я правильно понял его задача шунтировать переменную составляющую питания на землю? Уважаемый Эдуард, не могли бы вы уточнить каким образом вы рассчитали емкость этого конденсатора? Т.е. интуитивно я понимаю что это интегрирующее звено при этом резистор интегрирующего звена это внутреннее сопротивление источника питания. Но как подобрать емкость конденсатора?
Здравствуйте!
Я сейчас в Армении. Приеду — отвечу.
Т=R*C Внутреннее сопротивление мы можем рассчитать по падению напряжения, а вот из каких соображений выбирается постоянная времени T?
Здравствуйте!
Посмотрите об этом в уроке 37 http://mypractic.ru/urok-37-shirotno-impulsnaya-modulyaciya-v-arduino.html. Там задача противоположная, но принцип такой же. Если непонятно, пишите.
Эдуард, здравствуйте
Подскажите, а можно было условие if ( flagTempReady == true ) и соответственно вычисление температуры (но не вывод ее на дисплей) поместить в функцию timerInterrupt ? Почему само вычисление должно обязательно быть в loop ?
Здравствуйте!
Хороший стиль, да и здравый смысл, это в обработчике прерывания размещать только короткие, абсолютно необходимые программные блоки. Когда управление переходит на обработчик, то все остальные прерывания блокируются. У вас могут перестать считать системные часы, будут пропускаться данные, принятые UART и т.п.
Понял, спасибо
Эдуард, а не могли бы вы привести схему и главное формулу (на С) расчета температуры для датчика LM35 в режиме его работы в полном диапазоне температур (-55..150) градусов. Чё-то не хочет он у меня ниже нуля измерять ничего… Буду очень благодарен
Здравствуйте!
На сайте есть статья про этот датчик в рубрике Электронные компоненты. Там и схемы и характеристики.
Здравствуйте
Схемы и характеристики есть, не спорю. А вот как изменится программа? Там же какое-то смещение на величину сопротивления резистора R1 нужно вводить, если я чего-то вообще понял… Не могли бы вы в двух словах
Здравствуйте, Эдуард! Не могли бы вы пояснить из каких расчетов на вход стабилизатора LM431 устанавливается сопротивление 1 кОм.
Здравствуйте!
Простейший расчет параллельного стабилизатора. Через резистор должен течь ток обеспечивающий: минимальный ток стабилизатора LM431 (если не ошибаюсь 1 мА) и ток нагрузки (в нашем случае очень мала). Я выбрал ток 2,5 мА. Сопротивление резистора = 5 В — 2,5 В / 2,5 мА = 1 кОм.
А что, в данном случае является нагрузкой? С чем связано столь существенное ограничение по току?
Нагрузкой является вход ИОН АЦП. Но если бы к стабилизатору LM431 была подключена нагрузка, например 1 кОм (2,5 мА), то ограничительный резистор должен был обеспечить ток не менее 1 + 2,5 = 3,5 мА. И его минимальное сопротивление рассчитывалось бы так (5 В — 2,5 В) / 3,5 мА.
Последний вопрос, каково значение максимального допустимого тока через ИОН?
Здравствуйте!
Вы некорректно сформулировали вопрос.
Максимально допустимый ток это предельный параметр. Он имеет смысл, например для светодиода или транзисторного ключа. Если подать ток больше, то светодиод или транзистор сгорят.
Относительно ИОН правильно спросить, какой ток он потребляет или требует. Вход ИОН АЦП подключили к источнику напряжения и он потребляет от него ток.
Это мизерный ток, микроамперы. Поэтому можно считать, что к стабилизатору ничего не подключено.
Почитал как рассчитываются шунтирующие стабилизаторы на стабилитроне. Я так понимаю что ограничение тока на входе стабилизатора LM 431 рассчитывается подобным образом. Спасибо.
Спасибо.
Доброго времени, Эдуард.
Спасибо за уроки — интересно изучать.
Дошел до датчиков температур.
Плата — arduino uno. Оригинал и копия.
Датчик — tmp36.
Загружаю скетч — показывает -35 с копейками.
Грею паяльником — температура «падает».
В чем может быть проблема?
Здравствуйте!
Измерьте напряжение на аналоговом входе платы, и вы поймете, где ошибка в датчике или плате.
Примерно 12мВ
Перемерил. 45 мВ
Посчитайте сколько должно быть. Неправильное напряжение с датчика. Либо неправильно подключили, либо питание не подали…
Подключаю без резистора и без емкости.
analogRead(A0) всегда показывает напряжение, даже если ничего туда не подключено.
При этом, если я начинаю мерить тестером, то у меня выскакивает -44.5. Что в целом и должно быть, когда нет датчика.
Я чего то не понимаю?
Попробуйте другой аналоговый вход.
Написал скетч для измерения всех портов.
#include
#define MEASURE_PERIOD 500 // время измерения, *2мс
#define ADC_RESOLUTION 1//4.7265625
int timeCount; // счетчик времени измерения
long sumA0, sumA1, sumA2, sumA3, sumA4, sumA5;// переменная суммирования кодов АЦП
boolean flagVoltReady; // признак готовности измерения напряжения
float Volt1, Volt2, Volt3, Volt4, Volt5, Volt0; // создание переменных для напряжения
long avarageVolt1, avarageVolt2, avarageVolt3, avarageVolt4, avarageVolt5, avarageVolt0; //среднее значение напряжения
long sV0, sV1, sV2, sV3, sV4, sV5; // переменная суммирования кодов АЦП
void setup() {
MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру
MsTimer2::start(); // разрешение работать по таймеру
Serial.begin(9600);
Serial.println(«Test analog input»);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(A3, INPUT);
pinMode(A4, INPUT);
pinMode(A5, INPUT);
}
void loop() {
if ( flagVoltReady == true) {
flagVoltReady = false;
Volt1 = (avarageVolt1*ADC_RESOLUTION/500);
Volt2 = (avarageVolt2*ADC_RESOLUTION/500);
Volt3 = (avarageVolt3*ADC_RESOLUTION/500);
Volt4 = (avarageVolt4*ADC_RESOLUTION/500);
Volt5 = (avarageVolt5*ADC_RESOLUTION/500);
Volt0 = (avarageVolt0*ADC_RESOLUTION/500);
Serial.print(«Volt A0=»);
Serial.println(Volt0);
Serial.print(«Volt A1=»);
Serial.println(Volt1);
Serial.print(«Volt A2=»);
Serial.println(Volt2);
Serial.print(«Volt A3=»);
Serial.println(Volt3);
Serial.print(«Volt A4=»);
Serial.println(Volt4);
Serial.print(«Volt A5=»);
Serial.println(Volt5);
}
}
void timerInterrupt() {
timeCount++;
sV0+=analogRead(A0);
sV1+=analogRead(A1);
sV2+=analogRead(A2);
sV3+=analogRead(A3);
sV4+=analogRead(A4);
sV5+=analogRead(A5);
if (timeCount >= MEASURE_PERIOD) {
timeCount=0;
avarageVolt0=sV0;
sV0=0;
avarageVolt1=sV1;
sV1=0;
avarageVolt2=sV2;
sV2=0;
avarageVolt3=sV3;
sV3=0;
avarageVolt4=sV4;
sV4=0;
avarageVolt5=sV5;
sV5=0;
flagVoltReady = true;
}
}
Что скетчем, что тестером, показывает что везде 4.8 Вольта
Я понимаю, что не понимаю каких-то принципов, но тем не менее.
Когда я загрузил скетч выше, то у меня на всех портах высокое напряжение.
Когда я загрузил скетч из урока, то у меня высокое на 4,5 порту, на остальных портах низкое, но все есть напряжение.
А должно быть сколько? Если вы входы бросили в воздухе, то там напряжение может быть любым. Надо подключить резисторный делитель или подать от источника платы 3,3 В.
Здравствуйте. Можно ли использовать с Ардуино промышленные термосопротивления ТСП, ТСМ?
Здравствуйте!
Можно, как и с любым другим микроконтроллером. Но придется добавлять к Ардуино аппаратную часть, которая будет приводить выходной параметр датчика в диапазон напряжений АЦП. И программа должна вычислять температуру в соответствии с номинальной статической характеристикой (НСХ) датчика.