Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

77 проектов Arduino

.pdf
Скачиваний:
0
Добавлен:
13.05.2026
Размер:
49.45 Mб
Скачать

Эксперимент 45

211

Рис.45.1.Схема соединений для часов на DS3231 и LCD Keypad shield

LiquidCrystal lcd(8,9,4,5,6,7);

//переменная времени-даты tmElements_t datetime;

//массив дней недели

String weekdays[]={

{"

Sunday "},{"

Monday

"},{"

Tuesday

"},{"Wednesday "},

{"

Thursday "},{"

Friday

"},{"

Saturday

"}

};

// для смены данных второй строки boolean week=false;

unsigned long millis1=0;

void setup() {

Serial.begin(9600);

//запуск дисплея lcd.begin(16,2);

//вывод заставки lcd.setCursor(3,0); lcd.print("Clock DS3231"); lcd.setCursor(2,1); lcd.print("Arduino-kit.ru"); delay(3000);

lcd.clear();

}

void loop() {

212Эксперимент 45

//получение данных из ds3231 if (RTC.read(datetime)) {

//время HH:mm:ss lcd.setCursor(4,0);

lcd.print(print2(datetime.Hour, ":")); lcd.print(print2(datetime.Minute, ":")); lcd.print(print2(datetime.Second, " "));

//дата или день недели lcd.setCursor(3,1); Serial.println(); if(week) { // день недели

lcd.print(weekdays[datetime.Wday]);

}

else { // дата dd/mm/YYYY lcd.print(print2(datetime.Day, "/")); lcd.print(print2(datetime.Month, "/")); lcd.print(tmYearToCalendar(datetime.Year));

}

//изменение week каждые 5 секунд

if(millis()-millis1>5000) { week=!week; millis1=millis();

}

}

else {

lcd.print("error");

delay(5000);

}

delay(1000);

}

String print2(int nn,String str) { String s="";

if (nn >= 0 && nn < 10) { s=s+"0";}

s=s+String(nn);

s=s+str; return s;

}

Скачать данный скетч можно на сайте Arduino-kit по ссылке https://arduino-kit.ru/scetches/exp_45_01.zip.

Загружаем скетч на плату Arduino и на экране LCD Keypad shield получаем часы с отображением времени, даты и дня недели.

Эксперимент 46.

Добавляем часам на ЖК-дисплее LCD Keypad shield функционал будильника

В этом эксперименте добавим часам на ЖК-дисплее LCD Keypad shield функционал будильника

В эксперименте мы будем использовать следующие компоненты:

Плата Arduino UNO – 1;

Кабель USB – 1;

Плата прототипирования – 1;

Модуль DS3231 – 1;

LCD Keypad shield – 1;

Динамик – 1;

Провода MM – 12.

Переключатели на плате Arduino+WiFi установите следующим образом:

1

2

3

4

5

6

7

 

 

 

 

 

 

 

OFF

OFF

ON

ON

OFF

OFF

OFF

 

 

 

 

 

 

 

В эксперименте 45 мы создали часы на модуле DS3231. Добавим данным часам функционал будильника. Схема соединений показана на рис. 46.1.

Приступим к написанию скетча. Создадим структуру, описывающую будильник. struct ALARM{

int Hour;

// час срабатывания будильника

int Minute;

// минута срабатывания будильника

int Day;

// день срабатывания будильника

int Month;

// месяц срабатывания будильника

int Year;

// год срабатывания будильника

boolean repeat;

// true – повторять, false -одноразово

int wdays[7];

// дни недели

};

 

И создадим список необходимых будильников:

ALARM alarms[]={{7,30,14,12,2018,1,{1,1,1,1,1,0,0}}, {12,35, 14,12,2018,0,{0,0,0,0,0,0,0}},

{18,00, 5,12,2018,1,{1,1,1,1,1,0,0}}, {22,10, 10,12,2018,1,{1,1,1,1,1,1,1}},

};

214 Эксперимент 46

Рис.46.1.Схема соединений для часов с будильником на DS3231 и LCD Keypad shield

В цикле loop() скетча необходимо проводить проверку наступления события по расписанию и необходимых действий при наступлении события (воспроизведение звука, прерываемого удержанием более 1 сек кнопки RIGHT на клавиатуре LCD Keypad shield). Содержимое скетча показано в листинге 46.1.

Листинг 46.1.

//подключение библиотек

#include <Wire.h> #include <DS1307RTC.h> #include <Time.h> #include <TimeLib.h> #include <LiquidCrystal.h>

