Хабрахабр

Разработка велоспидометра на базе дисплея от Nokia 3310

Последнее время среди аксессуаров для велосипедов получили широкое распространение так называемые цифровые велоспидометры (велокомпьютеры). Данные устройства способны измерять множество параметров, главные из которых скорость и расстояние. Принцип измерения скорости основывается на подсчёте периода оборота колеса, а расстояние вычисляется на основе измерения количества таких оборотов. Зачастую датчиком оборота колеса служит геркон в совокупности с магнитом на спице колеса. В зависимости от функциональности, цена таких устройств варьируется в больших пределах. Самый дешёвый велоспидометр можно приобрести примерно за 500 р.

При этом я сформулировал ряд собственных требований, которым оно должно удовлетворять. У меня всегда было желание иметь подобное устройство. А также, фиксировать (логировать) измерения на запоминающее устройство для дальнейшей передачи статистических данных на компьютер, их более детального просмотра. Прежде всего, мне очень хотелось, чтобы по мере движения на дисплее пририсовывался график изменения скорости в зависимости от расстояния или времени, накопленный за небольшой период. Было множество вопросов, в частности о применяемой периферии. Дешёвые модели не полностью соответствуют моим требованиям, а за дорогие модели переплачивать не хочется.
Исходя из вышесказанного, я принял решение о создании собственного велоспидометра на базе микроконтроллера ATmega8. Прочитав на него даташит и убедившись в простоте его управления, у меня не оставалось и сомнений, что велоспидометр будет изготовлен в корпусе вышеупомянутого телефона с его же родным дисплеем. Случайно наткнулся на статьи про использование дисплея от некогда популярного мобильного телефона Nokia 3310. Корпус довольно неплохой, да и сам аппарат найти не составляет труда.

Заморачиваться на применении карты памяти SD/MMC я не стал. В качестве ПЗУ для записи статистики измерения я решил поставить классическое ПЗУ 24XX512 (на 512 Кбит), которая управляется по интерфейсу I2C. Они служат для привязки некоторых измеряемых определённых параметров (например, максимальная скорость) к дате и времени, а также, необходимы для записи временных отметок в статистике. Ещё одной немаловажной функцией в устройстве являются часы. В качестве часов я применил отдельную от микроконтроллера микросхему часов реального времени (RTC), которая имеет независимое питание от батарейки и также общается с контроллером по I2C.

Сюда относятся всякие организационные вопросы: количество задействованных кнопок, расположения на дисплее тех или иных элементов, навигация по интерфейсу и так далее. Дополнительные второстепенные требования я реализовывал в функционале устройства на этапе написания программы. Настройка часов осуществляется один раз. В плане навигации я заранее решил не усложнять программу, например, не реализовывать меню настроек, в частности, настройки даты и времени. 768 КГц и батареи питания, которой хватает на длительное время. Часы «тикают» независимо в самой микросхеме RTC благодаря кварцу 32. Через этот же интерфейс предполагалось считывание данных статистики из ПЗУ в компьютер. Настройка даты и времени осуществляется через UART интерфейс велоспидометра, подключающийся в COM-порт компьютера, одним нажатием. Однако, как показала дальнейшая практика, от последнего пришлось отказаться. Для всего этого необходимо написать соответствующую программу для компьютера. И, что ещё существеннее, увеличивался объём программы для контроллера. Во-первых, была проблема реализации приёма данных из контроллера в компьютер на этапе написания компьютерной программы. Для этого необходимо изготовить устройство считывания ПЗУ на основе SIM ридера по одной из известных схем программатора I2C ПЗУ. Гораздо было интереснее разместить ПЗУ (в SMD корпусе SOIC-8) на съёмной площадке, соразмерной с SIM-картой и использовать соответствующий свободный слот мобильного телефона. Как оказалось в дальнейшем, это решение не вызвало лишних неудобств.

Для этого необходима графическая информация о том или ином символе. Ещё один из немаловажных вопросов – вывод символьной (в том числе и цифровой) информации на графический дисплей. Для отображения основного параметра, скорости движения, для хорошей наглядности желательно применять крупный шрифт. Данная информация тесно связана с таким параметром, как размер отображаемого шрифта. Мной было принято решение в качестве самого крупного шрифта использовать шрифт высотой 8 точек. Однако, как будет показано в дальнейшем, подобная графическая информация о десяти цифрах не уместится в память МК, а применение того же внешнего более ёмкого ПЗУ замедлит скорость прорисовки шрифта. FNT» какой-то программы от MS DOS, предварительно разгадав его структуру и сделав дальнейшую обработку. Графическую информацию для этого шрифта я стянул из файла «8X8.

В качестве размера для дополнительного шрифта я выбрал размер 3x5 и самостоятельно нарисовал графику для цифр такого размера. Как в дальнейшем оказалось на практике, этого размера вполне достаточно для наглядности скорости. Этими мелкими цифрами отображаются дополнительные параметры: дата/время, средняя и максимальная скорость, путь.

