Модуль дистанционного телеуправления, телесигнализации, мониторинга температуры и сетевого напряжения

По большому счету так и есть. Человек так устроен. Но тут вы промахнулись, здесь реально таким никого не впечатлить

Ну во первых это очевидно. Иначе зачем публиковать информацию с новизной, как у таблицы умножения.

Во вторых: Да перестаньте же, наконец, дискутировать без смысла!

Сделайте следующие шаги:

  1. Код нужно вставить в обрамлении тройного обратного апострофа. Это символ ` . Он находится в АНГЛИЙСКОЙ раскладке слева от цифры 1.
  2. Код перед размещением НУЖНО ОТФОРМАТИРОВАТЬ. Это обязательно! Это можно сделать в Ардуино ИДЕ, нажав Ctrl+T.
  3. Схему и внешний вид в картинках тоже разместить на форуме.
  4. Свою ссылку на Яндекс диск можно оставить. Может быть кому-то это пригодится.

После этого я попрошу админа очистить тему от лишнего флуда, так как не имею заклинаний для удаления постов. И ты получишь нормальную публикацию проекта.
Хороший план?

я безусловно НЕ являюсь гуру программирования, но давай сравним 2 фрагмента твой (первый) и второй (мой с работающего проекта). От конца #includ-ов до setup()

Сводка
#define xAddr 0x50 // определяет базовый адрес внешней EEPROM
iarduino_RTC time(RTC_DS3231);
LiquidCrystal_I2C lcd(0x27,20,4); // Задаем адрес и размер дисплея
byte Trev = 12;//включение зуммера сигнала тревоги
byte Rej = 3;//Rej=1 - кнопка режима работы с реле, Rej=0 - режим измерения температуры и напряжения
byte R1 = 4;//тумблер выбора реле 1 (R = 1) - включить реле. (R = 0) - отключить реле
byte R2 = 5;//тумблер выбора реле 2
byte R3 = 6;// тумблер выбора реле 3
byte R4 = 7;// тумблер выбора реле 4
byte P = 9;//подтверждение успешного переключения реле в модуле передатчика
char Buf1[16];//массив для записи во внешнюю память даты и времени Tmax за архивируемый период
char Buf2[16];//массив для записи во внешнюю память даты и времени Tmin за архивируемый период
char Buf3[16];//массив для записи во внешнюю память даты и времени Vmax за архивируемый период
char Buf4[16];//массив для записи во внешнюю память даты и времени Vmin за архивируемый период
byte Mig = 8;//мигающий зелёный светодиод, показывающий нормальную работу программы
String str1,str2,str3,str4,str5,str6,stra,strb,strc,strd,stra1,strd1;

byte t;//переменная для выбора исполнительного реле или программного модуля
byte a1 = 1;//разрешение режима мониторинга по условию if((v > v1)||(v < v2))
byte b1 = 0;//запрет режима мониторинга по условию if((v < v3)&& (v>v4))
byte c1 = 1;//разрешение режима мониторинга по условию if((w > w1)|| (w < w2))
byte d1 = 0;//запрет режима мониторинга по условию if((w < w3)&&(w > w4))
byte v1 = 225;//максимально допустимое напряжение
byte v2 = 210;//минимально допустимое напряжение
byte v3 = 223;//напряжение гистерезиса для v1
byte v4 = 211;//напряжение гистерезиса для v2
byte a2;//признак записи архива напряжений
byte a3;//признак записи архива температур
float w1 = 24.00;//максимально допустимая температура
float w2 = 18.00;//минимально допустимая температура
float w3 = 23.30;//температура гистерезиса для w1
float w4 = 18.40;//температура гистерезиса для w2
unsigned int adr1 = 0;
unsigned int eepromAdd = 0;//начальный адрес записи архива в AT24C256
unsigned int adr5 = 0;//конечный адрес архива
Сводка
#pragma region Interface


TMessageList MessageList(16);   // очередь глубиной 12 сообщений
THardTimers  Timers;            // Таймеры, 10 штук

#pragma region Messages

constexpr uint16_t msg_SoftTimerStart   = 0x110;    // запустить таймер обратного отсчёта
constexpr uint16_t msg_SoftTimerEnds    = 0x111;    // таймер обратного отсчета закончился
//constexpr uint16_t msg_DisplayChange    = 0x112;    // сменить информацию на дисплее
constexpr uint16_t msg_GalletGhanged    = 0x113;    // галетник переключился
constexpr uint16_t msg_EnterClockSetup  = 0x114;    // вход в режим установки часов
constexpr uint16_t msg_ExitClockSetup   = 0x115;    // выход из режима установки часов
constexpr uint16_t msg_SetTemperature   = 0x116;    // вход в режим установки макс. температуры
constexpr uint16_t msg_EnterTempSetup   = 0x117;    // вход в режим установки температуры
constexpr uint16_t msg_ExitTempSetup    = 0x118;    // выход из режима установки температуры
constexpr uint16_t msg_LeftEncoderLong  = 0x120;    // длинное нажатие кнопки левого энкодера
constexpr uint16_t msg_RightEncoderLong = 0x121;    // длинное нажатие кнопки правого энкодера
constexpr uint16_t msg_LeftEncoderClick = 0x122;    // короткое нажатие кнопки левого энкодера
constexpr uint16_t msg_RightEncoderClick = 0x123;   // короткое нажатие кнопки правого энкодера
constexpr uint16_t msg_ClockNextFlash   = 0x124;    // перейти на след. цифру при установке часов
constexpr uint16_t msg_LeftEncoderMove  = 0x125;    // левый энкодер повращался
constexpr uint16_t msg_RightEncoderMove = 0x126;    // правый энкодер повращался
constexpr uint16_t msg_NextHeatState    = 0x127;    // состояние нагревателя изменилось
constexpr uint16_t msg_HeatSetupEnter   = 0x128;    // вход в установки температуры
constexpr uint16_t msg_HeatSetupExit    = 0x129;    // выход из установок температуры
constexpr uint16_t msg_NextFlashIndex   = 0x12A;
constexpr uint16_t msg_SetMaxTemp       = 0x12B;    // установилась макс. температура
constexpr uint16_t msg_TimerHeatSet     = 0x12C;    // 
constexpr uint16_t msg_TimerHeatStart   = 0x12D;    // включить вентилятор
constexpr uint16_t msg_TimerHeatPause   = 0x12E;    // остановить вентилятор
constexpr uint16_t msg_TimerHeatStop    = 0x12F;    // остановить (выключить) вентилятор
constexpr uint16_t msg_DisplayNext      = 0x130;    // показать след. экран в режиме нагревателя
constexpr uint16_t msg_Rotate           = 0x131;    // меняются обороты вентилятора
constexpr uint16_t msg_SetHandSetupMode = 0x132;    // вход в режим установки
constexpr uint16_t msg_SetMotorState    = 0x133;    // вкл/выкл/пауза мотора
constexpr uint16_t msg_MotorChangeDir   = 0x134;    // смена направления вращения мотора

#pragma endregion

#pragma region LedAlive

/// -------------------------------------------------------------------------------------
///
/// Блок светодиода активности 
/// 
constexpr uint32_t LED_ALIVE_PERIOD     = 5000; // Период мигания светодиода активности
constexpr uint32_t LED_ALIVE_ON_TIME    = 100;  // Горит 100 мс, остальное время - не горит
constexpr uint32_t LED_ALIVE_OFF_TIME   = LED_ALIVE_PERIOD - LED_ALIVE_ON_TIME;

TLed ledAlive(PIN_LED_ALIVE, ACTIVE_HIGH); // обьект светодиода

THandle hTimerAlive = INVALID_HANDLE;      // его таймер переключения

#pragma endregion

#pragma region Beeper

// --------------------------------------------------------------------------------------
//
//  Зуммер
//
constexpr uint32_t BEEP_CHANGE_STATE    = 300;  // пищать стока мс при смене режима
constexpr uint32_t BEEP_SETUP_END       = 200;  // пищать стока мс при входе в установки
constexpr uint32_t BEEP_CHIRP           = 50;   // пищать стока мс при нажатии на кнопку

TDigitalDevice Beeper(PIN_BEEPER);              // обьект зуммер

THandle hTimerBeeper = INVALID_HANDLE;          // таймер зуммера

void  Beep(const uint32_t ADuration);           // функция включения зуммера

#pragma endregion

#pragma region "RTC Clock"

constexpr int8_t MIN_HOUR = 0;
constexpr int8_t MAX_HOUR = 23;
constexpr int8_t MIN_MINUTE = 0;
constexpr int8_t MAX_MINUTE = 59;

THandle hTimerColon = INVALID_HANDLE;   // таймер мигания двоеточием

TDateTime Now;                          // здесь хранится текущее время
TDateTime SetTime;                      // здесь хранится устанавливаемое время

TDS3231 Clock;                          // объект часов

// void SaveTime(const TDateTime ATime); // сохранение времени в модуле часов

#pragma endregion

#pragma region "Экранчик TM1637"

TM1637 Disp(PIN_1637_CLOCK, PIN_1637_DATA, enTM1637Type::Time); // обьект Дисплейчика ТМ1637

void Display(void);     // Функция отображения

#pragma endregion

#pragma region "Датчик температуры DS18B20"

/// -----------------------------------------------------------------
///
///  Блок даччика температуры
///
///  
constexpr   int8_t ABSOLUTE_MIN_TEMP = 20;      // температура кюветы, меньше не будет
constexpr   int8_t ABSOLUTE_MAX_TEMP = 110;     // больше не должно быть

TDS18B20    TempSensor(PIN_TEMP_SENSOR);        // сам сенсор

int8_t      CurrentTemperature = INVALID_TEMPERATURE; // текущая температура

int8_t      MaxTemperature = ABSOLUTE_MIN_TEMP;     // Устанавливаемая температура                    

#pragma endregion

#pragma region Gallet

// ------------------------------------------------------------------
//
//  Галетный переключатель на PCF8574
//
constexpr uint8_t GALLET_VALUES[] = { 1,2,0,4,8 };
constexpr uint8_t GALLET_VALUES_SIZE = ArraySize(GALLET_VALUES);

Tpcf8574 Gallet(GALLET_ADDRESS, 0xFF); 

#pragma endregion

#pragma region "Энкодеры, левый и правый"
// указатели на функции

using PEncoderClickFunc = void(*)(void);
using PEncoderLongFunc = void(*)(void);
using PEncoderMoveFunc = void(*)(const int8_t);

PEncoderClickFunc onLeftClick   = NULL;
PEncoderLongFunc  onLeftLong    = NULL;
PEncoderMoveFunc  onLeftMove    = NULL;

PEncoderClickFunc onRightClick  = NULL;
PEncoderLongFunc  onRightLong   = NULL;
PEncoderMoveFunc  onRightMove   = NULL ;


TEncoder LeftEncoder(PIN_LEFT_ENCODER_LEFT,PIN_LEFT_ENCODER_RIGHT, PIN_LEFT_ENCODER_BUTTON);
TEncoder RightEncoder(PIN_R_ENCODER_LEFT, PIN_R_ENCODER_RIGHT, PIN_R_ENCODER_BUTTON);

#pragma endregion

#pragma region Heater

constexpr   uint16_t MAX_TIMER_VALUE    = 9999; // больше в TM1637 не влазиит
constexpr   int8_t   DELTA_TEMP         = 5;    // гистерезис температуры
constexpr   int8_t   MIN_VENT_TEMP      = 30;   // мин. температура вкл вентиляторов

constexpr   uint32_t DISPLAY_TIMER      = 10000;    // стока мс показывать таймер с обр. отсчетом
constexpr   uint32_t DISPLAY_TEMP       = 1500;     // а стока мс показывать температуру

enum class THeaterMode: uint8_t {Hand, MaxTemp, Timer}; // режим нагревателя, греть, пока сам не отключишь, греть до максимума, греть до конца таймера

THeaterMode HeaterMode = THeaterMode::Hand; // стартовый режим - ручной

bool TimerStarted = false; 

enum class THeatTimerState : uint8_t { Unknown = 0xFF, Run = 0, Pause = 1, Stop = 2, Error = 3 }; // все состояния в которых м.б нагреватель
THeatTimerState TimerState = THeatTimerState::Unknown; // начальное состояние при старте

void SetTimerState(const THeatTimerState ANewState);    // функция смены состояния нагревателя

uint16_t TimerCurrentValue = 0; // таймер нагревателя, 0..MAX_TIMER_VALUE

TDigitalDevice HeaterRelay(PIN_HEATER_RELAY, ACTIVE_LOW);   // реле нагревателя
TDigitalDevice VentRelay(PIN_VENT_RELAY, ACTIVE_LOW);       // реле вентилятора

#pragma endregion

Это только обьявления, без сопсно кода. Глядя в какой, ты быстрее разберешься через 2 года что хотел написать программист (даже если это был ты).

Дет! Оставь человека, Он написал, что ему 75, а тебе 54, а мне 53. Может он уже не так шустро соображает. Пусть делает, как может. Дай Б…г, чтобы я в 75 “if” с “while” не путал!

1 лайк

Скока б ему не было, бесят меня все эти b1, c2, v1 в глобалах. Ладно б 12 лет человеку было, я б наерна даже простил. По-русски это называется “со свиным рылом в калашный ряд”. Ах, простите.

А я эту графоманию вообще не читал. Не вставлено правильно - еще полбеды. Я не читаю не форматированный код вообще. Не из принципа, а просто не вижу его. Моск жалко, другого уже дадут, даже в Заказе к празднику!

а меня тема зацепила сделать маленький брелок/сигнализатор удаленный, который бы ненавязчиво пищал кратким сигналом каждые секунд 10, если в доме подача воды и/или электричества в аппарате в норме. И соответственно громкий длинный сигнал, если что то сбойнуло. Реально задолбало следить за аппаратом в течении нескольких часов :frowning:
А так в карман бросил и пошел в поле делами заниматься.

А зачем пищать, что все норм? Пищать надо только при сбоях. А то пошел в поле картошку жрать, а он всё пищит и пищит каждые 10 секунд зачем-то. Мешает.

Что бы ты под кустом не прикорнул …

Телефона в кармане не достаточно? Он умеет и в Блютус и в ВиФи и пищать умеет, и не пищать.

В области технического DIY творчества непреодолима тяга к изобретению велосипедов!

но не умеет мерять напряжение, температуру и архивировать

ТС непокобелимый !!! (ошибки нет !)

А брелок в кармане умеет? А откуда он данные берет? Из модуля получает? А телефон, значит, получать не умеет?

брелок тупо может умереть, а я этого не замечу, будет беда…

не спортивно :slight_smile:
да и на улице в деревне не ношу с собой телефон, то в цементе испачкаю, то сварочный аппарат уроню :slight_smile: всяко может быть

Знаю таких, хотя и не очень понимаю. Для вас придуманы браслеты. Снова нет нужды в велостроительстве.

да пожалуйста :slight_smile:
я в деревне отдыхаю от города и коллег, телефон без надобности.

А погода, калькулятор, переводчик, фотоаппарат, пасьянсы, радио, книжку почитать, карту посмотреть, пробки, навигатор?
Телефон просто так называется по инерции. Коммуникативные функции это не более 10% использования терминала. Включая вацап, телегу и даже форумы, типа нашего.

Обходится без терминала - как-то странно себя ощущаю… Даже просто сижу и думаю, а какое удельное сопротивление меди? Три секунды - и ответ.

ну ты оригинал )))
PS давненько я так не ржал, сенкс!!!

Если некое устройство у автора “выполняет все заложенные функции”, это совершенно не означает, что:

  1. Оно точно так же будет работать у желающего повторить конструкцию.
  2. Что оно в один прекрасный момент и у автора прекратит “выполнять все заложенные функции”

Верить на слово человеку, который сам осознает, что не считает себя специалистом?
Нет, это лучше Вы поверьте специалистам, что это еще ничего не значит.

Чтобы было нагляднее, приведу пример с автомобилем:
Скажите, Вы поверите, что автомобиль работает надежно и будет надежно работать еще много лет, если видите перед собой плохо покрашенную насквозь проржавевшую конструкцию, где-то перемотанную изолентой, а где-то подвязанную проволокой?
По внешнему виду невозможно гарантировать надежность работы, а вот гарантировать, что устройство в принципе неспособно надежно работать, - можно.
Так вот, Ваш код содержит многочисленные признаки ненадежности. Просто Вы этого в силу уровня своей квалификации не видите.
И еще одно: “Программ без ошибок не бывает”.
Тезис, что:

Не соответствует действительности, минимум, по двум причинам:

  1. Как правило, рано или поздно оказывается, что с кодом что-то не так. Ну, например, автор заложил в него 10 функций,а реально эксплуатировал только 3 из них. Как только у него появляется желание подключить 4-ю функцию, начинают вылезать глюки. Соответственно, появляется потребность внести в код исправления.
  2. Как правило, при попытках повторения возникают вынужденные отличия того, что делает “повторятель”, от авторского оригинала. И эти отличия вынуждают вносить в код правки.

Так вот, код должен не просто “надежно работать”, а еще и поддаваться поддержке, что подразумевает, что код должен быть понятно написан.
Код, в котором невозможно разобраться, не имеет никакой ценности, сколь бы полезные и сложные функции он не реализовывал. Возможно, Вам, как не специалисту, это может казаться диким, но это так.

2 лайка