Низкая чувствительность переменных резисторов

Nareg
Offline
Зарегистрирован: 24.12.2016

Всем доброго времени суток,

Я простой человек, и я не могу в электронику. Собрал midi-usb девайс по этой схеме:

https://cdn.instructables.com/F2L/4QL3/HYQDUAUW/F2L4QL3HYQDUAUW.LARGE.jpg

Arduino взял pro mini.

Залил туда это:

int chanVal_1;
int oldChanVal_1;
 
int chanVal_2;
int oldChanVal_2;
 
int chanVal_3;
int oldChanVal_3;
 
int chanVal_4;
int oldChanVal_4;
 
void setup(){
  Serial.begin(31250);  
}
 
void loop(){
    chanVal_1 = map(analogRead(A0), 0, 1023, 0, 127);
    chanVal_2 = map(analogRead(A1), 0, 1023, 0, 127);
    chanVal_3 = map(analogRead(A2), 0, 1023, 0, 127);
    chanVal_4 = map(analogRead(A3), 0, 1023, 0, 127);
 
//****************************************************** 1
    if(abs(chanVal_1 - oldChanVal_1) > 1){  
      Serial.write(0xB0);
      //Serial.print("::");
      Serial.write(1);
      //Serial.print("::");
      Serial.write(chanVal_1);
    }
//****************************************************** 2    
    if(abs(chanVal_2 - oldChanVal_2) > 1){  
      Serial.write(0xB0);
      //Serial.print("::");
      Serial.write(2);
      //Serial.print("::");
      Serial.write(chanVal_2);
    }
//****************************************************** 3    
    if(abs(chanVal_3 - oldChanVal_3) > 1){  
      Serial.write(0xB0);
      //Serial.print("::");
      Serial.write(3);
      //Serial.print("::");
      Serial.write(chanVal_3);
    }
 //****************************************************** 4  
    if(abs(chanVal_4 - oldChanVal_4) > 1){
      Serial.write(0xB0);
      Serial.write(4);
      Serial.write(chanVal_4);
    }
 
    oldChanVal_1 = chanVal_1;
    oldChanVal_2 = chanVal_2;
    oldChanVal_3 = chanVal_3;
    oldChanVal_4 = chanVal_4;
 
  delay(64);
}

Подключил 4 переменных резистора 10кОм и получил беду в виде их низкой чувствительности при плавном вращении. Если кручу резко, работают отлично. Если ооочень плавно кручу, то вообще не реагируют. Могу открая до края мееедленно крутить и ни одного сигнала не передастся. 

Подскажите пожалуйста где беда? Заранее спасибо.

 

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Строки 54-57 нужно раскидать по соответствующим блокам, обозначенным 1, 2, 3, 4. Иначе при медленном вращении изменение сигнала не превышает 1 за цикл, но ты помещаешь новое значение в oldChanVal и изменение не накапливается.

Nareg
Offline
Зарегистрирован: 24.12.2016

Спасибо большое! Но частично проблема осталась. Иногда перескакивает через 2 значения, пробовал уменьшать задержку, но это не помогло, может ли это быть погрешностью самих резисторов?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Не совсем понятно, что значит "перескакивают", но если я правильно понял, oldChanVal_1 нужно не присваивать chanVal_1, а инкрементировать на величину шага (например, на 2).

 

PS. И - да, шумы резисторов еще никто не отменял. Можно попытаться уменьшить, зашунтировав конденсатором.

ВН
Offline
Зарегистрирован: 25.02.2016

Nareg Беда в том, что ты ыводишь дельту, т.е. изменение за весьма кототкое время, а при медленном вращении эта дельта меньше 1 и в результате ничего не выводится. 

Очень равномерно вращать рукой не получится, поэтому возможно получение любых значений.

 

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

возможно подразумевался энкодер, а применен переменный резистор.

 

uragan
Offline
Зарегистрирован: 23.02.2015

Задержка стоит не в том месте.

Nareg
Offline
Зарегистрирован: 24.12.2016

Задача простая) midi контроллер. Пробовал даже из встроенных скетчей midi-usb, всё равно скачет зараза, купил другие переменные резисторы, та же песня.

#include <MIDI.h>
#include "Controller.h"

/*************************************************************
  MIDI CONTROLLER

  by Notes and Volts
  www.notesandvolts.com

  Version 1.2 **Arduino UNO ONLY!**
 *************************************************************/

MIDI_CREATE_DEFAULT_INSTANCE();

//************************************************************
//***SET THE NUMBER OF CONTROLS USED**************************
//************************************************************
//---How many buttons are connected directly to pins?---------
byte NUMBER_BUTTONS = 0;
//---How many potentiometers are connected directly to pins?--
byte NUMBER_POTS = 1;
//---How many buttons are connected to a multiplexer?---------
byte NUMBER_MUX_BUTTONS = 0;
//---How many potentiometers are connected to a multiplexer?--
byte NUMBER_MUX_POTS = 0;
//************************************************************

