Чтобы компенсировать этот недостаток, чипы подобные AT28C256, оснащаются функцией блочного программирования. При таком подходе к программированию, одновременно (блоком) загружаются 64, 128 или 256 байт. Блочный способ сокращает время программирования.
Как хранить данные в Arduino
У плат семейства плат Arduino есть несколько видов памяти. Во-первых, это статическое ОЗУ (оперативное запоминающее устройство), которая используется для хранения переменных в процессе выполнения программы. Во-вторых, это флеш-память, в которой хранятся написанные вами скетчи. И в-третьих, это EEPROM, которую можно использовать для постоянного хранения информации. Первый тип памяти – энергозависимый, он теряет всю информацию после перезагрузки Arduino. Вторые два типа памяти хранят информацию пока она не будет перезаписана новой, даже после отключения питания. Последний тип памяти – EEPROM – позволяет записывать данные, хранить их и считывать при необходимости. Эту память мы и рассмотрим сейчас.
Инструкция по использованию EEPROM в Arduino
EEPROM означает Electrically Erasable Programmable Read-Only Memory, т.е. электрически стираемое перепрограммируемое постоянное запоминающее устройство. Данные в этой памяти могут храниться десятки лет после отключения питания. Количество циклов перезаписи – порядка нескольких миллионов раз.
- для плат, основанных на микроконтроллере ATmega328 (например, Arduino UNO и Nano), количество памяти составляет 1 кБ,
- для плат на ATmega168 и ATmega8 – 512 байт,
- на ATmega2560 и ATmega1280 – 4 кБ.
Тип памяти серии 27… 27C… сохраняет записанные программатором данные до следующего программирования с функцией стирания или без таковой. Допускается многократное программирование без стирания, при условии изменения битов только от состояния единицы до состояния нуля или имеющих состояние нуль.
Библиотека avr/eeprom.h
Описание к этой библиотеке я спрятал под спойлер, потому что она не очень актуальна и знать о ней необязательно. Также она не работает на esp8266/32 по понятным причинам.
Стандартная библиотека eeprom.h идёт в комплекте с компилятором avr-gcc, который компилирует наши скетчи из под Arduino IDE. Полную документацию можно почитать здесь. Для подключения библиотеки в скетч пишем #include Библиотека имеет набор функций для работы с целочисленными типами данных ( byte – 1 байт, word – 2 байта, dword – 4 байта), float , и block “блоков” – наборов данных любого формата (структуры, массивы, и т.д.). Под работой подразумевается запись, чтение и обновление. Обновление – крайне важный инструмент, позволяющий избежать лишних перезаписей ячеек памяти. Обновление делает запись, если записываемое значение отличается от текущего в этой ячейке. Чтение:
- eeprom_read_byte(адрес) – вернёт значение
- eeprom_read_word(адрес) – вернёт значение
- eeprom_read_dword(адрес) – вернёт значение
- eeprom_read_float(адрес) – вернёт значение
- eeprom_read_block(адрес в SRAM, адрес в EEPROM, размер) – прочитает содержимое по адрес в EEPROM в адрес в SRAM
- eeprom_write_byte(адрес, значение)
- eeprom_write_word(адрес, значение)
- eeprom_write_dword(адрес, значение)
- eeprom_write_float(адрес, значение)
- eeprom_write_block(адрес в SRAM, адрес в EEPROM, размер) – запишет содержимое по адрес в SRAM в адрес в EEPROM
- eeprom_update_byte(адрес, значение)
- eeprom_update_word(адрес, значение)
- eeprom_update_dword(адрес, значение)
- eeprom_update_float(адрес, значение)
- eeprom_update_block(адрес в SRAM, адрес в EEPROM, размер) – обновит содержимое по адрес в SRAM в адрес в EEPROM
- _EEPUT(addr, val) – записывает (write) байт val по адресу addr . Приведение типов не требуется (оно сделано в макросе)
- _EEGET(val, addr) – читает байт по адресу addr и записывает его в переменную val . Приведение типов не требуется (оно сделано в макросе)
Рассмотрим простой пример, в котором происходит запись и чтение единичных типов данных в разные ячейки:
Хранить данные таким образом не очень удобно, потому что менеджмент адресов приходится проводить вручную, считать количество байт в каждом типе и “сдвигать” адрес на нужное количество. Гораздо удобнее хранить разношёрстные данные в структурах, про них мы подробнее говорили в уроке про типы данных. Мы должны передать функции адрес данных в памяти (оператор & ), по сути – указатель, а также преобразовать его к типу void* , потому что функция чтения/записи блока принимает именно такой тип. Подробнее про указатели мы говорили в отдельном уроке. Также функции чтения/записи блока нужно передать размер блока данных в количестве байт. Это можно сделать вручную (числом), но лучше использовать sizeof() , которая посчитает этот размер и передаст в функцию.
Точно так же можно хранить массивы:
В библиотеке avr/eeprom.h есть ещё один очень полезный инструмент – EEMEM, он позволяет сделать автоматическую адресацию данных путём создания указателей, значение которым присвоит компилятор. Рассмотрим пример, в котором запишем в EEPROM несколько переменных, структуру и массив, раздав им автоматически адреса. Важный момент! Адреса задаются снизу вверх по порядку объявления EEMEM, я подпишу их в примере:
Библиотека EEPROM.h
Библиотека EEPROM.h идёт в комплекте с ядром Arduino и является стандартной библиотекой. По сути EEPROM.h – это удобная оболочка для avr/eeprom.h, чуть расширяющая её возможности и упрощающая использование. Важный момент: подключая в скетч EEPROM.h мы автоматически подключаем avr/eeprom.h и можем пользоваться её фишками, такими как EEMEM. Рассмотрим инструменты, которые нам предлагает библиотека:
- EEPROM.write(адрес, данные) – пишет данные ( только byte! ) по адресу
- EEPROM.update(адрес, данные) – обновляет (та же запись, но лучше) байт данных, находящийся по адресу. Не реализована для esp8266/32!
- EEPROM.read(адрес) – читает и возвращает байт данных, находящийся по адресу
- EEPROM.put(адрес, данные) – записывает (по факту – обновляет , update) данные любого типа (типа переданной переменной) по адресу
- EEPROM.get(адрес, данные) – читает данные по адресу и сам записывает их в данные – указанную переменную
- EEPROM – библиотека позволяет работать с EEPROM памятью как с обычным массивом типа byte ( uint8_t )
В отличие от avr/eeprom.h у нас нет отдельных инструментов для работы с конкретными типами данных, отличными от byte, и сделать write/update/read для float/long/int мы не можем. Но зато у нас есть всеядный put/get, который очень удобно использовать! Рассмотрим пример с чтением/записью байтов:
Логика работы с адресами такая же, как в предыдущем пункте урока! Обратите внимание на работу с EEPROM как с массивом, можно читать, писать, сравнивать, и даже использовать составные операторы, например EEPROM0 += 10 , но это работает только для элементарных ячеек, байтов. Теперь посмотрим, как работает put/get:
Гораздо удобнее чем write_block и read_block, не правда ли? Put и get сами преобразовывают типы и сами считают размер блока данных, использовать их очень приятно. Они работают как с массивами, так и со структурами.
Для изменения значения придётся прочитать ячейку, выполнить нужные операции, и снова в неё записать. Ещё один удобный хак: можно ввести макросы на чтение и запись определённых значений, например:
А что такое EEPROM и где оно живет?
В последних версиях OpenComputers обрастает всякими загадочными вещами.
Игроки, которые только только освоились с предыдущей версией вдруг понимают, что надо изучать все заново.
«А пошло оно все!» — думают игроки, и уходят на версию 1.3.6, или переучиваются на ComputerCraft, который проще, и не требует непонятного.
А одна из самых загадочных — неведомый EEPROM.
Это такая мелкая хрень, без которой не работает ни один компьютер, или даже робот. Хорошо еще, что есть стандартный EEPROM который называется Lua BIOS. Он легко крафтится и заставляет работать компьютеры как и раньше.
Но найдем задачку посложнее, где Lua BIOS не поможет.
Попробуем собрать микроконтроллер, который будет управлять входными дверями.
Представим, как оно должно работать.
Слева от двери (если входить) — микроконтроллер.
Ради понтов, возьмем Микроконтроллер 2-ого уровня и поставим в него беспроводную сетевую плату. Кроме того добавим красную плату, чтобы управлять дверью.
1. Если контроллер принимает сигнал «open» — он открывает дверь.
2. Если примет сигнал «close» — он закрывает дверь.
3. Если примет посторонний сигнал — взрывает динамит. Дабы сокровища не достались хакерам.
Для управления задействуем любой комп, у которого тоже будет беспроводная плата (или точка доступа).
2. Крафтим контроллер
С этим проблем не возникнет. Потому, что я играю в креативе 😛 .
Открываем NEI и берем нужные детали. В последний слот положим пока пустой EEPROM. Потом поставим на него прошивку, а пока — не важно.
Нажимаем кнопку «Старт» и достаем готовый блок.
3. Готовим прошивку
Теперь, когда все готово, мы построили сокровищницу и скрафтили контроллер — осталось самое главное.
Программирование EEPROM’а отличается от программирования обычной программы.
Потому, что обычно, наши программы выполняются в OpenOS, которая заботливо загружает нужные библиотеки, предоставляет всякие удобные фичи и прочее.
Тем не менее писать мы будем именно в OpenOS. Запустим компьютер, напишем edit bios и введем следующие строки:
Дело в том, что большая часть библиотек, которые мы использовали — это библиотеки OpenOS. А значит мы не можем ими пользоваться в BIOS. Однако кое-что нам доступно.
Это библиотеки computer и component , и соответственно все установленные в целевом агрегате (микроконтроллер) компоненты.
Более чем достаточно для наших задач.
Вышеприведенный код делает следующее:
* ищет компонент с названием » redstone » и возвращает его прокси
* в вечном цикле посылает нулевой редстоун-импульс направо (side = 5), т.е. гасит сигнал
* ждет секунду (на самом деле — ожидает эвентов, то есть сигналов)
* посылает редстоун сигнал с силой 15 направо
Преследуем двоякую цель: во-первых проверить, что EEPROM вообще работает так про него написано на Вики. Кто его знает? А во-вторых: убедиться, что сторона 5 это именно та сторона, где дверь. А не какая-нибудь другая.
18 комментариев
Полезные ресурсы
Голосование
Информация
О нас
Проект ComputerCraft.ru основан в 2014 году. Особенностью наших игровых серверов является обязательное наличие компьютерных и технических модов и аддонов. Когда мод ComputerCraft устарел и больше не отвечал техническим требованиям, ему на замену пришел современный и высокотехнологичный мод OpenComputers. Черепашек заменили роботы из мода Opencomputers.
ComputerCraft.ru — это площадка для игры в Minecraft и общения на форуме, стабильные серверы и возможность в легкой и игровой форме обучиться программированию на языке Lua и реализовать все свои самые смелые инженерные идеи и решения и поделиться ими с другими игроками. За все время существования проекта сменилось 10 игровых серверов, которые посетили более 9000 игроков. На сайте собрано множество интересных программ и библиотек, статей, гайдов, веселых историй и горячих обсуждений, выдвинуто множество идей автоматизации и способов программирования.
У нас играют и пишут программы как новички так и опытные программисты. А самые продвинутые участники нашего коллектива даже разрабатывают собственные авторские моды и аддоны, ресурспаки, репозитории, мощнейшие библиотеки и операционные системы.
Регистрируйтесь прямо сейчас и присоединяйтесь к нашему дружному коллективу фанатов игры Minecraft , компьютерных и инженерных модов!
Типичный EEPROM протокол содержит 3 фазы: Код операции, фазы адреса и фазы данных. Код операции — обычно первые 8 бит, далее следует фаза адреса в 8-24 бита (зависит от устройства) и в конце запись или чтение информации.
Результат
Собственно все, теперь мы можем регистрировать в списке любые параметры:
Замечу, что пользователю параметров нужно только объявить параметр и список, а вся портянка с кодом, до этого, пишется один раз. Используются параметры точно также как и CachedNvData .
Что произойдет в этом примере, когда мы будем писать 10,11,12. 15 в наш параметр. Каждый раз при записи, адрес параметра будет смещаться на размер параметра + размер индекса + размер копии параметра и индекса. Как только количество записей превысит максимальное количество, параметр начнет писаться с начального адреса.
На картинке снизу как раз видно, что число 15 с индексом 5 записалось с начального адреса, а 10 теперь нет вообще.
В данном случае после сброса питания, при инициализации, будет найдена запись с индексом 5 и значением 15 и это значение и индекс будут записаны в кэшируемую копию нашего параметра.
Вот и все, надеюсь в этой статье цель получилось пояснить более детально, спасибо за то, что прочитали до конца.