Обмен данными через последовательный порт

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

Ещё вчера вечером описал проблему в другой теме, на неё даже ответил DetSimen (судя по подписке на почте), но сейчас там всё подтёрто. Создаю новую тему:

Есть задача отправлять информацию через последовательный порт с Arduino UNO на ESP8266.

Вот кусок кода на передающей стороне (Arduino):

void loop() {
  Serial.print("
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ДимЧик пишет:

Ещё вчера вечером описал проблему в другой теме, на неё даже ответил DetSimen (судя по подписке на почте), но сейчас там всё подтёрто. Создаю новую тему:

Есть задача отправлять информацию через последовательный порт с Arduino UNO на ESP8266.

Вот кусок кода на передающей стороне (Arduino):

void loop() {
  Serial.print("

и что не работает?  Должен  же стопудово работать, если двойную кавычку поставить, потом закрывающую скопку, потом точку с запятой, потом фигурную.  И всё. 

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

Не могу понять, почему все мои ссобщения режутся, вот полный текст: http://text.fancy.kz/zxzq

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ДимЧик пишет:

Не могу понять, почему все мои ссобщения режутся, вот полный текст: http://text.fancy.kz/zxzq

Ты чо думаешь, там текста больше?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

видимо, в кавычках первым символом идёть ^Z

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013
Ещё вчера вечером описал проблему в другой теме, на неё даже ответил DetSimen (судя по подписке на почте), но сейчас там всё подтёрто. Создаю новую тему:
 
Есть задача отправлять информацию через последовательный порт с Arduino UNO на ESP8266.
 
Вот кусок кода на передающей стороне (Arduino):
 
void loop() {
  Serial.print("Температура котельной: ");
  //    Serial.print(t);
  Serial.println(" °C");

  Serial.print("Температура воды: ");
  // Serial.print(TempWater);
  Serial.println(" °C");

  Serial.print("Температура на улице: ");
  //  Serial.print(TempOut);
  Serial.println(" °C");

  Serial.print("Влажность котельной: ");
  //  Serial.print(h);
  Serial.println(" %");

  Serial.print("Качество воздуха: ");
  // Serial.print(val135);
  Serial.println(" ед.");

  Serial.print("Природный газ: ");
  // Serial.print(val4);
  Serial.println(" ед.");

  Serial.print("Датчик протечки: ");
  // Serial.print(Potop);
  Serial.println(" ед.");

  delay (10000);

}

 

Вот кусок кода на принимающей (ESP):
 
int ch = 0;
String val = "";

if (Serial.available()) {  //если в мониторе порта ввели что-то
    while (Serial.available()) {  //сохраняем строку в переменную val
      ch = Serial.read();
      val += char(ch);
      delay(10);
    }
    //передача всех команд, набранных в мониторе порта в бота
    bot.sendMessage(chat_id, val, "");

    val = "";  //очищаем
  }

 

 
В плане функционирования и кода ESP полностью идентична Arduino, так что можно сделать вид, что общаются две ардуины. Проблема в том, что в итоге, строка, которая образуется в val получается вот такой:
 
Температура котельной:  °C
Температура воды:  °C
Температура н

 

 
Насколько я понимаю, дело в цикле на принимающей стороне. Как его исправить, чтобы было хорошо?) Думаю, может как-нибудь обозначить конец ввода? Заранее спасибо!
ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

Там был смайлик "градусник", для наглядности в боте. Не подумал, что он может вызвать какие-то проблемы

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а вот это 

//    Serial.print(t);

ни о чем не? 

И другие строчки тоже так, далее по тексту

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Пацкаска:  Что означает двойной слэш (//) перед Serial?

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

Я не настолько новичок) У меня дуина передаёт семь строк, а в итоге две с половиной. Это проблема

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Передатчик фигачит с максимально возможной скоростью, а на приёмнике зачем-то задержка стоит после каждого символа. Не смущает? Буфер передатчика переполняется и он перестаёт передавать. Попробуйте вызывать flush после каждого println

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну или прочитай себе вслух вэт это 

https://ravesli.com/urok-9-kommentarii-v-s/

и снова приходи, нам расскажешь

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

ЕвгенийП пишет:

Передатчик фигачит с максимально возможной скоростью, а на приёмнике зачем-то задержка стоит после каждого символа. Не смущает? Буфер передатчика переполняется и он перестаёт передавать. Попробуйте вызывать flush после каждого println

Спасибо за ответ. Сейчас открыл монитор порта на передатчике, он передаёт всё как и требуется. На всякий пожарный добавил flush, ничего не поменялось. Убрал задержку на приёмнике, ничего не поменялось(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ДимЧик пишет:

На всякий пожарный добавил flush, ничего не поменялось. Убрал задержку на приёмнике, ничего не поменялось(

Куда добавил? Как добавил? Показывайте.

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

ЕвгенийП пишет:

Куда добавил? Как добавил? Показывайте.

Сейчас через каждые две строки добавил delay(3000);

void loop() {
  Serial.print("Температура котельной: ");
  //    Serial.print(t);
  Serial.println(" °C");

  Serial.print("Температура воды: ");
  // Serial.print(TempWater);
  Serial.println(" °C");
  delay(3000);
  Serial.print("Температура на улице: ");
  //  Serial.print(TempOut);
  Serial.println(" °C");

  Serial.print("Влажность котельной: ");
  //  Serial.print(h);
  Serial.println(" %");
  delay(3000);
  Serial.print("Качество воздуха: ");
  // Serial.print(val135);
  Serial.println(" ед.");

  Serial.print("Природный газ: ");
  // Serial.print(val4);
  Serial.println(" ед.");
  delay(3000);
  Serial.print("Датчик протечки: ");
  // Serial.print(Potop);
  Serial.println(" ед.");

  delay (10000);

}

Стало приходить всё, но отдельными сообщениями соответственно:

Flush добавлял вот так:

void loop() {
  Serial.print("Температура котельной: ");
  //    Serial.print(t);
  Serial.println(" °C");
  Serial.flush();

  Serial.print("Температура воды: ");
  // Serial.print(TempWater);
  Serial.println(" °C");
  Serial.flush();

  Serial.print("Температура на улице: ");
  //  Serial.print(TempOut);
  Serial.println(" °C");
  Serial.flush();

  Serial.print("Влажность котельной: ");
  //  Serial.print(h);
  Serial.println(" %");
  Serial.flush();

  Serial.print("Качество воздуха: ");
  // Serial.print(val135);
  Serial.println(" ед.");
  Serial.flush();

  Serial.print("Природный газ: ");
  // Serial.print(val4);
  Serial.println(" ед.");
  Serial.flush();

  Serial.print("Датчик протечки: ");
  // Serial.print(Potop);
  Serial.println(" ед.");
  Serial.flush();

  delay (10000);

}

Правда я сейчас вычитал, что она буфер-то чистила на версиях до 1. Но что с ней, что без неё в мониторе порта передатчика, повторюсь, всё прекрасно:

Температура котельной:  °C
Температура воды:  °C
Температура на улице:  °C
Влажность котельной:  %
Качество воздуха:  ед.
Природный газ:  ед.
Датчик протечки:  ед.

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

а что не так? Все что передеал все принято. В чем вопрос-то?

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

wdrakula пишет:

а что не так? Все что передеал все принято. В чем вопрос-то?

Если Вы про вариант с костыльными делеями по 3 секунды- то это всё-таки не то. Хочется одного целостного сообщения. А то, что в мониторе порта, только лишь выход передатчика.

Если не придумаем более красивой реализации, придётся пользоваться вариантом с делеями

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ДимЧик пишет:

Flush добавлял вот так:

Надо одновременно и добавить flush, и убрать все задержки из приёмника. Вот и покажите как это сделано и что при этом принимается.

В приёмника вообще не должно быть никаких задержек - никогда. Вы же не знаете когда и что будет передаваться.

ДимЧик пишет:

Если не придумаем более красивой реализации, придётся пользоваться вариантом с делеями

Если не будете делать, что Вам говорят, то будете решать проблему сами :)

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

ЕвгенийП пишет:

Надо одновременно и добавить flush, и убрать все задержки из приёмника. Вот и покажите как это сделано и что при этом принимается.

Я так и делал, но, вот:

Передатчик:

void loop() {
  Serial.print("Температура котельной: ");
  //    Serial.print(t);
  Serial.println(" °C");
  Serial.flush();

  Serial.print("Температура воды: ");
  // Serial.print(TempWater);
  Serial.println(" °C");
  Serial.flush();

  Serial.print("Температура на улице: ");
  //  Serial.print(TempOut);
  Serial.println(" °C");
  Serial.flush();

  Serial.print("Влажность котельной: ");
  //  Serial.print(h);
  Serial.println(" %");
  Serial.flush();

  Serial.print("Качество воздуха: ");
  // Serial.print(val135);
  Serial.println(" ед.");
  Serial.flush();

  Serial.print("Природный газ: ");
  // Serial.print(val4);
  Serial.println(" ед.");
  Serial.flush();

  Serial.print("Датчик протечки: ");
  // Serial.print(Potop);
  Serial.println(" ед.");
  Serial.flush();

  delay (10000);

}

Приёмник:

if (Serial.available()) {  //если в мониторе порта ввели что-то
    while (Serial.available()) {  //сохраняем строку в переменную val
      ch = Serial.read();
      val += char(ch);
      //delay(10);
    }
    //передача всех команд, набранных в мониторе порта в бота
    bot.sendMessage(chat_id, val, "");

    val = "";  //очищаем
  }

Результат:

По- прежнему отсутсвуют четыре строки

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Женя! Я вроде спрашивал, но ответ не помню: у тебя практика преподавания большая?

Это я к тому, что я твою методику наведения на самостоятельное решение не всегда могу понять.

Вот в этом случае, конкретно не могу.

Далее под спойлером, чтобы не портить процесс.

Автор, на твоей совести - не читать!

Вроде как твои вопросы не готовят ТС к тому, что у него признака конца сообщения нет, 
а без него никто и никак не поймет, что все приняли и пора передавать в бот.
Можно, конечно, измерять паузу без приема, но это а) - плохой стиль, б) - не для уровня ТС. 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

wdrakula пишет:

Это я к тому, что я твою методику наведения на самостоятельное решение не всегда могу понять.

За себя скажу. После чтения определенного объёма глупых вопросов и разбора скетчей-франкенштейнов мозг начинает выдавать такие же безумные конструктивы и отказывается видеть явные и простые ошибки.

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

wdrakula пишет:

Автор, на твоей совести - не читать!

Вроде как твои вопросы не готовят ТС к тому, что у него признака конца сообщения нет, 
а без него никто и никак не поймет, что все приняли и пора передавать в бот.
Можно, конечно, измерять паузу без приема, но это а) - плохой стиль, б) - не для уровня ТС. 

 