//***ANY MULTIPLEXERS? (74HC4067)************************************
//MUX address pins must be connected to Arduino UNO pins 2,3,4,5
//A0 = PIN2, A1 = PIN3, A2 = PIN4, A3 = PIN5
//*******************************************************************
//Mux NAME (OUTPUT PIN, , How Many Mux Pins?(8 or 16) , Is It Analog?);


//Mux M1(10, 16, false); //Digital multiplexer on Arduino pin 10
//Mux M2(A5, 8, true); //Analog multiplexer on Arduino analog pin A0
//*******************************************************************


//***DEFINE DIRECTLY CONNECTED POTENTIOMETERS************************
//Pot (Pin Number, Command, CC Control, Channel Number)
//**Command parameter is for future use**

Pot PO1(A0, 0, 1, 1);
Pot PO2(A1, 0, 10, 1);
Pot PO3(A2, 0, 22, 1);
Pot PO4(A3, 0, 118, 1);
//Pot PO5(A4, 0, 30, 1);
//Pot PO6(A5, 0, 31, 1);
//*******************************************************************
//Add pots used to array below like this->  Pot *POTS[] {&PO1, &PO2, &PO3, &PO4, &PO5, &PO6};
Pot *POTS[] {&PO1};
//*******************************************************************


//***DEFINE DIRECTLY CONNECTED BUTTONS*******************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button BU1(2, 0, 60, 1, 5 );
//Button BU2(3, 0, 61, 1, 5 );
//Button BU3(4, 0, 62, 1, 5 );
//Button BU4(5, 0, 63, 1, 5 );
//Button BU5(6, 0, 64, 1, 5 );
//Button BU6(7, 0, 65, 1, 5 );
//Button BU7(8, 1, 64, 1, 5 );
//Button BU8(9, 2, 64, 1, 5 );
//*******************************************************************
//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {};
//*******************************************************************


//***DEFINE BUTTONS CONNECTED TO MULTIPLEXER*************************
//Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button MBU1(M1, 0, 0, 70, 1, 5);
//Button MBU2(M1, 1, 1, 71, 1, 5);
//Button MBU3(M1, 2, 2, 72, 1, 5);
//Button MBU4(M1, 3, 0, 73, 1, 5);
//Button MBU5(M1, 4, 0, 74, 1, 5);
//Button MBU6(M1, 5, 0, 75, 1, 5);
//Button MBU7(M1, 6, 0, 76, 1, 5);
//Button MBU8(M1, 7, 0, 77, 1, 5);
//Button MBU9(M1, 8, 0, 78, 1, 5);
//Button MBU10(M1, 9, 0, 79, 1, 5);
//Button MBU11(M1, 10, 0, 80, 1, 5);
//Button MBU12(M1, 11, 0, 81, 1, 5);
//Button MBU13(M1, 12, 0, 82, 1, 5);
//Button MBU14(M1, 13, 0, 83, 1, 5);
//Button MBU15(M1, 14, 0, 84, 1, 5);
//Button MBU16(M1, 15, 0, 85, 1, 5);
//*******************************************************************
////Add multiplexed buttons used to array below like this->  Button *MUXBUTTONS[] {&MBU1, &MBU2, &MBU3, &MBU4, &MBU5, &MBU6.....};
Button *MUXBUTTONS[] {};

//*******************************************************************


//***DEFINE POTENTIOMETERS CONNECTED TO MULTIPLEXER*******************
//Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
//**Command parameter is for future use**

//Pot MPO1(M2, 0, 0, 1, 1);
//Pot MPO2(M2, 1, 0, 7, 1);
//Pot MPO3(M2, 2, 0, 50, 1);
//Pot MPO4(M2, 3, 0, 55, 2);
//Pot MPO5(M2, 4, 0, 50, 1);
//Pot MPO6(M2, 5, 0, 55, 2);
//Pot MPO7(M2, 6, 0, 50, 1);
//Pot MPO8(M2, 7, 0, 55, 2);
//Pot MPO9(M2, 8, 0, 50, 1);
//Pot MPO10(M2, 9, 0, 55, 2);
//Pot MPO11(M2, 10, 0, 50, 1);
//Pot MPO12(M2, 11, 0, 55, 2);
//Pot MPO13(M2, 12, 0, 50, 1);
//Pot MPO14(M2, 13, 0, 55, 2);
//Pot MPO15(M2, 14, 0, 50, 1);
//Pot MPO16(M2, 15, 0, 55, 2);
//*******************************************************************
//Add multiplexed pots used to array below like this->  Pot *MUXPOTS[] {&MPO1, &MPO2, &MPO3, &MPO4, &MPO5, &MPO6.....};
Pot *MUXPOTS[] {};
//*******************************************************************


void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
}

