Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Andres SabasCarlos Alatorre
Published

Spotify & NeoPixel Controller

Intuitive control of Spotify using Arduino MKR IoT Carrier

IntermediateFull instructions provided1,446
Spotify & NeoPixel Controller

Things used in this project

Hardware components

CatSink USB-C PD
Electronic Cats CatSink USB-C PD
×1
Arduino MKR WiFi 1010
Arduino MKR WiFi 1010
×1
Arduino MKR IoT Carrier
×1

Software apps and online services

Arduino Web Editor
Arduino Web Editor

Story

Read more

Code

Spotify_and_NeoPixel_Controller.ino

Arduino
Main code
#include "arduino_secrets.h"
#include <ArduinoJson.h>    //Mejor manejo de la memoria, Better memory managment
#include <ArduinoHttpClient.h>
#include <Arduino_MKRIoTCarrier.h>
#include <Adafruit_NeoPixel.h>

#include "thingProperties.h"//Necesario para conexion a internet //Needed to conect to internt
#include "Logo.h"           //Se vincula el archivo donde esta nuestra imagen en C //Our imagen in C
#include "pitches.h"

//Configuracion de NeoPixel //NeoPixel variables
#define pin 5
#define numPixels 118
Adafruit_NeoPixel pixels(numPixels, pin, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 50

//Melodia que se tocara en el buzzer, Buzzer melody
/*int melody[] = {
 NOTE_C5, NOTE_G4, NOTE_E4, NOTE_A4, NOTE_B4, NOTE_A4, 
 NOTE_GS4, NOTE_AS4, NOTE_GS4, NOTE_G4, NOTE_D4, NOTE_E4
}; //Cancion de game over Super Mario //Super Mario's Game Over melody

//Duacion de las notas: 4 = cuarto de nota, 8 = octavo de nota, etc., Notes duration
int noteDurations[] = {
  4, 4, 4, 8, 8, 8, 
  8, 8, 8, 8, 8, 2
};*/

//Configuracion de Spotify, Spotify config
enum DrawnState { None, Play, Pause };

const char SPOTIFY_CLIENT[] = SECRET_SPOTIFY_CLIENT;  // Cliente ID de la aplicacion de Spotify, Spotify Client ID
const char SPOTIFY_SECRET[] = SECRET_SPOTIFY_SECRET;  // Cliente secreto de la aplicacion de Spotify, Spotify Secret Client
const unsigned long TOKEN_REFRESH_RATE = 3000000; 
const unsigned long UPDATE_REFRESH_RATE = 500;

//Web Server para autorizacion , Authentication web server
WiFiServer server(80);  // Servidor para autorizacion de Spotify, Web server initalization 
WiFiSSLClient ssl;      // Cliente para peticiones HTTPS de Spotify , HTTPS client for Spotify requests
HttpClient authClient = HttpClient(ssl, "accounts.spotify.com", 443);
HttpClient apiClient = HttpClient(ssl, "api.spotify.com", 443);
MKRIoTCarrier carrier; //Incialia el carrier y le da nombre "carrier" , Start the carrier and name it

String accessToken;
String refreshToken;
bool authenticated = false;
unsigned long lastTokenTime = 0;
unsigned long lastTrackTime = 0;
int songProgress = 0;
DrawnState lastDrawnState = None;

//-----------------------------UTILIDADES------------------------ UTILITIES
// Crear filtro para solo obtener los parametros requeridos, Filter to get the parameters requiered
StaticJsonDocument<200> getFilter() {
  StaticJsonDocument<200> filter;

  // Colocar "true" para la informacion requerida , Set true for the requiered info
  filter["is_playing"] = true;
  filter["device"]["volume_percent"] = true;
  filter["item"]["name"] = true;
  filter["item"]["album"]["artists"] = true;
  filter["item"]["duration_ms"] = true;
  filter["progress_ms"] = true;

  return filter;
}

// Imprime la cancion actual en el Serial , Prints the current song
void printCurrentSong() {
  Serial.print("Reproduciendo ahora: ");
  Serial.print(song_name);
  Serial.print(" de ");
  Serial.println(artist_name);
}

// Regresa el estilo de etiqueta HTML, Returns the style HTML tag
const char* getStyle() {
  return "<style>html{height:100\%;display:grid;justify-content:center;align-content:center;"
         "background-color:#1ED760;font-size:60px;}</style>";
}

String getHTML(const char* message) {
  String html = "<!DOCTYPE html>\n";
  html += "<html><body>";
  html += getStyle();
  html += "<div>";
  html += message;
  html += "</div></body></html>";
  return html;
}

// Regresa el indice del ultimo espacio antes del limite, Returns the last space index
int lastSpaceBeforeThreshold(String text, int threshold) {
  int prevIndex = 0;
  int index = text.indexOf(' ');
  while (index >= 0 && index < threshold) {
    prevIndex = index;
    index = text.indexOf(' ', index + 1);
  }
  return prevIndex;
}

//Regresa "true" si el indice de bit es 1, Returns true if the index bit is 1
bool isButtonPressed(byte states, byte index) {
  return (states & (1 << index)) > 0;
}

//--------------------------------AUTORIZACION-------------------AUTORIZATION
//Obtener el token de autorizacion del usuario, get the authorization user's token
bool getAccessToken(String userCode) {
  String postData = "grant_type=authorization_code&code=" + userCode + "&redirect_uri="
                    "http://" + ip_address + "/redirect/";
  authClient.beginRequest();
  authClient.post("/api/token");
  authClient.sendHeader("Content-Type", "application/x-www-form-urlencoded");
  authClient.sendHeader("Content-Length", postData.length());
  authClient.sendBasicAuth(SPOTIFY_CLIENT, SPOTIFY_SECRET); // Envia las credenciales de Spotify, Send Spotify's credentials
  authClient.beginBody();
  authClient.print(postData);
  authClient.endRequest();

  // Si fue exitoso , If succesful 
  if (authClient.responseStatusCode() == 200) {
    lastTokenTime = millis();
    DynamicJsonDocument json(512);
    deserializeJson(json, authClient.responseBody());
    accessToken = json["access_token"].as<String>();
    refreshToken = json["refresh_token"].as<String>();
    return true;
  }
  return false;
}

// Actualiza el token de autorizacion del usuario , Update the token
void refreshAccessToken() {
  String postData = "grant_type=refresh_token&refresh_token=" + refreshToken;
  authClient.beginRequest();
  authClient.post("/api/token");
  authClient.sendHeader("Content-Type", "application/x-www-form-urlencoded");
  authClient.sendHeader("Content-Length", postData.length());
  authClient.sendBasicAuth(SPOTIFY_CLIENT, SPOTIFY_SECRET); // Envia las credenciales de Spotify, Send Spotify's credentials
  authClient.beginBody();
  authClient.print(postData);
  authClient.endRequest();

  // Si fue exitoso, If succesful
  if (authClient.responseStatusCode() == 200) {
    lastTokenTime = millis();
    DynamicJsonDocument json(256);
    deserializeJson(json, authClient.responseBody());
    accessToken = json["access_token"].as<String>();
  }
}

//----------------------------------PETICION API-------------------------API REQUEST
//Obtener el estado actual del reproductor, Get the status of the player
void getPlayerState() {
  apiClient.beginRequest();
  apiClient.get("/v1/me/player");
  apiClient.sendHeader("Authorization", "Bearer " + accessToken);
  apiClient.endRequest();

  int statusCode = apiClient.responseStatusCode();
  // Si fue exitoso y esta reproduciendo (se debe de obtener el codigo de estado 204), If sucessful ans it is playing (status code 204)
  if (statusCode == 200) {
    // Crea un filtro ya que la respuesta es muy prolongada para que el Arduino lo soporte, Creta a filter to the Arduino be able to handle it
    StaticJsonDocument<200> filter = getFilter();
    DynamicJsonDocument json(4096);
    deserializeJson(json, apiClient.responseBody(), DeserializationOption::Filter(filter));
    is_playing = json["is_playing"].as<bool>();
    volume_percent = json["device"]["volume_percent"].as<int>();
    // Si la cancion a cambiado, If the song changes
    if (song_name != json["item"]["name"].as<String>()) {
      songProgress = json["progress_ms"].as<int>();
    }
    song_name = json["item"]["name"].as<String>();
    artist_name = json["item"]["album"]["artists"][0]["name"].as<String>();
    song_length = json["item"]["duration_ms"].as<int>();
    is_active = true;
    printCurrentSong();
  } else {
    is_active = false;
    is_playing = false;
  }
  updatePlayerDisplay();
}

//Saltar cancion en una direccion dada //Change song in a given direction
void skipSong(String direction) {
  apiClient.beginRequest();
  apiClient.post("/v1/me/player/" + direction);
  apiClient.sendHeader("Content-Length", 0);
  apiClient.sendHeader("Authorization", "Bearer " + accessToken);
  apiClient.endRequest();
}

//Saltar a la cancion anterior, Previous Song
void previousSong() {
  skipSong("previous");
  getPlayerState();
}

//Saltar a la cancion siguiente, Next Song
void nextSong() {
  skipSong("next");
  getPlayerState();
}

//Volumen del reproductor, Volume
void setVolume(int newVolume) {
  apiClient.beginRequest();
  apiClient.put("/v1/me/player/volume?volume_percent=" + String(newVolume));
  apiClient.sendHeader("Content-Length", 0);
  apiClient.sendHeader("Authorization", "Bearer " + accessToken);
  apiClient.endRequest();
}

// Subir volumen en un 5 pociento, Turn up the volume in 5%
/*void volumeUp() {
  int newVolume = volume_percent > 95 ? 100 : volume_percent + 5;
  setVolume(newVolume);
  getPlayerState();
}*/

//Bajar Volumen en un 10 porciento, Turn down the volume in 10%
void volumeDown() {
  int newVolume = volume_percent < 5 ? 0 : volume_percent - 10;
  setVolume(newVolume);
  getPlayerState();
}

//Cambio entre play/pause, Play/Pause
void playPause() {
  apiClient.beginRequest();
  apiClient.put("/v1/me/player/" + String(is_playing ? "pause" : "play"));
  apiClient.sendHeader("Content-Length", 0);
  apiClient.sendHeader("Authorization", "Bearer " + accessToken);
  apiClient.endRequest();
  getPlayerState();
}

//----------------------------------CONTROL DE LEDS--------------------------------- LED CONTROL
//Encender todos los LEDs en verde, Turn the LEDs in a green color
void flashLEDs() {
  for (int i = 0; i < 2; i++) {
    carrier.leds.setPixelColor(0, 0, 128, 0);
    carrier.leds.setPixelColor(1, 0, 128, 0);
    carrier.leds.setPixelColor(2, 0, 128, 0);
    carrier.leds.setPixelColor(3, 0, 128, 0);
    carrier.leds.setPixelColor(4, 0, 128, 0);
    carrier.leds.show();
    delay(100);
    turnOffLEDs();
    delay(100);
  }
}

//Ciclo de LEDs, LED's cycle
void cycleLEDs() {
  carrier.leds.setPixelColor(0, 0, 128, 0);
  carrier.leds.show();
  delay(20);
  carrier.leds.setPixelColor(0, 0);
  carrier.leds.setPixelColor(1, 0, 128, 0);
  carrier.leds.show();
  delay(20);
  carrier.leds.setPixelColor(1, 0);
  carrier.leds.setPixelColor(2, 128, 0, 0);
  carrier.leds.show();
  delay(20);
  carrier.leds.setPixelColor(2, 0);
  carrier.leds.setPixelColor(3, 0, 128, 0);
  carrier.leds.show();
  delay(20);
  carrier.leds.setPixelColor(3, 0);
  carrier.leds.setPixelColor(4, 0, 128, 0);
  carrier.leds.show();
  delay(20);
  carrier.leds.setPixelColor(4, 0);
  carrier.leds.show();
}

//Apagar todos los LEDs, Turn off the LEDs
void turnOffLEDs() {
  carrier.leds.setPixelColor(0, 0);
  carrier.leds.setPixelColor(1, 0);
  carrier.leds.setPixelColor(2, 0);
  carrier.leds.setPixelColor(3, 0);
  carrier.leds.setPixelColor(4, 0);
  carrier.leds.show();
}

//------------------------------CONTROL DE BOTONES------------------- BUTTONS CONROL
//Obetener el estado de todos los botones al mismo tiempo, Get the status of all the buttons at once
byte getButtonStates() {
  byte states = 0;
  states |= carrier.Buttons.onTouchDown(TOUCH0) << 0;
  states |= carrier.Buttons.onTouchDown(TOUCH1) << 1;
  states |= carrier.Buttons.onTouchDown(TOUCH2) << 2;
  /*states |= carrier.Buttons.onTouchDown(TOUCH3) << 3;*/ //No funciona bien este boton, this buttons didnt work well for us!
  states |= carrier.Buttons.onTouchDown(TOUCH4) << 4;
  return states;
}

// Checar el estadode los botones y actuar de forma adecuada, Chek the buttons statu
void checkButtonStates() {
  carrier.Buttons.update();
  byte states = getButtonStates();

  if (!authenticated) {
    if (states > 0) {
      flashLEDs();
    }
  } else if (!is_active) {
    if (states > 0) {
      cycleLEDs();
      getPlayerState();      
    }
  } else {
    // Button 0 - Bajar Volumen, Tunr down volume
    if (isButtonPressed(states, 0)) {
      carrier.leds.setPixelColor(0, 128, 0, 0);
      carrier.leds.show();
      volumeDown();
      carrier.leds.setPixelColor(0, 0);
      carrier.leds.show();
      return;
    }

    // Button 1 - Cancion previa, Previous song
    if (isButtonPressed(states, 1)) {
      carrier.leds.setPixelColor(1, 128, 0, 0);
      carrier.leds.show();
      previousSong();
      carrier.leds.setPixelColor(1, 0);
      carrier.leds.show();
      return;
    }

    // Button 2 - Play/Pause,
    if (isButtonPressed(states, 2)) {
      carrier.leds.setPixelColor(2, 128, 0, 0);
      carrier.leds.show();
      playPause();
      carrier.leds.setPixelColor(2, 0);
      carrier.leds.show();
      return;
    }

    // Button 3 - Subir Volumen, Turn Up volume
    /*if (isButtonPressed(states, 3)) {
      carrier.leds.setPixelColor(3, 128, 0, 0);
      carrier.leds.show();
      volumeUp();
      carrier.leds.setPixelColor(3, 0);
      carrier.leds.show();
      return;
    }*/

    // Button 4 - Canccion siguiente, Next Song
    if (isButtonPressed(states, 4)) {
      carrier.leds.setPixelColor(4, 128, 0, 0);
      carrier.leds.show();
      nextSong();
      carrier.leds.setPixelColor(4, 0);
      carrier.leds.show();
      return;
    }
  }
}

//----------------------------CONTROL DE DISPLAY-------------------- DISPLAY CONTROL
//Imprimir iconos de reproductor, Print player icons
void printMediaIcons() {
  // Regresar cancion, Previous song
  carrier.display.fillTriangle(38, 51, 51, 43, 51, 59, ST77XX_WHITE);
  carrier.display.fillTriangle(51, 51, 64, 43, 64, 59, ST77XX_WHITE);

  // Saltar cancion, Next song
  carrier.display.fillTriangle(189, 154, 189, 170, 202, 162, ST77XX_WHITE);
  carrier.display.fillTriangle(202, 154, 202, 170, 215, 162, ST77XX_WHITE);

  // Subir volumen, Turn up volume
  //carrier.display.fillRect(203, 43, 8, 24, ST77XX_WHITE);
  //carrier.display.fillRect(195, 8, 24, 8, ST77XX_WHITE);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.setTextSize(1); // 6 x 8
  carrier.display.setCursor(170, 51);
  carrier.display.print("No Sirvo"); //I dont work in spanish lol
  carrier.display.setTextWrap(true);
  

  // Bajar volumen, Turn Down volume
  carrier.display.fillRect(21, 162, 24, 8, ST77XX_WHITE);

  // Play/Pause
  printPlayPause();
}

//Imprimir el logo, Print logo
void printLogo() {
  carrier.display.drawBitmap(60, 60, LOGO, 120, 120, 0x26CC);
}

//Inicializar el display, Starts the display
void initializePlayerDisplay() {
  carrier.display.fillScreen(ST77XX_BLACK);
  printLogo();
  printMediaIcons();
}

//Dibujar el icono de play o pausa dependiendo si esta reproduciendo, Draw the play/pause icon depending on the status
void printPlayPause() {
  if (lastDrawnState == (is_playing ? Pause : Play)) {
    return;
  }

  // Primero borrar el display, Erase the display
  carrier.display.fillRect(105, 1, 30, 30, ST77XX_BLACK);

  // Ahora, dibuja el icono correspondiente, Draw the correct icon 
  if (is_playing) {
    // Pause icono, Pause
    carrier.display.fillRect(113, 6, 5, 23, ST77XX_WHITE);
    carrier.display.fillRect(122, 6, 5, 23, ST77XX_WHITE);
  } else {
    // Play icono, Play
    carrier.display.fillTriangle(112, 4, 112, 26, 128, 15, ST77XX_WHITE);
  }
  lastDrawnState = is_playing ? Pause : Play;
}

//Extiende la barra de progreso si la cancion se esta reproduciendo, ademas la elimina, Extend the progress bar if the song is playing
void updateTrackBar() {
  if (is_playing) {
    songProgress += millis() - lastTrackTime;
    if (songProgress > song_length) {
      getPlayerState();
      return;
    }
    carrier.display.drawRect(80, 220, 80, 5, ST77XX_GREEN); // Dibuja el contorno de la barra de progreso, Draw the outline of the progress bar
    int progress = 78 * songProgress / song_length;
    carrier.display.fillRect(81, 221, progress, 3, ST77XX_WHITE); // Dibuja la barra de progreso, Draw the progress bar
    carrier.display.fillRect(81 + progress, 221, 76 - progress, 3, ST77XX_BLACK); // Dibuja la barra que en negro (la parte que aun no esta en progreo), Draw the progress bar of the unplayed part of the song
  } else {
    carrier.display.fillRect(80, 220, 80, 5, ST77XX_BLACK); // Elimina la barra de progreso, Erase the progress bar
  }
  lastTrackTime = millis();
}

//Actualiza el nombre de la cancion si la cancion se esta reproduciendo, si no la elimina, Update the name of the song if is playing
void updateTrackName() {
  carrier.display.fillRect(70, 186, 100, 33, ST77XX_BLACK); // Elimina el nombre de la cancion, Erase the song name
  if (is_playing) {
    // Imprime el nombre de la cancion, Print the song name
    carrier.display.setTextColor(ST77XX_WHITE);
    carrier.display.setTextSize(1); // 6 x 8
    carrier.display.setCursor(70, 186);
    if (song_name.length() > 16) {
      // Intenta no partir palabras a la mitad, Try to no break words
      int lastSpace = lastSpaceBeforeThreshold(song_name, 16);
      if (lastSpace > 0) {
        carrier.display.print(song_name.substring(0, lastSpace));
        carrier.display.setCursor(70, 194);
        carrier.display.print(song_name.substring(lastSpace + 1, song_name.length() > lastSpace + 17 ?
                              lastSpace + 17 : song_name.length()));
      } else {
        carrier.display.print(song_name.substring(0, 16));
        carrier.display.setCursor(70, 194);
        carrier.display.print(song_name.substring(16, song_name.length() > 32 ? 32 : song_name.length()));
      }
    } else {
      carrier.display.print(song_name);
    }

    // Imprime el nombre del artista, Print the artist name
    carrier.display.setTextColor(0xCE59); // Gris, Gray
    carrier.display.setTextSize(1); // 6 x 8
    carrier.display.setCursor(70, 209);
    carrier.display.print(artist_name.substring(0, artist_name.length() > 16 ? 16 : artist_name.length()));
  }
}

//Actualiza el estado del reproductor, Update the status of the player
void updatePlayerDisplay() {
  printPlayPause();
  updateTrackBar();
  updateTrackName();
}

//Imprime el mensaje de autenticacion, Print the authentication message
void printAuthMessage() {
  carrier.display.fillScreen(ST77XX_BLACK);
  carrier.display.setTextColor(ST77XX_WHITE);
  carrier.display.setTextSize(2); // 12 x 16

  carrier.display.setCursor(80, 92);
  carrier.display.print("Porfavor"); 
  //carrier.display.print("Please");

  carrier.display.setCursor(30, 110);
  carrier.display.print("autentica en"); 
  //carrier.display.print("Authenticate in");


  carrier.display.setCursor(30 + (22 - ip_address.length()) / 2, 128);
  carrier.display.print(ip_address);
}

//-------------------------EVENTOS--------------------- EVENTS
//Actualiza la direccion IP cuando se conecta, Update the IP address when is connected
void onNetworkConnect() {
  IPAddress ip = WiFi.localIP();
  ip_address = String(ip[0]) + "." + String(ip[1]) + "." + String(ip[2]) + "." + String(ip[3]);
  printAuthMessage();
  Serial.println("Please authenticate at " + ip_address);
}

//-----------------------------------SETUP Y LOOP-----------------------
void setup() {
  Serial.begin(9600);

  //Inicializar las variables // initialize the variables
  volume_percent = 0;
  song_length = 0;
  is_active = false;
  is_playing = false;
  song_name = "";
  artist_name = "";
  carrier.Buzzer.beep();
  delay(400);
  carrier.Buzzer.noSound();
  // Definido en thingProperties.h, Defined in thingProperties.h
  initProperties();

  // Conectar a Arduino IoT Cloud //Connect to Ardino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection, false); // disable watchdog restart

  // Anadir una coneccion de llamada, Add a callback connection
  ArduinoIoTPreferredConnection.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect);

  //Inicializar el carrier, Initialize the carrier
  CARRIER_CASE = true; 
  carrier.begin();
  carrier.display.setRotation(0);
  
  /*//Iteracion de las notas de la melodia, Iteration of the notes of the melody
   for (int thisNote = 0; thisNote < 8; thisNote++) {
    //Para calcular la duracion de las notas, toma 1 segundo dividido por el tipo de nota. To calculate the duration of the notes, take 1 second divided by the type of note
    //Ejemplo: Cuarto de nota = 1000/4, etc.
    int noteDuration = 1000 / noteDurations[thisNote];
    carrier.Buzzer.sound(melody[thisNote]);
    delay(noteDuration);
    // Para distinguir las notas, configura un minimo de tiempo entre ellos.To distinguish the notes, set a minimum time between them
    // la duracion de las notas + 50% trabaja bien. Note duration + 50% works fine
    int pauseBetweenNotes = noteDuration * 1.50;
    delay(pauseBetweenNotes);
    // Detener los sonidos, stop the sound
    carrier.Buzzer.noSound();
  }*/
  //Iniciar el server, Initialize the server
  server.begin();
  
   //NeoPixel
  pixels.begin();  // Inicializa la barra de NeoPixel, Initalize the NeoPixel Strip
  //COLOR
  pixels.clear();  // Apaga todos los LEDs, Turn off the leds
  
  //Prende en colores la barra, turn on the strip with colors
  for (int i = 0; i < 59; i++) {  // Para cada LED... For each LED...
    pixels.setPixelColor(i, pixels.Color(0, 255, 100));
    pixels.show();  
    delay(DELAYVAL);
  }
  // Segunda hilera de LEDs, Second LEDs row
  for (int i = 60; i < 118; i++) { 
    pixels.setPixelColor(i, pixels.Color(255, 0, 255));
    pixels.show(); 
    delay(DELAYVAL);  
  }
}