//создание экземпляра дисплея

LiquidCrystal lcd(8,9,4,5,6,7);

//переменная времени-даты tmElements_t datetime;

//массив дней недели

String weekdays[]={

Monday

"},{" Tuesday

"},{"Wednesday "},

{"

Sunday "},{"

{"

Thursday "},{"

Friday

"},{" Saturday

"}

Эксперимент 46

215

};

//для смены данных второй строки boolean week=false;

unsigned long millis1=0;

//структура, описывающая будильник struct ALARM{

int Hour;

// час срабатывания будильника

int Minute;

// минута срабатывания будильника

int Day;

// день срабатывания будильника

int Month;

// месяц срабатывания будильника

int Year;

// год срабатывания будильника

boolean repeat;

// true – повторять, false - одноразово

int wdays[7];

// дни недели

};

// список будильников

ALARM alarms[]={{7,30,14,12,2018,1,{1,1,1,1,1,0,0}}, {12,35, 14,12,2018,0,{0,0,0,0,0,0,0}},

{18,00, 5,12,2018,1,{1,1,1,1,1,0,0}}, {22,10, 10,12,2018,1,{1,1,1,1,1,1,1}},

};

//будильник работает? boolean alarmyes=false;

//пин подключения динамика int pinSpeaker=10;

void setup() {

Serial.begin(9600);

//запуск дисплея lcd.begin(16,2);

//вывод заставки lcd.setCursor(3,0); lcd.print("Clock DS3231"); lcd.setCursor(2,1); lcd.print("Arduino-kit.ru"); delay(3000);

lcd.clear();

//пин динамика pinMode(pinSpeaker,OUTPUT);

}

void loop() {

// выключение будильника if(alarmyes==true) {

if(analogRead(A0)<100) { // кнопка RIGHT нажата?

216 Эксперимент 46

alarmyes=false;

noTone(pinSpeaker); Serial.println("ALARM STOP");

}

}

// получение данных из ds3231 if (RTC.read(datetime)) {

//время HH:mm:ss lcd.setCursor(4,0);

lcd.print(print2(datetime.Hour, ":")); lcd.print(print2(datetime.Minute, ":")); lcd.print(print2(datetime.Second, " "));

//дата или день недели lcd.setCursor(3,1); Serial.println(); if(week) { // день недели

lcd.print(weekdays[datetime.Wday]);

}

else { // дата dd/mm/YYYY lcd.print(print2(datetime.Day, "/")); lcd.print(print2(datetime.Month, "/")); lcd.print(tmYearToCalendar(datetime.Year));

}

//изменение week каждые 5 секунд

if(millis()-millis1>5000) { week=!week; millis1=millis();

// проверка времение срабатывания будильника isalarm();

}

}

else {

lcd.print("error");

delay(5000);

}

delay(1000);

}

String print2(int nn,String str) { String s="";

if (nn >= 0 && nn < 10) { s=s+"0";}

s=s+String(nn);

s=s+str;

Powered by TCPDF (www.tcpdf.org)

Эксперимент 46

217

return s;

}

// проверка времение срабатывания будильника void isalarm() {

// проход по всем будильникам for(int i=0;i<4;i++) {

if(alarms[i].repeat==false) { //одноразовый if(tmYearToCalendar(datetime.Year)==alarms[i].Year &&

datetime.Month==alarms[i].Month && datetime.Day==alarms[i].Day && datetime.Hour==alarms[i].Hour && datetime.Minute==alarms[i].Minute && datetime.Second<2) { tone(pinSpeaker,349,30000); alarmyes=true; Serial.println("ALARM OK");

}

}

else { if(alarms[i].wdays[datetime.Wday]==1 &&

datetime.Hour==alarms[i].Hour && datetime.Minute==alarms[i].Minute && datetime.Second<3) { tone(pinSpeaker,349,30000); alarmyes=true; Serial.println("ALARM OK1");

}

}

}

}

Скачать данный скетч можно на сайте Arduino-kit по ссылке https://arduino-kit.ru/scetches/exp_46_01.zip.

Загружаем скетч на плату Arduino. На экране LCD Keypad shield видим часы с отображением времени, даты и дня недели. При срабатывании будильника слышим звуковой сигнал продолжительностью 30 секунд, прерываемый удержанием более 1 сек кнопки RIGHT на клавиатуре LCD Keypad shield.

Эксперимент 47.

Память EEPOM.Запись в EEPROM данных для будильников

