Category Archives: Music

LMS Record player V.something .. final? No

But it works! Many iterations .. almost perfect

Recordplayer model by kriswillcode, but heavily remixed

Record player is going to be re-printed at a higher quality.

  • Put a printed image on the player, and it plays the album
  • Move the arm, and the next track will be played
  • Press upper white button, and the music will pause/resume
  • Press lower button … ??? Don’t know yet

Updated python client (see previous posts)

import paho.mqtt.client as mqtt
import urllib.request
from time import sleep

def on_connect(client, userdata, flags, rc):  # The callback for when the client connects to the broker 
        print("Connected with result code {0}".format(str(rc)))  
        client.subscribe("spotify/rfid/idlms")  
        client.subscribe("spotify/rfid/but1")  
        client.subscribe("spotify/rfid/but2")  
        client.subscribe("spotify/rfid/arm")  

def on_message(client, userdata, msg):  # The callback for when a PUBLISH message is received from the server. 
        print("Message received-> " + msg.topic + " " + str(msg.payload))  # Print a received msg
        if msg.topic == "spotify/rfid/idlms":
            urllib.request.urlopen("http://LMS-SERVER-IP:9000/anyurl?p0=playlistcontrol&p1=album_id:" + msg.payload.decode() + "&p2=cmd:load&player=00:04:20:16:d9:04")
        if msg.topic == "spotify/rfid/but1":
            urllib.request.urlopen("http://LMS-SERVER-IP:9000/anyurl?p0=pause&player=00:04:20:16:d9:04")
            sleep(1)
        if msg.topic == "spotify/rfid/but2":
            urllib.request.urlopen("http://LMS-SERVER-IP:9000/anyurl?p0=pause&pt=1&player=00:04:20:16:d9:04")
            sleep(1)
        if msg.topic == "spotify/rfid/arm":
            urllib.request.urlopen("http://LMS-SERVER-IP:9000/status.html?p0=button&p1=jump_fwd&player=00:04:20:16:d9:04")
            sleep(1)

client = mqtt.Client("lmsclient")  # Create instance of client with client ID “digi_mqtt_test”
client.on_connect = on_connect  # Define callback function for successful connection
client.on_message = on_message  # Define callback function for receipt of a message
client.connect('MQTTSERVER', 1883)
client.loop_forever()  # Start daemon

Wemos INO file

#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#define SS_PIN 15
#define RST_PIN 0

const int buttonPin1 = D1;  
const int buttonPin2 = D2;   

int buttonState1 = 0; 
int buttonState2 = 0; 

MFRC522 mfrc522(SS_PIN, RST_PIN);
  MFRC522::StatusCode status; //variable to get card status
  
  byte buffer[18];  //data transfer buffer (16+2 bytes data+CRC)
  byte size = sizeof(buffer);

  uint8_t pageAddr = 0x06;  //In this example we will write/read 16 bytes (page 6,7,8 and 9).
                            //Ultraligth mem = 16 pages. 4 bytes per page.  
                            //Pages 0 to 4 are for special functions.           
  
unsigned long cardId = 0;
WiFiClient net;
PubSubClient client(net);
const char* mqtt_server = "MQTTBROKER";
const char* ssid = "MYSSID";
const char* password = "MYWIFIPASWORD";
String topicStr = "";
byte buffer2[8];

boolean Rflag=false;
int r_len;
char payload[5];
byte value[5];
void setup() {
  Serial.begin(9600);
    pinMode(buttonPin1, INPUT_PULLUP);
    pinMode(buttonPin2, INPUT_PULLUP  );

  SPI.begin();
  mfrc522.PCD_Init();
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
  client.setServer(mqtt_server, 1883);
     delay(100);
    client.setCallback(callback);
      delay(100);
    client.subscribe("spotify/rfid/in/#");
}
void reconnect() {
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
  }
  while (!client.connected()) {
    String clientId = "rfid-";
    clientId += String(random(0xffff), HEX);
    if (!client.connect(clientId.c_str(), "rfidclient", "...")) {
      delay(5000);
    }
  }
  client.subscribe("spotify/rfid/in/#");
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print(F("Called"));
   Rflag=true; //will use in main loop
   r_len=length; //will use in main loop
   int j=0;
     for (j;j<length;j++) {
       buffer2[j]=payload[j];
       //Serial.print((char)payload[j]);
       }
