Отправка СМС с данными сенсора

DJ152
Offline
Зарегистрирован: 17.01.2016

Здравствуйте! 

Прошу помощи в указании на ошибки в реализации тривиальной задачи отправки смс с данными сенсора DS18b20 с использованием TinySine Shield GSM на Arduino Uno. В программировании не силён, но есть желание разобраться и реализовать этот проект для дачи. 

На данный момент: На LCD I2C экран выводится сообщение с температурой -127, что говорит о том, что контроллер не видит датчик. Сам дачтик подключён через беспаечную плату к 4 выходу.

На телефон присылается только сообщение с первоначальной строкой: "Starting ok". Данные датчика не отправляются.

Используемый код:

#include <SIM900.h>
#include <sms.h>
#include <OneWire.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#define ONE_WIRE_BUS 4 // DS18S20 wired to digital pin 4, same bus for all sensors



LiquidCrystal_I2C lcd(0x27,20,4); // Liquide crystal is a 4x20 LCD with I2C support
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress bathroom = { 0x10, 0x5E, 0xE8, 0x33, 0x02, 0x08, 0x00, 0xDB };   //Sensor 1


unsigned int swt = 0;  // flip for alternate the display btw temp and humidity



SMSGSM sms;

char number[]="+7912ХХХХХХХ";  // Destination number
char message[180];
char pos;
char *p;

void setup()
{
lcd.init();                      // initialize the lcd
lcd.backlight();                // Backlight ON
lcd.setCursor(0, 1);
lcd.print("     Ardui'Home   ");
lcd.setCursor(0, 2);
lcd.print("     Loading...   ");
sensors.begin();

sensors.setResolution(bathroom, 10);


Serial.begin(9600);
if (gsm.begin(2400))
Serial.println("\nstatus=READY");
else
Serial.println("\nstatus=IDLE");
(sms.SendSMS(number, "Starting ok !")); //sending sms when he starting up
pinMode(7, OUTPUT);                    // Pin 7 for bliking running led
}

void loop()
{
temps(); // calculate and displaying temps from DS18 and DHT sensor's
runingled();   //loop to displaying a running LED
}

void temps()
{
sensors.requestTemperatures();
float tbathroom = sensors.getTempC(bathroom); // Bathroom sensor


swt++; // Alternate displaying betwen DS18 and DHT sensors
if ((swt % 15) > 5 )
{
//////////////DS18B20 Sensors/////////////////
lcd.setCursor(0, 0);
lcd.print("Sdb         ");
lcd.print(tbathroom);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("                    ");
} 
}
/////////// Blink a Led to check if the code run correctly ///////////
void runingled()
{
digitalWrite(7, HIGH);
delay(80);
digitalWrite(7, LOW);
delay(1000);
}

 

Буду благодарен за любую помощь и совет. 

 

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

DJ152 пишет:

На телефон присылается только сообщение с первоначальной строкой: "Starting ok". Данные датчика не отправляются.

А должны? Покажите в какой строке. 

Пока я вижу во всём скетче единственную отправку смс в строке 48. Она, по Вашим словам, работает нормально. Никаких других отправок смс я в тексте программы не нашёл.

DJ152
Offline
Зарегистрирован: 17.01.2016

Теперь увидел, Вы правы. 

Нужно добавить в блок loop аналогичную функцию, заменив выражение на данные сенсора? 

(sms.SendSMS(number, "Starting ok !"));

И вопрос по самому датчику, почему он может не читаться на дисплее? Не в этой строке дело?

16 DeviceAddress bathroom = { 0x10, 0x5E, 0xE8, 0x33, 0x02, 0x08, 0x00, 0xDB };   //Sensor 1

 

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

DJ152 пишет:

И вопрос по самому датчику, почему он может не читаться на дисплее? Не в этой строке дело?

16 DeviceAddress bathroom = { 0x10, 0x5E, 0xE8, 0x33, 0x02, 0x08, 0x00, 0xDB };   //Sensor 1

Датчик не имеет никакого отношения к дисплею. Дело датчика выдать Вам цифирь, а дело дисплея эту цифирь показать. Т.е. ещё раз в строке 61 Вы получаете самое обыкновенное число типа float. На этом работа датчика закончилась. дальше Вы это число показываете на дисплее. Дисплею всё равно где Вы взяли это число - с датчика или руками вбили. Понимаете. что оно не могут быть ни совместимы, ни несовместимы друг с другом. Они друг другу фиолетово.

Теперь про эту строку. Это адрес датчика. Где Вы его взяли? Из какого-нибудь примера или прочитали со своего датчика? Если первое, то выбрасывайте - у каждого экземпляра датчика уникальный адрес.