void loop() {
  ArduinoCloud.update();
  checkButtonStates();

  if (!authenticated) {
    // Esperar a que el usuario se conecte, Wait to the user to connect
    WiFiClient wifiClient = server.available();

    // Si el usuario se ha conectado, If the user has connected
    if (wifiClient) {
      // Obtener la peticion, Get the request
      String header = "";
      while (wifiClient.available()) {
        header += char(wifiClient.read());
      }

      // Si esta autenticado, redirigir, If authenticated, redirect
      if (header.indexOf("?code") >= 0) {
        // Analizar el token, Analize the token
        String userCode = header.substring(header.indexOf("code=") + 5, header.indexOf("HTTP/1.1") - 1);
        authenticated = getAccessToken(userCode);
        if (authenticated) {
          wifiClient.print(getHTML("Authenticated!"));
          initializePlayerDisplay();
          getPlayerState();
        } else {
          wifiClient.print(getHTML("Authentication failed."));
        }
      } else if (header.indexOf("?error") >= 0) {
        wifiClient.print(getHTML("Cancelled."));
      }
      else {
        // Autenticar el usuario y el token, Authenticate the user and the token
        String webpage = "<!DOCTYPE html>\n";
        webpage += "<html><body>";
        webpage += getStyle();
        webpage += "<a href=\"https://accounts.spotify.com/authorize?client_id=";
        webpage += SPOTIFY_CLIENT;
        webpage += "&response_type=code&redirect_uri=http://";
        webpage += ip_address;
        webpage += "/redirect/&scope=user-read-playback-state "
                   "user-modify-playback-state\">Authenticate Spotify</a>\n";
        webpage += "</body></html>";
        wifiClient.print(webpage);
      }
      wifiClient.stop();
    }
  } else if (millis() - lastTokenTime > TOKEN_REFRESH_RATE) {
    // Refrescar token si esta a punto de expirar, Refresh the token if is about to expire
    refreshAccessToken();
  } else if (millis() - lastTrackTime > UPDATE_REFRESH_RATE) {
    // Actualzar la barra de progreso, Update the progress bar
    updateTrackBar();
  }
}

