Оптимизация размера скетча
- Войдите на сайт для отправки комментариев
Доброго времени суток, всем. Хочу обратиться к болле опытным когегам с вопросом об оптимизации ардуиновского скетча. Уже почти дописал прошивку для своего проекта, но встал вопрос о подключении модуля для работы с micro-SD картами. Ситуация следующая:
* Флеш-памяти для хранения скетча - 29696 байт
* Уже написаная програма занимает 12970 байт (43% памяти устройства)
* Придется подключить еще 12784 байт (еще 43% памяти устройства), так как подключаются используемые функции с библиотек SD.h и SPI.h
Выходит после такого подключения останется 3942 байта, чего будет определенно недостаточно для описания логики считывания и записи на sd-карту, а мне еще нужен запас памяти под еще несколько модулей. Как же мне оптимизировать код? Конкретно интересуют следующие вопросы:
-Какие впринципе есть способы уменьшить размер скетча не переходя на чистый С++ или Assembler?
-Влияет ли на использования памяти размер названий переменных и функций?(простите за тупой вопрос, но а вдруг?)
-Возможно ли оптимизировать библиотеку math.h, в часности функции sin(), cos(), tan(), pow(), sqrt() для использувание меньшего количества флеш-памяти?
Буду очень благодарен за ваши советы.
P.S.: уже полностью убрал с кода Serial, что позволило уменьшить размер кода на 6%.
Взять другой МК с большей памятью или урезать хотелки.
К сожалению не вариант. Если бы так можно было - уже б сделал. Заказывать новый микроконтроллер и ждать доставку - слишком долго, а по-поводу урезания хотелок, то думаю можно было бы использувать EEPROM, но за полным отсутсвием опыта использывания не знаю столит ли лезть в эти дебри, тем более хоть и по-идеи памяти ардуинки для этого хватит, но сделать постоянное считывание и запись текста в EEPROM, учитывая, что текста будет несколько килобайт, будет очень геморойным занятием, тем более, что текст нужно делить на небольшие кусочки для показа на маленьком экране.
раз задаёте подобные вопросы - сами вы это не сделаете (если даже это сможет помочь всунуть все ваши хотелки в код для вашего мк)
вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.
К сожалению не вариант. Если бы так можно было - уже б сделал. Заказывать новый микроконтроллер и ждать доставку - слишком долго,
Все стальные варианты - еще дольше.
Заказанное Вы получите через пару месяцев. Провести серьезную оптимизацию кода за это время Вы явно не успеете.
а по-поводу урезания хотелок, то думаю можно было бы использувать EEPROM, но за полным отсутсвием опыта использывания не знаю столит ли лезть в эти дебри, тем более хоть и по-идеи памяти ардуинки для этого хватит, но сделать постоянное считывание и запись текста в EEPROM, учитывая, что текста будет несколько килобайт, будет очень геморойным занятием, тем более, что текст нужно делить на небольшие кусочки для показа на маленьком экране.
Во-первых, в том контроллере, о котором Вы пишете, EEPROM всего 1 кбайт. А во-вторых, служит эта EEPROM совсем для других целей, и вряд ли, путем использования EEPROM Вам удастся сократить хотя бы один байт во FLASH.
Заметно сократить объем кода можно, отказавшись от использования данных с плавающей точкой. Но вряд ли это Вам по силам.
Т.о. надеяться можно лишь на следующее:
1. На то, что и первые 12к и вторые 12к используют одни и те же функции, следовательно, их объединение окажется замеьтно меньше 24к.
2. Если Вы будете грузить скетч не через встроенный загрузчик, а через внешний программатор, доступный объем памяти возрасет с 29к до 32к.
Но, в любом случае, самый простой способ - выбрать контроллер с достаточным объемом памяти.
Чистый С++ легко добавит в прошивку ещё килобайт пять ))
Не знаю, как более опытные коллеги, но я бы без осмотра пациента вообще не брался бы ничего предсказывать. Оптимизация в компиляторе - штука хитрая. Можно полкилобайта сэкономить, а можно и килобайт потерять чисто на неправильной организации кода.
Спасибо за ответ, но когда я говорил про EEPROM, я имел ввиду использование его вместо sd-карты для хранение текста, который будет вводить пользователь.
Чистый С++ легко добавит в прошивку ещё килобайт пять ))
Не знаю, как более опытные коллеги, но я бы без осмотра пациента вообще не брался бы ничего предсказывать. Оптимизация в компиляторе - штука хитрая. Можно полкилобайта сэкономить, а можно и килобайт потерять чисто на неправильной организации кода.
У меня в первой часте примерно 450 строк кода, при этом 99% строчек кода прокомментировано(в некоторых случаях даже когда это необязательно уже было), его я думаю оптимизировать можно, но врятли кто-то захочет в таком огромном исходнике копаться кроме меня(по-крайней мере за бесплатно).
Ну выложите, по диагонали хотя бы глянем на досуге
Библиотека для SD жрет много памяти из-за поддержки FAT. Если файловая система не обязательно (писать поблочно) то можно сильно уменьшить занимаемую память.
Здесь был код, но так, как он больше не нужен, я его удалил, так как по-нему можно узнать некую информацию, за которую... Впрочем не важно
Уже самому пришли светлые идеи в голову и удалось уменьшить размер с 12970 байт до 11152 путём заминение переменной String, которую меня бес попутал использовать как тригер в первом файле скетча. Выбросил Serial.print() и стало вообще 10368 байтов...
Испанский стыд... Так сильно извращаться с оптимизацией второй части и совсем забыть о банальных вещах во второй. Вообщем спасибо всем, кто помогали и простите все, у кого я скушал немного времени. Скетч занимает всего лишь 34% памяти в конечном результате и это вполне допустимо.
Ну конечно привет всем тем, кто в меня не верил(и не важно, что я по-сути просто починил то, что сам и сломал), а в часности автору вот-этого кусочка:
раз задаёте подобные вопросы - сами вы это не сделаете (если даже это сможет помочь всунуть все ваши хотелки в код для вашего мк)
вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.
У меня в первой часте примерно 450 строк кода,
....
но врятли кто-то захочет в таком огромном исходнике
Спасибо, насмешили :) 450 строк - это не огромный, это маленький исходник. Выкладывайте.
Ну конечно привет всем тем, кто в меня не верил(и не важно, что я по-сути просто починил то, что сам и сломал), а в часности автору вот-этого кусочка:
раз задаёте подобные вопросы - сами вы это не сделаете (если даже это сможет помочь всунуть все ваши хотелки в код для вашего мк)
вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.
вы вроде тему подняли по такой проблеме
* Флеш-памяти для хранения скетча - 29696 байт
* Уже написаная програма занимает 12970 байт (43% памяти устройства)
* Придется подключить еще 12784 байт (еще 43% памяти устройства), так как подключаются используемые функции с библиотек SD.h и SPI.h
ваш подвиг пока не решает вашей проблемки.
Ну конечно привет всем тем, кто в меня не верил(и не важно, что я по-сути просто починил то, что сам и сломал), а в часности автору вот-этого кусочка:
раз задаёте подобные вопросы - сами вы это не сделаете (если даже это сможет помочь всунуть все ваши хотелки в код для вашего мк)
вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.
вы вроде тему подняли по такой проблеме
* Флеш-памяти для хранения скетча - 29696 байт
* Уже написаная програма занимает 12970 байт (43% памяти устройства)
* Придется подключить еще 12784 байт (еще 43% памяти устройства), так как подключаются используемые функции с библиотек SD.h и SPI.h
ваш подвиг пока не решает вашей проблемки.
Да нет. Я выбросил все String`и и полностью убрал с кода Serial и у меня около 20% памяти устройства точно сэкономлено, а так как при подключении, конечный скетч весит не скетч1+скетч2, то всё влаазит. Ведь нужно не забывать, что учитывается еще вес загрузчика и стандартной библиотеки. Вообщем могу дать совет всем, кто в будущем возможно столкнеться с моей проблемой: в первую очередь удалите Serial и используйте массив символов, вместо String - это действительно экономит просто зверское кол-во флеш-памяти.
это с натяжкой можно назвать оптимизацией)))))
это с натяжкой можно назвать оптимизацией)))))
Мне этого хватило. И почему это не можно назвать оптимизацией? Задача стояла оптимизировать размер кода, дабы освободить флеш память и для этого я сделал следующие:
* отказался от String как таковой
* убрал все сообщения в монитор порта
* сжал все переменные типа int к short int, где это возможно
Оптимизация бывает разная и это необязательно должно быть осовобождение ОЗУ или снижение нагрузки на процессор(хотя это тоже произошло), так что названия темы соответсвует вопросу в полной мере.
* сжал все переменные типа int к short int, где это возможно
1) A short is a 16-bit data-type.
2) On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value.
* сжал все переменные типа int к short int, где это возможно
1) A short is a 16-bit data-type.
2) On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value.
я бы еще добавил, что на размер занятого флеша это вообще не влияет :)
Вот если бы ТС выкинул из программы все float и перешел на целочисленные вычисления - результат бы его поразил :)
* сжал все переменные типа int к short int, где это возможно
1) A short is a 16-bit data-type.
2) On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value.
я бы еще добавил, что на размер занятого флеша это вообще не влияет :)
Вот если бы ТС выкинул из программы все float и перешел на целочисленные вычисления - результат бы его поразил :)
Кстати вы оба правы)) Наконец-то дельные советы подъехали, а то всё либо "у тебя ничего не получится" либо "физически возьми больше памяти". Спасибо, что обратили внимание - переменные типа short int действительно лучше заменить на byte и сэкономить еще байтов 10-15 ОЗУ, ведь там у меня уже тоже мрак, причём на целый килобайт. Может еще кто-нибудь подскажет как оптимизировать использование sd-карты? Если не трудно, можете сбросить ссылку об использовании карточки без файловой системы, а то все говорят, что это существенно уменьшает размеры скетча через выброс с него громоздких библиотек, а url никто не бросит.
А на счёт выбросить все float, то идея конечно хороша, но в моём проекте, к сожелению, недопустимая.
Ну потому что он не нужен :)
Sketch uses 2,922 bytes (9%) of program storage space. Maximum is 30,720 bytes.
Ну потому что он не нужен :)
Sketch uses 2,922 bytes (9%) of program storage space. Maximum is 30,720 bytes.
Эххх... Спасибо. Чертовски хороший код, жаль что у не смогу его использовать, т.к. использую не оригинальную ардуинку, а аналог от компании wavgat и у меня чисто не компилится из-за устаревшей версии ядра. Даже использование самой старой версии биюлиотеки sdFat вызывает ошибку... :(
Врятли это что-то даст, но если что, вот сама ошибка:
попробуйте обновить ide
https://github.com/greiman/SdFat/issues/66
использую не оригинальную ардуинку, а аналог от компании wavgat и у меня чисто не компилится
Купите нормальную ардуину, не оригинал, а обычную китайскую, только не Вавгат- она стоит не дороже 200 рублей. А с Вавгатом вы еще намучаетесь и потом, скорее всего, все равно перейдете на нормальную плату.
попробуйте обновить ide
https://github.com/greiman/SdFat/issues/66
Спасибо за совет... Кароче чуть не сдох, пока переустановил IDE, вернул все библиотеки, залил ядро Wavgat и вавгатовские библиотеки, но самое главное, что проблема не только осталась, но теперь у меня еще й SPI.h не компилируется и это уже *цензура*, *цензура*, *цензура*.
использую не оригинальную ардуинку, а аналог от компании wavgat и у меня чисто не компилится
Купите нормальную ардуину, не оригинал, а обычную китайскую, только не Вавгат- она стоит не дороже 200 рублей. А с Вавгатом вы еще намучаетесь и потом, скорее всего, все равно перейдете на нормальную плату.
Да я уже 100500 раз пожелел о том, что купил этот кусок... кхм... платы. Только вот новую плату из Китая ждать месяц-два, а мне нужно проект доделать раньше.
Вообщем я уже вовсе не понимаю почему у меня не работает вавгатовская библиотека... Вот такая у меня теперь, даже не ошибка, а ошибище:
Ну потому что он не нужен :)
Sketch uses 2,922 bytes (9%) of program storage space. Maximum is 30,720 bytes.
Ну блин, ну не могу скомпилить твой скетч - хоть убейся. Но вроде как проблема именно в библиотеке SdFat.h, которая не хочет взаимодействовать с WAVGAT UNO R3. Есть ли какой-то аналог этой библиотеки?
Ошибка осталась та же самая, yield() не объявлен, это не проблема библиотеки sdfat, кстати, одной из лучших. Попробуйте выставить просто UNO в платах, не wavgat, тоже не собирается? Аналог - ардуиновская родная библиотека sd.h.
Да я уже 100500 раз пожелел о том, что купил этот кусок... кхм... платы. Только вот новую плату из Китая ждать месяц-два, а мне нужно проект доделать раньше.
А там где вы живете просто пойти в магазин и купить ардуино нельзя? Пусть не за 200 - а за 400 рублей? Это явно будет эффективнее, чем трахаться с Вавгатом
Ошибка осталась та же самая, yield() не объявлен, это не проблема библиотеки sdfat, кстати, одной из лучших. Попробуйте выставить просто UNO в платах, не wavgat, тоже не собирается? Аналог - ардуиновская родная библиотека sd.h.
Да... вы правы. Под ардуино уно всё собралось и заняло 9% памяти как вы и писали. Только с вавгатом оно походу дружить не будет, а других плат под рукой сейчас нет... Ладно, колупаюсь с SD.h и надеюсь, что памяти хватит.
Да я уже 100500 раз пожелел о том, что купил этот кусок... кхм... платы. Только вот новую плату из Китая ждать месяц-два, а мне нужно проект доделать раньше.
А там где вы живете просто пойти в магазин и купить ардуино нельзя? Пусть не за 200 - а за 400 рублей? Это явно будет эффективнее, чем трахаться с Вавгатом
Знаете, если б у меня был бы такой вариант - уже б купил бы три раза, я компанию Wavgat уже ненавижу просто, но есть только эта плата и купить сейчас возможности нету - только заказывать и ждать месяц-два, что уж точно не вариант.
Знаете, если б у меня был бы такой вариант - уже б купил бы три раза
Вы не отказывайтесь сразу - а просто подумайте.Похоже, вы просто не все варианты учитываете. Знаете. если вы не на льдине дрейфуете и не сейнере в море.... из любого уголка "нашей необьятной Родины" можно добраться до города с миллионным населением менее чем за сутки - а в любом городе-миллионнике можно купить ардуино Уно с получением "сразу"
И второй совет - вот прямо сейчас, сразу, сегодня вечером - закажите на Али пару-тройку Уно и Нано. Может статься, что вы свой проект еще полгода делать будете - а платы уже придут.
Знаете, если б у меня был бы такой вариант - уже б купил бы три раза
Вы не отказывайтесь сразу - а просто подумайте.Похоже, вы просто не все варианты учитываете. Знаете. если вы не на льдине дрейфуете и не сейнере в море.... из любого уголка "нашей необьятной Родины" можно добраться до города с миллионным населением менее чем за сутки - а в любом городе-миллионнике можно купить ардуино Уно с получением "сразу"
И второй совет - вот прямо сейчас, сразу, сегодня вечером - закажите на Али пару-тройку Уно и Нано. Может статься, что вы свой проект еще полгода делать будете - а платы уже придут.
Хорошо, спасибо за совет)) Платы сейчас закажу. Правда надеюсь проект закончу уже за дня три-четыре, ведь главная боль, основная логика роботы уже прописана. Осталось только настроить чтение с сд карты и запись на сд карту используя для записи данные полученые с блютуз модуля. Звучит, конечно, просто, но зная то, что это вавгат, а я еще довольно "новичковый" человек в электронике, то я думаю еще столкнуся как минимум с проблемами с чёртовым блютуз модулём.
А на счёт "дрейфования на льдине", то это почти про меня)))
А на счёт выбросить все float, то идея конечно хороша, но в моём проекте, к сожелению, недопустимая.
Это Ваше личное мнение.
Никаких доводов в его пользу Вы не приводите.
Это - первое.
И воторое. Я, конечно, могу ошибаться, но у меня сложилось впечатление, что ситуацию, когда занято 24 из доступных 29 кбайт Вы оцениваете как катастрофическую, а экономию в 2 кбайта - как решение. Лично мне такие оценки кажутся несколько странными. Конечно, 7 свободных кбайт лучше, чем 5, но не до такой же степени!
[/quote]
Вот если бы ТС выкинул из программы все float и перешел на целочисленные вычисления - результат бы его поразил :)
[/quote]
Извините за глупый вопрос, можете в общих чертах сказать как это сделать? Если мне реально нужны дробные числа.
Зависит от того, насколько важна точность после запятой.
Вот если бы ТС выкинул из программы все float и перешел на целочисленные вычисления - результат бы его поразил :)
Извините за глупый вопрос, можете в общих чертах сказать как это сделать? Если мне реально нужны дробные числа.
Кроме floating point есть еще fixed point. Они гораздо легче сводятся к целочисленным вычислениям, а сами вычисления, соответственно, занимают намного меньше места в объеме кода.
Зависит от того, насколько важна точность после запятой.
Ну, во-первых, боюсь, результат "36" вместо "36.61" - это не совсем то, что бы хотелось.
А во-вторых, дабы не утяжелять программу, в качестве множителя следовало бы использовать не 100, а подходящую степень двойки.
Насчет множителя ^2 не соглашусь, людям-то удобнее считать степенями десятки, а не двойки, и компьютер пока ещё сделан, чтобы выполнять мои вычисления, а не наоборот. Оптимизация оптимизацией, и очень конечно мило позаботиться о железном микроконтроллере, чтобы ему было удобнее, но он не оценит, а вот сопровождающие разработку люди вполне способны запутаться при отладке. Разумеется, в пограничных и критических случаях, когда важен каждый такт и каждый байт, можно и облегчить жизнь контроллеру, но без особой нужды, считаю, лучше делать удобнее всё-таки людям, а не железякам.
Negavoid - принцип вы подаете верно, но впш пример в #34 в корне неправильный и только запутывает ТС. Во-первых, float в коде не должно быть, иначе весь смысл пропадает. Во-вторых, вывод в Сериал напечатает тодько целую часть "36", а вовсе не 36.61, как надо спрашивающнму
Ну окей, хоть и не думаю, что это очень страшно.
Насчет множителя ^2 не соглашусь, людям-то удобнее считать степенями десятки, а не двойки, и компьютер пока ещё сделан, чтобы выполнять мои вычисления, а не наоборот.
Вот именно: считать будет контроллер, а не человек, поэтому и делать надо так, как ему, контроллеру "удобнее". А для человека - лишь выводить результат - как удобнее ему (но смотреть, а не считать).
PS. И, опять же, кода, который и показывал бы дробную часть, и обходился без float, Вы так и не привели. Хотя пытались. Причем, Ваша неудача, подозреваю, связана именно с неправильными представлениями о том, кто что доложен считать, и по каким принципам.
Собственно, попытайтесь доделать, то, что Вы пока не доделали, и, думаю, Вы поймете, почему лучше брать степень двойки, а не десятки.
Не все там просто со степенями двойки. Степень десятки обеспечит точность точно требуемую, до младшего знака десятичного представления, в том примере выше - до сотых. А степень двойки - или 1/64 или 1/128 (ну в нашем примере разумеется). Первой не хватает для всех возможных значений дробной, вторая избыточна но выбора как бы и нет. В результате получим что байтом можно представить по степеням десятки значения от 0.00 до 2.55 а по степеням двойки от 0.00 до 1.99. И с математикой не однозначно пробуем прибавить одну сотую. По степеням десятки все просто и однозначно, по степеням двойки или 1/128 или 2/128. Ну допустим 1/128 прибавляем. 0+1/128=0,0078 округляем получаем 0.01, далее 0.01+1/128=0,01562 снова округляем и имеем 0.02 (это соответствует 2/128). 0.02+1/128=0.02343 округляем и снова 0.02 получаем!! Потому как что 2/128 что 3/128 после округления до сотых дают 0.02. А это не весело, если например по нажатию кнопки хотим делать +0.01. Получим что кнопка иногда как бы не срабатывает )))
Хотя в общем случае математика по степеням двойки на голову проще конечно. Но с сюрпризами типа 1+1=1.9999999...
ПС. Помним что сдвиги в 328р реализуются циклом и деление на степень двойки не так и быстро работает.
Омойбох, как же теперь жить-то с этим... Ну наплевать на удобство для контроллера, ну вот абсолютно, в 99.9% случаев.
Но ведь придерутся снова и заставят ещё какую-нибудь фигню писать ))
Ну окей, хоть и не думаю, что это очень страшно.
код, который Вы привели - показывает, что Вы совершенно не понимаете сути проблемы. Приведение к типу float внутри Serial.print() - это уже использование вычислений с плавающей точкой, и соответвующее увеличение размера кода
Сравните:
Скетч использует 3212 байт (9%)
Глобальные переменные используют 200 байт
а теперь заменим вывод на целочисленный
Скетч использует 1834 байт (5%)
Глобальные переменные используют 190 байт
примечание - операция чтения х из сериал добавлена, чтобы компилятор не заменил значение х/100 заранее рассчитанной константой
Омойбох, как же теперь жить-то с этим... Ну наплевать на удобство для контроллера, ну вот абсолютно, в 99.9% случаев.
Но ведь придерутся снова и заставят ещё какую-нибудь фигню писать ))
ну наконец-то :) только это не придирки, разница в 1.5К флеша
Мало вам срани в голове. Открываем этот ютуб канал и впитываем. https://www.youtube.com/channel/UC1yFLfcOBeqHRTeZgs3UCzA и на фоне этого делить на два или на 10 уже не самое страшное.
Большое спасибо. Идею я понял. Дальше буду ее копать. А коллеги-форумчане дополнят...
Омойбох, как же теперь жить-то с этим... Ну наплевать на удобство для контроллера, ну вот абсолютно, в 99.9% случаев.
Но ведь придерутся снова и заставят ещё какую-нибудь фигню писать ))
ну наконец-то :) только это не придирки, разница в 1.5К флеша
Большое спасибо
Хотя в общем случае математика по степеням двойки на голову проще конечно. Но с сюрпризами типа 1+1=1.9999999...
Наоборот. Такие сюрпризы появляются как раз тогда, когда используются степени НЕ двойки.
Хотя в общем случае математика по степеням двойки на голову проще конечно. Но с сюрпризами типа 1+1=1.9999999...
Наоборот. Такие сюрпризы появляются как раз тогда, когда используются степени НЕ двойки.
Нет. Такие сюрпризы появляются если выполняются оба условия
1. Разрядность (читай число бит) для представления числа не бесконечно. Это вобщем всегда так, но для строгости напомню.
2. Число не удается точно представит как сумму степеней системы счисления (включая отрицательные степени). В двоичной рассмотренное выше 0.01 не удается. А в десятичной 1/3 не получится. Приходится приближенно представлять, округлять. Вот и лезут мелкие погрешности. Но мелкие они если число в нескольких десятках бит хранится. Но мы же тут типа экономим, разрядность ужимаем, а значить погрешности будут заметными если о них не позаботится.