Уж простите, не удержался. И поэтому спешу сообщить, что эту мысль я написал ещё в своём первом сообщении (!):

ДимЧик пишет:

Думаю, может как-нибудь обозначить конец ввода? Заранее спасибо!

Тоесть я понимаю, что надо сделать так, но не очень понимаю как написать(

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ДимЧик пишет:

Тоесть я понимаю, что надо сделать так, но не очень понимаю как написать(

Ну блин!

Предай, как конец, какой-нибудь дурацкий символ.... например '#' или, как в С положено - '\n'.

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

То есть ничего на приемнике не ждешь, понимаешь, что прием может не весь уложиться в один заход в loop().

При каждом заходе в loop() выгребаешь весь буфер приема и ждешь своего символа завершения.

Что тут может быть непонятного????

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ДимЧик пишет:

По- прежнему отсутсвуют четыре строки

А целиком приёмник показать слабо?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

у него признака конца сообщения нет,

Это следующий вопрос. Пока пусть хоть просто наладит бридж - "что пришло, то и вышло"

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

ЕвгенийП пишет:

А целиком приёмник показать слабо?

Вот, пожалуйста:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

char ssid[] = "";
char password[] = "";

#define BOTtoken ""

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int Bot_mtbs = 500;
long Bot_lasttime;
bool Start = false;

int ch = 0;
String val = "";

void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    String text = bot.messages[i].text;

    String from_name = bot.messages[i].from_name;
    if (from_name == "") from_name = "Guest";

    if (text == "/start") {
      String welcome = "Welcome to Universal Arduino Telegram Bot library, " + from_name + ".\n";
      welcome += "This is serial print bot example.\n";
      bot.sendMessage(chat_id, welcome, "Markdown");
    }
  }
}


