воскресенье, 11 августа 2013 г.

Еще одни часы на Ардуине. Часть 2. Выводим время на экран

В прошлой части Еще одни часы на Ардуине. Часть 1. Запускаем часы мы запустили модуль часов DS1307 и научились выводить время в Serial. Но пользоваться такими часами, конечно невозможно. Открывать Serial монитор для что-бы узнать "который час" :)
Так что, сегодня, мы

Подключаем экран:

Мне повезло. В случае Arduino Mega подключение экрана сводится к простому "нахлобучиванию" его на плату (главное, при первом втыкании  не торопится и не погнуть пины). У Меги SDA/SLC не закрываются шилдом. А 5V и GND дополнительно выведено возле D23 и D25. Так что LCD шилд ничуть не мешает подключению RTC шилда.

В случае же UNO - придется чуть-чуть взять в руки паяльник.
Вам потребуется:


Гнезда:

  •  PBS-5 - для выведения вверх SDA/SLC
  • PBS-6 - для выведения земли и питания
  • PBS-7 - что-бы вывести цифровые пины (пока мы их не используем, но что-бы два раза не вставать).

Впаиваем их сюда:


Там специально, производителем, именно для этих целей, оставлены дырочки-площадки.

В результате мы получим что-то такое:

[тут-будет-картинка]

Тут для примера впаяна PBD-5 и в которую воткнут проводок.

Заливаем в дуину такой скетч проверки экрана:
 
#include "LiquidCrystal.h" // библиотека экрана

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup(){
   lcd.begin(16, 2); // запускаем библиотеку
   lcd.setCursor(0,0); // курсов в левый верхний угол экрана
   lcd.print("Hello from LCD!!");
}
void loop(){}


Видим на экрнае такое:

[тут-будет-картинка]

И радуемся правильно подключенному экрану. Если необходимо, плохо видно буквы или, наоборот сквозь буквы проступают "квадратики" фоновые, берем тонкую плоскую отвертку (или кончиком ножа) и крутим регулятор контрастности (винтик в верхнем левом углу шилда).


Который час?

Теперь у нас все готово к выводу времени на экран.  Подключаем RTC модуль (если мы его отключали), берем финальный скетч из  первой части и добавляем в него инициализацию экрана. Строки 1,4,7 из "скетч проверки экрана" прошлого раздела (выделенные строки).

После чего у нас все готово, что-бы написать функцию вывода времени на экран.

Делаем все практически аналогично тому как в прошлой части выводили в Serial. Только функцию называем printTimeToLCD()

 
void printTimeToLCD(){
    byte static prevSecond=0; // тут будем хранить, сколько секунд было при выводе
    
    if(RTC.second!=prevSecond){ // что-то делаем только если секунды поменялись
       lcd.setCursor(0,0); // устанавливаем позицию курсора
       
      lcd.print(RTC.hour); // часы
    
      lcd.print(":"); // разделитель
      lcd.print(RTC.minute);
    
      lcd.print(":"); 
      lcd.print(RTC.second);
    
    prevSecond=RTC.second; // запомнили когда мы "отчитались"
  }
}

Добавляем вызов этой функции в loop(), заливаем в дуину и... мы сделали свои, пусть и неказистые, но первые электронные часы!!! :) На экране видно текущие время и "меняющие секунды".

А причесать?

Попробуем добавить чуть-чуть "эстетичности". Что мне не нравится в текущем варианте

  1. Хочется выводить время "по центру", а не в углу
  2. Убрать секунды. Мне они не нужны. Пусть лучше мигает двоеточие между часами и минутами (что-бы было видно что "секунды идут").
  3. Привести время к более привычному формату "16:03",  а не как сейчас "16:3"
  4. Если присмотрется в момент смены секунд видно легкое "помаргивание" надписи, она как-бы "пригасает".
Первый пункт - самый простой. Что-бы подвинуть время, нам достаточно сделать

lcd.setCursor(5,0).

Секунды - просто выкидываем :) А разделитель между часами и минутой показываем либо пробелом либо двоеточием. В зависимости от того четная или не четная у нас секунда

lcd.print( (RTC.second %2 )?" ":":");

Что осталось? Дописать "0" перед минутами если они меньше 10-ти

if(RTC.minute<10)lcd.print(0);

Аналогично для часов. Только добавлять впереди будем пробел, а не "0".  Ноль, вперди часов - выглядит некрасиво, а "что-то дописать" - нужно. Что-бы позиция времени не смещалась влево на малых значениях часа.

Наша функция вывода времени приняла вид:

 

void printTimeToLCD(){
    byte static prevSecond=0; // тут будем хранить, сколько секунд было при выводе
    
    if(RTC.second!=prevSecond){ // что-то делаем только если секунды поменялись
       lcd.setCursor(5,0); // устанавливаем позицию курсора
       
      if(RTC.hour<10)lcd.print(" ");
      lcd.print(RTC.hour); // часы
    
      lcd.print( (RTC.second % 2)?" ":":"); // разделитель моргает
      
      if(RTC.minute<10)lcd.print(0); // лидирующий ноль, если нужен
      lcd.print(RTC.minute);
    
    prevSecond=RTC.second; // запомнили когда мы "отчитались"
  }
}

В принципе, 4-тый пункт, "помаргивание" - уже не виден на глаз. Так что усложнять код, для борьбы с ним - мы пока не будем.

Сегодняшний наш финальный скетч таков:

 

// Author: alxarduino@gmail.com
// Sample Clock App for http://alxarduino.blogspot.com

// Библиотеки необходимые для работы модуля часов
#include "Wire.h"
#include "DS1307new.h"

// библиотека экрана
#include "LiquidCrystal.h" 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup(){
  Serial.begin(9600);
  if(RTC.isPresent()){ // обнаружен ли модуль?
    Serial.println("RTC Ready"); // все хорошо
  } else {
    Serial.println("Error!!!! RTC Module not found"); // сообщаем о проблеме
    while(1); // и останавливаем скетч
  }
  
  lcd.begin(16, 2); // запускаем библиотеку экрана
}

void loop(){
  RTC.getTime();// получить время от модуля
  printTimeToSerial(); // выводим полученное время в лог
  printTimeToLCD();; // выводи время на экран
  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; // запомнили когда мы "отчитались"
  }
}

// Выводит текущие время на LCD

void printTimeToLCD(){
    byte static prevSecond=0; // тут будем хранить, сколько секунд было при выводе
    
    if(RTC.second!=prevSecond){ // что-то делаем только если секунды поменялись
       lcd.setCursor(5,0); // устанавливаем позицию курсора
       
      if(RTC.hour<10)lcd.print(" ");
      lcd.print(RTC.hour); // часы
    
      lcd.print( (RTC.second % 2)?" ":":"); // разделитель моргает
      
      if(RTC.minute<10)lcd.print(0); // лидирующий ноль, если нужен
      lcd.print(RTC.minute);
    
    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:;
           // на неизвестную команду - ничего не делаем
    };
  }
}

На LCD Это выглядит примерно так:
В В реальности, конечно все симпатичней, использовать фотоаппарат я умею только "в автоматическом режиме".

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

Комментариев нет:

Отправить комментарий