Midi клавиатура, проблема с мультиплексором 4051

Тема в разделе "Arduino & Shields", создана пользователем kR1P, 10 май 2017.

  1. kR1P

    kR1P Нерд

    Здравствуйте, уважаемые форумчане! С ардуино опыта работы мало. Решил сделать миди клавиатуру из кнопок, так как цифровых входов Уно может не хватать решил использовать мультиплексор cd4051be. Сначала написал программу без использования мультиплексора, подключил кнопки, все работает, далее написал программу с использованием мультиплексора, подключил кнопки и мультиплексор и ничего не работает, кнопки как бы и нажимаются, но вот сигналов никаких нет и никуда они не идут:eek: Прошу помочь с написанием кода с мультиплексором и до конца разобраться как он вообще работает.
    Сам код:
    Код (C++):
    #define AnMltplx1 A0
    #define s0 2
    #define s1 3
    #define s2 4

    //int r0 = 0;

    int myButtonPin[7] = {0};
    const int myMidiNotes[] = {0x3C,0x3E,0x40,0x41,0x43,0x45,0x47,0x48};

    int NoteON[] = {false,false,false,false,false,false,false,false};
    int NoteOFF[] = {false,false,false,false,false,false,false,false};

    //int iAn0Val;

    int mux = 0;

    void setup()
    {
    pinMode(s0, OUTPUT);
    pinMode(s1, OUTPUT);
    pinMode(s2, OUTPUT);


    Serial.begin(57600);
      for(int i=0;i<7;i++)
      {
      pinMode(myButtonPin[mux], OUTPUT);
      }
    }
    void loop()
    {
    /*int iAn0ValPrev = iAn0Val; // previous value
    iAn0Val = analogRead(A0)/8; // Divide by 8 to get range of 0-127 for midi
    analogval(1,iAn0Val,iAn0ValPrev); //TX value  
    */

    for (mux=0;mux<=7;mux++)
    {
    myButtonPin[mux] = analogRead(AnMltplx1);
      for(int i=0;i<7;i++)
      {
        if (myButtonPin[mux] == HIGH && NoteON[i] == false)
        {
         noteSend(0x90, myMidiNotes[i], 0x7F);
         NoteON[i] = true;
         NoteOFF[i] = false;
        }
        else if (myButtonPin[mux] == HIGH && NoteON[i] == true)
        {
         noteSend(0x00, myMidiNotes[i], 0x7F);
         NoteON[i] = true;
         NoteOFF[i] = false;
        }
        else if (myButtonPin[mux] == LOW && NoteOFF[i] == false)
        {
         noteSend(0x80, myMidiNotes[i], 0x00);
         NoteON[i] = false;
         NoteOFF[i] = true;
        }
      }
    }
    }

    void mltpx1()
    {
      for (mux=0;mux<=7;mux++)
      {
        digitalWrite(s0, bitRead(mux,0));
        digitalWrite(s1, bitRead(mux,1));
        digitalWrite(s2, bitRead(mux,2));
        myButtonPin[mux] = analogRead(AnMltplx1);
      }
    }

    void noteSend(int cmd, int pitch, int velocity)
    {
       Serial.write(cmd);
       Serial.write(pitch);
       Serial.write(velocity);
    }
     
  2. serg_admin

    serg_admin Гик

  3. kR1P

    kR1P Нерд

    Просмотрел данную тему, но ничего связанного с мультиплексором не нашел. Меня интересует один вопрос. Как например происходит считывание состояния кнопки(в программе), подключенной к мультиплексору?
     
  4. mcureenab

    mcureenab Гуру

    Нужно вызвать функцию mltpx1() перед for.
    Код (C++):

    // Сюда воткнуть mltpx1()
    for (mux=0;mux<=7;mux++)
    {
    myButtonPin[mux] = analogRead(AnMltplx1); // Это не нужно.
     
    Она заполнит массив myButtonPin состояниями входов мультиплексора.

    Строка myButtonPin[mux] = analogRead(AnMltplx1); тут лишняя. Она всё испортит.

    Это бред:
    Код (C++):
      for(int i=0;i<7;i++)
      {
      pinMode(myButtonPin[mux], OUTPUT);
      }
     
    Последнее редактирование: 11 май 2017
    kR1P нравится это.
  5. mcureenab

    mcureenab Гуру

    Используйте локальные переменные:


    Код (C++):
    void mltpx1()
    {
      for (uint8_t mux=0;mux<=7;mux++)
      {
        digitalWrite(s0, bitRead(mux,0));
        digitalWrite(s1, bitRead(mux,1));
        digitalWrite(s2, bitRead(mux,2));
        myButtonPin[mux] = analogRead(AnMltplx1); // Это не HIGH и не LOW!!! Это число от 0 - 1023.
      }
    }
     
     
  6. mcureenab

    mcureenab Гуру

    Определитель что вам надо - аналоговый или цифровой ввод.
    Если
    Код (C++):
    myButtonPin[mux] = analogRead(AnMltplx1); // Это не HIGH и не LOW!!! Это число от 0 - 1023.
     
    то это работать не будет
    Код (C++):
    myButtonPin[mux] == HIGH
    Для

    Код (C++):
    myButtonPin[mux] == HIGH
    нужно

    Код (C++):
    myButtonPin[mux] = digitalRead(AnMltplx1); // Возвращает HIGH или LOW
     
     
    kR1P нравится это.
  7. kR1P

    kR1P Нерд

    Спасибо, что отозвались. Да хотелось бы использовать цифровые входы\выходы. Исправил все о чем написали, но пока все то же самое, никаких сигналов. Я так понимаю проблема сидит где-то в цикле, буду пробовать менять что-то в цикле, не отказался бы от вашей помощи.
    Пока что код такой:
    Код (C++):
    #define AnMltplx1 7
    #define s0 2
    #define s1 3
    #define s2 4

    int myButtonPin[7] = {0};
    const int myMidiNotes[] = {0x3C,0x3E,0x40,0x41,0x43,0x45,0x47,0x48};

    int NoteON[] = {false,false,false,false,false,false,false,false};
    int NoteOFF[] = {false,false,false,false,false,false,false,false};

    void setup()
    {
    pinMode(s0, OUTPUT);
    pinMode(s1, OUTPUT);
    pinMode(s2, OUTPUT);
    Serial.begin(57600);
    }

    void mltpx1()
    {
      for (uint8_t i=0;i<=7;i++)
      {
        digitalWrite(s0, bitRead(i,0));
        digitalWrite(s1, bitRead(i,1));
        digitalWrite(s2, bitRead(i,2));
        myButtonPin[i] = digitalRead(AnMltplx1);
      }
    }

    void loop()
    {
    for (uint8_t i=0;i<=7;i++)
      {
        if (myButtonPin[i] == HIGH && NoteON[i] == false)
        {
         noteSend(0x90, myMidiNotes[i], 0x7F);
         NoteON[i] = true;
         NoteOFF[i] = false;
        }
        else if (myButtonPin[i] == HIGH && NoteON[i] == true)
        {
         noteSend(0x00, myMidiNotes[i], 0x7F);
         NoteON[i] = true;
         NoteOFF[i] = false;
        }
        else if (myButtonPin[i] == LOW && NoteOFF[i] == false)
        {
         noteSend(0x80, myMidiNotes[i], 0x00);
         NoteON[i] = false;
         NoteOFF[i] = true;
        }
      }
    }

    void noteSend(int cmd, int pitch, int velocity)
    {
       Serial.write(cmd);
       Serial.write(pitch);
       Serial.write(velocity);
    }
     
  8. mcureenab

    mcureenab Гуру

    Нет вызова mltpx1();

    Код (C++):
    void loop()
    {
        mltpx1();  // Нужно вызывать перед for
        for (uint8_t i=0;i<=7;i++)
     
     
    kR1P нравится это.
  9. kR1P

    kR1P Нерд

    Спасибо вам большое за помощь, все заработало, написал внутри цикла for(мультиплексора), цикл for(для нот и обработки нажатий кнопки) и все теперь работает
    Вот рабочий код:
    Код (C++):
    #define AnMltplx1 7
    #define s0 2
    #define s1 3
    #define s2 4

    int myButtonPin[8] = {0};
    const int myMidiNotes[] = {0x3C,0x3E,0x40,0x41,0x43,0x45,0x47,0x48};

    int NoteON[] = {false,false,false,false,false,false,false,false};
    int NoteOFF[] = {false,false,false,false,false,false,false,false};

    void setup()
    {
    pinMode(s0, OUTPUT);
    pinMode(s1, OUTPUT);
    pinMode(s2, OUTPUT);
    Serial.begin(57600);
    }

    void mltpx1()
    {
      for (uint8_t i=0;i<=7;i++)
      {
        digitalWrite(s0, bitRead(i,0));
        digitalWrite(s1, bitRead(i,1));
        digitalWrite(s2, bitRead(i,2));
        myButtonPin[i] = digitalRead(AnMltplx1);
      }
    }

    void loop()
    {
    mltpx1();
    for (uint8_t i=0;i<=7;i++)
      {
        for(int note=0;note<=7;note++)
        {
        if (myButtonPin[note] == HIGH && NoteON[note] == false)
        {
         noteSend(0x90, myMidiNotes[note], 0x7F);
         NoteON[note] = true;
         NoteOFF[note] = false;
        }
        else if (myButtonPin[note] == HIGH && NoteON[note] == true)
        {
         noteSend(0x00, myMidiNotes[note], 0x7F);
         NoteON[note] = true;
         NoteOFF[note] = false;
        }
        else if (myButtonPin[note] == LOW && NoteOFF[note] == false)
        {
         noteSend(0x80, myMidiNotes[note], 0x00);
         NoteON[note] = false;
         NoteOFF[note] = true;
        }
        }
      }
    }

    void noteSend(int cmd, int pitch, int velocity)
    {
       Serial.write(cmd);
       Serial.write(pitch);
       Serial.write(velocity);
    }
     
  10. ostrov

    ostrov Гуру

    Я так понимаю, вы используете MIDI вход и какой то синтезатор? А как заставить Ардуину прикидываться MIDI устройством чернз USB не в курсе? Например, клавиатурой.
     
  11. kR1P

    kR1P Нерд

    Данные передаются через юсб в последовательный порт, после чего конвертируются утилитой Serial MIDI Converter, в дальнейшем планирую заняться прошивкой atmega16u2, как в проекте HIDUINO, в итоге ардуино должна будет определяться в системе не как последовательный порт, а например как HID-устройство или Звуковое устройство.
     
  12. ostrov

    ostrov Гуру

    Тоже хочу такое. Вот у меня midi-клавиатура есть от M-Audio, хорошо бы свой контроллер с подобными свойствами изготовить, но пока не пойму как стыкуются эти устройства с ПК.
     
  13. kR1P

    kR1P Нерд

    Могу так же посоветовать программу MIDI-OX чтобы отслеживать посылаемые миди данные. Из предыдущего сообщения забыл добавить что данные идут через конвертер Serial MIDI Converter, далее эти данные идут в виртуальный миди порт(loopMIDI или midiYoke), а далее их можно отследить в MIDI-OX ну либо уже в любом секвенсоре
     
  14. ostrov

    ostrov Гуру

    Serial MIDI Converter это аппаратное устройство? Я вот такое заказал, это оно?
     
  15. sslobodyan

    sslobodyan Гик

    Ostrov, посмотрите в сторону ардуины на stm32. На гитхабе есть midi_to_usb для нее. Как раз простые команды там реализованы. Нет вроде бы только sysex. Где-то здесь http://www.stm32duino.com/viewtopic.php?t=308
     
    ostrov нравится это.
  16. kR1P

    kR1P Нерд

    ostrov нравится это.
  17. ostrov

    ostrov Гуру

    Спасибо. Мне сейчас главное понять что в этой цепи аппаратное а что программное. Что нужно из железок еше кроме usb кабеля.У меня на руках Арлуина (есть и stm32), кабель, ноут с Аблетоном и немного интернета. Все остальное дома, очень далеко. Получится ли пощупать в таком виде что либо? Буду почитать и попробовать.
     
    Последнее редактирование: 11 май 2017
  18. kR1P

    kR1P Нерд

    Ну наверное это только кнопки, резисторы и перемычки, но можно и без них чтобы просто разобраться как миди сигнал идет, хватит usb кабеля и ардуины
     
  19. ostrov

    ostrov Гуру

    Нихрена не запускается. Конвертер уну видит, та подаёт команды на запуск нот периодически, на конвертере загорается огонек, дальше никуда ничего не уходит. MIDI-OX говорит что миди устройств не обнаружено, не говоря уже про Аблетон, в списке миди устройств которого ничего похожего на ОХ нет. Куда копать?
     
  20. ostrov

    ostrov Гуру

    Дополнение. Звук с конвертера идет, пианино играет правильно. Как дальше этот сигнал куда либо перенаправить? Желательно сразу в Аблетон, но можно и через что нибудь.