void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void loop() {
  String chat_id = "";

  if (Serial.available()) {  //если в мониторе порта ввели что-то
    while (Serial.available()) {  //сохраняем строку в переменную val
      ch = Serial.read();
      val += char(ch);
      //delay(10);
    }
    //передача всех команд, набранных в мониторе порта в бота
    bot.sendMessage(chat_id, val, "");

    val = "";  //очищаем
  }

  if (millis() > Bot_lasttime + Bot_mtbs)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages) {
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    Bot_lasttime = millis();
  }

}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Сможете поставить печать переменной val перед строкой 58? Понимаю, что Serial занят, но если сможете, то поймёте проблему.

Кстати (совсем про другое), в строке №63 ошибка, раз в два месяца (при переходе millis через 0) будет сбоить. см. http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

ЕвгенийП пишет:

Сможете поставить печать переменной val перед строкой 58? Понимаю, что Serial занят, но если сможете, то поймёте проблему.

Переделал вот так, подключив передатчик в SoftwareSerial:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(5, 14); // RX, TX

char ssid[] = "";
char password[] = "";

#define BOTtoken ""

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int Bot_mtbs = 500;
long Bot_lasttime;
bool Start = false;

int ch = 0;
String val = "";

void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    String text = bot.messages[i].text;

    String from_name = bot.messages[i].from_name;
    if (from_name == "") from_name = "Guest";

    if (text == "/start") {
      String welcome = "Welcome to Universal Arduino Telegram Bot library, " + from_name + ".\n";
      welcome += "This is serial print bot example.\n";
      bot.sendMessage(chat_id, welcome, "Markdown");
    }

    if (text == "/sensors") {
      Serial.print("sensors");
    }
  }
}


