Помогите оптимизировать код
- Войдите на сайт для отправки комментариев
Пнд, 31/08/2015 - 10:56
#include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Adafruit_BMP085.h> #include <Wire.h> #include <DS1307RTC.h> #include <Time.h> #include <Servo.h> #define OLED_RESET 4 #define Trig 7 #define Echo 6 Adafruit_SSD1306 display(OLED_RESET); Adafruit_BMP085 bmp; tmElements_t tm; Servo myservo; // create servo object to control a servo void setup() { Serial.begin(9600); if (!bmp.begin()) { Serial.println("Could not find a valid BMP085 sensor, check wiring!"); while (1) {} } display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); pinMode(Trig, OUTPUT); pinMode(Echo, INPUT); myservo.attach(10); // attaches the servo on pin 9 to the servo object display.setTextSize(2); display.setTextColor(WHITE); } unsigned int impulseTime=0; unsigned int distance_sm=0; int pos = 0; // variable to store the servo position void loop() { // ДАЛЬНОМЕР //---------------------------------------------------------------------------------------------------- digitalWrite(Trig, HIGH); /* Подаем импульс на вход trig дальномера */ delayMicroseconds(25); // равный 10 микросекундам digitalWrite(Trig, LOW); // Отключаем impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса distance_sm=impulseTime/58; // Пересчитываем в сантиметры Serial.println(distance_sm); // Выводим на порт if (distance_sm < 30) // Если расстояние менее 30 сантиметром { //ВЫВОДИМ НА ДИСПЛЭЙ //----------------------------------------------------------------------------------------------------- //Температура display.setCursor(0,0); display.print("T= "); display.print(bmp.readTemperature()); display.println(" C"); //Давление display.setCursor(0,20); display.print("P= "); display.print(bmp.readPressure()); //Часы display.setCursor(0,40); print2digits(tm.Hour); display.print(":"); print2digits(tm.Minute); display.print(":"); print2digits(tm.Second); display.display(); delay(1000); display.clearDisplay(); } else { display.setCursor(0,0); display.print(" "); display.display(); display.clearDisplay(); } delay(100); //СЕРВО ПРИВОД //-------------------------------------------------------------------------------------------- if(bmp.readTemperature()>30) { myservo.write(20); }else { myservo.write(90); } } void print2digits(int number) { //Функция добавления нуля если число (часы минуты секунды) от 0 до 10 if (number >= 0 && number < 10) { display.print('0'); } display.print(number); }
При компиляции пишет:
Sketch uses 16 212 bytes (50%) of program storage space. Maximum is 32 256 bytes.
Global variables use 1 681 bytes (82%) of dynamic memory, leaving 367 bytes for local variables. Maximum is 2 048 bytes.
Low memory available, stability problems may occur.
А я планирую еще добавлять датчики боюсь не зватит места.
Платка Arduino UNO.
Подскажите как правильно уменьшить вес прошивки.
Спасибо.
Global variables use 1 681 bytes (82%) of dynamic memory - кажись многовато...Хренова туча библиотек.. Самое простое - УНО на МЕГА если есть возможность...А так попробуйте строки типа
display.print(
"P= "
); превратить в
display.print(F(
"P= "
));
а что это за d
isplay.print(F
); ?
а что это за d
isplay.print(F
); ?
Ну вроде как загоняет всю последующую ерунду во флэш-память... У меня была такая проблема с УНО, когда я на на W5100 нагородил страничку большую... И тут на форуме мне посоветовали как раз строки типа client.print("Заданная температура основного водонагревателя"); превратить в client.print(F("Заданная температура основного водонагревателя")); И сразу все решилось... Думаю с d
isplay.print тоже должно сработать
> delayMicroseconds(25); // равный 10 микросекундам
Это в какой системе счисления? o_0
68-84
Или добавь чтение времени из часов, или выкинь совсем. tm у тебя не нициализируется нигде.
Еще можно вместо OLED использовать дисплей 2x16 например. Памяти расходовать будет намного меньше.
> delayMicroseconds(25); // равный 10 микросекундам
Ну он же не сам код писал))) Куски навставлял и все дела))
Andrey-S
Спасибо немного помогло
Код писал сам. Просто правил код а коментарии забыл :)
Так у меня и bmp нигде не инициализируется.
А как же тогда без tm время выводить на дисплей?
Тут, судя по бибиотекам, к УНЕ прихреначено немало... Если собираетесь туда впихивать еще прибамбасов, то все же советовал бы МЕГУ...
Andrey-S
Спасибо немного помогло
Код писал сам. Просто правил код а коментарии забыл :)
Так у меня и bmp нигде не инициализируется.
А как же тогда без tm время выводить на дисплей?
21-24 что тогда?
У тебя в tm мусор. Если хочешь выводить время, то читай в tm время из RTC.
А можно про tm по подробнее. Просто я пока только учусь. спасибо
Куда еще подробнее?
Она объявлена (16), из нее идет чтение (69-73), в нее нигде не идет запись, она нигде не инициализируеется.
в bmp тоже ничего не записывается. А как влияет инициализация?
bmp.readTemperature() - вызов метода класса. Функция возвращает значение.
tm.Hour - чтение поля структуры. Читается значение переменной.
Чтобы из переменной что-то прочитать, в нее надо что-то записать.
Ну это же самые основы. Как вообще можно писать без их знания?
учусь на примерах. Пытаюсь разобратся читая и перелапачивая код.
https://www.arduino.cc/en/Guide/HomePage
https://www.arduino.cc/en/Reference/HomePage
http://playground.arduino.cc/
http://arduino.ru/Reference
Я не могу понять зачем мне записывать что то в переменную что бы потом вывести это на экран если можно сразу на экран вывести без посредников.
http://www.pjrc.com/teensy/td_libs_DS1307RTC.html
Я не могу понять зачем мне записывать что то в переменную что бы потом вывести это на экран если можно сразу на экран вывести без посредников.
)))) Тут имеется ввиду, что если Вы инициализировали переменную, то в ней (как в коробке) должно что-то находиться... А для этого надо туда что-то положить (считать инфу с датчика и т.п.)... Radjah хорошую ссылочку для этого прилепил)
А где в этом примере происходит инициализация tm?
16 строка
можно вместо OLED использовать дисплей 2x16 например. Памяти расходовать будет намного меньше.
Да. Похоже либка к SSD1306 зажрала 1к RAM. Видать и сдесь сунули буфер под весь экран. Попробуйте закоментировать всю работу с экраном для проверки этого.
Да, библиотека Adafruit отжирает 1К под экранный буфер.
Если нужна попиксельная графика, без этого никак.
Но если выводить только текст, то без буфера можно обойтись.
В частности, библиотека, которую я здесь публиковал:
http://arduino.ru/forum/programmirovanie/kirillitsa-na-displee-ili-chto-...
не использует буфер, да и вообще соптимизирована с точки зрения минимизации используемой памяти.
Правда, выводить текст придется несколько угловатым шрифтом высотой 16 пикселей. Зато есть кириллица.
Да, библиотека Adafruit отжирает 1К под экранный буфер.
Если нужна попиксельная графика, без этого никак.
Нет. Во первых сложности только при подключении по I2C. Видео ОЗУ недоступно на чтение получается и канву надо хранить. Если верить описанию, то при работе по другим интерфейсам оно читаемо и никакой проблемы попиксельно работать без буфера нет, ну кроме тормозов может. Но и при подключении I2C не безнадежно. Можна напрямую выводить картинку из PRG, можно по формировать байты изображения на лету, как некоторую функцию от адреса, я так на нем осцилограф сделал. Если уж так дороги точки, линии, кружечки - тоже не беда - выделить буфер не глобально, а на время рисования и освободить его после передачи. К тому же буфер можно выделять не на весь экран, а только на его часть. Еще можна без буфера вертикальные и горизонтальные линии выводить, типа таблички а потом поверху текстом без буфера писать. В общем решаемо. Жаль что авторы библиотек о таком не парятся.
Если нужна попиксельная графика, без этого никак.
Нет.
Во первых сложности только при подключении по I2C.
Но и при подключении I2C не безнадежно.
...я так на нем осцилограф сделал.
Очевидно, осциллограф этим требованиям удовлетворяет.
Скажу больше, даже в примерах использования моей библиотеки есть случаи явно нетекстового вывода. Например вывод в стиле "спектранализатор" или даже анимация в стиле Packman. Но это не отменяет общности утверждения, что все кроме текста можно только в частных случаях.Цитата:
См выше - если при новом рисовании не нужно хранить нарисованное ранее.Цитата:
Ну да, если используеми не весь экран, буфер можно сделать поменьше.Цитата:
Строго говоря, либо только вертикальные (в режиме по умолчанию), либо только горизонтальные (если переопределить режим). Иначе последующий текст их сотрет.
Если уж так дороги точки, линии, кружечки - тоже не беда - выделить буфер не глобально, а на время рисования и освободить его после передачи.
К тому же буфер можно выделять не на весь экран, а только на его часть.
Еще можна без буфера вертикальные и горизонтальные линии выводить, типа таблички а потом поверху текстом без буфера писать. В общем решаемо. Жаль что авторы библиотек о таком не парятся.
А вообще, если проявить фантазию, можно очень много чего. Только, как я уже говорил, это все ЧАСТНЫЕ случаи, которые, как правило, нужны лишь одному человеку и никому больше. Поэтому помещать их в библиотеку, а тем более в библиотеку для устройства, имеющего существенные ограничения как по постоянной, так и по оперативной памяти, я думаю, нецелесообразно.
Лично я других 1306 не видел.
http://ru.aliexpress.com/item/0-96inch-OLED-A-Module-128-64-Pixel-I2C-II...
А вот здесь начинается масса ЧАСТНЫХ случаев. И никакой универсальности.Цитата:
Буфкр не нужен в одном единственном случае - когда изображение формируется целиком с нуля и не нужно хранить фон под ним.
...я так на нем осцилограф сделал.
Очевидно, осциллограф этим требованиям удовлетворяет.
Скажу больше, даже в примерах использования моей библиотеки есть случаи явно нетекстового вывода. Например вывод в стиле "спектранализатор" или даже анимация в стиле Packman. Но это не отменяет общности утверждения, что все кроме текста можно только в частных случаях.
Если уж так дороги точки, линии, кружечки - тоже не беда - выделить буфер не глобально, а на время рисования и освободить его после передачи.
К тому же буфер можно выделять не на весь экран, а только на его часть.
Еще можна без буфера вертикальные и горизонтальные линии выводить, типа таблички а потом поверху текстом без буфера писать. В общем решаемо. Жаль что авторы библиотек о таком не парятся.
А вообще, если проявить фантазию, можно очень много чего. Только, как я уже говорил, это все ЧАСТНЫЕ случаи, которые, как правило, нужны лишь одному человеку и никому больше. Поэтому помещать их в библиотеку, а тем более в библиотеку для устройства, имеющего существенные ограничения как по постоянной, так и по оперативной памяти, я думаю, нецелесообразно.
Целесообразней забрать сразу 50% памяти? Не думаю. Слишком много частных случаев означает только то, что автор библиотеки не интересовался реальным применением, формально подошел к вопросу и получил быдлокод. С чем и столкнулся ТС. Его либка слишком ресурсоемка и не обеспечивает эффективной работы с железом.
А ведь все вышеназваные частные случаи укладываются элементарно в одну функцию из либки с такими параметрами: координаты окна, его ширина и высота (причем Y и высота с точностю 8 пикселей), тип содержимого (заполненый буфер\PRG\callback\) и void*. Я думаю Вы уже догадались че там дальше ;)
Не догадался.
Не догадался.
А божеж!
А в скетче так