if (r_len < 3) {
  Rflag=false;
  Serial.print(F("Set false"));
}
buffer2[j]='\0'; //terminate string
}

void loop() {
    if (!client.connected()) {
    reconnect();
  }

buttonState1 = digitalRead(buttonPin1);
  //Serial.print(buttonState1);
  if (buttonState1 == 0 ) {
    client.publish("spotify/rfid/but1", "0");
  }
buttonState2 = digitalRead(buttonPin2);
  //Serial.println(buttonState2);
  if (buttonState2 == 0 ) {
    client.publish("spotify/rfid/but2", "0");
  }

int reading = analogRead(0);
  //Serial.println(reading);
  if (reading > 500 ) {
    client.publish("spotify/rfid/arm", "0");
  }
  
  client.loop();
  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  if (!mfrc522.PICC_ReadCardSerial()) {
    return;
  }
if (Rflag) {
        for (int i=0; i < 4; i++) {
    //data is writen in blocks of 4 bytes (4 bytes per page)
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Ultralight_Write(pageAddr+i, &buffer2[i*4], 4);
    if (status != MFRC522::STATUS_OK) {
      return;
    }
    
  }
  Rflag=false;
}

  cardId = getCardId();
  char buffer3[10];
  sprintf(buffer3, "%lu", cardId);
  client.publish("spotify/rfid/id", buffer3);

  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
  if (status != MFRC522::STATUS_OK) {
    Serial.println(F("MIFARE_Read() failed: (R)"));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  Serial.println(F("Read data: "));
  for (byte i = 0; i < 5; i++) {
    Serial.write(buffer[i]);
       buffer2[i]=buffer[i];
    }
       
  client.publish("spotify/rfid/idlms", buffer,5);
  delay(1000);
  mfrc522.PICC_HaltA();
}

unsigned long getCardId() {
  byte readCard[4];
  for (int i = 0; i < 4; i++) {
    readCard[i] = mfrc522.uid.uidByte[i];
  }
  return (unsigned long)readCard[0] << 24
    | (unsigned long)readCard[1] << 16
    | (unsigned long)readCard[2] << 8
    | (unsigned long)readCard[3];
}

Listening to Paganini

Niccolò (or Nicolò) Paganini.
October 1782 – 27 May 1840) was an Italian violinist and composer. He was the most celebrated violin virtuoso of his time, and left his mark as one of the pillars of modern violin technique. His 24 Caprices for Solo Violin Op. 1 are among the best known of his compositions and have served as an inspiration for many prominent composers.

I love listening to Paganini. The man was a beast.
Extreme technical, a pop star in his time.
But also because of that, he was seen as a demon.

Like the master bagpipers Stuart Liddell or the late Gordon Duncan.

Listening to Paganini’s caprices was wonderful.

A capriccio or caprice (sometimes plural: caprices, capri or, in Italian, capricci), is a piece of music, usually fairly free in form and of a lively character. The typical capriccio is one that is fast, intense, and often virtuosic in nature.

My top selection :

1,4,5,3

Why difficult?

Because of the advanced techniques, including parallel octaves, rapid interval shifts, extremely fast scales and arpeggios (including minor scales), left-hand pizzicato, high positions, and fast string crossings. Additionally, it features many double stops, such as thirds and tenths.

An arpeggio is a type of broken chord in which the notes that compose a chord are individually sounded in a progressive rising or descending order.

Pizzicato is a playing technique that involves plucking the strings of a string instrument.

Double stops are a fundamental technique in which two notes are played simultaneously on a stringed instrument. In the context of the violin, this entails using the bow to sound two adjacent strings at the same time.

On another note:

I finally got hold of the last missing Audio CD from Martyn Bennett!
I was looking for this for ages!

New POC / WIP Rfid Read/Write

yes, again. Another change.

UPDATE: Working example at bottom!

Micros*ft Surface Running Linux!

I don’t want IDs and Paths in a Home Assistant automation.
The RFIDs can store more than enough data to store the paths to albums.

I Also tested with ESPHOME in HA, but you can’t write tags.

ESPHOME Config for my RFID device (NOT USED ANYMORE)

esphome:
  name: rfidtag
  friendly_name: rfidtag

