(Bez)dotykowa interakcja. Przybliżamy Bare Conductive

Strona warsztatów

Przydatne linki

Link do pobrania środowiska Processing.
Link do pobrania środowiska Arduino (wybierzcie wersję 1.6.7.).

Dodanie Bare Conductive do Arduino IDE

Aby płytka Bare Conductive była widoczna na liście płytek w Arduino IDE trzeba zainstalować program dostępny tutaj:

Aby móc programować BC, na komputerze z systemem operacyjnym Windows mogą być potrzebne jeszcze sterowniki do pobrania stąd. Opis instalacji sterowników.
Cała instrukcja jak skonfigurować środowisko pracy tutaj: setting up Arduino with Touch Board.

MPR121 grapher

mpr121 Grapher na Github mpr121-grapher przykład

API

Inaczej mówiąc: nadawca mówi w taki sposób, aby odbiorca zrozumiał. I ten sposób mówienia jest jasno skodyfikowany. (Źródło obrazka: https://xkcd.com)

Small talk

Kolory

nazwa komenda parametr efekt
RED_UP 'R' val: [0 … 255] zwiększa intensywność kanału czerwonego (RGB)o val
RED_DOWN 'r' val: [0 … 255] zmniejsza intensywność kanału czerwonego (RGB) o val
GREEN_UP 'G' val: [0 … 255] zwiększa intensywność kanału zielonego (RGB) o val
GREEN_DOWN 'g' val: [0 … 255] zmniejsza intensywność kanału zielonego (RGB) o val
BLUE_UP 'B' val: [0 … 255] zwiększa intensywność kanału niebieskiego (RGB) o val
BLUE_DOWN 'b' val: [0 … 255] zmniejsza intensywność kanału niebieskiego (RGB) o val

Przesunięcia

nazwa komenda parametr efekt
X_POS_LEFT 'x' val: [0 … 300] przesuwa rysowany obiekt o val pikseli w lewo
X_POS_RIGHT 'X' val: [0 … 300] przesuwa rysowany obiekt o val pikseli w prawo
Y_POS_DOWN 'y' val: [0 … 350] przesuwa rysowany obiekt o val pikseli w dół
Y_POS_UP 'Y' val: [0 … 350] przesuwa rysowany obiekt o val pikseli w górę

Wielkość

nazwa komenda parametr efekt
SIZE 'S' val: [0 … 350] ustawia średnicę rysowanego obiektu na wartość val

Definicja komend w Arduino IDE

można sobie skopiować. :)

#define RED_UP 'R'
#define RED_DOWN 'r'
#define BLUE_UP 'B' 
#define BLUE_DOWN 'b' 
#define GREEN_UP 'G'
#define GREEN_DOWN 'g'
#define SIZE 'S' 
#define X_POS_LEFT 'x'
#define X_POS_RIGHT 'X'
#define Y_POS_DOWN 'y'
#define Y_POS_UP 'Y'

uint32_t data = 14;
          
if (!mesh.write(&data, RED_UP, sizeof(data))) {
    Serial.println("> Send error"); 
} else {
    Serial.print("> Send OK: msg "); 
    Serial.print( RED_UP ); 
    Serial.print("    val: "); 
    Serial.println(data);
}

Przykładowe kody

Arduino

Szkielet programu

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

Bare Conductive

Wykrywanie dotyku

// obiekt, ktory repzentuje plytke Bare Conductive w kodzie
#include <MPR121.h> 
#include <Wire.h>

#define TOUCH_BUTTONS 12

void setup() {
  
  Serial.begin(115200); 
  /*  while (!Serial) jest opcjonalne
   *  Jeśli chcecie, żeby Bare Conductive nie zaczęło działać dopóki
   *  nie otworzycie Serial Monitora - wstawcie tą linijkę. 
   *  Jeśli chcecie żeby działalo bez nadzoru (na przykład podłączone
   *  tylko do zasilacza) zakomentujcie. 
   */
  while (!Serial); 
  
  Serial.println("Bare Conductive - start"); 
  Serial.println(); 

  Wire.begin(); 
  
  /* 
   *  zainicjalizowanie czesci zwiazanej z dotykiem
   * jesli komunikacja zostala zainicjalizowana poprawnie, zwraca 1 (true)
   * jesli byl jakis blad = zwraca 0 (false)
  */
  if ( !MPR121.begin( 0x5C ) ) { 
    Serial.println("ERROR: Inicjalizacja elementu do wykrywania dotyku");
  } 

  /*
   * Tym pinem układ MPR121 jest (na stałe - dlatego tu zawsze będzie 4)
   * połączony z tą częścią, ktora pochodzi z Arduino Leonardo. 
   * Ustawiając wartość 0 na tym pinie MPR121 sygnalizuje, 
   * że stan przycisków zmienił się od ostatniego odczytu.
   */
  MPR121.setInterruptPin(4);
  
  /*
   * Konfiguracja czułości płytki
   */
  MPR121.setTouchThreshold(40); 
  MPR121.setReleaseThreshold(20); 

  MPR121.updateTouchData(); 
}

void loop() {

  /*
   * Sprawdzenie czy na elektrodach jest jakaś nowa "akcja"
   */
  if ( MPR121.touchStatusChanged() ) {
    
    /*
     * Aktualizuje status dotknięty/niedotknięty 
     * dla poszczególnych elektrod
     */
    MPR121.updateTouchData();

    /*
     * TOUCH_BUTTONS-1 --> ponieważ indeksy przycisków zaczęły się od 0
     * ostatni z nich ma indeks 11, 
     * w sumie jest ich 12. 
     */
    for (int i = 0; i <= TOUCH_BUTTONS-1 ; i++ ) {

      if ( MPR121.isNewTouch( i ) ) {
        Serial.print("elektroda "); Serial.print(i); 
        Serial.println(" zostala dotknieta"); 
        
      } else if ( MPR121.isNewRelease( i ) ) {
        Serial.print("elektroda "); Serial.print(i);  
        Serial.println(" zostala puszczona");  
      }
    } 
  }
}

Odtwarzanie dźwięku

Dodatkowo trzeba zaincludować:

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <SFEMP3Shield.h> 

Zadeklarować obiekty do obsługi karty SD i odtwarzacza MP3:

SFEMP3Shield MP3player; 
SdFat sd; 

Zainicjalizować kartę SD oraz odtwarzacz MP3 (w funkcji setup, po uruchomieniu protokołu I2C - Wire):

if ( !sd.begin( SD_SEL, SPI_HALF_SPEED) ) { 
    sd.initErrorHalt(); 
    Serial.print("Problem z inicjalizacja karty SD"); 
  }

  
  if ( MP3player.begin() != 0 ) { 
    Serial.println("Problem z inicjalizacja mp3 playera"); 
    
    Serial.println("SD_SEL: "); Serial.println(SD_SEL);
  } else {
    MP3player.setVolume(10, 10); 
  }

Odtwarzanie utworu:

MP3player.playTrack(i); 

Zatrzymywanie odtwarzania:

MP3player.stopTrack();

Komunikacja

Proste wysyłanie komend w meshu

#include "RF24.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
#include <SPI.h>
#include <EEPROM.h>
#include <printf.h>

/* 
 *  Utwórz obiekt radia, informując do których pinów 
 *  Arduino / Bare Conductive podłączyłaś(eś) piny
 *  CE i CS modułu nRF24L01+. 
 */
RF24 radio(11, 12);
/*
 * Następnie utwórz obiekty reprezentujące warstwę sieci
 * i siatkę połączeń między urządzeniami.
 */
RF24Network network(radio);
RF24Mesh mesh(radio, network);

 /*
  * Unikalny identyfikator dla każdego urządzenia w sieci. 
  * Patrz: ID na płytce Bare Conductive.
  */
#define nodeID 1
/*
 * Identyfikator siatki urządzeń. W jednym pomieszczeniu może działać kilka 
 * niezależnych sieci. Nadając odpowiednie identyfikatory można oddzielić od
 * siebie grupy urządzeń. 
 * Ważne: Master musi być podłączony do tej samej sieci.
 */
#define meshID 12

 /*
  * Zmienna, która służy do monitorowania upływającego czasu. 
  * Urządzenie wysyła wiadomość do Mastera w równych odstępach co 3 sekundy.
  */
uint32_t displayTimer = 0;

 /*
  * Liczba do wysłania
  */
uint32_t valueToSend = 242312;

void setup() {

  Serial.begin(115200);
  while (!Serial);

  /*  Inny - bardziej niskopoziomowy sposób komunikacji Arduino 
   *  (Bare Conductive) z komputerem przez Serial Monitor.
   *  tu będzie potrzebne do wywołania metody radio.printDetails(), 
   *  która wypisuje aktualne parametry radia.
   */
  printf_begin(); 
  
  /*
   * Nadanie unikalnego identyfikatora  urządzenia w sieci.
   */
  mesh.setNodeID(nodeID);

  Serial.println(F("Connecting to the mesh..."));
  /*
   * Przyłączenie urządzenia o identyfikatorze nodeID do siatki
   * o identyfikatorze meshID.
   */
  mesh.begin(meshID);
  radio.printDetails();
}

void loop() {

  mesh.update();

  if (millis() - displayTimer >= 3000) {
    displayTimer = millis();
    
    /*
     * wysłanie wiadomości
     * komenda: 'M'
     * parametr: displayTimer
     * 
     * mesh.write() zwraca 
     * 1 jeśli wiadomość została wysłana poprawnie
     * 0 jeśli podczas wysyłania wystąpił błąd.
     */
    if (!mesh.write(&valueToSend, 'M', sizeof(valueToSend))) {
      
      /*
       * Jeśli wysłanie wiadomości nie powiodło się -->
       * sprawdzenie czy urządzenie jest wciaz podlaczone do sieci. 
       */
      if ( ! mesh.checkConnection() ) {
         Serial.println("Odnawianie adresu");
        /*
         * Jeśli połączenie z siecią zostało utracone --> 
         * próba odnowienia połączenia z siecią (Master powinien nadać
         * temu urządzeniu ponownie adres w sieci).
         */
         mesh.renewAddress();
       } else {
        Serial.println("Blad wysylania, polaczenie z siecia: OK");
       }
    } else {
      Serial.print("Wyslanie OK: "); Serial.println(valueToSend);
    }
  }
}