Часовой показометр

Итак, хватит разговоров, надо сделать что-либо полезное и приятное. А начнем мы с часов, совмещенных с показометром чего-нибудь. Чего именно и конкретно – пока я не определился.

В общем, сгребаем всё, что есть в предидущем посту и складываем на стол. Первым делом подключаем кабелем ардуинку к компьютеру и скачиваем весь необходимый для нее софт. Я останавливаться на этом не буду, ибо в интернете этих описаний – тьма и на любом языке. Точно так же я не буду останавливаться на том, что делает каждая конкретная функция.

Проверка для перехода к следующему шагу – стандартная “мигалка” компилируется, заливается в ардуинку и мигает светодиодиком, как положено.

Теперь подсоединяем индикатор к ардуинке. Ножку индикатора VCC цепляем к выводу +3.3V ардуинки. Не стоит занимать 0 и 1 ножку (там работа с компьютером) и 13й – там светодиодик.

IMG_0061

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

int pinA=2;
int pinB=3;
int pinC=4;
int pinD=5;
int pinE=6;
int pinF=7;
int pinG=8;
int pinDP=9;
int pinPP=10;
int pinDIG1=11;
int pinDIG2=12;
int pinDIG3=A0;
int pinDIG4=A1;

Затем я делаю определение, в каком режиме должны работать порты ардуинки (у нас все работают на вывод)

pinMode(pinA, OUTPUT); //A
pinMode(pinB, OUTPUT); //B
pinMode(pinC, OUTPUT); //C
pinMode(pinD, OUTPUT); //D
pinMode(pinE, OUTPUT); //E
pinMode(pinF, OUTPUT); //F
pinMode(pinG, OUTPUT); // G
pinMode(pinDP, OUTPUT); // DP
pinMode(pinPP, OUTPUT); // PP

pinMode(pinDIG1, OUTPUT); // DIG 1
pinMode(pinDIG2, OUTPUT);
pinMode(pinDIG3, OUTPUT);
pinMode(pinDIG4, OUTPUT); // DIG 4

И переключаю эти порты в соответствующее состояние. По нашей схеме, что бы светодиод загорелся, надо порт включить в режим LOW.
Что бы погас – в HIGH.

Ну и что бы добавить “оживляжа”, зажгем первую и третью цифру

digitalWrite(pinDIG1,LOW);
digitalWrite(pinDIG2,HIGH);
digitalWrite(pinDIG3,LOW);
digitalWrite(pinDIG4,HIGH);

… восьмерками
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
digitalWrite(pinDP,HIGH);
digitalWrite(pinPP,HIGH);

и начнем включать/выключать точки с интервалом в одну секунду
digitalWrite(pinPP,LOW);
delay(1000);
digitalWrite(pinPP,HIGH);
delay(1000);

В итоге в ардуинке должен залиться вот такой вот скетч
int pinA=2;
int pinB=3;
int pinC=4;
int pinD=5;
int pinE=6;
int pinF=7;
int pinG=8;
int pinDP=9;
int pinPP=10;

int pinDIG1=11;
int pinDIG2=12;
int pinDIG3=A0;
int pinDIG4=A1;

void setup() {
Serial.begin(9600);
pinMode(pinA, OUTPUT); //A
pinMode(pinB, OUTPUT); //B
pinMode(pinC, OUTPUT); //C
pinMode(pinD, OUTPUT); //D
pinMode(pinE, OUTPUT); //E
pinMode(pinF, OUTPUT); //F
pinMode(pinG, OUTPUT); // G
pinMode(pinDP, OUTPUT); // DP
pinMode(pinPP, OUTPUT); // PP

pinMode(pinDIG1, OUTPUT); // DIG 1
pinMode(pinDIG2, OUTPUT);
pinMode(pinDIG3, OUTPUT);
pinMode(pinDIG4, OUTPUT); // DIG 4

digitalWrite(pinDIG1,LOW);
digitalWrite(pinDIG2,HIGH);
digitalWrite(pinDIG3,LOW);
digitalWrite(pinDIG4,HIGH);

digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
digitalWrite(pinDP,HIGH);
digitalWrite(pinPP,HIGH);
}

// the loop routine runs over and over again forever:
void loop() {

digitalWrite(pinPP,LOW);
delay(1000);
digitalWrite(pinPP,HIGH);
delay(1000);
}


И этот скетч должен произвести такой результат:

Если получилось, можно радостно ухмыльнуться и перейти к следующему шагу – сделаем другие циферки.

Для начала добавим функцию, которая будет рисовать нам циферки
void showDigit(int digit)
{
switch(digit) {
case 0:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,HIGH);
break;
case 1:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 2:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 3:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 4:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 5:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 6:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 7:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 8:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 9:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
}
}