esp8266:
  board: d1_mini

mqtt:
  broker: IPMQTTBROKER

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxx="

ota:
  password: "xxxxxxxxxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Rfidtag Fallback Hotspot"
    password: "xxxxxxxxxxxxxx"

captive_portal:
    
spi:
  clk_pin: D5
  miso_pin: D6
  mosi_pin: D7
rc522_spi:
  cs_pin: D8
  update_interval: 1s
  on_tag:
    then:
      - mqtt.publish:
          topic: rc522/tag
          payload: !lambda 'return x;'
  on_tag_removed:
    then:
      - mqtt.publish:
          topic: rc522/tag_removed
          payload: !lambda 'return x;'

The next iteration of my Rfid controller will have a write function for the RFID tags.

  1. Stick a tag on a cover art piece of cardboard. (see below)
  2. Read path from data sector.
    • Send path to player automation
  3. Send path to program using MQTT or website if needed.

Not sure yet, also want to implement a wifi manager on the wemos.

Changes on above idea:

  • Paths are too long, I could not work out how to create a working program using this.
  • I stopped using paths, instead I’m using the Logitech media server album IDs.
  • Using two python scripts, I can use one for programming the card, and another script to control LMS.

How does it work

RFid device is connected to the network.

Start query.py on your LMS server.
Search for an album name, it will present an ID and Album name in a list.
Enter the ID you want to program, or 0 to exit.
(This will also reset the programming mode)

Place an empty or previously programmed tag on the device.
It will write the album ID on the tag.

Then it will start the album.
Changing the tags will also just change the album playing.

(NOTE: My genre spotify player still works using this method, using the same device)

A second python script will read the Mqtt topic and control the Squeezebox player.

Python Code DB Query

import sqlite3
#paho-mqtt
import paho.mqtt.publish as publish

host = "IPMQTTBROKER"
port = 1883
topic = "spotify/rfid/in/write"
auth = {'username': 'xxxx','password': 'xxxxx'}
client_id = "spotithing"

def readSqliteTable(albumname):
    try:
        sqliteConnection = sqlite3.connect('/var/lib/squeezeboxserver/cache/library.db')
        cursor = sqliteConnection.cursor()
        albumname = "%" + albumname + "%"
        cursor.execute("select * from albums where title Like ?",
               (albumname,))
        records = cursor.fetchall()
        for row in records:
            print("Id: ", row[0],row[1])
        cursor.close()

    except sqlite3.Error as error:
        print("Failed to read data from sqlite table", error)
    finally:
        if sqliteConnection:
            sqliteConnection.close()

album = input("Album name ? ")
readSqliteTable(album)

number = input("Enter ID or 0 to quit : ")
publish.single(topic, "00000" , qos=1, hostname=host, port=port,
        auth=auth, client_id=client_id)
if number == 0:
        exit()
publish.single(topic, number, qos=1, hostname=host, port=port,
        auth=auth, client_id=client_id)
print("Program your tag")
print("Reset/disable writing using exit with 0!")

Python Code Controller (this one needs to be running at all times)

import paho.mqtt.client as mqtt
import urllib.request

def on_connect(client, userdata, flags, rc):  
        print("Connected with result code {0}".format(str(rc)))
        client.subscribe("spotify/rfid/idlms")

def on_message(client, userdata, msg):
        print("Message received-> " + msg.topic + " " + str(msg.payload))  # Print a received msg
        urllib.request.urlopen("http://IPADDRESLMS:9000/anyurl?p0=playlistcontrol&p1=album_id:" + msg.payload.decode() + "&p2=cmd:load&player=b8:27:eb:11:16:ab")
#NOTE also change b8:27:eb:11:16:ab into you players MACAddress!

client = mqtt.Client("digi_mqtt_test")  
client.on_connect = on_connect  
client.on_message = on_message  
client.connect('IPMQTTBROKER', 1883)
client.loop_forever()  

Arduino Code (see schematic in other post)

#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#define SS_PIN 15
#define RST_PIN 0
MFRC522 mfrc522(SS_PIN, RST_PIN);
  MFRC522::StatusCode status; //variable to get card status
  byte buffer[18];  //data transfer buffer (16+2 bytes data+CRC)
  byte size = sizeof(buffer);
  uint8_t pageAddr = 0x06;  //In this example we will write/read 16 bytes (page 6,7,8 and 9).
                            //Ultraligth mem = 16 pages. 4 bytes per page.  
                            //Pages 0 to 4 are for special functions.           