Каждый элемент массива, размером в 1 байт, обозначает распределение пикселей определённого столбца определённой цифры. Графическая информация обоих шрифтов хранится в определённых двумерных массивах. Для этого же мелкого шрифта, размером 3X5, формальная высота составляет не 5, а 8 точек (округление до одного байта). Для крупного шрифта на каждую цифру выделено 8 столбцов, а для мелкого – 3. Данные факты хорошо отображены на рисунке ниже, где продемонстрировано моделирование графики для первых двух цифр этого шрифта. Это позволяет заранее предусмотреть расположение 5-позиционного шрифта в пределах 8-позиционной зоны в вертикальном направлении одним из 4-х возможных способов. Исходными данными являются расстановки «единичек» в соответствующие поля для требуемой графики. Для моделирования отлично подходит всем известная программа Excel. Из них по формулам рассчитываются значения массивов, вплоть до кода языка Си, который в дальнейшем может быть скопирован в текст программы для микроконтроллера.

Данный дисплей монохромный и его размеры – 84 на 48 пикселей. Теперь речь пойдёт об особенностях управления применяемого дисплея. Переданные байты по SPI интерпретируются в дисплее в двух режимах: байты для вывода на дисплей и байты команд конфигурации. Управление дисплеем от МК осуществляется по SPI интерфейсу. Полный перечень команд приведён в даташите на дисплей. Эти режимы задаются самим МК по определённому пину дисплея (D/C). Сразу отмечу, что применяется горизонтальный режим прорисовки. Часть этих команд используется в моём устройстве, и служат для первоначальной инициализации дисплея при подаче питания на устройство: температурный коэффициент, контрастность, режим последовательной прорисовки (горизонтальный или вертикальный) и т.д. Когда заканчивается строка, адрес позиции переходит на начало следующей строки. Это значит, что при передаче байта в режиме вывода на дисплей, адрес автоматически увеличивается на единицу по строкам вправо. Стоит отметить особенность адресного пространства и интерпретации графики в зависимости от принимаемых дисплеем байтов. Достаточно только предварительно отправить в дисплей специальную команду позиционирования на определённый адрес строки и столбца (начальная позиция), и затем отправлять байты данных последовательно один за другим для вывода графики. Рассматриваемый дисплей разделён в вертикальном направлении на 6 горизонтальных зон по 8 строк в каждой (6*8=48). Замечу, что для монохромной графики один байт содержит информацию сразу о восьми пикселях. Адрес считается не с единицы, с нуля. Каждый столбец каждой зоны и будет соответствовать определённому байту, который отправляется с адресом соответствующего столбца (0…83) и номера зоны (0…5). Из этой особенности следует, на мой взгляд, один из недостатков: невозможность управлять состоянием каждого пикселя по отдельности на аппаратном уровне. Например, если позиционироваться по адресу (34; 2) и отправить байт данных 255 (в бинарном виде «11111111»), то загорятся все 8 пикселей с 16 по 23 по вертикали и в 35-ом столбце по горизонтали. При передаче байта по текущему адресу обновляются все 8 соответствующих пикселей в текущей зоне. Байт является минимальной порцией данных для графики. Поэтому, при необходимости, нужно заранее в МК хранить выводимую информацию в специально отведённом буфере, а для изменения состояния каких-либо пикселей (битов) применять битовые маски для байтов из этого буфера и передавать их в дисплей заново. Дисплей не поддерживает считывание текущей отображаемой графической информации в направление к микроконтроллеру.

Так было предпринято для упрощения кода при написании программы. Моделирование и продумывание расположения той или графической информации на дисплее производилось с учётом вышесказанной особенности. е. И совершенно не случайно размер шрифта рассматривался из разряда 8, 16, 24, т. Графическую информацию, по аналогии с дисплеем, я также разделил на 6 горизонтальных зон. кратным 8. Во второй зоне — абсолютное и текущее значения пути (в километрах с округлением до сотых). В первой зоне мелким шрифтом отображаются абсолютное и текущее (с момента включения устройства) значения оборотов. В четвёртой – максимальная скорость и крупным шрифтом – текущая скорость. В третьей зоне – средняя скорость. В шестой, последней зоне, – дата и время. В пятой зоне отображаются два прогресс бара для индикаций заполнения ПЗУ и количества перезаписи. Поэтому данная информация с применением битовых масок собирается в буфер, содержимое которого затем выводится на дисплей в эту пятую зону. Именно пятая зона является тем самым исключением, когда в вертикальном направлении любого взятого столбца присутствуют пиксели, относящиеся к разной информации. В последней зоне каждый первый (самый младший) бит на всех столбца установлен в «1» для прорисовки линии сепаратора (40-ая строка). Ещё, в 3-5 зонах присутствует информация для прорисовки рамки вокруг отображаемого значения скорости. Для данного моделирования и наглядности адресов я изобразил всё вышесказанное в ячейках Excel.

Всего два окна. Именно таким образом выглядит первое окно отображения. Для неё отведено 5 зон (40 строк) по вертикали и все 84 столбца по горизонтали. Второе окно – вывод графика (гистограммы) движения. Шестая зона с часами для обоих окон одинакова.

