После формирования цифры программа переходит к довольно запутанному, на первый взгляд, алгоритму работы АЦП. На самом деле он не так уж и сложен. Управляют этим процессом две переменных: счетчик циклов countCyk и счетчик преобразований count. Первый из них увеличивается на единицу каждый раз, когда происходит прерывание таймера. Когда его величина достигает 32 (т. е. когда устанавливается единица в бите 5, см. команду sbrs countCyk, 5), то значение счетчика сбрасывается для следующего цикла, и происходит запуск преобразования АЦП, причем для канала, соответствующего значению бита в регистре Flag, указывающего, что именно мы измеряем сейчас: температуру или давление. Таким образом измерения равномерно распределяются по времени.
Сами преобразования отсчитываются счетчиком count до 64 (т. е. цикл одного измерения занимает чуть более секунды: 32 х 64 = 2048 прерываний таймера, а в секунду их происходит примерно 1953). Когда это значение достигается, то мы переходим к обработке результатов по описанным ранее алгоритмам: сумма измерений делится на 64 (т. о. мы получаем среднее за секунду), затем вычитается или прибавляется значение «подставки», т. е. коэффициента Z, и полученная величина умножается на коэффициент К, точнее — на его целый эквивалент, полученный умножением на 1024. Произведение делится на это число и преобразуется к распакованному двоично-десятичному виду, отдельные цифры которого размещаются в памяти для последующей индикации. Как только очередной такой цикл заканчивается, меняется значение бита в регистре Flag, и таким образом давление и температура измеряются попеременно. В целом выходит, что значение каждой из величин меняется примерно раз в две секунды, и представляет собой среднее за половину этого периода.
Собственно результат измерения читается в прерывании АЦП (процедура по метке readADc), которое происходит автоматически по окончании каждого преобразования. В нем увеличивается значение счетчика count, извлекается из памяти предыдущее значение суммы показаний (в зависимости от регистра Flag — температуры или давления), считываются значения АЦП, суммируются и записываются обратно в память. Практически весь алгоритм мы описали — осталось только понять, как получить значения коэффициентов преобразования К и Z и затем выполнить точную калибровку.
Калибровка
Для того чтобы прибор заработал, в него необходимо ввести предварительные значения коэффициентов преобразования К и Z, причем желательно такие, чтобы они были достаточно близки к настоящим, и измеритель не показал бы нам «погоду на Марсе». В программе «зашиты» некие значения коэффициентов (см. процедуру Reset, секцию «Запись коэффициентов» в самом конце программы), которые подойдут вам, если вы не меняли характеристики схемы по рис. 15.2 и использовали тот же самый датчик давления. Как они получены?
Схема датчика температуры должна выдавать, как мы говорили, значение от 0 до 5 В в диапазоне температур примерно от -47 до 55 градусов. Следовательно, на 102 градуса у нас приходится 1024 градации АЦП, и крутизна характеристики составит 1020/1024 = 0,996 десятых градуса на единицу кода АЦП. Для вычислений в МК эту величину мы хотим умножить на 1024, так что можно было бы и не делить, ориентировочное значение коэффициента К так и будет 1020.
Величину Z, соответствующую 0 °C, вычислить также несложно. Мы полагаем, что нулю показаний соответствует температура -47°, тогда значение кода в нуле должно составить величину 470, поделенную на крутизну: 470/0,996 = 471.
Теперь разберемся с давлением. «Если повар нам не врет», то диапазон датчика, соответствующий изменению напряжения на его выходе от 0 до 4,6 В, составляет примерно 850 мм рт. ст. Это будет соответствовать изменению кодов примерно от 0 до 940 единиц, т. е. крутизна К равна 850/950 = 0,895 мм рт. ст. на единицу кода. В приведенном для наших расчетов виде это составит 0,895 х 1024 = 916. «Подставка» Z есть значение кода на нижней границе диапазона датчика, которая равна 11 мм рт. ст., соответственно, Z = 11/0,895 = 12 единиц. Полученные величины и «зашиваем» в программу.
После этого нужно сразу провести калибровку по температуре. Для этого следует запустить прибор и поместить датчик температуры в воду, записав для двух значений температур (как можно ближе к 0°, но не ниже его, и около 30–35 °C) показания датчика (/) и реальные значения температуры по образцовому термометру (О* Они, естественно, будут различаться. Для расчета новых (правильных) значений коэффициентов К' и Z' достаточно решить относительно них систему уравнений:
t'1 = К'(х1 — Z');
t1 = К(х1 — Z);
t'2 = К'(х2 — Z');
t2 = К(х2 — Z).
Здесь величины со штрихами относятся к правильным (новым) значениям, а без штрихов — к старым, причем значение коэффициента К нужно подставлять в изначальной форме (а не умноженным на 1024). Система четырех уравнений содержит четыре неизвестных, два из которых (величины кодов х1 и х2) вспомогательные. Если вы забыли, как решаются такие простые системы, купите любой справочник по математике для средней школы (или книжку по использованию Excel в алгебраических расчетах). Вычисленные значения (не забудьте К умножить на 1024) «забейте» в программу и перепрограммируйте контроллер.
Аналогично калибруется канал давления, только коэффициент Z в уравнениях не вычитается, а прибавляется к х. Но самое сложное здесь — получить действительные значения давления. Далеко не все научные лаборатории располагают образцовыми манометрами для измерения столь малых давлений с необходимой точностью. Поэтому самый простой, хотя и долгий метод — сравнивать показания датчика с данными по давлению, которые публикуются в Интернете. Есть сайты, которые публикуют погоду каждые 3 часа (это т. н. метеорологический интервал). Лучшие и наиболее популярные из них — weather.yandex.ru и gismeteo.ru. Причем лучше не ограничиваться данными одной какой-то службы, а обращаться к нескольким, отбрасывая явные ошибки и усредняя правдоподобные данные, с учетом того, что они публикуются с некоторым запаздыванием (отметьте показания прибора, например, в 9:00, а в Интернет лезьте примерно в 11:00). Данные радио и телевидения использовать нежелательно, т. к. текущие значения могут сообщаться с опозданием на полсуток, либо вообще отсутствовать, а по завтрашнему прогнозу, естественно, вы ничего не откалибруете.
Для получения двух точек дождитесь, пока давление на улице не станет достаточно низким, а затем, наоборот, высоким — экстремальные значения давления в регионе Москвы составляют примерно 720 и 770 мм рт. ст.[14] Чем дальше будут отстоять друг от друга значения, тем точнее калибровка. Для повышения точности можно усреднить коэффициенты, рассчитанные по нескольким парам значений давления, но это стоит делать только, если у вас хватит терпения вести наблюдения в течение нескольких месяцев, когда будет пройдено несколько минимумов и максимумов. Средние значения давления при калибровке лучше не учитывать, т. к. ошибка ее из-за узкого интервала и так достаточно велика.
Полученные коэффициенты пересчета кода в физические величины мы «зашивали» прямо в программу МК. Излишне говорить, что это приемлемый метод лишь тогда, когда изготавливается один-единственный экземпляр прибора, который стоит лично у вас на столе. Изготовить пару-другую экземпляров и подарить их кому-то уже не получится, поскольку при необходимости поправить коэффициенты пересчета владельцу придется обращаться к вам. Да и вообще, метод калибровки, при котором прибор требуется разобрать и переписать заново все его содержимое, выглядит как-то… некрасиво.
Логично придумать способ хранения констант, которые могут быть изменены в процессе эксплуатации, отдельно от программы. Для этой цели и служит энергонезависимая память данных, называемая EEPROM. Большинство МК семейства AVR имеют не менее 512 байт такой памяти, а младшие модели семейства Tuny — 64—128 байт. Для подавляющего большинства применений этого более чем достаточно. Не задерживаясь сейчас на вопросе, как осуществлять перезапись констант в процессе эксплуатации (этому вопросу будет посвящена глава 16), рассмотрим детали обращения с EEPROM.
Сохранность данных в EEPROM
Как мы уже говорили (см. главу 11), EEPROM и flash-память программ принципиально не отличаются, и предназначены для хранения данных в отсутствие питания. Однако между ними есть кардинальное различие: EEPROM может быть перезаписана в любой момент программой самого МК. В этом слабость всей системы: при снижении питания ниже определенных величин МК начинает совершать непредсказуемые операции, и EEPROM с большой вероятностью может быть повреждена. Для защиты от этой «напасти» (и вообще от выполнения каких-то операций, которые иногда могут навредить внешним устройствам) в AVR предусмотрена система BOD (см. главу 13), которая при снижении напряжения питания ниже определенного порога (4 или 2,7 В) «загоняет» МК в состояние сброса. Это помогает, но, как показывает опыт, для абсолютной защищенности данных в EEPROM, к сожалению, встроенной системы BOD недостаточно. Возможно, она недостаточно быстродействующая или в ней не слишком надежно фиксируется момент срабатывания, но факты свидетельствуют, что даже при включенной BOD данные все же могут быть повреждены.
Не исключено, что система BOD все время совершенствуется, но автор предпочитает не экспериментировать и использует самый надежный и проверенный способ с внешним монитором пита