unsigned long cardId = 0;
WiFiClient net;
PubSubClient client(net);
const char* mqtt_server = "IPMQTTBROKER";
const char* ssid = "MYSSID";
const char* password = "MYSSIDPASS";
String topicStr = "";
byte buffer2[8];

boolean Rflag=false;
int r_len;
char payload[5];
byte value[5];
void setup() {
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
  client.setServer(mqtt_server, 1883);
     delay(100);
    client.setCallback(callback);
      delay(100);
    client.subscribe("spotify/rfid/in/#");
}
void reconnect() {
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
  }
  while (!client.connected()) {
    String clientId = "rfid-";
    clientId += String(random(0xffff), HEX);
    if (!client.connect(clientId.c_str(), "rfidclient", "...")) {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      delay(5000);
    }
  }
  client.subscribe("spotify/rfid/in/#");
}
void callback(char* topic, byte* payload, unsigned int length) {
 
  Serial.print(F("Called"));
   Rflag=true; //will use in main loop
   r_len=length; //will use in main loop
   Serial.print("length message received in callback= ");
   Serial.println(length);
   int j=0;
     for (j;j<length;j++) {
       buffer2[j]=payload[j];
       }
if (r_len < 3) {
  Rflag=false;
  Serial.print(F("Set false"));
}
buffer2[j]='\0'; //terminate string
}

