Оптимизация размера скетча

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

Доброго времени суток, всем. Хочу обратиться к болле опытным когегам с вопросом об оптимизации ардуиновского скетча. Уже почти дописал прошивку для своего проекта, но встал вопрос о подключении модуля для работы с 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%.

nik182
Offline
Зарегистрирован: 04.05.2015

Взять другой МК с большей памятью или урезать хотелки. 

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

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

vvadim
Offline
Зарегистрирован: 23.05.2012

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

вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ictic_Step пишет:

К сожалению не вариант. Если бы так можно было - уже б сделал. Заказывать новый микроконтроллер и ждать доставку - слишком долго,

Все стальные варианты - еще дольше.

Заказанное Вы получите через пару месяцев. Провести серьезную оптимизацию кода за это время Вы явно не успеете.

Цитата:

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

Во-первых, в том контроллере, о котором Вы пишете, EEPROM всего 1 кбайт. А во-вторых, служит эта EEPROM совсем для других целей, и вряд ли, путем использования EEPROM Вам удастся сократить хотя бы один байт во FLASH.

Заметно сократить объем кода можно, отказавшись от использования данных с плавающей точкой. Но вряд ли это Вам по силам.

Т.о. надеяться можно лишь на следующее:

1. На то, что и первые 12к и вторые 12к используют одни и те же функции, следовательно, их объединение окажется замеьтно меньше 24к.

2. Если Вы будете грузить скетч не через встроенный загрузчик, а через внешний программатор, доступный объем памяти возрасет с 29к до 32к. 

Но, в любом случае, самый простой способ - выбрать контроллер с достаточным объемом памяти.

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

Чистый С++ легко добавит в прошивку ещё килобайт пять ))

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

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

Спасибо за ответ, но когда я говорил про EEPROM, я имел ввиду использование его вместо sd-карты для хранение текста, который будет вводить пользователь.

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

sadman41 пишет:

Чистый С++ легко добавит в прошивку ещё килобайт пять ))

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

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Ну выложите, по диагонали хотя бы глянем на досуге

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Библиотека для SD жрет много памяти из-за поддержки FAT. Если файловая система не обязательно (писать поблочно) то можно сильно уменьшить занимаемую память.

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

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

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

Уже самому пришли светлые идеи в голову и удалось уменьшить размер с 12970 байт до 11152 путём заминение переменной String, которую меня бес попутал использовать как тригер в первом файле скетча. Выбросил Serial.print() и стало вообще 10368 байтов...

Испанский стыд... Так сильно извращаться с оптимизацией второй части и совсем забыть о банальных вещах во второй. Вообщем спасибо всем, кто помогали и простите все, у кого я скушал немного времени. Скетч занимает всего лишь 34% памяти в конечном результате и это вполне допустимо.

Ну конечно привет всем тем, кто в меня не верил(и не важно, что я по-сути просто починил то, что сам и сломал), а в часности автору вот-этого кусочка:

vvadim пишет:

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

вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.

 

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

Ictic_Step пишет:

У меня в первой часте примерно 450 строк кода,

....

но врятли кто-то захочет в таком огромном исходнике

Спасибо, насмешили :) 450 строк - это не огромный, это маленький исходник. Выкладывайте.

vvadim
Offline
Зарегистрирован: 23.05.2012

Ictic_Step пишет:

Ну конечно привет всем тем, кто в меня не верил(и не важно, что я по-сути просто починил то, что сам и сломал), а в часности автору вот-этого кусочка:

vvadim пишет:

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

вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.

 

 

вы вроде тему подняли по такой проблеме

 

 * Флеш-памяти для хранения скетча - 29696 байт

 * Уже написаная програма занимает 12970 байт (43% памяти устройства)

 * Придется подключить еще 12784 байт (еще 43% памяти устройства), так как подключаются используемые функции с библиотек SD.h и SPI.h

 

ваш подвиг пока не решает вашей проблемки.

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

vvadim пишет:

Ictic_Step пишет:

Ну конечно привет всем тем, кто в меня не верил(и не важно, что я по-сути просто починил то, что сам и сломал), а в часности автору вот-этого кусочка:

vvadim пишет:

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

вам остаётся поменять мк или долго учиться и долбаться с оптимизацией.

 

 