void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  mySerial.begin(115200);
}

void loop() {
  String chat_id = "";

  if (mySerial.available()) {  //если в мониторе порта ввели что-то
    while (mySerial.available()) {  //сохраняем строку в переменную val
      ch = mySerial.read();
      val += char(ch);
      //delay(10);
    }
    //передача всех команд, набранных в мониторе порта в бота
    Serial.println(val);
    bot.sendMessage(chat_id, val, "");

    val = "";  //очищаем
  }

  if (millis() > Bot_lasttime + Bot_mtbs)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages) {
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    Bot_lasttime = millis();
  }

}

Текста стало ещё меньше:

тчик протечки:  ед.#

То же самое, что и отпправляет в бот

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Ох....

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

wdrakula пишет:

Ох....

Ну это всё ради вашего совета)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Хорошо, а если убрать пока байду с 72 по 81 строки? Никак не полегчает?

И кстати, софт сериал на таких скоростях не работает. Поставьте 9600 пока (и в передатчике тоже).

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ДимЧик пишет:

wdrakula пишет:

Ох....

Ну это всё ради вашего совета)

Прости, тут сейчас Женя рулит, пусть он и отдувается! (Женя! Прости меня, грешного!)

Про твою реплику могу только процитировать старую поговрку:

Дураку и грамота вредна.

В том смысле, что зря я влез... ты совсем не туда ушел, куда надо.

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

ЕвгенийП пишет:

Хорошо, а если убрать пока байду с 72 по 81 строки? Никак не полегчает?

И кстати, софт сериал на таких скоростях не работает. Поставьте 9600 пока (и в передатчике тоже).

Убрал, от неё ни тепло, ни холодно. Поставил 9600, всё тот же обрубок текста

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial(5, 14); // RX, TX

// Initialize Wifi connection to the router
char ssid[] = "";     // your network SSID (name)
char password[] = ""; // your network key

// Initialize Telegram BOT
#define BOTtoken "458450101:-XYqx3V_3qqtX0a1pUTXV-M"  // your Bot Token (Get from Botfather)

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int Bot_mtbs = 500;
long Bot_lasttime;
bool Start = false;

int ch = 0;
String val = "";

void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    String text = bot.messages[i].text;

    String from_name = bot.messages[i].from_name;
    if (from_name == "") from_name = "Guest";

    if (text == "/start") {
      String welcome = "Welcome to Universal Arduino Telegram Bot library, " + from_name + ".\n";
      welcome += "This is serial print bot example.\n";
      bot.sendMessage(chat_id, welcome, "Markdown");
    }

    if (text == "/sensors") {
      Serial.print("sensors");
    }
  }
}


void setup() {
  Serial.begin(9600);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  Serial.println("Test");
  mySerial.begin(9600);
}

void loop() {
  String chat_id = "";

  if (mySerial.available()) {  //если в мониторе порта ввели что-то
    while (mySerial.available()) {  //сохраняем строку в переменную val
      ch = mySerial.read();
      val += char(ch);
      //delay(10);
    }
    //передача всех команд, набранных в мониторе порта в бота
    Serial.println(val);
    bot.sendMessage(chat_id, val, "");

    val = "";  //очищаем
  }
}
Test
⸮тчик протечки:  ед.

⸮тчик протечки:  ед.

⸮тчик протечки:  ед.

⸮тчик протечки:  ед.

⸮тчик протечки:  ед.

⸮тчик протечки:  ед.

⸮тчик протечки:  ед.

⸮
тчик протечки:  ед.

⸮тчик протечки:  ед.

Что-то я чувствую, сейчас пойду напишу эти три несчастных дэлея, потому что я не особо понимаю, к чему всё это.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ДимЧик пишет:

Убрал, от неё ни тепло, ни холодно. Поставил 9600, всё тот же обрубок текста

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:
ты совсем не туда ушел, куда надо.
Да, я уже понял и готов сдаться :(

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016
void loop() {
  String chat_id = "";

    while (mySerial.available()) {  //сохраняем строку в переменную val
      ch = mySerial.read();
      if (ch == '#') break;
      val += char(ch);
      //delay(10);
    }
    //передача всех команд, набранных в мониторе порта в бота
    if (ch =='#') {
      Serial.println(val);
      bot.sendMessage(chat_id, val, "");
      val = "";  //очищаем
    }
}

Вместо '#' - тот символ, который ты В ПЕРЕДАТЧИКЕ, МЛЯ, используешь, как конец сообщения.

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

Спасибо! Сначала выводились такие простыни каждые 3 минуты:

Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице: Температура котельной:  °C
Температура воды:  °C
Температура на улице:  °C
Влажность котельной:  %
Качество воздуха:  ед.
Природный газ:  ед.
Датчик протечки:  ед.

Но потом я снизил скорость, и всё заработало. Возможно, сделай я это раньше, было бы меньше проблем

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ДимЧик пишет:

Возможно, сделай я это раньше, было бы меньше проблем

Надеюсь, Вы о "подумать"? :)

------------------

wdrakula, признаю, что я облажался по уши :(

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

Надеюсь, Вы о "подумать"? :)

Зачем там думать - нужно было снизить скорость. А ещё прохфессорами назвались...

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

ЕвгенийП пишет:

ДимЧик пишет:

Возможно, сделай я это раньше, было бы меньше проблем

Надеюсь, Вы о "подумать"? :)

В совокупности)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

wdrakula, признаю, что я облажался по уши :(

Женя! Ты о чём? Мне просто показалось, что ты ТС-а ведешь каким-то долгим путём, но "облажаться"??? Не понял тебя....

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ТС!  В строке 03 напиши

ch = 0;

Обязательно это добавь, иначе попадешь на глюк. ;))))

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

 

Написал, но чёт не очень понимаю, зачем? Ведь мы в цикле сразу же присваиваем ему Serial.read();

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ДимЧик пишет:

 

Написал, но чёт не очень понимаю, зачем? Ведь мы в цикле сразу же присваиваем ему Serial.read();

"Не напрягайся, морщины появятся!" ;)

....

Ну сам подумай! Вот нет ничего в буфере, а старое значение в ch осталось и чо? Можно чистить при отправке, или до цикла. Как тебе больше нравиццо!

sadman41
Offline
Зарегистрирован: 19.10.2016

При отправке экономней на пару спичек.

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

Почему-то всё равно, даже на скорости 9600 может прийти не всё. Без пауз может прийти чуть-чуть, а с паузами в 3 секунды не приходит вообще ничего. Четыре сообщения на картинке отправляет одна и та же функция:

void smssend(String text) {
  if (SendSMS == false) {

    //Считывание информации с сенсоров
    sensors.requestTemperatures();
    float TempWater = sensors.getTempC(WaterT);  //темп. воды
    float TempOut = sensors.getTempC(OutT);      //темп. улицы
    float h = dht.readHumidity();                //влажность комнаты
    float t = dht.readTemperature();             //темп. комнаты
    long val135 = 0;                             //качество воздуха
    for (int i = 0; i < 100; ++i) {
      val135 = val135 + analogRead(SENSOR_AQ);
    }
    val135 = val135 / 100;
    long val4 = 0;                               //природный газ
    for (int i = 0; i < 100; ++i) {
      val4 = val4 + analogRead(SENSOR_CH);
    }
    val4 = val4 / 100;
    long Potop = 0;                              //уровень воды
    for (int i = 0; i < 100; ++i) {
      Potop = Potop + analogRead(A3);
    }
    Potop = Potop / 100;
    Serial.println(text);

    Serial.print("Температура котельной: ");
    Serial.print(t);
    Serial.println(" °C");
    delay(1500);

    Serial.print("Температура воды: ");
    Serial.print(TempWater);
    Serial.println(" °C");
    delay(1500);

    Serial.print("Температура на улице: ");
    Serial.print(TempOut);
    Serial.println(" °C");
    delay(1500);

    Serial.print("Влажность котельной: ");
    Serial.print(h);
    Serial.println(" %");
    delay(1500);

    Serial.print("Качество воздуха: ");
    Serial.print(val135);
    Serial.println(" ед.");
    delay(1500);

    Serial.print("Природный газ: ");
    Serial.print(val4);
    Serial.println(" ед.");
    delay(1500);

    Serial.print("Датчик протечки: ");
    Serial.print(Potop);
    Serial.println(" ед.#");
    delay(1500);

    delay(500);

    if (text != "Как Вы просили:") {
      SendSMS = true;
    }
    delay(2000);
  }

}

Приёмник:

void loop() {
  String chat_id = "";
  ch = 0;
  while (Serial.available()) {
    ch = Serial.read();
    if (ch == '#') break;
    val += char(ch);
  }

  if (ch == '#') {
    Serial.println(val);
    bot.sendMessage(chat_id, val, "");
    val = "";
  }
}

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