Суть её простая: просто зажигаем или гасим нужные сегменты в зависимости от того, какую циферку нам надо нарисовать.

И просто перебираем циферки по порядку:

void loop() {
showDigit(count);
count++;
if(count>9)
{
count=0;
}
digitalWrite(pinPP,LOW);
delay(500);
digitalWrite(pinPP,HIGH);
delay(500);
}

Все просто: зажигаем циферку, затем увеличиваем ее и если она превышает 9, сбрасываем на 0. И затем с меньшим интервалом мигаем. В результате должен получиться вот такой вот скетч
int pinA=2;
int pinB=3;
int pinC=4;
int pinD=5;
int pinE=6;
int pinF=7;
int pinG=8;
int pinDP=9;
int pinPP=10;

int pinDIG1=11;
int pinDIG2=12;
int pinDIG3=A0;
int pinDIG4=A1;

void showDigit(int digit)
{
switch(digit) {
case 0:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,HIGH);
break;
case 1:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 2:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 3:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 4:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 5:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 6:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 7:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 8:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 9:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
}
}

void setup() {
Serial.begin(9600);
pinMode(pinA, OUTPUT); //A
pinMode(pinB, OUTPUT); //B
pinMode(pinC, OUTPUT); //C
pinMode(pinD, OUTPUT); //D
pinMode(pinE, OUTPUT); //E
pinMode(pinF, OUTPUT); //F
pinMode(pinG, OUTPUT); // G
pinMode(pinDP, OUTPUT); // DP
pinMode(pinPP, OUTPUT); // PP

pinMode(pinDIG1, OUTPUT); // DIG 1
pinMode(pinDIG2, OUTPUT);
pinMode(pinDIG3, OUTPUT);
pinMode(pinDIG4, OUTPUT); // DIG 4

digitalWrite(pinDIG1,LOW);
digitalWrite(pinDIG2,HIGH);
digitalWrite(pinDIG3,LOW);
digitalWrite(pinDIG4,HIGH);

digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
digitalWrite(pinDP,HIGH);
digitalWrite(pinPP,HIGH);
}

int count=0;

// the loop routine runs over and over again forever:
void loop() {
showDigit(count);
count++;
if(count>9)
{
count=0;
}
digitalWrite(pinPP,LOW);
delay(500);
digitalWrite(pinPP,HIGH);
delay(500);
}

С вот таким вот результатом

Ура? Ура конечно. Следующим шагом надо вывести какое-нибудь число. Я взял 1234.

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

Добавляем функцию, которая будет разбивать число на циферки и показывать их по порядку
void showNumber(int num)
{
int divide=0;
for(int c=1;c<5;c++) { switch(c) { case 1: digitalWrite(pinDIG1,LOW); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=1000; break; case 2: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,LOW); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=100; break; case 3: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,LOW); digitalWrite(pinDIG4,HIGH); divide=10; break; case 4: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,LOW); divide=1; break; } // switch String s(int(num/divide)); char c=s.charAt(s.length()-1); showDigit(c-'0'); delay(100); } }

Самым сложным тут является кусок кода
String s(int(num/divide));
char c=s.charAt(s.length()-1);
showDigit(c-'0');

Вся его функция - "выкусить" нужную цифру из числа и затем показать.

скажем, нам нужна цифра 2 из 1234.

int(num/divide) - это "взять целую часть из деления num на divide". В нашем случае 1234/100=12

String(s - это "превратить данное число в строку"

s.length() - узнать длину строки в символах

s.charAt - взять Нный символ из строки

В итоге s.charAt(s.length()-1) значит "взять последний символ из строки". -1 нужен из-за того, что ардуинка считает, что 1й символ имеет "адрес" 0

c-'0' - превращаем символ назад в число. Отнеситесь к этому как к магии, иначе мне надо будет рассказывать вам про то, что такое ASCII

И заставляем ардуинку показать нам циферку

void loop() {
showNumber(1234);
}

Как обычно, скетч целиком

int pinA=2;
int pinB=3;
int pinC=4;
int pinD=5;
int pinE=6;
int pinF=7;
int pinG=8;
int pinDP=9;
int pinPP=10;

int pinDIG1=11;
int pinDIG2=12;
int pinDIG3=A0;
int pinDIG4=A1;

void showDigit(int digit)
{
switch(digit) {
case 0:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,HIGH);
break;
case 1:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 2:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 3:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 4:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 5:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 6:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 7:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 8:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 9:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
}
}