Лично мне проще разобраться в даташите, реализовать часть функций самостоятельно, чем разбираться в библиотеке. При программировании мной было принято решение не прибегать к использованию какой-либо библиотеки для работы с данным дисплеем. Недавно, скачав одну из библиотек, я всё же разобрался в её функциональных особенностях. Тем более, в этом нашлись определённые достоинства. Но библиотека использует буфер, размером 84*6 Байт, и данный буфер по таймеру периодически отправляется в дисплей, производя обновление графики. Она является универсальной, с её помощью можно управлять пикселями по отдельности и позиционироваться на реальный адрес пикселя. В моём конкретном случае нет необходимости использования библиотеки, так как при моделировании я заранее позаботился о максимальном разделении информации по отображаемым зонам, поставленным в полное соответствие зонам дисплея. Тем самым, занят таймер и часть памяти МК. Тем самым я ещё раз подчёркиваю: в зависимости от поставленной задачи можно избежать использования каких-либо библиотек. И нет необходимости периодически обновлять информацию на дисплее: информация обновляется только тогда и только в том месте, когда она изменяется (с каждым оборотом колеса, с каждым нажатием какой-либо кнопки и т.д.).

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

Теперь рассмотрим электрическую схему устройства.

Кроме всего перечисленного выше, схема содержит элемент IC5 MAX756, служащий преобразователем питания из 3 в 5 Вольт для надёжного питания от оригинальной батареи мобильно телефона Nokia 3310. Схема велоспидометра относительно простая. На текущий момент времени MAX756 я пока не приобрёл, и вся схема пока питается от выносной батареи «Крона» с применением регулятора LM7805 (не совсем оптимальный вариант). Реализовывать схему под 3-вольтовое питание я не стал за неимением соответствующего МК и периферии. К порту прерывания INT0 МК (пин 32) подключен геркон SF1, являющийся датчиком оборота колеса. Она подключается к разъёму наушников с нижней стороны телефона. К произвольным портам (пины 23, 27, 28) подключены функциональные кнопки S1-S3, совпадающие с кнопками «1», «2», «3» мобильного телефона. Он надёжно подключается с нижней стороны телефона к разъёму зарядки. Это я сделал просто так. К пину 29 сброса МК подключена кнопка S4, совпадающая с верхней торцевой кнопкой включения питания мобильного телефона. К SPI порту контроллера (пины 15-17) подключен дисплей IC2 и разъём для перепрошивки X1. Само же устройство не имеет дежурного режима и включается с подачи питания. На этот же разъём зацеплен UART интерфейс для пользовательского подключения к компьютеру, через который настраиваются дата и время на устройстве (пины 30-31, RX/TX). С разъёмом, который я хотел сделать на основе уже имеющихся «пятачков» на оригинальной плате для сопряжения с ПК (в этом же месте), получилась небольшая загвоздка, и в дальнейшем я перенесу его на другое место. 3 В. Дисплей к контроллеру подключен через делители на резисторах, служащие для снижения напряжения, ибо дисплей работает на напряжении 3. Питание дисплея осуществляется через диоды D1-D3 и резистор R6, которые служат для снижения напряжения с 5 до 3. В дополнение, пины дисплея D/C (данные/команда), SCE (строб) и RES (сброс дисплея) подключены к произвольным портам МК PB0, PB1 и PB2 соответственно (пины 12-14). Кварц Cr1, тактирующий МК, номиналом 4. 3 В, избегая применения линейного регулятора. Просто он мне попался под руку, и я решил применить именно его. 5 МГц выбран случайно, но обдуманно. Контроллер предусматривает возможность управлять подсветками по отдельности, как это предусматривает оригинальная схема мобильного телефона (это было на аппаратном уровне, а не на пользовательском), хотя на практике этого не нужно. К портам МК PD4 и PD5 (пины 2 и 9) подключены транзисторы Q1 и Q2, на которые нагружены светодиоды подсветки дисплея и клавиатуры. На шине подвешены ПЗУ IC3 и часы реального времени (RTC) IC4. Шина I2C подключена к портам PC2-PC3 (пины 25-26) и для простоты реализована программно с применением соответствующей библиотеки (хотя и подключена к портам аппаратного TWI). ПЗУ находится на съёмном разъёме, по аналогии с SIM-картой. Сразу оговорюсь, чтобы не было критики в комментариях: я знаю, что DS1307 не лучшее решение, но на момент разработки схемы я не знал про существование DS3231. Все пассивные компоненты обвесов – согласно даташитам на каждый активный компонент. Дополнительный порт контроллера PC1 (пин 24) служит для приёма импульсов с частотой 1 Гц с RTC, по которым обновляется время на дисплее.

