The Idea
I've wanted to build myself a small MQTT based message reader like those majestic 90s pagers everybody lusted after back then and I have a Lameboy.
So I knew what i had to do.
This "mod" does consist of 2 parts, a little hardware upgrade and a very small firmware.
The Hardware
All we need is an NPN-transistor and a small vibration motor (+ something to glue it to the Lameboy)
The Lameboy has 2 visible Action Buttons, the A and B button. But there is also a C button hidden on the backside/inside of your little Lameboy and thanks
to the magic of the I/O expander used, this button will be an OUTPUT!!!!
We add an NPN Transistor with its base connected to the C-Button pad, collector to 3.3V and the emitter to the positive side of our vibration motor. And the negative side of the motor we just solder to ground.
The Software
/**
* _ ____ _
* | | / __ \ (_)
* | | __ _ _ __ ___ ___| | | |_ _ ___ __
* | | / _` | '_ ` _ \ / _ \ | | | | | | \ \/ /
* | |___| (_| | | | | | | __/ |__| | |_| | |> <
* |______\__,_|_| |_| |_|\___|\___\_\\__,_|_/_/\_\
*/
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <Wire.h>
#include <PubSubClient.h>
uint32_t bat = 4200;
Adafruit_PCD8544 display = Adafruit_PCD8544(2, 15, 0);
#define BUTTON_UP B10000000
#define BUTTON_DOWN B00100000
#define BUTTON_LEFT B01000000
#define BUTTON_RIGHT B00010000
#define BUTTON_B B00000100
#define BUTTON_A B00001000
#define BUTTON_SD B00000010
#define MESSAGE_LENGTH 100
#define MAX_MESSAGES 4
boolean bottonU_pressed = false;
boolean bottonD_pressed = false;
boolean bottonL_pressed = false;
boolean bottonR_pressed = false;
boolean bottonA_pressed = false;
boolean bottonB_pressed = false;
boolean bottonSD_pressed = false;
boolean bottonU_last_pressed = false;
boolean bottonD_last_pressed = false;
boolean bottonL_last_pressed = false;
boolean bottonR_last_pressed = false;
boolean bottonA_last_pressed = false;
boolean bottonB_last_pressed = false;
boolean bottonSD_last_pressed = false;
boolean bottonU_changed = false;
boolean bottonD_changed = false;
boolean bottonL_changed = false;
boolean bottonR_changed = false;
boolean bottonA_changed = false;
boolean bottonB_changed = false;
boolean bottonSD_changed = false;
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_server = "your.mqtt.server";
const char* readChannel = "inTopic";
const char* writeChannel = "outTopic";
WiFiClient espClient;
PubSubClient client(espClient);
char msg[100];
long lastMsg = 0;
int showMessage = 0;
int messageCount = 0;
char lastmsg[MAX_MESSAGES][MESSAGE_LENGTH];
bool hasMessage = false;
bool hasRead = true;
int value = 0;
void setup()
{
Serial.begin(115200);
Wire.begin();
Wire.beginTransmission(0x38);
Wire.write(B11111110);
Wire.endTransmission();
setBackgroundColor('c', 200,200,200);
display.begin();
display.clearDisplay();
display.setRotation(2);
display.setContrast(58);
display.display();
setBackgroundColor('n', 255, 100, 100);
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(2);
display.setTextColor(BLACK);
display.println("OH HI!");
display.display();
delay(2000);
display.setTextColor(BLACK, WHITE);
display.setTextSize(1);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
if (messageCount < MAX_MESSAGES) {
messageCount++;
}
///// lastmsg buffer change
for (int k = MAX_MESSAGES - 1; k > 0; k--) {
for(int l = 0; l < MESSAGE_LENGTH; l++) {
lastmsg[k][l] = lastmsg[k-1][l];
}
}
for(int j = 0; j < MESSAGE_LENGTH; j++) {
lastmsg[0][j] = NULL;
}
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
if (i < MESSAGE_LENGTH) {
lastmsg[0][i] = (char)payload[i];
}
}
hasMessage = true;
hasRead = false;
showMessage = 0;
Serial.println();
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP8266Client")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish(writeChannel, "hello world");
// ... and resubscribe
client.subscribe(readChannel);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop()
{
read_buttons();
display.clearDisplay();
// show selected message
display.print("Msg #");
display.print((showMessage + 1));
display.print("/");
display.print(messageCount);
// show battery voltage
uint32_t aIn = analogRead(A0);
aIn = map(aIn, 0, 1024, 0, 4400);
bat = (aIn+bat)/2;
display.print(" ");
display.println(bat);
if (!client.connected()) {
reconnect();
}
client.loop();
// print selected message
display.print(lastmsg[showMessage]);
display.println("");
// backlight on in case of unread message
if (hasRead) {
setBackgroundColor('n', 0, 0, 0);
} else {
setBackgroundColor('n', 255, 100, 100);
}
// notify for new message
if (hasMessage) {
vibrate(200);
hasMessage = false;
}
// scroll messages down
if (bottonD_pressed && bottonD_changed) {
if (showMessage < ( MAX_MESSAGES - 1) ) {
showMessage++;
}
}
// scroll messages up
if (bottonU_pressed && bottonU_changed) {
if (showMessage > 0) {
showMessage--;
}
}
// mark message read
if (bottonB_pressed) {
if (showMessage == 0) {
hasRead = true;
}
}
// send message
if (bottonA_pressed && bottonA_changed) {
++value;
snprintf (msg, 75, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish(writeChannel, msg);
vibrate(100);
}
display.display();
delay(100);
}
void vibrate(int milli) {
Wire.beginTransmission(0x38);
Wire.write(B11111111);
Wire.endTransmission();
delay (milli);
Wire.beginTransmission(0x38);
Wire.write(B11111110);
Wire.endTransmission();
}
void setBackgroundColor(char c, int r, int g, int b)
{
// c is fade to color, n is now color
Wire.beginTransmission(0x80);
Wire.write(c);
Wire.write(r);
Wire.write(g);
Wire.write(b);
Wire.endTransmission();
}
void read_buttons()
{
Wire.requestFrom(0x38, 1);
byte data = Wire.read();
bottonU_pressed = (~data & BUTTON_UP) > 0;
bottonD_pressed = (~data & BUTTON_DOWN) > 0;
bottonL_pressed = (~data & BUTTON_LEFT) > 0;
bottonR_pressed = (~data & BUTTON_RIGHT) > 0;
bottonA_pressed = (~data & BUTTON_A) > 0;
bottonB_pressed = (~data & BUTTON_B) > 0;
bottonSD_pressed = (~data & BUTTON_SD) > 0;
bottonU_changed = bottonU_last_pressed != bottonU_pressed;
bottonD_changed = bottonD_last_pressed != bottonD_pressed;
bottonL_changed = bottonL_last_pressed != bottonL_pressed;
bottonR_changed = bottonR_last_pressed != bottonR_pressed;
bottonA_changed = bottonA_last_pressed != bottonA_pressed;
bottonB_changed = bottonB_last_pressed != bottonB_pressed;
bottonSD_changed = bottonSD_last_pressed != bottonSD_pressed;
bottonU_last_pressed = bottonU_pressed;
bottonD_last_pressed = bottonD_pressed;
bottonL_last_pressed = bottonL_pressed;
bottonR_last_pressed = bottonR_pressed;
bottonA_last_pressed = bottonA_pressed;
bottonB_last_pressed = bottonB_pressed;
bottonSD_last_pressed = bottonSD_pressed;
}
Now i have my very own small and simple MQTT based pager \o/
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
for later: https://www.adafruit.com/product/1201
Dimension: 10mm diameter, 2.7mm thick
Voltage: 2V - 5V
5V current draw: 100mA, 4V current draw: 80mA, 3V current draw: 60mA, 2V current draw: 40mA
11000 RPM at 5V
Weight: 0.9 gram
Are you sure? yes | no
i created a github repository for this project
https://github.com/woodworker/lamequix
Are you sure? yes | no
Awesome update buddy!
Are you sure? yes | no
@woodworker did a great job on his lameboy :)
Are you sure? yes | no
He certainly did! I'd love to use one as a little handheld controller for my son's tank robot. A Nodemcu is running a webserver to control it at the moment but this would make a great little remote for him. The messaging feature of the pager would come in handy too :-)
Are you sure? yes | no