Arduino и подсветка лучей коптера с сигнализацией активации фейлсейва

Решил написать статейку, возможно кому то пригодится.

Летал все время со статичной подсветкой, читаемость положения коптера в разы улучшается, но! иногда сильно засвечивает камеру и потребовалась возможность управлять подсветкой с пульта. Решено было использовать arduino nano, так как имеет небольшие габариты и порт USB для быстрой отладки и настройки. Началось все с гугления темы про “чтение PWM сигнала с RC приемника” (и прочие запросы в таком духе) конечно же ничего годного не нашел, предлагали всякие бредовые решения пока не наткнулся на использование функции attachInterrupt() и дело сразу же сдвинулось с мертвой точки. Почитав про данную функци, выясняем, что на плате arduino nano можно использовать всего два порта для данной функции: это D2 и D4 (в самой функции указывается как 0 и 1 соответственно).
И сразу же скажу, при непрерывном чтении порта, ой как не желательно использовать в коде программы функции delay(), так как каждая из них будет тормозить чтение сигнала PWM, по этому так же было решено обойти эту функцию используя подсчет времени работы контроллера ардуины (micros() и millis()).
Еще сразу же подумал сделать интересную, как мне кажется опцию - сигнал о отработке фелйсейва при потере сигнала (используется опция приемника)

P.S. следующей статьей думаю написать о присобачивании фейлсейва к приемникам не имеющих такой возможности, но обязательно имеющую одну особенность о которой будет описано потом…

Ниже приведен код того что получилось, с комментариями:


volatile int start_time = 0;
volatile int length = 0;
unsigned long timing;
int on=0;
int ledpin=12; // задаем номер пина управления подсветкой, к которой подключается затвор транзистора через резистор 100 ом (в пинципе не критичен номинал, но задирать не стоит)
volatile int state = LOW;

void setup() {
pinMode(ledpin, OUTPUT); //определяем пин для управления подсветкой как выход
attachInterrupt(0, rising, RISING);// Привязываем к Pin2 прерывание по фронту сигнала. п.с. да да "0" это цифровой пин 2 (смотреть описание attachInterrupt();)
Serial.begin(9600);  //включаем монитор порта для отладки

}

void loop() {
if (on<250 & on>200){miganie();} // если полученое PWM значение (минус тыща, смотреть ниже присвоение значения переменной) меньше 250 но больше 200 (тоесть диапазон от 200 до 250) то начинаем мигать подсветкой
                                //диапазоном задается полученное плавающее значение при переходе приемника в режим фейл сейв. необходимый уровень задается пультом


  if (on>500){digitalWrite(ledpin, HIGH);} // если значение PWM-1000 больше 500, то включаем подсветку, можно поменять как вам удобнее
  if (on<100){digitalWrite(ledpin, LOW);} // если значение PWM-1000 менше 100, то выключаем подсветку, можно поменять как вам удобнее
  Serial.println(on);//можно стереть, чисто для вывода в монитор порта статуса PWM для отладки и настройки условий

}
void rising() {
attachInterrupt(0, falling, FALLING);// Привязываем к Pin2 прерывание по фронту сигнала. п.с. да да "0" это цифровой пин 2 (смотреть описание attachInterrupt();)
start_time = micros(); //сохраняем значение времени начала импульса
}

//Обработчик прерывания по срезу сигнала
void falling() {
attachInterrupt(0, rising, RISING);// Привязываем к Pin2 прерывание по фронту сигнала. п.с. да да "0" это цифровой пин 2 (смотреть описание attachInterrupt();)
length = micros() - start_time; //получаем значение PWM в микросекундах (обычно от 1000 до 2000 с чем то)
on=length-1000; //уменьшаем полученное значение PWM на тыщу, для удобства
}
void miganie(){ //функция мигания
  digitalWrite(ledpin, state); //задаем на заданный пин статус (хай или лоу) исходя из состояния переменной state
   if (millis() - timing > 100){  //нужное вам значение интервала мигания
         timing = millis();
         blinked(); //при каждом выполнении данного участка кода конвертируем статус активности подсветки
         digitalWrite(ledpin, LOW); //гашение чтобы не повисало
   }
}

void blinked()  //функция смены значения переменной state
{state=!state;}

мигание в данном коде настроено на уровень PWM сигнала от 1200 до 1250, но я “просто так” от уровня полученного сигнала отнял 1000, по этому значения в условии 200 и 250 соответственно. опять же, по комментам думаю понятно, что и где. далее настраиваете фейлсейв аппаратуры на этот диапазон PWM сигнала и всё.
Подключив ардуино к компьютеру и приемнику, открыв монитор порта, можно наблюдать текущее значение получаемое с приемника.

Так как у нас используется светодиодная лента, питание ее сделано через полевой транзистор по схеме:

Схема подключения ардуины к приемнику:

Видео того, что получилось:

  • 32