И ещё. судя по коду Вы программируете свосем недавно. Тогда послушайте: я программирую почти сорок лет (с 1979 года) и я бы не взялся сразу писать Ваш скетч - это слишком сложно делать сразу. Я бы сначала отладил бы работу с датчиком. Для этого написал бы скетч БЕЗ экрана и БЕЗ смс - только датчик и вывод температуры в сериал. Потом бы я написал скеч для экрана БЕЗ датчика и БЕЗ смс - только вывод числа на экран. Число бы руками вбивал. Наконец, я бы написал скетч для смс БЕЗ датчика и БЕЗ экрана - отправлял бы вбитое руками число. И только когда все три куска у меня надёжно бы работали - я бы объединил их вместе.

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

DJ152
Offline
Зарегистрирован: 17.01.2016

Евгений, благодарю за помощь, но просьба понять правильно. Я не программирую на С. Я знаю HTML5, частично PHP и JS, но профессионально я занят совсем в другом направлении, я занимаюсь логистикой уже 15 лет и у меня нет в ближайшем будущем цели программировать для Ардуино. У меня есть конкретная цель запустить этот проект и всё.  Я перерыл весь интернет в поисках подходящего скетча но ни один не подошёл, поэтому вынужден был взять за основу близкий пример и вручную его дорабатывать.

Благодаря Вашим подсказкам мне уже удалось разобраться с выводом показания датчика на экран и регулярной отправкой СМС в цикле Loop. Но сейчас остался последний затык - не очень понимаю как указать вместо текстового сообщения именно значение температуры.

Если не затруднит, намекните пожалуйста.

  

#include <SIM900.h>
#include <sms.h>
#include <OneWire.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#define ONE_WIRE_BUS 4 // DS18S20 wired to digital pin 4, same bus for all sensors

LiquidCrystal_I2C lcd(0x27,20,4); // Liquide crystal is a 4x20 LCD with I2C support
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress bathroom = { 0x28, 0xFF, 0x32, 0x3D, 0x90, 0x15, 0x04, 0xC0 };   //Sensor 1

unsigned int swt = 0;  // flip for alternate the display btw temp and humidity

SMSGSM sms;

char number[]="+7912ХХХХХХХ";  // Destination number
char message[180];
char pos;
char *p;
char buffer1[] = "sensors";

void setup()
{
lcd.init();                      // initialize the lcd
lcd.backlight();                // Backlight ON
lcd.setCursor(0, 1);
lcd.print("     Ardui'Home   ");
lcd.setCursor(0, 2);
lcd.print("     Loading...   ");
sensors.begin();
sensors.setResolution(bathroom, 10);

Serial.begin(9600);
if (gsm.begin(2400))
Serial.println("\nstatus=READY");
else
Serial.println("\nstatus=IDLE");
(sms.SendSMS(number, "Starting ok !")); //sending sms when he starting up
pinMode(7, OUTPUT);                    // Pin 7 for bliking running led
}

void loop()
{
temps(); // calculate and displaying temps from DS18 and DHT sensor's
runingled();   //loop to displaying a running LED
}

void temps()
{
sensors.requestTemperatures();
float tbathroom = sensors.getTempC(bathroom); // Bathroom sensor

if (sms.SendSMS(number, buffer1))
        Serial.println("\nSMS sent OK");
delay(10000);

swt++; // Alternate displaying betwen DS18 and DHT sensors
if ((swt % 15) > 5 )
{
//////////////DS18B20 Sensors/////////////////
lcd.setCursor(0, 0);
lcd.print("Sdb         ");
lcd.print(tbathroom);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("                    ");
}
}
/////////// Blink a Led to check if the code run correctly ///////////
void runingled()
{
digitalWrite(7, HIGH);
delay(80);
digitalWrite(7, LOW);
delay(1000);
}

 

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

Я ек понял, вопроса. Разве в 67 строке у Вас не выводится температура?

Иил Вы про сообщение в строке 57? Оно что, всё время слово "sensors" шлёт?

Так вставьте перед ней (строкой 57) запись Вашей температуры в buffer1. Как-то примерно так:

dtostrf(tbathroom, sizeof(buffer1)-1, 1, buffer1);

 

DJ152
Offline
Зарегистрирован: 17.01.2016

Да, я про 57 строку, отправляло всё время слово "sensors".

Супер, помогло. Спасибо огромное за помощь! 

DJ152
Offline
Зарегистрирован: 17.01.2016

Всем доброго дня!