void loop() {
    if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  if (!mfrc522.PICC_ReadCardSerial()) {
    return;
  }
if (Rflag) {
        for (int i=0; i < 4; i++) {
    //data is writen in blocks of 4 bytes (4 bytes per page)
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Ultralight_Write(pageAddr+i, &buffer2[i*4], 4);
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("MIFARE_Read() failed: (W) "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }
  }
  Serial.println(F("MIFARE_Ultralight_Write() OK "));
  Serial.println();
  Rflag=false;
}
  cardId = getCardId();
  char buffer3[10];
  sprintf(buffer3, "%lu", cardId);
  client.publish("spotify/rfid/id", buffer3);
  // Read data ***************************************************
  Serial.println(F("Reading data ... "));
  //data in 4 block is readed at once.
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
  if (status != MFRC522::STATUS_OK) {
    Serial.println(F("MIFARE_Read() failed: (R)"));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  Serial.println(F("Read data: "));
  //Dump a byte array to Serial
  for (byte i = 0; i < 5; i++) {
    Serial.write(buffer[i]);
       buffer2[i]=buffer[i];
    }
  client.publish("spotify/rfid/idlms", buffer,5);
  delay(1000);
  mfrc522.PICC_HaltA();
}

unsigned long getCardId() {
  byte readCard[4];
  for (int i = 0; i < 4; i++) {
    readCard[i] = mfrc522.uid.uidByte[i];
  }
  return (unsigned long)readCard[0] << 24
    | (unsigned long)readCard[1] << 16
    | (unsigned long)readCard[2] << 8
    | (unsigned long)readCard[3];
}

Uilleann Pipe recordings

Best Uilleann recordings I own or listen to.

Do you know any other good recordings? Let me know.

Uilleann CDs (no order)

  • Liam O’Flynn – The Pipers Call
  • Davy Spillane – Atlantic Bridge, Pipedreams, Out of the Air
  • Paddy Keenan – The Long Grazing Acre
  • Sean McKeon – The Dusty Miller ( Multiple players playing harmony)

Calum Stewart (I know him from his Flute playing)
I play “Am Monadh Ruadh” from this CD, also Randolph’s Leap is awesome.
Look up “Randolph’s Leap”. I’ve been there, beautiful.
(A better name should be Cummings Leap)

Brian McNamara

He plays a ‘flat’ set pitched in ‘C’ made by Geoff Wooff in 1997 and a ‘concert-pitched’ set of pipes made by Peter Maguire, I was lucky enough to have him as my teacher in Drumshanbo.

Single tracks I like

High energy playing of Blackie O’Connoll. He was my tutor when I attended Tionol 2011

Fred Morrison‘s Kansas City Hornpipe

Paddy Keenan – Harvest Home & Boys of blue hill
(Check The Pipering Of Willie Clancy Vol II)

Doinna by John McSherry (I play this one also, but it is nothing compared to his pipe-sound, melodic virtuosity and feeling he puts in this relatively easy piece of music)

Another often played CD with Uileann, Borderpipes and Low Whistles is:

Partners in Crime by Jarlath Henderson and Ross Ainslie.
A very nice combination of two different pipes together.
Coline and I try to have at least one set with both instruments.

Some others:

  • Some tracks of Bad Shepherds
  • Some tracks of Afro Celt Sound System
  • Some tracks of Enya (See Sun in the stream post)

List of Artist i’ve got recordings from:

Cillian Vallely, Finbar Furey, Ronan Browne, Willie Clancy, Seamus Ennis, Johnny Doran, Leo Rowsome, Liam O’Flynn,Davy Spillane, Paddy Keenan, Finbar Furey, Brian McNamara, Paddy Moloney, Jerry O’Sullivan, Gay Conor, Sean McKeon, Declan Masterson, Michael McGoldrick I probably missed several

Female pipers

In the middle of recording Mhairi Bhan Og

Also known as Mary Young and Fair – this Gaelic air was published in Capt Simon Fraser’s “Knockie” Collection of 1816.

I made an arrangement using Musescore, Ardour and Bagpipe Music Writer.

Hardware used: Tascam 2488, Behringer B-1 studio microphone, Yamaha QY-100 sequencer, ESI MidiMate eX USB 2.0 MIDI-interface and Shepherd Smallpipes.

Musescore
Ardour remixing, using QY-100 via midi and Sound Fonts

(I tried Qtractor and some other tools but liked Ardour more)

Recording online soon, I have to re-record the harmony part.
Maybe I’m going to add a Flute part also.

PDF

Today some lasercutting for Home Assistant Spotify RFID

see:

Lasercutting a case and the playlist selectors.

Close-up RFID stickers I’m using.

Below is a test with different methods.
I like reading the booklets, so a CD i cool, and I don’t need a CD player.
(The RFID tag is in the case)
The little cards are for bought audio files I don’t have a physical CD for.

Wooden case with RFID reader being powered by external powerbank

What am I gonna do?
Cube as I had? Wooden playlist selectors as in above movies?
The cards I’ve printed?
Maybe a small record player with an RFID reader inside?

3D printed like this? https://makerworld.com/en/models/66671
UPDATE: 20240327 – Little Record I 3D printed with little groves.

Home Assistant code for Playlist and Album automations
(B.t.w. The method is still using an Arduino and MQTT topics, as mentioned before)

# ALBUM PLAYER
alias: SpotifyAlbum
description: ""
trigger:
  - platform: mqtt
    topic: spotify/rfid/id
condition:
  - condition: template
    value_template: "{{ trigger.payload in playlistkeys.keys() }}"
action:
  - service: media_player.play_media
    target:
      entity_id: media_player.spotify_fashice
    data:
      media_content_type: album
      media_content_id: spotify:album:{{ playlistkeys.get(trigger.payload) }}
mode: single
variables:
  playlistkeys:
    "71719674": 20TANs4iXVeLp387zjgmec
    "71260666": 5325ECcBhnIysoqyENGCYi
    "71457530": 7wyOeD9HcUuMFMO8pTflap
# PLAYLIST PLAYER
alias: SpotifyCube
description: ""
trigger:
  - platform: mqtt
    topic: spotify/rfid/id
condition:
  - condition: template
    value_template: "{{ trigger.payload in playlistkeys.keys() }}"
action:
  - service: media_player.play_media
    target:
      entity_id: media_player.spotify_fashice
    data:
      media_content_type: playlist
      media_content_id: spotify:user:spotify:playlist:{{ playlistkeys.get(trigger.payload) }}
variables:
  playlistkeys:
    "69229050": 0SOay3RkjojjevrF5lHMON
    "69491194": 5f8w3UHlD9Ozz6Y4VHs6kF
    "69753338": 0bJvpsn0TDZwIDUjz4d75S
    "70015482": 37i9dQZF1DX9HwI3Crikcm
    "70277626": 37i9dQZF1EQmK1rjZuPGDt
    "70539770": 2KeRLMmGMxI5UgzE7m0iCp

In the past, Aloha and I made a simple solution like this using barcodes in < 2000s.
Due to the many obscure recordings I have, I am thinking about creating something like this for Picore player and my local Squeezebox server.

Logitech Squeezebox / Media Server Solution

alias: squeezealbumplay
description: ""
trigger:
  - platform: mqtt
    topic: spotify/rfid/id
condition:
  - condition: template
    value_template: "{{ trigger.payload in playlistkeys.keys() }}"
action:
  - service: squeezebox.call_method
    target:
      entity_id: media_player.squeezebox
    data:
      command: playlist
      parameters:
        - play
        - "{{ playlistkeys.get(trigger.payload) }}"
mode: single
variables:
  playlistkeys:
    "71719674": /tank/celtic/Celtic/M/Martyn Bennett/Bothy Culture/
    "71719675": /tank/celtic/Celtic/D/Davy Spillane/Atlantic Bridge/
    "2159056458": /tank/celtic/Celtic/M/Michael McGoldrick/Arc/

Revisiting the Spotify Cube

In the past I posted about my genre selector for Spotify using a cube.

UPDATE: 20240501 below – using esphome

Most was done using NodeRed and a python script.

Now, I’ve moved it to Home Assistant using a single automation.
(Maybe the Arduino sketch can be made with Esphome also.
But I don’t have time for that)
It still uses the Arduino sketch as before, which uses Mqtt to post the RFID code to Mosquitto.

My new Home Assistant automation

alias: SpotifyCube
description: ""
trigger:
  - platform: mqtt
    topic: spotify/rfid/id
condition:
  - condition: template
    value_template: "{{ trigger.payload in playlistkeys.keys() }}"
action:
  - service: media_player.play_media
    target:
      entity_id: media_player.spotify_fash
    data:
      media_content_type: playlist
      media_content_id: spotify:user:spotify:playlist:{{ playlistkeys.get(trigger.payload) }}
variables:
  playlistkeys:
    "70539770": 2KeRLMmGMxI5UgzE7m0iCx
    "70277626": 37i9dQZF1EQmK1rjZuPGDx
    "69229050": 0SOay3RkjojjevrF5lHMOx
    "70015482": 37i9dQZF1DX9HwI3Crikcx
    "69753338": 0bJvpsn0TDZwIDUjz4d75x
    "69491194": 5f8w3UHlD9Ozz6Y4VHs6kx

Some notes about above script:

  • The MQTT topic is configured in the sketch below
  • The playlist keys are at the bottom
    “RFIDID”: playliststring as can be found in web spotify

Pasted link

Arduino Code

#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>

#define SS_PIN 15
#define RST_PIN 0

MFRC522 mfrc522(SS_PIN, RST_PIN);
unsigned long cardId = 0;

WiFiClient net;
PubSubClient client(net);
const char* mqtt_server = "IPMQTTBROKER";
const char* ssid = "MYSSID";
const char* password = "MYWIFIPASSWORD";

void setup() {

  Serial.begin(115200);
  SPI.begin();
  mfrc522.PCD_Init();
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);

  client.setServer(mqtt_server, 1883);
     delay(100);
    client.setCallback(callback);
      delay(100);
    client.subscribe("spotify/rfid/in/#");
}

void reconnect() {
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
  }

  while (!client.connected()) {
    String clientId = "NodeMCUClient-";
    clientId += String(random(0xffff), HEX);

    if (!client.connect(clientId.c_str(), "rfidclient", "...")) {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      delay(5000);
    }

  }
  client.subscribe("spotify/rfid/in/#");
}

void callback(char* topic, byte* payload, unsigned int length) {
    String topicStr = topic;
      byte value = atoi((char*)payload);
}

void loop() {
    if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  if (!mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  cardId = getCardId();
  char buffer[10];
  sprintf(buffer, "%lu", cardId);
  client.publish("spotify/rfid/id", buffer);

  uint8_t control = 0x00;
  do {
    control = 0;
    for (int i = 0; i < 3; i++) {
      if (!mfrc522.PICC_IsNewCardPresent()) {
        if (mfrc522.PICC_ReadCardSerial()) {
          control |= 0x16;
        }
        if (mfrc522.PICC_ReadCardSerial()) {
          control |= 0x16;
        }
        control += 0x1;
      }
      control += 0x4;
    }

    delay(0);
  } while (control == 13 || control == 14);

  reconnect();
  client.publish("spotify/rfid/id", "0");
  delay(500);

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

unsigned long getCardId() {
  byte readCard[4];
  for (int i = 0; i < 4; i++) {
    readCard[i] = mfrc522.uid.uidByte[i];
  }

  return (unsigned long)readCard[0] << 24
    | (unsigned long)readCard[1] << 16
    | (unsigned long)readCard[2] << 8
    | (unsigned long)readCard[3];
}

ESPHOME Config same as above

esphome:
  name: rfidtag
  friendly_name: rfidtag

esp8266:
  board: d1_mini

mqtt:
  broker: 192.168.1.1

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxx="

ota:
  password: "xxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Rfidtag Fallback Hotspot"
    password: "xxxxxxxxxxx"

captive_portal:
    
spi:
  clk_pin: D5
  miso_pin: D6
  mosi_pin: D7
rc522_spi:
  cs_pin: D8
  update_interval: 1s
  on_tag:
    then:
      - mqtt.publish:
          topic: spotify/rfid/id
          payload: !lambda 'return x;'
  on_tag_removed:
    then:
      - mqtt.publish:
          topic: spotify/rfid/idremoved
          payload: !lambda 'return x;'

My google-fu is still strong (and Tunepal ramblings)

Google-Fu : (informal) Skill in using search engines (especially Google) to quickly find useful information on the Internet.

I was thinking of a famous piece of music, but what was it?

Whistling it, while using Shazam or Tunepal, didn’t work.

So I googled “well known classical part repeats sped up and transposes”

The second link was a Reddit link named : “Need help finding a song that starts very slow and builds to be frantic!”

First YT link in there: In the Hall of the Mountain King (Peer Gynt) by Edvard Grieg

Epic tune!

“In the Hall of the Mountain King” is a piece of orchestral music composed by Edvard Grieg in 1875 as incidental music for the sixth scene of act 2 in Henrik Ibsen’s 1867 play Peer Gynt. It was originally part of Opus 23 but was later extracted as the final piece of Peer Gynt, Suite No. 1, Op. 46.

I’ve used Tunepal many times, it’s great for folkies!

Sometimes it works also on classical pieces, because they were arranged into folk music.

https://tunepal.org/

I bought the Android app, because I liked it so much.

Tunepal is a search-by-playing search engine for traditional Irish, Welsh, Scottish, Breton, American marching band and Canadian tunes.
By playing a 12-second extract from a traditional tune on an instrument such as the flute or fiddle, you can:

  • Retrieve score matches from a database of over 24,000 music scores
  • View and playback, share and download the score
  • Find and play other recordings of the tune from a collection of over 30 million recordings

Tunepal is a search-by-playing search engine for traditional Irish, Welsh, Scottish, Breton, American marching band and Canadian tunes.

On the Record page, click the Tunepal logo or tap the screen if your computer has a touch screen. Start playing straight away. Don’t wait for the countdown to complete. Tunepal works best if there is no silence at the start of the recording.

Tunepal works best with “legato” style instruments such as the tin-whistle, flute, concertina, accordion, pipes and fiddle. It doesn’t work very well with “plucked string” instruments such as the banjo and harp.

To find a tune using Tunepal, first make sure you have a PC microphone connected to your computer or use the phone app

If your instrument uses a different “fundamental note” to the usual D (for example you are playing a C flute) or you are playing a tune in an unusual key, then you can adjust the transcription algorithm by choosing a different “fundamental” from the settings page.

You can filter the search results from the settings page to limit searches to certain tunebooks or time signatures.

Three channel mixer for ay-3-8910 is almost done.

At the back the 8 pin single channel lm368 amplifier.
At the front the 3 channel setup.
I still have to tweak the resistors, and potmeters.
Then I can make a permanent PCB, and figure out the connections to the 6502.

At the moment, the Arduino Nano is playing some real sound samples by using the registers of the sound chip.
The music is being played by sending the register dumps directly to the chip.

Much like i’ve been using SID register dumps to play songs in another project.

This is version 0.1 .. do not use.
If its wrong, or can do better please mail me.
Oh it needs a 1k resistor from the 20K’s to ground I think.