Как уже в начале было сказано, принцип измерения скорости основывается на подсчёте периода оборота колеса, а расстояние вычисляется на основе измерения количества таких оборотов. Рассмотрим математические соображения для расчёта тех или иных параметров. Результат измерения преобразуется в значение скорости путём деления значения периметра колеса на период оборота, и это значение обновляется на дисплее с каждым импульсом (оборотом колеса). Контроллер измеряет время между предыдущим и вновь приходящим импульсом с геркона. Отдельно подсчитывается количество импульсов, преобразующееся затем в значение расстояния. Здесь стоит отметить, что, с точки зрения физики, вычисляется средняя скорость движения велосипеда на участке пути, соответствующем периметру колеса. В ATmega8 имеется 8-битный и 16-битный таймер. Для измерения периода оборота колеса контроллер использует собственный таймер. В моём случае применяется 16-битный таймер, так как 8 бит (256 градаций счёта) категорически недостаточно. От разрядности таймера зависит динамический диапазон измерения. Можно ввести так называемый программный таймер, который позволит измерять большие периоды. Максимальный период измерения (до переполнения таймера) будет соответствовать минимально измеряемой скорости. При применяемом кварце 4. Однако для упрощения программы я этого делать не стал. 000227556 сек. 5 МГц и максимальном значении делителя 1024 в конфигурации таймера имеем: (1/(4500000/1024)) = 0. А максимальный период счёта составит 0. Этому значению соответствует минимальный период счёта. 913 сек. 000227556*65536 = 14. Этого даже и не стоило оговаривать, «запас сверху» просто огромный. Максимально измеряемая скорость, соответствующая минимально измеряемому периоду, составит порядка 30000 км/ч. 26/14. А вот минимально измеряемая скорость, соответствующая максимально измеряемому периоду, составит 2. 54 км/ч. 913/1000*3600 = 0. 26 – периметр велосипедного колеса (в метрах) в моём случае. Здесь 2. Если велосипед будет двигаться со скоростью меньше, чем 0. Меня вполне устраивает данное минимально измеряемое значение. При данном кварце 4. 54 км/ч, велоспидометр будет фиксировать отсутствие движения (и переполнение таймера). Этой скорости также вполне хватает, тем более, UART используется у меня для разовой настройки часов с компьютера (для копирования даты и времени с компьютера в устройство). 5 МГц UART интерфейс отлично работает на скорости 2400 бод с допустимой приемлемой погрешностью. А если брать ниже, то снижается быстродействие устройства в целом. Если брать кварц по частоте выше, минимально измеряемая скорость будет увеличиваться, что будет для меня недопустимо, и появится необходимость использовать программный таймер. Поэтому я решил оставить именно этот кварц.

В нашем случае на диапазон измерения (0. Замечу, что величины период и скорость лежат в обратно пропорциональной зависимости, а таймер микроконтроллера измеряет период дискретно. 913) равномерно нанесены точки в количестве 65535, разделяя его на множество равных интервалов. 000227556…14. Применяя преобразование интервалов из времени в скорость, данная система интервалов преобразуется из равномерной в обратно пропорциональную. И эти точки соответствуют всевозможным измеряемым значениям. Длина этих интервалов возрастает с возрастанием самого значения скорости. Следовательно, диапазон всевозможно измеряемых скоростей разбивается на неравномерные интервалы. На практике будет вполне достаточно за максимально измеряемую скорость велосипеда взять значение 100 км/ч. Учитывая этот факт, огромный «запас сверху», о котором я писал чуть выше, будет не лишним. Посчитаем, чему равна длинна интервала между соседними возможными значениями на скорости в окрестности, например, 90 км/ч. Это хотя бы для того, чтобы не вводить новый разряд (сотни) и не увеличивать ширину отображаемого параметра на дисплее. 06 км/ч. По обратным формулам или подбором несложно подсчитать, что для значения таймера 397 (из 65536 возможных) соответствует измеренная скорость 90. 83 км/ч. А при соседнем значении таймера 398 – 89. 23 км/ч, что уже более чем допустимо. А разность между скоростями – 0. Дисплей отображает значение скорости с точностью до сотых. А на более низких скоростях данная разность будет ещё меньше. Из всего сказанного можно сделать вывод: неравномерностью «сетки» скоростей можно пренебречь, так как вызванная ею погрешность измерения не превосходит допустимую погрешность. Однако на практике обычно хватает округления до целого или до десятых.

При этом, разумеется, расстояние рассчитывается с точностью до периметра колеса, что вполне допустимо. Для подсчёта расстояния достаточно умножить количество импульсов (оборотов) на периметр колеса. Это самое время контроллер считает путём подсчёта количества импульсов, приходящих раз в секунду с RTC. Текущая средняя скорость рассчитывается, как отношение текущего пройденного пути к значению времени с момента включения. Все остальные параметры обновляются с каждым оборотом колеса. Средняя скорость на дисплее обновляется вместе с обновлением времени (раз в секунду).

Первая кнопка служит для переключения режимов (графический режим или режим отображения значений). Теперь по поводу мелких особенностей интерфейса. Также, выводится дата и время достижения этой скорости на место текущей даты и времени. Вторая кнопка – для вывода абсолютной (за всё время) максимальной скорости взамен относительной при её удерживании. Оценить это значение можно по горизонтальному прогресс бару на 38-ой строке дисплея. А ещё, выводится значение текущего адреса ПЗУ на место значения относительного числа оборотов (для контроля). Как будет сказано позже, достаточно записывать первоначально измеряемый параметр (период оборота колеса) с меткой начального времени. На данное ПЗУ, ёмкостью 65536 байт (512 кбит), осуществляется запись измеряемых параметров. Третья кнопка предназначена для управления подсветкой. Все остальные параметры легко рассчитываются компьютерной программой на этапе сканирования ПЗУ. В графическом режиме слева направо прорисовывается гистограмма скорости движения, которая наглядно демонстрирует процесс изменения скорости за небольшой участок расстояния в 84 оборота колеса. В отличие от эскиза экрана выше, я в дальнейшем убрал незначащие нули на второстепенных параметрах для более наглядного их отображения. Если скорость движения превышает 40 км/ч, масштаб изображения сокращается по вертикали в 2 раза во избежание зашкаливания. Значение гистограммы – скорость в масштабе 1 пиксель на 1 км/ч. Доскональные особенности поведения устройства описывать здесь не нужно.

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