Вот ещё какой вопрос появился. Код доработал, передавая данные от 4 датчиков по событиям. Всё работает. Но, как только подключаю в коде вывод данных на lcd монитор (сейчас он в коде закомментирован), то при сработке события происходит перезагрузка и сообщения не приходят. Без монитора всё ок. Помогите понять логику. 

#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
#include <Wire.h>
#include <DallasTemperature.h>
//#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#include <OneWire.h>

DHT  sensor;
SMSGSM sms;
String smsText = "Motion detected";
String smsText1 = "GAZ - ALARM!";
String smsText2 = "Podval - Low temp!";
String smsText3 = "Room - Low temp!";
boolean started=false;
char sms_text[160];
char sms_text1[160];
char sms_text2[160];
char sms_text3[160];
char* smsNumbers[] = {"+7912ХХХХХХХ", "+7908ХХХХХХХ"}; // номера на которые необходимо отсылать аварийные сообщения
int ledPin = 13;
int pirPin = 7;
int val = 0;
int komnata;
#define analogInPin A0 // Датчик Газа к А0
#define ONE_WIRE_BUS 4 // DS18S20 подключаем к 4 пину
DeviceAddress podval = { 0x28, 0xFF, 0x32, 0x3D, 0x90, 0x15, 0x04, 0xC0 };   // Датчик в подвале
//LiquidCrystal_I2C lcd(0x27,20,4); // Liquide crystal is a 4x20 LCD with I2C support
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() 
{
  Wire.begin();
  pinMode (ledPin,OUTPUT);
  pinMode (pirPin, INPUT);
  pinMode(analogInPin, INPUT);  //определить выходной контакт для датчика газа
  sensors.begin();
  sensors.setResolution(podval, 10);
  
  Serial.begin(9600);
  if (gsm.begin(9600)) 
    {
        Serial.println("\nstatus=READY");
        started=true;
    } 
    else 
        Serial.println("\nstatus=IDLE");
        
//lcd.init();                      // initialize the lcd
//lcd.backlight();                // Backlight ON
//lcd.setCursor(0, 0);
//lcd.print("Home");
//lcd.setCursor(0, 1);
//lcd.print("Loading...");
        
}
void loop () 
{
  val = digitalRead(pirPin);
  digitalWrite(ledPin,val);

if (val == 1)
{
  smsText = smsText;
  smsText.toCharArray(sms_text,160);
  sms.SendSMS(smsNumbers,sms_text);
  String smsText = "Motion detected";
  delay(6000);
}

  int sensorValue = analogRead(analogInPin);
  
if (sensorValue >= 400)
{
  smsText1 = smsText1;
  smsText1.toCharArray(sms_text1,160);
  sms.SendSMS(smsNumbers,sms_text1);
  String smsText1 = "GAZ - ALARM!";
  delay(6000);
}  

  sensors.requestTemperatures();
  float tpodval = sensors.getTempC(podval); // Датчик температуры в подвале

if (tpodval > 27)
{
  smsText2 = smsText2;
  smsText2.toCharArray(sms_text2,160);
  sms.SendSMS(smsNumbers,sms_text2);
  String smsText2 = "Podval - Low temp!";
  delay(6000);
  
}

  komnata = sensor.read(5); // нужно указать № вывода для DHT (сейчас 5pin)

if (sensor.tem > 27)
{
  smsText3 = smsText3;
  smsText3.toCharArray(sms_text3,160);
  sms.SendSMS(smsNumbers,sms_text3);
  String smsText3 = "Room - Low temp!";
  delay(6000);
  
}  

//lcd.setCursor(0, 0);
//lcd.print("T1 ");
//lcd.print(tpodval);
//lcd.setCursor(7, 0);
//lcd.print("G ");
//lcd.print(sensorValue);
//lcd.setCursor(0, 1);
//lcd.print((String)"T2 "+sensor.hum+"% "+sensor.tem+"C");

}

 

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

А что там говорит про память после компиляции (ну. если раскомментировать использование экрана)?

DJ152
Offline
Зарегистрирован: 17.01.2016

С закомментированным экраном - Скетч использует 16 372 байт (50%) памяти устройства. Всего доступно 32 256 байт. Глобальные переменные используют 1 746 байт (85%) динамической памяти, оставляя 302 байт для локальных переменных. Максимум: 2 048 байт. Недостаточно памяти, программа может работать нестабильно.

После добавления экрана значения меняются на 63% и 88% соответствено.  Но первый вариант работает, даже с учётом такого. 

В этом всё дело? как можно оптимизировать использование памяти?

 

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

Ой, с памятью у Вас полный кошмар. Вот только первое, что бросается в глаза при беглом взгляде.

