Полноценный диспетчер должен вести списки выделенных кусков (указатель на начало куска, размер куска, указатель следующего/предыдущего куска и т.д. - только "описание" куска - очереди, коллекции - "наше всё"), вести список "дырок", уметь сливать соседние дырки в одну большую, иметь стратегию выделения/поиска подходящего куска и они есть разные .. и мн.др.
Догадываюсь что делает .. я про "цена вопроса". К тому что "пользовать можно", но, как обычно, "с головой", понимая чего и сколько оно за собой потянет, а не потому что "во как кузяво". :)
Блин, я чего-то не понимаю или одно из двух. У меня вот есть проект устройство , которое может обслуживать 10 датчиков разных типов, при этом к устройству одновременно может быть подключен только 1. некоторые тут наверно помнят о чем речь. Так вот, в проекте используется 16х2 LCD и после того как определился тип датчика,
его название и некоторые параметры выводятся в первую строку лсд, причем занимая ее всю, т.е. 16 символов.
Вначале скетча я определил все это дело как
char* SensType[]={ "датчик такой-то бла бла", " датчик другой бла бла" , и тд};
Ну и понятно есть некая переменная byte type , которой в ходе выполнения процедуры определения типа датчика присваивается номер от 0 до 9, ну а чтоб напечатать соответсвенно дается команда
lcd.print (SensType[type]);
И это происходит только один раз после старта скетча определили тип напечатали и забыли. Так оно там на лсд и висит в первой строчке.
10 датчиков описание каждого 16 символов. Вот мне ниразу неохота чтобы как минимум 160 байт ненужной мне инфы все время висели в ОЗУ.
Вопрос. То как я сделал как будет работать? И как надо сделать правильно.
Никак. Ибо это вовсе не "ненужные 160 байт", а очень даже нужные. Поскольку определение типа датчика вынесено в runtime, то весь код, зависящий от типа, точно также будет в runtime. То есть то что вы печатаете 1 раз за весь цикл работы проги - ни разу не "основание" искать способ экономии. Ваши строки - нужны все, даже если они используются ровно 1 раз.
Да, нужны они все, но блин это же расточительство ОЗУ. Я-то хочу чтобы они все время были во флеше. А когда понадобилась одна строка взяли ее загрузили в ОЗУ, напечатали и всё. И не будет постоянно висеть в памяти. Это что же получается если в каком нить проекте идет большая работа с текстом, он что все время будет весь в озу, забьет его целиком и не останется ничего?
Не нравится мне это. Может мне мой char* запихнуть в функцию? И превратится он в локал. Когда надо будет напечатать ( тот самы один единственный раз при выполнении setup) ну появятся эти 160 байт в оперативке, а потом исчезнут. Как думаете прокатит?
Короче мне надо понимать произойдет ли выделение памяти (те самы 160 байт) как только в начале скетча выполнится команда char*... И постоянно в озу будут висеть все строки или все это подгрузится при обращении к массиву лсд.принт и когда печать произойдет память освободится. Не, ну мужики, ну это ж не дело так озу-то расходовать :(
Seva1800, можно сделать какую-нибудь функцию LCDprint, давать ей номер сообщения выводимого на экране (байт, или два байта если таких сообщений больше 256), а она будет мотать цикл с pgm_read() в буфер сколько там длина экрана (16 байт например), и выводить из нужного места флеша/EEPROM в экран. Или 4 байта сделать буфер. Или вообще один байт сделать на буфер, но тогда будет лагать, буквы будут набиваться по одной, как на пишущей машинке.
Ну а все сообщения типа марка датчика, здрасьте хозяин, состояние выключено, состояние включено, то есть неизменные тексты определить либо как PROGMEM byte[], (UPD: то есть char :) либо в EEPROM записать.
Игого расход - 1 (или 2) байта - номер, 1 байт - промежуточный буфер (куда pgm_read() будет читать флеш), 1 байт - счётчик, плюс буфер сообщения.
а еще есть регистры быстрого доступа, о них как-то не упоминули. Они вроде тоже к озу относятся. Но многие ардуиновцы даташитов не читали. Раскажите и о них (о регисрах а не о тех ардуиновцах).
Для программирующих с использованием Wiring - регистров, как таковых нет, ибо они - часть локалов, причем достаточно небольшая, учитывая "любовь" в длинным целым числам. Поэтому как-бы их нет и "рассказывать" не о чем. А тем, кто wiring не пользует - рассказывать не требуется, они и сами вам рассказать могут .. :)
Ещё напомню тут, поскольку тема прибита гвоздиком, а вопрос периодически возникает:
Для программирующих в Wiring надо помнить о том, что ИДЕ переносит все объявления функций скетча в ЕГО НАЧАЛО, даже если вы это сделали сами. Отсюда возникает трабл: при объявлении в самом скетче классов и их методов - очень легко словить "липовую ошибку" в виде "неопределен класс параметра" в объявлении функции.
ВСЕ объявления классов надо выносить в отдельные файлы и их инклудить в скетч. Верно по меньшей мере для ИДЕ 1.6.5
Угу. И этот перенос - основная идея (и по большему счету единственная существенная) у этого самого виринга. Я бы её автора кастрировал, в интелектуальном смысле слова. Потому от версии ИДЕ это не зависит.
Трабла возникает не только для классов но и для других пользовательских типов, используеммых в параметрах функции. Потому иногда выручает приводить к стандартному, указательн свою структуру к void* например, а в функции приводить обратно. Выносить свои типы удобно в ашник в папке скетча, тогда ИДЕ его инклудит сама и открывает автоматом в закладке.
Да, не только типов и классов. Например, если умалчиваемым значением параметра функции задать что-то определённое в define - задница. А с ifdef'ами что творится! Да там дофига "фокусов" вылезает. Руки отрывать надо таким "упрощателям для чайников". Сами, блин, чайники а туда же - упрощать полезли.
Только вот Wiring тут при каких делах, я не понял. IDE'шный препроцессор воду мутит, а Wiring-то причём? К нему и своих претензий хватает, зачем на него ещё лишних собак вешать?
IDE'шный препроцессор воду мутит, а Wiring-то причём?
Так Wiring как раз и реализован в препроцессоре! Т.е. ИДЕ вызывает препроцессор Wiringa, тот глумится над кодом, затем вызываются штатные средства gcc препроцессор, компилер, линкер. Вы думаете эти упрощатели свой компилер писали?! То им сложно очень, непосильно..
Ну еще есть набор либок сишных с специфическими функциями, так либка и есть либка, на язык это не тянет.
Да, ну, ладно. Я то думал, что wiring, это библиотека расположенная в файлах wiring*.c и wiring*.h, а препроцессор делает всего лишь две простые вещи: вставляет #include <arduino.h>, и собирает заголовки функций в начало. А дальше, просто вызывает gcc для компиляции.
Logik прав полностью. Wiring - это то самое глумление над кодом встроенным в ИДЕ препроцессором, а wiring.c и пр. лабуда - всего лишь плохо написанные библиотеки к нему.
Так библиотека и есть библиотека - набор функций, классов и т.д. Если её считать языком, то и до языков stddef io и т.д. недалеко. Язык прежде всего синтаксис, известные отличия описаны выше и реализуются ни как не либой. С ними не столкнутся работая в ИДЕ я не могу, а хотелось бы, а вот без wiring*.c можно обойтись. По крайней мере можно обойтись, если бы ИДЕ их не подключало не спрашивая меня.
Не нужен wiring, не используйте, кто заставляет?
Есть куча ide, которые wiring не используют и не заставляют. Нравится ArduinoIDE? Но не нужен wiring? Продолжайте маяться. Чего ныть то? Рук нет?
Не в этом дело. Я уже не первый раз натыкаюсь на эти проблемы с Wiring, поэтому и отписал сюда. Народ, который умеет программировать на С++ первым делом ваяет "свои" классы и их методы .. и наступает на эту граблю. Вот и поместил сюда, ибо тема "прибита гвоздиком", а значит "не утонет". Понятно, что новичкам, пишущим исключительно на Wiring и пользующим только его типовые либы - это не нужно. Но срединих часто "попадаются" и люди, имеющие опыт писания на С с плюсами. А вот прочитать "что делает Wiring" и чем отличается от чистого С с плюсами .. не все удосуживаются внимательно и двумчиво, хотя там всё это и изложено.
"то у него будет третий элемент a[3]. Это не так. Элементы данного массива будут: a[0], a[1] и a[2], а вот попытка использовать a[3] – как раз и есть выход за границы массива. Что при такой попытке произойдёт? Ну, если читаем, то скорее всего ничего страшного, просто прочитаем что там в памяти сразу после массива лежит. А вот если пишем – то мы то, что там после массива лежит, запросто поменяем! И нашей программе это наверняка не понравится!"
Мне просто интересно, а как вообще допускается? По хорошему вызывается исключение. Я с C подобными языками пока не очень, но я точно помню что в том же pascal при обращении к памяти которую я не инициализировал я получу исключение. Если обратиться скажем напрямую к адресу в памяти, то конечно куда угодно (не защищенный режим), а так скажем объявив c[3], и сделав хоть x=c[3], хоть c[3]=x я получу исключение. А в С вездте так или это конкретно особенность avr? Или тут наобород сделано типа на безотказность. Но тогда можно очень долго искать скажем баг связанный с x=c[3], когда надо было x=c[2].
Везде так. В принципе, некоторые компиляторы имеют опцию - сгенеровать код для проверки выхода за границы массива, но это уже "типа расширение языка", т.к. в языке как таковом никакие такого рода проверки не предусмотрены и выходить за пределы "можно".
Стек можно сравнить со скелетом, если его неумело "почистить", тело развалится. Как правило этого не нужно делать. Во всяком случае этого лучше избегать и биться за это до конца. И отвечая на Ваш вопрос, да, можно почистить, но не нужно.
В PIC 16 (начинал изучать с них и ассемблера,даташиты на PIC отличные,в отличии от Atmel, но это мое мнение) стек ограничен,приходилось изворачиваться что бы не переполнить,да и в MPLAB отладчик помогал. А вот на атмеге раз нет ограничения и в ИДЕ ардуино нет отладчика где можно посмотреть что со стеком ,становится страшно. Вот сейчас добиваю проэкт и после множественных вызовов одной из функций в которой присутствует GOTO выкидывающая из незавершенного цикла while к входу в этот цикл (изменяемые при необходимости настройки времени, а в while это время является одним из условий выполнения цикла ) существует вероятность что переполнится стек. Хотя бы размер стека возможно проверять? или ограничить его адресное пространство? Как его контролировать зверька этого? Переход на другую IDE не предлогать,мы же ARDUINO изучаем.
Seva1800, можно сделать какую-нибудь функцию LCDprint, давать ей номер сообщения выводимого на экране (байт, или два байта если таких сообщений больше 256), а она будет мотать цикл с pgm_read() в буфер сколько там длина экрана (16 байт например), и выводить из нужного места флеша/EEPROM в экран. Или 4 байта сделать буфер. Или вообще один байт сделать на буфер, но тогда будет лагать, буквы будут набиваться по одной, как на пишущей машинке.
Ну а все сообщения типа марка датчика, здрасьте хозяин, состояние выключено, состояние включено, то есть неизменные тексты определить либо как PROGMEM byte[], (UPD: то есть char :) либо в EEPROM записать.
Игого расход - 1 (или 2) байта - номер, 1 байт - промежуточный буфер (куда pgm_read() будет читать флеш), 1 байт - счётчик, плюс буфер сообщения.
А к ней описать парочку функций готовящих этот самый массив. Выйдет очень существенная экономия памяти даже не только для статистических данных. Прсото мы зарезирвируем малость на генерацию одной строки и будет поочередно готовить обе строки, а потом выводить. Но это нужно только если опять же объем выводимых данных велик, а памяти уже не хватает.
Хотя бы размер стека возможно проверять? или ограничить его адресное пространство? Как его контролировать зверька этого? Переход на другую IDE не предлогать,мы же ARDUINO изучаем.
Конечно, доступна переменная - "край кучи" и доступен stack pointer - контролируйте, на здоровье.
Вот родился вопрос. А если в ходе выполения кода какая то часть глобальных переменных стала не нужна? Можно ли как-то прибить их, чтобы они не отедали ОЗУ? Например, в начале скетча объявлен массив из 35 элементов, но по ходу выполения последние 10 или первые десять элементов становятся более не нужными для дальнейшего исполения кода, а память- то они кушают... Как бы так сделать чтоб они исчезли. Ну типа переопределить это массив чтоли... Или как то подругому от них избавиться... Можно, конечно, в setup все сделать, но тогда при переходе в loop убьется весь массив, и исчезнут в том числе и нужные элементы.
Создавать массив "динамически" вначале, а не глобалом. Потом его удалять и создавать новый. Динамически - это через malloc(), или "в куче". Но, тут можно наступить на грабли "дырявости кучи": память освобождена будет, но вот использовать её как часть большего размера может и не получиться. Надо иметь верный порядок "выделений кучи". :)
Вот не хотелось бы как раз грабли иметь... Не по теме. Ваша затея увеличить озу на амеле. Рулит. Оч полезно. Даже 32 кб весьма расширят круг задач. Главное чтоб малой кровью. У меня 328 чип. Жаль что ему нельзя увеличить озу.
Так вас никто не заставляет "использовать грабли для чесания под лопаткой". В том смысле, что у Атмела недаром наверчено 100500 моделей, что на каждый класс задач использовать ровно то, что ему подходит. Тут надо определиться самостоятельно что вам нужнее: использовать именно тот МК что у вас есть и тогда решать на нем его круг задач или оттолкнуться от задачи и взять тот МК, который её решает оптимальным способом.
Тут достаточно часто "говорят правильные вещи", например "плясать от задачи" и при этом стараются использовать железо, совершенно не предназначенное для такого класса задач .. или методики создания ПО также "поперечные" к программированию МК. Меня это уже не удивляет. Это на случай, дабы не обижались. Вы тут не одиноки со своим 328 и кругом задач, выходящим за его рамки.
Да. Вот к примеру у меня есть проект, там используется сейчас всего 10 ножек, но объем памяти просто... очень душит. Брать мегу? Ну так стоимость взлетает, и выйдет так что на меге слишком много этой памяти. Жаба душит )
Так тчо если смотреть в сторону именно ардуинок, то выходит что между уно подобными и мега подобными пропасть.
Стоп. Ежели вы решаете некие задачи, то зачем вам "ардуино" решения? Плата ардуино - на то и "готовая плата" чтобы на ней УЧИТЬСЯ и пгобовать. А решения делаются в конечном устройстве. Какая нафиг разница какой МК паять в оконцовке? А разовое устройство для "дома сада" - не смешите мои тапки по поводу его "стоимости". Мегу даже сейчас ещё можно найти в пределах 600руб. Или вы предпочитаете экономить на спичках? :)
Ну начнем с того что это у 90% сдесь собравшихся хобби. И платить за устройство для сада/огорода за 600 даже р, когда скажем хватает пино mini или еще чего подобного с ценой в 50 рублей... переплачивать в 12 раз - как то не камильфо. В там раскладе проще брать готовые законченные комерческие решения и т.д. Но как бы в этом и суть. Тут сразу и занятие приятное с полезным и существенная экономия. Вот скажем вытяжка 220В с автоматически закрывающимися/открывающимися створками стоит 1100 рублей, а такая же с датчиком влажности 1900. Зачем переплачивать 800 рублей, у меня за стенкой висит arduino nano и у нее есть немного места свободного и есть 2 пина свободных. Докупаем модуль реле + dht11. Выходит порядка 150р от силы, а то на распродаже и дешевле (у меня вышло меньше 100р), дописываем немного кода и в ванной я могу с красивой кнопочки на tft экране запустить в ручную вытяжку, а вообще она умная и запускается автоматически при пороге который легко настроить. Вот Вам экономия 700 рублей, пару вечеров колупания и существенный профит. А так у нас еще и температура в ванной стала известна, мы со временем пригондобюим управление теплым полом и батареей. Ну и т.д. и т.п. А как по вашему... если учиться, то ну ни как не на ардуине. Учится надо на голой мк. Ибо тот кто начал учисья на ардуине будет в шоке с предстоящих трудностей скажем тех же admux и прочих херней в голой МК. Я кажем не смог одновременной в одной атмеге юзать serial, ацп и прерывания. Что-то 2-е в одном проекте крутится, а все вместе ни как. А уж это гребоное ацп... жопа страшная. Хотя я легко ваяю приложения, в свое время бесконечная машина тьюринга упирающаяся только в объем памяти ПК была написана за 1 ночь с визуализацией, графическим редактором и функцией проверки таблицы условий и входных данных. Т.е. само по себе программирование (хоть и другой язык, но с С я знаком более или менее) для меня не проблема, в том числе алгоритмизация и прочее. Но вот эту тупые трудности адмуксами и остальным, чтение 2-е суток мануалов и примеров, плюнул на протеус, собрал на макетке, ни хера. Плюнул и купил на пробу 1 ардуинку и через 3 часа половина готового устройства. Так вот для себя я решил что для дома и даже в производство много куда проще прикрутить ардуинку чем голый мк. Вот выпустили недавно подмотку к спидометру. Основана на nano, включается с радиометки и ей же управляется. Ни один завгар не запалит. И стоимость вышла 250 рублей если запчасти брать по штучно. А продает ее знакомый по 1500 ) Кода там на 15 минут было, а профит 200р с каждого девайса мои. Вот вам и голый мк.
sirota, Ну так "в чем пгоблема"? Как понимаю, эта философия тут рулит больше чем в 80% участников .. не лезет в память? Так вам по-любому, придется ИЛИ писать свои библиотеки и разбираться с этими ADMUX (не нашел в них ничего сложного, ATMEL сделал всё, чтобы работа с железом была даже и проще чем с wiring в ряде случаев!) И/ИЛИ переходить на тот МК, в который оно лезет. Память - ровно такой же "ресурс" как и пины у МК, и его точно также "маловато будет". Особенно, если делать "тяп-ляп".
А последнее - есть основной тезис философии тутошнего большинства: сэкономить копейку на приобретении МК и потратить гору времени (и денег) потом, чтобы впихнуть невпихуемое. Посмотрите на количество тем "не лезет" (ну не преназначен ногодрыг для работы с дисплеями!), "таймер не пашет" (ну так нога уже занята под другое!) и пр. чудеса "экономистов". :)
Я от части согласен. ПОнятно что нет смысла на меге8 городить интерфейс на 10'' экране. Но я про то что вообще разрыв между 328P и Мега2560 большое. Что нет золотой серединки между ними в готовом к употреблении изделии.
И я не справился с admux. Честно первый раз сидел 2-е суток, колупал протеус. Не вышло. Начал новый проект с примера, т.е. только аналоговые измерения. Взял готовый пример, работает, вставил в код свой - не работает. Ну дуамаю протеус лажает, собрал в железе, сосать. СОбираю в железе чисто кусок с аналогом, и из своего кода вырезаю все не связанное и... не работает все равно, хотя по сравнению с примером там изменений тольк опод мои реалии (другой пин и таймер). Так я и бросил голые мк )
Разрыв только в Ардуино платах и их совместимостях. Разрывов в МК не настолько много, можно подобрать тот, который именно вам нужен под именно вашу задачу. И, если вы паяете плату с каким-либо "обвесом" .. запаять корпус не из TQFP-100 не знаю у кого может вызвать пгоблему. Есть вполне паябельные корпуса ручками. Вполне нормально запаял SO-20 на плату расширителя памяти, что называется "левой задней" .. вот пропаять сторону памяти между корпусами (там 4мм расстояние) устанавливая 2 DIP-28 ака SOP на плату .. оказалось куда как сложней (жало паяльника не пролазит между корпусами), но за 3 часа вполне справился.
ИМХО, все ваши аргументы - сильно надуманы. Берите ATmega128A и не парьтесь. теже 80руб за корпус.
Вот родился вопрос. А если в ходе выполения кода какая то часть глобальных переменных стала не нужна? Можно ли как-то прибить их, чтобы они не отедали ОЗУ? Например, в начале скетча объявлен массив из 35 элементов, но по ходу выполения последние 10 или первые десять элементов становятся более не нужными для дальнейшего исполения кода, а память- то они кушают... Как бы так сделать чтоб они исчезли. Ну типа переопределить это массив чтоли... Или как то подругому от них избавиться... Можно, конечно, в setup все сделать, но тогда при переходе в loop убьется весь массив, и исчезнут в том числе и нужные элементы.
Ответ был дан в затравочной статье топика (первый абзац раздела "Статические и глобальные переменные"): "Занятую этими переменными память в программе не нужно явно запрашивать и нет никакой возможности освободить – они живут в течение всего времени выполнения программы". Слово "никакой" означает "совсем никакой".
Правда, эту память можно повторно использовать. Например, в одной части программы Вам нужен массив из 20 символов, а в другой массив из 10 целых чисел - наложите их друг на друга с помощью union и "повторно используйте" на здоровье.
Полноценный диспетчер должен вести списки выделенных кусков (указатель на начало куска, размер куска, указатель следующего/предыдущего куска и т.д. - только "описание" куска - очереди, коллекции - "наше всё"), вести список "дырок", уметь сливать соседние дырки в одну большую, иметь стратегию выделения/поиска подходящего куска и они есть разные .. и мн.др.
Avr-libc всё это делает.
вот еще бы простейший примерчик, чтобы воочию увидеть этот "изюм"...
Ну, дождитесь следующего этюда :)
Догадываюсь что делает .. я про "цена вопроса". К тому что "пользовать можно", но, как обычно, "с головой", понимая чего и сколько оно за собой потянет, а не потому что "во как кузяво". :)
Блин, я чего-то не понимаю или одно из двух. У меня вот есть проект устройство , которое может обслуживать 10 датчиков разных типов, при этом к устройству одновременно может быть подключен только 1. некоторые тут наверно помнят о чем речь. Так вот, в проекте используется 16х2 LCD и после того как определился тип датчика,
его название и некоторые параметры выводятся в первую строку лсд, причем занимая ее всю, т.е. 16 символов.
Вначале скетча я определил все это дело как
char* SensType[]={ "датчик такой-то бла бла", " датчик другой бла бла" , и тд};
Ну и понятно есть некая переменная byte type , которой в ходе выполнения процедуры определения типа датчика присваивается номер от 0 до 9, ну а чтоб напечатать соответсвенно дается команда
lcd.print (SensType[type]);
И это происходит только один раз после старта скетча определили тип напечатали и забыли. Так оно там на лсд и висит в первой строчке.
10 датчиков описание каждого 16 символов. Вот мне ниразу неохота чтобы как минимум 160 байт ненужной мне инфы все время висели в ОЗУ.
Вопрос. То как я сделал как будет работать? И как надо сделать правильно.
Вместо char*, const char*. Или это вид сбоку?
Никак. Ибо это вовсе не "ненужные 160 байт", а очень даже нужные. Поскольку определение типа датчика вынесено в runtime, то весь код, зависящий от типа, точно также будет в runtime. То есть то что вы печатаете 1 раз за весь цикл работы проги - ни разу не "основание" искать способ экономии. Ваши строки - нужны все, даже если они используются ровно 1 раз.
Да, нужны они все, но блин это же расточительство ОЗУ. Я-то хочу чтобы они все время были во флеше. А когда понадобилась одна строка взяли ее загрузили в ОЗУ, напечатали и всё. И не будет постоянно висеть в памяти. Это что же получается если в каком нить проекте идет большая работа с текстом, он что все время будет весь в озу, забьет его целиком и не останется ничего?
Не нравится мне это. Может мне мой char* запихнуть в функцию? И превратится он в локал. Когда надо будет напечатать ( тот самы один единственный раз при выполнении setup) ну появятся эти 160 байт в оперативке, а потом исчезнут. Как думаете прокатит?
Короче мне надо понимать произойдет ли выделение памяти (те самы 160 байт) как только в начале скетча выполнится команда char*... И постоянно в озу будут висеть все строки или все это подгрузится при обращении к массиву лсд.принт и когда печать произойдет память освободится. Не, ну мужики, ну это ж не дело так озу-то расходовать :(
Правильно написал, как здесь описано:
http://arduino.ru/Tutorial/Memory
Описание PROGMEM здесь:
http://atmel.ucoz.ru/publ/progmem/1-1-0-64
Seva1800, можно сделать какую-нибудь функцию LCDprint, давать ей номер сообщения выводимого на экране (байт, или два байта если таких сообщений больше 256), а она будет мотать цикл с pgm_read() в буфер сколько там длина экрана (16 байт например), и выводить из нужного места флеша/EEPROM в экран. Или 4 байта сделать буфер. Или вообще один байт сделать на буфер, но тогда будет лагать, буквы будут набиваться по одной, как на пишущей машинке.
Ну а все сообщения типа марка датчика, здрасьте хозяин, состояние выключено, состояние включено, то есть неизменные тексты определить либо как PROGMEM byte[], (UPD: то есть char :) либо в EEPROM записать.
Игого расход - 1 (или 2) байта - номер, 1 байт - промежуточный буфер (куда pgm_read() будет читать флеш), 1 байт - счётчик, плюс буфер сообщения.
а еще есть регистры быстрого доступа, о них как-то не упоминули. Они вроде тоже к озу относятся. Но многие ардуиновцы даташитов не читали. Раскажите и о них (о регисрах а не о тех ардуиновцах).
Для программирующих с использованием Wiring - регистров, как таковых нет, ибо они - часть локалов, причем достаточно небольшая, учитывая "любовь" в длинным целым числам. Поэтому как-бы их нет и "рассказывать" не о чем. А тем, кто wiring не пользует - рассказывать не требуется, они и сами вам рассказать могут .. :)
Ещё напомню тут, поскольку тема прибита гвоздиком, а вопрос периодически возникает:
Для программирующих в Wiring надо помнить о том, что ИДЕ переносит все объявления функций скетча в ЕГО НАЧАЛО, даже если вы это сделали сами. Отсюда возникает трабл: при объявлении в самом скетче классов и их методов - очень легко словить "липовую ошибку" в виде "неопределен класс параметра" в объявлении функции.
ВСЕ объявления классов надо выносить в отдельные файлы и их инклудить в скетч. Верно по меньшей мере для ИДЕ 1.6.5
Угу. И этот перенос - основная идея (и по большему счету единственная существенная) у этого самого виринга. Я бы её автора кастрировал, в интелектуальном смысле слова. Потому от версии ИДЕ это не зависит.
Трабла возникает не только для классов но и для других пользовательских типов, используеммых в параметрах функции. Потому иногда выручает приводить к стандартному, указательн свою структуру к void* например, а в функции приводить обратно. Выносить свои типы удобно в ашник в папке скетча, тогда ИДЕ его инклудит сама и открывает автоматом в закладке.
Да, не только типов и классов. Например, если умалчиваемым значением параметра функции задать что-то определённое в define - задница. А с ifdef'ами что творится! Да там дофига "фокусов" вылезает. Руки отрывать надо таким "упрощателям для чайников". Сами, блин, чайники а туда же - упрощать полезли.
Только вот Wiring тут при каких делах, я не понял. IDE'шный препроцессор воду мутит, а Wiring-то причём? К нему и своих претензий хватает, зачем на него ещё лишних собак вешать?
IDE'шный препроцессор воду мутит, а Wiring-то причём?
Так Wiring как раз и реализован в препроцессоре! Т.е. ИДЕ вызывает препроцессор Wiringa, тот глумится над кодом, затем вызываются штатные средства gcc препроцессор, компилер, линкер. Вы думаете эти упрощатели свой компилер писали?! То им сложно очень, непосильно..
Ну еще есть набор либок сишных с специфическими функциями, так либка и есть либка, на язык это не тянет.
Да, ну, ладно. Я то думал, что wiring, это библиотека расположенная в файлах wiring*.c и wiring*.h, а препроцессор делает всего лишь две простые вещи: вставляет #include <arduino.h>, и собирает заголовки функций в начало. А дальше, просто вызывает gcc для компиляции.
Logik прав полностью. Wiring - это то самое глумление над кодом встроенным в ИДЕ препроцессором, а wiring.c и пр. лабуда - всего лишь плохо написанные библиотеки к нему.
Так библиотека и есть библиотека - набор функций, классов и т.д. Если её считать языком, то и до языков stddef io и т.д. недалеко. Язык прежде всего синтаксис, известные отличия описаны выше и реализуются ни как не либой. С ними не столкнутся работая в ИДЕ я не могу, а хотелось бы, а вот без wiring*.c можно обойтись. По крайней мере можно обойтись, если бы ИДЕ их не подключало не спрашивая меня.
Не нужен wiring, не используйте, кто заставляет?
Есть куча ide, которые wiring не используют и не заставляют. Нравится ArduinoIDE? Но не нужен wiring? Продолжайте маяться. Чего ныть то? Рук нет?
Не в этом дело. Я уже не первый раз натыкаюсь на эти проблемы с Wiring, поэтому и отписал сюда. Народ, который умеет программировать на С++ первым делом ваяет "свои" классы и их методы .. и наступает на эту граблю. Вот и поместил сюда, ибо тема "прибита гвоздиком", а значит "не утонет". Понятно, что новичкам, пишущим исключительно на Wiring и пользующим только его типовые либы - это не нужно. Но срединих часто "попадаются" и люди, имеющие опыт писания на С с плюсами. А вот прочитать "что делает Wiring" и чем отличается от чистого С с плюсами .. не все удосуживаются внимательно и двумчиво, хотя там всё это и изложено.
"то у него будет третий элемент a[3]. Это не так. Элементы данного массива будут: a[0], a[1] и a[2], а вот попытка использовать a[3] – как раз и есть выход за границы массива. Что при такой попытке произойдёт? Ну, если читаем, то скорее всего ничего страшного, просто прочитаем что там в памяти сразу после массива лежит. А вот если пишем – то мы то, что там после массива лежит, запросто поменяем! И нашей программе это наверняка не понравится!"
Мне просто интересно, а как вообще допускается? По хорошему вызывается исключение. Я с C подобными языками пока не очень, но я точно помню что в том же pascal при обращении к памяти которую я не инициализировал я получу исключение. Если обратиться скажем напрямую к адресу в памяти, то конечно куда угодно (не защищенный режим), а так скажем объявив c[3], и сделав хоть x=c[3], хоть c[3]=x я получу исключение. А в С вездте так или это конкретно особенность avr? Или тут наобород сделано типа на безотказность. Но тогда можно очень долго искать скажем баг связанный с x=c[3], когда надо было x=c[2].
Везде так. В принципе, некоторые компиляторы имеют опцию - сгенеровать код для проверки выхода за границы массива, но это уже "типа расширение языка", т.к. в языке как таковом никакие такого рода проверки не предусмотрены и выходить за пределы "можно".
А существует возможность принудительной очистки стека?
Стек можно сравнить со скелетом, если его неумело "почистить", тело развалится. Как правило этого не нужно делать. Во всяком случае этого лучше избегать и биться за это до конца. И отвечая на Ваш вопрос, да, можно почистить, но не нужно.
В PIC 16 (начинал изучать с них и ассемблера,даташиты на PIC отличные,в отличии от Atmel, но это мое мнение) стек ограничен,приходилось изворачиваться что бы не переполнить,да и в MPLAB отладчик помогал. А вот на атмеге раз нет ограничения и в ИДЕ ардуино нет отладчика где можно посмотреть что со стеком ,становится страшно. Вот сейчас добиваю проэкт и после множественных вызовов одной из функций в которой присутствует GOTO выкидывающая из незавершенного цикла while к входу в этот цикл (изменяемые при необходимости настройки времени, а в while это время является одним из условий выполнения цикла ) существует вероятность что переполнится стек. Хотя бы размер стека возможно проверять? или ограничить его адресное пространство? Как его контролировать зверька этого? Переход на другую IDE не предлогать,мы же ARDUINO изучаем.
А с чего вы решили, что GOTO выкидывающий в начало цикла увеличивает стек? Значение указателя стека проверяли?
Действительно. А что там переполнится? Стек чего?
Да тут же нечему переполняться,раз нет ограничения то и переполниться нечему,так только на кучу налезть может.
Извиняюсь,туплю по страшному,вот засело в голове переполнение стека,последствия PIC и невнимательность,хотя тему то прочитал и зациклился хз на чем.
Seva1800, можно сделать какую-нибудь функцию LCDprint, давать ей номер сообщения выводимого на экране (байт, или два байта если таких сообщений больше 256), а она будет мотать цикл с pgm_read() в буфер сколько там длина экрана (16 байт например), и выводить из нужного места флеша/EEPROM в экран. Или 4 байта сделать буфер. Или вообще один байт сделать на буфер, но тогда будет лагать, буквы будут набиваться по одной, как на пишущей машинке.
Ну а все сообщения типа марка датчика, здрасьте хозяин, состояние выключено, состояние включено, то есть неизменные тексты определить либо как PROGMEM byte[], (UPD: то есть char :) либо в EEPROM записать.
Игого расход - 1 (или 2) байта - номер, 1 байт - промежуточный буфер (куда pgm_read() будет читать флеш), 1 байт - счётчик, плюс буфер сообщения.
А можно еще проще. Скажем зачести тот же
А потом читать в нее PROGMEM. И написать скажем функцию:
И вставлять нужные данные. Можно описать одну функцию скажем
А к ней описать парочку функций готовящих этот самый массив. Выйдет очень существенная экономия памяти даже не только для статистических данных. Прсото мы зарезирвируем малость на генерацию одной строки и будет поочередно готовить обе строки, а потом выводить. Но это нужно только если опять же объем выводимых данных велик, а памяти уже не хватает.
Хотя бы размер стека возможно проверять? или ограничить его адресное пространство? Как его контролировать зверька этого? Переход на другую IDE не предлогать,мы же ARDUINO изучаем.
Конечно, доступна переменная - "край кучи" и доступен stack pointer - контролируйте, на здоровье.
Вот родился вопрос. А если в ходе выполения кода какая то часть глобальных переменных стала не нужна? Можно ли как-то прибить их, чтобы они не отедали ОЗУ? Например, в начале скетча объявлен массив из 35 элементов, но по ходу выполения последние 10 или первые десять элементов становятся более не нужными для дальнейшего исполения кода, а память- то они кушают... Как бы так сделать чтоб они исчезли. Ну типа переопределить это массив чтоли... Или как то подругому от них избавиться... Можно, конечно, в setup все сделать, но тогда при переходе в loop убьется весь массив, и исчезнут в том числе и нужные элементы.
Создавать массив "динамически" вначале, а не глобалом. Потом его удалять и создавать новый. Динамически - это через malloc(), или "в куче". Но, тут можно наступить на грабли "дырявости кучи": память освобождена будет, но вот использовать её как часть большего размера может и не получиться. Надо иметь верный порядок "выделений кучи". :)
Вот не хотелось бы как раз грабли иметь... Не по теме. Ваша затея увеличить озу на амеле. Рулит. Оч полезно. Даже 32 кб весьма расширят круг задач. Главное чтоб малой кровью. У меня 328 чип. Жаль что ему нельзя увеличить озу.
Так вас никто не заставляет "использовать грабли для чесания под лопаткой". В том смысле, что у Атмела недаром наверчено 100500 моделей, что на каждый класс задач использовать ровно то, что ему подходит. Тут надо определиться самостоятельно что вам нужнее: использовать именно тот МК что у вас есть и тогда решать на нем его круг задач или оттолкнуться от задачи и взять тот МК, который её решает оптимальным способом.
Тут достаточно часто "говорят правильные вещи", например "плясать от задачи" и при этом стараются использовать железо, совершенно не предназначенное для такого класса задач .. или методики создания ПО также "поперечные" к программированию МК. Меня это уже не удивляет. Это на случай, дабы не обижались. Вы тут не одиноки со своим 328 и кругом задач, выходящим за его рамки.
Да. Вот к примеру у меня есть проект, там используется сейчас всего 10 ножек, но объем памяти просто... очень душит. Брать мегу? Ну так стоимость взлетает, и выйдет так что на меге слишком много этой памяти. Жаба душит )
Так тчо если смотреть в сторону именно ардуинок, то выходит что между уно подобными и мега подобными пропасть.
Возьмите ATmega128A у неё тоже есть x-bus шина для расширения памяти и ножек не настолько много и стоит она копейки.
Стоп, а когда мы от ардуинок приобретаемых в китае ушли в голые мк? С голыми мк все в разы легче.
Стоп, а когда мы от ардуинок приобретаемых в китае ушли в голые мк? С голыми мк все в разы легче.
чем легче?
Разнообразием контроллеров. Если тут мы грубо говоря имеем 168, 328 и мега, то в голым мк выбор значителен. Не устраивает атмеги, бери stm.
Стоп. Ежели вы решаете некие задачи, то зачем вам "ардуино" решения? Плата ардуино - на то и "готовая плата" чтобы на ней УЧИТЬСЯ и пгобовать. А решения делаются в конечном устройстве. Какая нафиг разница какой МК паять в оконцовке? А разовое устройство для "дома сада" - не смешите мои тапки по поводу его "стоимости". Мегу даже сейчас ещё можно найти в пределах 600руб. Или вы предпочитаете экономить на спичках? :)
Ну начнем с того что это у 90% сдесь собравшихся хобби. И платить за устройство для сада/огорода за 600 даже р, когда скажем хватает пино mini или еще чего подобного с ценой в 50 рублей... переплачивать в 12 раз - как то не камильфо. В там раскладе проще брать готовые законченные комерческие решения и т.д. Но как бы в этом и суть. Тут сразу и занятие приятное с полезным и существенная экономия. Вот скажем вытяжка 220В с автоматически закрывающимися/открывающимися створками стоит 1100 рублей, а такая же с датчиком влажности 1900. Зачем переплачивать 800 рублей, у меня за стенкой висит arduino nano и у нее есть немного места свободного и есть 2 пина свободных. Докупаем модуль реле + dht11. Выходит порядка 150р от силы, а то на распродаже и дешевле (у меня вышло меньше 100р), дописываем немного кода и в ванной я могу с красивой кнопочки на tft экране запустить в ручную вытяжку, а вообще она умная и запускается автоматически при пороге который легко настроить. Вот Вам экономия 700 рублей, пару вечеров колупания и существенный профит. А так у нас еще и температура в ванной стала известна, мы со временем пригондобюим управление теплым полом и батареей. Ну и т.д. и т.п. А как по вашему... если учиться, то ну ни как не на ардуине. Учится надо на голой мк. Ибо тот кто начал учисья на ардуине будет в шоке с предстоящих трудностей скажем тех же admux и прочих херней в голой МК. Я кажем не смог одновременной в одной атмеге юзать serial, ацп и прерывания. Что-то 2-е в одном проекте крутится, а все вместе ни как. А уж это гребоное ацп... жопа страшная. Хотя я легко ваяю приложения, в свое время бесконечная машина тьюринга упирающаяся только в объем памяти ПК была написана за 1 ночь с визуализацией, графическим редактором и функцией проверки таблицы условий и входных данных. Т.е. само по себе программирование (хоть и другой язык, но с С я знаком более или менее) для меня не проблема, в том числе алгоритмизация и прочее. Но вот эту тупые трудности адмуксами и остальным, чтение 2-е суток мануалов и примеров, плюнул на протеус, собрал на макетке, ни хера. Плюнул и купил на пробу 1 ардуинку и через 3 часа половина готового устройства. Так вот для себя я решил что для дома и даже в производство много куда проще прикрутить ардуинку чем голый мк. Вот выпустили недавно подмотку к спидометру. Основана на nano, включается с радиометки и ей же управляется. Ни один завгар не запалит. И стоимость вышла 250 рублей если запчасти брать по штучно. А продает ее знакомый по 1500 ) Кода там на 15 минут было, а профит 200р с каждого девайса мои. Вот вам и голый мк.
Ни один завгар не запалит.
а, есть точно такое же, только для банкомата?
Брутфорс Вам нужен. Ломом )
sirota, Ну так "в чем пгоблема"? Как понимаю, эта философия тут рулит больше чем в 80% участников .. не лезет в память? Так вам по-любому, придется ИЛИ писать свои библиотеки и разбираться с этими ADMUX (не нашел в них ничего сложного, ATMEL сделал всё, чтобы работа с железом была даже и проще чем с wiring в ряде случаев!) И/ИЛИ переходить на тот МК, в который оно лезет. Память - ровно такой же "ресурс" как и пины у МК, и его точно также "маловато будет". Особенно, если делать "тяп-ляп".
А последнее - есть основной тезис философии тутошнего большинства: сэкономить копейку на приобретении МК и потратить гору времени (и денег) потом, чтобы впихнуть невпихуемое. Посмотрите на количество тем "не лезет" (ну не преназначен ногодрыг для работы с дисплеями!), "таймер не пашет" (ну так нога уже занята под другое!) и пр. чудеса "экономистов". :)
Я от части согласен. ПОнятно что нет смысла на меге8 городить интерфейс на 10'' экране. Но я про то что вообще разрыв между 328P и Мега2560 большое. Что нет золотой серединки между ними в готовом к употреблении изделии.
И я не справился с admux. Честно первый раз сидел 2-е суток, колупал протеус. Не вышло. Начал новый проект с примера, т.е. только аналоговые измерения. Взял готовый пример, работает, вставил в код свой - не работает. Ну дуамаю протеус лажает, собрал в железе, сосать. СОбираю в железе чисто кусок с аналогом, и из своего кода вырезаю все не связанное и... не работает все равно, хотя по сравнению с примером там изменений тольк опод мои реалии (другой пин и таймер). Так я и бросил голые мк )
Разрыв только в Ардуино платах и их совместимостях. Разрывов в МК не настолько много, можно подобрать тот, который именно вам нужен под именно вашу задачу. И, если вы паяете плату с каким-либо "обвесом" .. запаять корпус не из TQFP-100 не знаю у кого может вызвать пгоблему. Есть вполне паябельные корпуса ручками. Вполне нормально запаял SO-20 на плату расширителя памяти, что называется "левой задней" .. вот пропаять сторону памяти между корпусами (там 4мм расстояние) устанавливая 2 DIP-28 ака SOP на плату .. оказалось куда как сложней (жало паяльника не пролазит между корпусами), но за 3 часа вполне справился.
ИМХО, все ваши аргументы - сильно надуманы. Берите ATmega128A и не парьтесь. теже 80руб за корпус.
Ответ был дан в затравочной статье топика (первый абзац раздела "Статические и глобальные переменные"): "Занятую этими переменными память в программе не нужно явно запрашивать и нет никакой возможности освободить – они живут в течение всего времени выполнения программы". Слово "никакой" означает "совсем никакой".
Правда, эту память можно повторно использовать. Например, в одной части программы Вам нужен массив из 20 символов, а в другой массив из 10 целых чисел - наложите их друг на друга с помощью union и "повторно используйте" на здоровье.
Ну начнем с того что это у 90% сдесь собравшихся хобби.
Вот поэтому, ВОЗМОЖНО, памяти и не хватает. Копипастить надо меньше и все подряд не инклюдить, а что инклюдим проверять.
Конечно, может я и ошибаюсь, возможно вы решили дисплей к дуне подцепить и в WOT гонять по сети, тогда конечно не хватит.
Скажите специалисты, что тут не так? как надо? вот такая ошибка
Скажите специалисты, что тут не так? как надо? вот такая ошибка
Если просит "variable 'station' must be const ", почему бы не удовлетворить?