void setup() {
Serial.begin(9600);
pinMode(pinA, OUTPUT); //A
pinMode(pinB, OUTPUT); //B
pinMode(pinC, OUTPUT); //C
pinMode(pinD, OUTPUT); //D
pinMode(pinE, OUTPUT); //E
pinMode(pinF, OUTPUT); //F
pinMode(pinG, OUTPUT); // G
pinMode(pinDP, OUTPUT); // DP
pinMode(pinPP, OUTPUT); // PP

pinMode(pinDIG1, OUTPUT); // DIG 1
pinMode(pinDIG2, OUTPUT);
pinMode(pinDIG3, OUTPUT);
pinMode(pinDIG4, OUTPUT); // DIG 4

digitalWrite(pinDIG1,HIGH);
digitalWrite(pinDIG2,HIGH);
digitalWrite(pinDIG3,HIGH);
digitalWrite(pinDIG4,HIGH);

digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
digitalWrite(pinDP,HIGH);
digitalWrite(pinPP,HIGH);
}

void showNumber(int num)
{
int divide=0;
for(int c=1;c<5;c++) { switch(c) { case 1: digitalWrite(pinDIG1,LOW); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=1000; break; case 2: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,LOW); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=100; break; case 3: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,LOW); digitalWrite(pinDIG4,HIGH); divide=10; break; case 4: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,LOW); divide=1; break; } // switch String s(int(num/divide)); char c=s.charAt(s.length()-1); showDigit(c-'0'); delay(100); } } // the loop routine runs over and over again forever: void loop() { showNumber(1234); }

Превращается в ...

А теперь уменьшаем задержку, меняя delay(100) на delay(1) и получаем ...

... циферку! Такую, какую я попросил! Очередное ура!

Но если вы приглядитесь к результату ...

IMG_0070

Какая-то фигня, не правда ли? Почему-то вокруг циферок светятся лишние сегменты. Хоть и тускло, но некрасиво же. Почему так?

Дело в скорости работы ардуинки. Скажем, откуда появились лишние сегменты у цифры 1?

Если посмотрите на логику работы скетча, у нас получится следующее

(много пропущено)
1. Включить 4й индикатор
2. Показать цифру 4
3. Включить 1й индикатор
4. Показать цифру 1
(опять пропускаем)

И вот обратите внимание, во время между шагами 3 и 4 на индикаторе горит 4! Да, это время невелико, но хватает, что бы мы заметили это.

Вывод? Надо между шагами 2 и 3 выключить показ циферок.

Добавляем вывод спец-цифры "10"

case 10:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;

Она просто будет гасить все сегменты. И вставим ее вызов самое начало ShowNumber

for(int c=1;c<5;c++) { showDigit(10);

IMG_0073

Как видим, все получилось. Все красиво и никаких засветов нет. Можно побаловаться с разными циферками, поделать секундомеры.

Но нам нужны часы. Выключаем ардуинку, и вставляем на плату блок часиков. Предварительно вставьте туда батарейку, иначе чуда не будет. Соединения простые:

GND к GND,
VCC к +5V (НЕ к 3.3!)
SDA к A4
SCL к A5

И снова включаем, что бы удостовериться, что ничего не поломали и не оторвали.

IMG_0077

Теперь для проверки уже блока часов скачиваем с https://github.com/adafruit/RTClib библиотечку RTC, добавляем ее в проект и заливаем вот такой вот скетч:

#include
#include "RTClib.h"

RTC_DS1307 RTC;

void setup () {
Serial.begin(57600);
Wire.begin();
RTC.begin();

if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
//RTC.adjust(DateTime(__DATE__, __TIME__));
}

}

void loop () {
DateTime now = RTC.now();

Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();

Serial.print(" since 1970 = ");
Serial.print(now.unixtime());
Serial.print("s = ");
Serial.print(now.unixtime() / 86400L);
Serial.println("d");

// calculate a date which is 7 days and 30 seconds into the future
DateTime future (now.unixtime() + 7 * 86400L + 30);

Serial.print(" now + 7d + 30s: ");
Serial.print(future.year(), DEC);
Serial.print('/');
Serial.print(future.month(), DEC);
Serial.print('/');
Serial.print(future.day(), DEC);
Serial.print(' ');
Serial.print(future.hour(), DEC);
Serial.print(':');
Serial.print(future.minute(), DEC);
Serial.print(':');
Serial.print(future.second(), DEC);
Serial.println();

Serial.println();
delay(3000);
}

Если все в порядке, то в выводе Serial Monitor вы должны увидеть ужас, похожий на

2000/61/120 0:81:4
since 1970 = 1023758464s = 11849d
now + 7d + 30s: 2002/6/18 1:21:34