спать нужно по ночам. всё завтра.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

Женя! Ты о чём? Мне просто показалось, что ты ТС-а ведешь каким-то долгим путём, но "облажаться"??? Не понял тебя....

Как о чём, был уверен, что за пару тройку итераций доведу. Но не довёл.

ЧА что до длинного пути, так если бы у него сначала получилась копировалка длинной портянки, а потом уж ставить признак конца, то он бы понял проблему, а так ...

ТС, хотиите проверить поняли ли Вы проблему? Уберите оттуда while и добейтесь, чтобы без него также хорошо работало. 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Нашего  ТопикСтартера что-то не видать.... Ну ладно.

Вот вопросы к нему:

1.есть ли резон для того, чтобы все длинные тексты передавать с Уно? Вопрос в том, что на Уно памяти мало, а на ЕСП - неограниченно ;), может стоит передавать только значения?

2. Если пропажа строк сохраняется, то нужно синхронизировать передачу и прием. То есть передатчик кидает что-то, например '?'  в приемник и ждет ответа. Получив ответ кидает уже данные, и ждет подтверждения получения.

Это можно выращивать до полноценного протокола обмена, или при ошибке просто повторять всё с начала.  Тогда нужно завести запрос первого сообщения, запрос продолжения и запрос окончания. Приемник может отвечать только одним образом. При неответе - передатчик по таймауту вылетает и переходит в начало цикла.

ДимЧик
ДимЧик аватар
Offline
Зарегистрирован: 30.03.2013

Первый вопрос реализовал, но всё-таки кривовато. Зато работает на 100%. Пока что ни одного сбоя. Вот финальная версия на данный момент:

Передатчик (Уже основной девайс):

//Подключаем библиотеки
#include <Wire.h>
#include "DHT.h"
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>

//Прописываем датчики воздуха
#define SENSOR_AQ A0
#define SENSOR_CH A1

//Прописываем пороги срабатывания
const long mq135ok = 240;   //попугаи дыма
const long mq4ok = 90;      //попугаи природного газа
const float tok = 35;       //температура котельной
const float hok = 95;       //влажность котельной
const float watermax = 85;  //макс. темп. воды
const float watermin = 15;  //мин темп. воды
const long PotopMax = 300;  //уровень воды (в попугаях)

int ch = 0;
boolean SendSMS = false;
boolean SendRequest = false;
String val = "";

//Прописываем DHT
DHT dht(13, DHT22);

//Прописываем датчики температуры Dallas
OneWire  oneWire(11);
DallasTemperature sensors(&oneWire);
DeviceAddress OutT = {
  0x28, 0xFF, 0x26, 0x97, 0x00, 0x16, 0x02, 0xB1
};  // адрес датчика на улице
DeviceAddress WaterT = {
  0x28, 0xFF, 0xE1, 0xA3, 0x00, 0x16, 0x01, 0x66
};  // адрес датчика воды

//Прописываем экран
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE );  // Set the LCD I2C address




void setup()
{
  //Инициализация экрана
  lcd.begin(20, 4);        // initialize the lcd for 20 chars 4 lines
  pinMode(1, OUTPUT);
  digitalWrite(1, LOW);

  //Вывод приветствия
  lcd.setCursor(4, 0); //Start at character 4 on line 0
  lcd.print("BoilerSecurity");
  delay(250);
  lcd.setCursor(6, 2);
  lcd.print("Loading");
  lcd.setCursor(4, 3);
  delay(250);
  lcd.print("Please wait...");

  delay(500);

  //Инициализация пинов
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, INPUT);
  pinMode(13, INPUT);
  SendSMS = false;

  //Serial
  Serial.begin(9600);

  //Инициализация DHT
  dht.begin();
  sensors.begin();

  //Инициализация Dallas
  sensors.setResolution(WaterT, 10);
  sensors.setResolution(OutT, 10);

  delay(1750);
}


void loop()
{
  //Проверяем, есть ли запрос из бота
  if ((digitalRead(13) == HIGH) & (SendRequest == false)) {
    SendSMS = false;
    smssend(String ("Сенсоры:"));
    SendRequest = true;
  } else {
    SendRequest = false;
  }

  

  //Сичтываем показания с датчиков
  //Температура воды и улицы
  sensors.requestTemperatures();
  float TempWater = sensors.getTempC(WaterT);
  float TempOut = sensors.getTempC(OutT);

  //Температура и влажность в котельной
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  //Отработка аварии по температурам
  if ((TempWater <= watermax && TempWater >= watermin) && (t <= tok)) {
    digitalWrite(10, HIGH);   // зажигаем светодиод
    delay(10);
    digitalWrite(10, LOW);
  } else {
    digitalWrite(10, HIGH);   // зажигаем светодиод
    smssend(String ("Проверь температуру!"));
  }


  //Считываем показания датчиков газов
  //MQ-135
  long val135 = 0;
  for (int i = 0; i < 100; ++i) {
    val135 = val135 + analogRead(SENSOR_AQ);
  }
  val135 = val135 / 100;

  //MQ4
  long val4 = 0;
  for (int i = 0; i < 100; ++i) {
    val4 = val4 + analogRead(SENSOR_CH);
  }
  val4 = val4 / 100;

  //Отработка аварии по газам
  if (val4 <= mq4ok && val135 <= mq135ok) {
    digitalWrite(7, HIGH);   // зажигаем светодиод
    delay(10);
    digitalWrite(7, LOW);
  } else {
    digitalWrite(7, HIGH);   // зажигаем светодиод
    smssend(String ("Проверь газы!"));
  }

  //Считывание датчика уровня воды
  long Potop = 0;
  for (int i = 0; i < 100; ++i) {
    Potop = Potop + analogRead(A3);
  }
  Potop = Potop / 100;

  if (Potop >= PotopMax) {
    digitalWrite(8, HIGH);   // зажигаем светодиод
    delay(10);
    digitalWrite(8, LOW);
  } else {
    digitalWrite(8, HIGH);   // зажигаем светодиод
    smssend(String ("Проверь уровень воды!"));
  }

  //Считвание показаний датчика пламени
  if (digitalRead(11) == HIGH) {
    digitalWrite(9, HIGH);   // зажигаем светодиод
    delay(10);
    digitalWrite(9, LOW);

  } else {
    digitalWrite(9, HIGH);   // зажигаем светодиод
    smssend(String ("Обнаружено пламя"));
  }

  //Вывод данных на экран
  //Очистка экрана
  //lcd.clear(); //ОСТОРОЖНО!!!

  //Температура и влажность котельной
  if (isnan(t) || isnan(h)) {
    lcd.setCursor(3, 0);
    lcd.print("Failed to read");
    lcd.setCursor(6, 1);
    lcd.print("from DHT");
    smssend(String ("Ошибка чтения данных с DHT!"));
  }
  else {
    lcd.setCursor(0, 0);
    lcd.print("Humidity: ");
    lcd.setCursor(13, 0);
    lcd.print(h);
    lcd.setCursor(19, 0);
    lcd.print("%");
    lcd.setCursor(0, 1);
    lcd.print("Temperature: ");
    lcd.setCursor(13, 1);
    lcd.print(t);
    lcd.setCursor(19, 1);
    lcd.print("C");
  }

  lcd.setCursor(0, 2);
  lcd.print("Water temp: ");
  lcd.setCursor(12, 2);
  lcd.print(TempWater);
  lcd.setCursor(18, 2);
  lcd.print("C");
  lcd.setCursor(0, 3);
  lcd.print("Out Temp: ");
  lcd.setCursor(12, 3);
  lcd.print(TempOut);
  lcd.setCursor(18, 3);
  lcd.print("C");

  delay(3000); //задержка перед новым опросом датчиков

}

void smssend(String text) {
  if (SendSMS == false) {

    //Считывание информации с сенсоров
    sensors.requestTemperatures();
    float TempWater = sensors.getTempC(WaterT);  //темп. воды
    float TempOut = sensors.getTempC(OutT);      //темп. улицы
    float h = dht.readHumidity();                //влажность комнаты
    float t = dht.readTemperature();             //темп. комнаты
    long val135 = 0;                             //качество воздуха
    for (int i = 0; i < 100; ++i) {
      val135 = val135 + analogRead(SENSOR_AQ);
    }
    val135 = val135 / 100;
    long val4 = 0;                               //природный газ
    for (int i = 0; i < 100; ++i) {
      val4 = val4 + analogRead(SENSOR_CH);
    }
    val4 = val4 / 100;
    long Potop = 0;                              //уровень воды
    for (int i = 0; i < 100; ++i) {
      Potop = Potop + analogRead(A3);
    }
    Potop = Potop / 100;
    
    Serial.print(text);
    Serial.print("r");
    delay (1500);

    Serial.print(t);
    Serial.print("k");
    delay(1500);

    Serial.print(TempWater);
    Serial.print("w");
    delay(1500);

    Serial.print(TempOut);
    Serial.print("o");
    delay(1500);

    Serial.print(h);
    Serial.print("h");
    delay(1500);

    if (digitalRead(11) == HIGH) {
      Serial.print("z");
    } else {
      Serial.print("x");
    }
    Serial.print("f");
    delay(1500);

    Serial.print(val135);
    Serial.print("q");
    delay(1500);

    Serial.print(val4);
    Serial.print("g");
    delay(1500);

    Serial.print(Potop);
    Serial.print("p");
    delay(1500);

    Serial.print("#");

    delay(500);

    if (text != "Сенсоры:") {
      SendSMS = true;
    }
    delay(2000);
  }

}



