Skocz do zawartości

Pomocna odpowiedź

Napisano

Cześć!

Ostatnio starałem się zbudować układ, za pomocą którego, mógłbym otrzymywać sygnały MIDI z mojego pianina. Zbudowałem układ według tego poradnika:

Dodam, że układ działa. Jednak nie mam pojęcia, jak napisać program, który umożliwiłby mi odczytywanie każdego klawisza na pianinie i np. przypisania temu klawiszowi jakiejś funkcji. 

Z góry dziękuję za pomoc 😀

@patrinio, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.

27 minut temu, patrinio napisał:

Jednak nie mam pojęcia, jak napisać program, który umożliwiłby mi odczytywanie każdego klawisza na pianinie i np. przypisania temu klawiszowi jakiejś funkcji. 

Pytasz o program bezpośrednio na Arduino czy chciałbyś napisać np. program na PC, który będzie sterowany przez Arduino podłączone do piania?

Bezpośrednio na Arduino, używam biblioteki z opisu filmu <MIDI.h>.

Konkretnie, chciałbym aby po naciśnięciu klawisza na pianinie zapali się odpowiadająca mu dioda z paska LED-ów adresowalnych 😉

Arduino będzie przyklejone od dołu pianina i zasilane z kostki 12V.

@patrinio a na czym dokładnie utknąłeś? Masz jakikolwiek działający program? Co on robi? Jeśli komunikacja działa to przypisanie klawiszy do LEDów nie powinno stanowić żadnego problemu.

Mam 2 programy; działający i nie :).

Pierwszy (działający) jedynie wykrywa naciśnięty klawisz:

#include <MIDI.h>  
#define LED 13

//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  pinMode (LED, OUTPUT); 
  MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
  // OMNI sets it to listen to all channels.. MIDI.begin(2) would set it 
  // to respond to notes on channel 2 only.
  MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
  // tells the Midi Library which function you want to call when a NOTE ON command
  // is received. In this case it's "MyHandleNoteOn".
  MIDI.setHandleNoteOff(MyHandleNoteOff); // This command tells the Midi Library 
  // to call "MyHandleNoteOff" when a NOTE OFF command is received.
}

void loop() { 
  MIDI.read(); // Continuously check if Midi data has been received.
}

// MyHandleNoteON is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) { 
  digitalWrite(LED,HIGH);  //Turn LED on
}

// MyHandleNoteOFF is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOff(byte channel, byte pitch, byte velocity) { 
  digitalWrite(LED,LOW);  //Turn LED off
}

 

I drugi (nie działający), który miał wykrywać i wypisywać wciśnięty klawisz:

#include <MIDI.h>  

#define LED 13    

MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  pinMode (LED, OUTPUT); 
  MIDI.begin(MIDI_CHANNEL_OMNI); 
  MIDI.setHandleNoteOn(MyHandleNoteOn); 
  MIDI.setHandleNoteOff(MyHandleNoteOff); 
  
  int velocity = 0;
  int channel = 0;
}

void loop() { 
  MIDI.read(); 
}

//On
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) { 
  digitalWrite(LED,HIGH);  
  int note = 0;
  velocity = 0;
  channel = 0;
  
  if(MIDI.read()){
    //write variable
    note = MIDI.getData1();
    velocity = MIDI.getData2();
    channel = MIDI.getChannel();
    //print variables
    Serial.println(String("Note on: ch=") + channel + String(", note=") + note + String(", velocity") + velocity);
  }
}

//Off
void MyHandleNoteOff(byte channel, byte pitch, byte velocity) { 
  digitalWrite(LED,LOW);  
}

 

Moim problemem w drugim kodzie są jakieś (chyba) zakłócenia w komunikacji (tak mi się wydaje, ale nie jestem pewien). Po włączeniu monitora ciągle wypisuje on znaki zapytania, a po wciśnięciu klawisza na pianinie, nie wypisuje on czysto kodu (nie tak jak powinien, trochę jakby był ustawiony na złej częstotliwości). Nie mam pojęcia jak 'czysto' wyciągnąć naciśniętą nutę.

