Tuesday, 24 April 2018

Using SPI to interface the ESP-12E to the MAX7219 LED display (updated 2019-03-24)

From top: ESP-12E Nodemcu, middle: Level Converter, bottom: MAX7219 8-digit 7-segment display
You will need an ESP-12E NodeMCU ESP8266, a 4-channel level converter and a MAX7219 7-segment LED display.

2019-03-24 update: it was difficult to start the ESP-12E program, and the problem is that SS, or D8 or GPIO 15 must be pulled low on power up. The ESP-12E has a voltage divider doing this but when the voltage level converter is plugged in the this did not work well. To fix this, I used GPIO 12 or D6 instead of D8. Now D8 is usually used as SPI  MISO but the MAX7219 does not use it.

 The modified wiring is now as follows:
   GPIO    NodeMCU   Name  |   MAX7219
   ===================================
     12       D6                MISO  |   CS
     13       D7                MOSI  |   DIN
     15       D6                SS        |   Not connected
     14       D5                SCK    |   CLK

Since the MAX7219 is a 5V device and the ESP-12E a 3.3V you will need a level converter in between. I used one based on 4 MOSFETs, covered in some detail here.

The MAX7219 draws quite a bit of power so it is advisable to have a separate power source from the ESP-12E. I used a 3A D-Link USB 3.0 hub.

I based my program on the sample code in the NodeMCU Lua sample code 'SPISlave_SafeMaster'  that came with the Arduino IDE.

With the level converter connected, the ESP-12E would not program, so I ended up having to unplug the 3.3V side of the level converter before programming.

The program merely initializes the MAX7219, displays '12345678', then triggers the MAX7219's built-in test function (lights up everything with maximum brightness). The built-in test requires a relatively high-ampere 5V supply.

The program is a Lua sketch, and requires the Arduino IDE. I used a custom-built Slackware Linux version, but there are stock Linux and Windoes versions that work the same.

The program is:

    SPI Safe Master Demo Sketch
    Connect the SPI Master device to the following pins on the esp8266:

*/
#include <SPI.h>

class ESP_MAX7219
{
private:
    uint8_t _ss_pin;
    void SS_High()
    {
        digitalWrite(_ss_pin, HIGH);
    }
    void SS_Low()
    {
        digitalWrite(_ss_pin, LOW);
    }
 
public:
    ESP_MAX7219(uint8_t pin):_ss_pin(pin) {}
    void begin()
    {
        pinMode(_ss_pin, OUTPUT);
        SS_High(); // Default to high
    }

    void writeData(const uint8_t MSB, const uint8_t LSB)
    {
        SS_Low();
        SPI.transfer(MSB);      
        SPI.transfer(LSB);
        SS_High();
    }
};

ESP_MAX7219 esp(12); // 2019-03-24 changed from ESP_MAX7219 esp(SS);

 
void send(const uint8_t msb, const uint8_t lsb)
{
    esp.writeData(msb, lsb);
    delay(10);
    // Serial.print("Slave: ");
    // Serial.println(esp.readData());
    // Serial.println();
}

void setup()
{
    Serial.begin(115200);
    SPI.begin();
    esp.begin();
    delay(1000);
    send(0x0C, 0x01); // Normal Operation
}

void loop()
{
    delay(1000);
    send(0x0C, 0x01); // Normal Operation
    Serial.println("Shutdown off");
    delay(1000);
    send(0x09, 0xFF);
    Serial.println("BCD Mode all 8 digits");
    delay(1000);
    send(0x0A, 0x03);
    Serial.println("Quarter brightness");
    delay(1000);
    send(0x0B, 0x07);
    Serial.println("8 Digit Scan");
    delay(1000);
    send(0x0F, 0x01);
    Serial.println("Test mode on");
    delay(1000);
    send(0x0F, 0x00);
    Serial.println("Test mode off");
    delay(1000);
    send(0x01, 0x08);
    Serial.println("Digit 8");
    send(0x02, 0x07);
    Serial.println("Digit 7");
    send(0x03, 0x06);
    Serial.println("Digit 6");
    send(0x04, 0x05);
    Serial.println("Digit 5");
    send(0x05, 0x04);
    Serial.println("Digit 4");
    send(0x06, 0x03);
    Serial.println("Digit 3");
    send(0x07, 0x02);
    Serial.println("Digit 2");
    send(0x08, 0x01);
    Serial.println("Digit 1");

    /* send(0x0C, 0x00);
    delay(3000);
    Serial.println("Shutdown on"); */
 
    send(0x0C, 0x01);
    Serial.println("Shutdown off");
    delay(3000);
}

There are plenty of other projects out there using the MAX7219, but I could not find one that uses the ESP-12E (or ESP8266). The MAX7219 uses SPI which seems to be gradually being replaced by I2C. This has been tested and worked for me, but turned out to be harder than I thought, but that is another blog post.

Happy Trails.

No comments:

Post a Comment