Приёмник:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// Initialize Wifi connection to the router
char ssid[] = "";     // your network SSID (name)
char password[] = ""; // your network key

// Initialize Telegram BOT
#define BOTtoken ":AAH_fTlgywix-XYqx3V_3qqtX0a1pUTXV-M"  // your Bot Token (Get from Botfather)

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int Bot_mtbs = 500; //Время между сканированием сообщений
long Bot_lasttime;  //last time messages' scan has been done
bool Start = false;

//Пин запроса
const int Pin = 13;

int ch = 0;
String val = "";

String TempWater = "";  //темп. воды
String TempOut = "";    //темп. улицы
String h = "";          //влажность комнаты
String t = "";          //темп. комнаты
String val135 = "";     //качество воздуха
String val4 = "";       //природный газ
String Potop = "";      //уровень воды
String flame = "";      //датчик пламени
String reason = "";     //причина отправки

void handleNewMessages(int numNewMessages) {

  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    String text = bot.messages[i].text;

    String from_name = bot.messages[i].from_name;
    if (from_name == "") from_name = "Guest";

    if ((chat_id == "") & (text == "Sensors")) {
      digitalWrite(Pin, HIGH);
      delay (5000);
      digitalWrite(Pin, LOW);
      bot.sendMessage(chat_id, "Запрос отправлен, ожидайте", "Markdown");
    }

    if (text == "/start") {
      String welcome = "Приветствую в информационном центре котельной, " + from_name + "!\n";
      welcome += "Я выслал тебе кнопку для запроса состояния\n";
      String keyboardJson = "[[\"Sensors\"]]";
      bot.sendMessageWithReplyKeyboard(chat_id, welcome, "", keyboardJson, true);
    }

  }
}


void setup() {
  Serial.begin(9600);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

  pinMode(Pin, OUTPUT);
  delay(10);
  digitalWrite(Pin, LOW);
}

void loop() {
  String chat_id = "";
  ch = 0;

  while (Serial.available()) {
    ch = Serial.read();
    if (ch == 'r') break;
    if (ch == 'k') break;
    if (ch == 'w') break;
    if (ch == 'o') break;
    if (ch == 'h') break;
    if (ch == 'f') break;
    if (ch == 'q') break;
    if (ch == 'g') break;
    if (ch == 'p') break;
    if (ch == '#') break;
    val += char(ch);
  }

  //Причина отправки
  if (ch == 'r') {
    reason = val;
    val = "";
  }
  
  //Температура котельной
  if (ch == 'k') {
    t = val;
    val = "";
  }

  //температура воды
  if (ch == 'w') {
    TempWater = val;
    val = "";
  }

  //температура на улице
  if (ch == 'o') {
    TempOut = val;
    val = "";
  }

  //влажность котельной
  if (ch == 'h') {
    h = val;
    val = "";
  }

  //пламя
  if (ch == 'f') {
    flame = val;
    if (flame == "z") {
      flame = "Датчик пламени сработал!";
    }

    if (flame == "x") {
      flame = "Датчик пламени в покое";
    }
    val = "";
  }

  //качество воздуха
  if (ch == 'q') {
    val135 = val;
    val = "";
  }

  //природный газ
  if (ch == 'g') {
    val4 = val;
    val = "";
  }

  //датчик протечки
  if (ch == 'p') {
    Potop = val;
    val = "";
  }

  //конец передачи
  if (ch == '#') {
    String welcome = reason + "\n";
    welcome += "Температура котельной: " + t + " °C\n";
    welcome += "Температура воды: " + TempWater + " °C\n";
    welcome += "Температура на улице: " + TempOut + " °C\n";
    welcome += "Влажность котельной: " + h + " %\n";
    welcome += flame + " \n";
    welcome += "Качество воздуха: " + val135 + " ед.\n";
    welcome += "Природный газ: " + val4 + " ед.\n";
    welcome += "Датчик протечки: " + Potop + " ед.\n";
    bot.sendMessage(chat_id, welcome, "Markdown");
    val = "";
  }


  if (millis() > Bot_lasttime + Bot_mtbs)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages) {
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    Bot_lasttime = millis();
  }

}

Результат: