Introducción

Mesa de control multimedia con botones de pause, siguiente canción, anterior canción, favoritos para Spotify y control de volumen.

Materiales

Fundamentos:

La idea original era construir un botón de favoritos para Spotify, basándome siguiendo el estupendo trabajo de Rincón Ingenieril.

En esta web se explican todos los pasos necesarios para construir un botón de favoritos para Spotify.

Usando una placa compatible ESP8266 y a través de APIs se puede acceder a tu cuenta de Spotify y proclamar la canción que esté sonando en ese momento como favorita pulsando un botón.

Tan solo he añadido unas mejoras complementarias a través de una placa de arduino que maneje el control multimedia del PC. Para ello he usado una placa que es capaz de simular pulsaciones de teclado a través del USB. Es el caso de la arduino pro mini.

Controlaremos el volumen con un encoder rotativo con pulsador incorporado. Al presionar este pulsador, el volumen caerá al mínimo (bajará el volumen 50 veces) y minimizará todas las ventanas mostrando el escritorio (tecla windows+m).

Mediante 3 pulsadores podremos controlar además las funciones multimedia de siguiente canción, anterior canción y pause o play.

Conexión de los componentes

Conexiones

Como se observa, usaremos la placa ESP8266 tan solo para asignar la canción que está activa a favoritos, para este propósito tiene un pulsador asignado a D3. Por otro lado, cuando el pulsador es presionado y se obtiene respuesta OK mediante la aplicación API, a través del D7 se envía una señal positiva a la placa arduino Pro Micro a modo de confirmación.

Cuando la placa arduino Pro Micro recibe esta señal HIGH de confirmación, activa los leds WS2812B en azul para expresar que la canción ha sido añadida a favoritos con éxito. (La razón por la que los leds están conectados a la Pro Micro en vez de a la ESP8266 es que esta última funciona a 3.3v, no suficiente para encender los leds a 5V, además, estos leds también se encenderán en verde dependiendo del volumen multimedia).

Por otro lado, la placa Pro Micro tiene 3 pulsadores conectados en D5, D6 y D7 correspondientes a siguiente canción, anterior canción y pause. 

El encoder control de volumen se conectará a D2 y D3. El pulsador incorporado se conectará a D4 para mutar y mostrar el escritorio.

Los leds WS2812b se conectarán a D9 que mostrará la magnitud del volumen.

Tener en cuenta que la placa ESP8266 funciona a 3.3V por lo que debe ser alimentada por Vin, ya que administraremos 5V a través del USB.

Para conectar la caja a la placa arduino Pro Micro he usado el alargador de USB de fácil fabricación.


Piezas STL para imprimir en 3D.


Programación

En el tutorial de El botón IoT de me gusta para Spotify – Rincón Ingenieril (rinconingenieril.es) se detallan los pasos para programar la ESP8266.

Arduino Pro micro

/////////////////////////////////////////////////////////////////
#include "HID-Project.h"
#include "Button2.h"; //  https://github.com/LennartHennigs/Button2
#include "ESPRotary.h";
#include <Adafruit_NeoPixel.h>

/////////////////////////////////////////////////////////////////
#define PIN         9
#define ROTARY_PIN1	3
#define ROTARY_PIN2	2
#define BUTTON_PIN	4
#define BUTTON_PLAY 6
#define BUTTON_NEXT 7
#define BUTTON_PREVIOUS 5
#define CLICKS_PER_STEP   4   // this number depends on your rotary encoder 
#define NUMPIXELS 15
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int volumen = 0;
int volumen2 = 0;

/////////////////////////////////////////////////////////////////

ESPRotary r = ESPRotary(ROTARY_PIN1, ROTARY_PIN2, CLICKS_PER_STEP);
Button2 b = Button2(BUTTON_PIN);

/////////////////////////////////////////////////////////////////

void setup() {
  pinMode (8, INPUT);
  Serial.begin(9600);
  delay(50);
  Serial.println("\n\nSimple Counter");

  r.setChangedHandler(rotate);
  r.setLeftRotationHandler(showDirection);
  r.setRightRotationHandler(showDirection);

  b.setTapHandler(click);
  b.setLongClickHandler(resetPosition);
  pinMode (BUTTON_PLAY, INPUT_PULLUP);
  pinMode (BUTTON_NEXT, INPUT_PULLUP);
  delay (1000);
  pinMode (BUTTON_PREVIOUS, INPUT_PULLUP);
  for (int i = 50; i > 0; i--) {
    Consumer.write(MEDIA_VOLUME_DOWN);
    delay(1);
  }
  pixels.begin();
  pixels.clear();
  pixels.setPixelColor(0, pixels.Color(20, 0, 0));
  pixels.show();
}

void loop() {


  r.loop();
  b.loop();
  if (!digitalRead (BUTTON_PLAY)) {
    Consumer.write(MEDIA_PLAY_PAUSE);
    delay (500);
  }
  if (!digitalRead (BUTTON_NEXT)) {
    Consumer.write(MEDIA_NEXT);
    delay (500);
  }

  if (!digitalRead (BUTTON_PREVIOUS)) {
    Consumer.write(MEDIA_PREVIOUS);
    delay (500);
  }
  if (digitalRead (8)) {
    for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...
      pixels.setPixelColor(i, pixels.Color(0, 0, 20));
    }
    pixels.show();
    delay (1000);
    for (int i = 0; i < volumen2; i++) { // For each pixel...
      pixels.setPixelColor(i, pixels.Color(0, 20, 0));
    }
    for (int i = volumen2; i < NUMPIXELS; i++) { // For each pixel...
      pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    }
    pixels.show();
  }

}

/////////////////////////////////////////////////////////////////

// on change
void rotate(ESPRotary& r) {
  //Serial.println(r.getPosition());

  volumen2 = map (volumen, 0, 100, 1, 15);
  Serial.println (volumen2);
  for (int i = 0; i < volumen2; i++) { // For each pixel...
    pixels.setPixelColor(i, pixels.Color(0, 20, 0));
  }
  for (int i = volumen2; i < NUMPIXELS; i++) { // For each pixel...
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
  }
  if (volumen == 0) {
    pixels.setPixelColor(0, pixels.Color(20, 0, 0));
  }
  pixels.show();
}

// on left or right rotation
void showDirection(ESPRotary& r) {
  Serial.println(r.directionToString(r.getDirection()));
  if (r.directionToString(r.getDirection()) == "LEFT") {
    Consumer.write(MEDIA_VOLUME_DOWN);
    volumen = volumen - 2;
    if (volumen <= 0) {
      volumen = 0;
    }
  }
  if (r.directionToString(r.getDirection()) == "RIGHT") {
    Consumer.write(MEDIA_VOLUME_UP);
    volumen = volumen + 2;
    if (volumen >= 100) {
      volumen = 100;
    }
  }
}
// single click
void click(Button2& btn) {
  Serial.println("Click!");
  //Consumer.write(MEDIA_VOLUME_MUTE);
  for (int i = 50; i > 0; i--) {
    Consumer.write(MEDIA_VOLUME_DOWN);
    delay(1);
  }
  volumen = 0;
  Keyboard.press(KEY_RIGHT_GUI);  //tecla windows
  Keyboard.press('m');
  delay(100);
  Keyboard.releaseAll ();
  for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
  }
  pixels.setPixelColor(0, pixels.Color(20, 0, 0));
  pixels.show();
}

// long click
void resetPosition(Button2& btn) {
  // r.resetPosition();
  // Consumer.write(MEDIA_STOP);
  Serial.println("Reset!");
}



/////////////////////////////////////////////////////////////////