Я уже писал раньше на эту тему. Я сделал ооочень маленькую плату, для управления навигационными огнями коптера с пульта, которую легко повторить. В этой статье вы найдете все исходники проекта, а также инструкции по сборке и программированию.
Аппаратная часть
Сразу покажу как это выглядит в итоге:
Плата предельно простая, односторонняя, дешевая и маленькая (всего 18х13мм). Для ее сборки потребуются следующие компоненты:
Плата подключается одной стороной к приемнику (потребуется аппа с раздельными каналами), а другой стороной к подсветке. Все плюсы соединяются вместе, а минусы соединяются попарно и подводятся к контактам платы. Также наобходимо подключить к плате минус аккумулятора. Вот как это выгляит, если для подсветки используется обычная светодиодная лента:
Выходы платы рассчитаны на ток по 3А инапряжение по 50В на канал.
Программирование
На данный момент наибольшей популярностью пользуется проргамма в которой релизовано четыре режима, задающихся с пульта (hex-файл в конце):
Вот исходный код программы:
/*
Flasher
PB2 - PPM-signal
PB1, PB4 - out
CKSEL0=on; SUT0=on; CKDIV8=on; SPIEN=on (default fuses)
*/
#include <avr/io.h>
#define F_CPU 1200000UL // 1.2 MHz
#include <util/delay.h>
uint8_t mode = 0;
void always() {
PORTB |= ((1<<1)|(1<<4));
}
void flash() {
PORTB |= ((1<<1)|(1<<4));
_delay_ms(100);
PORTB &= ~((1<<1)|(1<<4));
_delay_ms(700);
}
void doubleflash() {
PORTB |= ((1<<1)|(1<<4));
_delay_ms(100);
PORTB &= ~((1<<1)|(1<<4));
_delay_ms(100);
PORTB |= ((1<<1)|(1<<4));
_delay_ms(100);
PORTB &= ~((1<<1)|(1<<4));
_delay_ms(700);
}
void change() {
PORTB |= (1<<1);
PORTB &= ~(1<<4);
_delay_ms(500);
PORTB |= (1<<4);
PORTB &= ~(1<<1);
_delay_ms(500);
}
void off() {
PORTB &= ~(1<<4);
PORTB &= ~(1<<1);
}
void siren() {
PORTB |= (1<<1); _delay_ms(50);
PORTB &= ~(1<<1); _delay_ms(50);
PORTB |= (1<<1); _delay_ms(50);
PORTB &= ~(1<<1); _delay_ms(50);
PORTB |= (1<<1); _delay_ms(50);
PORTB &= ~(1<<1); _delay_ms(50);
PORTB |= (1<<4); _delay_ms(50);
PORTB &= ~(1<<4); _delay_ms(50);
PORTB |= (1<<4); _delay_ms(50);
PORTB &= ~(1<<4); _delay_ms(50);
PORTB |= (1<<4); _delay_ms(50);
PORTB &= ~(1<<4); _delay_ms(50);
}
void HardwareInit() {
PORTB |= (1<<2);
DDRB &= (1<<2);
PORTB &= ~((1<<1)|(1<<4));
DDRB |= ((1<<1)|(1<<4));
}
int main(void)
{
HardwareInit();
while(1)
{
mode = 0;
while ( (PINB&(1<<2)) == (1<<2) ) {};
while ( (PINB&(1<<2)) == 0b00000000 ) {};
_delay_us(1200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
_delay_us(200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
_delay_us(200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
if ( mode == 0 ) off();
if ( mode == 1 ) doubleflash();
if ( mode == 2 ) siren();
if ( mode == 3 ) always();
}
}
Как вы знаете - вся программа начинается с функции main. В ней сначала происходит определение длительности сигнала, а затем, в зависимости от результата, запуск того или ионого режима. То есть, например, строка if ( mode == 1 ) doubleflash(); вызывает функцию, которая делает двойную вспышку.
Вы можете легко поменять порядок режимов, выбрать другие или вообще прописать свои. Из готовых функций есть:
Чтобы скомпелировать вашу версию софта достаточно поставить Atmel Studio с официального сайта (бесплатно, без SMS и регистрации) и обзавестить программатором. Я рекомендую для таких целей иметь под рукой USBasp, либо программатор из Arduino.
Видео работы
На данный момент наибольшей популярностью пользуется набор режимов, который предложил автор это видео:
Сам я для себя тзначально делал немного под-другому, но в итоге тоже пришел к выводу, что нужно иметь возможность полностью отключить навигационные огни.
Небольшой отступление
С момента прошлой публикации, мне стали часто писать на почту с просьбой продать плату. Сначала я отнекивался и некоторые даже уходили и делали сами, что для меня было очень лестно, но периодически я все-таки запускал изготовление в ручную десятка-другого этих плат.
С недавних пор мне это дело надоело и я (как вы успели заметить) заказал производсвто этих платы в Китае. Сейчас, те кто не хотят, или не могут по каким-то причинам сделать самостоятельно могут купить эту плату готовой здесь.
Если захотите приобрести готовую - то в комментарии к заказу сделайте пометку PARKFLYER и я сделаю скидку 20%.
Файлы для скачивания
Печатная плата в Sprint Layout
Hex-файл
Мои остальные статьи о коптеростроительстве
UPD:
Друзья, обратите внимание, что после 8го марта 2016 скидка по промокоду PARKFLYER будет снижена до 10%.
Сразу покажу как это выглядит в итоге:
Плата предельно простая, односторонняя, дешевая и маленькая (всего 18х13мм). Для ее сборки потребуются следующие компоненты:
- Микроконтроллер Attiny13A в DIP8 - 1шт
- Транзисторная сборка IRF7103 в корпусе SO8 - 1шт
- Резистор 0805-1кОм - 1шт
- PLS-контакты - 6 штырьков
- Колодка под корпус DIP8
Плата подключается одной стороной к приемнику (потребуется аппа с раздельными каналами), а другой стороной к подсветке. Все плюсы соединяются вместе, а минусы соединяются попарно и подводятся к контактам платы. Также наобходимо подключить к плате минус аккумулятора. Вот как это выгляит, если для подсветки используется обычная светодиодная лента:
Выходы платы рассчитаны на ток по 3А инапряжение по 50В на канал.
Программирование
На данный момент наибольшей популярностью пользуется проргамма в которой релизовано четыре режима, задающихся с пульта (hex-файл в конце):
- огни выключены
- двойные вспышки
- попеременное мерцание (типа полицейской сирены)
- все огни включены
Вот исходный код программы:
/*
Flasher
PB2 - PPM-signal
PB1, PB4 - out
CKSEL0=on; SUT0=on; CKDIV8=on; SPIEN=on (default fuses)
*/
#include <avr/io.h>
#define F_CPU 1200000UL // 1.2 MHz
#include <util/delay.h>
uint8_t mode = 0;
void always() {
PORTB |= ((1<<1)|(1<<4));
}
void flash() {
PORTB |= ((1<<1)|(1<<4));
_delay_ms(100);
PORTB &= ~((1<<1)|(1<<4));
_delay_ms(700);
}
void doubleflash() {
PORTB |= ((1<<1)|(1<<4));
_delay_ms(100);
PORTB &= ~((1<<1)|(1<<4));
_delay_ms(100);
PORTB |= ((1<<1)|(1<<4));
_delay_ms(100);
PORTB &= ~((1<<1)|(1<<4));
_delay_ms(700);
}
void change() {
PORTB |= (1<<1);
PORTB &= ~(1<<4);
_delay_ms(500);
PORTB |= (1<<4);
PORTB &= ~(1<<1);
_delay_ms(500);
}
void off() {
PORTB &= ~(1<<4);
PORTB &= ~(1<<1);
}
void siren() {
PORTB |= (1<<1); _delay_ms(50);
PORTB &= ~(1<<1); _delay_ms(50);
PORTB |= (1<<1); _delay_ms(50);
PORTB &= ~(1<<1); _delay_ms(50);
PORTB |= (1<<1); _delay_ms(50);
PORTB &= ~(1<<1); _delay_ms(50);
PORTB |= (1<<4); _delay_ms(50);
PORTB &= ~(1<<4); _delay_ms(50);
PORTB |= (1<<4); _delay_ms(50);
PORTB &= ~(1<<4); _delay_ms(50);
PORTB |= (1<<4); _delay_ms(50);
PORTB &= ~(1<<4); _delay_ms(50);
}
void HardwareInit() {
PORTB |= (1<<2);
DDRB &= (1<<2);
PORTB &= ~((1<<1)|(1<<4));
DDRB |= ((1<<1)|(1<<4));
}
int main(void)
{
HardwareInit();
while(1)
{
mode = 0;
while ( (PINB&(1<<2)) == (1<<2) ) {};
while ( (PINB&(1<<2)) == 0b00000000 ) {};
_delay_us(1200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
_delay_us(200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
_delay_us(200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
if ( mode == 0 ) off();
if ( mode == 1 ) doubleflash();
if ( mode == 2 ) siren();
if ( mode == 3 ) always();
}
}
Как вы знаете - вся программа начинается с функции main. В ней сначала происходит определение длительности сигнала, а затем, в зависимости от результата, запуск того или ионого режима. То есть, например, строка if ( mode == 1 ) doubleflash(); вызывает функцию, которая делает двойную вспышку.
Вы можете легко поменять порядок режимов, выбрать другие или вообще прописать свои. Из готовых функций есть:
- always() - всегда включено
- flash() - однокраная вспышка
- doubleflash() - двойная вспышка
- change() - попеременное включение
- off() - полностью выключено
- siren() - мерцание сирены
Чтобы скомпелировать вашу версию софта достаточно поставить Atmel Studio с официального сайта (бесплатно, без SMS и регистрации) и обзавестить программатором. Я рекомендую для таких целей иметь под рукой USBasp, либо программатор из Arduino.
Видео работы
На данный момент наибольшей популярностью пользуется набор режимов, который предложил автор это видео:
Сам я для себя тзначально делал немного под-другому, но в итоге тоже пришел к выводу, что нужно иметь возможность полностью отключить навигационные огни.
Небольшой отступление
С момента прошлой публикации, мне стали часто писать на почту с просьбой продать плату. Сначала я отнекивался и некоторые даже уходили и делали сами, что для меня было очень лестно, но периодически я все-таки запускал изготовление в ручную десятка-другого этих плат.
С недавних пор мне это дело надоело и я (как вы успели заметить) заказал производсвто этих платы в Китае. Сейчас, те кто не хотят, или не могут по каким-то причинам сделать самостоятельно могут купить эту плату готовой здесь.
Если захотите приобрести готовую - то в комментарии к заказу сделайте пометку PARKFLYER и я сделаю скидку 20%.
Файлы для скачивания
Печатная плата в Sprint Layout
Hex-файл
Мои остальные статьи о коптеростроительстве
UPD:
Друзья, обратите внимание, что после 8го марта 2016 скидка по промокоду PARKFLYER будет снижена до 10%.
Видел на одном сайте, парни делали БАНО из какого-то полевика с материнки компа и АТТИНИ8 Но у нас и эту микросхему только под заказ купить можно (
И самое главное... у меня управление по i-BUS, я так понял, что с пульта управлять не получится, а можно без управления, просто один режим моргания запустить? Я понимаю, что для ардуино можно простенький скетч написать типа стандартного "светодиод" на ногу 13, но это надо знать язык программирования + знать какой и как использовать транзистор в качестве ключа, а я нахватался только вершков и терминов (
А для самолётов ничего не планируется?
БАНО, строб, проблесковые, фары и тд....
Было бы тоже неплохо.
Чтобы отдельно можно было включать. Допустим есть бано, строб, проблесковый и фары.
Режимы работы:
Бано (красный, зелёный) - горят постоянно.
Фары(белый) - горит постоянно.
Строб (белый )- двойная вспышка, пауза ....
Проблесковый (красный) - моргающий.
Идеальный вариант когда всё это добро может включатся в разных вариациах.
Задачка конечно ещё та.
Всегда же хочется оставить возможность включать и выключать свет.
В каментах к основной статье есть мод под ваш контроллер, позволяющий навигационными огнями сигнализировать о разряде аккумулятора.
подключить?
А по прошивке Вы ждете такой : ̅ ̅ ̅ ̅ |_| ̅ ̅ ̅ ̅ .
Или я что-то не так понял?
Смотрите, нчало бесконечного цикла попадает на произвольный момент в этом сигнале. Сначала идет цикл while ( (PINB&(1<<2)) == (1<<2) ) {}; Если начало программы совпало с высоким уровнем, то цикл останавливает программу пока не придет низкий уровень. Либо (если попало на момент низкого уровня) он просто не заходит ни разу в тело цикла.
Далее, циклом while ( (PINB&(1<<2)) == 0b00000000 ) {}; программа останавливается на все время, пока на входе логический ноль.
В итоге, после этих двух действий, программа убеждается, что "нащупала" именно фронт импульса. А дальше уже просто по пороговым значениям проверяется длительность импульса. То есть я привязываюсь именно к длительности активной части периода.
На самом деле это все довольно хардкорный способ измерения длительности импульсов, работающий только в этих конкретных условиях. Со временем я планирую перевести эту часть кода на таймер, а в мэйне оставить только отрабьотку мерцаний.
while ( (PINB&(1<<2)) == 0b00000000 )
_delay_us(1200);
Отсюда и вопрос возник.