При изготовлении платы я использовал программу «SLayout». Печатная плата изготовлена методом ЛУТ по форме оригинальной платы применяемого мобильного телефона. Это необходимо для того, чтобы нарисовать площадки для коннекта дисплея, кнопок и разъёмов в исключительно нужных местах. При этом я заранее на сканере сделал снимок оригинальной платы с двух сторон и подложил изображения в SLayout как шаблон. 5 мм. При изготовлении платы возникала погрешность около 0. Однако эта погрешность сказалась на качестве подстветки: запаянные светодиоды оказались смещены на доли миллиметров и не попали в фокус светорассеивающих оправок. Данная погрешность оказалось приемлемая в плане совмещения контактных площадок и элементов. Ниже на рисунках показан вид печатной платы в SLayout вместе с тремя мелкими печатными платами для ПЗУ в форме SIM карты. Из-за этого яркость подстветки уменьшилась, снизив КПД. Также, приведены сканы оригинальной печатной платы с двух сторон.

Предусмотрен запас по всем имеющимся кнопкам, т.е., есть возможность задействовать любую имеющуюся кнопку. Часть элементов (кнопки, разъёмы) сообщаются между собой тонкими проводными перемычками за неимением возможности проложить дорожки. В верхнем левом углу на плате размещена 3-вольтовая батарея питания RTC. Возможно, удобно будет большую кнопку по центру сделать кнопкой переключения режимов отображения. В отличие от позолоченного оригинала, плата собственного изготовления покрыта обычным припоем. Вообще, все элементы на плате размещены грамотно с согласованием их габаритов с габаритами корпуса. Как показала первоначальная практика, контакт с дисплеем и прочей периферией не теряется.

Кроме этого, программа предусматривает использование собственной энергонезависимой памяти контроллера (EEPROM) для записи и сохранения необходимой информации. Программа для МК получилась довольно большой и занимает значительную часть его памяти. Ниже представлена таблица распределения этой информации по адресам EEPROM.

Address

Size

Data

0

4

n (for S)

4

2

t_min (for v_max)

6

6

Date of t_min

12

2

Address EEPROM

14

1

EEPROM RW Count

128

80

Digits 8X8

208

30

Digits 3X5

Я специально выбрал 32-битный целочисленный тип для данной переменной, поскольку на практике значения пройденного пути сравнительно велики. Первыми четырьмя байтами сохраняется пройденный путь, как количество оборотов колеса. Далее следуют два байта для сохранения абсолютной максимальной скорости. К примеру, целочисленная 16-битная переменная смогла бы сохранить максимум 65536 оборотов (около 148 км), что естественно мало. Переменная занимает два байта, поскольку её значение является результатом измерения 16-битного таймера. По факту сохраняется минимальное время оборота колеса. Данные представлены ровно в том формате, в каком они считываются из микросхемы RTC (исключая номер дня недели). Следующие 6 байт – дата и время достижения вышесказанной максимальной скорости. Это своего рода указатель, который необходим для возможности продолжения записи статистики на ПЗУ после очередного включения устройства. Далее – два байта, сохраняющие значение текущего адреса внешнего ПЗУ. С этой позиции МК продолжит запись. МК должен знать, на какой позиции адресного пространства внешнего ПЗУ он остановился в последний раз. Это следует из размера ПЗУ в 64 кБ. Этому значению отведено 2 байта, так как адресное пространство внешнего ПЗУ 16-битное. Перезаписью считается тот случай, когда вышеописанный указатель достигнет максимального значения и обратится в ноль. Далее – однобайтовая переменная, сохраняющая значение количества перезаписей ПЗУ. Целочисленная однобайтовая переменная способна сохранять максимум 256 значений. При этом вновь поступающая информация на ПЗУ начнёт записываться с самого начала, стирая имеющуюся на ней старую информацию. Далее, после большого резервного пробела EEPROM МК, начиная с адреса 128, хранится графическая информация о цифрах размера 8x8. Напоминаю, что значения указателя адреса ПЗУ и количества перезаписей визуально индицируются двумя прогресс барами на дисплее. И, наконец, начиная с адреса 208, хранятся 30 Байт для графической информации о мелких цифрах 3x5 (по три байта на цифру). Для неё отведено 80 Байт (8 Байт на каждую цифру, как уже говорилось ранее).

Все программы не имеют графического интерфейса и работают из командной строки Windows XP. Кроме основной программы для микроконтроллера, мной были написаны ещё три вспомогательные программы для компьютера, о которых речь пойдёт ниже.

