Saturday 26 October 2024

Mega City Block Upgrade - Arduino Nano MAX7219 Display

A while ago I built a Mega City One Miniature Cary Case for my Judge Dredd miniatures and it was always my intention to have some sort of digital display which I could display random "in game" messages and to send instructions to the players such as ROLL FOR INITIATIVE.

The Components

Arduino Uno / Arduino Nano

I'd been itching to mess around with an Arduino microcontroller for years but never had the courage to just dive in.  However, there are so many people on ebay and Aliexpress selling ridiculously cheap arduino kits that there really is no barrier to entry. 

I plumped for an Arduino Uno Rev 3 Starter Kit which included a breadboard, jumpers and a whole pack of additional resistors and what nots.

The goal here is to make a small form factor self contained device so migrating from the large Uno dev board is essential.  I ordered a random Nano board from Aliexpress before realising that they come in 3 varieties with different board to PC connectors.  the cheap one I had picked came with an old style mini USB B connector and no lead.  Fortunately I had an lead from an old digital camera to use in the meantime, but I quickly ordered a bunch of nanos with USB C connectors for this and other projects I have in mind.  

MAX7219 8x32 Dot Matrix Display

The perfect lo-fi display for this project is a MAX7219 LED 8x32 dot matrix display.  It's small enough to work as a standalone unit and can take its power from the Arduino itself.  I bought one from AliExpress for only a couple of pounds. 

Wiring the MAX7219

I grabbed a bunch of dupont wires (these are the handy dandy push pin connectors which you get in your arduino kit.  I chopped one end off each wire and soldered them to the MAX7219 pins:

  • VCC - Purple - 5v
  • GND - White - GND
  • DIN - Black - Digital Pin 11
  • CS - Blue - Digital Pin 10
  • CLK - Grey - Digital Pin 13

Wiring the Button

The button is wired into:

  • VCC - Red - 5v
  • OUT - Orange - Digital Pin 7
  • GND - Yellow - GND

Entering the The Matrix Code

A bit of googling discovered the perfect code in the form of MAX7219 Message Selector on the Arduino Forums by user groundFungus.  Some tweaking later and I had a bunch of messages which I could toggle through with the addition of a button push on PIN7

// Program to demonstrate the MD_Parola library
// button select canned messages
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
// by groundFungus AKA c. goulding

#include 
#include 
#include 

const byte  buttonPin = 7;    // the pin that the pushbutton is attached to

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4

// Scrolling parameters
#define SPACE_IN      A5
#define DIRECTION_SET 8 // change the effect
#define INVERT_SET    9 // change the invert

#define CLK_PIN   13
#define DATA_PIN  11
#define CS_PIN    10

MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

// individual messages in strings
const char msg_1[] = "<< WEATHER ALERT>> RAIN IN 10 MIN <> SECTOR 237 RIOT IN PROGRESS <> HOTTIE DAWGS ARE GOOD TO EAT <> BE GOOD CITIZENS LITTERING IS A CRIME>>  ";
const char msg_2[] = "<> ROLL FOR INITIATIVE>>";
const char msg_3[] = "<> GET UGLY GET OTTO SUMPS OIL OF UGLY TODAY!! >>";
const char msg_4[] = "<> HEAVY TRAFFIC ON THE BIG MEG CHOOSE ALTERNATE ROUTES >>";
const char msg_5[] = "<> THIS AREA IS IN LOCKDOWN >>";
const char msg_6[] = "<> CLEAN UP CREWS IN TRANSIT >>";

// an array of pointers to the strings
char *messages[] = {msg_1, msg_2, msg_3, msg_4, msg_5, msg_6};
byte messageNum = sizeof(messages) / sizeof(messages[0]);

int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup(void)
{
   Serial.begin(115200);
   Serial.println("\nParola pick a message program\n");
   P.begin();
   pinMode(buttonPin, INPUT_PULLUP);
}

void loop(void)
{
   if (P.displayAnimate())  // time to show next frame?
   {
      P.displayText(messages[buttonPushCounter], PA_CENTER, 50, 3000, PA_SCROLL_LEFT, PA_SCROLL_UP);
   }
   checkButton();
}

void checkButton()
{

   static unsigned long timer = 0;
   unsigned long interval = 25;
   if (millis() - timer >= interval)
   {
      timer = millis();
      buttonState = digitalRead(buttonPin);
      // compare the buttonState to its previous state
      if (buttonState != lastButtonState)
      {
         if (buttonState == LOW)
         {
            // if the current state is LOW then the button
            // went from off to on:
            buttonPushCounter++;  // add one to counter
            // if counter over number of messages, reset the counter to message 0
            if (buttonPushCounter >= messageNum)
            {
               buttonPushCounter = 0;
            }
            //Serial.println(buttonPushCounter);
         }
      }
      lastButtonState = buttonState;
   }
}

Debugging the Code

Unfortunately this particular code only reads the button state at the end of each scroll.  This is where an interrupt is going to be necessary.  The arduino Uno and Nano boards that I have access to are only enabled for interrupts on digital pin 2s and 3 and will necessitate a bit of a rethink in the code 

MAX7219 Case - Thingiverse: Thing 6809712

No one wants to live in a run down cyberpunk world with exposed wires everywhere, so I needed a case for the display with enough depth to house the nano and the button which would switch modes.

I found a simple MAX7219 8x32 case on Thingiverse which I could easily embed magnets into to affix to the top or side of my Mega City Block Storage Case.  Sadly this did not fit my particular MAX7219 board as the pins came out sideways.  

This was easily fixed with a bit of modelling in Sketchup and if you need a case and have side exit pins feel free to download this from Thingiverse using the link above.


No comments:

Post a Comment