Морзянка, моргаем 2 светодиодами без задержки... RTOS?

achest
achest аватар
Offline
Зарегистрирован: 01.10.2012

привет всем!

Делаю маленькое устройство, и не хочу ставить туда нормальный индикатор... Есть меню1 : 1-2-3-4  Меню2  1-2-3..9

Хочется поставить 2 светодиода, и они должны моргать оба, морзянкой.  кол-во морганий == положение в меню.  Все через прервывание, ничего дергать из loop  не хочется. Кол-во  светодиодов не обязательно 2. Хочется на пример подключить еще и вибромотор, который можно на пример 1 раз дернуть  при смене меню вниз, 2 раза вверх и Тире, "остановка". Светодиды, и мотор работают на разных "частотах"

Зачем изобретать велосипед?. Может кто-то уже написал подобное? В какую сторону я думаю. Взять библиотеку Timer2, и на ее основе написать.  добавить туда список следующих  событий. Событие: {задержка, номер порта, новое состояние} . Прерывание: берется первый элемент из списка, выполняется, стирается из стека, таймер настраивается на следующий элемент... Проблема сводится только к библиотеке отсортированных arraylist. Но все еще не понятно как добавлять "циклические последовательности". Мелодия разложенная на шаги может получиться относительно длинной...

Короче я избретаю RTOS...  У кого-нибудь есть идеи, или может видел библиотеку, как  такое просто надежно сделать? вызывать run из loop категорически отказываюсь.

 

 

 

 

Vладимир
Offline
Зарегистрирован: 27.01.2015

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

Joiner
Offline
Зарегистрирован: 04.09.2014

Можно сдвиговый регистр и 8 светодиодов. В двоичной системе покажет 256 положений.

achest
achest аватар
Offline
Зарегистрирован: 01.10.2012

Vладимир пишет:

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

На самом деле важно не второй светодиод, а вибромотор. Что бы нажал на кнопку и получил feedback, что команда дошла. Так как пользователь один и это я, и реально режимов всего 3, а второй параметр это "интенсивность" то это логичнее, чем дисплей. 

На самом деле эта библиотека мне пригодится и в других проектах. На пример крутить 2 шаговых мотора...

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

achest, из вашего словесного описания всё равно не очень понятно, что же конкретно вы хотите. Я когда изучал таймеры в ардуине, то писал простенький скетч, там от некоего события, (в моём случае нажатие на кнопку), запускается таймер, и по определённой программе дёргает ногой.  Может посвистеть в динамик, может поморгать светодиодом, или пожужжать виброй, -по вкусу.  Программу (строка 11) можно менять, она не привязана жёстко. Никакого loop разумеется )  Вкратце о принципе работы: По нажатию кнопки (висящей на прерывании) запускается таймер2, и создаёт каждые 10миллисекунд  прерывание. В векторе прерывания переменной n идёт подсчёт числа вхождений, если счёт совпадает с переменными a..e то инвертируется указанная нога порта.  C первым входом включается нога 13. Переменная А -выключает  её спустя a*10 мс, переменная b снова включает  спустя b*10мс  от первого входа, и так далее. Когда программа выполнится таймер отключается. По-моему примерно о этом вы и говорили, только набор переменных нужно подставлять для каждого события свой.

byte a,b,c,d,e;
void setup() {
pinMode(13,OUTPUT);// светодиод  на 13 ноге
pinMode(2,INPUT_PULLUP); //knopka
attachInterrupt(0, key_start, FALLING);
TCCR2A=(1<<WGM21)|(1<<WGM20); //FastPWM
TIMSK2=0; TCCR2B=0; OCR2A=155; // every 10 ms interrupt
}

void key_start(){ 
a=10;b=15;c=35;d=40;e=50;  
TCNT2=0; TIMSK2=1<<TOIE2; TCCR2B=15;
}

ISR (TIMER2_OVF_vect) { 
static byte n=0;  
if (!n){PORTB|=1<<5;} //первый вход, включаем 13 ногу
n++;
if (n==a||n==b||n==c||n==d||n==e) {PORTB ^= (1<<5); }
if (n==e){ PORTB&=~(1<<5); n=0; TCCR2B=0; TIMSK2=0;  }
}

void loop() {    
  }

 

achest
achest аватар
Offline
Зарегистрирован: 01.10.2012

Спасибо за участие. Я к сожалению мыслю все еще  на Java и концепты у меня OO. Я хочу написать более-менее универсальную библиотеку. т.е. Кол-во светодиодов и как они будут моргать оно  не известно...

Мой конечный код может выглядеть примерно так:

 

#inclule"timecommander"
int menu1;
int menu2;
int led1pin = 9;
int led2pin = 10;
int vibropin=11;


void setup() {
  timeCommander.init();
  timeCommander.AddCommand(1,LOW,led1pin, led1Callback);
  timeCommander.AddCommand(1,LOW,led2pin, led2Callback);
}

void loop ()
 { 
   if ( Key1Pressed()) {
   menu1++;
   // Включили вибромотор на 500 мс.
   timeCommander.AddCommand (1, HIGH, viborpin, null);
   timeCommander.AddCommand (500, LOW, viborpin, null);

  } 
  if ( Key2Pressed()) {
   menu2++;
   // Включили вибромотор на 200 мс.
   timeCommander.AddCommand (1, HIGH, viborpin, null);
   timeCommander.AddCommand (200, LOW, viborpin, null);

  } 
  ...
 
}

void led1Callback() {
 
    // Моргнули светодиодом menu1 раз .
     for(int i=0; i< menu1 ; i++ ) {
          timeCommander.AddCommand(100,HIGH,led1pin, null);
          timeCommander.AddCommand(100,LOW,led1pin, null);
    }
    // цикл закончился. Сначала пауза. Потом добавили себя еще раз.
    timeCommander.AddCommand(500,LOW,led1pin, led1Callback);
 
}
void led2Callback();

Мне не понятно только как реализовать стек с вставками/ отсортировать список по возрастанию, что бы библиотека определяла только время следующего события, беря событие из одного списка.