Теперь меняем кусочек скетча в начале на

if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled

}
RTC.adjust(DateTime(__DATE__, __TIME__));
}

(если кто не понял, строчку одну перенес) И снова заливаем.

Теперь в выводе должно появиться реальное время. Ибо компьютер подставил их вместо __DATE__ и __TIME__, а функция
RTC.ajust "поставила часы" как надо.

Теперь выдыхаем и модифицируем скетч вот так:

#include

#include

int pinA=2;
int pinB=3;
int pinC=4;
int pinD=5;
int pinE=6;
int pinF=7;
int pinG=8;
int pinDP=9;
int pinPP=10;

int pinDIG1=11;
int pinDIG2=12;
int pinDIG3=A0;
int pinDIG4=A1;

RTC_DS1307 RTC;

void showDigit(int digit)
{
switch(digit) {
case 0:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,HIGH);
break;
case 1:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 2:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 3:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 4:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 5:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 6:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 7:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 8:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 9:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 10:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
}
}

void showNumber(int num)
{
int divide=0;
float z;
for(int c=1;c<5;c++) { showDigit(10); switch(c) { case 1: digitalWrite(pinDIG1,LOW); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=1000; break; case 2: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,LOW); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=100; break; case 3: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,LOW); digitalWrite(pinDIG4,HIGH); divide=10; break; case 4: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,LOW); divide=1; break; } // switch String s(int(num/divide)); char b=s.charAt(s.length()-1); showDigit(b-'0'); delay(5); } } void setup() { Serial.begin(115200); Wire.begin(); RTC.begin(); pinMode(pinA, OUTPUT); //A pinMode(pinB, OUTPUT); //B pinMode(pinC, OUTPUT); //C pinMode(pinD, OUTPUT); //D pinMode(pinE, OUTPUT); //E pinMode(pinF, OUTPUT); //F pinMode(pinG, OUTPUT); // G pinMode(pinDP, OUTPUT); // DP pinMode(pinPP, OUTPUT); // PP pinMode(pinDIG1, OUTPUT); // DIG 1 pinMode(pinDIG2, OUTPUT); pinMode(pinDIG3, OUTPUT); pinMode(pinDIG4, OUTPUT); // DIG 4 digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); digitalWrite(pinA,LOW); digitalWrite(pinB,LOW); digitalWrite(pinC,LOW); digitalWrite(pinD,LOW); digitalWrite(pinE,LOW); digitalWrite(pinF,LOW); digitalWrite(pinG,LOW); digitalWrite(pinDP,HIGH); digitalWrite(pinPP,HIGH); } long previousMillis = 0; long interval = 1000; DateTime now; // the loop routine runs over and over again forever: void loop() { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
now = RTC.now();
if((now.second() % 2) == 0)
{
digitalWrite(pinPP,LOW);
}
else
{
digitalWrite(pinPP,HIGH);
}
}

showNumber(now.hour()*100+now.minute());

}

Кака работает код, в принципе понятно из него самого. Но все-таки прокомментирую.

Система просто смотрит, не прошел ли уже заданный интервал и если прошел, то считывает время из часов точного времени и мигает двоеточием.

Почему я просто не поставил посередине что-нибудь типа delay(995)? Ответ опять же в том, что разные ардуинки имеют разную скорость работы. И код, который выполняется между delay,
выполняется за разный промежуток времени. А значит, в реальности между delay проходит разное количество времени. И чего, мне после каждого изменения кода или логики подбирать
задержку? Бессмысленное занятие при наличии под боком нормальных часов.

Код "now.second() % 2" означает "дробная часть при делении на два". Попросту говоря, я зажигаю светодиод каждую четную секунду (14/2=7.0), а гашу - нечетную (15/2=7.5).

Ну и now.hour()*100+now.minute() из часов и минут делает большое число.

Запускаем!

Ура! Работает! Теперь у нас есть часики. Свои, персональные! Можем танцевать и бросать в воздух чепчики!

Но мне же надо еще и показометр ...

Добавляем в loop

while (Serial.available() > 0) {
s=(char)Serial.read();
if (s == 'n') {
char ca[5];
txtMsg.toCharArray(ca, 5);
number_to_show = atoi(ca);
time_to_show=2;
digitalWrite(pinPP,HIGH); // we do to need dots
txtMsg = "";
} else {
txtMsg +=s;
}
}