Подключение велоспидометра к компьютеру осуществляется через микросхему MAX232. Первая программа позволяет скопировать дату и время с компьютера в велоспидометр через COM порт. Из этой переменной извлекаются текущие день, месяц, год, номер дня недели, часы, минуты, секунды в десятичном формате. Средствами WinAPI программа получает текущую дату и время в специальную структурную переменную типа SYSTEMTIME. Значение года преобразуется в двузначное число вычитанием из него числа 2000, значения текущего тысячелетия. Все эти числа, за исключением года, не превышают двух десятичных разрядов (меньше 100) и лежат в пределах одного байта. В этом формате двузначное число также занимает объём в один байт. Каждое из таких двузначных десятичных чисел преобразуется в двоично-десятичный формат, характерный для микросхемы RTC. В дальнейшем из этих чисел формируется посылка, размером 13 Байт, согласно заранее определённому мной протоколу. Старшими 4-мя битами кодируется цифра десятков, а младшими – цифра единиц. Потом следуют секунды, минуты, часы, день недели, день, месяц, год. Первые пять байт представляют собой слово «TIME=», согласно стандартной кодировке ASCII. Данная посылка отправляется с компьютера в устройство по COM порту. Последний байт представляет собой символ «#», как символ конца сообщения. Если первые пять байтов «TIME=», а последний «#», посылка считается корректной, и внутри стоящие байты интерпретируются в соответствующем порядке. Программа микроконтроллера принимает посылку и проверяет её на корректность, согласно вышесказанному формату. Отмечу, что эта микросхема поддерживает счёт дней недели от 1 до 7, хотя как таковым календарём, определяющим соответствие даты и дня недели, она не является. Не изменяя эту цепочку байт, контроллер отправляет её в микросхему RTC по шине I2C, конфигурируя её на текущую дату и время. Вывод информации на дисплей о дне недели в своём устройстве я не предусматривал.

Изначально предполагалась, что данное содержимое должно переписаться из ПЗУ в файл-образ с помощью какой-либо известной программы, работающей с известными программаторами МК и ПЗУ (например, «icprog»). Вторая программа предназначена для обработки данных из содержимого внешнего ПЗУ. Схема программатора ПЗУ такой серии, которую я применил в устройстве, представлена на рисунке ниже. Однако, детальнее изучив принцип работы I2C, я сумел реализовать данный функционал и включил его в свою программу.

Через вывод TX осуществляется питание ПЗУ, которое стабилизируется до 5В регулятором 78L05. ПЗУ подключается к COM порту компьютера, который используется не как средство обмена информацией по RS-232 (где достаточно задействовать выводы TX, RX, GND), а как средство произвольного ввода-вывода логических сигналов. Однонаправленная линия тактирования SCL сосредоточена на пине RTS розетки COM порта, а двунаправленная линия данных SDA – на двух пинах: CTS (приём данных) и DTR (передача данных). Управляя с компьютера выводом TX, мы можем включить или выключить микросхему ПЗУ. Резисторы и стабилитроны D1 и D2 служат для ограничения уровня сигнала до TTL, на котором работает ПЗУ.

Данный стандартный программатор я изготовил для моего особого случая, где вместо панельки для ПЗУ применён SIM-ридер от сломанного мобильного телефона.

На базе этого инструментария реализован функционал для работы с I2C, согласно соответствующей спецификации, в подробности которой я вдаваться не буду. Средствами WinAPI программа обращается к пинам COM порта компьютера, устанавливает необходимые на них значения (0 или 1), а также снимает с пина CTS приходящее двоичное значение с ПЗУ. Обработка информации заключается в получении выходных файлов статистики в заранее определённом табличном формате на основе входной информации с ПЗУ. Программа может считывать содержимое ПЗУ в файл-образ (как и штатный программатор), а также обрабатывать такой файл, или обрабатывать информацию с ПЗУ напрямую. Сначала я кратко опишу формат входных данных, который я заранее определил. Каждый такой файл соответствует одной поездке (с момента текущего до момента следующего включения устройства). При начале вращения колеса (при первом импульсе) после таймаута или после включения устройства записывается текущая дата и время в двоично-десятичном формате (как она хранится в регистрах микросхемы RTC). При каждом включении устройства записываются два байта нулей по текущему адресу, который считывается из EEPROM микроконтроллера. Во время вращения колеса при каждом k-ом импульсе (k=2,3,...) записывается время оборота колеса между (k-1)-ым и k-ым импульсом двумя байтами (старшим и младшим). А следом записывается два байта «единиц» 0xFF. Выходной формат является текстовым и представляет собой табулированную таблицу в файлах *.csv, которые открываются в программе Excel по «двойному щелчку» мыши. Очевидно, что данной информации достаточно для привязки текущего (не абсолютного) пройденного пути и скорости к дате и времени. Строки этой таблицы соответствуют оборотам колеса, а значения столбцов приведены ниже.

ADR

Значение адреса ПЗУ

DATE/TIME

Дата и время начала движения

DEC

Значение таймера в десятичном формате

time

Текущее время

t

Время в пути с момента включения

v

Скорость

n

Число оборотов

S

Путь

an

Абсолютное число оборотов (только в пределах текущего ПЗУ)

aS

Абсолютный путь (только в пределах текущего ПЗУ)

n_day

Число оборотов за текущие сутки

S_day

Путь за текущие сутки

v_max

Максимальная скорость за текущую поездку

av_max

Абсолютная максимальная скорость (только в пределах текущего ПЗУ)

v_mid

Средняя скорость за текущую поездку

