77 проектов Arduino
.pdf
Эксперимент 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]);
