Помогите со стрингами! :)
- Войдите на сайт для отправки комментариев
Добрый день!
Вопрос о работе с информацией - как хранить и обрабатывать, что-то я делаю не так и поэтому вылезает куча проблем.
Преамбула.
У меня нет программистского образования, но за свою жизнь сталкивался достаточно много - и в институте в лаборатории параллельно работал, писали СУБД бухгалтерскую, и на ПХП для сайта какую-то простейшую обработку тестов-опросников делал. Но - на ассемблере не писал и в отношении Си мой опыт был где-то на уровне "привет мир!"
Заинтересовался Ардуинками, начал разбирася с C#. Ковырялся со всякими более-менее простыми задачками - начиная с блинка и далее со всякими датчиками и устройствами. Ну вообщем-то для того, чтобы что-то изучить - надо найти для себя интересную задачу и постараться её решить и реализовать. Решил собрать высотомер-логгер - в простом варианте - включаясь, вычисляет на BMP280 высоту, присваевает переменной текущей высоты значение измеренной высоты (то есть текущая высота будет теперь привязана к нулю). И выводит значение температуры и высоты на дисплей 5110 84x84 LCD. И - пишет в файл строку с датой-временем и с текущей высотой (первая высота = 0). И далее в void loop при изменении высоты - выводит показания на экран и записывает в файл новую строку. Ну и естественно всё это завязано на RTC на DS1307, откуда берётся время.
"Амбула". Требующая "амбуланса" - "лечения".
Вначале я вообще хотел формировать строковую переменную - название файла - из текущего времени, полученного с RTC во время запуска - выполнения сетапа. Но - видно что-то я делаю не так, и создаётся впечатление, что строковые переменные "перегружают" память и ардуинка сходит с ума. Сейчас - название файла просто прописано заранее. Так - работает.
Мой вопрос заключается в том, как проще и правильнее обходиться с "текстовой" (?) информацией, как её "передавать" от устройства к устройству - в схеме - или "от объекта объекту - в программе"? может быть это неправильно, что я стал использовать String? возможно - это отжирает память? у меня и так получается большой код, в Ардуино Нано 168 - не умещается, только в Уно.
Вот код - который "работает если не включать ничего в void loop. Лишнее (работа с экраном и запись на СД - убрал пока из кода - там проблем сейчас нет, всё работает).
Пробовал переписывать код. Я до этого делал, что функция была "вынесена" - и вызываясь, возвращала значение в виде строки и присваивалось переменной (myTimeStamp = digitalClockString();). Решил - "меньше переменых" - думал если сразу "пихать информацию в строку" - то будет лучше работать - ан, нет.
В каком направлении "копать" - наставьте на путь истинный!
/*
* TimeRTC.pde
* example code illustrating Time library with Real Time Clock.
*
*/
#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
//
String myTimeStamp;
String mySaveFile;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// RTC has set the system time:
setSyncProvider(RTC.get); // the function to get the time from the RTC
digitalClockString();
mySaveFile = myTimeStamp;
Serial.print("Startup (setup) TimeStamp: ");
Serial.println(myTimeStamp);
Serial.println();
Serial.print("Startup (setup) mySaveFile: ");
Serial.println(mySaveFile);
Serial.println();
delay(4000);
digitalClockString();
Serial.print("Delayed TimeStamp: ");
Serial.println(myTimeStamp);
}
void loop()
{
// если включить эти строки - то код грузится, но ардуино - зависает и не выдает ничего в компорт.
// delay(4000);
// digitalClockString();
// Serial.print("Delayed TimeStamp: ");
// Serial.println(myTimeStamp);
}
/****************************************************************************/
/*****************all of my functions are down there*************************/
/****************************************************************************/
char digitalClockString() {
// digital clock display of the time
myTimeStamp = "";
if (hour() < 10) myTimeStamp.concat("0");
myTimeStamp.concat(hour());
myTimeStamp.concat(":");
if (minute() < 10) myTimeStamp.concat("0");
myTimeStamp.concat(minute());
myTimeStamp.concat(":");
if (second() < 10) myTimeStamp.concat("0");
myTimeStamp.concat(second());
myTimeStamp.concat("_");
if (day() < 10) myTimeStamp.concat("0");
myTimeStamp.concat(day());
myTimeStamp.concat("-");
if (month() < 10) myTimeStamp.concat("0");
myTimeStamp.concat(month());
myTimeStamp.concat("-");
myTimeStamp.concat(year());
return 0;
}
Заинтересовался Ардуинками, начал разбирася с C#.
В каком направлении "копать" - наставьте на путь истинный!
Для начала постарайте узнать на каком именно языке Вы программируете. А потом уже читайте литературу о том, как с ним работать. Именно с ним, а не с каким-то другим языком. Похоже Вы читаете литературу об одном языке, а пишете на другом. Отсюда и проблемы с памятью.
63 строка void
digitalClockString() {84 удалите нахрен.
Перед 17 строкой добавьте myTimeStamp.reserve(20);
Объясните мне и себе зачем вам переменная mySaveFile.
И внимательно прочитайте то что написал ЕвгенийП.
ПС: Язык он здесь в минимуме http://arduino.ru/Reference
Или здесь в углубленом виде http://cpp.com.ru/kr_cbook/index.html#content
просто изучите коды библиотеки RTC и примеров, в которых УЖЕ сделан вывод даты в строковом виде, например Rtc_by_Makuna.
ессно, на аглицком.
brokly, спасибо!
Вообщем-то самый толковый и по делу комментарий. То что вы написали - попробую вечерком подпавить, да, "даже странно что так написал". Видно - вылезло, когда для себя разбирался и пытался продифференцировать "переменную", "объект", "метод-процедуру/функцию".
И про reserve() - спасибо, интуитивно понимал, что "что-то с памятью моей стало" - но как её "зарезервировать" - не знал...
>> Объясните мне и себе зачем вам переменная mySaveFile.
Изначально в эту переменную записывалось значение времени при стартапе плюс ".txt" - и это должно было становиться именем файла, в который записываются данные текущей "измерительной сессии" (времени, когда устройство включено). То есть - "зесь и сейчас" - это лишнее...
wdrakula - спасибо за наводку на эту библиотеку РТС (Макуна) - у меня несколько других скачано и установлено, я и учился по примерам - сейчас посмотрю примеры в этой библиотеке - может быть действительно чего для себя найду того, что будет доступно моему разумению.
С английским проблем нет, наоборот иногда какие-то технические вещи проще на английском прочитать - более точно.
Так что - пока что всем большое спасибо, буду "грызть дальше".
Просто иногда - "не хватает опыта понять - где искать проблему"... я тут месяц назад убил день на попытки подключить 5110 84x84 LCD - что только не перепробовал... пока не выяснилось, что один из двух имевшихся в наличии дисплеев был "дохлым" - и гребёнку я запаял и соответственно "игрался" - с этим "дохлым"... Интерфейс-то у него работал, с ардуинкой общался по И2С - но только ничего не показывал. А я думал - что я неправильно библиотеку подключаю или ещё чего-то не так делаю. :)
63 строка void
digitalClockString() {Cобственно она появилась, когда я пытался "колдовать" - вместо String пытался символьный массив использовать, и там возвращалось значение (символьный массив). А когда это не помогло - уже начал "напрямую в переменную данные шлёпать по ходу выполнения метода".
Но всё равно - без "резервирования памяти" - "что-то шло не так".
Сейчас всё заработало, и я подправил в полном коде, где работают и другие датчики. Всё компилируется, имя файла теперь тоже - динамическое, - время/дата включения - правда в ардуину полный код пока не грузил - лень датчики прикручивать, жду, когда придёт пятивольтовая мини-про адруинка - чтобы сразу собрать и запаять на макетке всё вместе (на трёхвольтовой мини-про почему-то не пошёл барометр BMP20).
* * *
Нескромный вопрос - (книжку со временем почитаю) - а что, получается что в Си для строковых объектов надо вот так вот в явном виде определять область памяти? я пробовал добиться этого же изначальным присвоением при инициализации им некоторых значений - но это не давало результата...
Жесть. Прочел бы книгу, меньше вопросов было. Вот вы собираетестесь толпой на курорт. Места надо явно заказывать,звоня что бы там вам подготовили места, или же забить на все ,приехать и узнать что часть народа будет спать на улице. И еще есть строковые константы и строковые переменные. Первые храняться в памяти программы, а вторые в памяти ОЗУ.
Ну если памяти немерянно, то ее расход можно не контролировать. У ардуино память ограничена. Тут на сайте есть исследования ЕвгенияП, там доходчиво объяснено в чем косяк String. Вообще нужно знакть как си использует память, как правило все реализовано через кучи и "базовые" функции динамического выделения памяти malloc(). Если же вы четко знаете размер нужной вам переменной и правильно описываете ее, то помимо некоторой экономии памяти получаете возможность хранить ее в стеке. В общем это не "популярное" разъяснение, не смогу в двух словах объяснить.
Родной способ оперирования текстовыми строками это массив чаров, стринг сделан для облегчения работы со строками и как минус, не найден способ полного контроля над памятью. Если часто "дергать" стринг, то в большинстве случаев куча будет сильно дефрагментироватся и из оборота будут выпадать мелкие куски, они вроде как свободны, но никому не нужны. Отсюда и нехватка памяти.
Кстати да если Serial.print("Delayed TimeStamp: "); записать как Serial.print(F("Delayed TimeStamp: ")); вы заставите компилятор сохранять текстовые данные в памяти программы, а озу оставите свободным от этой длинно и ненужной строки.
https://www.arduino.cc/en/Reference/PROGMEM
#include <time.h>
Нескромный вопрос - (книжку со временем почитаю) -
Прекращаёте наглеть-то. Вам сказали что прочитать, так и читайте. Людям заняться нечем, кроме как перепечатывать здесь содержимое книг, которые Вы "со временем почитаете"?
На Ваш вопрос, я "со временем отвечу".
Не всегда к сожалению "прочтение" материала приводит к его "осознанию" и "пониманию". Я по интересующему меня вопросу (Strings) - много чего прочитал - в основном на англоязычных сайтах - и статей, и примеров. Но не заметил, чтобы выделяли память - может быть примеры были простенькие - или я просто не заметил.
Общие принципы мне вроде как понятно, но когда дело доходит до деталей - могу где-то "закапываться" - путаясь в обилии информации.
Сейчас - всё в порядке!
Но все эти строки нужны мне только на этапе отладки, когда всё будет собрано/спаяно и будет работать - всё это можно будет спокойно убрать, я это оставлял в первую очередь для того, чтобы понимать - "до какого момента программа доходит и на чём подвисает". Как-то я пока не научился более эффективно дебаггером пользоваться в VisualMicro.
brokly - ещё раз спасибо вам большое!
И еще есть строковые константы и строковые переменные. Первые храняться в памяти программы, а вторые в памяти ОЗУ.
Вот с этого момента поподробнее, пожалуйста.
...
Не всегда к сожалению "прочтение" материала приводит к его "осознанию" и "пониманию". Я по интересующему меня вопросу (Strings) - много чего прочитал - в основном на англоязычных сайтах - и статей, и примеров. Но не заметил, чтобы выделяли память - может быть примеры были простенькие - или я просто не заметил.
Да заметили Вы все. Только признатесь себе боитесь. Все эти либки , от stl до boost включая Strings всех пород - хрень несусветная, расчитаные на лохов поведущихся на шаровой код, они даже рядом не лежали с эффективной реализацией грамотного разраба. Пишите код сами, не расчитывайте на шару, так у вас возникнет понимание происходящего (Вам лично +10 в карму;) и эффективность решения - как побочный продукт понимания сущностей.
И еще есть строковые константы и строковые переменные. Первые храняться в памяти программы, а вторые в памяти ОЗУ.
Вот с этого момента поподробнее, пожалуйста.
Увы, сие кочует по всей научно-популярной литературе для непрограммистов. И ведь веришь, пока не доберешься до этих граблей.((((
Ну а это что?