Также, изображены графики изменения текущей, средней и максимальной скорости различными цветами в одной системе координат. Скриншот содержимого такого файла в Excel представлен на рисунке ниже. На рисунке представлены изменения параметров за первые 730 оборотов. Аргумент (ось X) – значения числа оборотов, как исходные данные. Поэтому, можно сказать, что графики отражают зависимости скоростей от расстояния (с точностью до масштаба по горизонтали), в отличие от традиционной зависимости скорости от времени, на что следует обращать внимание. С данной переменной линейной зависимостью связан пройденный путь (730 оборотов соответствует примерно 1650 м). Но ведь каждому обороту колеса (моменту сближения магнита и геркона) приписан определённый момент времени. Как уже говорилось, данная особенность обусловлена идеологией и принципом измерения скорости по оборотам колеса. Однако, для формальности и удобства, в Excel есть возможность в качестве аргумента для графиков указать массив значений времени в пути или текущего времени. Естественно, данная последовательность временных меток не является равномерной. Но всё равно следует помнить, что реальная зависимость скорости от времени (на равномерных интервалах времени для дискретного случая) выглядела бы по-другому, с переменным масштабом по горизонтали.

Все графики построены в программе Excel известными методами. На рисунке ниже изображена та же зависимость скорости от оборотов, но уже с применением фильтра методом скользящей средней с шириной окна в 11 оборотов.

удалён шум. Сравнивая два графика изменения скорости, очевидно, что в отфильтрованном графике отсутствует высокочастотная компонента, т.е. Если действительно ставить вопрос о фильтрации показаний от шума, то достаточно взять небольшую ширину окна, например, равной трём. Ширина окна скользящего среднего в 11 оборотов (около 25 м пути), на мой взгляд, великовата. к. Этот алгоритм можно заложить в программу велоспидометра, т. Несмотря на простоту этого алгоритма, я не буду вдаваться в подробности его описания, так как эта тема освещается в курсе математики и выходит за рамки данной статьи. он может применяться не только для анализа извлечённых показаний, но и для отображения этих показаний в реальном времени. Как я уже писал, средняя скорость это единственный параметр, который обновляется не с каждым оборотом колеса, а каждую секунду. И здесь ещё одно уточнение по поводу средней скорости. Поэтому, значения показаний на дисплее в реальном времени будут немного отличаться от значений, рассчитываемых в дальнейшем компьютерной программой на этапе сканирования ПЗУ. Это я сделал для того, чтобы на дисплее наблюдалось изменение средней скорости даже при очень медленном движении. На дисплее отображаются действительно абсолютные значения (за всё время существования устройства), а в выходных таблицах – только в пределах текущего считываемого ПЗУ. Также будут отличаться показания абсолютного числа оборотов, абсолютного пути и абсолютной максимальной скорости.

Я работаю с простейшим программатором «STK 200», подключенным к LPT порту компьютера, а точнее, с его аналогом, если его так можно назвать, ибо в простейшем случае программатор вовсе не содержит активных элементов. Третья программа, по своей сути, является той же программой для прошивки микроконтроллера. Программа реализует протокол обмена данными с контроллером ATmega8, согласно его даташиту (стр. Фактически, МК по SPI интерфейсу подключается к определённым пинам LPT порта напрямую и работает, как ведомое устройство. Физический уровень SPI реализован путём управления регистрами LPT порта с применением известной динамической библиотеки «inpout32.dll». 237). Переменной данного типа ставится в соответствие библиотека «inpout32.dll», и в дальнейшем в отдельные переменные извлекаются указатели на функции из данной библиотеки. Библиотека у меня подключается не как к проекту (так как я в «Dev-cpp» избежал создания как такового проекта, создав один простейший «сишный» файл), а с помощью функции LoadLibrary с применением структурного типа HINSTANCE. Обращение к этим функциям происходит по извлечённым заранее указателям. В inpout32.dll имеются только две функции, которые отвечают за ввод и вывод данных. В моём конкретном случае, написанная мной программа работает с EEPROM областью контроллера и предназначена для считывания, резервирования, записи, корректировки и восстановления из резервной копии хранящихся в ней данных, которые я расписал ранее. Управление пинами LPT порта по отдельности осуществляется при помощи битовых масок. В таких случаях, для реализации многофункциональности программы применяются функции «switch-case» и текстовый пользовательский диалог, например, «введите ‘1’ для операции №1, …, введите ‘0’ для выхода из программы». Как и все остальные программы, программа работает из командной строки. В дополнение к сказанному, программа может выводить полный дамп EEPROM контроллера в 512 Байт на экран. Данные отображаются в различных удобных для меня форматах. В случае с мелким шрифтом, размером 3X5, программа берёт информацию из текстового файла «Fonts 3X5.txt», который находится с ней в одном каталоге. Также, программа умеет записывать в память контроллера графическую информацию о применяемых шрифтах. При желании его можно легко отредактировать в текстовом редакторе, изменив, таким образом, графику данного шрифта. Файл содержит табулированную таблицу из 30 байтов (3 на 10), записанных в 16-ричном формате. Единственное, может только потребоваться его вертикальный сдвиг, так как имеется запас пространства по высоте в 8 пикселей, а шрифт имеет высоту, равную 5. Как уже говорилось, этот мелкий шрифт настолько простой, что менять его графику не имеет смысла. Графическая информация о данном шрифте представлена не в текстовом файле в виде таблицы байтов, а в графических наглядных файлах BMP. В случае с крупным шрифтом, размером 8X8, которым отображается текущая скорость, я предусмотрел функционал куда интереснее. Его параметры – размер 8X8, монохромный с чёрно-белой палитрой. Каждой цифре соответствует один такой файл. Ниже показан скриншот известного графического редактора «MS Paint» с открытым в нём файлом «8.bmp».