//*****************************************************************
void updateButtons() {

  // Cycle through Button array
  for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
    byte message = BUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (BUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (BUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 1;
          }
          else if (BUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }

    //  Button is not pressed
    if (message == 1) {
      switch (BUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}
//*******************************************************************
void updateMuxButtons() {

  // Cycle through Mux Button array
  for (int i = 0; i < NUMBER_MUX_BUTTONS; i = i + 1) {

    MUXBUTTONS[i]->muxUpdate();
    byte message = MUXBUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (MUXBUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 1;
          }
          else if (MUXBUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }
    //  Button is not pressed
    if (message == 1) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}
//***********************************************************************
void updatePots() {
  for (int i = 0; i < NUMBER_POTS; i = i + 1) {
    byte potmessage = POTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(POTS[i]->Pcontrol, potmessage, POTS[i]->Pchannel);
  }
}
//***********************************************************************
void updateMuxPots() {
  for (int i = 0; i < NUMBER_MUX_POTS; i = i + 1) {
    MUXPOTS[i]->muxUpdate();
    byte potmessage = MUXPOTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(MUXPOTS[i]->Pcontrol, potmessage, MUXPOTS[i]->Pchannel);
  }
}

void loop() {
  if (NUMBER_BUTTONS != 0) updateButtons();
  if (NUMBER_POTS != 0) updatePots();
  if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
  if (NUMBER_MUX_POTS != 0) updateMuxPots();
}

Этот попробовал, тоже значения спонтанные (1,2,5,7,11 и т.д.) :(

Nareg
Offline
Зарегистрирован: 24.12.2016

Однако да, вернулся к старому скетчу

int chanVal_1;
int oldChanVal_1;
 
void setup(){
  Serial.begin(31250);  
}
 
void loop(){
    chanVal_1 = map(analogRead(A0), 0, 1023, 0, 127);

    if(abs(chanVal_1 - oldChanVal_1) > 0.5){
      Serial.write(0xB0);
      //Serial.print("::");
      Serial.write(1);
      //Serial.print("::");
      Serial.write(chanVal_1);
      oldChanVal_1 = chanVal_1;
    }
       delay(1);
}

Шаг поставил 0,5. Это помогло, но, если крутить аккуратно, то значение начинает скакать туда сюда, или же после выравнивания значения и отпускания ручки, всё равно продолжает передаваться сигнал, будто резистор ещё вращается. Что же делать? Как же быть?:)

UPD:

Поменял на 0,9. Теперь изредка попадаю на промежуточное значение. Но всё равно попадаю.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Это в перлы!

Nareg пишет:

int chanVal_1;

int oldChanVal_1;
 
...
    if(abs(chanVal_1 - oldChanVal_1) > 0.5){

nik182
Offline
Зарегистрирован: 04.05.2015

Если взять вот такой http://www.chipdip.ru/product/3590s-2-104/ резистор за более 1000 руб, тогда можно попробовать поймать один бит изменения оцифровки при повороте ручки на 3 градуса. Правда после долгого и упорного сглаживания результата.

И прочитайте, наконец, чем целые числа в компьютере отличаются от тех, которые записываются с десятичной точкой.  

Nareg
Offline
Зарегистрирован: 24.12.2016

Точно! Только и всего! Всё что было нужно это высмеять меня и предложить купить деталь в которой сами не уверены:)

Хвала человеку который придумал форумы:) Они так помагают.

Спасибо за помощь парни!

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

Технические форумы такие технические форумы.

P.S. за пару советов действительно спасибо. Вроде кондёра и с кодом.

С Новым Годом всех и Рождеством! Всем хороших праздников, а мне бан:)

nik182
Offline
Зарегистрирован: 04.05.2015

С наступающим это да, с наступающим!
Резистор такой у меня есть. Позволяет устанавливать напряжение с точностью до пятого знака. А теперь включаем мозги и следим за последовательностью рассуждений. Разрядность АЦП 10 бит - 1024 отсчёта. После функции мап количество отсчётов уменьшится в 8 раз и изменение переменной (помним что она челое число) будет происходить не меньше чем на единицу при изменении значения АЦП на 8. Кроме того, при оцифровке получамое значение не стабильно в силу целого ряда причин. Поэтому можно получить изменение ваших переменных даже без вращения резистора. Получаемое значение целое. Поэтому сравнение с любой(!) величиной меньше единицы равнозначно сравнению с нулём, только отъедает огромное количество памяти и времени процессора. Сравнение с нулём абсолютной разности тоже лишнее действие. Достаточно сравнить старое и новое значение. Из всего сказанного простые выводы для улучшения скетча. Надо сглаживать получаемые от АЦП значения и только потом применять функцию мап. Сравнивать старое и новое значение надо с помощью !=. В этом случае вы будете получать новые значения при любой скорости вращения резистора. Но при этом всегда найдётся его положение при котором будет идти изменение сигнала на единицу без вращения. Избавиться от этого можно увеличив в вашем скетче сравниваемую величину до двойки или больше. Но тогда присвоение старому значению АЦП надо внести под соответствующий if что бы получить изменение при медленном вращении.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

nik182 пишет:

Если взять вот такой http://www.chipdip.ru/product/3590s-2-104/ резистор за более 1000 руб

...

https://ru.aliexpress.com/item/Free-Shipping-5pcs-3590S-2-103L-3590S-2-1...

Оно?