[130] MIDI - język nie tylko instrumentów cz. 6

[130] MIDI - język nie tylko instrumentów cz. 6

Jak pisałem w poprzednim artykule, dobry przełącznik sceniczny powinien mieć jakiś wskaźnik – najlepiej na diodzie świecącej. Zróbmy więc użytek z diody RGB, którą mam na płytce edukacyjnej TME, a każdy może sobie taką dołożyć. Jest pięć przycisków, więc będzie pięć kolorów: czerwony, pomarańczowy, zielony, niebieski i fioletowy. Są one jednoznaczne, ale jeśli ktoś chciałby mieć siedem przycisków, może zatrudnić jeszcze barwę turkusową i białą. I znowu pokombinujemy, by napisać obsługę kolorów nie na piechotę, jak to robiłem zwykle dotąd, a z wykorzystaniem kolejnych tablic.


const byte iloscKlawiszy = 5;                      // Liczba klawiszy.
const byte adresKlawiatury[] = { 5, 4, 8, 7, 6 };  // Adresy klawiszy.
const byte numerProgramu[] = { 0, 1, 2, 3, 4 };    // Numery programów przyporządkowane klawiszom w powyższej tablicy.
const byte adresRGB[] = { 9, 10, 11 };             // Adresy diod: R, G, B
const bool koloryRGB[5][3] = {                     // Pięć kolejnych stanów poszczególnych diod dla kolejnych numerów programów.
  { 1, 0, 0 },
  { 1, 1, 0 },
  { 0, 1, 0 },
  { 0, 0, 1 },
  { 1, 0, 1 }
};
void setup() {
  Serial.begin(31250);                          // Inicjuj port z nietypową szybkością 31250 bps
  for (byte x = 0; x < iloscKlawiszy; x++)      // Dla każdego pstryczka...
    pinMode(adresKlawiatury[x], INPUT_PULLUP);  // Deklaruj pin jako wejście podciągnięte wewnętrznie do wysokiego stanu.
  for (byte x = 0; x < 3; x++)                  // Dla każdej diody...
    pinMode(adresRGB[x], OUTPUT);               // Deklaruj pin jako wyjście.
  Serial.write(192);                            // Wyślij komunikat "zmień program" na kanale pierwszym.
  Serial.write(numerProgramu[0]);               // Wyślij zerowy numer programu.
  digitalWrite(adresRGB[0], koloryRGB[0][0]);   // Ustaw kolor diod świecących dla zerowego programu.
}
void loop() {
  for (byte x = 0; x < iloscKlawiszy; x++)                // Wybieraj kolejne klawisze.
    if (digitalRead(adresKlawiatury[x]) == HIGH) {        // Jeśli kolejny przycisk został wciśnięty...
      Serial.write(192);                                  // Wyślij komunikat "zmień program" na kanale pierwszym.
      Serial.write(numerProgramu[x]);                     // Wyślij numer programu.
      for (byte y = 0; y < 3; y++)                        // Wybieraj kolejne diody świecące.
        digitalWrite(adresRGB[y], koloryRGB[x][y]);       // Ustaw stany diod według klucza z tablicy.
      delay(50);                                          // Zabezpieczenie na drgające styki.
      while (digitalRead(adresKlawiatury[x]) == HIGH) {}  // Czekaj aż przycisk zostanie puszczony.
      delay(50);                                          // Zabezpieczenie na drgające styki.
    }
}

Podstawą będzie oczywiście szkic poprzedni. Zadeklarujemy dodatkowe dwie tablice: pierwsza adresRGB będzie zawierać adresy pinów, do których podłączę diody świecące – to już znamy, bo jest bliźniacze tablicy z adresami przycisków. Druga koloryRGB będzie nowością, bo to tablica dwuwymiarowa. Pierwszy wymiar ma pięć pozycji, dla każdego pstryczka własną. Drugi – trzy i opisuje stan każdej z diod dla kolejnych pstryczków. Tablice wielowymiarowe muszą mieć zadeklarowane wymiary, więc nie możemy zostawić nawiasów pustych.

const bool koloryRGB[5][3] = {                     // Pięć kolejnych stanów poszczególnych diod dla kolejnych numerów programów.
  { 1, 0, 0 },
  { 1, 1, 0 },
  { 0, 1, 0 },
  { 0, 0, 1 },
  { 1, 0, 1 }
};

Spójrzmy na dane: pierwsza kolumna to kolor czerwony, druga – zielony, trzecia – niebieski. Jadąc od góry możemy sobie zaprogramować kolory dla wszystkich programów. W części wstępnej programu oprócz stworzenia bliźniaczej pętli deklarującej porty ledów, postanowiłem wstępnie wybierać zerowy program i zapalać zerowego reprezentanta. Po co? Żeby cokolwiek po resecie się zaświeciło. Inaczej do momentu zmiany programu mielibyśmy diodę zgaszoną.

W głównej pętli pojawiła się dodatkowa pętla, która wybiera kolor diody RGB dla konkretnego numeru programu. Zauważmy, że zmienna x jest tutaj indeksem, czyli wartością wybranego programu, więc w pętli sterującej diodami musimy powołać do życia kolejną zmienną – y. Teraz y będzie wybierało po kolei diodę czerwoną, zieloną i niebieską, które będą zapalane bądź gaszone według indeksu x.