На этапе построчного горизонтального чтения снизу вверх (именно так и организована структура BMP файла), программа преобразует информацию в вертикальный формат, свойственный применяемому дисплею. Эмпирическим путём я изучил структуру монохромных BMP файлов, полученных из MS Paint», и на этой основе мне удалось научиться читать каждый пиксель монохромной BMP картинки (исключая использование структур и вспомогательных библиотек). Ниже я покажу этот участок кода для i-ой цифры, обратив внимание на простоту процесса. Эта операция осуществляется в один проход, где применяются битовые маски и накопление значения переменных.

for(k=0; k<8; k++){ fnt[i][k] = 0;
}
for(j=0; j<8; j++) }
}

В дальнейшем, каждый k-ый элемент этого массива (k=0…7) для i-ой цифры (i=0…9) будет нести графическую информацию о каждом соответствующем столбце каждой соответствующей цифры. В первом цикле происходит инициализация элементов массива fnt нулями. Оператором fseek мы позиционируемся на байт по смещению 62+4*j заранее определённого BMP файла f. Следующий цикл – пробег по строкам картинки BMP файла. В промежуточную переменную byte мы получаем значение байта по вышесказанному смещению. Специфика формулы, по которой рассчитывается смещение в зависимости от номера строки j, обусловлена структурой BMP файла. Оператором ‘~’ происходит побитовая инверсия байта, что приводит к цветовой инверсии каждого пикселя. Этот байт хранит информацию обо всех восьми пикселях монохромной картинки в текущей строке j. В применяемом же дисплее – всё наоборот. Это связано с тем, что чёрный пиксель в палитре монохромного BMP файла соответствует логическому «0», а белый – «1». Функция pow2 – возведение двойки в неотрицательную целочисленную степень, написанная самостоятельно. Во вложенном цикле происходит побитовый анализ байта и в тоже время накопление информации в выходной массив fnt. Вместо этой функции можно применить более эффективный оператор побитового сдвига «<<», но на момент написания этой программы я им не пользовался.

Эти варианты реализованы с помощью директорий (папок) с именем вида «v1», «v2», «v3» и т. Кроме этого, программа предусматривает возможность записать в память МК одну из нескольких графических вариантов этого шрифта на мой выбор. А уже в этих папках лежат необходимые BMP файлы. д., которые располагаются в папке «Fonts 8X8» в одном каталоге с программой. У меня имеется три варианта шрифта. Благодаря вышеописанному функционалу, имеется возможность в графическом редакторе поправить или нарисовать цифры с «чистого листа», сохранив и распределив их по директориям. Второй – как и оригинал, но с зачёркнутым нулём и видоизменённой единицей (без нижнего подчёркивания). Первый вариант – оригинальный. Третий – шрифт с прямоугольной окантовкой.

На фотографиях ниже изображены: изготовленная печатная плата устройства с задней стороны; устройство на столе с подключенным к нему питанием (с неокончательной версией прошивки); устройство в работе, установленное на велосипед, с отображающимся на нём графиком изменения скорости.

Прежде всего – плохой контакт дисплея с контактными площадками печатной платы. В процессе эксплуатации устройства всё-таки были выявлены небольшие недостатки, связанные с особенностями изготовления. В моём случае они просто лужёные. В оригинальном мобильном телефоне контакты на плате позолоченные, и окисление отсутствует.

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

Для этого я предварительно набросал эскизы корпуса в программе SPlan, почти полностью не владея тематикой чертежей, САПР и т.д. Корпус для устройства я изготовил из куска оргстекла, толщиной 17 мм, на фрезерном станке ЧПУ.

На их основании пишется программа на станок ЧПУ, принимая во внимание общие принципы и последовательности фрезеровки. Данные наброски нужны для общего представления и получения координат опорных точек. Программу ЧПУ я писал вручную в Excel, применяя функции автозаполнения на повторяющиеся операции.

Схему устройства я также немного подкорректировал, она представлена на рисунке ниже.

Также перерисованы разъёмы, и отсутствуют другие элементы, которые не понадобились в обновлённой версии конструкции. Вместо ненужной подсветки стоит для красоты один светодиод, который вспыхивает с каждым оборотом колеса. 433619 МГц, незначительно подкорректировав некоторые константы в исходном коде собственной программы. дальнейшем я нашёл и поставил кварц 4. Было также сделано ещё несколько незначительных изменений в программе.

Устройство питается от АКБ, которая стоит на борту велосипеда. Фотография готового изделия представлена ниже. От неё же запитано освещение на случай поездок в тёмное время суток.

Единственный недостаток — применение не очень качественного чипа RTC: зимой при низких температурах время заметно спешит, приходится раз в месяц корректировать. Именно в таком исполнении устройство заработало полностью без каких-либо сбоев.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть