А почему вы используете С++ вместо языка программирования?
© Баш.
Данная тема создана с одной единственной целью – собрать воедино невероятно рассеянную и разрозненную инфу в форме, доступной для понимания «с нуля».
Вы используете велофары? Они питаются от линейника? На линейнике или любом другом драйвере стоит контроллер ATTiny13а? Тогда мы пришли к вам и вынесем вам остаток мозга .
Цель стояла очень простая - переделать под себя режимы драйверов, убрать память режимов и, самое сложное, заставить всё это работать от тактовых кнопок, включая адский строб для распугивания окружающих по долгому нажатию. Реализовано всё.
Базовая информация была почерпнута из этих тем:
http://flashlight-wiki.com/AVR_Drivers
http://budgetlightforum.com/node/799
Однако, их содержимое вообще ни разу не отвечает на вопросы новичков. Сама кастомная прошивка там освещена достаточно хорошо, много написано по её тексту, много по заливке в чип, но ничего про компиляцию. А с ней-то у новичка (типа меня, ага ) и будет основной затык. К тому же на всех форумах при любых вопросах относительно команд чипу посылают в датащит, а в нём реально чёрт ногу сломит, т.к. он писался для людей глубоко в теме.
Ну что, приступим? Для наших увлекательных опытов нам понадобятся следующие девайсы:
программатор (любой вариант USBAsp)
клипса (опять же – любая, можно и без неё – подпаиваясь к самому чипу, но это неудобно)
драйвер
паяльник
прямые руки
архив с исходной кастомной прошивкой
WinAVR.
Пункт 1. Софтовый, в котором мы долго втыкаем в код, мучаем WinAVR и пытаемся заставить прошивку компилироваться.
Начнём мы с софта. Необходимо скачать и установить WinAVR. Если вы – профессионал программирования и всякие makefilы вам не чужды – можете не читать.
WinAVR даст нам среду для компиляции. При этом, открыв готовый код в ихнем Programmers Notepad и попытавшись его там скомпилить, ничего там не скомпилится. Вылезет огромное количество ошибок (хотя сам код – правильный). А после удачной компиляции и заливки в чип оно не один хрен не будет работать. Потому что надо долго и нудно трахаться с мейкфайлами и прочей лабудой. Мы так делать не будем .
Итак, WinAVR стоит. Распаковываем архив с прошивкой на С:. Нас интересует только один файл – driver.c. Это – оно. Автор сделал невероятно сложную и богатую на функционал прошивку с несколькими вариантами компиляции. Можете попытаться в ней разобраться, ничего сверхъестественного там нет (и большую часть кода, кстати, занимает работа с EEPROM – записью режимов в память). Открываем CMD, заходим в папку с прошивкой. Дальше, если мы собираемся компилить сей авторский продукт, мы заходим в ту папку, какой вариант функционала нам нужен. Fixed Modes для простых High-Med-Low-strobe-sos, Programmable для программируемых режимов, simple для High-Med-Low, Default для компиляции кода в driver.c без каких либо условий. Что там написано – то и скомпилится.
Копируем в сторону driver.с, вместо него с тем же именем создаём пустой файл и пихаем туда тот самый код, над которым я бился месяц...
Дальний свет. Версия 3. Off-High---Strobe. При коротком нажатии происходит включение/отключение. При нажатии дольше 150 мс и удержании кнопки начинается строб сериями по 7 пыхов с паузой в 300 мс между сериями. Если кнопку отпустить, фара сразу возвращается в режим, который был до нажатия с удерживанием.
Код:
#include<avr/io.h>
#include<util/delay.h>
#include <avr/power.h>
int t; // объявляем счётчик
t=0; // обнуляем его
int p; // переменная для цикла строба
int mode[2]={0,255}; // массив режимов, мощность выставляется от 0 (выкл) до 255 (максимум).
void strobe() // функция строба
{
for(p = 0; p < 8; ++p) // основной цикл из 7ми миганий
{
if (!(PINB & _BV(PB4))) // если кнопка нажата
{
OCR0B = 255; // максимум
_delay_ms(20); // пауза
OCR0B = 0; // минимум
_delay_ms(50); // пауза
}
else break; // если кнопка отпущена
// прерываем цикл
}
for(p = 0; p < 31; ++p){ // пауза между порциями строба оформлена в виде цикла для выхода из него в течение 10мс, а не 300, если кнопка будет отпущена в этот момент
if (!(PINB & _BV(PB4))) _delay_ms(10); // если кнопка нажата - ждём 10мс
else {
modesw();
break; // в противном случае меняем режим и выходим из цикла
}
}
}
void modesw() // функция переключения режимов
{
t=t+1; // прибавляем счётчик
if (t==sizeof(mode)/sizeof(int)) t=0; // если он стал больше номера последнего режима в массиве, возвращаем его на 0
OCR0B=mode[t]; // выставляем режим из массива по счётчику
}
int main(void) // основная программа
{
PORTB |= _BV(PB4); // пин PB4 (третий) будет опрашиваться
DDRB |= _BV(PB1); // пин PB1 (шестой) будет использоваться для вывода ШИМ (на нём через 7135е висит диод)
TCCR0A = 0x21; // корректируем ШИМ по фазе (взято из исходного драйвера)
TCCR0B = 0x01; // множитель частоты ШИМ ((1 => 1, 2 => 8, 3 => 64...)
OCR0B=mode[t]; // ставим начальный режим первым элементом из массива
while(1) // основной непрерывный цикл
{
if (!(PINB & _BV(PB4))) _delay_ms(75); // если пин PB4 замкнут на землю ждём для пропуска дребезга контактов 50мс
if (!(PINB & _BV(PB4))) // если он всё ещё замкнут
{
modesw(); // меняем режим
_delay_ms(150); // делаем паузу перед возможным стробом, чтобы успеть отпустить кнопку без мигания при штатном переключении
while(!(PINB & _BV(PB4))) strobe(); // пока кнопка нажата - стробим
}
}
return 0; // Всё :).
}
Ближний с плавной регулировкой. При коротком нажатии происходит переключение режимов Off-High-Preset. При первом подключении аккумулятора 3й режим - максимум. При нажатии дольше 150 мс и удержании кнопки фара проходит от максимума к минимуму и обратно, пока кнопка не будет отпущена. Яркость фары в момент отпускания кнопки записывается в третий режим. Там она остаётся до следующей регулировки или до отключения аккумулятора.
Код:
#include<avr/io.h>
#include<util/delay.h>
#include <avr/power.h>
int t; // объявляем счётчик
t=0; // обнуляем его
int p; // переменная для плавной регулировки
int s; // флаг для направления плавной регулировки
int mode[3]={0,255,255}; // массив режимов, мощность выставляется от 0 (выкл) до 255 (максимум).
void modesw() // функция переключения режимов
{
t=t+1; // прибавляем счётчик
if (t==sizeof(mode)/sizeof(int)) t=0; // если он стал больше номера последнего режима в массиве, возвращаем его на 0
OCR0B=mode[t]; // выставляем режим из массива по счётчику
}
p=255; // первый раз плавная регулировка начнётся с максимума
s=1; // и пойдёт к минимуму
int main(void) // основная программа
{
PORTB |= _BV(PB4); // пин PB4 (третий) будет опрашиваться
DDRB |= _BV(PB1); // пин PB1 (шестой) будет использоваться для вывода ШИМ (на нём через 7135е висит диод)
TCCR0A = 0x21; // корректируем ШИМ по фазе (взято из исходного драйвера)
TCCR0B = 0x01; // множитель частоты ШИМ ((1 => 1, 2 => 8, 3 => 64...)
OCR0B=mode[t]; // ставим начальный режим первым элементом из массива
while(1) // основной непрерывный цикл
{
if (!(PINB & _BV(PB4))) // если пин PB4 замкнут на землю
{
_delay_ms(50); // ждём для пропуска дребезга контактов 50мс
if (!(PINB & _BV(PB4))) // если он всё ещё замкнут
{
modesw(); // меняем режим
_delay_ms(150); // делаем паузу перед регулировкой, чтобы успеть отпустить кнопку при штатном переключении
while(!(PINB & _BV(PB4))) // пока кнопка нажата
{
_delay_ms(10); // задержка, выставляющая скорость регулировки
if (s==1){ // идём от максимума к минимуму
p=p-1; // отнимаем от переменной
if (p==1){ // если дошли до минимума
s=0; // пойдём в обратную сторону
_delay_ms(150); // немного подождём
}
OCR0B=p; // ставим режим по переменной
mode[2]=p; // и пишем её значение в третий элемент массива режимов
}
else{ // идём от минимума к максимуму
p=p+1; // прибавляем к переменной
if (p==255){ // если дошли до максимума
s=1; // снова меняем направление движения
_delay_ms(150); // немного ждём в максимуме
}
OCR0B=p; // ставим режим по переменной
mode[2]=p; // и пишем её значение в третий элемент массива режимов
}
}
}
}
}
return 0; // Всё :).
}
Упрощённый ближний Off-High, с переходом в Low по долгому нажатию. Сорри, но уже без комментариев в коде.
Код:
#include<avr/io.h>
#include<util/delay.h>
#include <avr/power.h>
int t;
t=0;
int mode[3]={0,255,50};
void modesw(){
t=t+1;
if (t==sizeof(mode)/sizeof(int)-1) t=0;
OCR0B=mode[t];
}
int main(void)
{
PORTB |= _BV(PB4);
DDRB |= _BV(PB1);
TCCR0A = 0x21;
TCCR0B = 0x01;
OCR0B=mode[t];
while(1)
{
if (!(PINB & _BV(PB4)))
{
_delay_ms(50);
if (!(PINB & _BV(PB4)))
{
modesw();
_delay_ms(300);
if (!(PINB & _BV(PB4))){
OCR0B=mode[2];
t=1;
while (!(PINB & _BV(PB4))){
}
} }
}
}
return 0;
}
Заходим в CMD в папку Default и пишем make all. Драйвер должен после этого скомпилиться без проблем. Не закрываем CMD.
Пункт 2. Железячный, в котором мы ругаемся на кривую клипсу и пытаемся запугать программатор, чтобы он увидел чип.
Программатор USBAsp – чуть ли не самый дешёвый на рынке. Их существует великое множество вариантов, потому что вся его разработка была оупенсорсовая. У меня, например, вот такой .
Берём клипсу. Предупреждаю сразу, эта клипса – дерьмо и надолго её не хватит (вот, что с моей стало ), но она самая дешёвая (причём резко дешевле любых аналогов, особенно от 3М)… Разбираем разъём, идущий к программатору, отрываем от общего шлейфа 8й провод (считаем от красного) и переставляем его в 9е гнездо. 798px-Ribbon.jpgЗакрываем разъём, вставляем его в программатор. Провод, кстати, рекомендуют укоротить. При длине свыше 15см возможны помехи и нестабильная работа. Реорганизуем провода на клипсе по следующей схеме:
Программатор_______Клипса
1__________________5
2__________________8
4__________________4
5__________________1
7__________________7
9__________________6
Остальные просто не подключаем - они не нужны.
Номера контактов на клипсе смотрим по чипу Ak47pins.jpg.
Лучше всего шить на уже готовой и собранной фаре, так как может понадобиться запитать драйвер от аккума в процессе перепрошивки.
Втыкаем программатор в USB, подсовываем драйвера, цепляем клипсу к чипу (не путая верх и низ), снова открываем CMD и пишем
Код:
avrdude -p t13 -c usbasp -n
Если программатор выдал следующее
Код:
avrdude: warning: cannot set sck period. please check for usbasp firmware update
.
avrdude: error: programm enable: target doesn't answer. 1
avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.
avrdude done. Thank you.
Проверяем контакты – что-то где-то не контачит.
Если программатор выдал следующее
Код:
avrdude: warning: cannot set sck period. please check for usbasp firmware update
.
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.03s
avrdude: Device signature = 0x1e9007
avrdude: current erase-rewrite cycle count is 808793655 (if being tracked)
avrdude: safemode: Fuses OK
avrdude done. Thank you.
Нам невероятно повезло и всё работает. Переходим к п. 3
Если программатор ругается на device signature 0x000012, то это значит, что он слишком резвый и надо снизить его частоту. Если у вас на нём есть джампер J3 – его надо замкнуть. Если его нету (как у меня - китайцы не распаяли) – припаиваем проводок к земле и 25й ноге чипа (вот так , ноги всегда считаются от точки на чипе против часовой стрелки).
Если теперь программатор ругается на device signature 0x000000,
Код:
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.13s
avrdude: Device signature = 0x000000
avrdude: Yikes! Invalid device signature.
Double check connections and try again, or use -F to override
this check.
то это значит, что ему помогло снижение частоты, но не хватает сил запитать чип. В этом случае необходимо подключить (припаять, если с нуля делаем) к драйверу аккум.
Важное замечание. Не пытайтесь залить прошивку, если AVRDude ругается на несоответствие Device signature. Либо ничего не выйдет, либо угробите чип. Прошивать можно только если Device signature отображается как 0x1e9007! 99% проблем с левым Device Signature - результат плохого контакта или замыкания ног.
Пункт 3. Копируем в CMD следующую строку (в консоли должна быть открыта папка Default).
Код:
avrdude -p t13 -c usbasp -u -Uflash:w:BLF-VLD.hex:a -Ueeprom:w:BLF-VLD.eep:a -Ulfuse:w:0x79:m -Uhfuse:w:0xed:m
Если прошивание идёт на готовой фаре, она будет прикольно моргать в процессе. По окончании прошивки, в случае использования моего кода, фара просто погаснет. Не пугаемся – всё ОК.
Припаиваем провода от тактовой кнопки к 3й и 4й ногам чипа. Так как китайцы – молодцы, нам не надо подпаиваться непосредственно к самим ногам. 4я нога – земля, проводок припаивается туда же, куда и минус от аккума. 3я нога выведена на вторую справа звёздочку .
Проверяем. Если при нажатии кнопки фара включается и выключается – всё прошло замечательно.
А это - кнопа .
На веле теперь такая же, только феншуйно-красная .