Для следующего проекта, попались мне в руки два таких шилда:

Текстовый экран 16x2 плюс четыре кнопки с помощью делителя напряжения заведенные на пин A0
Руки зачесались...
Понятно, что это 1001 проект "часы на ардуине" и можно просто взять что-то готовое. Но у меня две цели: поиграться с модулями и показать как "вырастает проект". Правильный, с моей точки зрения, процесс. В противовес тому, как многие новички пытаются "накупить железо", составить 1000 "хотелок" и запустить все это сразу.
Итак, раз мы будем идти мелкими шагами - откладываем пока наш экран в сторону. Для начала освоимся с часами.
Железная составляющая
Подключаем их в соотвествии с wiki-производителя:
Линию DS - можно, пока, не подключать (пунктирная линия). С ней будем разбиратся позже.
Но у меня плата - Arduino Mega. У нее шина I2C (по ней передает данные модуль часов) расположены не на A4,A5, а на D20,D21
Поэтому я подключал SDA->D20 , SLC->D21
Если у вас другая плата - можете сверится с этой табличкой:
Плата | I2C / TWI pins |
Uno, Ethernet | A4 (SDA), A5 (SCL) |
Mega2560 | 20 (SDA), 21 (SCL) |
Leonardo | 2 (SDA), 3 (SCL) |
Due | 20 (SDA), 21 (SCL) |
Щупаем програмно
Что-бы комфортно работать с часами, на закапываясь в даташиты нам потребуется скачать и установить библиотеку для DS1307. Производитель модуля - предоставляет ее, но мне больше понравилась альтернативная. Вот эта: ds1307new - DS1307 RTC Library with NV-RAM support - Google Project Hosting
Скачиваем ее, распаковываем, забрасываем в папку libraries и пишем первый наш код, проверяющий видит ли ардуина наши часы:
Для перепроверки, отсединяем, скажем, линю SLC. Закрываем, открываем монитор (перезапускаем скетч) и видим что надпись у нас сменилась на "Error!!!! RTC Module not found".
Возвращаем проводок на место и опять видим "RTC Ready". Наш "детектор проблем" - работает.
C одной стороны - хорошо. Модуль посылает нам время и мы научились отправлять его в Serial. С другой... он старается делать это как можно чаще. Насколько хватает пропускной способности Serial. А нам - это не нужно :) Столько дублирования. Поэтому давайте отправлять время в Serial только если, скажем секунды, изменились с прошлого вызова функции.
Теперь наш лог, примет такой вид:
Каждая надпись - появляется раз в секунду. Можно дествительно смотреть как "часы идут".
Кстати, возможно вы заметили что время выглядит "не очень красиво", вмето привычных 18:00:26, у нас получилось 18:0:26. Но так как работа с Serial у нас "вспомогательная", мы не будет отвлекатся на решение этой проблемы. Но вернемся к ней и будем "наводить красоту", когда время будет показываться уже на LCD экране.
// Библиотеки необходимые для работы модуля часов #include <Wire.h> #include <DS1307new.h> void setup(){ Serial.begin(9600); if(RTC.isPresent()){ // обнаружен ли модуль? Serial.println("RTC Ready"); // все хорошо } else { Serial.println("Error!!!! RTC Module not found"); // сообщаем о проблеме while(1); // и останавливаем скетч } } void loop(){ }Заливаем, открываем Serial монитор и надпись:
Возвращаем проводок на место и опять видим "RTC Ready". Наш "детектор проблем" - работает.
А который час?
На данный момент, мы знаем что "модуль часов работает", но хочется увидить "хотя-бы время" (работу с датой я опущу, для сокращения размера статьи - там все аналогично).
Ну что-же давай попробуем вывести время. Что-бы сразу привыкать к "хорошим манерам", не будем сильно захламлять loop(), вынесем вывод времени в отдельную функцию и назовем ее printTimeToSerial() и будем ее вызвать из loop()
void loop(){ RTC.getTime();// получить время от модуля printTimeToSerial(); // выводим полученное время } void printTimeToSerial(){ Serial.print(RTC.hour); // часы Serial.print(":"); // разделитель Serial.print(RTC.minute); Serial.print(":"); Serial.println(RTC.second); }В логе (сериал мониторе видим) что-то типа:
17:53:35 17:53:35 17:53:35 17:53:35 17:53:35Много, много раз...
C одной стороны - хорошо. Модуль посылает нам время и мы научились отправлять его в Serial. С другой... он старается делать это как можно чаще. Насколько хватает пропускной способности Serial. А нам - это не нужно :) Столько дублирования. Поэтому давайте отправлять время в Serial только если, скажем секунды, изменились с прошлого вызова функции.
// Выводит текущие время в Serial void printTimeToSerial(){ byte static prevSecond=0; // тут будем хранить, сколько секунд было при прошлом отчете if(RTC.second!=prevSecond){ // что-то делаем только если секунды поменялись Serial.print(RTC.hour); // часы Serial.print(":"); // разделитель Serial.print(RTC.minute); Serial.print(":"); Serial.println(RTC.second); prevSecond=RTC.second; // запомнили когда мы "отчитались" } }
Теперь наш лог, примет такой вид:
RTC Ready 18:0:26 18:0:27 18:0:28 18:0:29
Каждая надпись - появляется раз в секунду. Можно дествительно смотреть как "часы идут".
Кстати, возможно вы заметили что время выглядит "не очень красиво", вмето привычных 18:00:26, у нас получилось 18:0:26. Но так как работа с Serial у нас "вспомогательная", мы не будет отвлекатся на решение этой проблемы. Но вернемся к ней и будем "наводить красоту", когда время будет показываться уже на LCD экране.
А точнее?
Получать время - это хорошо. Но его же нужно еще уметь устанавливать. В конечном итоге - будем делать это с помощью кнопок, но пока... сделаем временное решение. Самое простейшие: забъем нужное нам время прямо в скетч. И будем его посылать модулю, если из Serial нам пришел символ 's'
Функция установки времени:
Функция установки времени:
void setSomeTime(){ RTC.stopClock();// останавливаем часы RTC.fillByHMs(19,15,0); // "подкручиваем стрелки на 19:15:00 RTC.setTime();// отправляем "подкрученное время" самому модулю RTC.startClock(); // и опять запускаем часы }
Функция которая слушает команды из Serial
void doSerialCommands(){ if(Serial.available()){ // что-нибудь пришло? char ch=Serial.read(); // читаем что пришло switch(ch){ case 's': // команда устновки времени setSomeTime(); // устанавливаем break; // тут, в будущем, мы можем добавлять дополнительные команды default:; // на неизвестну команду - ничего не делаем }; } }
Все. Нам осталось только вставить вызов doSerialCommand() в loop() для регулярного опроса команда из Serial. После чего наш скетч принимает вид:
// Author: alxarduino@gmail.com // Sample Clock App for http://alxarduino.blogspot.com // Библиотеки необходимые для работы модуля часов #include "Wire.h" #include "DS1307new.h" void setup(){ Serial.begin(9600); if(RTC.isPresent()){ // обнаружен ли модуль? Serial.println("RTC Ready"); // все хорошо } else { Serial.println("Error!!!! RTC Module not found"); // сообщаем о проблеме while(1); // и останавливаем скетч } } void loop(){ RTC.getTime();// получить время от модуля printTimeToSerial(); // выводим полученное время doSerialCommands(); // слушаем и выполняем команды из Serial } // Выводит текущие время в Serial void printTimeToSerial(){ byte static prevSecond=0; // тут будем хранить, сколько секунд было при прошлом отчете if(RTC.second!=prevSecond){ // что-то делаем только если секунды поменялись Serial.print(RTC.hour); // часы Serial.print(":"); // разделитель Serial.print(RTC.minute); Serial.print(":"); Serial.println(RTC.second); prevSecond=RTC.second; // запомнили когда мы "отчитались" } } // устанавливает часы модуля на какое-то заранее определенное время void setSomeTime(){ RTC.stopClock();// останавливаем часы RTC.fillByHMS(19,15,0); // "подкручиваем стрелки на 19:15:00 RTC.setTime();// отправляем "подкрученное время" самому модулю RTC.startClock(); // и опять запускаем часы } // слушает из Serial команды и выполняет их. Каждая команда - один символ. // доступны команды: // s - установить время указанное в функции setSomeTime() void doSerialCommands(){ if(Serial.available()){ // что-нибудь пришло? char ch=Serial.read(); // читаем что пришло switch(ch){ case 's': // команда установки времени setSomeTime(); // устанавливаем break; // тут, в будущем, мы можем добавлять дополнительные команды default:; // на неизвестную команду - ничего не делаем }; } }
Заливаем.Открываем Serial Монитор. Набираем s (в нижнем регистре) и нажимает "отправить"
Итого:
- Мы подключили модуль часов DS1307.
- Убедились что Ардуина "его видит" (и сообщает нам если не видит).
- Научились получать от модуля время и отправлять его в Serial.
- Научились устанавливать время модуля по команде из Serial
В следующей части: мы подключим уже LCD и выведем время на него