В строках 17-20 Вы завели 4 буфера пщ 160 байтов, но используете их строго по одному. Они никогда не нужны Вам все вместе. Почему не обойтись одним? Это сэкономит 160*3=480 байтов, т.е. 23% ВСЕЙ Вашей памяти! Нехило?
 
В 12 строке Вы заводите строку smsText. а в строке 69 зачем-то ещё одну. Именно заводите ещё одну, а не используете ту, что есть. То же самое касается и smsText1,  smsText2,  smsText3.
 
Это только первый взгляд, подробно не разбирался.
DJ152
Offline
Зарегистрирован: 17.01.2016

Учёл Ваши замечания, убрал задвоения, уменьшил память до 

Скетч использует 20 358 байт (63%) памяти устройства. Глобальные переменные используют 1 127 байт (55%) динамической памяти.
Но проблема не решилась, при достижении события экран сначала замирает на 6 секунд,  указанных в delay, затем полностью перезагружается в Setup и на этом всё по новой в цикл до следующей сработки. Отправка СМС при этом не происходит.   
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Выложите текущий скетч, я завтра посмотрю.

DJ152
Offline
Зарегистрирован: 17.01.2016
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
#include <Wire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#include <OneWire.h>

DHT  sensor;
SMSGSM sms;

boolean started=false;

char smsNumber[] = "+7912ХХХХХХХ"; // номер на который необходимо отсылать аварийные сообщения
int ledPin = 13;
int pirPin = 7;
int val = 0;
int komnata;
#define analogInPin A0 // Датчик Газа к А0
#define ONE_WIRE_BUS 4 // DS18S20 подключаем к 4 пину
DeviceAddress podval = { 0x28, 0xFF, 0x32, 0x3D, 0x90, 0x15, 0x04, 0xC0 };   // Датчик в подвале
LiquidCrystal_I2C lcd(0x27,20,4); // Liquide crystal is a 4x20 LCD with I2C support
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() 
{
  Wire.begin();
  pinMode (ledPin,OUTPUT);
  pinMode (pirPin, INPUT);
  pinMode(analogInPin, INPUT);  //определить выходной контакт для датчика газа
  sensors.begin();
  sensors.setResolution(podval, 10);
  
  Serial.begin(9600);
  if (gsm.begin(9600)) 
    {
        Serial.println("\nstatus=READY");
        started=true;
    } 
    else 
        Serial.println("\nstatus=IDLE");
        
lcd.init();                      // initialize the lcd
lcd.backlight();                // Backlight ON
lcd.setCursor(0, 0);
lcd.print("Home");
lcd.setCursor(0, 1);
lcd.print("Loading...");
        
}
void loop () 
{
  val = digitalRead(pirPin);
  digitalWrite(ledPin,val);

if (val == 1)
{
  char sms_text[160];
  String smsText = "Motion detected";
  smsText = smsText;
  smsText.toCharArray(sms_text,160);
  sms.SendSMS(smsNumber,sms_text);
  delay(6000);
}

  int sensorValue = analogRead(analogInPin);
  
if (sensorValue >= 400)
{
  char sms_text1[160];
  String smsText1 = "GAZ - ALARM!";
  smsText1 = smsText1;
  smsText1.toCharArray(sms_text1,160);
  sms.SendSMS(smsNumber,sms_text1);
  delay(6000);
}  

  sensors.requestTemperatures();
  float tpodval = sensors.getTempC(podval); // Датчик температуры в подвале

if (tpodval > 27)
{
  char sms_text2[160];
  String smsText2 = "Podval - Low temp!";
  smsText2 = smsText2;
  smsText2.toCharArray(sms_text2,160);
  sms.SendSMS(smsNumber,sms_text2);
  delay(6000);
  
}

  komnata = sensor.read(5); // нужно указать № вывода для DHT (сейчас 5pin)

if (sensor.tem > 27)
{
  char sms_text3[160];
  String smsText3 = "Room - Low temp!";
  smsText3 = smsText3;
  smsText3.toCharArray(sms_text3,160);
  sms.SendSMS(smsNumber,sms_text3);
  delay(6000);
  
}  

lcd.setCursor(0, 0);
lcd.print("T1 ");
lcd.print(tpodval);
lcd.setCursor(7, 0);
lcd.print(" G ");
lcd.print(sensorValue);
lcd.setCursor(0, 1);
lcd.print((String)"T2 "+sensor.hum+"% "+sensor.tem+"C");
delay(1000);
}

 

DJ152
Offline
Зарегистрирован: 17.01.2016
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
#include <Wire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>

SMSGSM sms;
boolean started=false;

