Saw a cool game a while ago, and found some old code. There was no schematic, so I had to reverse engineer it using the Arduino code. This one uses a Micro Pro.
Build a working version, now I can use this as base to create other games. But first i’m going to rebuild it so it can use Wifi and uses a Lipo Battery. Making it usable without wires.
Rotary – set angle/speed (Press resets)
Blue – toggle angle or speed ( was rotary press )
Green – select digit to change
Red – Fire
Led – not completely working yet, shows color of player Wil be changed to addressable leds with more functions (Player color, energy warning and more)
The next iteration of my Rfid controller will have a write function for the RFID tags.
Stick a tag on a cover art piece of cardboard. (see below)
Read path from data sector.
Send path to player automation
Send path to program using MQTT or website if needed.
Back of printed sticker, to stick on 250gr paper below
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];
}
Today we worked on this project again. (Bigred and me)
There were some problems we needed to fix since last time:
It was quite hard to get the correct parts. Our display connector was only fitted with connection pins on the wrong side of the connector. (up/down) So I bought a connector with both positions populated. So we had to replace this hard to solder (40 pin) connector.
It was not clear what the orientation should be of the atmega328pb. We looked at the pinout, and followed the VCC/GND. But these are also available of the opposite side of the chip. (We missed that) Later, we saw a tiny line on the PCB, which showed the pin 1 placement. So we had to remove and replace the chip. When turning on the power, (with incorrect placement) probably fried R5 (10k resistor), on both our boards. Had to replace those also.
Programming the atmega328pb was not easy, see below fixes.
Compiling the pico firmware resulted in a black screen. Below the fixes I had to make to get the screen working.
Other things still to fix.
Bigreds screen.
atmega328p didn’t work for Bigred, so probably needs to replace with the pb version.
My battery controller is not charging. See bottom of page
Some of my buttons are working. The pewpew and some of the cursor keys (not as I expect, there are some up/down issues) And none of the other keys are working.
Some other things we noticed.
sdcard: remove partitions, format using mkfs.exfat Create a c64 directory on this filesystem where you can put the d64 files!
0402 SMD is far too small for me. There is enough room on the board to use 0805 for example. Even THT is possible, there are only a few components.
Some components are TOO close together, removing a component resulted in other small parts disconnecting also.
My friend Bigred said: If I can see it, I can solder it. But it is not easy. This probably keeps a lot of people from building it!
<?php
// squeezebox.php
// leave playerid as is, for the default.
// change to MAC address of player to get coverart specific player
$img = file_get_contents('http://IP-LOGITECH_MEDIA_SERVER:9000/music/current/cover.jpg?player=<playerid>');
$im = imagecreatefromstring($img);
$width = imagesx($im);
$height = imagesy($im);
$newwidth = '240';
$newheight = '240';
$thumb = imagecreatetruecolor($newwidth, $newheight);
imagecopyresized($thumb, $im, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
//imagejpeg($thumb,'small.jpg'); //save image as jpg
header('Content-Type: image/jpeg');
imagejpeg($thumb);
imagedestroy($thumb);
imagedestroy($im);
?>
Arduino install:
Start IDE
Install TJpg_Decoder library
Open examples>Tjpeg_decoder>SPIFFS>SPIFFS_web_spiffs
change wifi credentials
and the url to your php script.
bool loaded_ok = getFile("https://myserver/onkyo.php", "/M81.jpg"); // Note name preceded with "/"
replace bottom part with
// while(1) yield();
delay(5000);
SPIFFS.remove("/M81.jpg");
I was afraid to start this myself, SMD is on another level for me. But my good friend Marco said … No problem!
So I ordered components online, which was not easy. Selecting the correct parts, sizes and options.
Finding orientations of the componentsThe master at work, he has always been our soldering master (see GPC)Using a microscopeFluxWickI have to do one myself
These things are really really small
1.6mm x 0.8mm40 connections / 20mm !
Using tweezers to place the components was even difficult. The slippery tiny bastard got catapulted everywhere. (Or got stuck on fingers, soldering iron and alike) Many small components got lost into the 7th dimension. Never to be found again.
Awesome to work on this together, but Marco said that I have to try it myself. Welllll, I got 3/4 of the ATmega328PB-A perfectly soldered, then I notished that it was crooked. Desoldering was a mess, and I heated the PCB TOO much with the heatgun.
My messed-up PCB, and f*cked-up IC. Leave it to the professionals.
Next step for me is soldering the 75 mini buttons!
Got a Trinitron display from him, I was looking for this for a long time.
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.
Using the Libraries from Fabrizio Di Vittorio, named FabGL, you can transform this device into a dumb terminal, game device, VIC-20, a 8086 pc and more. There are even some projects to turn this into a C64.
Some generic testing using sound and DOS
But the main thing I want to do: A simple terminal. (I probably revisit the other options again at a later stage)
Soldered some pinheaders on the device for serialSome terminal testing.
My Wozmon bios has bare minimum support for serial communication, so i have to do some bitbanging. (6502 is using a 6551 ACIA)
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.
Not posted in the past, new version using ESPHOME and a m5stickc
Previous version using a ESP12
A “watch” with core and environment temperature of my smoker with a alarm, and button for timers.
ESP32 dac’s drawing on oscilloscope ( no additional components)
ESP32 in front of scope, two clips for x and y
For above i used sin/cos functions 2:3, which creates Lissajous figures. See: https://www.henriaanstoot.nl/1992/01/01/oscilloscope-graphics-using-a-amiga-bonus-vectrex/
3 battery operated buttons (no wires needed) to control my shelly dimmer at the dinner table.
left button on, middle steps per 20% and 3rd button off. (This cheapass button only sends ON commands)