arduino_secrets.h

C/C++
Arduino Secret File to save the credentials
#define SECRET_SPOTIFY_CLIENT ""
#define SECRET_SPOTIFY_SECRET ""
#define SECRET_SSID ""
#define SECRET_PASS ""

thingProperties.h

Arduino
// Code generated by Arduino IoT Cloud, DO NOT EDIT.

#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>

const char SSID[]     = SECRET_SSID;    // Network SSID (name)
const char PASS[]     = SECRET_PASS;    // Network password (use for WPA, or use as key for WEP)


String artist_name;
String ip_address;
String song_name;
int song_length;
int volume_percent;
bool is_active;
bool is_playing;

void initProperties(){

  ArduinoCloud.addProperty(artist_name, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(ip_address, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(song_name, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(song_length, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(volume_percent, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(is_active, READ, ON_CHANGE, NULL);
  ArduinoCloud.addProperty(is_playing, READ, ON_CHANGE, NULL);

}

WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);

Logo.h

C/C++
Logo in C file
// Logo, https://github.com/bitbank2/image_to_c
const unsigned char LOGO[] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
	0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 
	0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 
	0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x00, 
	0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 
	0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 
	0x01, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 
	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 
	0xff, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 
	0xf8, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfc, 
	0x00, 0x7e, 0x00, 0x3f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x3f, 
	0xff, 0xfc, 0x3f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe1, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0x87, 0xff, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x01, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xff, 
	0xf8, 0x03, 0xff, 0x80, 0x03, 0xe0, 0x07, 0xe0, 0x01, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xc0, 
	0x03, 0xff, 0x80, 0x07, 0xf0, 0x0e, 0x60, 0x03, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0x80, 0x03, 
	0xff, 0xc0, 0x06, 0x70, 0x0c, 0x70, 0x03, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x03, 0xff, 
	0xc0, 0x0e, 0x30, 0x0e, 0x7c, 0x03, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x03, 0xff, 0xc0, 
	0x3e, 0x30, 0x0f, 0xff, 0x03, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xc0, 0xff, 
	0xf0, 0x07, 0xff, 0xc7, 0xff, 0xc0, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xe3, 0xff, 0xe0, 
	0x01, 0x0f, 0xf7, 0xff, 0xe0, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x07, 0xff, 0xef, 0xf0, 0x80, 0x00, 
	0x03, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 
	0xff, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x3f, 
	0xff, 0xf0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 
	0xf0, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, 
	0x00, 0x07, 0xff, 0xe0, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, 0x00, 
	0x07, 0xff, 0xe0, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x07, 
	0xff, 0xe0, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x3c, 0x7e, 0x00, 0x07, 0xff, 0xff, 0x00, 0x07, 0xff, 
	0xe0, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x7e, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xe0, 
	0x03, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xe0, 0x1f, 
	0xff, 0xff, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xe7, 0x7f, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0x80, 0x00, 0xfe, 0x7e, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
	0x00, 0x7e, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
	0x18, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 
	0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 
	0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 
	0x7f, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfe, 0x00, 0x00, 0x00, 0x01, 0xfe, 
	0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0x80, 0x00, 0x00, 0x07, 0xf8, 0x03, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1f, 0xe0, 0x00, 0x03, 0xdf, 0xe0, 0x01, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x07, 0xfb, 0xc0, 0x07, 0xff, 0x80, 0x00, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xe0, 0x0e, 0x7c, 0x00, 0x00, 0x3f, 0xff, 0xff, 
	0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3e, 0x70, 0x0c, 0x78, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 
	0xff, 0xff, 0xf8, 0x00, 0x00, 0x0e, 0x30, 0x0c, 0x70, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 
	0xff, 0xe0, 0x00, 0x00, 0x06, 0x30, 0x0f, 0xe0, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 
	0x80, 0x00, 0x00, 0x07, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xfe, 0x00, 
	0x00, 0x00, 0x07, 0xe0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 
	0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

pitches.h

C/C++
Needed to play buzzer melodies
/*************************************************
 * Public Constants
 *************************************************/
#define REST      0
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

Credits

Andres Sabas
49 projects • 49 followers
Co-Founder of The Inventor's House Hackerspace, DIY, Workaholic
Contact
Carlos Alatorre
18 projects • 6 followers
Mechatronic Engineer working on supporting you! An open source user. I'm very curious in almost most of my life areas. Born and raised in MX
Contact
Thanks to Altug.

Comments

Please log in or sign up to comment.