"пропадают" данные в диаграмме

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

SHA_MAN пишет:

Не могу понять почему фокус с выносом во флеш не получается при формировании строки смс 

statusText = "F(I am here     )"; // + String (date)+ String (time) +String (lat)+String (lng));

Как правильно оформить синтаксис в таком случае, чтобы "подтягивались" значения из скетча к фразам из флеши? 

Блин, слушайте внимательно:

Вам не надо ничего "подтягивать". Константы из флеша печатайте прямо, а переменные части отдельно.

Как только Вы начинаете "подтягивать", т.е. формировать единую строку, Вы напрочь убиваете саму идею хранения во флеше, т.к. Вы вытаскиваете строку из флеша и формируете результирующую строку уже в оперативной памяти. За что боролись-то?

Можно, клнечно, сделать так. чтобы она формировалась в опреативке и сразу же после печати оперативка освобождалась. Но, Вы умеете это?

Не выпендирвайтесь и не формируйте единую строку. Константные части выводите отдельными print'ами прямо из флеша. Нафига Вам всё в одну строку формировать? Чем плохо выводить по частям?

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

У меня есть пример случая, в котором по частям выводить плохо (если интересно). Но он очень специфический и, конечно, может быть обойдён всякими методами.

Но в данном случае, конечно, овчинка выделки не стоит, соглашусь с ЕвгенийП.

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

const char text_elapsedTime[] PROGMEM = "Elapsed time (ms): ";

#define FSH_P(p) (reinterpret_cast<const __FlashStringHelper *>(p))

void setup() {
  Serial.begin(115200);
  Serial.println(String(FSH_P(text_elapsedTime)) + String(millis()));
}

Только всё равно это сравнимо с ударом сковородкой по голове. Гораздо "дешевле" по ресурсам сразу в Serial.print() передавать указатель на PGM-строку.

если заранее положить строчку в ПРОГМЕМ, а потом вывести двумя отдельными принтами -

const char text_elapsedTime[] PROGMEM = "Elapsed time (ms): ";

#define FSH_P(p) (reinterpret_cast<const __FlashStringHelper *>(p))

void setup() {
  Serial.begin(115200);
  Serial.println(FSH_P(text_elapsedTime)));
 Serial.print(millis());
}

то для однократного вызова это будет аналогично использованию F(), но зато если эта строка нужна нам в несколькиз местах программы - последний способ будет много экономичнее, чем несколько F() с одинаковым содержимым

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

Вообще-то, я просто не стал делать String allText = String(FSH_P(text_elapsedTime))+String(огроменное_число), что пытался сделать вопрошающий - подумал что и так будет понятно, как в String PGM засунуть.

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

sadman41 пишет:

String PGM засунуть.

Беда только в том, что ТС не понимает, что как только он пихает PGM в String, он получает копию в RAM (см. конструктор String). А если делать копию в RAM, то за что боролись?

SHA_MAN
Offline
Зарегистрирован: 10.05.2019

Cпасибо. Кажется дошло.  

serial.Print поделил построчно. 

Не могу осилить как это же проделать для строки смс statusText

statusText = "I am here    " + String (date)+ String (time) +String (lat)+String (lng));

Вот так по моему представлению оно должно было работать на начальном этапе.

Если пробовать по аналогии с serial.Print, то

statusText = (F( "I am here     ")); 
statusText += String (date);
statusText += String (time);
statusText += String (lat);
statusText += String (lng);

Это тождественно? или опять напутал?

Спасибо

b707
Offline
Зарегистрирован: 26.05.2017

что ж вы так тупите....

Вам же уже раз пять сказали - как только вы преобразуете строку в String - вся экономия памяти идет коту под хвост. Избавьтесь от класса String совсем.

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

SHA_MAN пишет:
опять напутал

Что у Вас делает строка

statusText = (F( "I am here     ")); 

???

Она создаёт копию "I am here " в оперативной памяти! 

Сдаётся мне, что все эти разные названия памятей для Вас тёмный лес, поэтому давайте, чтобы не путаться, я объясню Вам проще.

Всё, что Вы имеете право делать со строками из прогмем - это их печатать и ничего (совсем ничего, просто нихера) больше.

Т.е. Вы пишете примерно так.

float tempC = getTemperature();
Serial. priint(F"Temperature');
Serial.println(tempC );

// и НИКОГДА не пишете

String msg = F"Temperature'; // вот здесь Вы проср@ли свою экономию памяти!
msg += getTemperature();
Serial.println(msg);

И никак по-другому! Строки, начинающиеся с F имеют право встречаться ТОЛЬКО в виде аргумента print и быть там в одиночестве - безо всяких плюсов и любой другой херни.

Ни в каком другом месте эти строки не используйте.

SHA_MAN
Offline
Зарегистрирован: 10.05.2019

То, что во флеш можно только набор символов поместить и оттуда их печатать я понял. Благодаря этому уже почти 15% сэкономлено по результатам компиляции. Спасибо, это даже больше, чем я ожидал.

 

Цитата:
Строки, начинающиеся с F имеют право встречаться ТОЛЬКО в виде аргумента print и быть там в одиночестве - безо всяких плюсов и любой другой херни.

Я так и сделал уже. 

 Serial.println(F("location:"));
        Serial.println (lat);
        Serial.println (lng);
        Serial.println(F("date:"));
        Serial.println (date);
        Serial.println (time);

Работает. Процент загруженности меньше. Спасибо.

b707 пишет:
что ж вы так тупите....
:( я только учусь.

Цитата:
Сдаётся мне, что все эти разные названия памятей для Вас тёмный лес
Так и есть, не скрываю.

Я тотально запутался. 

b707 пишет:
Вам же уже раз пять сказали - как только вы преобразуете строку в String - вся экономия памяти идет коту под хвост. Избавьтесь от класса String совсем.

Не пойму никак, как я могу уйти от string вообще, если мне надо выводить для передачи в смс переменные? Переменные же не могу быть во флеши, если я верно понял.

Если можно построчно выводить в порт данные то из флеши то из скетча для реализации print, не смешивая их при этом по месту хранения и экономя при этом память, то (вот тут я спотыкаюсь) как аналогично сделать для statusText, если это вообще реально. Вывести и отправить "заготовки" текста из флеш и между ними данные из скетча. Вот тут я запнулся.
 
Спасибо большое, что не бросаете. 
sadman41
Offline
Зарегистрирован: 19.10.2016

Значения переменных, которые не отмечены клеймом PROGMEM на старте перегружаются из ROM в RAM. Таким образом, они одновременно существуют и в Progmem Space (ROM) и RAM. F() намекает функции, что всё, что внутри ея - нужно специальными методами читать из ROM. Т.е. println() чует, что ей передали адрес ячейки во ROM, а не в RAM и последовательно читает байтики из ячеек и отправляет куда сказано - в Serial, например. String же создаётся в RAM, засасывает туда все байты из ROM и существует до уничтожения. Т.е. получается то же самое, что и без F().

Вопрос формирования "заготовки" имеет более одного ответа и рассмотрен, например, тут. Однако, если Вы начинающий, то можете вполне себе продолжить выводит вперемешку текст и переменные. Для принимающей стороны нет особой разницы: 4 раза по 50 грамм или один раз по 200.