if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if(time_to_show > 0)
{
time_to_show--;
}
else
{
now = RTC.now();

Суть кода простая: если компьютер послал что-либо в ардуинку, то тупо собираем все, пока не попадется спецсимвол n - это Enter или Return.
Затем превращаем полученное в число и на две секунды показываем вместо часов. Думаю, что если вы одолели предидущее, то этот будет просто понять.

Вот он целиком (для тех, кто не просто копипастит, внутри сюрприз):

#include

#include

int pinA=2;
int pinB=3;
int pinC=4;
int pinD=5;
int pinE=6;
int pinF=7;
int pinG=8;
int pinDP=9;
int pinPP=10;

int pinDIG1=11;
int pinDIG2=12;
int pinDIG3=A0;
int pinDIG4=A1;

RTC_DS1307 RTC;

void showDigit(int digit)
{
switch(digit) {
case 0:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,HIGH);
break;
case 1:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 2:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 3:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,LOW);
break;
case 4:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 5:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 6:
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 7:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
case 8:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,LOW);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 9:
digitalWrite(pinA,LOW);
digitalWrite(pinB,LOW);
digitalWrite(pinC,LOW);
digitalWrite(pinD,LOW);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,LOW);
digitalWrite(pinG,LOW);
break;
case 10:
digitalWrite(pinA,HIGH);
digitalWrite(pinB,HIGH);
digitalWrite(pinC,HIGH);
digitalWrite(pinD,HIGH);
digitalWrite(pinE,HIGH);
digitalWrite(pinF,HIGH);
digitalWrite(pinG,HIGH);
break;
}
}

void showNumber(int num)
{
int divide=0;
float z;
for(int c=1;c<5;c++) { showDigit(10); switch(c) { case 1: digitalWrite(pinDIG1,LOW); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=1000; break; case 2: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,LOW); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); divide=100; break; case 3: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,LOW); digitalWrite(pinDIG4,HIGH); divide=10; break; case 4: digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,LOW); divide=1; break; } // switch String s(int(num/divide)); char b=s.charAt(s.length()-1); showDigit(b-'0'); delay(5); } } void setup() { Serial.begin(115200); Wire.begin(); RTC.begin(); pinMode(pinA, OUTPUT); //A pinMode(pinB, OUTPUT); //B pinMode(pinC, OUTPUT); //C pinMode(pinD, OUTPUT); //D pinMode(pinE, OUTPUT); //E pinMode(pinF, OUTPUT); //F pinMode(pinG, OUTPUT); // G pinMode(pinDP, OUTPUT); // DP pinMode(pinPP, OUTPUT); // PP pinMode(pinDIG1, OUTPUT); // DIG 1 pinMode(pinDIG2, OUTPUT); pinMode(pinDIG3, OUTPUT); pinMode(pinDIG4, OUTPUT); // DIG 4 digitalWrite(pinDIG1,HIGH); digitalWrite(pinDIG2,HIGH); digitalWrite(pinDIG3,HIGH); digitalWrite(pinDIG4,HIGH); digitalWrite(pinA,LOW); digitalWrite(pinB,LOW); digitalWrite(pinC,LOW); digitalWrite(pinD,LOW); digitalWrite(pinE,LOW); digitalWrite(pinF,LOW); digitalWrite(pinG,LOW); digitalWrite(pinDP,HIGH); digitalWrite(pinPP,HIGH); } long previousMillis = 0; long interval = 1000; DateTime now; String txtMsg = ""; char s; int number_to_show=0; int time_to_show=0; // the loop routine runs over and over again forever: void loop() { unsigned long currentMillis = millis(); while (Serial.available() > 0) {
s=(char)Serial.read();
if (s == 'n') {
//if(txtMsg=="HIGH") { digitalWrite(13, HIGH); }
//if(txtMsg=="LOW") { digitalWrite(13, LOW); }
//Serial.println(txtMsg.charAt(0));

char ca[5];
txtMsg.toCharArray(ca, 5);
number_to_show = atoi(ca);
time_to_show=2;
digitalWrite(pinPP,HIGH); // we do to need dots
txtMsg = "";
} else {
txtMsg +=s;
}
}

if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if(time_to_show > 0)
{
time_to_show--;
}
else
{
now = RTC.now();
if((now.second() % 2) == 0)
{
digitalWrite(pinPP,LOW);
}
else
{
digitalWrite(pinPP,HIGH);
}
number_to_show=now.hour()*100+now.minute();
}
}

showNumber(number_to_show);

}

И в реальности:

Все закадровые звуки принадлежат игрушке на айпадике, в который играет сын.

Ну вот и все. Первый этап завершен. Часики тикают и показывают то, что в них плюнет компьютер.

Но это еще не финал, поэтому паять проводки и собирать полученное в одну кучку я бы не спешил. Хотя дело ваше 🙂