(edytowany)

@Treker po dodaniu "Serial.begin(9600); ",ustawieniu monitora na 9600 i podłączeniu pianina, w dalszym ciągu komunikacja jest zakłócona:

"⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮``⸮⸮⸮ha⸮⸮⸮⸮⸮⸮#a⸮⸮⸮⸮⸮ha⸮⸮⸮qa⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮`h⸮⸮aa⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮"

Coś takiego wyskakuje po naciskaniu tego samego klawisza wielokrotnie + z każdą pętlą, na monitorze,  dopisywany jest znak zapytania.

 Czy możliwe jest to, że ta biblioteka MIDI nie rozumie sygnału MIDI z mojego pianina (YAMAHA Arius YDP-140)?

Edytowano przez patrinio

@Belferek chyba nie o to chodzi, ale dzięki za pomoc ;). Aktualnie udało mi się wywnioskować, że podczas komunikacji MIDI nie da się używać monitora. Element :

void loop() { 
  MIDI.read(); 
}

generuje te tajemnicze znaki zapytania. Postanowiłem zmodyfikować kod:

#include <MIDI.h> 

#define LED 13  

int piB = 0 + 19;           //pitch (begin)
int piE = 88 + 19;          //pitch (end)

MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  pinMode (LED, OUTPUT);
  MIDI.begin(MIDI_CHANNEL_OMNI); 
  MIDI.setHandleNoteOn(MyHandleNoteOn); 
  MIDI.setHandleNoteOff(MyHandleNoteOff);
}

void loop() { 
  MIDI.read(); 
}

void MyHandleNoteOn(byte channel, byte pitch, byte velocity) { 
  while (piB <= piE){
    piB++;
    int Pitch = MIDI.getData1();
    int Velocity = MIDI.getData2();
    int Channel = MIDI.getChannel();
    if (Pitch == piB){
      digitalWrite(LED,HIGH);  
    }
  }
  piB = 0;
}

void MyHandleNoteOff(byte channel, byte pitch, byte velocity) { 
  digitalWrite(LED,LOW);  //Turn LED off
}

Z jego pomocą można już wykryć każdy naciśnięty klawisz na pianinie. Tylko mam wątpliwości, czy ten kod będzie równie skuteczny dla większej ilości naciśniętych klawiszy. 

W jaki sposób powinienem teraz wyciągnąć każdy naciśnięty klawisz i zaświecić odpowiednią diodę LED (adresowalną)? I czy te ledy będą dobre?

Dziękuję za pomoc 😉

@patrinio taka taśma powinna być dobra, ale pamiętaj o zadbaniu o odpowiednie zasilanie, bo nie możesz podłączyć jej bezpośrednio pod 5V z Arduino.

1 godzinę temu, patrinio napisał:

W jaki sposób powinienem teraz wyciągnąć każdy naciśnięty klawisz i zaświecić odpowiednią diodę LED (adresowalną)?

Rozpisz sobie warunki dla różnych warto zmiennych Pitch i tyle 🙂

@Treker  czy podłączenie takiej taśmy z 88 LEDami (lub 120) pod 12V nie uszkodzi LEDów i wystarczy? Czy mogę użyć zwykłego zasilacza do Arduino? 

Wydaje mi się, że napisałem już poprawny kod, ale nie jestem pewien. Czekam teraz na LEDy ;>

Wszystko zależy od konkretnej taśmy - każda ma inne parametry pracy. Taśmy WS2812B zasila się raczej z 5V i taka jest informacja na aukcji, którą linkowałeś wcześniej. Jeśli podłączysz taką taśmę pod 12V to uszkodzisz diody. Musisz zaopatrzyć się w odpowiedni zasilacz 5V, potrzebujesz około 15W na każdy metr taśmy.

  • 3 tygodnie później...

@Treker mam problem (chyba ze strony zasilacza). Po podłączeniu wszystkiego (z użyciem zasilacza) i włączeniu arduino, ledy kompletnie inaczej się zapalają niż powinny. Po podłączeniu ledów, zamiast do zasilacza, do wyjścia arduino 3.3V wszystko działa normalnie.

