Официальный сайт компании Arduino по адресу arduino.cc
Впихнуть Невпихуемое
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Прошу прощения за мой плохой французский в названии темы. Есть Uno, у нее 32 килобайта. Получил вот такую штуку:
Скетч использует 32362 байт (100%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 1759 байт (85%) динамической памяти, оставляя 289 байт для локальных переменных. Максимум: 2048 байт.
Тут можете спросить как мне это удалось, но не буду вдаваться в подробности. Если кратко -
#include <SoftwareSerial.h> #include <SPI.h> #include <swRTC.h> #include <Ethernet.h> #include <EthernetUdp.h> #include "SdFat.h" #include <dht11.h>
в дополнение - совсем немножко чисел с плавающей точкой и работа с классом String. И это я еще хотел веб морду там написать чтобы можно было по сети зайти с браузера и посмотреть что творится в железке, но понял что это мои мечты и дальше уведомления бродкастом по протоколу UDP (уже реализовано) дело не пойдет и "морда" будет написана под винду, благо много ума для этого не нужно чтобы пакет распарсить.
Все нужное, уточню что для чего. По Ethernet, а точнее EthernetUdp идет общение с внешним миром и синхронизация часов. Через SoftwareSerial опрашивается и управляется одна железяка. swRTC для часов реального времени. SdFat и SPI - чтобы на карту памяти что-то писать (логи, статистика). Все нужное. До получения данных с датчика температуры дело еще не дошло.
Теперь, собственно, вопрос. В каком направлении мне двигаться? (Гусары, молчать!)
Есть ли какая-то легкая замена SdFat, жрущая меньше памяти? Много ли я выиграю если откажусь от чисел с плавающей точкой (при желании, умножая на 1000 падает точность но укладываюсь в integer, говорят 2кб экономии), если перейду со String на массив байт? Никто случайно не пробовал кастрировать библиотеки Adruino, например, выпилить из Ethernet все что не нужно для UDP протокола (ICMP, TCP, предполагаю что от них солидный оверхед). Опыт возни есть, в свое время кастрировал системные модули Borland Studio и Delphi, и даже на assembler писал. У кого есть опыт написания "тяжелых" скетчей чтобы поделиться рекомендациями что из выше перечисленного будет эффективнее? Столкнулся еще с подвисанием железяки если код занимает слишком много памяти, видимо, где-то динамическое выделение валится...
Прежде, чем выносить какие-то оценочные суждения - надо бы увидеть хотя бы часть кода. Возможно, и даже скорее всего - там есть места, поддающиеся оптимизации.
если твоё рабочее время стоит дороже 500 р за день, то двигаться надо в сторону покупки Меги.
Моего кода там мало, основной объем тянется из стандартных библиотек. Вот например если убрать прием - отправку UDP пакетов - Скетч использует 24052 байт (74%) памяти устройства. Глобальные переменные используют 1392 байт (67%). С ним - Скетч использует 30002 байт (93%) памяти устройства. Глобальные переменные используют 1647 байт (80%). Больше всего экономиться если не использовать SdFat.h
Где-то писали что использовать String это плохая идея, но у меня в коде один раз формируется строка, она отправляется в USB для отладки (это можно и убрать) и передается функции, которая пишет ее в лог с текущим временем. Еще преимущество этого класса - конвертация чисел в строку. Вот начну я сейчас трахаться с самописным inttostr а окажется что экономия не существенна. Или наоборот, убрать в Delphi модуль SysUtils и получить -40 кб кода оптимизации. К сожалению, не знаю прикуп.
Если не рефлексировать - то самый простой путь, как посоветовали выше - взять Мегу 2560. Потому как надо ещё подумать - стоит ли тратить на оптимизацию время, если задача - частная, и не проще ли и дешевле (во всех смыслах) взять подходящий камень.
А если хотите подешевле - берите STM32f103c8t6 стоимостью с пачку сигарет. Без плясок с бубнами тут, конечно, не обойтись - но зато возможности!
Присоединяюсь к #1.
Присоединяюсь к #1.
а какая разница, что у ТС за код? оптимизация -- задача глубокого изучения программирования, если даже штатные функции работы с С-строками у ТС "самописные". Мега стоит 500р. А дальше уже автору решать, какая у него задача: улучшать навыки в программировании или получить результат. Путь к результату -- Мега. А Путь изучения -- долог м тернист! ;)))))
Постоянно впихиваю невпихуемое. Выкидывание float освободит 2-3, процедура получения температуры отожрет 3-4 кб. Закон подлости такой. Причём, библиотека Dallas снова притащит за собой float.
Тут надо 80% библиотек перешерстить, простой перестановкой кроватей делу не помочь.
Вот я именно про это. Всё от целей зависит. Нужен быстрый результат или есть спортивный интерес. Это как "ехать на работу на машине или на велике" - на выбор влияет огромная куча обстоятельств. Я вот, например, не езжу на велике потому, что в офисе душа нет.
А оптимизации и "стабилизации" там немеряно, это сразу видно. Например, если получение времени тащит за собой аж 10к (как он написал), почему бы не получить его at-командами практически даром? Если есть сомнения, что всё виснет из-за динамической памяти, почему бы уж хотя бы не проверять факт её успешного выделения (никто из новичков этого не делает)? Стринги сами по себе не так страшны, как навороченные операции с ними, которые и не такую память зафрагментируют, ну и т.д.
Евгений, как можно получить AT-командами время, если в хидерах чистейший Ethernet?
Вам дать код?
Он на самописном "сериале", прямой разбор буфера полученного по сериалу от ESP-шки - никаких библиотек. Все про всё (сериал + NTP +отладочная печать (через I2C)) - менее 500 строк.
простой перестановкой кроватей делу не помочь.
не скажите, иногда смена кровати значительно улучшает настроение )))
Вам дать код?
Он на самописном "сериале", прямой разбор буфера полученного по сериалу от ESP-шки - никаких библиотек. Все про всё (сериал + NTP +отладочная печать (через I2C)) - менее 500 строк.
Мы же обсуждаем, как впихнуть код топикстартера в его железо, а не в Ваше. Или я ошибаюсь?
Вам дать код?
Он на самописном "сериале", прямой разбор буфера полученного по сериалу от ESP-шки - никаких библиотек. Все про всё (сериал + NTP +отладочная печать (через I2C)) - менее 500 строк.
Это что за монстр, которому на еспэшке места мало, нейросеть ?
Мы же обсуждаем, как впихнуть код топикстартера в его железо, а не в Ваше. Или я ошибаюсь?
Ну, сами подумайте, как мы можем обсуждать код и железо ТС, если кроме "Uno" он не сказал ничего? Ни что там ещё, ни схемы, ни собственно кода - вообще ничего?
Нет предмета для обсуждения, мы просто так треплемся (ну, по крайней мере, я) :)))
Это что за монстр, которому на еспэшке места мало
Не мало (и не много) - даже попыток никаких не делалось. Изначальное проектное решение было использовать есп-шку исключительно как внешний девайс с интерфейсом AT-команд и ничего более. Т.е. она вообще не прошивалась, а работала с прошивкой, которую китайцы залили.
Нет предмета для обсуждения, мы просто так треплемся (ну, по крайней мере, я) :)))
Формально - так. На уровне интуиции - я по инклюдам понимаю, чего он там творит.
Мегу взять можно, но я хочу приключений. Если серьезно - уже придумал корпус и собрал всю схему, отладил ее модульно (кусками) и убедился что все работает, собрал - а потом понял что немножечко не хватает памяти. Хотя для меня 32 килобайта это выше крыши, писал уже что и на ассемблере работать приходилось. Еще не хочу мегу потому что это будет выглядеть как из пушки по воробьям, у меня еще на Uno свободных пинов куча осталась.
У меня только Uno и к нему шилд Ethernet + microSD, ну еще целая самопальная но это к делу не относится. Получить время из сырых заголовков входящих IP пакетов думаю реально но не думаю что это освободит место, скорее займет, потому время тикает с помощью swRTC а получается по NNTP (скетч чуть более чем стандартный, только вместо delay между запросом и ответом выполняются другие полезные задачи).
> а какая разница, что у ТС за код? оптимизация -- задача глубокого изучения программирования
Как-то именно так. Пробую значит сегодня избавиться от String, а после начинаю ковырять стандартные модули. Вчера с ethernet начал но не успешно, там простой копипаст библиотеки с переименованием приводит к конфликтам инклюдов, нужно чуть глубже копать.
Я бы на вашем месте с такого сложного не начинал. Для начала бы в dht поковырялся, float убрал, от стрингов избавился. swRTC заменил бы на нормальные часы типа DS3231 и пяток простых функций доступа к ним.
Вчера с ethernet начал но не успешно, там простой копипаст библиотеки с переименованием приводит к конфликтам инклюдов, нужно чуть глубже копать.
Вы надеялись создать копию библиотеки, просто переместив ее в другую папку? - это не работает. Ардуино ИДЕ вообще по барабану название папок, оно различает библиотеки по именам инклюдов. Если вы хотите создать свою копию библиотеки для редактирования - мало переместить ее в другую папку - нужно переименовать все инклюды уникальным образом, поменяв заодно имена включаемых файлов во всех директивах #include внутри всех файлов библиотеки.
Так что если библиотека большая и разветвленная - проще не связываться с копиями а просто править оригинал. И еще - имейте в виду, что если вы поправили библиотеку, то изменения вступят в силу только после перезапуска Ардуино или после очистки директории, где собираются временные люьектные файлы для сборки прошивки.
где собираются временные люьектные файлы для сборки прошивки.
какие? мошт, я пропустил чего?
Если вы хотите создать свою копию библиотеки для редактирования - мало переместить ее в другую папку - нужно переименовать все инклюды уникальным образом, поменяв заодно имена включаемых файлов во всех директивах #include внутри всех файлов библиотеки.
Не совсем так страшно надо делать, но процесс геморный )
Не совсем так страшно надо делать, но процесс геморный )
Ну не наю, если правлю, оставляю ее одну в папке библиотек. С проектом закончил-отладил, перемещаю в облако вместе с проектом, и возвращаю оригинал на место. Это ИМХО.
где собираются временные люьектные файлы для сборки прошивки.
какие? мошт, я пропустил чего?
ну я имел в виду, что если ты поправил строчку в библиотеке и хочешь, что изменения попали в текущий скетч - надо бы выполнить что-то типа make clean
Но послько такой команды в ИДЕ нет, то приходится либо перезапукать ИДЕ, либо, скажем, менять в настройках плату, компилировать, снова менять и компилировать вторично
Не совсем так страшно надо делать, но процесс геморный )
Ну не наю, если правлю, оставляю ее одну в папке библиотек. С проектом закончил-отладил, перемещаю в облако вместе с проектом, и возвращаю оригинал на место. Это ИМХО.
Я в project-name\src складирую, ибо надёжней иметь компилируемый комплект, чем через полгода влезать в отладку и вспоминать, чего ты там с бодуна нафиксил за это время в либе и почему всё перестало компилиться.
> Для начала бы в dht поковырялся, float убрал
Без него пока что памяти тоже не хватает, надо с чего-то более существенного начинать. Я еще не подключил термодатчик к схеме и код получения температуры закомментирован.
> swRTC заменил бы на нормальные часы типа DS3231
Часов на Ethernet+SD шилде, кажется, нет. Утяжелять схему еще и часами - идея так себе.
> мало переместить ее в другую папку - нужно переименовать все инклюды
походу и имена объектов внутри инклюдов, это то на что я нарвался. Оно цепляло все библиотеки и ругалось на дубликат описания класса, хотя из 2 библиотек инклюдилась только одна... вообщем надо разобраться будет.
> а просто править оригинал
Тоже вариант. Это мой единственный проект на Arduino, собрать, заархивировать включая каталог с библиотеками, если что нужно будет писать на стандартных - восстановить из бекапа. Все к этому и идет.
> файлы для сборки прошивки
Object файлы чтоли? :)
Вот из моих заметок. прирост % памяти и динамической памяти в скобках при раскомментировании директивы компилятора, ниже по коду все в #ifdef сидит чтоб не вспоминать где что забыл раскомментировать:
По swRTC не замерял хотя можно. От вебсервера я окончательно отказался, пока на 1 месте по прожорливости SdFat, за ним Ethernet. Пошел строки колупать, пока что от float отказываться не буду.
Я через всё это уже прошёл. На поиск ходов, которые я советую применить, были потрачены не часы, не дни, а недели и месяцы. Да и то я считаю, что не познал и пятой части...
Замеры потерь program space и ram методом отключения некоторого функционала могут дать ошибку процентов... в 20, скажем. Даже в разных версиях IDE можно получить разный ресурсный импакт . Потому что ход работы оптимизирующего компилятора практически непредсказуем для простого "пользователя".
Ethernet меньше чем в 10кб не всадить, SDFAT - не знаю, в лучшем случае пользовательский код со всем этим обвесом будет стартовать с отметки в 18-20кб. +3кб на float, +Serial... Ну и остаётся там килобайт 6-8 может. О каком там вебе говорить?
Замеры потерь program space и ram методом отключения некоторого функционала могут дать ошибку процентов... в 20, скажем. Даже в разных версиях IDE можно получить разный ресурсный импакт . Потому что ход работы оптимизирующего компилятора практически непредсказуем для простого "пользователя".
Но всеже койчего предсказать можна. Если некую базовую функцию использует несколько частей общего функционала то базовая функция уберется из кода только если уберутся все использующие её. Отсюда и погрешности. Нельзя просто суммировать замеры. Там может и поболе 20% набратся.
SDFAT действительно очень тяжолая.
Предсказать можно, если есть опыт и уже знаешь, как эти библиотеки изнутри выглядят и что у них общего. А так, с бухты-барахты - практически тыканье пальцем в небо.
Я уже дошёл до того, что между for и while выбираю последнее:
Предсказать можно, если есть опыт и уже знаешь, как эти библиотеки изнутри выглядят и что у них общего. А так, с бухты-барахты - практически тыканье пальцем в небо.
Я уже дошёл до того, что между for и while выбираю последнее:
Смотрю на код. Уверены что замена эквивалентная?
Чтоб не тыкать пальцем полезно постоянно следить за ресурсами. Добавил либу - посотрел чего "стоит", убрал еЁ но добавил вторую - тоже самое, включил обе - сново глянул. И так по ходу развития проекта, а не в конце рыдать и переписывать.
Во-во рефакториг это . Переписывание кода по частям . А по плач Ярославны DIYMan ничего не говорил. Хотя может технологически тоже надо.
Да, что-то я там единицу зря воткнул в условие. Однако я помню, что ко while я склонился на основе опытов. Надо будет вернуться к ним.
Всё, вспомнил. Экономил условием сравнения с нулём. Два байта цельных без оптимизации компилятором и 34 (в данном раскладе) - с оптимизацией.
Товарищи, а substr(string, index_from, count) для char array существует в природе или писать самому? Мне нужно из буфера данных повырезать нужные позиции по несколько символов и потом сконвертировать их в числовые значения...
Посмотрите тут: http://cppstudio.com/cat/309/325/
Спасибо. Memcpy вещь интересная, но уже написал свою с циклом. Благо там 2-5 знаков в подстроке, не так много итераций. Если будет не лень - перепишу еще раз.
Такс, первые результаты. 2 тестовых скетча, в одном из которых присутствует String Reply = ""; а в другом его нет (и больше никаких использований класса String отличаются на 1072 байта. Всего убрав substring, toFloat, toInt, toCharArray и что у меня там еще использовалось, заменив это кучей вызовов strcpy и strcat, а также посимвольным присвоением в цикле, получил экономию 2396 байт кода, что уже неплохо. Иду дальше...
Снова всплыл какой-то интересный баг с зависанием наглухо при вызове Udp.beginPacket(), который лечился исключительно выключением устройства на какое-то время.
Товарищи, а substr(string, index_from, count) для char array существует в природе или писать самому? Мне нужно из буфера данных повырезать нужные позиции по несколько символов и потом сконвертировать их в числовые значения...
Изучи, дорогой, полный набор стандарной библиотеки. Интересующие тебя функции в string.h.
https://www.nongnu.org/avr-libc/user-manual/modules.html
Это официальная страница avr-libc, на сайте Atmel есть копия.
Для инвалидов советского образования есть русский перевод где-то на народе.ру.... тут, на форуме, давали ссылку.
==================
(после редактирования):точно есть, её дал первый ответ яндекса: http://avr-libc.narod.ru/
Что не знаю, так это версию, которую там перевели, но для Уно и Нано, это не имеет значения.
Еще не хочу мегу потому что это будет выглядеть как из пушки по воробьям, у меня еще на Uno свободных пинов куча осталась.
Если не хватает памяти, то как может помочь избыток пинов? (нет, конечно, из каждого пина можно извлечь пару битов памяти, но не думаю, что это радикально изменит ситуацию)