AVR Урок 23. Собираем часы на DS1307 и LED индикаторе. Часть 4



 

Урок 23

Часть 4

 

Собираем часы на DS1307 и LED индикаторе

 

В прошлой части нашего занятия мы уже отобразили на нашем индикаторе текущее время, а также. используя выход генератора прямоугольных импульсов в микросхеме DS1301, научили мигать двоеточие на индикаторе, что сделало данные показания более живыми и натуральными.

Небольшое лирическое отступление. Почему я решил собрать именно часы на данном индикаторе? А потому, что здесь пересекаются очень многие технологии и периферии — и динамическая индикация, и ШИМ, и I2C, и АЦП также будет задействовано, вообщем, много чего есть возможность повторить, а также хорошие электронные часы — это всегда интересно!

Теперь к делу. Сегодня мы как раз-то и задействуем модуль АЦП. С помощью АЦП и фоторезистора мы будем измерять интенсивность освещения и на основе результата измерений наш код будет «решать», с какой интенсивностью будет в данный момент светиться наш индикатор.

Вот такой вот я использовал фоторезистор

 

image20

 

Вот такой вот у нас резистор. Как мы видим. он подключен через делитель напряжения, одной из частей которого является сам фоторезистор, а второй — обычный постоянный резистор. Среднее сопротивление фоторезистора 10 килоом, а освещение будет измеряться в диапазоне где-то от 1 килоома до 100 килоом, поэтому нам будет делитель напряжения просто необходим.

Посмотрим теперь нашу общую схему с подключенным делителем напряжения на фоторезисторе (нажмите на картинку для увеличения изображения)

 

image21_0500

 

Здесь выделен участок делителя. Как видно. делитель фоторезистором подключен к общему проводу, а постоянным резистором на 120 килоом подключен к шине питания, а центральный провод делителя подключен к контакту микроконтроллера, соответствующему нулевому каналу АЦП.

Поэтому чем меньше сопротивление фоторезистора, тем меньшее напряжение мы получим на делителе и чем больше — тем большее напряжение. И когда сопротивление фоторезистора достигнет 120 килоом, то напряжение будет приблизительно 2,5 вольта, что нам, в принципе и нужно. Это почти максимальное напряжение, так как опорное напряжение у нас 2,56 вольт.

Режим 10-битный АЦП я считаю использовать в часах нецелесообразным, потому что зачем нам такая точность для регулирования свечения, 8-битного вполне хватит.

Но для 8-битного режима для удобства считывания 8 бит удобнее всего воспользоваться вторым вариантом комбинирования бит в регистре ADC при бите ADLAR в регистре ADMUX, равном 1. В этом случае нам считывать придётся только старший регистр регистровой пары данных — ADCH. Вернее мы будем запоминать только этот регистр, считывать-то мы их обязаны все, так как будут использоваться прерывания, так как при таком режиме требуется меньше ресуросов, в том числе процессорного времени, а чтобы запустилось следующее преобразование, мы обязаны считать оба регистра, причем в особенной последовательности

Для использования аналого-цифрового преобразователя из проекта урока по АЦП MyADCISRLCD с использованием прерываний мы подключим файлы adc.c и adc.h.

 

 

Подключим также данную библиотеку в main.h

 

#include «PWM.h»

#include «adc.h»

 

Также здесь же добавим глобальную переменную для результата АЦП и вместе с ней ещё две для усреднения показаний, чтобы не было скачков результата преобразования

 

#include «led.h»

unsigned int adc_value,adc_counter,adc_tmp;

 

Также добавим ещё эти переменные в adc.c, первая там уже, соответственно, есть

 

extern unsigned int adc_value,adc_counter,adc_tmp;

 

В функции инициализации АЦП включим бит ADLAR

 

ADMUX |= (1<<ADLAR)|(1<<REFS1)|(1<<REFS0); //Внутренний Источник ОН 2,56в, вход ADC0

 

Включим большую частоту АЦП, для 8-битного режима медленная не нужна

 

|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0)//Делитель 32 = 256 кГц

 

 

Также напишем усреднение показателей в обработчике прерываний АЦП

 

ISR(ADC_vect)

{

  low_adc = ADCL;

  high_adc = ADCH;//Верхняя часть регистра ADC должна быть считана последней, иначе не продолжится преобразование

  if(adc_counter<20) {adc_tmp+=high_adc;adc_counter++;}

  else {adc_value=adc_tmp/20;adc_counter=0;adc_tmp=0;}

}

 

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

Инициализируем АЦП в функции main()

 

init_PWM_timer();

ADC_Init();

 

Ну, и теперь, прежде чем придумать расчет ШИМ из показаний АЦП, то мы пока будем отображать результат преобразований АЦП, а когда их посмтотрим, то что-нибудь решим.

Напишем следующий код в бесконечном цикле функции main(), перед этим полностью закомментировав код работы с показаниями часов

 

  //date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат

  ledprint(adc_value);

  _delay_ms(50);

}

 

Прошьём код и попробуем позатемнять фоторезистор. При очень светлом освещение у нас показатель около 7, а в темноте ложится на 255, то есть на максимум.

Ну и на этом основании мы теперь можем поуправлять значением ШИМ. Теперь мы на индикаторе будем показыать значение регистра ШИМ OCR2

 

ledprint(OCR2);

 

А также напишем саму зависимость

 

if(adc_value<120) OCR2=128-adc_value;

else OCR2=7;

ledprint(OCR2);

 

Вот такая вот зависимость. У нас ведь чем темнее. тем показатель ADCH больше, то есть всё наоборот, поэтому мы будем вычитать показания АЦП из 128, я подобрал такую оптимальную цифру для ШИМ, больше которой индикатор светится слишком ярко, нам это не надо. Вернее не слишком ярко, а больше которой у индикатора уже малоразличима разница интенсивности свечения.

Теперь соберем код, прошьём контроллер и посмотрим как будет это всё работать.

Показывать это в виде картинок нет смысла, да и интереснее будет смотреть когда уже будут ходить часы, а если кому интересно, то всё видно в видеоверсии урока, размещённой внизу страницы.

Вернём теперь весь закомментированный код и отображение времени на индикатор

 

date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат

if(adc_value<120) OCR2=128-adc_value;

else OCR2=7;

ledprint(hour*100+min);

 

Опять соберём код, прошьём контроллер, теперь можно и посмотреть

 

image22 image23 image24

 

Вот так вот у нас всё работает. Я думаю, неплохо!

Но работы у нас с часами ещё много. И продолжим мы её в следующей части занятия.

 

 

Предыдущая часть Программирование МК AVR Следующая часть

 

Программатор, модуль RTC DS1307 с микросхемой памяти и индикатор можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Модуль RTC DS1307 с микросхемой памяти

Семисегментный чертырехразрядный индикатор красный с общим анодом 10 шт

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

AVR Собираем часы на DS1307 и LED индикаторе

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*