В этом эксперименте рассмотрим работу с энергонезависимой памятью Arduino – EEPROM и создадим программу для загрузки и удаления

из памяти EEPROM данных для будильников

В эксперименте мы будем использовать только плату Arduino+ WiFi и кабель USB для подключения к компьютеру. Переключатели на плате установлены следующим образом:

1

2

3

4

5

6

7

 

 

 

 

 

 

 

OFF

OFF

ON

ON

OFF

OFF

OFF

 

 

 

 

 

 

 

В эксперименте 46 мы создали часы на модуле DS3231 с функционалом будильника. Список будильников вписан в скетч. Но очень часто необходимо удалять старые будильники и добавлять новые. Где же в таком случае хранить информацию о будильниках? Микроконтроллер ATmega328 имеет на борту энергонезависимую память EEPROM объемом 1024 байта, которая не потеряет записанные в нее данные даже после отключения питания. Память типа EEPROM допускает несколько десятков тысяч циклов записи и стирания данных. Ее мы и будем использовать для сохранения данных о будильниках для часов.

Для работы с этой памятью в составе Arduino IDE имеется удобная библиотека EEPROM. Библиотека содержит две функции: чтения и записи в память данных. И чтение и запись происходят побайтно.

Структура, описывающая будильник из эксперимента 46: struct ALARM{

int Hour;

// час срабатывания будильника

int Minute;

// минута срабатывания будильника

int Day;

// день срабатывания будильника

int Month;

// месяц срабатывания будильника

int Year;

// год срабатывания будильника

boolean repeat;

// true – повторять, false - одноразово

int wdays[7];

// дни недели

};

Эксперимент 47

219

Для хранения каждого будильника требуется 14 байт (на год – 2 байта, на остальные параметры по одному). Необходимо в памяти сохранять и общее количество будильников (нулевой байт памяти EEPROM). Тогда память EEPROM 1-1023 может использоваться для хранения информации о 73 будильниках!

Предварительно очистим память EEPROM, загрузив на Arduino скетч Файл Примеры EEPROM eeprom_clear.

Добавление, удаление будильников будем производить по последовательному порту, отправляя соответствующие команды. Список команд:

Наименование

Формат

 

 

 

1

Добавить будильник

1;hour;minute;day;month;Year;repeat;s;m;t;w;t;f;s$

 

 

 

2

Удалить будильник

2;num$

 

 

 

3

Получить количество будильников

3$

 

 

 

4

Вывести список будильников

4$

 

 

 

5

Очистить

5$

 

 

 

Arduino собирает поступающие по последовательному порту данные, пока не придет символ '$'. Далее идет анализ поступивших данных и Arduino отправляет в последовательный порт ответ OK или ERROR и дополнительную информацию.

Содержимое скетча показано в листинге 47.1.

Листинг 47.1.

//подключение библиотек

#include <EEPROM.h>

//данные, пришедшие из последовательного порта

String inputString = "";

//строка пришла

boolean stringComplete = false;

void setup() {

//запуск последовательного порта

Serial.begin(9600);

//резервирование 30 bytes для inputString: inputString.reserve(50); Serial.println("wait.....");

}

void loop() {

// проверка прихода строки из последовательного порта if (stringComplete) {

Serial.println(inputString); // обработка строки

220 Эксперимент 47

parse();

// очистить строку inputString = ""; stringComplete = false; Serial.println("wait.....");

}

}

// получение данных по последовательному порту void serialEvent() {

boolean flag1=false;

while (Serial.available() && flag1==false) { // получить байт:

char inChar = (char)Serial.read(); // добавление в строку inputString += inChar;

if (inChar == '$') { stringComplete = true; flag1=true;

}

}

}

// парсинг поступивших данных void parse() {

int data[15]; int index=0;

String str1=""; unsigned int count;

// очистить

for(int i=0;i<15;i++) { data[i]=0;

}

for(int i=0;i<inputString.length();i++) { if(inputString[i]==';' || inputString[i]=='$') {

data[index]=str1.toInt();

str1="";

index++;

}

else { str1=str1+inputString[i];

}

}

// выполнить команды count=EEPROM.read(0); switch(data[0]) {

case 1: Serial.println("OK"); // добавление будильника count=EEPROM.read(0);

EEPROM.write(count*14+1,data[1]);

EEPROM.write(count*14+2,data[2]);

EEPROM.write(count*14+3,data[3]);

EEPROM.write(count*14+4,data[4]);