вы вроде тему подняли по такой проблеме

 

 * Флеш-памяти для хранения скетча - 29696 байт

 * Уже написаная програма занимает 12970 байт (43% памяти устройства)

 * Придется подключить еще 12784 байт (еще 43% памяти устройства), так как подключаются используемые функции с библиотек SD.h и SPI.h

 

ваш подвиг пока не решает вашей проблемки.

Да нет. Я выбросил все String`и и полностью убрал с кода Serial и у меня около 20% памяти устройства точно сэкономлено, а так как при подключении, конечный скетч весит не скетч1+скетч2, то всё влаазит. Ведь нужно не забывать, что учитывается еще вес загрузчика и стандартной библиотеки. Вообщем могу дать совет всем, кто в будущем возможно столкнеться с моей проблемой: в первую очередь удалите Serial и используйте массив символов, вместо String - это действительно экономит просто зверское кол-во флеш-памяти.

vvadim
Offline
Зарегистрирован: 23.05.2012

это с натяжкой можно назвать оптимизацией)))))

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

vvadim пишет:

это с натяжкой можно назвать оптимизацией)))))

Мне этого хватило. И почему это не можно назвать оптимизацией? Задача стояла оптимизировать размер кода, дабы освободить флеш память и для этого я сделал следующие:

 * отказался от String как таковой

 * убрал все сообщения в монитор порта

 * сжал все переменные типа int к short int, где это возможно

Оптимизация бывает разная и это необязательно должно быть осовобождение ОЗУ или снижение нагрузки на процессор(хотя это тоже произошло), так что названия темы соответсвует вопросу в полной мере.

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

Ictic_Step пишет:

 * сжал все переменные типа 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. 

 

b707
Онлайн
Зарегистрирован: 26.05.2017

sadman41 пишет:

Ictic_Step пишет:

 * сжал все переменные типа 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 и перешел на целочисленные вычисления - результат бы его поразил :)

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

b707 пишет:

sadman41 пишет:

Ictic_Step пишет:

 * сжал все переменные типа 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, то идея конечно хороша, но в моём проекте, к сожелению, недопустимая.

negavoid
Offline
Зарегистрирован: 09.07.2016

Ictic_Step пишет:
Если не трудно, можете сбросить ссылку об использовании карточки без файловой системы, а то все говорят, что это существенно уменьшает размеры скетча через выброс с него громоздких библиотек, а url никто не бросит.

Ну потому что он не нужен :)

#include <SPI.h>
#include <SdFat.h>
const uint8_t CS_PIN = 10;
Sd2Card card;
uint8_t block[512];
uint32_t address = 12345L;
void setup() {
  Serial.begin(9600);
  if (!card.begin(CS_PIN)) Serial.println("begin error");
  if (!card.writeBlock(address, block)) Serial.println("write error");
  if (!card.readBlock(address, block)) Serial.println("read error");
  Serial.println("Done!");
}
void loop() {}

Sketch uses 2,922 bytes (9%) of program storage space. Maximum is 30,720 bytes.

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

negavoid пишет:

Ictic_Step пишет:
Если не трудно, можете сбросить ссылку об использовании карточки без файловой системы, а то все говорят, что это существенно уменьшает размеры скетча через выброс с него громоздких библиотек, а url никто не бросит.

Ну потому что он не нужен :)

#include <SPI.h>
#include <SdFat.h>
const uint8_t CS_PIN = 10;
Sd2Card card;
uint8_t block[512];
uint32_t address = 12345L;
void setup() {
  Serial.begin(9600);
  if (!card.begin(CS_PIN)) Serial.println("begin error");
  if (!card.writeBlock(address, block)) Serial.println("write error");
  if (!card.readBlock(address, block)) Serial.println("read error");
  Serial.println("Done!");
}
void loop() {}

Sketch uses 2,922 bytes (9%) of program storage space. Maximum is 30,720 bytes.

Эххх... Спасибо. Чертовски хороший код, жаль что у не смогу его использовать, т.к. использую не оригинальную ардуинку, а аналог от компании wavgat и у меня чисто не компилится из-за устаревшей версии ядра. Даже использование самой старой версии биюлиотеки sdFat вызывает ошибку... :(

Врятли это что-то даст, но если что, вот сама ошибка:

Внимание: platform.txt из ядра 'Arduino AVR Boards' содержит устаревшие recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}", автоматически преобразовано в recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}". Ожидайте обновления ядра.
In file included from C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SdFat.h:26:0,

                 from E:\arduinoDev\SdCard_demo\SdCard_demo.ino:2:

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SysCall.h: In static member function 'static void SysCall::yield()':

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SysCall.h:74:3: error: '::yield' has not been declared

   ::yield();

   ^

In file included from C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/FatLib/FatLib.h:23:0,

                 from C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SdFat.h:28,

                 from E:\arduinoDev\SdCard_demo\SdCard_demo.ino:2:

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/FatLib/ArduinoStream.h: In member function 'void ArduinoInStream::readline()':

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/FatLib/ArduinoStream.h:53:13: error: 'yield' was not declared in this scope

       yield();

             ^

exit status 1
Ошибка компиляции для платы WAVGAT UNO R3.

 

negavoid
Offline
Зарегистрирован: 09.07.2016

попробуйте обновить ide

https://github.com/greiman/SdFat/issues/66

b707
Онлайн
Зарегистрирован: 26.05.2017

Ictic_Step пишет:

использую не оригинальную ардуинку, а аналог от компании wavgat и у меня чисто не компилится

Купите нормальную ардуину, не оригинал, а обычную китайскую, только не Вавгат- она стоит не дороже 200 рублей. А с Вавгатом вы еще намучаетесь и потом, скорее всего, все равно перейдете на нормальную плату.

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

negavoid пишет:

попробуйте обновить ide

https://github.com/greiman/SdFat/issues/66

Спасибо за совет... Кароче чуть не сдох, пока переустановил IDE, вернул все библиотеки, залил ядро Wavgat и вавгатовские библиотеки, но самое главное, что проблема не только осталась, но теперь у меня еще й SPI.h не компилируется и это уже *цензура*, *цензура*, *цензура*. 

b707 пишет:

Ictic_Step пишет:

использую не оригинальную ардуинку, а аналог от компании wavgat и у меня чисто не компилится

Купите нормальную ардуину, не оригинал, а обычную китайскую, только не Вавгат- она стоит не дороже 200 рублей. А с Вавгатом вы еще намучаетесь и потом, скорее всего, все равно перейдете на нормальную плату.

Да я уже 100500 раз пожелел о том, что купил этот кусок... кхм... платы. Только вот новую плату из Китая ждать месяц-два, а мне нужно проект доделать раньше.

 

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

Arduino: 1.8.9 (Windows 10), Плата:"WAVGAT UNO R3"

Внимание: platform.txt из ядра 'Arduino AVR Boards' содержит устаревшие recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}", автоматически преобразовано в recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}". Ожидайте обновления ядра.
In file included from C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SdFat.h:26:0,

                 from E:\arduinoDev\SdCard_demo\SdCard_demo.ino:2:

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SysCall.h: In static member function 'static void SysCall::yield()':

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SysCall.h:74:3: error: '::yield' has not been declared

   ::yield();

   ^

In file included from C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/FatLib/FatLib.h:23:0,

                 from C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/SdFat.h:28,

                 from E:\arduinoDev\SdCard_demo\SdCard_demo.ino:2:

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/FatLib/ArduinoStream.h: In member function 'void ArduinoInStream::readline()':

C:\Users\Sklyanskiy\Documents\Arduino\libraries\SdFat\src/FatLib/ArduinoStream.h:53:13: error: 'yield' was not declared in this scope

       yield();

             ^

Несколько библиотек найдено для "SPI.h"
 Используется: C:\Users\Sklyanskiy\Documents\Arduino\libraries\SPI
Не используется: F:\Programs\Arduino\libraries\SPI
exit status 1
Ошибка компиляции для платы WAVGAT UNO R3.

Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"

 

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

negavoid пишет:

Ictic_Step пишет:
Если не трудно, можете сбросить ссылку об использовании карточки без файловой системы, а то все говорят, что это существенно уменьшает размеры скетча через выброс с него громоздких библиотек, а url никто не бросит.

Ну потому что он не нужен :)

#include <SPI.h>
#include <SdFat.h>
const uint8_t CS_PIN = 10;
Sd2Card card;
uint8_t block[512];
uint32_t address = 12345L;
void setup() {
  Serial.begin(9600);
  if (!card.begin(CS_PIN)) Serial.println("begin error");
  if (!card.writeBlock(address, block)) Serial.println("write error");
  if (!card.readBlock(address, block)) Serial.println("read error");
  Serial.println("Done!");
}
void loop() {}

Sketch uses 2,922 bytes (9%) of program storage space. Maximum is 30,720 bytes.

Ну блин, ну не могу скомпилить твой скетч - хоть убейся. Но вроде как проблема именно в библиотеке SdFat.h, которая не хочет взаимодействовать с WAVGAT UNO R3. Есть ли какой-то аналог этой библиотеки?

negavoid
Offline
Зарегистрирован: 09.07.2016

Ошибка осталась та же самая, yield() не объявлен, это не проблема библиотеки sdfat, кстати, одной из лучших. Попробуйте выставить просто UNO в платах, не wavgat, тоже не собирается? Аналог - ардуиновская родная библиотека sd.h.

b707
Онлайн
Зарегистрирован: 26.05.2017

Ictic_Step пишет:

Да я уже 100500 раз пожелел о том, что купил этот кусок... кхм... платы. Только вот новую плату из Китая ждать месяц-два, а мне нужно проект доделать раньше.

А там где вы живете просто пойти в магазин и купить ардуино нельзя? Пусть не за 200 - а за 400 рублей? Это явно будет эффективнее, чем трахаться с Вавгатом

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

negavoid пишет:

Ошибка осталась та же самая, yield() не объявлен, это не проблема библиотеки sdfat, кстати, одной из лучших. Попробуйте выставить просто UNO в платах, не wavgat, тоже не собирается? Аналог - ардуиновская родная библиотека sd.h.

Да... вы правы. Под ардуино уно всё собралось и заняло 9% памяти как вы и писали. Только с вавгатом оно походу дружить не будет, а других плат под рукой сейчас нет... Ладно, колупаюсь с SD.h и надеюсь, что памяти хватит.

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

b707 пишет:

Ictic_Step пишет:

Да я уже 100500 раз пожелел о том, что купил этот кусок... кхм... платы. Только вот новую плату из Китая ждать месяц-два, а мне нужно проект доделать раньше.

А там где вы живете просто пойти в магазин и купить ардуино нельзя? Пусть не за 200 - а за 400 рублей? Это явно будет эффективнее, чем трахаться с Вавгатом

Знаете, если б у меня был бы такой вариант - уже б купил бы три раза, я компанию Wavgat уже ненавижу просто, но есть только эта плата и купить сейчас возможности нету - только заказывать и ждать месяц-два, что уж точно не вариант.

b707
Онлайн
Зарегистрирован: 26.05.2017

Ictic_Step пишет:

Знаете, если б у меня был бы такой вариант - уже б купил бы три раза

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

И второй совет - вот прямо сейчас, сразу, сегодня вечером - закажите на Али пару-тройку Уно и Нано. Может статься, что вы свой проект еще полгода делать будете - а платы уже придут.

Ictic_Step
Offline
Зарегистрирован: 15.07.2019

b707 пишет:

Ictic_Step пишет:

Знаете, если б у меня был бы такой вариант - уже б купил бы три раза

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

И второй совет - вот прямо сейчас, сразу, сегодня вечером - закажите на Али пару-тройку Уно и Нано. Может статься, что вы свой проект еще полгода делать будете - а платы уже придут.

Хорошо, спасибо за совет)) Платы сейчас закажу. Правда надеюсь проект закончу уже за дня три-четыре, ведь главная боль, основная логика роботы уже прописана. Осталось только настроить чтение с сд карты и запись на сд карту используя для записи данные полученые с блютуз модуля. Звучит, конечно, просто, но зная то, что это вавгат, а я еще довольно "новичковый" человек в электронике, то я думаю еще столкнуся как минимум с проблемами с чёртовым блютуз модулём.

А на счёт "дрейфования на льдине", то это почти про меня)))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ictic_Step пишет:

А на счёт выбросить все float, то идея конечно хороша, но в моём проекте, к сожелению, недопустимая.

Это Ваше личное мнение.

Никаких доводов в его пользу Вы не приводите.

Это - первое.

И воторое. Я, конечно, могу ошибаться, но у меня сложилось впечатление, что ситуацию, когда занято 24 из доступных 29 кбайт Вы оцениваете как катастрофическую, а экономию в 2 кбайта - как решение. Лично мне такие оценки кажутся несколько странными. Конечно, 7 свободных кбайт лучше, чем 5, но не до такой же степени!

cyberman
Offline
Зарегистрирован: 30.10.2018

[/quote]

Вот если бы ТС выкинул из программы все float и перешел на целочисленные вычисления - результат бы его поразил :)

[/quote]

Извините за глупый вопрос, можете в общих чертах сказать как это сделать? Если мне реально нужны дробные числа.

negavoid
Offline
Зарегистрирован: 09.07.2016

cyberman пишет:
Извините за глупый вопрос, можете в общих чертах сказать как это сделать? Если мне реально нужны дробные числа.

Зависит от того, насколько важна точность после запятой.

float fTemp = 36.61;
int   iTemp = fTemp * 100;
// ...
// тут работаем с целым iTemp = 3661
// ...
Serial.println( iTemp / 100 );

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

cyberman пишет:

Цитата:

Вот если бы ТС выкинул из программы все float и перешел на целочисленные вычисления - результат бы его поразил :)

Извините за глупый вопрос, можете в общих чертах сказать как это сделать? Если мне реально нужны дробные числа.

Кроме floating point есть еще fixed point. Они гораздо легче сводятся к целочисленным вычислениям, а сами вычисления, соответственно, занимают намного меньше места в объеме кода.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

negavoid пишет:

cyberman пишет:
Извините за глупый вопрос, можете в общих чертах сказать как это сделать? Если мне реально нужны дробные числа.

Зависит от того, насколько важна точность после запятой.

float fTemp = 36.61;
int   iTemp = fTemp * 100;
// ...
// тут работаем с целым iTemp = 3661
// ...
Serial.println( iTemp / 100 );

 

Ну, во-первых, боюсь, результат "36" вместо "36.61" - это не совсем то, что бы хотелось.

А во-вторых, дабы не утяжелять программу, в качестве множителя следовало бы использовать не 100, а подходящую степень двойки.

 

negavoid
Offline
Зарегистрирован: 09.07.2016

Насчет множителя ^2 не соглашусь, людям-то удобнее считать степенями десятки, а не двойки, и компьютер пока ещё сделан, чтобы выполнять мои вычисления, а не наоборот. Оптимизация оптимизацией, и очень конечно мило позаботиться о железном микроконтроллере, чтобы ему было удобнее, но он не оценит, а вот сопровождающие разработку люди вполне способны запутаться при отладке. Разумеется, в пограничных и критических случаях, когда важен каждый такт и каждый байт, можно и облегчить жизнь контроллеру, но без особой нужды, считаю, лучше делать удобнее всё-таки людям, а не железякам.

b707
Онлайн
Зарегистрирован: 26.05.2017

Negavoid - принцип вы подаете верно, но впш пример в #34 в корне неправильный и только запутывает ТС. Во-первых, float в коде не должно быть, иначе весь смысл пропадает. Во-вторых, вывод в Сериал напечатает тодько целую часть "36", а вовсе не 36.61, как надо спрашивающнму

negavoid
Offline
Зарегистрирован: 09.07.2016

Ну окей, хоть и не думаю, что это очень страшно.

int iTemp = Sensor.getFloatTemp() * 100;
// ...
Serial.println( (float) iTemp / 100 );

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

negavoid пишет:

Насчет множителя ^2 не соглашусь, людям-то удобнее считать степенями десятки, а не двойки, и компьютер пока ещё сделан, чтобы выполнять мои вычисления, а не наоборот.

Вот именно: считать будет контроллер, а не человек, поэтому и делать надо так, как ему, контроллеру "удобнее". А для человека - лишь выводить результат - как удобнее ему (но смотреть, а не считать).

 

PS. И, опять же, кода, который и показывал бы дробную часть, и обходился без float, Вы так и не привели. Хотя пытались. Причем, Ваша неудача, подозреваю, связана именно с неправильными представлениями о том, кто что доложен считать, и по каким принципам.

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

Logik
Offline
Зарегистрирован: 05.08.2014

Не все там просто со степенями двойки. Степень десятки обеспечит точность точно требуемую, до младшего знака десятичного представления, в том примере выше - до сотых. А степень двойки - или 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р реализуются циклом и деление на степень двойки не так и быстро работает.

negavoid
Offline
Зарегистрирован: 09.07.2016

Омойбох, как же теперь жить-то с этим... Ну наплевать на удобство для контроллера, ну вот абсолютно, в 99.9% случаев.

Serial.print(iTemp/100); Serial.print(iTemp%100);

Но ведь придерутся снова и заставят ещё какую-нибудь фигню писать ))

b707
Онлайн
Зарегистрирован: 26.05.2017

negavoid пишет:

Ну окей, хоть и не думаю, что это очень страшно.

int iTemp = Sensor.getFloatTemp() * 100;
// ...
Serial.println( (float) iTemp / 100 );

 

код, который Вы привели - показывает, что Вы совершенно не понимаете сути проблемы. Приведение к типу float внутри Serial.print() - это уже использование вычислений с плавающей точкой, и соответвующее увеличение размера кода

Сравните:

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
byte x = Serial.read();
Serial.println( (float) x/100  );
}

Скетч использует 3212 байт (9%)
Глобальные переменные используют 200 байт

а теперь заменим вывод на целочисленный


Serial.print(  x/100  );
Serial.print(  "."  );
Serial.println(  x%100  );

Скетч использует 1834 байт (5%)
Глобальные переменные используют 190 байт

примечание - операция чтения х из сериал добавлена, чтобы компилятор не заменил значение х/100 заранее рассчитанной константой

b707
Онлайн
Зарегистрирован: 26.05.2017

negavoid пишет:

Омойбох, как же теперь жить-то с этим... Ну наплевать на удобство для контроллера, ну вот абсолютно, в 99.9% случаев.

Serial.print(iTemp/100); Serial.print(iTemp%100);

Но ведь придерутся снова и заставят ещё какую-нибудь фигню писать ))

ну наконец-то :) только это не придирки, разница в 1.5К флеша

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Мало вам срани в голове. Открываем этот ютуб канал и впитываем. https://www.youtube.com/channel/UC1yFLfcOBeqHRTeZgs3UCzA    и на фоне этого делить на два или на 10 уже не самое страшное.

cyberman
Offline
Зарегистрирован: 30.10.2018

Большое спасибо. Идею я понял. Дальше буду ее копать. А коллеги-форумчане дополнят...

cyberman
Offline
Зарегистрирован: 30.10.2018

b707 пишет:

negavoid пишет:

Омойбох, как же теперь жить-то с этим... Ну наплевать на удобство для контроллера, ну вот абсолютно, в 99.9% случаев.

Serial.print(iTemp/100); Serial.print(iTemp%100);

Но ведь придерутся снова и заставят ещё какую-нибудь фигню писать ))

ну наконец-то :) только это не придирки, разница в 1.5К флеша

Большое спасибо

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Logik пишет:

Хотя в общем случае математика по степеням двойки на голову проще конечно. Но с сюрпризами типа 1+1=1.9999999... 

Наоборот. Такие сюрпризы появляются как раз тогда, когда используются степени НЕ двойки.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

andriano пишет:
Наоборот. Такие сюрпризы появляются как раз тогда, когда используются степени НЕ двойки.

Вы не правы. Сюрпризы начинаются когда корень берут из -1. А рациональные и иррациональные числа не страшны.

Logik
Offline
Зарегистрирован: 05.08.2014

andriano пишет:

Logik пишет:

Хотя в общем случае математика по степеням двойки на голову проще конечно. Но с сюрпризами типа 1+1=1.9999999... 

Наоборот. Такие сюрпризы появляются как раз тогда, когда используются степени НЕ двойки.

Нет. Такие сюрпризы появляются если выполняются оба условия

1. Разрядность (читай число бит) для представления числа не бесконечно. Это вобщем всегда так, но для строгости напомню.

2. Число не удается точно представит как сумму степеней системы счисления (включая отрицательные степени). В двоичной рассмотренное выше 0.01 не удается. А в десятичной 1/3 не получится. Приходится приближенно представлять, округлять. Вот и лезут мелкие погрешности. Но мелкие они если число в нескольких десятках бит хранится. Но мы же  тут типа экономим, разрядность ужимаем, а значить погрешности будут заметными если о них не позаботится.