Преобразование строки

Модератор: Alex

svetozar161
Сообщения: 72
Зарегистрирован: Пт янв 13, 2017 11:48 pm
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Преобразование строки

Сообщение svetozar161 » Сб сен 29, 2018 5:20 pm

Здравствуйте уважаемые знатоки. Прошу помощи.
С помощью уважаемого serghei наконец-то запустил систему отопления и парсинг температуры с внешнего датчика, но температура конвертится с помощью Int в целое число и термостат неудобно работает по целому числу, хотелось бы десятые доли. Есть оператор "atof" но как его применить толком не пойму. Вот код:
Объявляется переменная

Код: Выделить всё

int data1
Парсится строка "espdata&idesp" и ищется символ с 50 по 55 затем преобразуется в переменную data1

Код: Выделить всё

if (parameter.startsWith("espdata&idesp")) {        // Температура датчика в спальне ESP05
    data1 = (parameter.substring(50,55)).toInt();
Здесь код для реле

Код: Выделить всё

void testRele(){ 
    if(!releSt && data1 > 24){
      
  digitalWrite(relePin, HIGH);

  timeStamp();
  Serial.println(" Rele \"OFF\"");
  releSt = 1;
  #ifdef MAJORDOMO_FEATURE
        sendRequestM("Rele_kotla", 0);
      #endif
  }
    if(releSt && data1 < 21){
{
  digitalWrite(relePin, LOW);
 timeStamp();
  Serial.println(" Rele \"ON\"");
  releSt = 0;
  #ifdef MAJORDOMO_FEATURE
        sendRequestM("Rele_kotla", 1);
      #endif
  }
}
Все работает. Но хотелось бы использовать float вместо int. Как сделать десятые доли?

Да и еще забыл такой момент. Если на пинах АМС не висит хотя бы один даллас, цикл реле не работает. Почему?
Последний раз редактировалось svetozar161 Вс сен 30, 2018 11:25 am, всего редактировалось 1 раз.
Аватара пользователя
ser009
Сообщения: 595
Зарегистрирован: Сб окт 13, 2012 9:55 am
Благодарил (а): 4 раза
Поблагодарили: 43 раза

Re: Преобразование строки

Сообщение ser009 » Вс сен 30, 2018 7:18 am

Если вы используете библиотеку <DallasTemperature.h>, значение с датчика читается в формате float.

Код: Выделить всё

...
float current_temp[MAX_TEMP_SENSORS];...
...
current_temp[n] = sensors.getTempC(tempSensor[n]);
...
Если у вас проблемы с передачей значения с плавающей точкой, то в таких случаях из Float разбивают на 2 int (целое число и все что после запятой) передают 2 int и потом их снова собирают во float
svetozar161
Сообщения: 72
Зарегистрирован: Пт янв 13, 2017 11:48 pm
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Re: Преобразование строки

Сообщение svetozar161 » Вс сен 30, 2018 10:56 am

Это очень сложно, да и зачем float разбивать на int, потом опять собирать в float? Нужно просто правильно составить строку substring с atof
svetozar161
Сообщения: 72
Зарегистрирован: Пт янв 13, 2017 11:48 pm
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Re: Преобразование строки

Сообщение svetozar161 » Вс сен 30, 2018 11:54 am

Да и значение температуры у меня берется не со встроенных далласов а преобразуется из строки из сериала
alexsis_76
Сообщения: 791
Зарегистрирован: Пт янв 22, 2016 10:08 am
Благодарил (а): 6 раз
Поблагодарили: 63 раза

Re: Преобразование строки

Сообщение alexsis_76 » Вс сен 30, 2018 1:15 pm

а что флоат разве уже не передают целиком, видимо надо коды переписывать
Аватара пользователя
ser009
Сообщения: 595
Зарегистрирован: Сб окт 13, 2012 9:55 am
Благодарил (а): 4 раза
Поблагодарили: 43 раза

Re: Преобразование строки

Сообщение ser009 » Вс сен 30, 2018 3:07 pm

Дайте кусок кода, который разбирает принятый пакет данных и получаемые данные
serghei
Сообщения: 2575
Зарегистрирован: Пт ноя 06, 2015 10:22 am
Откуда: Кишинёв
Благодарил (а): 303 раза
Поблагодарили: 282 раза

Re: Преобразование строки

Сообщение serghei » Вс сен 30, 2018 4:08 pm

Смысл происходящего простой - AMS получает по сети или сериалу данные с других ардуино. Для этого создаем буфер в 64 байта и записываем туда всё что прилетело. Дальше по шаблону ( первые несколько байт ) распарсиваем ответ. В этом ответе ( от сети WiFi-iot ) первые байты всегда одинаковые. А интересующая температура всегда с 50 по 55 байт в виде 12,34 . Вот её и надо присвоить некой переменной Data1, что бы потом дергать реле или вывести на страницу. Код работал у меня на ESP32 и получал данные от сети MySensors. Но меня интересовали целые значения температур или влажности.
Затем я применил этот же алгоритм и для Меги по сериалу 3 получаю время от AMS на 8266 и от UNO по сериалу 2. И дробное значение всегда правильное. Почему это не работает с HTTP я не знаю. Вернее целое число видно , а дробное нет. Что делаем:
1 Определяем переменные

Код: Выделить всё

  String data1;    
  String data2;//  20;2;1;0;0;23.8 - Температура 20 ноды
2 В парсере

Код: Выделить всё

      if (serialReq.startsWith("20;2;1;0;0;")) { 
     data2 = (serialReq.substring(11,16));
    Serial.println(data2);
  }
C ESP32 и UDP это работает. А с WiFi-iot не хочет.
Полный код для MySensors Тут. Для сериала только тестирую.
AMS : ESP32 + NRF24 + 1Wire-I2C мост DS2482 + счетчик DS2423 + сеть MySensors + редактирование страниц в браузере + Upload по воздуху + SPIFFS
Аватара пользователя
ser009
Сообщения: 595
Зарегистрирован: Сб окт 13, 2012 9:55 am
Благодарил (а): 4 раза
Поблагодарили: 43 раза

Re: Преобразование строки

Сообщение ser009 » Пн окт 01, 2018 5:11 am

У вас data2 является строкой String, а вы хотите float.
Создайте переменную типа float и уже в ней пишите значения.
http://cppstudio.com/post/792/
svetozar161
Сообщения: 72
Зарегистрирован: Пт янв 13, 2017 11:48 pm
Благодарил (а): 6 раз
Поблагодарили: 3 раза

Re: Преобразование строки

Сообщение svetozar161 » Вт окт 02, 2018 12:50 am

Подсказали сделать так:
Объявляем

Код: Выделить всё

float data1;
bool releSt = 0;
парсим строку из сериала: espdata&idesp=ESP826600895b59&hostname=ESP05&shtt=21.3&shth=62.7&uptime=95130&errconn=334&wanip=192.168.1.2

Код: Выделить всё

if (parameter.startsWith("espdata&idesp")) {        // Температура датчика в спальне ESP05
   data1 = atof(parameter.substring(50,54).c_str());
    Serial.println(data1);
  }
в сериале появляется "21.3"
цикл реле:

Код: Выделить всё

#define relePin 49 // пин реле

void testInit()
{
  pinMode(relePin, OUTPUT);
  digitalWrite(relePin, HIGH);
}
//==============
void testRele()
{ 
  if(!releSt && data1 > 23)
  {
      digitalWrite(relePin, HIGH);
  timeStamp();
  Serial.println(" Rele \"OFF\"");
  releSt = 1;
  #ifdef MAJORDOMO_FEATURE
        sendRequestM("Rele_kotla", 0);
      #endif
}
  if(releSt && data1 < 21)
  { 
  digitalWrite(relePin, LOW);
  timeStamp();
  Serial.println(" Rele \"ON\"");
  releSt = 0;
  #ifdef MAJORDOMO_FEATURE
        sendRequestM("Rele_kotla", 1);
      #endif
      }
И нихрена! Как включалось реле по целому числу, так и включается. Непонятно...
Аватара пользователя
ser009
Сообщения: 595
Зарегистрирован: Сб окт 13, 2012 9:55 am
Благодарил (а): 4 раза
Поблагодарили: 43 раза

Re: Преобразование строки

Сообщение ser009 » Вт окт 02, 2018 4:42 am

Попробуйте так.
Для начала создайте для реле отдельную функцию отвечающую за вкл и выкл
СпойлерПоказать

Код: Выделить всё

#define RELE_1_PIN 1

byte rele1State = 0;

void initReles() {
  pinMode(RELE_1_PIN, OUTPUT);
  moduleReles = ENABLE;
  started(F("RELE"), true);
}

void rele1On(){
   if(digitalRead(RELE_1_PIN)==LOW){
     digitalWrite(RELE_1_PIN, HIGH);
     rele1State = 1;
     }else{}
}
void rele1Off(){
  if(digitalRead(RELE_1_PIN)==HIGH){
     digitalWrite(RELE_1_PIN, LOW);
     rele1State = 0;
     }else{}
}
А функция вкл/выкл котла будет выглядеть так
СпойлерПоказать

Код: Выделить всё

void testRele(){ 
    if(rele1State==1 && data1 > 24){
     rele1Off();
    timeStamp();
    Serial.println(" Rele \"OFF\"");
    #ifdef MAJORDOMO_FEATURE
        sendRequestM("Rele_kotla", 0);
      #endif
  }
    if(rele1State==0 && data1 < 21){
{
    rele1On();
    Serial.println(" Rele \"ON\"");
    #ifdef MAJORDOMO_FEATURE
        sendRequestM("Rele_kotla", 1);
    #endif
  }
Ответить