Jump to content
  • entries
    26
  • comments
    430
  • views
    45579

Простой селектор входов для УМ (2..4 входа)

Простой селектор входов для усилителя мощности. Выполнен на микроконтроллере ATtiny13A.

Подключение выполняется по следующей схеме:

SELECTOR.png.0325ddd52ddc53e6f245b828e73f036d.png

Естественно, что вместо светодиодов должны стоять реле.

В 1 кбайте памяти микроконтроллера спрятан следующий функционал:
- использование от 2-х до 4-х входов, количество которых определяется автоматически (неиспользуемые 4-й или 3-й и 4-й входы следует подтянуть к питанию через резистор 5-10 кОм);
- переключение одной кнопкой "по кругу";
- запоминание последнего выбранного входа;
- задержка при включении (2 c);
- защита от дребезга кнопки;
- mute между переключениями каналов (0,5 c).

При программировании следует установить фьюзы следующим образом: HIGH - 0xFF, LOW  - 0x79. То есть нужно отключить делитель частоты на 8, и выбрать источник тактирования - внутренний RC-генератор на 4,8 МГц с задержкой старта в 64 мс.

Платы под схему нет, предполагаю, что каждый нарисует себе сам под необходимые детали.

На видео показан макет, демонстрирующий работу селектора:

 

Скачать файл прошивки

  • Like 3
  • Upvote 3


39 Comments


Recommended Comments