char smsNumber[] = "+7912ХХХХХХХ"; // номер на который необходимо отсылать аварийные сообщения
int ledPin = 13; // Диод
int pirPin = 7; // Подключаем датчик движения к 7 пину
int val = 0; // Обнуляем датчик движения 

#define analogInPin A0 // Датчик Газа к А0
#define ONE_WIRE_BUS 4 // DS18S20 подключаем к 4 пину
DeviceAddress kotel = { 0x28, 0xFF, 0x32, 0x3D, 0x90, 0x15, 0x04, 0xC0 };   // Датчик котла
LiquidCrystal_I2C lcd(0x27,20,4); // Подключаем монитор 
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() 
{
  Wire.begin();
  pinMode (ledPin,OUTPUT);
  pinMode (pirPin, INPUT);
  pinMode(analogInPin, INPUT);  //определить выходной контакт для датчика газа
  sensors.begin();
  sensors.setResolution(kotel, 10);
  
  Serial.begin(9600);
  gsm.begin(9600); 
    
  lcd.init();                      // Включаем lcd
  lcd.backlight();                // Backlight ON
  lcd.setCursor(0, 0);
  lcd.print("Home");
  lcd.setCursor(0, 1);
  lcd.print("Loading...");
}

void loop () 
{
  val = digitalRead(pirPin);
  digitalWrite(ledPin,val);
  int sensorValue = analogRead(analogInPin);
  sensors.requestTemperatures();
  float tkotel = sensors.getTempC(kotel); // Датчик температуры в подвале
  
if (val == 1)
{
  char sms_text[160];
  String smsText = "Motion detected";
  smsText = smsText;
  smsText.toCharArray(sms_text,160);
  sms.SendSMS(smsNumber,sms_text);
  delay(6000);
}
  
      else if (sensorValue >= 400)
      {
        char sms_text1[160];
        String smsText1 = "GAZ - ALARM!";
        smsText1 = smsText1;
        smsText1.toCharArray(sms_text1,160);
        sms.SendSMS(smsNumber,sms_text1);
        delay(6000);
      }  

              else if (tkotel > 27)
              {
                char sms_text2[160];
                String smsText2 = "Kotel - Low temp!";
                smsText2 = smsText2;
                smsText2.toCharArray(sms_text2,160);
                sms.SendSMS(smsNumber,sms_text2);
                delay(6000);
                
              }

                              else 
                              {
                                lcd.setCursor(0, 0);
                                lcd.print("Temp Kotel: ");
                                lcd.print(tkotel);
                                lcd.setCursor(0, 1);
                                lcd.print("Gaz level: ");
                                lcd.print(sensorValue);
                                delay(1000);
                              }
}

Евгений, благодарю Вас ещё раз за помощь!

Изменил немного логику работы программы, теперь всё работает в целом как нужно. 

Код рабочий, если кому будет нужен.

Остался один момент - это delay - позже сам разберусь как его корректно на millis заменить, чтобы экран не замирал на время отправки СМС и чтобы СМС не сыпались при этом каждую секунду. 

Araris
Offline
Зарегистрирован: 09.11.2012

Да чего там разбираться :

1. В начале скетча заведите некую переменную, например, unsigned long lastSendSMSmillis;

Также можно обозначить значение (в миллисекундах) минимального промежутка времени между отправками SMS, например #define SMSInterlapse 60000 // пусть будет минута

2. Перед каждым вызовом sms.SendSMS() вставьте строку lastSendSMSmillis = millis();

3. К каждому if, управляющему вызовом sms.SendSMS(), добавьте ещё одно условие && (millis() - lastSendSMSmillis > SMSInterlapse)

4. Все строки delay(6000); смело вычищайте.

UPD: Можно усложнить, сделав разную частоту отправок для разных событий.

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

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

Про delay, там несложно.

DJ152
Offline
Зарегистрирован: 17.01.2016

Araris пишет:

Да чего там разбираться

UPD: Можно усложнить, сделав разную частоту отправок для разных событий.

Спасибо огромное за подсказку! Теперь всё хорошо. Отличный форум и люди отзывчивые)

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

частота отправок вроде бы не требуется разная, но подумаю.  

 

Евгений, согласен, так действительно лучше, но Вы правда сильно помогли мне

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

а, никто не отправлял длинные значения в смс???

точнее все в одну строку - некрасиво выходит, а как делать в отправляемой  смс перенс строки:

TEMP1: +38 TEMP2: +40 TEMP3: +10

 

или

 

TEMP1: +38С
TEMP2: +40С
TEMP3: +10С

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

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

А что - \r\n уже отменили?