Перейти к содержанию

Эмуляция нажатия кнопок энкодером на Attiny24


ploshka

Рекомендуемые сообщения

Здравствуйте,
Есть андроид-автомагнитола умеющая обучаться кнопкам на мультируле (резистивная матрица).
Есть энкодер (модель [url=https://www.promelec.ru/product/328188/]EC28A[/url]), который хочу к этой магнитоле подключить. Он должен регулировать громкость.
Сделать это хочу через эмуляцию нажатия кнопок. Т.е. кручу влево - на входе магнитолы сопротивление равное сопротивлению при нажатии кнопки Volume-, кручу вправо - Volume+.
Сама логика зашита в Attiny24. Кроме этого, в ней же логика кнопки вкл/откл с памятью.
Аналогичную схему уже делал недавно на PIC10. Там только Volume-, Volume+ делал. И магнитола была андроид, но другой модели. И в принципе работало. Были небольшие проблемы с отлавливанием сигнала магнитолой изначально - не могла она понять, что кнопка нажата. Отрегулировал длину импульса нажатия кнопки (50мс) и стало нормально.
Алгоритм в pic и attiny примерно схожи, реализация разная только.
На Attiny что-то не заводится. Эмуляция в протеусе работает нормально вроде. Но магнитола считает, что поворот влево и вправо - это одно и тоже. Соответственно регулирует громкость только в одну сторону независимо от того куда крутить. 
scheme.png.e872ac5152c3e5261b55f156ce9ccca5.png
На схеме резистор R2 имитирует общее сопротивление мультируля в состоянии покоя.
При вращении ручки энкодера влево на ноге 7 появляется импульс, который на время замыкает резистор R6 на массу, подключаясь тем самым параллельно к сопротивлению мультируля. Их общее сопротивление равно сопротивлению при нажатой кнопке Volume-.
Аналогично и при вращении вправо - с ноги 6 идет импульс и замыкает R7, Volume+.
Так это должно работать.
Пробовал оптроны заменить на транзисторы, ситуация не изменилась.
Подумал также, что может энкодер загнулся. Заменил на другой, ничего не поменялось.
Возможно я что-то с инициализацией входов-выходов намудрил в МК. Т.к. в этом деле еще новичок.
Исходники программы и проект в proteus прилагаю.

Спойлер
#include <tiny24a.h>

#define BUTTON1       PINA.0              // вход первой кнопки
#define OUT1          PORTB.0             // выход состояния первой кнопки
#define VOLUME_UP     PORTA.6             // Выходной импульс "Volume +" (по часовой стрелке)
#define VOLUME_DOWN   PORTA.7             // Выходной импульс "Volume -" (против часовой стрелки)
#define CHATTER_WAIT  10                  // задержка после отжатия кнопки для антидребезга - 100 мсек
#define POWEROFF_WAIT 5000                // время удержания кнопки для отключения
#define IMPULSE_DELAY 200                 // Длительность импульса нажатой кнопки на выходе:
                                          //  указанное кол-во * (1000 мсек / частоту срабатывания прерывания в секунду) = ~ 50 мсек

eeprom unsigned char button1Memory; 
unsigned char triggerChatter1;
unsigned char pressed1;
unsigned int offCounter1;
unsigned int encoderState, encoderStatePrev, 
             volumeUpStateCounter, volumeDownStateCounter, 
             delayUpCounter, delayDownCounter; 
             
void main(void)
{
  DDRA  = (1<<DDA7)   | (1<<DDA6)   | (0<<DDA5)   | (0<<DDA4)   | (0<<DDA3)   | (0<<DDA2)   | (0<<DDA1)   | (0<<DDA0);
  PORTA = (0<<PORTA7) | (0<<PORTA6) | (1<<PORTA5) | (1<<PORTA4) | (0<<PORTA3) | (1<<PORTA2) | (1<<PORTA1) | (1<<PORTA0);

  DDRB  =   (0<<DDB3) | (1<<DDB2)   | (1<<DDB1)   | (1<<DDB0);
  PORTB = (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

  // --- Настройка работы прерывания таймера по переполнению ---
  /*
  Предделитель 8, Частота МК 1,200,000 Гц, "тик" таймера 1200000/8 = 150000 раз в секунду. 
  В счетный регистр таймера вносится 0хDA = 216. 
  Cчетчик таймера однобайтовый (max значение = 255), значит до переполнения он инкрементируется 255-218 = 37 раз
  Тогда счетчик таймера переполнится и прерывание будет срабатывать:
  150000 / 37 = 4054 раз в секунду
  */
  TCCR0B = (0<<WGM02)  | (0<<CS02)   | (1<<CS01)   | (0<<CS00);  // инициализация работы таймера предделитель 8 (150кГц)
  TIMSK0 = (0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);               // включение прерывания нулевого таймера по переполнению
  ACSR   =    (1<<ACD) | (0<<ACBG)   | (0<<ACO)    | (0<<ACI)   | (0<<ACIE)   | (0<<ACIS1) | (0<<ACIS0); // Отключить аналаговый компаратор
  TCNT0  = 0xDA;  // счетчик таймера
 
  if (button1Memory)      
   OUT1 = button1Memory;  //  последнее запомненное состояние кнопки 1 на выход
     
  #asm("sei")             // разрешить прерывания
   
  while (1)
  {      
      if (volumeUpStateCounter >= 4) 
      {                            
        VOLUME_UP = 1;
        volumeUpStateCounter = 0;
        delayUpCounter = 0;
      } 
      
      if (volumeDownStateCounter >= 4) 
      {                              
        VOLUME_DOWN = 1;       
        volumeDownStateCounter = 0;
        delayDownCounter = 0;
      }             
      
      
      if (delayUpCounter == IMPULSE_DELAY & VOLUME_UP == 1)
      {
         VOLUME_UP = 0;
      }
      
      if (delayDownCounter == IMPULSE_DELAY & VOLUME_DOWN == 1)
      {
         VOLUME_DOWN = 0;
      } 
                    
  };
}

// Прерыванию по переполнению счетчика таймера. ~ 4000 раз в секунду
interrupt [TIM0_OVF] void timer0_ovf_isr(void) 
{
  TCNT0 = 0xDA;                                // выставить счетчик таймера  
  encoderState = PINA & 0b00110000;            // на pin 4 и 5 - входы фаз A и B энкодера
  delayUpCounter++;
  delayDownCounter++; 
  
  // --- обработка сигнала энкодера ---
  
  if (encoderState != encoderStatePrev)
  {  
    switch(encoderStatePrev)
    {
      case 32:
      {
        if(encoderState == 48) volumeUpStateCounter++;
        if(encoderState == 0) volumeDownStateCounter++; 
        break;
      }
      case 0:
      {
        if(encoderState == 32) volumeUpStateCounter++;
        if(encoderState == 16) volumeDownStateCounter++; 
        break;
      }
      case 16:
      {  
        if(encoderState == 0) volumeUpStateCounter++;
           if(encoderState == 48) volumeDownStateCounter++; 
        break;
      }
      case 48:
      {
        if(encoderState == 16) volumeUpStateCounter++;
        if(encoderState == 32) volumeDownStateCounter++; 
        break;
      }
    }
    encoderStatePrev = encoderState;            
  } 
  
  // --- обработка нажатия кнопки 1 ---
  if (BUTTON1 == 0)                  
  {
    if (triggerChatter1 == 0 && OUT1 == 0)     // если кнопка нажата только что и до этого выход был отключен 
    { 
        OUT1 = 1;                              // включить выход 
        button1Memory = 1;                     // запоминить состояние кнопки в памяти  
        pressed1 = 1;                          // запоминить, что при нажатии кнопки выход включился
    } 
    else if (pressed1 == 0)                    // если выход не включался
    {
      if (offCounter1 < POWEROFF_WAIT)         // и не истекло время удержания кнопки для выключения выхода
        offCounter1++;                         // увеличивать счетчик удержания отключения
        
      else if (offCounter1 == POWEROFF_WAIT)   // если подошло кнопку удерживали нужное для отключения время
      {
         OUT1 = 0;                             // выключить выход
         button1Memory = 0;                    // запоминить состояние кнопки в памяти  
         offCounter1 = 0xFFFF;                 // счетчик удержания отключения установить в MAX значение, чтобы он был больше времени задержки
      }                     
    }   
    
    triggerChatter1 = 1;                       // включить триггер-защелку    
  }
  else                                         // кнопка1 отжата
  { 
    offCounter1 = 0;                           // сбросить счетчик удержания отключения
    pressed1 = 0;                              // сбросить состояние кнопки1 
    
    if (triggerChatter1)                       // если кнопка1 была нажата
    {
      triggerChatter1++;                       // увеличить счетчик антидребезга
      
      if (triggerChatter1 > CHATTER_WAIT)
        triggerChatter1 = 0;                   // если время антидребезга прошло, то сбросить триггер-защелку
    }
  }   
     
}

 



Подскажите что не так

EncoderDecoder.zip

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...