// Экран 595 и термодатчик на Attyny85
// © Naevus 2016
#define SCLK 2 // пины Attyny85
#define RCLK 1
#define DIO 0
byte digitBuffer[4];
#include <OneWire.h>
OneWire oneWire(4); // пин термодатчика
float Temp;
OneWire ds(4);
long TMillis = 0;
long TPause = 5000; // интервал опроса датчика
long PMillis = 0;
long PPause = 800; // пауза на датчике для протокола (минимум 750)
int s = 0; //скринсейвер
long SMillis = 0;
long SPause = 20000; // интервал скринсейвера
const byte chr[4] = { // маска для разряда
0b00001000,
0b00000100,
0b00000010,
0b00000001
};
int T = 0; // сотни
int D = 2; // десятки
int U = 0; // единицы
void setup(void)
{
pinMode(RCLK, OUTPUT);
pinMode(SCLK, OUTPUT);
pinMode(DIO, OUTPUT);
pinMode(3, OUTPUT);
}
void loop(void)
{
// скринсейвер
if (millis() > SMillis){
if (s == 1) {s = 0;} else {s = 1;};
if (T != 0 && T != 10 ) {s=1;};
SMillis = millis()+SPause;
}
// Если пауза больше, то читаем датчик
if(millis() > TMillis) {
digitalWrite(3,LOW);
byte i;
byte present = 0;
byte data[12];
byte addr[8];
ds.reset();
ds.skip();
// Start conversion
ds.write(0x44, 1);
// Тут по протоколу долна быть пауза 750 минимум
PMillis = millis()+PPause;
while (millis() < PMillis){
// Пока пауза - рефрешим дисплей
showDisplay(); // delay(1);
};
present = ds.reset();
ds.skip();
// Issue Read scratchpad command
ds.write(0xBE);
// Receive 9 bytes
for ( i = 0; i < 9; i++) { data[i] = ds.read(); }
// Calculate temperature value
Temp = ( (data[1] << 8) + data[0] )*0.0625;
// Сотни
T = Temp/100;
// Десятки
D = (Temp - (T*100)) / 10;
// Единицы
U = Temp - (T*100) - (D*10);
if (T == 0) {T = 10;} // пусто
if (s==0) { digitBuffer[3]= 10; }
else { digitBuffer[0]= T; };
digitBuffer[0+s]= D;
digitBuffer[1+s]= U;
digitBuffer[2+s]= 11;
digitalWrite(3,HIGH);
TMillis = millis()+TPause;
}
//595
showDisplay();
}
void showDisplay(){
const byte digit[18] = { // маска для 7 сигментного индикатора
0b11000000, // 0
0b11111001, // 1
0b10100100, // 2
0b10110000, // 3
0b10011001, // 4
0b10010010, // 5
0b10000010, // 6
0b11111000, // 7
0b10000000, // 8
0b10010000, // 9
0b11111111, // 10 Пусто
0b10011100, // 11 Градус
0b10001000, // 12 A
0b11000110, // 13 C
0b10100001, // 14 d
0b10000110, // 15 E
0b10101111, // 16 r
0b10001011, // 17 h
};
// отправляем в цикле по два байта в сдвиговые регистры
for(byte i = 0; i <= 3; i++){
digitalWrite(RCLK, LOW); // открываем защелку
shiftOut(DIO, SCLK, MSBFIRST, digit[digitBuffer[i]]); // отправляем байт с "числом"
shiftOut(DIO, SCLK, MSBFIRST, chr[i]); // включаем разряд
digitalWrite(RCLK, HIGH); // защелкиваем регистры
}
}
// Термометр, часы 1307 и вольтметр на 7-сегментном дисплее на 595 (динамическая индикация)
// © Naevus 2016
/// Настройки. Все насройки, которые слдует просмотреть/изменить под себя помечены тремя косыми чертами ///
/// Блоки условного компилирования. Если какое то оборудование не используется - отключите его и прошивка
/// скомпилируется без этого функционала (и можно не настраивать соответствующий блок в настройках
#define D7SEG 1 /// Если подключен 7 сегментный дисплей, то 1 иначе 0.
#define VOLT 1 /// Если подключен вольтметр... (мигать экраном при выходе напряжения за пределы)
#define DS1820 1 /// Если подключен термодатчик...
#define RTCDS 1 /// Если подключен модуль RTC...
#define BUTTN 1 /// Если подключены кнопки...
#if D7SEG == 1
/// Экран на 595 сдвиговом регистре
#define SCLK 12 /// пины для подключения экрана
#define RCLK 11 ///
#define DIO 10 ///
byte digit[4]; // Буфер значений знакомест. В буфер помещается маска выводимых символов для отправки на дисплей
#endif
#if VOLT == 1
/// Вольтметр
//
// Измеряемое
// напряжение ─┐
// ┌┴┐
// │ │R2
// └┬┘
// ├───── Аналоговый вход Arduino
// ┌┴┐
// │ │R1
// └┬┘
// ═╧═
//
// Rmax должно быть минимум в 3 раза больше Rmin. (позволяет измерять напряжение до 20в).
// Например 30 и 10 КОм соответственно. Лучше взять 4 одинаковых резистора, один R1 и три последовательно на R2
#define R1 7.3 /// Резистор в нижнем плече делителя. У меня 7,3К
#define R2 29.5 /// Резистор в верхнем плече делителя. У меня 29,5К.
#define VIN A0 /// аналоговый вход для вольтметра
#define VCORR 0.912 /// коэффициент корректировки
/// Для расчета коэффициента:
/// 1. выставляем коэффициент = 1
/// 2. Выставляем vmin = 100
/// 3. Компилируем, запускаем.
/// 4. Подключаем источник напряжения (АКБ 12В)
/// 5. Записываем показания индикатора (например 13,5)
/// 6. Замеряем это же напряжение образцовым вольтметром. Записываем (например 12,3)
/// 7. Делим замеренное на показаное. Т.е. 12,3/13,5=0,911
/// 8. Это и есть коэффициент для вашего экземпляра ардуины. Прописываем его в vcorr
/// 9. Не забываем вернуть обратно vmin
/// Если не подключен или не используется - задайте VMIN = 0 а VMAX = 1000.
#define VMIN 0 /// минимальное напряжение для аларма (если ниже - будет мигать)
#define VMAX 15.1 /// максимальное напряжение для аларма (если выше - будет мигать)
#define VRPIN 13 /// Пин для подключения реле
#define VRMIN 11.0 /// Реле выключается если напряжение меньше VRMIN
#define VRMAX 12.5 /// Реле включается если напряжение больше VRMAX
float vvalue; // Напряжение
#endif
#if DS1820 == 1
/// Термодатчик
#define TPIN 9 /// Пин термодатчика. Тип термодатчика DS18x20 определяется автоматически
#include <OneWire.h> // Библиотека термодатчика
OneWire ds(TPIN);
byte type_s = 0; // Тип датчика (после автоматического определения)
#endif
/// Часы
#define POINTTIME 500 /// Полупериод мигания точкой - полсекунды. Этот же период берется за основу для мигания прочих элементов.
#define SETPAUSE 500 /// Пауза для быстрой смены показаний при настройке часов при удержании кнопки set
#include <Time.h>
#include <DS1307RTC.h>
#include <Wire.h>
long pointmillis; // Время для мигания точкой
int point = HIGH; // состояние точки в данный момент
int H; // часы
int M; // минуты
long setmillis=0; //Время для паузы корректировки показаний длинного нажатия
#if BUTTN == 1
/// Кнопки. Кнопки без резисторов, замыкание на землю.
// "Режим" - длинное нажатие переводит в режим установки часов. Выход из режима так же или через 5сек
// Короткое нажатие - меняет режим установки часов на минут и обратно.
// В режиме часов короткое нажатие показывает напряжение
// "Установка" - в режиме часов показывает термометр.
// В режиме корректировки меняет значение часов или минут.
#define MPIN 8 /// пин кнопки "Режим"
#define SPIN 7 /// пин кнопки "Установка"
#define BPAUSE 2000 /// пауза для длинного нажатия 2 сек
#define AD 5 /// пауза для антидребезга. подбирать для конкретных кнопок экспериментально
#define TOPAUSE 5000/// пауза для автоматического выхода из режима уствновки часов-минут
int mstate = 0; // состояние кнопки mode
int sstate = 0; // состояние кнопки set
// 0 - не нажата
// 1 - нажата, не отпущена (короткое нажатие)
// 2 - нажата, отпущена (короткое нажатие)
// 3 - нажата не отпущено (длинное нажатие)
// 4 - нажата, отпущена (длинное нажатие)
long mmillis; // время для запоминания нажатия кнопки mode
long smillis; // время для запоминания нажатия кнопки set
#include "Bounce2.h"; // Библиотека с антидребезгом
Bounce mbutton = Bounce(); // Антидребезговые кнопки
Bounce sbutton = Bounce();
#endif
/// Общие переменные и константы
#define CPAUSE 20000 /// Время отображения часов - 20 сек
#define TPAUSE 3500 /// Время отображения градусника (или напряжения) - 3.5 сек
long ctmillis = 0; // Время для счетчика переключателя часы-температура
int state; // Режим работы:
// 0 - Часы. Отображает часы, мигает точкой раз в секунду. Каждые (задано) сек переключается в режим температуты
// 1 - Термометр. Запрашивает температуру, отображает заданое время, по окончании - возврат в часы.
// 2 - Установка часов. Вход а режим - длительное нажатие кнопки mode. Выход так же или через (задано) сек неактивности.
// 3 - Установка минут. Вход а режим - короткое нажатие кнопки mode из режима установки часов. Выход так же или через (задано) сек неактивности.
// 4 - Аларм по напряжению. Мигает напряжением если оно вышло за пределы
// 5 - Напряжение. время отображения - как у термометра
// Из 2 в 3 и обратно - короткое нажатие mode. В 2 и 3 нажатие set меняет показания часов/минут.
// Если состояние требует различать вход и повторный вход, то для повторного к состоянию добавляем 10.
// Т.е. 0 - часы первый запуск, 10 - часы последующие запуски
char dbuffer [6]; // буффер для строки с запятой
void setup(void)
{
// Инициализация пинов экрана
pinMode(RCLK, OUTPUT);
pinMode(SCLK, OUTPUT);
pinMode(DIO, OUTPUT);
#if BUTTN == 1
// Инициализация пинов кнопок.
pinMode(MPIN, INPUT_PULLUP);
pinMode(SPIN, INPUT_PULLUP);
// инициализация антидребезга
mbutton.attach(MPIN);
sbutton.attach(SPIN);
mbutton.interval(AD);
sbutton.interval(AD);
#endif
#if VOLT == 1
// Инициализация пина вольтметра
pinMode(VIN, INPUT);
pinMode (VRPIN, OUTPUT);
#endif
#if DS1820 == 1
//Поиск и распознавание термодатчика
byte addr[8];
if ( !ds.search(addr)) {ds.reset_search(); type_s = 99;} // датчик не найден
else {switch (addr[0]) { // Первый байт - тип датчика
case 0x10: type_s = 1; break; //DS18S20 или старый DS1820
case 0x28: type_s = 0; break; //DS18B20
case 0x22: type_s = 0; break; //DS1822
default: type_s = 99; //ошибка определения типа датчика
}
}
#endif
// Инициализация часов
setSyncProvider(RTC.get); // получаем время с RTC
///установим вручную - один раз установили и хватит
///TimeElements te;
///te.Second = 0; //секунды
///te.Minute = 53; //минуты
///te.Hour = 12; //часы
///te.Day = 16; //день
///te.Month = 2; // месяц
///te.Year = 2016 - 1970; //год в библиотеке отсчитывается с 1970
///time_t timeVal = makeTime(te);
///RTC.set(timeVal);
///setTime(timeVal);
state = 0; // По умолчанию - часы
}
void loop(void)
{
switch(state){
case 0 : rclock(); break; // отрабатываем часы (первый раз)
case 10 : rclock(); break; // отрабатываем часы
#if DS1820 == 1
case 1 : rtemp() ; break; // отрабатываем термометр (первый раз)
case 11 : rtemp() ; break; // отрабатываем термометр
#endif
#if BUTTN == 1
case 2 : rhour (); break; // установка часов
case 12 : rhour (); break; // установка часов
case 3 : rmin (); break; // установка минут
case 13 : rmin (); break; // установка минут
#endif
#if VOLT == 1
case 4 : rvalarm(); break; // отрабатываем аларим по напряжению (первый раз)
case 14 : rvalarm(); break; // отрабатываем аларим по напряжению
case 5 : rvolt() ; break; // отрабатываем напряжение (первый раз)
case 15 : rvolt() ; break; // отрабатываем напряжение
#endif
default : rclock();
}
#if VOLT == 1
// Вольтметр
float vread = analogRead(VIN); // Читаем АЦП
vvalue = vread * ((5*VCORR*(R1+R2)/R1)/1024); // Преобразуем к напряжению
if (vvalue < VRMIN){digitalWrite(VRPIN,LOW);} // Выкл реле если напряжение меньше
if (vvalue > VRMAX){digitalWrite(VRPIN,HIGH);} // Вкл реле если напряжение больше
if (vvalue > VMAX || vvalue < VMIN) {state = 4;};// аларм вольтметра
#endif
#if BUTTN == 1
rbutton(); // опрашиваем кнопки
#endif
showDisplay(); // Рефрешим дисплей
}
#if BUTTN == 1
void rbutton (void) { // Кнопки
mbutton.update(); // Mode
switch (mstate){
case 0: if (!mbutton.read()){mstate = 1; mmillis = millis() + BPAUSE;}// нажали кнопку
break;
case 1: if ( mbutton.read()){mstate = 2;} // отжали кнопку
else {if (millis()>mmillis){mstate = 3;}} // длинное нажатие
break;
case 2: mstate = 0; break;
case 3: if ( mbutton.read()){mstate = 4;} // отжали длинное нажатие
break;
case 4: mstate = 0; break;
default: mstate = 0;
}
sbutton.update(); // Set
switch (sstate){
case 0: if (!sbutton.read()){sstate = 1; smillis = millis() + BPAUSE;}// нажали кнопку
break;
case 1: if ( sbutton.read()){sstate = 2;} // отжали кнопку
else {if (millis()>smillis){sstate = 3;}} // длинное нажатие
break;
case 2: sstate = 0; break;
case 3: if ( sbutton.read()){sstate = 4;} // отжали длинное нажатие
break;
case 4: sstate = 0; break;
default: sstate = 0;
}
}
#endif
#if VOLT == 1
void rvolt(void){ // Отображение напряжения
if (state == 15) { // Повторный вход. просто проверяем время и выходим
if (millis() > ctmillis){state = 0;} // Если время отображения термометра кончилось, переключаемся на часы
return;
} else {
dtostrf(vvalue, 4, 1, dbuffer); // Преобразуем напряжение в набор символов
// пытаемся вставить знак U в нужное место (проверяем, есть ли в наборе символов точка или запятая)
if (dbuffer[1]==44 || dbuffer[1]==46 ||
dbuffer[2]==44 || dbuffer[2]==46){dbuffer[4] = 'U';}
else {dbuffer[3] = 'U';}
led7print(dbuffer); // Функция для записи символов в буфер индикатора
ctmillis = millis()+TPAUSE; // время для переключения обратно на часы
state = 15; // меняем состояние на повторное
}
}
#endif
#if VOLT == 1
void rvalarm(void){ // Аларм напряжения (мигает)
if (vvalue>VMIN && vvalue<VMAX) {state = 0; return;} //Если напряжение нормальное - выходим в часы
if (millis()>=pointmillis) {
point = !point; //раз в pointtime мигаем напряжением
pointmillis = pointmillis + POINTTIME;
if (point) {
dtostrf(vvalue, 4, 1, dbuffer); // Преобразуем напряжение в набор символов
// пытаемся вставить знак U в нужное место (проверяем, есть ли в наборе символов точка или запятая)
if (dbuffer[1]==44 || dbuffer[1]==46 ||
dbuffer[2]==44 || dbuffer[2]==46){dbuffer[4] = 'U';}
else {dbuffer[3] = 'U';}
}
else {
dbuffer[0] = ' ';
dbuffer[1] = ' ';
dbuffer[2] = ' ';
dbuffer[3] = ' ';
} // мигаем напряжением
led7print(dbuffer); // Функция для записи символов в буфер индикатора
}
}
#endif
void rclock(void) { // Отображение часов
char cbuff[6]; //Буфер для часов
if (state == 10) { // Повторный вход. просто проверяем время
if (millis() > ctmillis){state = 1; return;} // Если время отображения часов кончилось, переключаемся на термометр
#if BUTTN == 1
// Проверяем кнопки
#if VOLT == 1
if (mstate == 2) {state = 5; return;} // если нажата Mode то переходим к вольтметру
#endif
#if DS1820 == 1
if (sstate == 2) {state = 1; return;} // если нажата Set то переходим к термометру
#endif
if (mstate == 3) {state = 2; return;} // если долго нажата Mode то переходим к корректировке часов
#endif
}
else{
#if BUTTN == 1
if (mstate != 4) { //если длинная кнопка отпущена
state = 10; ctmillis = millis()+CPAUSE;} // если первый вход - запоминаем время
#else
state = 10; ctmillis = millis()+CPAUSE;
#endif
}
// мигание точки в часах
if (millis()>=pointmillis) {
point = !point; //раз в pointtime меняем точку на не точку
pointmillis = pointmillis + POINTTIME;
H=hour();
M=minute();
if (point) {
cbuff[0]=H/10;
cbuff[1]=H-(cbuff[0]*10);
cbuff[0]=cbuff[0]+48; // +48, чтобы из значения получить ascii код цифры
cbuff[1]=cbuff[1]+48;
cbuff[2]=',';
cbuff[3]=M/10;
cbuff[4]=M-(cbuff[3]*10);
cbuff[3]=cbuff[3]+48;
cbuff[4]=cbuff[4]+48;
}
else {
cbuff[0]=H/10;
cbuff[1]=H-(cbuff[0]*10);
cbuff[2]=M/10;
cbuff[3]=M-(cbuff[2]*10);
cbuff[0]=cbuff[0]+48;
cbuff[1]=cbuff[1]+48;
cbuff[2]=cbuff[2]+48;
cbuff[3]=cbuff[3]+48;
}
led7print(cbuff); // выводим время и мигаем точкой
}
}
#if BUTTN == 1
void rhour(void) { // Установка часов
char cbuff[6]; //Буфер для часов
M=minute();
if (state == 2) { // Первый вход. Ждем когда отпустят кнопку mode
if (mstate != 3){ //Если кнопку отпустили
state = 12; ctmillis = millis()+TOPAUSE; // Запоминаем время
H=hour();}
}
if (state == 12){
if (millis()>ctmillis){state = 0;}
// Проверяем кнопки
if (mstate == 2) {state = 3; return;} // если была нажата Mode то переходим к установке минут
if (mstate == 3) {state = 0; return;} // если долго нажата Mode то переходим к часам
if (sstate == 2){ // если нажата Set
H = H+1; if(H > 23) {H = 0;}
ctmillis = millis()+TOPAUSE; // и обнуляем таймаут для выхода
}
if (sstate == 3) { // если долго нажата Set
if (millis() > setmillis) {
H++; if(H > 23) {H = 0;}
setmillis = millis() + SETPAUSE; // пауза чтобы показания менялись не слишком быстро
}
ctmillis = millis()+TOPAUSE; // и обнуляем таймаут для выхода
}
if (sstate == 2 || sstate == 4) { //кнопку отпустили - толкаем все в rtc
setTime(H, M, 0, day(), month(), year());
RTC.set(now());
}
}
cbuff[0]=H/10;
cbuff[1]=H-(cbuff[0]*10);
cbuff[0]=cbuff[0]+48; // +48, чтобы из значения получить ascii код цифры
cbuff[1]=cbuff[1]+48;
cbuff[2]=',';
cbuff[3]=M/10;
cbuff[4]=M-(cbuff[3]*10);
cbuff[3]=cbuff[3]+48;
cbuff[4]=cbuff[4]+48;
// мигание часов
if (millis()>=pointmillis) {
point = !point; //раз в pointtime меняем точку на не точку
pointmillis = pointmillis + POINTTIME;
if (point && sstate != 3) { //мигаем если не нажата set
cbuff[0]=' ';
cbuff[1]=' ';
}
led7print(cbuff); // выводим время и мигаем
}
}
#endif
#if BUTTN == 1
void rmin(void) { // Установка минут
char cbuff[6]; //Буфер для часов
H=hour();
if (state == 3) { // Первый вход.
state = 13; ctmillis = millis()+TOPAUSE; // Запоминаем время
M=minute();
}
if (state == 13){
if (millis()>ctmillis){state = 0;}
// Проверяем кнопки
if (mstate == 2) {state = 2; return;} // если была нажата Mode то переходим к установке часов
if (mstate == 3) {state = 0; return;} // если долго нажата Mode то переходим к часам
if (sstate == 2) { // если нажата Set то прибавляем часы
M = M+1; if(M > 59) {M = 0;}
ctmillis = millis()+TOPAUSE; // и обнуляем таймаут для выхода
}
if (sstate == 3) { // если нажата Set то прибавляем часы
if (millis() > setmillis) {
M = M+1; if(M > 59) {M = 0;}
setmillis = millis() + SETPAUSE; // пауза чтобы показания менялись не слишком быстро
}
ctmillis = millis()+TOPAUSE; // и обнуляем таймаут для выхода
}
if (sstate == 2 || sstate == 4) {
/// тут как то надо затолкать часы в RTC
setTime(H, M, 0, day(), month(), year());
RTC.set(now());
}
}
cbuff[0]=H/10;
cbuff[1]=H-(cbuff[0]*10);
cbuff[0]=cbuff[0]+48; // +48, чтобы из значения получить ascii код цифры
cbuff[1]=cbuff[1]+48;
cbuff[2]=',';
cbuff[3]=M/10;
cbuff[4]=M-(cbuff[3]*10);
cbuff[3]=cbuff[3]+48;
cbuff[4]=cbuff[4]+48;
// мигание часов
if (millis()>=pointmillis) {
point = !point; //раз в pointtime меняем точку на не точку
pointmillis = pointmillis + POINTTIME;
if (point && sstate != 3) { //мигаем если не нажата set
cbuff[3]=' ';
cbuff[4]=' ';
}
led7print(cbuff); // выводим время и мигаем
}
}
#endif
#if DS1820 == 1
void rtemp (void) { // Отображение температуры
float temp; // Температура
byte present = 0;// Наличие датчика
byte data[12]; // Сюда читаем данные с датчика
if (type_s == 99 ) {state = 0; return;} // если датчик не найден, то сразу возвращаемся в часы
if (state == 11) { // Повторный вход. просто проверяем время и выходим
if (millis() > ctmillis){state = 0;} // Если время отображения термометра кончилось, переключаемся на часы
return;
}
else { // Иначе - запрашиваем температуру
byte i;
ds.reset();
ds.skip();
ds.write(0x44, 1);
delays(800); //по протоколу пауза перед считыванием температуры. Минимум 750мс
present = ds.reset();
ds.skip();
ds.write(0xBE);
for ( i = 0; i < 9; i++) { data[i] = ds.read(); }
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
}
temp = (float)raw / 16.0; // Получаем температуру
dtostrf(temp, 4, 1, dbuffer); // Преобразуем температуру в набор символов
// пытаемся вставить знак градуса в нужное место (проверяем, есть ли в наборе символов точка или запятая)
if (dbuffer[1]==44 || dbuffer[1]==46 ||
dbuffer[2]==44 || dbuffer[2]==46){
dbuffer[4] = '"';}
else {dbuffer[3] = '"';}
led7print(dbuffer); // Функция для записи символов в буфер индикатора
ctmillis = millis()+TPAUSE; // время для переключения обратно на часы
state = 11; // меняем состояние на повторное
}
}
#endif
void delays (long pause){ // Замена штатной функции delay на собственную - с рефрешем индикатора
long pmillis = millis()+pause; // запоминаем время паузы
while (millis() < pmillis){showDisplay();}; // Ждем наступления времени паузы, попутно рефрешим дисплей
}
void led7print (char dstr[6]){ // Процедура разбора строки и заполнение буфера для индикатора
byte c = 0; //счетчик для входного буфера
byte d = 0; //счетчик для ВЫходного буфера
// Разбираем буфер на символы (ищем запятую)
while (d < 4) {
switch (dstr[c]) {
case 44: c++;bitClear(digit[d-1],7);break; // запятая
case 46: c++;bitClear(digit[d-1],7);break; // точка
case 0 : for (byte i=d; i<4; i++) {digit[i]=22;}; d=4; break; //конец строки, заполняем все остальное пробелами
default: digit[d]=ascii2mask(dstr[c]); c++; d++; // по умолчанию просто переносим символ
}
}
}
void showDisplay(void){ // процедура отображения экрана
const byte chr[4] = {0b00001000,0b00000100,0b00000010,0b00000001}; // маска для разряда знакоместа
for(byte i = 0; i <= 3; i++){ // отправляем в цикле по два байта в сдвиговые регистры
digitalWrite(RCLK, LOW); // открываем защелку
shiftOut(DIO, SCLK, MSBFIRST, digit[i]); // отправляем байт с "числом"
shiftOut(DIO, SCLK, MSBFIRST, chr[i]); // включаем разряд
digitalWrite(RCLK, HIGH); // защелкиваем регистры
//delay(1); // ждем немного перед отправкой следующего "числа"... если не ждать то мигания меньше.
}
}
byte ascii2mask (int ascii){ // Функция перевода кода символа в его маску
// Маски символов
const byte mask[27] = {
0b11000000, // 0
0b11111001, // 1
0b10100100, // 2
0b10110000, // 3
0b10011001, // 4
0b10010010, // 5
0b10000010, // 6
0b11111000, // 7
0b10000000, // 8
0b10010000, // 9
0b10001000, // 10 A
0b10000011, // 11 b
0b10100111, // 12 c
0b10100001, // 13 d
0b10000110, // 14 E
0b11111111, // 15 F
0b10001011, // 16 h
0b11000111, // 17 L
0b10100011, // 18 o
0b10001100, // 19 P
0b10101111, // 20 r
0b10000111, // 21 t
0b11100011, // 22 u
0b11111111, // 23 Пусто
0b10011100, // 24 Градус (")
0b10111111, // 25 -
0b11110111, // 26 _
};
if (ascii > 47 && ascii < 58) {return mask[ascii-48];} // цифры
if (ascii > 64 && ascii < 71) {return mask[ascii-55];} // A-F
if (ascii > 96 && ascii < 103){return mask[ascii-87];} // a-f
switch(ascii){
case 32 :return mask[23]; // пробел
case 34:return mask[24]; // градус
case 45 :return mask[25]; // -
case 95 :return mask[26]; // _
case 72 :return mask[16]; // H
case 104:return mask[16]; // h
case 76 :return mask[17]; // L
case 108:return mask[17]; // l
case 79 :return mask[18]; // O
case 111:return mask[18]; // o
case 80 :return mask[19]; // P
case 112:return mask[19]; // p
case 82 :return mask[20]; // R
case 114:return mask[20]; // r
case 83 :return mask[5]; // S
case 115:return mask[5]; // s
case 84 :return mask[21]; // T
case 116:return mask[21]; // t
case 85 :return mask[22]; // U
case 117:return mask[22]; // u
}
return mask[26]; // если символ не из списка, то отображаем подчеркивание
}
+59 |
2904
75
|
+34 |
3472
49
|
Но обзор понравился
Спасибо
точки — разрядность, и цена тоже хорошая.
https://aliexpress.com/item/item/New-MAX7219-LED-Dot-matrix-8-Digit-Digital-Display-Control-Module-for-Arduino-Wholesale/32605671192.html,searchweb201602_2_10039_10057_10048_10047_10056_10055_10037_10049_10059_10033_10046_10058_10032_10045_10017_405_404_407_10040,searchweb201603_4&btsid=56d70f2d-1af7-433e-9b08-ae87c2634a54
Спасибо тебе,Naevus, за помощь в освоении этого индикатора, уверен это пригодится еще многим.
P.S.Кот прикольный.
ps О, оттуда можно выковырять маски на алфавит.
arduino-kit.ru/catalog/id/modul-klaviaturyi-i-svetodiodnoy-indikatsii-tm1638-led_key
отличное описание и пример и библиотека.
samopal.pro/esp8266-hcontroller2/
С платы 3231 нужно выпаять мелкий красный диод справа от м/с часов. Иначе батарейка быстро выйдет из строя от перезаряда.
В общем — мне оно больше нравилось… Про диод — у китайцев в эти модули видимо ставятся аккумуляторы литиевые, и диод — это цепь подзарядки. Не представляю — зачем (если и на батарейке они проживут несколько лет), так что спасибо что напомнили — диод удалять.
Маленький вопрос: а в тиньку 13 первый код поместится?
Можно убрать ненужные символы, переменные перевести в постоянные, отказаться от «скринсейвера»… но, боюсь что в 3 раза этим код не ужмешь. Более того — думаю, что основной объем дает библиотека 1wire. А как от нее избавиться — я не знаю :(
ide 1,0,6 храню на всякий случай, хотя по слухам в ней тоже есть несовместимости с 1,0,5
З.Ы. Сейчас вот идея возникла: может вообще вместо энкодера аналоговый джойстик влепить? И программировать проще, и у кого ещё духовка с джойстиком есть? ;)
С джойстиком прикольно :)
:)
ps Энкодеры заказал, будет на чем поиграться через месяц
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.