Простой фэйлсэйф - помогите с программой
- Войдите на сайт для отправки комментариев
Здравствуйте! Я хочу сделать на базе ардуино модуль для модели, выполняющий роль фэйл-сэйфа и инвертора одного серво-канала. Модуль будет работать с обычным р/у приемником, он будет промежуточным звеном между некоторыми сервами и приемником.
Я не программист, и решил сейчас потренироваться и сделать программу, по которой ардуино будет просто копировать длительность серво импульса на другую ногу - восходящий фронт серво сигнала через прерывание ставит 1 в булевую переменную, нисходящий ставит 0, в основном цикле программа проверяет состояние переменной: если переменная равна 1 то ставит high на пин с серво, если 0 соответственно low. Моя китайская мега работает на 12мгц, то есть она вроде должна успевать все делать даже при самом коротком серво-импульсе, ведь и программа маленькая.
Сначала я вообще хотел использовать прерывание по лоу левелу на входном пине (жаль нет прерывания по высокому уровню..), и в отработчике прерывания ставить значение на выходной пин, и совсем ничего не делать в основном цикле, имхо, так надежнее, но тогда нужно ставить инвертор, а мне не хотелось паять.
[code]
int pin0 = 2; //пин, на который идет сигнал с приемника
int pin1 = 7;//выходной сигнал на серву
boolean state = 0;//состояние выхода
void setup() {
pinMode(pin0, INPUT);
pinMode(pin1, OUTPUT);
attachInterrupt(pin0, get_rise, RISING);
attachInterrupt(pin0, get_fall, FALLING);
}
void get_rise()
{
state = 1;
}
void get_fall()
{
state = 0;
}
void loop() {
if(state == 0)
pin1 = LOW;
if(state == 1)
pin1 = HIGH;
}
[/code]
Все верно подключаю, а серва не реагирует, подскажите, что не так.. Приемник и серва рабочие, несколько раз уже все проверял.
Я стараюсь писать максимально просто, потому что потом на эту мегу я хочу добавить гироскоп, чтобы одна из серв автоматически держала горизонт(в моем случае дифферент), а для этого судя по всему нужен будет пид -регулятор, не знаю пока, насколько он будет сложен в реализации, плюс еще на меге должен калман работать.
1. Переменные, которые изменяются в обработчике прерывания, должны быть объявлены с volatile.
2. Использование attachInterrupt неправильное. Указывать надо не номер пина, а номер прерывания (0 или 1). То, что они сидят на пине 2 и 3 указывать не надо. Поэтому строки 2 и 6 можно убрать. И как ниже написал коллега dimax, для одного внешнего прерывания (для одного пина) может быть только один обработчик. С одним из четырёх режимов: LOW, CHANGE, RISING, FALLING.
3. Вместо:
void loop() { if(state == 0) pin1 = LOW; if(state == 1) pin1 = HIGH; }Должно быть:
void loop() { if(state == 0) digitalWrite(pin1, LOW) if(state == 1) digitalWrite(pin1, HIGH) }Vladimir_KVG, код ужасный. Начиная от крупных косяков (типа 8 и 9 строка -должно быть что-то одно, либо райзин либо фоллин). Заканчивая вообще идеологией. Зачем применять МК там, где можно использовать один транзистор? :)
Спасибо за ответы! Про volatile и только одно прерывание на порт я не знал, спасибо. Буду основательно все изучать :)
А фэйлсэйф будет работать по такому алгоритму:
-на вход с прерыванием по низкому уровню подается инвертированный (транзистором :) ) сигнал с приемника
-в прерывании выходной порт ставится в 1, обнуляется значение специальной переменной
-в основном цикле программа по таймеру инкрементирует значение переменной, и если оно достигнет определенного значения(из-за пропадания сигнала и, значит, прерываний, обнуляющих эту переменную) выполняет "фэйлсэйфовые" операции
Алгоритм, вроде, рабочий. Может можно как-то проще сделать?