I to wszystko, po kompilacji całość pracuje jak poprzednio, dodatkowo informując nas o wybranym programie kolorem. To jest już jak najbardziej użyteczny przełącznik, ale uczyńmy jeszcze jeden, korzystając z wyświetlacza siedmiosegmetowego, który mam na płytce. W tym projekcie założenia będą następujące: dwa przyciski: w górę i w dół i 9 zapętlonych programów. Do roboty więc. Na początek odkopię stary szkic, który obsługiwał mi ósemkę siedzącą na brzegu płytki.

#include <Adafruit_MCP23008.h>  // Dołącz bibliotekę sterującą układem MCP23008
Adafruit_MCP23008 ekspander;    // Nadaj układowi nazwę "ekspander".

const byte pstryczekMinus = 4;  // Adres pstryczka zmniejszającego numer programu.
const byte pstryczekPlus = 7;   // Adres pstryczka zwiększającego numer programu.
const byte wyswietlacz[] =      // Tablica zawierająca wzorce znaków wyświetlacza siedmiosegmentowego.
  {
    B0000110,  // 1, połączenia: G-F-E-D-C-B-A
    B1011011,  // 2
    B1001111,  // 3
    B1100110,  // 4
    B1101101,  // 5
    B1111101,  // 6
    B0000111,  // 7
    B1111111,  // 8
    B1101111,  // 9
  };
byte program = 0;  // Numer aktualnego programu.

void setup() {
  Serial.begin(31250);                    // Inicjuj port z nietypową szybkością 31250 bps
  pinMode(pstryczekMinus, INPUT_PULLUP);  // Deklaruj linie pstryczków jako wejścia podciągnięte wewnętrznie do wysokiego stanu.
  pinMode(pstryczekPlus, INPUT_PULLUP);
  ekspander.begin(36);             // Inicjuj bibliotekę sterującą układem MCP23008 pod adresem 0x4
  for (byte x = 0; x < 8; x++)     // Zadeklaruj wszystkich osiem portów...
    ekspander.pinMode(x, OUTPUT);  // Jako wyjścia.
  wyslij();                        // Po resecie ustaw program pierwszy.
}
void loop() {
  if (digitalRead(pstryczekPlus) == HIGH && program < 8) {  // Jeśli wciśnięto plus i numer programu jest mniejszy od 8...
    program++;                                              // Zwiększ numer programu.
    wyslij();                                               // Wyślij numer programu i wyświetl jego stan.
    while (digitalRead(pstryczekPlus) == HIGH) {}           // Czekaj aż przycisk zostanie puszczony.
    delay(50);                                              // Zabezpieczenie na drgające styki.
  }
  if (digitalRead(pstryczekMinus) == HIGH && program > 0) {  // Jeśli wciśnięto minus i program jest większy od 0...
    program--;                                               // Zmniejsz numer programu.
    wyslij();                                                // Wyślij numer programu i wyświetl jego stan.
    while (digitalRead(pstryczekMinus) == HIGH) {}           // Czekaj aż przycisk zostanie puszczony.
    delay(50);                                               // Zabezpieczenie na drgające styki.
  }
}
void wyslij() {                                                   // Procedura zmieniająca program i wyświetlająca jego numer.
  Serial.write(192);                                              // Wyślij komunikat "zmień program" na kanale pierwszym.
  Serial.write(program);                                          // Wyślij numer programu.
  for (byte x = 0; x < 7; x++)                                    // Dla każdego segmentu wyświetlacza...
    ekspander.digitalWrite(x, bitRead(wyswietlacz[program], x));  // Ustawiaj bit według wzorców z tablicy.
  delay(50);                                                      // Zabezpieczenie na drgające styki.
}

Ponieważ mój wyświetlacz jest podłączony do ekspandera I2C, będziemy potrzebować biblioteki obsługi tej kostki. Na ten temat napisałem wiele we wspomnianym artykule, zatem dziś tylko krótko: musimy zadeklarować nazwę dla obiektu ekspander oraz zainicjować wszystkie piny kostki jako wyjścia.

Zadeklaruję także tablicę z wyglądem cyferek – od jedynki do dziewiątki. Wzorce pożyczyłem sobie ze wspomnianego szkicu. W pętli głównej mamy dwa bliźniacze warunki: na sprawdzanie obu przycisków. Akcja jednego wykona się po wciśnięciu plusa i wtedy, gdy numer aktualnego programu nie jest większy od ósemki. W drugim – podobnie, z tym że wciskamy minus i badamy, czy numer programu wciąż jest większy od zera.

Gdy warunki są akceptowalne, zwiększamy bądź zmniejszamy wartość programu, wysyłamy go, a także jego reprezentację na wyświetlacz. Tutaj należy pobrać stan każdego z siedmiu segmentów (siedmiu, gdyż kropkę zignorowałem) i wysłać go zgodnie z wartością bieżącego programu. Dlatego jest to zmienna globalna, dzięki czemu nie trzeba jej przekazywać do podprogramu. I na dziś to już wszystko. Taki przełącznik może być bardzo użyteczny na scenie. A jeszcze bardziej w wersji bateryjnej – oszczędnej – ale o tym napiszę innym razem.

Powiązane tematy

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2Sprawdź tutaj

Przeczytaj również

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2025 arduino.pl