Podobnie, po podłączeniu paska 8 LED, z użyciem zasilacza i uruchomieniu kodu (poniżej),  w ledach pojawiają się 'zakłócenia'.

Kod:

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel x = Adafruit_NeoPixel(8, A0, NEO_GRB + NEO_KHZ800);

int R = 0;
int G = 0;
int B = 0;

int setColors(int noLeds){
    for(int i=0; i<noLeds; i++){
    x.setPixelColor(i, x.Color(R, G, B));
    }
    x.show();

    return 0;
}

void setup() {
  // put your setup code here, to run once:
  x.begin();
  x.show();
  x.setBrightness(50);
}

void loop() {
  // put your main code here, to run repeatedly:
  for(int i=0; i<3; i++){
    for(int i=0; i<255; i++){
      R++;
      setColors(8);
      delay(10);
    }

    if(B!=0){
      for(int i=0; i<255; i++){
        B--;
        setColors(8);
        delay(10);
      }
    }

    for(int i=0; i<255; i++){
      G++;
      setColors(8);
      delay(10);
    }

    for(int i=0; i<255; i++){
      R--;
      setColors(8);
      delay(10);
    }

    for(int i=0; i<255; i++){
      B++;
      setColors(8);
      delay(10);
    }

    for(int i=0; i<255; i++){
      G--;
      setColors(8);
      delay(10);
    }
  }
}

 

'Zakłócenia' w ledach:

https://drive.google.com/open?id=1QA2Wg8q1anRekhdTkNUD7RIxWk9jZTti

Działanie programu (poprawne) po podłączeniu do gniazda 3.3V:

https://drive.google.com/open?id=1CV-jUsaqsalOMdBLTAd84nwKSHKiUk68

Działanie programu (niepoprawne) po podłączeniu do zasilacza:

https://drive.google.com/open?id=1Yyemh7ctmwDty9uMz2tqsFLr7tYMRuwt

Kod programu:

#include <MIDI.h> 
#include <Adafruit_NeoPixel.h>


Adafruit_NeoPixel pStrip = Adafruit_NeoPixel(88, A0, NEO_GRB + NEO_KHZ800);     //sets for LED strip 
                                                          //88 LEDs and A0 pin in arduino

int colorR = 0;             //set amount of red
int colorG = 255;             //set amount of green
int colorB = 0;             //set amount of blue

int pBegin = 21;              //pitch (first)       //in my case 21
int pEnd = 88 + pBegin;       //pitch (last)         //in my case 108
int pNote = 0;                //piano note

MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  MIDI.begin(MIDI_CHANNEL_OMNI); 
  MIDI.setHandleNoteOn(MyHandleNoteOn); 
  MIDI.setHandleNoteOff(MyHandleNoteOff);

  pStrip.begin();
  pStrip.show();
  pStrip.setBrightness(50);

  pNote = pBegin;
}

void loop() { 
  MIDI.read(); 
}

void MyHandleNoteOn(byte channel, byte pitch, byte velocity) { 
  while (pNote <= pEnd){
    int Pitch = MIDI.getData1();
    int Velocity = MIDI.getData2();
    int Channel = MIDI.getChannel();
    
    if (Pitch == pNote){          //take the note from pitch
      
      pStrip.setPixelColor(pNote - 21 , pStrip.Color(colorR,colorG,colorB));      //on i-1 LED set white color
      pStrip.show();
    }
    
    pNote++;
  }
  pNote = pBegin;
}

void MyHandleNoteOff(byte channel, byte pitch, byte velocity) {       //if ANY of the notes has been turned off
  while (pNote <= pEnd){
    int Pitch = MIDI.getData1();
    int Velocity = MIDI.getData2();
    int Channel = MIDI.getChannel();
    if (Pitch == pNote){        //take the note from Pitch

      pStrip.setPixelColor(pNote - 21 , pStrip.Color(0,0,0));      //on i-1 LED set 'black' color
      pStrip.show();
    }
    pNote++;
  }
  pNote = pBegin;
}

 

Z góry dziękuję za pomoc.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...