Завидую я вам, новичкам. Глаза горят, руки по клавиатуре бьют. У меня вот даже мысли не возникало все эти умные бани лепить, ибо геморрой это редкостный, когда знаешь, что в перспективе ожидает.
Блин, подскажите как надо пожалуйста! Я понимаю что вы правы, но не знаю как на деле это написать.....
Если я отправляю 5 интов (10 байт), то и приняться должны 10 байт....
Оставьте вы байты, раз не понимаете. Если вы отправляете пять интов - то и принимайте пять интов. Ваши данные содержатся в элементах с bn[0] по bn[4], подряд, а не в четных
Поставил приём 5, данные всё также только в чётных...... почему??? Как при присвоении переменным массива принятых данных программа умудряется перепрыгивать через один....
Алекс, ну а сколько программа должна напечатать, если у вас в коде 10 оператора print ?
Поймите важную вещь - в языке С нет встроенных проверок размера массива. Если обьявили массив из пяти элементов, а потом записали в него 250 значений - никаких ошибок вам компилятор не выдаст.
Все эти проверки - на совести программиста, то есть вас. Если вы захотели напечатать десять значений из массива с пятью элементами - программа вам напечатает. Все на ваш риск.
Поставил приём 5, данные всё также только в чётных...... почему??? Как при присвоении переменным массива принятых данных программа умудряется перепрыгивать через один....
покажите новый код, как вы поставили прием 5. Только код целиком - и именно тот, что тестируете, а не какой-то "я вот тут чуть-чуть изменил"
Так значения записывает программа, а не я. Принтом я только вывожу на печать то что есть. Элементам массива я ничего не присваиваю..... присваивает программа. Я с вами согласен, что данные должны быть в первых пяти, но на деле это не так - они в чётных элементах массива оказываются.... Работа этой строки rf95.recv(int(bn), 5); и вызывает залезание в чужую область памяти скорее всего... но почему?
Поставил приём 5, данные всё также только в чётных...... почему??? Как при присвоении переменным массива принятых данных программа умудряется перепрыгивать через один....
покажите новый код, как вы поставили прием 5. Только код целиком - и именно тот, что тестируете, а не какой-то "я вот тут чуть-чуть изменил"
Всё тоже самое, только в строке rf95.recv(int(bn), 10); 10 заменил на 5 и всё
"- вот вы и влезли в чужую область памяти, при этом знаете что бывает? - программа либо зависает (привет вопросам годичной давности) либо в ней портятся другие переменные - вот вам и обнуление температуры"
я вижу что это так и происходит, только не могу понять почему. При чтении rf95.recv(int(bn), 10); мои данные содержатся в чётных байтах, потому и печатаю с нулевого по девятый. И вынимаю чётные.
b707 поставил Вам абсолютно точный диагноз: Вы путаете байты и двухбайтовые целые.
Я же говорю - перепробовал все варианты, и ваш в том числе - при присвоении перескакивает через элемент массива....
Не нужно ничего пробовать - нужно писать сразу единственный правильный вариант.
PS. Говорят, если миллион обезьян посадить за пишущие машинки, то за 20 лет они смогут напечатать "Войну и мир".
С момента появления форумов прошло уже больше времени, да и количество их пользователей перевалило далеко за миллиард, но нетленки почему-то так и не появилось. Может, нужно было, чтобы были все-таки обезьяны?
Спасибо вам большое, b707! Ейбогу не знал что инты в дуе другой размерности! Первый раз на ней что-то делал. И температура перестала соскакивать на ноль ))))))
Ну, вот, как умнó я вчера попросил Вас код выложить. Пока я дрых до обеда, после тяжёлой командировки, вопрос и без меня решился, спасибо коллегам :-)
Позвольте, мне поворчать по стариковски и дать Вам пару общих советов и некую отправную точку для понимания всего этого нагромождения типов данных. Надеюсь, будет полезно.
Но для начала пара комментариев, которые мне кажутся наиболее важными.
alexbel620017 пишет:
Так значения записывает программа, а не я.
Стоп! Кто в доме хозяин? Программа ничего никуда не записывает. Всё делаете всегда Вы сами. То, что компилятор помогаем Вам в рутинных операциях - вовсе не означает, что он что-то делает. Он делат ровно то, что Вы ему сказали делать. Делаете всегда Вы сами. И Вы должны понимать каждый "чих". Если Вы не понимаете, что "он" делает, значит Вы потеряли контроль над ситуацией - немедленно опускайтесь ниже и разбирайтесь что на самом деле происходит. Делаете всегда Вы, и Вы должны понимать что Вы делаете до последних мелких нюансов.
alexbel620017 пишет:
Капец....... я не знал......
Вы не поверите, но переходя на новый процессор или новый компилятор для старого процессора, я ВСЕГДА запускаю нечто вроде вот такого:
после этого я точно знаю что у меня за типы. Делайте тоже самое, заведите это привычкой. Вот сейчас запустите это на своей DUE и покажите нам результат (мне, кстати, очень интересно, т.к. я не знаю как там сделаны double).
Так, ну теперь к "полезностям". Я могу рассказать Вам про работы с памятью и типами данных так, как я рассказывал внуку. У него с тех пор проблем нет, потому я думаю, что это было понятно. Хотя, конечно, ничего нового я не скажу - откуда тут новое. Надо? Или Вы итак уже всё поняли, просто с DUE затык вышел?
Или Вы итак уже всё поняли, просто с DUE затык вышел?
Евгений, позволю себе опять влезть. Это не просто "затык с Дуе". Думаю тут все серьезно.
Почему мне так кажется? -Не заметить другой размер целого мог и более опытный программист. Но ни один даже самый начинающий - не стал бы решать проблему чтением шестого-десятого элементов из массива int bn[5]. Это дичь, очевидная даже школьнику, вчера прочитавшего про массивы. И любой школьник, хотя бы, догадался бы описать массив как int bn[10] :) - это был бы кривой костыль - но он решил бы все проблемы в коде ТС :)
ТС, что называется, программирует методом тыка. Он всю программу написал путем пристраивания подходящих кусков из готовых примеров, даже не пытаясь понять, что они делают. А когда у него возникла проблема с передачей данных - он уже стал пробовать туда все подряд, по его собственному выражению - совершенно не считаясь с логикой и смыслом.
Сомневаюсь, что у ТС сильно прибавилось в понимании после вчерашней развязки. Скорее, он просто скопировал те строчки, что я ему дал. - как ставят заплату на прорехе. "Решил проблему" и забыл.
А по поводу всего остального.... Господа Гуру, вы поймите, что я не ПРОГРАММИСТ. Этой хренью я занимаюсь чисто для себя. Я никогда не учился этим языкам (исключая Бэйсик в школе в 87-м году) и программированию. Моё образование, работа лежат совсем в другой сфере. Два года назад если бы меня спросили что такое С++ я бы сказал что это буква с двумя плюсами... Я леплю маленькие проектики типа GSM сигналки в гараж, метеостанцию с выходом в НМ, часы с синхрой от GPS, инфосистема в котельную в частный дом и подобное для себя. Да, код не только кривой, но и, даже я вижу, очень не рациональный. И часто копирую код из примеров досконально не понимая как он работает.Занимаюсь я этим либо по ночам, либо в выходной. Времени у меня уходит на всё много. Проект годичной давности с последующим двух-трёх месячным прогоном я делал почти год - времени и знаний (по софту) не хватает. Напрасно вы так на меня нападаете, то что вам кажется элементарным может для другого человека оказаться не известным или не понятным.
По поводу вчерашнего вопроса с размерностью на DUE - я не "просто скопировал" строчки, когда b707 сказал что размерность инта в два раза больше всё сразу стало понятно - и про неприём, и захват чужой области памяти... Я не то что не знал этого нюанса, я даже предположить не мог что такая хрень может быть. Это надо просто знать. Я никогда не имел дело с армовскими процами. Эта DUE приехала мне из китая только пару недель назад. И тот код, который Евгений показал я мог бы и сам конечно написать, но я и предположить не мог что на разных платах может быть разная размерность одного типа данных.
Вся эта хрень всё же зависает на работе какого-нибудь модуля SPI. Их три - W5500, SD карта и RA-01(LoRa). Все модули имеют питание 3,3 вольта, уровни, как пишут, "толерантны к пити вольтам". Но что бы сделать всё по-человечески на каждый модуль спаял переходную плату на 74HC125. Питание на неё беру с самого модуля - 3,3 в. Виснет (по меткам в программе) именно на работе W5500 или SD карты. Работать без зависания может от нескольких секунд до нескольких десятков минут.
Ну так как, ни у кого мыслей нет? По одному модулю - зависаний нет, если два или все три - виснет. Работает от нескольких секунд до нескольких минут. Схему буфера на каждую плату прикладываю.....
// при окончательной установке убрать коммент. "аварию отоления" 562 стр.
#include <RH_RF95.h>
#include <Adafruit_SHT31.h>
#include <EEPROM.h>
#include <TinyGPS.h>
#include <Ethernet2.h>
#include <Nextion.h>
#include <OneWire.h>
#include <DS1307RTC.h>
#include <DS3231.h>
#include <Time.h>
//#include <SPI.h>
#include <SD.h>
#include <iarduino_Pressure_BMP.h>
// ------------------------- сеть ---------------------------------
byte mac[] = {0x2C, 0xF7, 0xF1, 0x08, 0x00, 0x9A};
IPAddress ip(192, 168, 1, 6);
EthernetServer server(756);
// ------------------------- LoRa ---------------------------------
RH_RF95 rf95(48, 2); // (SS, interrupt) внимательно с выводом прерывания на Ардуине!
uint32_t data[5]; // Создаём массив для приёма данных - 32 разряда, тк передатчик DUE
// ------------------------- часы ---------------------------------
DS3231 Clock;
TinyGPS gps;
// ------------------------- давление -----------------------------
iarduino_Pressure_BMP sensor;
// ------------------------- влажность ----------------------------
Adafruit_SHT31 sht31 = Adafruit_SHT31();
// ------------------------- температура --------------------------
OneWire sensDs1(7); // датчик температуры подключен к выводу 7 дом
byte bufData1[9]; // буфер данных температуры в доме
byte addr1[8]; // массив адреса датчика темп. в доме
OneWire sensDs2(6); // датчик температуры подключен к выводу 6 вход
byte bufData2[9]; // буфер данных
byte addr2[8]; // массив адреса датчика
bool frchtd = false; // флаг разрешения чтения с дисплея "сброса"
bool newdata = false;
bool Century = false;
bool h12;
bool PM;
bool td = false; // флаг разрешения обработки данных датчика температуры в доме
bool fwdt = true; // флаг WDT
bool fsd = true; // флаг однократности вывода "данные устарели"
byte m, s, h, d, M; // переменные даты и времени
int Y = 2000;
bool fscht; // флаг разрешения суммирования при чтении с дисплея
bool BanTM = false; // флаг наличия данных из бани
bool Zu = false; // флаг печати значка SD-карты на дисплей
bool fp = false; // флаг разрешения сброса раз в сутки
bool fa = true; // флаг для однократности сработывания аварии
int celsius1, celsius2, celsius3; // температура в доме
float celsgis = 100; // промежуточная темп. для прохождения гистерезиса
int toutside = 0; // температура на улице с датчика влажности
int tPred; // переменная для проверки перехода с одного разряда на два и обратно при печати ул. температуры на дисплей
int p; // давление
int hum; // влажность на улице
int ch; // переменная для вычитывания буфера Nextion
int val; // строка из дисплея
int i;
float tuprm; // считанное значение уличной температуры
float huprm; // считанное значение уличной влажности
float dvl; // считанное значение атм. давления
bool gisalarm;
float toutsidegis = 100; // переменная для гистерезиса
unsigned long mln = 300000; // период синхронизации с GPS (сначала ч/з 5 минут (считывание альманаха при перв вкл, потом раз в 7 сут. (604800000)
unsigned long sinhr; // переменная в мсек задающ. период синхронизации
unsigned long za; // переменная в мсек задающ. задержку на сработывание аварии (2 мин, искл. ложных срабатываний)
unsigned long zadavar; // переменная в мсек задающ. период синхронизации
unsigned long start; // переменная в мсек задающ. цикл считывания данных gps
unsigned long registr; // переменная в мсек для таймера регистратора
unsigned long dvt = 3000; // период измерения давл. вл. и температуры (нач. 5 сек, потом раз в минуту)
unsigned long dvtperiod; // переменная в мсек для таймера измерен. давл.вл и у.темп.
unsigned long loraperiod; // переменная таймера проверки приёма LoRa
unsigned long swi = millis(); // перенная для смены фона на сайте ТМ данных
unsigned long treg = 290000; // период записи регистратора 5 мин (переменная на 10 сек меньше - догоняет остаток от деления =0)
unsigned long tperiod; // переменная в мсек для таймера обработки измерен. темп. в доме
unsigned long nadisplei; // переменная в мсек для таймера вывода на дисплей
unsigned long disp = 50; // период таймера вывода на дисплей, нач. 1 сек, потом 10 сек.
unsigned long olddata; // переменная
unsigned long pwdt; // переменная для WDT
unsigned long time, date; // переменные для считыв. даты и времени для вычисления "пустой" даты
float gis = 0.2; // гистерезис температуры и влажности
float pgis, hgis; // вспомогательная переменная для гистерезиса влажн. и давления
String pch; // переменная для вывода на дисплей
String SMSOUT; // текстовая переменная "номер для смс"
int db1; // темпеатура парной
int db2; // темпеатура комната бани
int db3; // темпеатура т. пола бани
int db4; // нагрев (0 - нет, 1 - нагрев)
int db5; // CRC с LoRa
int d1; // темпеатура выход котла К-->
int d2; // темпеатура вход котла (обратка) K<--
int d5; // темпеатура выход на ТП
int d6; // темпеатура вход с ТП (обратка)
int d7; // темпеатура бойлера
int d8; // давление системы водоснабжения
int d9; // давление системы отопления
int d81, d82, d91, d92; // промеж. параметры для отобр. гидро давления в СМС
int d10; // темпеатура в котельной
int d11; // темпеатура в гараже
int d12; // темпеатура скважины
int d13; // расход фильтра Мех.
int d14; // расход фильтра Ca Mg.
int d15; // расход фильтра Fe.
int d3, d4; // резерв
String(s1), (s2), (s3), (s4), (s5), (s6), (s7), (s8), (s9), (s10), (s11), (s12), (s13), (s14), (s15), (s16);
String(s151), (s152), (s161), (s162);
String(ss1), (ss2), (ss3), (ss4), (ss5), (ss6), (ss7);
int ttt;
// ------------------------------------------------------ setup --------------------------------------------------------------
void setup() {
SPI.begin;
//SPI.setClockDivider(SPI_CLOCK_DIV16);
Serial.begin(9600);
Serial1.begin(9600); // порт GPS
Serial2.begin(9600); // порт Nextion
Serial3.begin(9600); // порт SIM800
pinMode(48, OUTPUT); // CS LoRa
pinMode(49, OUTPUT); // CS W5500
pinMode(47, OUTPUT); // CS SD
pinMode(33, OUTPUT); // выход на WDT
digitalWrite(47, HIGH);
digitalWrite(48, HIGH);
digitalWrite(49, HIGH);
digitalWrite(33, LOW);
setSyncProvider(RTC.get); // библиотечная команда извлечения данных из модуля часов
za = millis(); // переменная в мсек задающ. задержку на сработывание аварии (2 мин, искл. ложных срабатываний)
sinhr = millis(); // переменная в мсек для синхронизации по GPS
zadavar = millis(); // переменная задержки сработки АВАРИИ по давлению отопл. или t котла (на минуту после вкл. или сброса аварии)
registr = millis(); // переменная в мсек для таймера регистратора
dvtperiod = millis();
loraperiod = millis();
tperiod = millis(); // переменная в мсек для таймера изм. температуры
nadisplei = millis(); // переменная в мсек для таймера вывода на дисплей
olddata = millis(); // переменная для проверки новизны данных с котельной
pwdt = millis();
SendDataP("q0.picc", 11); // очистка уличной температуры
SendDataP("pio0", 0); // выключили сирену в Nextion
if (EEPROM.read(10) == 1) {
SendDataP("tm5.en", 1); // запустили тревогу на дисплее
frchtd = true; // разрешили чтение с дисплея "сброса"
}
else {
SendDataP("page0.tm5.en", 0); // остановили таймеры мигания "АВАРИИ" на дисплее
SendDataP("page0.tm6.en", 0);
SendDataP("page0.p0.pic", 10); // опять нарисовали "БАНЬКУ"
frchtd = false; // запретили чтение с дисплея "сброса"
}
Ethernet.begin(mac, ip);
server.begin();
sensor.begin(); // инициализация датчика давления
sht31.begin(0x44); // инициализация датчика влажности
SD.begin(47); // инициализация модуля SD карты
rf95.init(); // инициализация SX1278
//rf95.setTxPower(5, false); // мощность 5 - 23, максимальная мощность (при 23) 100мВт (шаги с 5 по 23 не подряд! смотреть в библиотеке)
//void clearRxBuf();
sensDs1.search(addr1); // поиск и запись адреса датчика температуры
sensDs1.write(0x4E); // разрешение записи 3-х байт в DS18B20 (предустановка)
sensDs1.write(0x7F); // TH
sensDs1.write(0xFF); // TL
sensDs1.write(0x20); // регистр конфигурации (разрешение: 0х00-0.5 0х20-0.25 0х40-0.125 0х60-0.0625)
sensDs2.search(addr2); // поиск и запись адреса датчика температуры
sensDs2.write(0x4E); // разрешение записи 3-х байт в DS18B20 (предустановка)
sensDs2.write(0x7F); // TH
sensDs2.write(0xFF); // TL
sensDs2.write(0x20); // регистр конфигурации (разрешение: 0х00-0.5 0х20-0.25 0х40-0.125 0х60-0.0625)
Serial3.println("AT+IPR=9600"); // скорость модема
delay(200);
//Serial3.println("AT+CSQ"); // уровень сигнала // ПРИ УРОВНЕ СИГНАЛА
//delay(500);
Serial3.println("AT+CLIP=1"); // включить АОН
delay(200);
Serial3.println("AT+CMGF=1"); // текстовый формат SMS
delay(200);
Serial3.println("AT+CSCS=\"GSM\""); // кодировка текста - GSM
delay(200);
Serial3.println("AT+CMGD=1,4"); // удалить все смс
delay(200);
Serial3.println("AT+CNMI=2,2,0,0,0"); // вывод смс в консоль
delay(200);
Serial3.println("AT&W"); // запомнить настройки
delay(200);
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
// ==========================================================================================================================
// ============================================================ L O O P =====================================================
void loop() {
//Serial.println("1");
//Serial.println(millis());
ttt++;
if (ttt == 100) {
//Serial.println(millis());
ttt = 0;
}
// --------------------------------------- суточный брос ------------------------------------------------------------------
if (h == 10 && m == 6 && fp == true) { // RESET в 10 часов 06 минут каждый день
goto M3; // для сут. сброса нет стробов WDT
}
if (m == 8) {
fp = true;
}
// --------------------------------------------------- WDT ----------------------------------------------------------------
if (millis() - pwdt > 500) {
if (fwdt) {
//digitalWrite(33, HIGH);
fwdt = false;
pwdt = millis();
}
else {
//digitalWrite(33, LOW);
fwdt = true;
pwdt = millis();
}
}
M3:
// -------------------------------------------- LoRa ------------------------------------------------------------
Serial.println("1");
if (rf95.available()) {
delay(10);
rf95.recv((uint8_t*)data, sizeof(data));
if (data[0] + data[1] + data[2] + data[3] == data[4] && data[0] + data[1] + data[2] + data[3] != 0) { // проверка на отсутствие 0 приёма и на соответствие CRC
db1 = data[0];
db2 = data[1];
db3 = data[2];
db4 = data[3];
db5 = data[4];
olddata = millis();
fsd = true;
BanTM = true; // есть данные из бани
}
}
if (millis() - olddata > 60000 && fsd == true) {
BanTM = false; // нет данных из бани
fsd = false;
}
// -------------------------------------------------- SD карта ------------------------------------------------------------------------------
Serial.println("2");
//delay(10);
//if ((millis() - registr) > treg && m % 5 == 0) { // таймер для записи регистратора на 5 мин и кратно 5 мин.
if ((millis() - registr) > 10000) { // таймер для записи регистратора на 5 мин и кратно 5 мин.
String logStringData = ""; // формирование строки с данными
String Bm; // переменная для минут меньше 10, чтобы минуты на дисплее были с нулём
if (m < 10) {
Bm = "0" + String(m);
}
else {
Bm = String(m);
}
String Bh; // переменная для часов меньше 10, чтобы часы на дисплее были с нулём
if (h < 10) {
Bh = "0" + String(h);
}
else {
Bh = String(h);
}
// формируем строку с данными
logStringData = Bh + ":" + Bm + " > " + "Котёл " + d1 + "/" + d2 + "; ТП " + d5 + "/" + d6 + "; Бойл " + d7 + "; Давл.вс " + d8 / 10 + ","
+ (d8 - (d8 / 10) * 10) + "; Давл.от " + d9 / 10 + "," + (d9 - (d9 / 10) * 10) + ";" + "\n" + " Темп ул. " + toutside + "; Вл. "
+ hum + "; Давл. " + p + "; Темп. дом " + celsius1 + "; Темп. вход " + celsius2 + "; Темп. гараж " + d11 + "; Темп. кот. " + d10 + "; Темп. скв. " + d12 + ";";
//Serial.println(logStringData);
String DirectName = "20" + String(Y) + "/" + String(M); // Создаём имя папки из месяца и года
String logStringName = DirectName + "/" + String(d) + ".txt"; // формируем текстовый файл на один день максимум 12 знаков в названии файла
//Serial.println (logStringName);
if (SD.begin(47)) {
if (SD.mkdir(DirectName)) { // создаём на SD указанную территорию, может включать в себя вложенные папки, разделенные прямым слешем "/"
// Открываем файл, Если файла с таким именем не будет, ардуино создаст его.
File dataFile = SD.open(logStringName, FILE_WRITE);
// Если все хорошо, то записываем строку:
if (dataFile) {
dataFile.println(logStringData); // в файл записываем строку данных с переводом строки
dataFile.close(); // закрываем файл
SendDataP("page0.p1.pic", 3); // ЗЕЛЁНЫЙ значёк
Serial.println("Запись прошла на SD");
Zu = true; // флаг для печати нужного значка в цикле печати
}
else {
SendDataP("page0.p1.pic", 4); // КРАСНЫЙ значёк
Serial.println("Ошибка записи на SD!");
Zu = false; // флаг для печати нужного значка в цикле печати
}
registr = millis();
}
}
}
// -------------------------------------------------- Сеть ------------------------------------------------------------------
//Serial.println("3");
d9 = 16; // для отработки
d8 = 32;
html();
//Serial.println("4");
// -------------------------------------------------- ОСНОВНОЙ ЦИКЛ ------------------------------------------------
// --------------------------------------- влажность и температура с датчика влажности -----------------------------
//Serial.println("5");
if (millis() - dvtperiod > dvt) { // таймер для измерения температуры, давл. и влажности, dvt 5c\60c
tuprm = sht31.readTemperature(); //снятые с датчика значения вл и темп для работы с ними (float)
huprm = sht31.readHumidity();
if ((huprm - hgis > gis) || (hgis - huprm > gis)) { // проверка на гистерезис для влажности
hum = huprm;
if (huprm - hum >= 0.5) {
hum = hum + 1;
}
hgis = huprm;
}
if ((toutsidegis - tuprm > gis) || (tuprm - toutsidegis > gis) || (toutsidegis - tuprm < -gis) || (tuprm - toutsidegis < -gis)) { // проверка на гистерезис для температуры
toutside = tuprm;
if (tuprm - toutside >= 0.5) {
toutside = toutside + 1;
}
if (tuprm - toutside <= -0.5) {
toutside = toutside - 1;
}
toutsidegis = tuprm;
}
// --------------------------------------- давление -----------------------------------------------------------
sensor.read(1);
dvl = sensor.pressure;
if ((pgis - dvl > gis) || (dvl - pgis > gis)) {
p = dvl;
if (dvl - p >= 0.5) {
p = p + 1;
}
pgis = dvl;
}
//Serial.println("6");
// ------------------------------------- температура DS18B20 (дом) ---------------------------------------------
sensDs1.reset();
sensDs1.select(addr1);
sensDs1.write(0x44, 0); // инициализация измерения с первого датчика
sensDs2.reset();
sensDs2.select(addr2);
sensDs2.write(0x44, 0); // инициализация измерения с второго датчика
delay(300);
sensDs1.reset();
sensDs1.select(addr1);
sensDs1.write(0xBE, 0); // команда чтения памяти датчика
sensDs1.read_bytes(bufData1, 9); // чтение памяти датчика, 9 байтов
if ( OneWire::crc8(bufData1, 8) == bufData1[8] ) {
float cels1 = (float)((int)bufData1[0] | (((int)bufData1[1]) << 8)) * 0.0625;
celsius1 = cels1; // температура в доме
if ((cels1 - celsius1) >= 0.5) {
celsius1 = celsius1 + 1;
}
}
sensDs2.reset();
sensDs2.select(addr2);
sensDs2.write(0xBE, 0); // команда чтения памяти датчика
sensDs2.read_bytes(bufData2, 9); // чтение памяти датчика, 9 байтов
if ( OneWire::crc8(bufData2, 8) == bufData2[8] ) {
float cels2 = (float)((int)bufData2[0] | (((int)bufData2[1]) << 8)) * 0.0625;
celsius2 = cels2; // температура входа
if ((cels2 - celsius2) >= 0.5) {
celsius2 = celsius2 + 1;
}
}
dvtperiod = millis();
dvt = 5000; // установка таймера изм. темп, давления и влажности в 1 мин.
}// ----------------------------------------- конец ОСНОВНОГО цикла температуры, влажности ---------------------------------------
// ------------------------------------------------- SIM800 ---------------------------------------------------------------
//Serial.println("3");
//Serial3.println("AT+CSQ"); // ПРИ УРОВНЕ СИГНАЛА
if (Serial3.available()) {
delay(20);
char ch = ' ';
String val = "";
while (Serial3.available())
{
ch = Serial3.read();
val += char(ch); // собираем принятые символы в строку
delay(2);
}
//Serial.println(val); // ПРИ УРОВНЕ СИГНАЛА
if (val.indexOf("RING") > -1) { // если есть входящий вызов
if (val.indexOf("9122234744") > -1) {
SMSOUT = "+79122230000"; // мой номер
}
else {
if (val.indexOf("79121111111") > -1) {
SMSOUT = "+79122857000"; // другой номер
}
else {
if (val.indexOf("79121111111") > -1) {
SMSOUT = "+79122459000"; // другой номер
}
else {
Serial3.println("ATH"); // разрываем связь в случае "левого" звонка
goto M1;
}
}
}
Serial3.println("ATH"); // разрываем связь в случае одного из трёх звонков
delay(1000);
balans(); // запрос баланса
s1 = String(toutside); // строковая переменная с уличной температурой
s2 = String(hum); // строковая переменная с уличной влажностью
s3 = String(p); // строковая переменная с давлением
s4 = String(celsius1); // строковая переменная с температурой в доме
s5 = String(d11); // строковая переменная с температурой в гараже
s6 = String(d10); // строковая переменная с температурой в котельной
s7 = String(d12); // строковая переменная с температурой скважины
s8 = String(d1); // строковая переменная с температурой выхода из котла
s9 = String(d2); // строковая переменная с температурой входа в котёл (обратка)
s10 = String(d5); // строковая переменная с температурой выход на ТП
s11 = String(d6); // строковая переменная с температурой ТП обратка
s14 = String(d7); // строковая переменная с температурой бойлера
d81 = (d8 / 10); // формирование дробных переменных для давл. в.с.
d82 = (d8 - (d8 / 10) * 10); // формирование дробных переменных для давл. в.с.
d91 = (d9 / 10); // формирование дробных переменных для давл. отопл.
d92 = (d9 - (d9 / 10) * 10); // формирование дробных переменных для давл. отопл.
s151 = String(d81); // строковая переменная с давлением водоснабжения
s152 = String(d82); // строковая переменная с давлением водоснабжения
s161 = String(d91); // строковая переменная с давлением отопления
s162 = String(d92); // строковая переменная с давлением отопления
sms(String("Balans sim: " + ss1 + ss2 + ss3 + ss4 + ss5 + ss6 + ss7 + '\n' + '\n'
+ "Temp. ulica: " + s1 + '\n'
+ "Vlagnost ulica: " + s2 + "%" + '\n'
+ "Davlenie atm: " + s3 + "mm" + '\n' + '\n'
+ "Temp. dom: " + s4 + '\n'
+ "Temp. garag: " + s5 + '\n'
+ "Temp. kotelnay: " + s6 + '\n'
+ "Temp. skvagina: " + s7 + '\n' + '\n'
+ "Temp. kotel podacha: " + s8 + '\n'
+ "Temp. kotel vozvrat: " + s9 + '\n'
+ "Temp. TP podacha: " + s10 + '\n'
+ "Temp. TP vozvrat: " + s11 + '\n'
+ "Temp. boyler: " + s14 + '\n' + '\n'
+ "Davl. vodosn: " + s151 + "," + s152 + '\n'
+ "Davl. otopl: " + s161 + "," + s162), String(SMSOUT)); // номер на кот пойдет смс
}
if (val.indexOf("+CMT") > -1) { // если есть входящее смс
if (val.indexOf("9122230000") > -1) {
if (val.indexOf("Reset") > -1) {
EEPROM.write(10, 0); // сбросили тревогу
delay(5);
SendDataP("page0.tm5.en", 0); // остановили таймеры мигания "АВАРИИ" на дисплее
SendDataP("page0.tm6.en", 0);
SendDataP("page0.p0.pic", 10); // опять нарисовали "БАНЬКУ"
fa = true; // разрешили вновь сработку тревоги tm1.en=0
digitalWrite(62, HIGH); // аппаратный RESET
delay(500);
}
if (val.indexOf("S") > -1) { // смотрим время последней синхронизации с GPS, отправл. СМС
sms(String("Poslednyy sinhr: " + String(EEPROM.read(13)) + "." + String(EEPROM.read(12))
+ "." + String(EEPROM.read(11)) + " " + String(EEPROM.read(14))
+ ":" + String(EEPROM.read(15))), "+79122230000");
}
}
}
}
M1:
//----------------------------------------------- работа GPS модуля ----------------------------------------------------------------------
//Serial.println("8");
if (millis() - sinhr > mln) {
newdata = false;
start = millis();
while (millis() - start < 2000)
{
if (Serial1.available())
{
char c = Serial1.read(); // чтение массива, переданного NEO-6M
//Serial.print(c); // вывести на печать массив из NEO-6M
if (gps.encode(c)) // проверка данных на правильность
{
newdata = true;
break; // остановить цикл при нормальной декодировке
}
}
}
if (newdata)
{
getgps(gps); // при нормальной декодеровке уходим на выполнение getgps(TinyGPS &gps)
}
}
//d8 = 26; //
//d9 = 20; // отопл.
// --------------------------------- вывод на Nextion уличной температуры ------------------------------------------------
//Serial.println("9");
if ((millis() - nadisplei) > disp) {
if ((abs(tPred) == 10 && abs(toutside) == 9) || (tPred < 0 && toutside >= 0) || (toutside < 0 && tPred >= 0)) { // переход с двух разрядов температуры на один - очистка знакомест
SendDataP("q0.picc", 11); // очистка всей температуры
}
if (toutside < 0 && toutside > -10) { // ---- два разряда температуры ( -5 )
SendDataP("n29.picc", 11); // печать минуса
SendDataP("n32.val", abs(toutside));
SendDataP("t43.picc", 11); // печать градуса двух разрядов
}
if (toutside < 10 && toutside >= 0) { // ------------ один разряд температуры ( 8 )
SendDataP("n30.val", toutside);
SendDataP("t42.picc", 11); // печать градуса одного разряда
}
if (toutside <= -10) { // ------------ три разряда температуры ( -23 )
SendDataP("n0.val", abs(toutside)); // печать температуры
SendDataP("n31.picc", 11); // печать минуса
SendDataP("t0.picc", 11); // печать градуса одного разряда
}
if (toutside >= 10) { // ------------ три разряда температуры ( 40 )
SendDataP("n28.val", toutside); // печать температуры
SendDataP("t41.picc", 11); // печать градуса одного разряда
}
tPred = toutside;
// ---------------- печать ТМ параметров ------------------
//Serial.println("10");
SendDataP("n3.val", hum); // печать влажности
SendDataP("n4.val", p); // печать давления
SendDataP("n12.val", celsius1); // печать температуры в доме
SendDataP("page0.n14.val", d11); // печать температуры в гараже
SendDataP("page0.n15.val", d10); // печать температуры в котельной
SendDataP("page0.n16.val", d12); // печать температуры скважины
SendDataP("page0.n7.val", d1); // печать температуры котёл подача
SendDataP("page0.n8.val", d2); // печать температуры котёл обратка
SendDataP("page0.n21.val", d1 - d2); // печать дэльты температуры котла
SendDataP("page0.n9.val", d5); // печать температуры ТП подача
SendDataP("page0.n10.val", d6); // печать температуры ТП обратка
SendDataP("page0.n22.val", d5 - d6); // печать дэльты температуры ТП
SendDataP("page0.n11.val", d7); // печать температуры бойлера
SendDataP("page0.n23.val", d1 - d7); // печать дэльты температуры бойлера
SendDataP("page0.n17.val", d9 / 10); // печать целого давления отопления
SendDataP("page0.n19.val", d9 - (d9 / 10) * 10); // печать десяток давления отопления
SendDataP("page0.n18.val", d8 / 10); // печать целого давления водоснабжения
SendDataP("page0.n20.val", d8 - (d8 / 10) * 10); // печать десяток давления водоснабжения
SendDataP("page0.n13.val", celsius2); // печать температуры входа
if (BanTM) { // есть инфа с бани
SendDataP("page1.n7.val", db1); // печать температуры парной в бане
SendDataP("page1.n9.val", db2); // печать температуры комнаты в бане
SendDataP("page1.n8.val", db3); // печать температуры т.пола в бане
SendDataP("page1.t2.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t1.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t5.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t34.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t7.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t8.picc", 11); // рисуем надписи и градусы
if (db4 == 1) { // нагрев включен
SendDataP("page1.tm3.en", 1);
}
else { // нагрев выключен
SendDataP("page1.tm3.en", 0); // останавливаем таймеры "костра"
SendDataP("page1.tm4.en", 0);
SendDataP("page1.tm5.en", 0);
SendDataP("page1.tm6.en", 0);
SendDataP("page1.p3.pic", 12); // рисуем картинку "нагрев выключен"
}
}
else { // нет инфы с бани
SendDataP("page1.tm3.en", 0); // останавливаем таймеры "костра"
SendDataP("page1.tm4.en", 0);
SendDataP("page1.tm5.en", 0);
SendDataP("page1.tm6.en", 0);
SendDataP("page1.t9.picc", 11); // закрасили верх от "нагрев выключен"
SendDataP("page1.p4.pic", 16); // написали "нет данных" от бани
}
// ------------------------------------------------------ часы -------------------------------------------------------
Y = Clock.getYear(); // получение года из модуля часов DS3231
M = Clock.getMonth(Century); // получение месяца из модуля часов DS3231
d = Clock.getDate(); // получение дня из модуля часов DS3231
h = Clock.getHour(h12, PM); // получение часов из модуля часов DS3231
m = Clock.getMinute(); // получение минут из модуля часов DS3231
s = Clock.getSecond(); // получение секунд из модуля часов DS3231
// ---------------------------------- синхронизация часов и календаря с Nextion ------------------------------------
SendDataP("rtc0", 2000 + Y);
SendDataP("rtc1", M);
SendDataP("rtc2", d);
SendDataP("rtc3", h);
SendDataP("rtc4", m);
SendDataP("rtc5", s);
//Serial.println("11");
// ------------------------------------ печать значка SD-карты на дисплей -----------------------------------------
if (Zu) {
SendDataP("page0.p1.pic", 3); // ЗЕЛЁНЫЙ значёк
}
else {
SendDataP("page0.p1.pic", 4); // КРАСНЫЙ значёк
}
disp = 10000; // установка периода вывода на дисплей основной информации (10 сек)
nadisplei = millis();
} // -------------------------------------- конец печати на Nextion ----------------------------------------------------
// ---------------------------------------------------------------- авария ----------------------------------------------------------
d9 = 7;
d1 = 31;
if ((d9 < 6 || d1 < 30) && fa == true) { // условия аварии: давл отопл <0,6 Атм или темп выхода котла <30 градусов / флаг однократности сработки "Аварии"
}
else {
za = millis();
}
// при наступлении аварийного условия ждём минуту устоявшегося события (типа защита от "дребезга")
if ((millis() - za) > 10000) {
sms(String("AVARIY OTOPLENIY!"), String("+79122230000"));
EEPROM.write(10, 1); // записали аварию в память
delay(5);
SendDataP("page0.tm5.en", 1); // запустили таймеры "АВАРИИ" на Nextion
frchtd = true; // флаг разрешения чтения с дисплея "сброс аварии"
fa = false; // флаг однократности сработки "Аварии"
}
//Serial.println("12");
// ---------------------------------------- сброс тревоги и смена страницы (принимаем с Nextion) ----------------------------
if (Serial2.available()) {
delay (20);
i = 1;
val = 0;
while (Serial2.available()) {
ch = Serial2.read();
delay (2);
if (ch == 101) {
fscht = true; // разрешили счёт считываемых байт если передача началась со 101
}
if (i < 5 && fscht) {
val += ch; //собираем принятые символы в строку (4 байта всего): 173 - сброс аварии
i++;
}
}
//Serial.println(val);
if (val == 196 || val == 148) {
disp = 0; // разовый период вывода на дисплей
delay(100); // таймер пиканья на Nextion не даёт очистить знакоместо - ждём пока пикнет Nextion
nadisplei = millis();
SendDataP("q0.picc", 11); // очистка места температуры при переключении страницы
}
fscht = false; // закончили и опять разрешили счёт четырёх первых байт с дисплея
if (frchtd) { // разрешение сброса тревоги с дисплея
if ((val == 196 || val == 148) && EEPROM.read(10) == 1) { // приняли с дисплея "сброс аварии"
EEPROM.write(10, 0); // сбросили тревогу в ЕЕПРОМе
delay(5);
//Serial.println("сброс");
SendDataP("page0.tm5.en", 0); // остановили таймеры мигания "АВАРИИ" на дисплее
SendDataP("page0.tm6.en", 0);
SendDataP("page0.p0.pic", 10); // опять нарисовали "БАНЬКУ"
SendDataP("pio5", 0); // заткнули пищалку
fa = true; // разрешили вновь сработку тревоги
za = millis();
frchtd = false; // запретили читать "сброс" с дисплея, но чтение перекл страницы возможно
}
}
}
} // -------------------------- конец LOOP ------------------------------
// --------------------------------------------------------------------
//================================================================================================================================
//================================================================================================================================
// ----------------- подпрограмма вывода данных из gps и синхронизации модуля часов ---------------------
void getgps(TinyGPS & gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
// вынимание данных из массива, полученного из модуля gps
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
hour = hour + 5; // переделка час. пояса
if (hour > 23) // избежание 25, 26 часов на дисплее
{
hour = hour - 24;
}
if (hour > 0 && hour < 5) { // коррекция даты в зависимости от времени и час. пояса
day = day + 1; // от 0 до 5 утра синхронизируется ещё старая дата (по Гринвичу)
}
gps.get_datetime(&date, &time);
if (date == 0) { // проверка на "нулевую дату" (бывает такой косяк при синхр.)
mln = 60000; // при косячной дате период синхр. GPS - 1 минута
//Serial.println("Косячная дата! - нет синхронизации");
}
else {
setTime(hour, minute, second, day, month, year); // устанавливаем: часы, минуты, секунды, день, месяц, год)
RTC.set(now()); // применяем значение
// запись времени и даты последней синхронизации с GPS, можно вытащить смской "S"
EEPROM.write(11, 2000 + Y); // год
delay(5);
EEPROM.write(12, M); // месяц
delay(5);
EEPROM.write(13, d); // день
delay(5);
EEPROM.write(14, h); // часы
delay(5);
EEPROM.write(15, m); // минуты
delay(5);
//Serial.println("Дата норма!");
mln = 90000000; // при норм. дате период синхр. GPS - до след. перезагрузки устройства, для запаса 25 часов. (90000000)
}
sinhr = millis();
}
//=========================================== Подпрограмма посылки SMS ====================================
void sms(String text, String phone)
{
//Serial3.println("AT+CMGS=\"" + phone + "\"");
delay(1000);
Serial3.println(text);
delay(300);
Serial3.println((char)26);
delay(300);
Serial3.println("AT+CMGD=1,4");
delay(500);
}
// ============================= Подпрограмма отправки на Nextion =========================================
void SendDataP(String dev, int dataP) // для вывода картинок и чисел
{
Serial2.print(dev); // Отправляем данные dev(номер экрана, название переменной) на Nextion
Serial2.print("="); // Отправляем данные =(знак равно, далее передаем сами данные) на Nextion
Serial2.print(dataP); // Отправляем данные data(данные) на Nextion
Serial2.write(0xff); // Отправляем данные 0xff(значение показывающее Nextion конец передачи) на Nextion
Serial2.write(0xff); // Отправляем данные 0xff(значение показывающее Nextion конец передачи) на Nextion
Serial2.write(0xff); // Отправляем данные 0xff(значение показывающее Nextion конец передачи) на Nextion
dev = ""; // Очищаем переменную
}
// ============================= Подпрограмма получения баланса GSM =========================================
void balans() // получение баланса
{
Serial3.println("AT+CUSD=1,\"#100#\""); // запрос баланса
while (Serial3.available()) // очистка буфера
{
Serial3.read();
delay(2);
}
delay(7000);
if (Serial3.available()) { // задержка спец. не нужна - 7 сек. хватает
char ch = ' ';
String val = "";
while (Serial3.available())
{
ch = Serial3.read();
val += char(ch); //собираем принятые символы в строку
delay(3);
}
if (val.indexOf("+CUSD") > -1) {
char result1 = val.charAt(21); // для МТС\SIM800 21
char result2 = val.charAt(22);
char result3 = val.charAt(23);
char result4 = val.charAt(24);
char result5 = val.charAt(25);
char result6 = val.charAt(26);
char result7 = val.charAt(27);
ss1 = String(result1);
ss2 = String(result2);
ss3 = String(result3);
ss4 = String(result4);
ss5 = String(result5);
ss6 = String(result6);
ss7 = String(result7);
}
}
}
//=================================== Пишем страницу html ============================================
void html()
{
EthernetClient client = server.available();
if (client) {
//Serial.println("00");
float d8p = d8; // промежуточная переменная для индикации давления
d8p = d8p / 10;
float d9p = d9; // промежуточная переменная для индикации давления
d9p = d9p / 10;
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
//client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 15"); // обновление страницы через 60 сек
client.println();
//Serial.println("11");
client.println("<!DOCTYPE HTML>");
client.println("<html>"); //---------------------- Пишем страницу -------------
client.println("<head>");
client.println("<meta charset=\"UTF-8\">"); // Установка кодировки
client.println("<title>п.Залесье, ул.Осенняя, д.00</title>");
//Serial.println("22");
client.println("</head>");
if (millis() - swi < 60000) { //1800000 3600000 5400000 7200000 9000000 10800000 12600000 14400000
client.println("<body background=https://wmpics.pics/di-TW62.jpg><font color=\"WHITE\">"); // из мурманска в Питер
}
if (millis() - swi > 60000 && millis() - swi < 120000) {
client.println("<body background=https://wmpics.pics/di-EAI35.jpg><font color=\"WHITE\">"); // разлив Ишима
}
if (millis() - swi > 120000 && millis() - swi < 180000) {
client.println("<body background=https://wmpics.pics/di-M3D9.jpg><font color=\"WHITE\">"); // полуостров ночью
}
if (millis() - swi > 180000 && millis() - swi < 240000) {
client.println("<body background=https://wmpics.pics/di-7QFR2.jpg><font color=\"BLACK\">"); // Санрайз 2
}
if (millis() - swi > 240000 && millis() - swi < 300000) {
client.println("<body background=https://wmpics.pics/di-5QQV.jpg><font color=\"WHITE\">"); // Санрайз
}
if (millis() - swi > 300000 && millis() - swi < 360000) {
client.println("<body background=https://wmpics.pics/di-T3D0.jpg><font color=\"WHITE\">"); // в открытом море
}
if (millis() - swi > 360000 && millis() - swi < 420000) {
client.println("<body background=https://wmpics.pics/di-9GCF.jpg><font color=\"WHITE\">"); // колокольня в Калязине
}
if (millis() - swi > 420000 && millis() - swi < 480000) {
client.println("<body background=https://wmpics.pics/di-I4U1.jpg>"); // ромашковое поле
}
if (millis() - swi > 480000) {
swi = millis();
}
//Serial.println("23");
//client.println("<blockquote>");
client.println("<div style=\"position: absolute; top: 42px; left: 90px\">"); // блок Котельная
client.println("<h1>Котельная:</h1>");
client.println("<h2>Котёл подача: "); client.println(d1); client.println("°"); client.println("<br />");
client.println("Котёл возврат: "); client.println(d2); client.println("°"); client.println("<br />");
client.println("Тёплый пол подача:"); client.println(d5); client.println("<br />");
client.println("Тёплый пол возврат:"); client.println(d6); client.println("°"); client.println("<br />");
client.println("Бойлер:"); client.println(d7); client.println("°"); client.println("<br />");
client.println("Давление отопления:"); client.println(d9p); client.println("Bar."); client.println("<br />");
client.println("Давление водоснабж.:"); client.println(d8p); client.println("Bar."); client.println("<br />");
client.println("</h2></div>");
client.println("<div style=\"position: absolute; top: 42px; left: 500px\">"); // блок Температурные параметры
client.println("<h1>Температурные параметры:</h1>");
client.println("<h2>Температура на улице: "); client.println(toutside); client.println("°"); client.println("<br />");
client.println("Влажность: "); client.println(hum); client.println("%"); client.println("<br />");
client.println("Атмосф. давление:"); client.println(p); client.println("мм.рт.ст."); client.println("<br /><br />");
client.println("Дом:"); client.println(celsius1); client.println("°"); client.println("<br />");
client.println("Вход:"); client.println(celsius2); client.println("°"); client.println("<br />");
client.println("Гараж:"); client.println(d11); client.println("°"); client.println("<br />");
client.println("Котельная:"); client.println(d10); client.println("°"); client.println("<br />");
client.println("Скважина:"); client.println(d12); client.println("°"); client.println("</div>");
client.println("<div style=\"position: absolute; top: 42px; left: 980px\">"); // блок Баня
client.println("<h1>Баня:</h1>");
if (BanTM) {
client.println("<h2>Парная: "); client.println(db1); client.println("°"); client.println("<br />");
client.println("Комната: "); client.println(db2); client.println("°"); client.println("<br />");
client.println("Тёплый пол:"); client.println(db3); client.println("°"); client.println("<br />");
if (db4 != 0) {
client.println("<p><font color=\"red\">Нагрев включен</font></p>");
}
else {
client.println("<br />Нагрев выключен");
}
}
else {
client.println("<h2>Нет данных</h2>");
}
client.println("</div>");
client.println("<div style=\"position: absolute; top: 42px; left: 1230px\">"); // блок Расход фильтров
client.println("<h1>Фильтры:</h1>");
client.println("<h2>Мех.: "); client.println(" "); client.println(d12); client.println("%"); client.println("<br />");
client.println("Ca Mg: "); client.println(" "); client.println(d14); client.println("%"); client.println("<br />");
client.println("Fe:"); client.println(" "); client.println(d15); client.println("%"); client.println("<br />");
client.println("</div>");
if (frchtd) {
client.println("<div style=\"position: absolute; top: 420px; left: 400px\">"); // Авария
client.println("<h1><p><blink><font color=\"red\">АВАРИЯ! АВАРИЯ! АВАРИЯ! АВАРИЯ! АВАРИЯ!</font></blink></p></h1>"); client.println("</div>");
}
client.println("</html>"); //------------------------- Закончили страницу -------------------------------
//Serial.println("33");
delay(500);
client.stop();
//Serial.println("44");
Serial.println(millis());
}
}
Вот код, где отключено почти всё кроме обращения к трём модулям SPI. Всё равно виснет....
По одному работают нормально, два или три - виснет через несколько секунд или минут. Виснет на любом модуле, не на каком-то одном. Не понятно почему не сразу. Был бы аппаратный конфликт не работало бы вообще, а так - не ясно.
Может не успевает отключиться предыдущий модуль?
Проверял свободную память - 1607 байт свободно. Софт или железо всё-таки?...
Плата МЕГА 2560
#include <SD.h>
// при окончательной установке убрать коммент. "аварию отоления" 562 стр.
#include <RH_RF95.h>
#include <Adafruit_SHT31.h>
#include <EEPROM.h>
#include <TinyGPS.h>
#include <Ethernet2.h>
#include <Nextion.h>
#include <OneWire.h>
#include <DS1307RTC.h>
#include <DS3231.h>
#include <Time.h>
#include <SPI.h>
#include <iarduino_Pressure_BMP.h>
// ------------------------- сеть ---------------------------------
byte mac[] = {0x2C, 0xF7, 0xF1, 0x08, 0x00, 0x9A};
IPAddress ip(192, 168, 1, 6);
EthernetServer server(756);
// ------------------------- LoRa ---------------------------------
RH_RF95 rf95(48, 2); // (SS, interrupt) внимательно с выводом прерывания на Ардуине!
uint32_t data[5]; // Создаём массив для приёма данных - 32 разряда, тк передатчик DUE
// ------------------------- часы ---------------------------------
DS3231 Clock;
TinyGPS gps;
// ------------------------- давление -----------------------------
iarduino_Pressure_BMP sensor;
// ------------------------- влажность ----------------------------
Adafruit_SHT31 sht31 = Adafruit_SHT31();
// ------------------------- температура --------------------------
OneWire sensDs1(7); // датчик температуры подключен к выводу 7 дом
byte bufData1[9]; // буфер данных температуры в доме
byte addr1[8]; // массив адреса датчика темп. в доме
OneWire sensDs2(6); // датчик температуры подключен к выводу 6 вход
byte bufData2[9]; // буфер данных
byte addr2[8]; // массив адреса датчика
bool frchtd = false; // флаг разрешения чтения с дисплея "сброса"
bool newdata = false;
bool Century = false;
bool h12;
bool PM;
bool td = false; // флаг разрешения обработки данных датчика температуры в доме
bool fwdt = true; // флаг WDT
bool fsd = true; // флаг однократности вывода "данные устарели"
byte m, s, h, d, M; // переменные даты и времени
int Y = 2000;
bool fscht; // флаг разрешения суммирования при чтении с дисплея
bool BanTM = false; // флаг наличия данных из бани
bool Zu = false; // флаг печати значка SD-карты на дисплей
bool fp = false; // флаг разрешения сброса раз в сутки
bool fa = true; // флаг для однократности сработывания аварии
int celsius1, celsius2, celsius3; // температура в доме
float celsgis = 100; // промежуточная темп. для прохождения гистерезиса
int toutside = 0; // температура на улице с датчика влажности
int tPred; // переменная для проверки перехода с одного разряда на два и обратно при печати ул. температуры на дисплей
int p; // давление
int hum; // влажность на улице
int ch; // переменная для вычитывания буфера Nextion
int val; // строка из дисплея
int i;
float tuprm; // считанное значение уличной температуры
float huprm; // считанное значение уличной влажности
float dvl; // считанное значение атм. давления
bool gisalarm;
float toutsidegis = 100; // переменная для гистерезиса
unsigned long mln = 300000; // период синхронизации с GPS (сначала ч/з 5 минут (считывание альманаха при перв вкл, потом раз в 7 сут. (604800000)
unsigned long sinhr; // переменная в мсек задающ. период синхронизации
unsigned long za; // переменная в мсек задающ. задержку на сработывание аварии (2 мин, искл. ложных срабатываний)
unsigned long zadavar; // переменная в мсек задающ. период синхронизации
unsigned long start; // переменная в мсек задающ. цикл считывания данных gps
unsigned long registr; // переменная в мсек для таймера регистратора
unsigned long dvt = 3000; // период измерения давл. вл. и температуры (нач. 5 сек, потом раз в минуту)
unsigned long dvtperiod; // переменная в мсек для таймера измерен. давл.вл и у.темп.
unsigned long loraperiod; // переменная таймера проверки приёма LoRa
unsigned long swi = millis(); // перенная для смены фона на сайте ТМ данных
unsigned long treg = 290000; // период записи регистратора 5 мин (переменная на 10 сек меньше - догоняет остаток от деления =0)
unsigned long tperiod; // переменная в мсек для таймера обработки измерен. темп. в доме
unsigned long nadisplei; // переменная в мсек для таймера вывода на дисплей
unsigned long disp = 50; // период таймера вывода на дисплей, нач. 1 сек, потом 10 сек.
unsigned long olddata; // переменная
unsigned long pwdt; // переменная для WDT
unsigned long time, date; // переменные для считыв. даты и времени для вычисления "пустой" даты
float gis = 0.2; // гистерезис температуры и влажности
float pgis, hgis; // вспомогательная переменная для гистерезиса влажн. и давления
String pch; // переменная для вывода на дисплей
String SMSOUT; // текстовая переменная "номер для смс"
int db1; // темпеатура парной
int db2; // темпеатура комната бани
int db3; // темпеатура т. пола бани
int db4; // нагрев (0 - нет, 1 - нагрев)
int db5; // CRC с LoRa
int d1; // темпеатура выход котла К-->
int d2; // темпеатура вход котла (обратка) K<--
int d5; // темпеатура выход на ТП
int d6; // темпеатура вход с ТП (обратка)
int d7; // темпеатура бойлера
int d8; // давление системы водоснабжения
int d9; // давление системы отопления
int d81, d82, d91, d92; // промеж. параметры для отобр. гидро давления в СМС
int d10; // темпеатура в котельной
int d11; // темпеатура в гараже
int d12; // темпеатура скважины
int d13; // расход фильтра Мех.
int d14; // расход фильтра Ca Mg.
int d15; // расход фильтра Fe.
int d3, d4; // резерв
String(s1), (s2), (s3), (s4), (s5), (s6), (s7), (s8), (s9), (s10), (s11), (s12), (s13), (s14), (s15), (s16);
String(s151), (s152), (s161), (s162);
String(ss1), (ss2), (ss3), (ss4), (ss5), (ss6), (ss7);
int ttt;
// ------------------------------------------------------ setup --------------------------------------------------------------
void setup() {
Serial.begin(9600);
Serial1.begin(9600); // порт GPS
Serial2.begin(9600); // порт Nextion
Serial3.begin(9600); // порт SIM800
pinMode(48, OUTPUT); // CS LoRa
pinMode(49, OUTPUT); // CS W5500
pinMode(47, OUTPUT); // CS SD
pinMode(53, OUTPUT); // штатный CS не используется, но надо определить его
pinMode(33, OUTPUT); // выход на WDT
digitalWrite(47, HIGH);
digitalWrite(48, HIGH);
digitalWrite(49, HIGH);
digitalWrite(33, LOW);
setSyncProvider(RTC.get); // библиотечная команда извлечения данных из модуля часов
za = millis(); // переменная в мсек задающ. задержку на сработывание аварии (2 мин, искл. ложных срабатываний)
sinhr = millis(); // переменная в мсек для синхронизации по GPS
zadavar = millis(); // переменная задержки сработки АВАРИИ по давлению отопл. или t котла (на минуту после вкл. или сброса аварии)
registr = millis(); // переменная в мсек для таймера регистратора
dvtperiod = millis();
loraperiod = millis();
tperiod = millis(); // переменная в мсек для таймера изм. температуры
nadisplei = millis(); // переменная в мсек для таймера вывода на дисплей
olddata = millis(); // переменная для проверки новизны данных с котельной
pwdt = millis();
SendDataP("q0.picc", 11); // очистка уличной температуры
SendDataP("pio0", 0); // выключили сирену в Nextion
if (EEPROM.read(10) == 1) {
SendDataP("tm5.en", 1); // запустили тревогу на дисплее
frchtd = true; // разрешили чтение с дисплея "сброса"
}
else {
SendDataP("page0.tm5.en", 0); // остановили таймеры мигания "АВАРИИ" на дисплее
SendDataP("page0.tm6.en", 0);
SendDataP("page0.p0.pic", 10); // опять нарисовали "БАНЬКУ"
frchtd = false; // запретили чтение с дисплея "сброса"
}
SPI.begin;
SPI.setClockDivider(SPI_CLOCK_DIV4);
Ethernet.begin(mac, ip);
server.begin();
sensor.begin(); // инициализация датчика давления
sht31.begin(0x44); // инициализация датчика влажности
SD.begin(47); // инициализация модуля SD карты
rf95.init(); // инициализация SX1278
//rf95.setTxPower(5, false); // мощность 5 - 23, максимальная мощность (при 23) 100мВт (шаги с 5 по 23 не подряд! смотреть в библиотеке)
//void clearRxBuf();
sensDs1.search(addr1); // поиск и запись адреса датчика температуры
sensDs1.write(0x4E); // разрешение записи 3-х байт в DS18B20 (предустановка)
sensDs1.write(0x7F); // TH
sensDs1.write(0xFF); // TL
sensDs1.write(0x20); // регистр конфигурации (разрешение: 0х00-0.5 0х20-0.25 0х40-0.125 0х60-0.0625)
sensDs2.search(addr2); // поиск и запись адреса датчика температуры
sensDs2.write(0x4E); // разрешение записи 3-х байт в DS18B20 (предустановка)
sensDs2.write(0x7F); // TH
sensDs2.write(0xFF); // TL
sensDs2.write(0x20); // регистр конфигурации (разрешение: 0х00-0.5 0х20-0.25 0х40-0.125 0х60-0.0625)
Serial3.println("AT+IPR=9600"); // скорость модема
delay(200);
//Serial3.println("AT+CSQ"); // уровень сигнала // ПРИ УРОВНЕ СИГНАЛА
//delay(500);
Serial3.println("AT+CLIP=1"); // включить АОН
delay(200);
Serial3.println("AT+CMGF=1"); // текстовый формат SMS
delay(200);
Serial3.println("AT+CSCS=\"GSM\""); // кодировка текста - GSM
delay(200);
Serial3.println("AT+CMGD=1,4"); // удалить все смс
delay(200);
Serial3.println("AT+CNMI=2,2,0,0,0"); // вывод смс в консоль
delay(200);
Serial3.println("AT&W"); // запомнить настройки
delay(200);
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
// ==========================================================================================================================
// ============================================================ L O O P =====================================================
void loop() {
//Serial.println("1");
//Serial.println(millis());
ttt++;
if (ttt == 1000) {
Serial.println(millis());
ttt = 0;
}
/*
// --------------------------------------- суточный брос ------------------------------------------------------------------
if (h == 10 && m == 6 && fp == true) { // RESET в 10 часов 06 минут каждый день
goto M3; // для сут. сброса нет стробов WDT
}
if (m == 8) {
fp = true;
}
// --------------------------------------------------- WDT ----------------------------------------------------------------
if (millis() - pwdt > 500) {
if (fwdt) {
//digitalWrite(33, HIGH);
fwdt = false;
pwdt = millis();
}
else {
//digitalWrite(33, LOW);
fwdt = true;
pwdt = millis();
}
}
M3:
*/
// -------------------------------------------- LoRa ------------------------------------------------------------
Serial.println("1");
if (rf95.available()) {
rf95.recv((uint8_t*)data, sizeof(data));
if (data[0] + data[1] + data[2] + data[3] == data[4] && data[0] + data[1] + data[2] + data[3] != 0) { // проверка на отсутствие 0 приёма и на соответствие CRC
db1 = data[0];
db2 = data[1];
db3 = data[2];
db4 = data[3];
db5 = data[4];
olddata = millis();
fsd = true;
BanTM = true; // есть данные из бани
}
}
if (millis() - olddata > 60000 && fsd == true) {
BanTM = false; // нет данных из бани
fsd = false;
}
// -------------------------------------------------- SD карта ------------------------------------------------------------------------------
Serial.println("2");
//delay(10);
SDcard();
// -------------------------------------------------- Сеть ------------------------------------------------------------------
Serial.println("3");
d9 = 16; // для отработки
d8 = 38;
html();
Serial.println("4");
/*
// -------------------------------------------------- ОСНОВНОЙ ЦИКЛ ------------------------------------------------
// --------------------------------------- влажность и температура с датчика влажности -----------------------------
//Serial.println("5");
if (millis() - dvtperiod > dvt) { // таймер для измерения температуры, давл. и влажности, dvt 5c\60c
tuprm = sht31.readTemperature(); //снятые с датчика значения вл и темп для работы с ними (float)
huprm = sht31.readHumidity();
if ((huprm - hgis > gis) || (hgis - huprm > gis)) { // проверка на гистерезис для влажности
hum = huprm;
if (huprm - hum >= 0.5) {
hum = hum + 1;
}
hgis = huprm;
}
if ((toutsidegis - tuprm > gis) || (tuprm - toutsidegis > gis) || (toutsidegis - tuprm < -gis) || (tuprm - toutsidegis < -gis)) { // проверка на гистерезис для температуры
toutside = tuprm;
if (tuprm - toutside >= 0.5) {
toutside = toutside + 1;
}
if (tuprm - toutside <= -0.5) {
toutside = toutside - 1;
}
toutsidegis = tuprm;
}
// --------------------------------------- давление -----------------------------------------------------------
sensor.read(1);
dvl = sensor.pressure;
if ((pgis - dvl > gis) || (dvl - pgis > gis)) {
p = dvl;
if (dvl - p >= 0.5) {
p = p + 1;
}
pgis = dvl;
}
//Serial.println("6");
// ------------------------------------- температура DS18B20 (дом) ---------------------------------------------
sensDs1.reset();
sensDs1.select(addr1);
sensDs1.write(0x44, 0); // инициализация измерения с первого датчика
sensDs2.reset();
sensDs2.select(addr2);
sensDs2.write(0x44, 0); // инициализация измерения с второго датчика
delay(100);
sensDs1.reset();
sensDs1.select(addr1);
sensDs1.write(0xBE, 0); // команда чтения памяти датчика
sensDs1.read_bytes(bufData1, 9); // чтение памяти датчика, 9 байтов
if ( OneWire::crc8(bufData1, 8) == bufData1[8] ) {
float cels1 = (float)((int)bufData1[0] | (((int)bufData1[1]) << 8)) * 0.0625;
celsius1 = cels1; // температура в доме
if ((cels1 - celsius1) >= 0.5) {
celsius1 = celsius1 + 1;
}
}
sensDs2.reset();
sensDs2.select(addr2);
sensDs2.write(0xBE, 0); // команда чтения памяти датчика
sensDs2.read_bytes(bufData2, 9); // чтение памяти датчика, 9 байтов
if ( OneWire::crc8(bufData2, 8) == bufData2[8] ) {
float cels2 = (float)((int)bufData2[0] | (((int)bufData2[1]) << 8)) * 0.0625;
celsius2 = cels2; // температура входа
if ((cels2 - celsius2) >= 0.5) {
celsius2 = celsius2 + 1;
}
}
dvtperiod = millis();
dvt = 5000; // установка таймера изм. темп, давления и влажности в 1 мин.
}// ----------------------------------------- конец ОСНОВНОГО цикла температуры, влажности ---------------------------------------
// ------------------------------------------------- SIM800 ---------------------------------------------------------------
//Serial.println("3");
//Serial3.println("AT+CSQ"); // ПРИ УРОВНЕ СИГНАЛА
if (Serial3.available()) {
delay(20);
char ch = ' ';
String val = "";
while (Serial3.available())
{
ch = Serial3.read();
val += char(ch); // собираем принятые символы в строку
delay(2);
}
//Serial.println(val); // ПРИ УРОВНЕ СИГНАЛА
if (val.indexOf("RING") > -1) { // если есть входящий вызов
if (val.indexOf("9122234744") > -1) {
SMSOUT = "+79122230000"; // мой номер
}
else {
if (val.indexOf("79121111111") > -1) {
SMSOUT = "+79122857000"; // другой номер
}
else {
if (val.indexOf("79121111111") > -1) {
SMSOUT = "+79122459000"; // другой номер
}
else {
Serial3.println("ATH"); // разрываем связь в случае "левого" звонка
goto M1;
}
}
}
Serial3.println("ATH"); // разрываем связь в случае одного из трёх звонков
delay(1000);
balans(); // запрос баланса
s1 = String(toutside); // строковая переменная с уличной температурой
s2 = String(hum); // строковая переменная с уличной влажностью
s3 = String(p); // строковая переменная с давлением
s4 = String(celsius1); // строковая переменная с температурой в доме
s5 = String(d11); // строковая переменная с температурой в гараже
s6 = String(d10); // строковая переменная с температурой в котельной
s7 = String(d12); // строковая переменная с температурой скважины
s8 = String(d1); // строковая переменная с температурой выхода из котла
s9 = String(d2); // строковая переменная с температурой входа в котёл (обратка)
s10 = String(d5); // строковая переменная с температурой выход на ТП
s11 = String(d6); // строковая переменная с температурой ТП обратка
s14 = String(d7); // строковая переменная с температурой бойлера
d81 = (d8 / 10); // формирование дробных переменных для давл. в.с.
d82 = (d8 - (d8 / 10) * 10); // формирование дробных переменных для давл. в.с.
d91 = (d9 / 10); // формирование дробных переменных для давл. отопл.
d92 = (d9 - (d9 / 10) * 10); // формирование дробных переменных для давл. отопл.
s151 = String(d81); // строковая переменная с давлением водоснабжения
s152 = String(d82); // строковая переменная с давлением водоснабжения
s161 = String(d91); // строковая переменная с давлением отопления
s162 = String(d92); // строковая переменная с давлением отопления
sms(String("Balans sim: " + ss1 + ss2 + ss3 + ss4 + ss5 + ss6 + ss7 + '\n' + '\n'
+ "Temp. ulica: " + s1 + '\n'
+ "Vlagnost ulica: " + s2 + "%" + '\n'
+ "Davlenie atm: " + s3 + "mm" + '\n' + '\n'
+ "Temp. dom: " + s4 + '\n'
+ "Temp. garag: " + s5 + '\n'
+ "Temp. kotelnay: " + s6 + '\n'
+ "Temp. skvagina: " + s7 + '\n' + '\n'
+ "Temp. kotel podacha: " + s8 + '\n'
+ "Temp. kotel vozvrat: " + s9 + '\n'
+ "Temp. TP podacha: " + s10 + '\n'
+ "Temp. TP vozvrat: " + s11 + '\n'
+ "Temp. boyler: " + s14 + '\n' + '\n'
+ "Davl. vodosn: " + s151 + "," + s152 + '\n'
+ "Davl. otopl: " + s161 + "," + s162), String(SMSOUT)); // номер на кот пойдет смс
}
if (val.indexOf("+CMT") > -1) { // если есть входящее смс
if (val.indexOf("9122230000") > -1) {
if (val.indexOf("Reset") > -1) {
EEPROM.write(10, 0); // сбросили тревогу
delay(5);
SendDataP("page0.tm5.en", 0); // остановили таймеры мигания "АВАРИИ" на дисплее
SendDataP("page0.tm6.en", 0);
SendDataP("page0.p0.pic", 10); // опять нарисовали "БАНЬКУ"
fa = true; // разрешили вновь сработку тревоги tm1.en=0
digitalWrite(62, HIGH); // аппаратный RESET
delay(500);
}
if (val.indexOf("S") > -1) { // смотрим время последней синхронизации с GPS, отправл. СМС
sms(String("Poslednyy sinhr: " + String(EEPROM.read(13)) + "." + String(EEPROM.read(12))
+ "." + String(EEPROM.read(11)) + " " + String(EEPROM.read(14))
+ ":" + String(EEPROM.read(15))), "+79122230000");
}
}
}
}
M1:
//----------------------------------------------- работа GPS модуля ----------------------------------------------------------------------
//Serial.println("8");
if (millis() - sinhr > mln) {
newdata = false;
start = millis();
while (millis() - start < 2000)
{
if (Serial1.available())
{
char c = Serial1.read(); // чтение массива, переданного NEO-6M
//Serial.print(c); // вывести на печать массив из NEO-6M
if (gps.encode(c)) // проверка данных на правильность
{
newdata = true;
break; // остановить цикл при нормальной декодировке
}
}
}
if (newdata)
{
getgps(gps); // при нормальной декодеровке уходим на выполнение getgps(TinyGPS &gps)
}
}
//d8 = 26; //
//d9 = 20; // отопл.
// --------------------------------- вывод на Nextion уличной температуры ------------------------------------------------
//Serial.println("9");
if ((millis() - nadisplei) > disp) {
if ((abs(tPred) == 10 && abs(toutside) == 9) || (tPred < 0 && toutside >= 0) || (toutside < 0 && tPred >= 0)) { // переход с двух разрядов температуры на один - очистка знакомест
SendDataP("q0.picc", 11); // очистка всей температуры
}
if (toutside < 0 && toutside > -10) { // ---- два разряда температуры ( -5 )
SendDataP("n29.picc", 11); // печать минуса
SendDataP("n32.val", abs(toutside));
SendDataP("t43.picc", 11); // печать градуса двух разрядов
}
if (toutside < 10 && toutside >= 0) { // ------------ один разряд температуры ( 8 )
SendDataP("n30.val", toutside);
SendDataP("t42.picc", 11); // печать градуса одного разряда
}
if (toutside <= -10) { // ------------ три разряда температуры ( -23 )
SendDataP("n0.val", abs(toutside)); // печать температуры
SendDataP("n31.picc", 11); // печать минуса
SendDataP("t0.picc", 11); // печать градуса одного разряда
}
if (toutside >= 10) { // ------------ три разряда температуры ( 40 )
SendDataP("n28.val", toutside); // печать температуры
SendDataP("t41.picc", 11); // печать градуса одного разряда
}
tPred = toutside;
// ---------------- печать ТМ параметров ------------------
//Serial.println("10");
SendDataP("n3.val", hum); // печать влажности
SendDataP("n4.val", p); // печать давления
SendDataP("n12.val", celsius1); // печать температуры в доме
SendDataP("page0.n14.val", d11); // печать температуры в гараже
SendDataP("page0.n15.val", d10); // печать температуры в котельной
SendDataP("page0.n16.val", d12); // печать температуры скважины
SendDataP("page0.n7.val", d1); // печать температуры котёл подача
SendDataP("page0.n8.val", d2); // печать температуры котёл обратка
SendDataP("page0.n21.val", d1 - d2); // печать дэльты температуры котла
SendDataP("page0.n9.val", d5); // печать температуры ТП подача
SendDataP("page0.n10.val", d6); // печать температуры ТП обратка
SendDataP("page0.n22.val", d5 - d6); // печать дэльты температуры ТП
SendDataP("page0.n11.val", d7); // печать температуры бойлера
SendDataP("page0.n23.val", d1 - d7); // печать дэльты температуры бойлера
SendDataP("page0.n17.val", d9 / 10); // печать целого давления отопления
SendDataP("page0.n19.val", d9 - (d9 / 10) * 10); // печать десяток давления отопления
SendDataP("page0.n18.val", d8 / 10); // печать целого давления водоснабжения
SendDataP("page0.n20.val", d8 - (d8 / 10) * 10); // печать десяток давления водоснабжения
SendDataP("page0.n13.val", celsius2); // печать температуры входа
if (BanTM) { // есть инфа с бани
SendDataP("page1.n7.val", db1); // печать температуры парной в бане
SendDataP("page1.n9.val", db2); // печать температуры комнаты в бане
SendDataP("page1.n8.val", db3); // печать температуры т.пола в бане
SendDataP("page1.t2.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t1.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t5.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t34.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t7.picc", 11); // рисуем надписи и градусы
SendDataP("page1.t8.picc", 11); // рисуем надписи и градусы
if (db4 == 1) { // нагрев включен
SendDataP("page1.tm3.en", 1);
}
else { // нагрев выключен
SendDataP("page1.tm3.en", 0); // останавливаем таймеры "костра"
SendDataP("page1.tm4.en", 0);
SendDataP("page1.tm5.en", 0);
SendDataP("page1.tm6.en", 0);
SendDataP("page1.p3.pic", 12); // рисуем картинку "нагрев выключен"
}
}
else { // нет инфы с бани
SendDataP("page1.tm3.en", 0); // останавливаем таймеры "костра"
SendDataP("page1.tm4.en", 0);
SendDataP("page1.tm5.en", 0);
SendDataP("page1.tm6.en", 0);
SendDataP("page1.t9.picc", 11); // закрасили верх от "нагрев выключен"
SendDataP("page1.p4.pic", 16); // написали "нет данных" от бани
}
// ------------------------------------------------------ часы -------------------------------------------------------
Y = Clock.getYear(); // получение года из модуля часов DS3231
M = Clock.getMonth(Century); // получение месяца из модуля часов DS3231
d = Clock.getDate(); // получение дня из модуля часов DS3231
h = Clock.getHour(h12, PM); // получение часов из модуля часов DS3231
m = Clock.getMinute(); // получение минут из модуля часов DS3231
s = Clock.getSecond(); // получение секунд из модуля часов DS3231
// ---------------------------------- синхронизация часов и календаря с Nextion ------------------------------------
SendDataP("rtc0", 2000 + Y);
SendDataP("rtc1", M);
SendDataP("rtc2", d);
SendDataP("rtc3", h);
SendDataP("rtc4", m);
SendDataP("rtc5", s);
//Serial.println("11");
// ------------------------------------ печать значка SD-карты на дисплей -----------------------------------------
if (Zu) {
SendDataP("page0.p1.pic", 3); // ЗЕЛЁНЫЙ значёк
}
else {
SendDataP("page0.p1.pic", 4); // КРАСНЫЙ значёк
}
disp = 10000; // установка периода вывода на дисплей основной информации (10 сек)
nadisplei = millis();
} // -------------------------------------- конец печати на Nextion ----------------------------------------------------
// ---------------------------------------------------------------- авария ----------------------------------------------------------
d9 = 7;
d1 = 31;
if ((d9 < 6 || d1 < 30) && fa == true) { // условия аварии: давл отопл <0,6 Атм или темп выхода котла <30 градусов / флаг однократности сработки "Аварии"
}
else {
za = millis();
}
// при наступлении аварийного условия ждём минуту устоявшегося события (типа защита от "дребезга")
if ((millis() - za) > 10000) {
sms(String("AVARIY OTOPLENIY!"), String("+79122230000"));
EEPROM.write(10, 1); // записали аварию в память
delay(5);
SendDataP("page0.tm5.en", 1); // запустили таймеры "АВАРИИ" на Nextion
frchtd = true; // флаг разрешения чтения с дисплея "сброс аварии"
fa = false; // флаг однократности сработки "Аварии"
}
//Serial.println("12");
// ---------------------------------------- сброс тревоги и смена страницы (принимаем с Nextion) ----------------------------
if (Serial2.available()) {
delay (20);
i = 1;
val = 0;
while (Serial2.available()) {
ch = Serial2.read();
delay (2);
if (ch == 101) {
fscht = true; // разрешили счёт считываемых байт если передача началась со 101
}
if (i < 5 && fscht) {
val += ch; //собираем принятые символы в строку (4 байта всего): 173 - сброс аварии
i++;
}
}
//Serial.println(val);
if (val == 196 || val == 148) {
disp = 0; // разовый период вывода на дисплей
delay(100); // таймер пиканья на Nextion не даёт очистить знакоместо - ждём пока пикнет Nextion
nadisplei = millis();
SendDataP("q0.picc", 11); // очистка места температуры при переключении страницы
}
fscht = false; // закончили и опять разрешили счёт четырёх первых байт с дисплея
if (frchtd) { // разрешение сброса тревоги с дисплея
if ((val == 196 || val == 148) && EEPROM.read(10) == 1) { // приняли с дисплея "сброс аварии"
EEPROM.write(10, 0); // сбросили тревогу в ЕЕПРОМе
delay(5);
//Serial.println("сброс");
SendDataP("page0.tm5.en", 0); // остановили таймеры мигания "АВАРИИ" на дисплее
SendDataP("page0.tm6.en", 0);
SendDataP("page0.p0.pic", 10); // опять нарисовали "БАНЬКУ"
SendDataP("pio5", 0); // заткнули пищалку
fa = true; // разрешили вновь сработку тревоги
za = millis();
frchtd = false; // запретили читать "сброс" с дисплея, но чтение перекл страницы возможно
}
}
}
*/
} // -------------------------- конец LOOP ------------------------------
// --------------------------------------------------------------------
//================================================================================================================================
//================================================================================================================================
// ----------------- подпрограмма вывода данных из gps и синхронизации модуля часов ---------------------
/*
void getgps(TinyGPS & gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
// вынимание данных из массива, полученного из модуля gps
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
hour = hour + 5; // переделка час. пояса
if (hour > 23) // избежание 25, 26 часов на дисплее
{
hour = hour - 24;
}
if (hour > 0 && hour < 5) { // коррекция даты в зависимости от времени и час. пояса
day = day + 1; // от 0 до 5 утра синхронизируется ещё старая дата (по Гринвичу)
}
gps.get_datetime(&date, &time);
if (date == 0) { // проверка на "нулевую дату" (бывает такой косяк при синхр.)
mln = 60000; // при косячной дате период синхр. GPS - 1 минута
//Serial.println("Косячная дата! - нет синхронизации");
}
else {
setTime(hour, minute, second, day, month, year); // устанавливаем: часы, минуты, секунды, день, месяц, год)
RTC.set(now()); // применяем значение
// запись времени и даты последней синхронизации с GPS, можно вытащить смской "S"
EEPROM.write(11, 2000 + Y); // год
delay(5);
EEPROM.write(12, M); // месяц
delay(5);
EEPROM.write(13, d); // день
delay(5);
EEPROM.write(14, h); // часы
delay(5);
EEPROM.write(15, m); // минуты
delay(5);
//Serial.println("Дата норма!");
mln = 90000000; // при норм. дате период синхр. GPS - до след. перезагрузки устройства, для запаса 25 часов. (90000000)
}
sinhr = millis();
}
*/
//=========================================== Подпрограмма посылки SMS ====================================
/*
void sms(String text, String phone)
{
//Serial3.println("AT+CMGS=\"" + phone + "\"");
delay(1000);
Serial3.println(text);
delay(300);
Serial3.println((char)26);
delay(300);
Serial3.println("AT+CMGD=1,4");
delay(500);
}
*/
// ============================= Подпрограмма отправки на Nextion =========================================
void SendDataP(String dev, int dataP) // для вывода картинок и чисел
{
Serial2.print(dev); // Отправляем данные dev(номер экрана, название переменной) на Nextion
Serial2.print("="); // Отправляем данные =(знак равно, далее передаем сами данные) на Nextion
Serial2.print(dataP); // Отправляем данные data(данные) на Nextion
Serial2.write(0xff); // Отправляем данные 0xff(значение показывающее Nextion конец передачи) на Nextion
Serial2.write(0xff); // Отправляем данные 0xff(значение показывающее Nextion конец передачи) на Nextion
Serial2.write(0xff); // Отправляем данные 0xff(значение показывающее Nextion конец передачи) на Nextion
dev = ""; // Очищаем переменную
}
// ============================= Подпрограмма получения баланса GSM =========================================
/*
void balans() // получение баланса
{
Serial3.println("AT+CUSD=1,\"#100#\""); // запрос баланса
while (Serial3.available()) // очистка буфера
{
Serial3.read();
delay(2);
}
delay(7000);
if (Serial3.available()) { // задержка спец. не нужна - 7 сек. хватает
char ch = ' ';
String val = "";
while (Serial3.available())
{
ch = Serial3.read();
val += char(ch); //собираем принятые символы в строку
delay(3);
}
if (val.indexOf("+CUSD") > -1) {
char result1 = val.charAt(21); // для МТС\SIM800 21
char result2 = val.charAt(22);
char result3 = val.charAt(23);
char result4 = val.charAt(24);
char result5 = val.charAt(25);
char result6 = val.charAt(26);
char result7 = val.charAt(27);
ss1 = String(result1);
ss2 = String(result2);
ss3 = String(result3);
ss4 = String(result4);
ss5 = String(result5);
ss6 = String(result6);
ss7 = String(result7);
}
}
}
*/
//=================================== Пишем страницу html ============================================
void html()
{
EthernetClient client = server.available();
if (client) {
float d8p = d8; // промежуточная переменная для индикации давления
d8p = d8p / 10;
float d9p = d9; // промежуточная переменная для индикации давления
d9p = d9p / 10;
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 15"); // обновление страницы через 60 сек
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>"); //------------------------------------- Пишем страницу ------------------------------------
client.println("<head>");
client.println("<meta charset=\"UTF-8\">"); // Установка кодировки
client.println("<title>п.Залесье, ул.Осенняя, д.00</title>");
client.println("</head>");
if (millis() - swi < 60000) { //1800000 3600000 5400000 7200000 9000000 10800000 12600000 14400000
client.println("<body background=https://wmpics.pics/di-TW62.jpg><font color=\"WHITE\">"); // из мурманска в Питер
}
if (millis() - swi > 60000 && millis() - swi < 120000) {
client.println("<body background=https://wmpics.pics/di-EAI35.jpg><font color=\"WHITE\">"); // разлив Ишима
}
if (millis() - swi > 120000 && millis() - swi < 180000) {
client.println("<body background=https://wmpics.pics/di-M3D9.jpg><font color=\"WHITE\">"); // полуостров ночью
}
if (millis() - swi > 180000 && millis() - swi < 240000) {
client.println("<body background=https://wmpics.pics/di-7QFR2.jpg><font color=\"BLACK\">"); // Санрайз 2
}
if (millis() - swi > 240000 && millis() - swi < 300000) {
client.println("<body background=https://wmpics.pics/di-5QQV.jpg><font color=\"WHITE\">"); // Санрайз
}
if (millis() - swi > 300000 && millis() - swi < 360000) {
client.println("<body background=https://wmpics.pics/di-T3D0.jpg><font color=\"WHITE\">"); // в открытом море
}
if (millis() - swi > 360000 && millis() - swi < 420000) {
client.println("<body background=https://wmpics.pics/di-9GCF.jpg><font color=\"WHITE\">"); // колокольня в Калязине
}
if (millis() - swi > 420000 && millis() - swi < 480000) {
client.println("<body background=https://wmpics.pics/di-I4U1.jpg>"); // ромашковое поле
}
if (millis() - swi > 480000) {
swi = millis();
}
//Serial.println("23");
//client.println("<blockquote>");
client.println("<div style=\"position: absolute; top: 42px; left: 90px\">"); // блок Котельная
client.println("<h1>Котельная:</h1>");
client.println("<h2>Котёл подача: "); client.println(d1); client.println("°"); client.println("<br />");
client.println("Котёл возврат: "); client.println(d2); client.println("°"); client.println("<br />");
client.println("Тёплый пол подача:"); client.println(d5); client.println("<br />");
client.println("Тёплый пол возврат:"); client.println(d6); client.println("°"); client.println("<br />");
client.println("Бойлер:"); client.println(d7); client.println("°"); client.println("<br />");
client.println("Давление отопления:"); client.println(d9p); client.println("Bar."); client.println("<br />");
client.println("Давление водоснабж.:"); client.println(d8p); client.println("Bar."); client.println("<br />");
client.println("</h2></div>");
client.println("<div style=\"position: absolute; top: 42px; left: 500px\">"); // блок Температурные параметры
client.println("<h1>Температурные параметры:</h1>");
client.println("<h2>Температура на улице: "); client.println(toutside); client.println("°"); client.println("<br />");
client.println("Влажность: "); client.println(hum); client.println("%"); client.println("<br />");
client.println("Атмосф. давление:"); client.println(p); client.println("мм.рт.ст."); client.println("<br /><br />");
client.println("Дом:"); client.println(celsius1); client.println("°"); client.println("<br />");
client.println("Вход:"); client.println(celsius2); client.println("°"); client.println("<br />");
client.println("Гараж:"); client.println(d11); client.println("°"); client.println("<br />");
client.println("Котельная:"); client.println(d10); client.println("°"); client.println("<br />");
client.println("Скважина:"); client.println(d12); client.println("°"); client.println("</div>");
client.println("<div style=\"position: absolute; top: 42px; left: 980px\">"); // блок Баня
client.println("<h1>Баня:</h1>");
if (BanTM) {
client.println("<h2>Парная: "); client.println(db1); client.println("°"); client.println("<br />");
client.println("Комната: "); client.println(db2); client.println("°"); client.println("<br />");
client.println("Тёплый пол:"); client.println(db3); client.println("°"); client.println("<br />");
if (db4 != 0) {
client.println("<p><font color=\"red\">Нагрев включен</font></p>");
}
else {
client.println("<br />Нагрев выключен");
}
}
else {
client.println("<h2>Нет данных</h2>");
}
client.println("</div>");
client.println("<div style=\"position: absolute; top: 42px; left: 1230px\">"); // блок Расход фильтров
client.println("<h1>Фильтры:</h1>");
client.println("<h2>Мех.: "); client.println(" "); client.println(d12); client.println("%"); client.println("<br />");
client.println("Ca Mg: "); client.println(" "); client.println(d14); client.println("%"); client.println("<br />");
client.println("Fe:"); client.println(" "); client.println(d15); client.println("%"); client.println("<br />");
client.println("</div>");
if (frchtd) {
client.println("<div style=\"position: absolute; top: 420px; left: 400px\">"); // Авария
client.println("<h1><p><blink><font color=\"red\">АВАРИЯ! АВАРИЯ! АВАРИЯ! АВАРИЯ! АВАРИЯ!</font></blink></p></h1>"); client.println("</div>");
}
client.println("</html>"); //------------------------- Закончили страницу -------------------------------
delay(50);
client.stop();
Serial.println(millis());
}
}
// -------------------------------------------------- SD карта ------------------------------------------------------------------------------
void SDcard()
{
//delay(10);
//if ((millis() - registr) > treg && m % 5 == 0) { // таймер для записи регистратора на 5 мин и кратно 5 мин.
if ((millis() - registr) > 10000) { // таймер для записи регистратора на 5 мин и кратно 5 мин.
String logStringData = ""; // формирование строки с данными
String Bm; // переменная для минут меньше 10, чтобы минуты на дисплее были с нулём
if (m < 10) {
Bm = "0" + String(m);
}
else {
Bm = String(m);
}
String Bh; // переменная для часов меньше 10, чтобы часы на дисплее были с нулём
if (h < 10) {
Bh = "0" + String(h);
}
else {
Bh = String(h);
}
// формируем строку с данными
logStringData = Bh + ":" + Bm + " > " + "Котёл " + d1 + "/" + d2 + "; ТП " + d5 + "/" + d6 + "; Бойл " + d7 + "; Давл.вс " + d8 / 10 + ","
+ (d8 - (d8 / 10) * 10) + "; Давл.от " + d9 / 10 + "," + (d9 - (d9 / 10) * 10) + ";" + "\n" + " Темп ул. " + toutside + "; Вл. "
+ hum + "; Давл. " + p + "; Темп. дом " + celsius1 + "; Темп. вход " + celsius2 + "; Темп. гараж " + d11 + "; Темп. кот. " + d10 + "; Темп. скв. " + d12 + ";";
//Serial.println(logStringData);
String DirectName = "20" + String(Y) + "/" + String(M); // Создаём имя папки из месяца и года
String logStringName = DirectName + "/" + String(d) + ".txt"; // формируем текстовый файл на один день максимум 12 знаков в названии файла
//Serial.println (logStringName);
if (SD.begin(47)) {
if (SD.mkdir(DirectName)) { // создаём на SD указанную территорию, может включать в себя вложенные папки, разделенные прямым слешем "/"
// Открываем файл, Если файла с таким именем не будет, ардуино создаст его.
File dataFile = SD.open(logStringName, FILE_WRITE);
// Если все хорошо, то записываем строку:
if (dataFile) {
dataFile.println(logStringData); // в файл записываем строку данных с переводом строки
dataFile.close(); // закрываем файл
SendDataP("page0.p1.pic", 3); // ЗЕЛЁНЫЙ значёк
Serial.println("Запись прошла на SD");
Zu = true; // флаг для печати нужного значка в цикле печати
}
else {
SendDataP("page0.p1.pic", 4); // КРАСНЫЙ значёк
Serial.println("Ошибка записи на SD!");
Zu = false; // флаг для печати нужного значка в цикле печати
}
registr = millis();
}
}
}
}
Алекс, а что, реально в строчках 785, 788, 791 и тд - кавычки в строках не экранированы? - или это криво вставилось? ... хотя нет, например в строке 814 все нормально
Который раз поражаюсь, как у вас вообще хоть что-то запускается...
Ну и еще - вы про макрос F() вообще не в курсе? - У Меги куча флеш памяти, но довольно мало оперативки, все константные строки в выводе стоило бы положить во флеш - наверно килобайт а то и пару выиграете
про кавычки ответьте. Если действительно так, как сейчас в коде - надо переделать немедленно. Не знаю, может ли это приводить к зависаниям, но косяк серьезный.
+100, нет даже +100500
Блин, подскажите как надо пожалуйста! Я понимаю что вы правы, но не знаю как на деле это написать.....
Если я отправляю 5 интов (10 байт), то и приняться должны 10 байт....
Оставьте вы байты, раз не понимаете. Если вы отправляете пять интов - то и принимайте пять интов. Ваши данные содержатся в элементах с bn[0] по bn[4], подряд, а не в четных
Поставил приём 5, данные всё также только в чётных...... почему??? Как при присвоении переменным массива принятых данных программа умудряется перепрыгивать через один....
При печати выводится десять чисел:
27
0
28
0
27
0
1
0
83
0
При печати выводится десять чисел:
27
0
28
0
27
0
1
0
82
0
Алекс, ну а сколько программа должна напечатать, если у вас в коде 10 оператора print ?
Поймите важную вещь - в языке С нет встроенных проверок размера массива. Если обьявили массив из пяти элементов, а потом записали в него 250 значений - никаких ошибок вам компилятор не выдаст.
Все эти проверки - на совести программиста, то есть вас. Если вы захотели напечатать десять значений из массива с пятью элементами - программа вам напечатает. Все на ваш риск.
Поставил приём 5, данные всё также только в чётных...... почему??? Как при присвоении переменным массива принятых данных программа умудряется перепрыгивать через один....
покажите новый код, как вы поставили прием 5. Только код целиком - и именно тот, что тестируете, а не какой-то "я вот тут чуть-чуть изменил"
Так значения записывает программа, а не я. Принтом я только вывожу на печать то что есть. Элементам массива я ничего не присваиваю..... присваивает программа. Я с вами согласен, что данные должны быть в первых пяти, но на деле это не так - они в чётных элементах массива оказываются.... Работа этой строки rf95.recv(int(bn), 5); и вызывает залезание в чужую область памяти скорее всего... но почему?
Поставил приём 5, данные всё также только в чётных...... почему??? Как при присвоении переменным массива принятых данных программа умудряется перепрыгивать через один....
покажите новый код, как вы поставили прием 5. Только код целиком - и именно тот, что тестируете, а не какой-то "я вот тут чуть-чуть изменил"
Всё тоже самое, только в строке rf95.recv(int(bn), 10); 10 заменил на 5 и всё
Всё тоже самое, только в строке rf95.recv(int(bn), 10); 10 заменил на 5 и всё
блин, я и не заметил, у вас тут тоже бредятина.
вот так вот напишите (и цифра - именно 10)
rf95.recv((uint8_t*) bn, 10);
Нифига!... )))))) тоже самое....
26
0
27
0
26
0
1
0
80
0
Я же говорю - перепробовал все варианты, и ваш в том числе - при присвоении перескакивает через элемент массива....
"- вот вы и влезли в чужую область памяти, при этом знаете что бывает? - программа либо зависает (привет вопросам годичной давности) либо в ней портятся другие переменные - вот вам и обнуление температуры"
я вижу что это так и происходит, только не могу понять почему. При чтении
rf95.recv(
int
(bn), 10); мои данные содержатся в чётных байтах, потому и печатаю с нулевого по девятый. И вынимаю чётные.
PS. Бросайте программирование - не Ваше это.
alexbel620017 - выкладывайте код передатчика. Полностью.
кстати, передатчик на какой плате? и приемник? Год назад это были две Мега, но там был другой проект.
Я же говорю - перепробовал все варианты, и ваш в том числе - при присвоении перескакивает через элемент массива....
PS. Говорят, если миллион обезьян посадить за пишущие машинки, то за 20 лет они смогут напечатать "Войну и мир".
С момента появления форумов прошло уже больше времени, да и количество их пользователей перевалило далеко за миллиард, но нетленки почему-то так и не появилось. Может, нужно было, чтобы были все-таки обезьяны?
alexbel620017 - выкладывайте код передатчика. Полностью.
кстати, передатчик на какой плате? и приемник? Год назад это были две Мега, но там был другой проект.
На DUE
На DUE
б**ть!!!!!!!!!!!! (простите)
На Дуе инты - 4 байта
Капец....... я не знал......
Капец....... я не знал......
поэтому у вас и данные идут через один.
А приемник тоже на Дуе или все еще на Меге?
Короче, опишите и на приемнике и на передатчике массив данных одинаково -
на передатчике
uint32_t data[5]
на приемнике
uint32_t bn[5]
строчку приема опишите как
rf95.recv((uint8_t*) bn, sizeof(bn));
PS. Бросайте программирование - не Ваше это.
alexbel620017 - а ведь Андриано прав.
Писать огромные портянки кода, не выяснив за год даже размер типов данных на используемом контроллере... это ламерство.
И о чудо! - всё встало на свои места.......
Спасибо вам большое, b707! Ейбогу не знал что инты в дуе другой размерности! Первый раз на ней что-то делал. И температура перестала соскакивать на ноль ))))))
Спасибо!
PS. Бросайте программирование - не Ваше это.
alexbel620017 - а ведь Андриано прав.
Писать огромные портянки кода, не выяснив за год даже размер типов данных на используемом контроллере... это ламерство.
Да я и не претендую на хакера, так, для себя по-мелочи делаю и всё.
На DUE
всегда поражаюсь.
Ну, вот, как умнó я вчера попросил Вас код выложить. Пока я дрых до обеда, после тяжёлой командировки, вопрос и без меня решился, спасибо коллегам :-)
Позвольте, мне поворчать по стариковски и дать Вам пару общих советов и некую отправную точку для понимания всего этого нагромождения типов данных. Надеюсь, будет полезно.
Но для начала пара комментариев, которые мне кажутся наиболее важными.
Так значения записывает программа, а не я.
Стоп! Кто в доме хозяин? Программа ничего никуда не записывает. Всё делаете всегда Вы сами. То, что компилятор помогаем Вам в рутинных операциях - вовсе не означает, что он что-то делает. Он делат ровно то, что Вы ему сказали делать. Делаете всегда Вы сами. И Вы должны понимать каждый "чих". Если Вы не понимаете, что "он" делает, значит Вы потеряли контроль над ситуацией - немедленно опускайтесь ниже и разбирайтесь что на самом деле происходит. Делаете всегда Вы, и Вы должны понимать что Вы делаете до последних мелких нюансов.
Капец....... я не знал......
Вы не поверите, но переходя на новый процессор или новый компилятор для старого процессора, я ВСЕГДА запускаю нечто вроде вот такого:
например, на Нане это даёт вот такой результат (только что специально запустил):
после этого я точно знаю что у меня за типы. Делайте тоже самое, заведите это привычкой. Вот сейчас запустите это на своей DUE и покажите нам результат (мне, кстати, очень интересно, т.к. я не знаю как там сделаны double).
Так, ну теперь к "полезностям". Я могу рассказать Вам про работы с памятью и типами данных так, как я рассказывал внуку. У него с тех пор проблем нет, потому я думаю, что это было понятно. Хотя, конечно, ничего нового я не скажу - откуда тут новое. Надо? Или Вы итак уже всё поняли, просто с DUE затык вышел?
Или Вы итак уже всё поняли, просто с DUE затык вышел?
Евгений, позволю себе опять влезть. Это не просто "затык с Дуе". Думаю тут все серьезно.
Почему мне так кажется? -Не заметить другой размер целого мог и более опытный программист. Но ни один даже самый начинающий - не стал бы решать проблему чтением шестого-десятого элементов из массива int bn[5]. Это дичь, очевидная даже школьнику, вчера прочитавшего про массивы. И любой школьник, хотя бы, догадался бы описать массив как int bn[10] :) - это был бы кривой костыль - но он решил бы все проблемы в коде ТС :)
ТС, что называется, программирует методом тыка. Он всю программу написал путем пристраивания подходящих кусков из готовых примеров, даже не пытаясь понять, что они делают. А когда у него возникла проблема с передачей данных - он уже стал пробовать туда все подряд, по его собственному выражению - совершенно не считаясь с логикой и смыслом.
Сомневаюсь, что у ТС сильно прибавилось в понимании после вчерашней развязки. Скорее, он просто скопировал те строчки, что я ему дал. - как ставят заплату на прорехе. "Решил проблему" и забыл.
Евгений, за это спасибо, обязательно буду иметь это в виду.
А по поводу всего остального.... Господа Гуру, вы поймите, что я не ПРОГРАММИСТ. Этой хренью я занимаюсь чисто для себя. Я никогда не учился этим языкам (исключая Бэйсик в школе в 87-м году) и программированию. Моё образование, работа лежат совсем в другой сфере. Два года назад если бы меня спросили что такое С++ я бы сказал что это буква с двумя плюсами... Я леплю маленькие проектики типа GSM сигналки в гараж, метеостанцию с выходом в НМ, часы с синхрой от GPS, инфосистема в котельную в частный дом и подобное для себя. Да, код не только кривой, но и, даже я вижу, очень не рациональный. И часто копирую код из примеров досконально не понимая как он работает.Занимаюсь я этим либо по ночам, либо в выходной. Времени у меня уходит на всё много. Проект годичной давности с последующим двух-трёх месячным прогоном я делал почти год - времени и знаний (по софту) не хватает. Напрасно вы так на меня нападаете, то что вам кажется элементарным может для другого человека оказаться не известным или не понятным.
По поводу вчерашнего вопроса с размерностью на DUE - я не "просто скопировал" строчки, когда b707 сказал что размерность инта в два раза больше всё сразу стало понятно - и про неприём, и захват чужой области памяти... Я не то что не знал этого нюанса, я даже предположить не мог что такая хрень может быть. Это надо просто знать. Я никогда не имел дело с армовскими процами. Эта DUE приехала мне из китая только пару недель назад. И тот код, который Евгений показал я мог бы и сам конечно написать, но я и предположить не мог что на разных платах может быть разная размерность одного типа данных.
Очень благодарен Евгению и b707 за помощь!
Так, а как с моей просьбой? Мне правда интересно, как там на дуе.
Так, а как с моей просьбой? Мне правда интересно, как там на дуе.
С какой просьбой, Евгений?
Выложить код передатчика?
С какой просьбой, Евгений?
Выложить код передатчика?
запустить на Дуе код, который выводит размеры разных типов данных
Блин, чё-то не могу найти printing.h
Блин, чё-то не могу найти printing.h
зачем? только не говорите, что вы этот код не можете переписать под обычный Serial.print()
Пардон, почти три ночи, мозги уже не те...
4
4
8
4
8
8
Теперь буду проверять все платы перед писаниной кода...
Блин, чё-то не могу найти printing.h
https://github.com/elilitko/ArduinoStuff/tree/master/Printing
Ещё..... вопрос из прошлой жизни....
Вся эта хрень всё же зависает на работе какого-нибудь модуля SPI. Их три - W5500, SD карта и RA-01(LoRa). Все модули имеют питание 3,3 вольта, уровни, как пишут, "толерантны к пити вольтам". Но что бы сделать всё по-человечески на каждый модуль спаял переходную плату на 74HC125. Питание на неё беру с самого модуля - 3,3 в. Виснет (по меткам в программе) именно на работе W5500 или SD карты. Работать без зависания может от нескольких секунд до нескольких десятков минут.
...но я и предположить не мог что на разных платах может быть разная размерность одного типа данных.
https://www.youtube.com/watch?v=aw10753OJyg
Ну так как, ни у кого мыслей нет? По одному модулю - зависаний нет, если два или все три - виснет. Работает от нескольких секунд до нескольких минут. Схему буфера на каждую плату прикладываю.....
а без буферов они не работают, что ли?
Нет, конфликт по MISO идёт. Ну и для согласования уровней.
Нет, конфликт по MISO идёт. Ну и для согласования уровней.
если честно, Алекс, после прошлой темы я уверен, что вы опять где-то накосячили. Но копаться в вашем коде... увольте
У меня три девайса SPI без проблем работали одновременно без всяких буферов
На модуле microSD такая микросхемка стоит уже изначально, правда управление по-другому - повторители всегда открыты.
Вот код, где отключено почти всё кроме обращения к трём модулям SPI. Всё равно виснет....
По одному работают нормально, два или три - виснет через несколько секунд или минут. Виснет на любом модуле, не на каком-то одном. Не понятно почему не сразу. Был бы аппаратный конфликт не работало бы вообще, а так - не ясно.
Может не успевает отключиться предыдущий модуль?
Проверял свободную память - 1607 байт свободно. Софт или железо всё-таки?...
Плата МЕГА 2560
Алекс, а что, реально в строчках 785, 788, 791 и тд - кавычки в строках не экранированы? - или это криво вставилось? ... хотя нет, например в строке 814 все нормально
Который раз поражаюсь, как у вас вообще хоть что-то запускается...
Ну и еще - вы про макрос F() вообще не в курсе? - У Меги куча флеш памяти, но довольно мало оперативки, все константные строки в выводе стоило бы положить во флеш - наверно килобайт а то и пару выиграете
А чему там не запускаться?
Про макрос слышал, но как-то не сподобился применять его раньше....
Мне бы про зависания прояснить как-то. То ли переполнение где-то идёт, то ли потенциал накапливается....
Почитал ваши сообщения в других постах по поводу макроса - переделаю у себя.
про кавычки ответьте. Если действительно так, как сейчас в коде - надо переделать немедленно. Не знаю, может ли это приводить к зависаниям, но косяк серьезный.
Сейчас вот так стоит, ещё раз скопировал весь код
Менял режимы, скорость SPI - не помогает....
Вот если честно - Вы ожидаете, что кто-то будет эти сотни строк у себя в голове прокручивать, чтобы понять, где стек пропарывает кучу?
на самом деле в коде вот так, просто когда вы вставляете в форум, часть строки вырезается
и тут просто дофига не прикрытых кавычек.
Нужно абсолютно все кавычки внутри строки оформить так, как записано "WHITE":