Мой проект на 5110
- Войдите на сайт для отправки комментариев
Добрый день, уважаемые!
Это мой первый пост в этом форуме, хотя читаю его уже с полгода. Вобщем пинайте!
Лирическое отступление. Некоторое время назад решил освежить свое серое вещество и занялся ардуинством. Это было... трудно! Вещество не понимало, что от него хотят и требовало пива. Но постепенно ритм наладился и стало даже получаться копировать чужие наработки и понеслась.. Рабочий стол начал обрастать проводками, платками и прочей непонятной посторонним людям фигней. Вобщем все как у всех! Очень скоро стало не хватать экранчика 1602 и выбор пал на 5110. Заказал и стал мучить его. Или он меня. То одно не устраивало, то другое. Главным критерием было наличие русского языка. Перерыл кучу инфы, в том числе и на этом форуме. В итоге родился проект, которым и хочу сейчас поделиться.
Теперь собственно к делу. По плану в проекте должны быть использованы часы DS3231, экран Nokia 5110 и цифровой датчик температуры DS18B20, а также кнопка для корректировки времени. На экран должна быть выведена информация о текущем времени, дата, день недели и температура с обоих датчиков (в DS3231 свой датчик). Вот собственно то, что получилось в итоге (пока что на столе):

Ну и сам скетч:
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Software SPI (slower updates, more flexible pin options):
// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = {0x28, 0xFF, 0x03, 0xAD, 0x00, 0x16, 0x01, 0x2A}; // адрес датчика DS18B20 280054B604000092
#include <DS3231.h>
DS3231 rtc(SDA, SCL);
Time q;
uint32_t ms, ms1 = 0;
void setup() {
pinMode(8, INPUT);//Слушаем кнопку
digitalWrite(2, HIGH); //подключаем подтягивающий резистор
sensors.begin();
sensors.setResolution(Thermometer1, 10);
display.begin();
display.clearDisplay();
rtc.begin();
display.cp437(true);
display.display();
}
void printTemperature(DeviceAddress deviceAddress) {
sensors.requestTemperatures();
float tempC = sensors.getTempC(deviceAddress);
display.setTextSize(1);
display.setCursor(0, 32);
display.print(utf8rus("Внутри :"));
display.setCursor(47, 32);
display.print(rtc.getTemp());
display.setCursor(77, 32);
display.print(utf8rus("°"));
display.setCursor(0, 40);
display.print(utf8rus("Cнаружи:"));
display.setCursor(47, 40);
display.print(tempC);
display.setCursor(77, 40);
display.print(utf8rus("°"));
}
void printTimeDate() {
q = rtc.getTime();
display.setTextSize(2);
display.setCursor(10, 0);
if (q.hour < 10) {
display.print("0");
display.setCursor(22, 0);
}
display.print(q.hour);
display.setCursor(38, -3);
display.print("_");
display.setCursor(52, 0);
if (q.min < 10) {
display.print("0");
display.setCursor(64, 0);
}
display.print(q.min);
display.setTextSize(1);
display.setCursor(37, 0);
if (q.sec < 10) {
display.print("0");
display.setCursor(43, 0);
}
display.print(q.sec);
display.setCursor(13, 16);
display.println(rtc.getDateStr(FORMAT_LONG));
if (rtc.getDOWStr(FORMAT_SHORT) == "Mon") {
display.print(utf8rus(" Понедельник"));
}
if (rtc.getDOWStr(FORMAT_SHORT) == "Tue") {
display.print(utf8rus(" Bторник"));
}
if (rtc.getDOWStr(FORMAT_SHORT) == "Wed") {
display.print(utf8rus(" Cpeдa"));
}
if (rtc.getDOWStr(FORMAT_SHORT) == "Thu") {
display.print(utf8rus(" Четверг"));
}
if (rtc.getDOWStr(FORMAT_SHORT) == "Fri") {
display.print(utf8rus(" Пятница"));
}
if (rtc.getDOWStr(FORMAT_SHORT) == "Sat") {
display.print(utf8rus(" Cуббота"));
}
if (rtc.getDOWStr(FORMAT_SHORT) == "Sun") {
display.print(utf8rus(" Bоcкресенье"));
}
}
void loop() {
ms = millis();
if (digitalRead(8) == LOW) {
rtc.setTime(q.hour, q.min + 1, 0); //Сброс секунд в 0, минуты +1 (можно -1, если часы спешат)
}
if ( ( ms - ms1 ) > 1000 || ms < ms1 ) {
ms1 = ms;
printTemperature(Thermometer1);
printTimeDate();
display.display();
display.clearDisplay();
}
}
/* Recode russian fonts from UTF-8 to Windows-1251 */
String utf8rus(String source)
{
int i, k;
String target;
unsigned char n;
char m[2] = { '0', '\0' };
k = source.length(); i = 0;
while (i < k) {
n = source[i]; i++;
if (n >= 0xC0) {
switch (n) {
case 0xD0: {
n = source[i]; i++;
if (n == 0x81) {
n = 0xA8;
break;
}
if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
break;
}
case 0xD1: {
n = source[i]; i++;
if (n == 0x91) {
n = 0xB8;
break;
}
if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
break;
}
}
}
m[0] = n; target = target + String(m);
}
return target;
}
Очень хотелось бы услышать мнение специалистов, как можно оптимизировать код, потому как навыков в программировании еще очень мало, а задумок по проекту много, но все как всегда упрется в память.
Спасибо за внимание!
Про строки 80-100. День недели можно запрашивать силом, а не строкой и соответсвенно всё значительно упростится и по времени и по месту. В частности, все эти строки заменятся на одну.
Про строки 80-100. День недели можно запрашивать силом, а не строкой и соответсвенно всё значительно упростится и по времени и по месту. В частности, все эти строки заменятся на одну.
Извините я не в теме, что значит запрашивать силом?
Извините я не в теме, что значит запрашивать силом?
Виноват, опечатка - "числом".
Я понял Вас. Поменял условие.
Было:
Я понял Вас. Поменял условие.
Было:
Коннечно, можно. Я не помню там неделя начинается с воскресенья или понедельника, ну, допустим с воскресенья. Тогда воскресенью соответсвует 0, понедельник - 1, вторник - 2 и т.п. Допустим, также, что Вы уже прочитали день недели (числом) и присвоили его переменной dow (типа int8_t). Тогда Вам достаточно где-то определеить массив названий дней (хоть в progmem загоняйте), а вместо строк 80-100 написать одну вот такую строку
// // Где-то надо определить массив названий дней // static utf8rus days[] = { utf8rus(" Bоcкресенье"), utf8rus(" Понедельник"), utf8rus(" Bторник"), utf8rus(" Cpeдa"), utf8rus(" Четверг"), utf8rus(" Пятница"), utf8rus(" Cуббота") }; ,,, int8_t dow = ... // запрашиваем день недели как число ,,, // Вместо строк 80-100 пишем всего одну строку display.print(days[dow]);Проверьте что там чему соответствует, но идею Вы поняли. dow оказывается просто индексом в массиве и никакие if'ы вообще не нужны.
В моем случае dow это не переменная, а часть строки, которую выдает функция времени в строке:
Поэтому q.min - минуты, q.sec - секунды, а q.dow - DayOfWeek - день недели.
В принципе ход Ваших мыслей мне понятен, постараюсь учесть. Спасибо!
Вы не поняли.
Ну вот вроде сваял нечто. Правда все сырое и вместо дня недели выводит лишь последний символ из названия букву "а" (сегодня пятница).
#include <Adafruit_GFX.h> #include <Adafruit_PCD8544.h> // Software SPI (slower updates, more flexible pin options): // pin 7 - Serial clock out (SCLK) // pin 6 - Serial data out (DIN) // pin 5 - Data/Command select (D/C) // pin 4 - LCD chip select (CS) // pin 3 - LCD reset (RST) Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); #include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 2 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress Thermometer1 = {0x28, 0xFF, 0x03, 0xAD, 0x00, 0x16, 0x01, 0x2A}; // адрес датчика DS18B20 280054B604000092 #include <DS3231.h> DS3231 rtc(SDA, SCL); Time q; uint32_t ms, ms1 = 0; char days[7] = { ' Bоcкресенье', ' Понедельник', ' Bторник', ' Cpeдa', ' Четверг', ' Пятница', ' Cуббота' }; void setup() { pinMode(8, INPUT);//Слушаем кнопку digitalWrite(2, HIGH); //подключаем подтягивающий резистор sensors.begin(); sensors.setResolution(Thermometer1, 10); display.begin(); display.clearDisplay(); rtc.begin(); display.cp437(true); display.display(); // show splashscreen } void printTemperature(DeviceAddress deviceAddress) { sensors.requestTemperatures(); float tempC = sensors.getTempC(deviceAddress); display.setTextSize(1); display.setCursor(0, 32); display.print(utf8rus("Внутри :")); display.setCursor(47, 32); display.print(rtc.getTemp()); display.setCursor(77, 32); display.print(utf8rus("°")); display.setCursor(0, 40); display.print(utf8rus("Cнаружи:")); display.setCursor(47, 40); display.print(tempC); display.setCursor(77, 40); display.print(utf8rus("°")); } void printTimeDate() { q = rtc.getTime(); display.setTextSize(2); display.setCursor(10, 0); if (q.hour < 10) { display.print("0"); display.setCursor(22, 0); } display.print(q.hour); display.setCursor(38, -3); display.print("_"); display.setCursor(52, 0); if (q.min < 10) { display.print("0"); display.setCursor(64, 0); } display.print(q.min); display.setTextSize(1); display.setCursor(37, 0); if (q.sec < 10) { display.print("0"); display.setCursor(43, 0); } display.print(q.sec); display.setCursor(13, 16); display.println(rtc.getDateStr(FORMAT_LONG)); display.print(days[q.dow]); } void loop() { ms = millis(); if (digitalRead(8) == LOW) { rtc.setTime(q.hour, q.min + 1, 0); //Корректировка часов } if ( ( ms - ms1 ) > 1000 || ms < ms1 ) { ms1 = ms; printTemperature(Thermometer1); printTimeDate(); display.display(); display.clearDisplay(); } } /* Recode russian fonts from UTF-8 to Windows-1251 */ String utf8rus(String source) { int i, k; String target; unsigned char n; char m[2] = { '0', '\0' }; k = source.length(); i = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x30; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB8; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x70; break; } } } m[0] = n; target = target + String(m); } return target; }Во-первых непонятно, почему у Вас days char, а не utf8rus как раньше.
Во-вторых, даже если char, так описывайте его правильно
не
char days[7] = { ' Bоcкресенье', ' Понедельник', ' Bторник', ' Cpeдa', ' Четверг', ' Пятница', ' Cуббота' };а
char * days[] = { " Bоcкресенье", " Понедельник", " Bторник", " Cpeдa", " Четверг", " Пятница", " Cуббота" };это же строки, а не отдельные символы.
Спасибо за замечание Евгений. Все заработало. И (ровно килобайт) 500 байт памяти высвобождено.
Спасибо за замечание Евгений. Все заработало. И (ровно килобайт) 500 байт памяти высвобождено.
:)
Сейчас много работы, может вечерком я ещё посмотрю. Это было то, что просто само сразу в глаза бросилось.
По поводу вывода нуля перед числом менее 10
//вместо display.setCursor(10, 0); if (q.hour < 10) { display.print("0"); display.setCursor(22, 0); } display.print(q.hour); //написать функцию void printSc (uint8_t x, uint8_t y, uint8_t sze, uint8_t numb){ //(координата x, координата y, размер шрифта, само число) display.setTextSize(sze); display.setCursor(x, y); if (numb < 10) { display.print("0"); display.setCursor(x+12, y); } display.print(numb); } //вместо строк 60-90 будет void printTimeDate() { q = rtc.getTime(); printSc (10,0,2,q.hour); display.setCursor(38, -3); display.print("_"); printSc (52,0,2,q.min); printSc (37,0,1,q.sec); display.setCursor(13, 16); display.println(rtc.getDateStr(FORMAT_LONG)); display.print(days[q.dow]); }По поводу вывода нуля перед числом менее 10
Спасибо большое, как говорится В самую дырочку! И поучительно конечно же. Минус еще 100 байт.
По поводу вывода нуля перед числом менее 10
Спасибо большое, как говорится В самую дырочку! И поучительно конечно же. Минус еще 100 байт.
Можно такуюже функцию написать и для вывода дней недели и т.п.
Друзья подскажите если вместо DS18B20 заюзать LM35 (я понимаю что они разные, первый цифровой , второй аналог) что в скетче поменять нужно?
Прикрутите датчик давления для полноты информации о погоде!
а теперь выкинь ардуину и часы, бери время с ntp, вместо ардуины esp8266. ну это как дальнейшее развитие проекта
Автор, а где финальная версия скетча?
Автор, а где финальная версия скетча?
Да не будет финальной, этот проект был как баловство и процесс самообучения. Позже еще прикрутил датчик газа MQ-135, убедился в его неэффективности. Хотя проект до сих пор рука не поднимается разобрать. Кароче забросил)))
удалил
У меня жена окна мыла, градусник смахнула, хотел побыстрому собрать термометр, не вникая в детали. Видимо из первого поста скетч и так будет работать хорошо, как я понимаю. Просто в ходе обсуждения какието оптимизации происходили.
Оптимизация в коде присутствует, но чисто косметическая. А так да - работает.
Попробовал скомпелировать исходный код, получил;
DS3231 rtc(SDA, SCL)
no matching function for call to 'DS3231::DS3231(const uint8_t&, const uint8_t&)'
Принято к сведению.
Если появятся вопросы, не стесняйтесь, спрашивайте.
Евгений П спасибо что оперативно откликнулись. Я думал тема уже не рабочая, попробовал и неожиданно быстро получил ответ. С тринадцати лет занимаюсь электроникой, сделал много конструкций в том числе три транзистортестера на разных контроллерах, а вот на ардуино еще не пробовал. Конструкция понравилась своей гибкостью, поменял скетч, периферию и уже другой аппарат. Здесь понравилась картинка с первого поста, ардуино есть Mega 2560, дисплей есть, датчики есть. Взял код тоже с первого поста и сразу же облом, а в программировании знаю только как прошить контролер. Может потихоньку как-нибудь со временем разберусь что к чему, хотя в 66 лет оперативка уже не та.
Узнайте у автора кода какую именно библиотеку он использовал, поставьте её и всё будет нормально. У Вас библиотека другая.
вот эта бибилиотека
https://vk.com/doc428336442_461456678
распаковать в папку с бибилиотеками, при необходимости старую заменить на эту.
Спасибо boscfr, что откликнулись, установил Вашу библиотеку все, ожило, но снова застопорилось теперь выглядит так:
display.cp437(true); 'class Adafruit_PCD8544' has no member named 'cp437'
По-моему, опять не достает какой-то библиотеки с серии PCD8544. Перерыл весь интернет понаскачивал и установил кучу библиотек для 5110, не помогает.
этих адафруитов развелось куча))
лови: https://vk.com/doc428336442_461460117
Совершенно верно. У меня такая уже стояла, установил Вашу с заменой файлов и все скампилировалось. Спасибо. Буду игратся дальше.