Первая тема: Часы на max7219 метеостанция V1
В продолжении разработки часов на max7219, подключил DS1307. Для показаний уличной температуры установлен датчик DS18B20, а для показаний давления и домашней температуры датчик атмосферного давления BMP280. Так же добавил две тактовые кнопки c подтягивающими резисторами на 10 кОм, одна для выбора действия другая для изменения. Если нажать на кнопку выбора будут мигать часы на дисплее, и кнопкой установки устанавливаем время. При повторном нажатии на копку выбора - будут мигать минуты, а если нажать кнопку ещё раз (третий) то мигать ни чего не будет, и в это же время секунды установятся на нули. Мигание двоеточия можно изменить - что бы оно "бегало" вверх - вниз на один пиксель. Для поддержки кириллицы (русские буквы) используются библиотеки Adafruit max 7219 и GFX. Вот что в итоге у меня получилось.
- КОД
Code: Select all
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <DallasTemperature.h>
#include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
iarduino_RTC time(RTC_DS1307); // Объявляем объект time для работы с RTC модулем на базе чипа DS1307, используется аппаратная шина I2C
Adafruit_BMP085 bmp;
// ============================== кнопки
#define keyHor 4
#define keyMin 2
#define keyBr 8
#define keyPL 3
#define DS18B20 8 // Указываем, к какому выводу подключена DQ (уличн темп)
int mig = 0;
int migtime = 0;
long previousMillis = 0;
int val=0;
int wait = 50; // скорость бегущей строки
int spacer = 2;
int width = 5 + spacer; // Регулируем расстояние между символами
int refresh=0;
int pinCS = 10; // Подключение пина CS
int numberOfHorizontalDisplays = 4; // Количество светодиодных матриц по Горизонтали
int numberOfVerticalDisplays = 1; // Количество светодиодных матриц по Вертикали
String weatherString; //бегущая строка
String clocks; // время
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
OneWire oneWire(DS18B20);
DallasTemperature sensors(&oneWire);
// =======================================================================
void setup(void) {
Serial.begin( 9600 ); // Инициируем передачу данных в монитор последовательного порта
if (!bmp.begin()) //для температуры улицы
{
while (1) {}
}
time.begin(); // Инициируем работу с модулем.
//time.settime(0,27,21,03,01,18,3); // Записываем время в модуль: 0 сек, 27 мин, 21 час, 3, января, 2018 года, среда. time.settime(0,27,21,03,01,18,3);
matrix.setIntensity(0); // Яркость матрицы от 0 до 15
matrix.setRotation(matrix.getRotation()+2); //1 - 90 2 - 180 3 - 270 угол поворота
// начальные координаты матриц 8*8
matrix.setRotation(0, 1); // 1 матрица
matrix.setRotation(1, 1); // 2 матрица
matrix.setRotation(2, 1); // 3 матрица
matrix.setRotation(3, 1); // 4 матрица
// ============================== кнопки
pinMode(keyHor, INPUT_PULLUP);
pinMode(keyMin, INPUT_PULLUP);
pinMode(keyPL, INPUT_PULLUP);
pinMode(keyBr, INPUT_PULLUP);
}
// =======================================================================
int updCnt = 0;
int dots = 0;
long dotTime = 0;
long clkTime = 0;
byte del=0;
// =======================================================================
void loop(void)
{
if(updCnt<=0)
{ // каждые 10 циклов получаем данные времени и погоды
updCnt = 1;
getWeatherData();
clkTime = millis();
}
if(millis()-clkTime > 180000 && !del && dots) { //каждые 3 минуты/180000 сек запускаем бегущую строку
//ScrollText(utf8rus("sampawno.ru!")); //тут текст строки
ScrollText(utf8rus(weatherString)); //тут текст температуры и давления
updCnt--;
clkTime = millis();
}
DisplayTime();
if(millis()-dotTime > 500)
{
dotTime = millis();
dots = !dots;
}
}
// =======================================================================
void DisplayTime()
{
sensors.requestTemperatures(); // Считываем показания температуры
clocks = String(time.gettime("His"))+" "; // Время
matrix.fillScreen(LOW);
int y = (matrix.height() - 8) / 2; // Центрируем текст по Вертикали
// if(clocks[5] & 1){matrix.drawChar(14, y, (String(":"))[0], HIGH, LOW, 1);} //каждую четную секунду печатаем двоеточие по центру (чтобы мигало)
//else{matrix.drawChar(14, y, (String(" "))[0], HIGH, LOW, 1);} //каждую НЕЧЕТНУЮ секунду НЕ ПЕЧАТАЕМ двоеточие по центру (чтобы мигало)
if(clocks[5] & 1){matrix.drawChar(14, 0, (String(":"))[0], HIGH, LOW, 1);} //каждую четную секунду печатаем двоеточие по центру (чтобы бегало)
else{matrix.drawChar(14, -1, (String(":"))[0], HIGH, LOW, 1);} //каждую НЕЧЕТНУЮ секунду печатаем двоеточие ВЫШЕ на 1 (чтобы бегало)
//============================================ Кнока выбора часов/минут для установки времени
if (!digitalRead(keyPL) && mig==0)
{
time.blinktime(3); // мигают часы для установки времени
mig = 1;
delay(700);
}
if (!digitalRead(keyPL) && mig==1)
{
time.blinktime(2); // мигают минуты для установки времени
mig=2;
delay(700);
}
if (!digitalRead(keyPL) && mig==2)
{
time.blinktime(0); // НЕмигают минуты и часы
mig=0;
time.settime(0, -1, -1); // Сбросит секунды на 0, а часы, минуты и дату, оставит без изменений.
delay(700);
}
//============================================ Установка часов
if (mig==1 && !digitalRead(keyHor))
{
time.Hours ++; // прибавляем единицу к часам
if (time.Hours > 23) time.Hours = 0; // если вылезли за границы присваеваем 0
time.settime(-1, -1, time.Hours); // установит часы, а секунды, минуты и дату, оставит без изменений.
delay(200);
}
//============================================ Установка минут
if (mig==2 && !digitalRead(keyHor))
{
time.minutes ++; // прибавляем единицу к минутам
if (time.minutes > 59) time.minutes = 0; // если вылезли за границы присваеваем 0
time.settime(-1, time.minutes, -1); // установит минуты, а секунды, часы и дату, оставит без изменений.
delay(200);
}
int xh = 2;
int xm = 19;
matrix.drawChar(xh, y, clocks[0], HIGH, LOW, 1);
matrix.drawChar(xh+6, y, clocks[1], HIGH, LOW, 1);
matrix.drawChar(xm, y, clocks[2], HIGH, LOW, 1);
matrix.drawChar(xm+6, y, clocks[3], HIGH, LOW, 1);
matrix.write(); // Вывод на дисплей
}
// =======================================================================
void ScrollText (String text)
{
for ( int i = 0 ; i < width * text.length() + matrix.width() - 1 - spacer; i++ ) {
if (refresh==1) i=0;
refresh=0;
matrix.fillScreen(LOW);
int letter = i / width;
int x = (matrix.width() - 1) - i % width;
int y = (matrix.height() - 8) / 2; // Центрируем текст по Вертикали
while ( x + width - spacer >= 0 && letter >= 0 )
{
if ( letter < text.length() )
{
matrix.drawChar(x, y, text[letter], HIGH, LOW, 1);
}
letter--;
x -= width;
}
matrix.write(); // Вывод на дисплей
delay(wait);
}
}
// =======================================================================
float tempOffset = 1.5; //поправка уличного датчика
void getWeatherData()
{
weatherString = "t.дом: " + String(bmp.readTemperature(),1)+" ";
weatherString += " улица: " + String(sensors.getTempCByIndex(0) - tempOffset, 1)+" ";
weatherString += " давл: " + String(bmp.readSealevelPressure()/131.42) + " мм "; //131.42 поправка реального(из инета)
}
// ============================ латиница =================================
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-1;
break;
}
case 0xD1: {
n = source[i]; i++;
if (n == 0x91) { n = 0xB8; break; }
if (n >= 0x80 && n <= 0x8F) n = n + 0x70-1;
break;
}
}
}
m[0] = n; target = target + String(m);
}
return target;
}