энкодер для управления громкостью

duh
Offline
Зарегистрирован: 14.02.2015

Привет.

Пытаюсь в машину поставить планшет и очень уж хочется поставить энкодер для управления громкостью...

В принципе всё вроде как работает. Единственно что какие-то лаги при попытке изменить уровень громкости... он то меняется еле-еле, то резко довольно таки резко поднимается вдвое...

Принцип управления - замыкаю контакты кнопок на дешёвенькой китайской усб звуковухе. До куче контроллер ещё и переключает реле своей кнопкой.

Проблем с кнопкой которая управляет реле не замечено...а вот с энкодером не айс... может есть какой-то другой способ кроме делэя что-б замкнуть контакт на какое-то время и потом опять его разомкнуть?

 

 
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 0;       // pin 0
const int pin_B = 1;       // pin 1
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;

const int button = 3;          //пин кнопки вкл/выкл
const int relay = 13;          //пин управления реле
 
void setup()  {
  // declare pin 9 to be an output:
  pinMode(9, OUTPUT);         // устанавливаем pin 9 как выход + 
  pinMode(10, OUTPUT);         // устанавливаем pin 10 как выход - 
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime; 
  pinMode(relay, OUTPUT);
  pinMode(button, INPUT);
} 
 
void loop()  {
  currentTime = millis();
  if(currentTime >= (loopTime + 5)){ // проверяем каждые 5мс (200 Гц)
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера 
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода Б энкодера    
    if((!encoder_A) && (encoder_A_prev)){    // если состояние изменилось с положительного к нулю
      if(encoder_B) {
        // выход В в полож. сост., значит вращение по часовой стрелке
        digitalWrite(9, HIGH);
        delay(500);
        digitalWrite(9, LOW);        
      }   
      else {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        digitalWrite(10, HIGH);
        delay(500);
        digitalWrite(10, LOW);              
      }   
    }   
    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла     
    loopTime = currentTime;
  } 
  if (digitalRead(button)==HIGH){
    if (digitalRead(relay)==HIGH){digitalWrite(relay,LOW);delay(300);}else{digitalWrite(relay,HIGH);delay(300);}
  }
  
}

 

vvadim
Offline
Зарегистрирован: 23.05.2012

А зачем в сетапе строки 18 и 19?

duh
Offline
Зарегистрирован: 14.02.2015

хз. я не курил тот мануал особо детально. Это изначально было примером как работать с энкодером для управления яркостью светодиода. Я лишь немного подогнал под себя тот пример =)

http://cxem.net/arduino/arduino8.php

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

9 и 10 выходы у вас подпаяны к кнопкам управления громкости планшета?

Почему еле еле увеличивается уменьшается это понятно, что из-за delay, пока вы в delay энкодер продолжает выдавать импульсы которые вы не учитываете, поэтому большую часть просто теряете отсюда и такой эффект.

А резкое увеличение вполне может быть связано с особенностью планшета. Короткое нажатие это на один шаг увеличить громкость, а длинное, вполне может хватить 500 быстрое (в андроиде так, например). Т.е. чуть чуть передержали и сразу несколько ступений громкости получили.

duh
Offline
Зарегистрирован: 14.02.2015

9 и 10 выходы через резисторы подключены у транзисторам. 

вот так примерно - https://drive.google.com/file/d/0BxUnFu94i50SdG5JN3FhOFlJeXc/view?usp=sharing

проверял работу на винде покамест.

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

Я вообще думаю может это связано как-то с тем что цикл обработки энкодера выполняется раз в 5мс... может это как-то связано в тем что там внутри делэй стоит... что-то типа рассинхронизации получается...

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Так у вас и нет цикла 5мс в рабочем полождении. 5мс только в простое, а как только начинаете крутить у вас сразу цикл 500мс из-за делаев. Вот если будите крутить так чтобы один щелчок энкодера был раз в пол секунды хотябы а лучше и раз в секунду, всё будет чётко работать.

Надо избавляться от delay как минимум, а там уже видно будет.

duh
Offline
Зарегистрирован: 14.02.2015

вот я и спрашивал - как можно выставить пин в 1 на 100-200мс и потом опять в 0 без делэя... пока мне ничего не придумалось =\

duh
Offline
Зарегистрирован: 14.02.2015

хотя есть одна идея..... сейчас попробую =)

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Конечно можно, BlinkWithoutDelay в помощь

duh
Offline
Зарегистрирован: 14.02.2015

а вот такой вопрос возник... что выдаёт энкодер когда он не крутится никуда?

я вот подумываю в этот цикл энкодера при вращении в одну сторону - замыкать и не размыкать контакт 9 но разомкнуть 10 и наоборот. но мне тогда надо при прекращении вращения разомкнуть оба...

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Я так понимаю у вас инкрементный энкодер а не абсолютный, значит ничего не выдаёт.

Я с энкодарами вплотную не работал, но если бы вот пярм сейчас не поленился и сходил в гараж раскурочил старую магнитолу вытащил оттуда энкодер принёс его домой и подключил, то действовал бы примерно так :)

В цикле loop читаю энкодер (тем кодом что у вас есть) с частотой в 200Гц и умеличию значение переменных volume_up и volume_down. После чтения энкодера (всё в том же loop) в зависимости он значений volume_up/down (пока не 0 грубо говоря) давал бы высокий уровень на выход и уменьшал значение переменной на 1. Тогда при остановки вращения энкодера звук прибавится/убавится пока переменная 0 не станет, а потом будет просто крутиться в цикле и ждать новых вращений энкодера.