Создал проект, добавил файл прошивки, в опциях микросхемы поставил CKSEL Fuses в 4.8MHz, запускаю симуляцию, кликаю кнопочку - светодиоды не загораются :(

1122.PNG

1122.PNG

Edited by drcrash

Share this comment


Link to comment

Спасибо, заработало, но не так, как ожидалось - как видите по схеме у меня 2 входа, но контроллер считает, что их 4. пробовал 5К и 10К - на R32 и R31 при переключении точно также переключает, как и на активные каналы, то есть 4 активных канала вместо двух

Edited by drcrash

Share this comment


Link to comment

Открыл исходники, а то забыл уже что там было. 

В общем, при запуске проверяются только 4 и 3 каналы, т.е. с конца. А вы отключили 1 и 2.

Share this comment


Link to comment

Ок, сделал как показано на схеме:

1122.PNG.f2736836645ab46a92e5bf5d57061fa2.PNG

 

В результате есть проблема - как видно из схемы 7-й контакт микросхемы "загорелся", в общем участвует в переключении. Со вторым контактом все ок - его пропускает. Странно.

И можно ли задержку переключения в пол-секунды поставить?

Edited by drcrash

Share this comment


Link to comment

Действительно с подтяжками 10к такое поведение. Вечером посмотрю где ошибка.

Задержка между переключениями и так полсекунды сейчас.

Share this comment


Link to comment

Собственно без них напрямую контакты на питание все ок работает, но вот можно ли так использовать микросхему в реальности не знаю :unknw:

Edited by drcrash

Share this comment


Link to comment

Защита от дребезга контактов - слишком громко сказано. Это элементарщина. Вижу код тут не выкладывается. Зря. Конечные автоматы, автоматное программирование. Функционал в начале расписан. Будем считать это как ТЗ. Накидать программу за вечерок как два пальца... Дарю кусочек кода

Spoiler

//========================================================================
#ifndef KBD_DRV_H

#define KBD_DRV_H

#include "kbd_drv.h"

#include "main_def_func.h"
//========================================================================

//========================================================================
#ifdef __PROJECT_MODE_WORK__
#define DEBOUNCE_DELAY 30
#define HOLD_DELAY_1   300
#define HOLD_DELAY_2   5000
#endif

#ifdef __PROJECT_MODE_DEBUG__
#define DEBOUNCE_DELAY 3
#define HOLD_DELAY_1   10
#define HOLD_DELAY_2   50
#endif
//========================================================================

//========================================================================
#ifdef __WORK_BOARD__
#define KEY_PIN        PINB
#define KEY_PORT       PORTB
//------------------------------------------------------------------------
#define KEY            PB0
#define KEY_BIT        1<<KEY
#endif
//------------------------------------------------------------------------

//------------------------------------------------------------------------
#ifdef __DEBUG_BOARD__
#define KEY_PIN        PIND
#define KEY_PORT       PORTD
//------------------------------------------------------------------------
#define KEY            PD0
#define KEY_BIT        1<<KEY
#endif
//========================================================================

//========================================================================
//#define KEY1_PRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 0)
//#define KEY1_UNPRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 1)

#ifdef __PROJECT_MODE_WORK__
#define Set_Is_Key_Pressed() !(check_bit (KEY_PIN, KEY))  // Low level.
#endif

#ifdef __PROJECT_MODE_DEBUG__
#define Set_Is_Key_Pressed() check_bit (KEY_PIN, KEY)  // Low level.
#endif

// При работе с буфером входов (расширение ввода-вывода):
// #define Set_Is_Key_Stop_Pressed()   check_bit (inputs_buf [0], KEY_STOP)
//========================================================================

//========================================================================
typedef enum _kbd_drv
{
   KBD_DRV_INIT = 0,
   KBD_DRV_NONE,
   KBD_DRV_WAIT_DOWN,
   KBD_DRV_DOWN,
   KBD_DRV_WAIT_UP,
   KBD_DRV_UP,
} kbd_drv_t;
//========================================================================

//========================================================================
typedef enum keys_buf
{
   KEY_COD_SHORT_PRESS = 0,
   KEY_COD_LONG_PRESS,
} key_cod_t;
//========================================================================

//========================================================================
typedef enum key_press_mode
{
   KEY_PRESS_MODE_NONE = 0,
   KEY_PRESS_MODE_WAIT_LONG_PRESS,
   KEY_PRESS_MODE_WAIT_RESET,
} key_press_mode_t;
//========================================================================

//========================================================================
void kbd_drv (void);
//------------------------------------------------------------------------
void Set_Keys_Buf (key_cod_t a);
key_cod_t Get_Keys_Buf (void);
//========================================================================

#endif

//========================================================================
#include "kbd_drv.h"
//========================================================================

//========================================================================
static kbd_drv_t _kbd_drv;

static key_cod_t keys_buf;

static key_press_mode_t key_press_mode;

static soft_timer ST_KBD_DRV;
//========================================================================

//========================================================================
void kbd_drv (void)
{
   switch (_kbd_drv)
   {
      case KBD_DRV_INIT:
         key_press_mode = KEY_PRESS_MODE_NONE;
         _kbd_drv = KBD_DRV_NONE;
         break;

      case KBD_DRV_NONE:
         if (Set_Is_Key_Pressed ()) // Если кнопка нажата, то
         {
            set_soft_timer (ST_KBD_DRV, DEBOUNCE_DELAY); // установка таймера антидребезга.
            _kbd_drv = KBD_DRV_WAIT_DOWN;
         }
         break;

      case KBD_DRV_WAIT_DOWN:
         if (handle_soft_timer (ST_KBD_DRV)) // Таймер антидребезга.
         {
            if (Set_Is_Key_Pressed ())
            {
               set_soft_timer (ST_KBD_DRV, HOLD_DELAY_1); // Установка таймера длинного нажатия кнопки.
               key_press_mode = KEY_PRESS_MODE_WAIT_LONG_PRESS;
               _kbd_drv = KBD_DRV_DOWN;
            }
            else
               _kbd_drv = KBD_DRV_NONE;
         }
         break;

      case KBD_DRV_DOWN:
         if (Set_Is_Key_Pressed ())
         {
            if (handle_soft_timer (ST_KBD_DRV))
            {
               switch (key_press_mode)
               {
                  case KEY_PRESS_MODE_WAIT_LONG_PRESS:
                     set_soft_timer (ST_KBD_DRV, HOLD_DELAY_2); // Установка таймера RESET.
                     key_press_mode = KEY_PRESS_MODE_WAIT_RESET;
                     break;

                  case KEY_PRESS_MODE_WAIT_RESET:
                     Set_Event (EV_ID_RESET, USER_EVENT); // Событие нажатия кнопки.
                     key_press_mode = KEY_PRESS_MODE_NONE;
                     _kbd_drv = KBD_DRV_WAIT_UP;
                     break;
               }
            }
         }
         else
            _kbd_drv = KBD_DRV_WAIT_UP;
         break;

      case KBD_DRV_WAIT_UP:
         if (!(Set_Is_Key_Pressed ())) // Если кнопка отпущена, то
         {
            set_soft_timer (ST_KBD_DRV, DEBOUNCE_DELAY); // Таймер подавления дребезга.
            _kbd_drv = KBD_DRV_UP;
         }
         break;

      case KBD_DRV_UP:
         if (handle_soft_timer (ST_KBD_DRV)) // Таймер подавления дребезга.
         {
            if (!(Set_Is_Key_Pressed ()))
            {
               switch (key_press_mode)
               {
                  case KEY_PRESS_MODE_WAIT_LONG_PRESS:
                     Set_Keys_Buf (KEY_COD_SHORT_PRESS); // Короткое нажатие.
                     Set_Event (EV_ID_KEY_PRESSED, USER_EVENT); // Событие нажатия кнопки.
                     break;

                  case KEY_PRESS_MODE_WAIT_RESET:
                     Set_Keys_Buf (KEY_COD_LONG_PRESS); // Длинное нажатие.
                     Set_Event (EV_ID_KEY_PRESSED, USER_EVENT); // Событие нажатия кнопки.
                     break;
               }

               _kbd_drv = KBD_DRV_INIT;
            }
            else
               _kbd_drv = KBD_DRV_WAIT_UP;
         }
         break;
   }
}
//========================================================================

//========================================================================
void Set_Keys_Buf (key_cod_t a)
{
   keys_buf = a;
}
//------------------------------------------------------------------------
key_cod_t Get_Keys_Buf (void)
{
   return keys_buf;
}
//========================================================================


//Шкелет основной программы:

//========================================================================
void proc_device (void)
{
   static proc_device_t _proc_device;

   static soft_timer ST_PROC_DEVICE;

   static u08 cnt_inputs;

   if (Get_Event (EV_ID_RESET))
      _proc_device = PROC_DEVICE_INIT;

   switch (_proc_device)
   {
      case PROC_DEVICE_INIT: // Блок инициализации.
         break;

      case PROC_DEVICE_1:
         if (Get_Event (KEY_COD_SHORT_PRESS))
         {
            if (++cnt_inputs >= MAX_INPUTS)
               cnt_inputs = 0;
         }

         switch (cnt_inputs)
         {
            case 0:
               INPUTS_PORT = INPUT_2
               break;

            case 1:
               INPUTS_PORT = INPUT_3
               break;

            case 2:
               INPUTS_PORT = INPUT_4
               break;

            case 3:
               INPUTS_PORT = INPUT_1
               break;
         }
         break;

      case PROC_DEVICE_2:
         break;
   }
}
//========================================================================

 

 

Share this comment


Link to comment

у меня еще вопрос - почему вместо реле не используют транзисторы в подобных схемах?

Edited by drcrash

Share this comment


Link to comment
Только что, drcrash сказал:

почему вместо реле не используют транзисторы в подобных схемах?

Искажения, однако...

Share this comment


Link to comment

Мне кажется для микроконтроллера это маловато, переключение каналов можно организовать на D тригере и логикой (=1). Думаю тут надо идти дальше и сделать автоматический селектор. Правда Attiny тут хватит на не больше чем 2 канала. Можно влепить Атмегу 168 или 328p.

Её прошивать проще, среда разработки ардуино.

Share this comment


Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Add a comment...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...