Ну как-то так :) Хотя думаю есть и более красивые решения, может кто-то отзовётся из тех кто сталкивался с энкодерами поближе

duh
Offline
Зарегистрирован: 14.02.2015

не ну это имхо немного не то. громкость должна реагировать в процессе пока крутится энкодер а не после... имхо...

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Так то что я описал и есть в процессе. Я имел ввиду что после того как прекратили крутить вы получите две переменных со значением 0 по которым и сможете оба выхода установить в LOW

duh
Offline
Зарегистрирован: 14.02.2015

прпробовал так - не пашет =\ очень медленно и почему-то только увеличивается громкость... не уменьшается... видимо слишком часто цикл выполняется и если не быстро крутить - получается что размыкается кнопка быстрее чем успеет сработать...

    if((!encoder_A) && (encoder_A_prev)){    // если состояние изменилось с положительного к нулю
      if(encoder_B) {
        // выход В в полож. сост., значит вращение по часовой стрелке
        digitalWrite(9, HIGH);
        
        digitalWrite(10, LOW);        
      }   
      else {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        digitalWrite(10, HIGH);
        
        digitalWrite(9, LOW);              
      }   
    }
   if ((!encoder_A)&&(!encoder_B)){digitalWrite(9, LOW); digitalWrite(10, LOW);}   

 

duh
Offline
Зарегистрирован: 14.02.2015

ок попробую покурить... что-то голова совсем с утра не варит =) навер надо к коням сходить сначала, а ардуинку вечером мучать )

duh
Offline
Зарегистрирован: 14.02.2015

ну скажем так - работает намного лучше, но если крутить быстро энкодер - тупит тоже... если неспешно - то всё красиво и плавно получается =)

  if(currentTime >= (loopTime + 5)){ // проверяем каждые 5мс (200 Гц)
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера 
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода Б энкодера    
    if((!encoder_A) && (encoder_A_prev)){    // если состояние изменилось с положительного к нулю
      if(encoder_B) {
        // выход В в полож. сост., значит вращение по часовой стрелке
        vol_up = 20;      
      }   
      else {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        vol_down = 20;              
      }   
    }
    
   //if ((!encoder_A)&&(!encoder_B)){digitalWrite(9, LOW); digitalWrite(10, LOW);}   
    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла     
    loopTime = currentTime;
    if (vol_up > 0) {digitalWrite(9,HIGH); vol_up--;} else {digitalWrite(9,LOW);}
    if (vol_down > 0) {digitalWrite(10,HIGH); vol_down--;} else {digitalWrite(10,LOW);}

 

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

duh, а зачем вам usb-звуковуха, в планшете же есть свой выход аудио? Можно было бы просто купить Usb-регулятор громкости на енкодере, и никаких забот. Или можно собрать такой регулятор самому, (http://obruboff.ru/usb-volume-control-ver-2/ )  там всего несколько деталей Ещё интересней что нибудь через bluetooth придумать..

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

А почему 20 всегда присваивается? Империческим путем установилось? :) Я бы в 7 строке просто делал vol_up++ а если HIGH держится небольшое время и надо чтобы подольше держался для срабатывания то в 7 строке делал бы vol_up += 2 (3, 5, 10), а в 18 строке оставил как есть уменьшение на 1.

duh
Offline
Зарегистрирован: 14.02.2015

++ не катит - не работает. она сразу-же обнуляется и задержка маленькая слишком. 20 - это 100мс заедржка =) т.е получается всегда нажата кнопка какбыдто пока крутится энкодер. перестали крутить - чере 100 мс прекращает наживаться кнопка )

duh
Offline
Зарегистрирован: 14.02.2015

шоп я ещё заранее знал что есть такие усб регуляторы =) знакомый сказал заказать звуковуху и с неё сделать управления...а я повлся =) ну а для планшета надо переделаывать.... на звуковухе кнопки наживаются на землю, а на планшете хз куда - надо оба контакта замыкать.. у меня плата разведена так что кнопки на землю замыкаться будут

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

duh, на планшете ничего замыкать не надо :)  Усб регулятор громкости -по факту  обрезок мультимедия-клавиатуры. Есть готовые например: http://store.griffintechnology.com/powermate А можно сделать и самому (ссылку давал) .  А есть вообще полная юсб-карта с енкодером.

Вы представляете себе то, что вы хотите сделать? Это ж какая  масса проводов будет болтаться. планшет-юсб карта, юсб карта -ардуино, юсб карта - усилитель, ардуино -питание.  Я бы  на вашем месте сделал вообще беспроводный регулятор громкости )

duh
Offline
Зарегистрирован: 14.02.2015

беспроводной тоже будет когда-то. а все провода убираются внутрь за планшет и не будут видны совсем ;)

Кстати ссылка первая не открылась =\

duh
Offline
Зарегистрирован: 14.02.2015
duh
Offline
Зарегистрирован: 14.02.2015

вообще почему я взялся за контроллер - мне надо управлять реле для включения и выключения планшета. в данном случае регулятор громкости + кнопка будут выполнены одним девайсом. в итоге на приборке будет торчать одна ручка и одна дырка под усб.