RGB Matrix Display Arduino Sketch

Definitions and Variables

// rgb matrix display - 64x32 envirinmental display


// Library written by Limor Fried/Ladyada & Phil Burgess/PaintYourDragon

// for Adafruit Industries.

// BSD license, all text above must be included in any redistribution.

// John Saunders 4/23/2020 Garage fan change, added clear notification

// John Saunders 5/20/2020 added 4 more fields from the solar Sensor r message

// 5/7/2020. Key OF for night page. Added Bluetooth Speaker and Girl Fountain Pump notification

// Flashing and Bullseye notifications were interchanged. Magenta for door "UP"

// 5/29/2021 Bullseye changed to Missions

// Mike Mitchell's advice is much appreciated

#include <RGBmatrixPanel.h>

#include <Wire.h> //I2C library

#define TRUE 1

#define FALSE 0

// **************************************  hardware definitions ******************************

// **************************************  the rgb matrix ************************************

#define CLK 11 // Using an ARDUINO MEGA 2560

#define OE   9

#define LAT 10

#define A   A0

#define B   A1

#define C   A2

#define D   A3

RGBmatrixPanel matrix(A, B, C, D, CLK, LAT, OE, true, 64);     // For Mega with its 8K RAM

// ************************************** data acquisition ***********************************

// **************************************  External data from the Picax **********************

// The Picaxe sub-assembly gets sensor values from several remote sources via 433 MHz transmissions

// I consolidates them into a single message and sends that to the Arduino, via I2C

// The Picaxe is in Master mode, since it does not do slave

#define megaReady 19    // This pin controls Picaxe = Arduino communications

#define I2Caddr 0x07

// **************************************  External data storage **********************

typedef struct {

  char modeCommand;

  char event;

  char tDate[6];

  char tTime[6];

  char sTemp[4];

  char sHum[4];

  char sMA[4];

  char battV[5];

  char gTemp[5];

  char aPress[6];

  char chgVolt[5];

  byte discretes;

} eData_t;


eData_t eData = { 'G', 'z', {"02/67"}, {"05:30"}, {"033"}, {"026"}, {"077"}, {"6.45"}, {"456"}, {"29.56"}, {"12.3"}};


/int num_byte;

Functions

/ ************************************** function called on message received ***********************************

volatile int loopCount;

char BLZ(char c) {              // Some leading zeroes are blanked for appearance purposes

  char rv = c;

  if (c == '0') {

    rv = ' ';

  }

  return rv;

}


void receiveEvent(int HowMany) {

  Serial.println(loopCount);

  num_byte = Wire.available();

  Serial.println(num_byte);

  char m = Wire.read();

  digitalWrite(megaReady, LOW);

  if ((m >= 'A') && (m <= 'G')) {

    eData.modeCommand = m;

  }

  else {

    eData.modeCommand = 'J';

  }

  eData.event = Wire.read();

  eData.tDate[0] = BLZ(Wire.read());  eData.tDate[1] = Wire.read();

  eData.tDate[3] = Wire.read();  eData.tDate[4] = Wire.read();

  eData.tTime[0] = BLZ(Wire.read());  eData.tTime[1] = Wire.read();

  eData.tTime[3] = Wire.read();  eData.tTime[4] = Wire.read();

  eData.sTemp[0] = BLZ( Wire.read());  eData.sTemp[1] = Wire.read(); eData.sTemp[2] = Wire.read();

  eData.sHum[0] = BLZ(Wire.read());  eData.sHum[1] = Wire.read(); eData.sHum[2] = Wire.read();

  eData.sMA[0] = BLZ(Wire.read());  eData.sMA[1] = Wire.read(); eData.sMA[2] = Wire.read();

  eData.battV[0] = Wire.read();  eData.battV[2] = Wire.read(); eData.battV[3] = Wire.read();

  eData.gTemp[0] = BLZ(Wire.read());  eData.gTemp[1] = Wire.read(); eData.gTemp[2] = Wire.read();

  eData.aPress[1] = Wire.read();  eData.aPress[3] = Wire.read(); eData.aPress[4] = Wire.read();

  eData.chgVolt[0] = BLZ(Wire.read());  eData.chgVolt[1] = Wire.read(); eData.chgVolt[3] = Wire.read();

  eData.discretes = Wire.read();

  if (eData.aPress[1] > '5') {

    eData.aPress[0] = '2';

  }

  else {

    eData.aPress[0] = '3';

  }

  loopCount = 0;

}


// ************************************** Internal HIH6130 temperature-humidity sensor ******************************

byte iHum, iTemp;          // Sensor values in integer go here

byte fetch_humidity_temperature()

{

  float RH, T_C;

  byte address, Hum_H, Hum_L, Temp_H, Temp_L, _status;

  unsigned int H_dat, T_dat;

  address = 0x27;;

  Wire.beginTransmission(address);

  Wire.endTransmission();

  delay(100);


  Wire.requestFrom((int)address, (int) 4);

  Hum_H = Wire.read();

  Hum_L = Wire.read();

  Temp_H = Wire.read();

  Temp_L = Wire.read();

  Wire.endTransmission();


  _status = (Hum_H >> 6) & 0x03;

  Hum_H = Hum_H & 0x3f;

  H_dat = (((unsigned int)Hum_H) << 8) | Hum_L;

  T_dat = (((unsigned int)Temp_H) << 8) | Temp_L;

  T_dat = T_dat / 4;

  RH = (float) H_dat * 6.10e-3;

  iHum = (byte)RH;

  T_C = (float) T_dat * 1.007e-2 - 40.0;

  iTemp = (byte) ((T_C * 1.8) + 32);

  return (_status);

}


// ************************************** Optional diagnostic printout ******************************

void printout(void) {

  int i;

  // char c;

  Serial.print("Mode=");

  Serial.print(eData.modeCommand, BIN);

  Serial.print(",Event=");

  Serial.println(eData.event);

  Serial.print((char*)eData.tDate);

  Serial.print(',');

  Serial.println((char*)eData.tTime);

  Serial.print("Outside Temperature=");

  Serial.print((char*)eData.sTemp);

  Serial.print(",Outside Humidity=");

  Serial.print((char*)eData.sHum);

  Serial.print(",Atmospheric pressure=");

  Serial.println((char*)eData.aPress);

  Serial.print("Solar Current=");

  Serial.print((char*)eData.sMA);

  Serial.print(",Battery Voltage=");

  Serial.print((char*)eData.battV);

  Serial.print(",Charging Voltage=");

  Serial.println((char*)eData.chgVolt);

  Serial.print("Garage Temperature=");

  Serial.print((char*)eData.gTemp);

}

// ************************************** Text colors and dimming ******************************

int brightness;               // part of index into the color taqble

#define lDim 2

#define lNormal 0

#define lBright 1

#define ulLimit 130

#define llLimit 70


typedef struct {

  uint8_t rVal;

  uint8_t gVal;

  uint8_t bVal;

} SM_RGB;


enum colorList {black, red, blue, magenta, green, yellow, cyan, white};

// color table -- black, red, green, yellow, blue, magenta, cyan, white

// Three different intensities, normal, bright, dim.Color is 5-6-5

const SM_RGB colorTable[] = {

  { 32,  32,  32}, {100,   0,   0}, {  0, 100,   0}, {100, 100,   0},

  {  0,   0, 84}, {100,   0, 100}, {  0, 100, 100}, {100, 100, 100},


  { 64,  64,  64}, {255,   0,   0}, {  0, 255,   0}, {255, 255,   0},

  {  0,   0, 255}, {255,   0, 255}, {  0, 255, 255}, {255, 255, 255},


  {  0,   0,   0}, {32,   0,   0}, {  0, 32,   0}, {32, 32,   0},

  {  0,   0,  16}, {32,   0, 32}, {  0, 32, 32}, {32, 32, 32}

};


uint16_t getColorVal(byte colorIndex) {

  uint16_t colorVal;

  int tableIndex = (8 * brightness) + colorIndex;

  colorVal = (((colorTable[tableIndex].rVal) & 0xf8) << 8) |

             (((colorTable[tableIndex].gVal) & 0xfc) << 3) |

             (((colorTable[tableIndex].bVal) & 0xf8) >> 3);

  return colorVal;

}

// ************************************** Page Formatting ******************************


typedef struct {

  byte fCol;                    // column to left

  byte fRow;                    // top row

  byte fColor;                  // character color

  char *fData;

} item_t;


byte hotColor;

item_t pageA[11] = {{ 0, 0, white, eData.tTime}, { 35, 0, white, eData.tDate},

  { 5, 8, green, "-"}, { 0, 8, green, "E"}, { 9, 8, green, "Temp"}, { 37, 8, white, eData.sTemp}, { 59, 8, magenta, "F"},

  { 5, 16, green, "-"}, { 0, 16, green, "I"}, { 9, 16, green, "Temp"}, { 59, 16, magenta, "F"}

};

item_t pageB[11] = {{ 0, 0, white, eData.tTime}, { 35, 0, white, eData.tDate},

  { 5, 8, green, "-"}, { 0, 8, green, "E"}, { 9, 8, green, "Hum"}, { 37, 8, green, eData.sHum}, { 59, 8, green, "%"},

  { 5, 16, green, "-"}, { 0, 16, green, "I"}, { 9, 16, green, "Hum"}, { 59, 16, magenta, "%"}

};

item_t pageC[7] = {{ 0, 0, white, eData.tTime}, { 35, 0, white, eData.tDate},

  { 0, 8, white, eData.aPress}, { 36, 8, magenta, "inHg"},

  { 0, 16, magenta, "Solar"}, {34, 16, white, eData.sMA}, { 53, 16, cyan, "MA"},


};

item_t pageD[11] = {{5, 0, green, "-"}, { 0, 0, green, "G"}, { 9, 0, green, "Fan"},

  { 5, 8, green, "-"}, { 0, 8, green, "G"}, { 9, 8, green, "Temp"}, {37, 8, hotColor, eData.gTemp}, { 59, 8, green, "F"},

  { 5, 16, green, "-"}, { 0, 16, green, "G"}, { 10, 16, green, "Door"}

};

item_t pageE[8] = {{ 0, 0, red, eData.tTime}, { 35, 0, red, eData.tDate},

  { 0, 8, green, "Batt"}, { 34, 8, white, eData.battV}, { 59, 8, green, "V"},

  { 0, 16, green, "Charg"}, {34, 16, white, eData.chgVolt}, { 59, 16, green, "V"}

};

item_t pageG[1] = {20, 12, blue, eData.tTime};


item_t pageJ[4] = {{ 0, 0, red, "Made In"}, { 0, 8, red, "2019 By"}, { 0, 16, red, "John"}, { 0, 24, red, "Saunders"}

};

item_t *f;


void dispStrng(int i) {                             // For strings defined in page arrays

  matrix.setTextColor(getColorVal(f->fColor));

  matrix.setCursor(f->fCol, f->fRow);

  matrix.print(f->fData);

}

void dispNum(int col, int row, byte color, int dat) {  // For binary values

  matrix.setTextColor(getColorVal(color));

  matrix.setCursor(col, row);

  matrix.print(dat, DEC);

}

// ************************************** Notifications ******************************

// The notification is in two parts, unit and command, per the universal control

//                             0        1        2       3       4       5         6       7

const  char  *unitStr[]  = {"Shelf", "Flash", "Temps", "Cube", "Pole", "Circle", "Eggs", "Hang",

                            "Hums", "Solar", "Pineaple", "Ceiling", "Missions", "Floor", "Gate", "Door", "Clear", "Speaker", "Pump"

                           };

//                            8       9         10          11         12         13       14      15      16       17      18


//                           0     1       2      3       4       5        6       7       8       9

const  char  *actStr[]  = {"On", "Off", "Down", "Red", "Blue", "Siren", "Green", "Open", "Shut", "Up"};


typedef struct {

  char cmd;

  byte firstIndx;

  byte sndIndx;

} note_t;


note_t notifications[] = { {'e', 3, 4}, {'D', 3, 6}, {'H', 3, 1}, {'Q', 14, 7}, {'B', 14, 8}, {'A', 3, 3}, {'Y', 1, 0}, {'W', 1, 1}, {'P', 5, 0}, {'l', 5, 1},

  {'d', 6, 0}, {'9', 6, 1}, {'M', 12, 0}, {'g', 12, 1}, {'R', 11, 0}, {'G', 11, 1}, {'I', 7, 0}, {'C', 7, 1}, {'h', 3, 6}, {'8', 10, 1},

  {'K', 10, 0}, {'k', 4, 1}, {'i', 4, 0}, {'f', 13, 1}, {'b', 13, 0}, {'F', 0, 1}, {'E', 0, 0}, {'m', 16, 0}, {'J', 16, 1}, {'U', 17, 1}, {'S', 17, 0},

  {'T', 18, 1}, {'j', 18, 0}, {'z', 0, 0}

};

void dispNot(void) {

  byte indx = 0;

  //  byte firstIndx;

  //  byte secondIndx;

  while ((eData.event != notifications[indx].cmd) && (notifications[indx].cmd != 'z')) {

    indx++;

  }

  if (notifications[indx].cmd != 'z') {

    matrix.setTextColor(getColorVal(red));

    matrix.setCursor(0, 24);

    matrix.print((char *)unitStr[notifications[indx].firstIndx]);

    matrix.print(' ');

    matrix.print((char *)actStr[notifications[indx].sndIndx]);

  }

}

Setup and Loop

// ************************************** Setup and Loop ******************************

void setup() {

  Serial.begin(9600);

  matrix.begin();

  matrix.setTextWrap(false); // Allow text to run off right edge

  matrix.setTextSize(0);

  matrix.fillScreen(0);     // Clear background

  Wire.begin(I2Caddr);

  Wire.onReceive(receiveEvent);

  pinMode(megaReady, OUTPUT);

  digitalWrite(megaReady, LOW);

  loopCount = 0;

  eData.modeCommand = 'C';

  delay(1000);

}


// Pick apart the mode command

#define cmdMask 0x07

#define doorMask 0x08

#define hotMask 0x10

#define fanMask 0x20

#define tAgeMask 0x40

#define sAgeMask 0x80


void loop() {

  byte _status;

  if (loopCount == 2) {

    digitalWrite(megaReady, HIGH);

  }

  if (loopCount == 1) {

    _status = fetch_humidity_temperature();

  }

  brightness = lNormal;

  matrix.fillScreen(0);     // Clear background

  switch (eData.modeCommand) {

    case 'C':

      if ((eData.discretes & tAgeMask) > 0) {

        pageA[0].fColor = red;

      }

      else {

        pageA[0].fColor = white;

      }

      if  ((eData.discretes & sAgeMask) > 0)  {

        pageA[5].fColor = red;

      }

      else {

        pageA[5].fColor = white;

      }

      for (int i = 0; i < 11; i++) {

        f = &pageA[i];

        dispStrng(i);

      }

      matrix.drawCircle(56, 9, 1, getColorVal(magenta));

      matrix.drawCircle(56, 17, 1, getColorVal(magenta));

      dispNum( 37, 16, white, iTemp);

      dispNot();

      break;


    case 'D':

      for (int i = 0; i < 11; i++) {

        f = &pageB[i];

        dispStrng(i);

      }

      dispNum( 37, 16, white, iHum);

      dispNot();

      break;


    case 'E':

      for (int i = 0; i < 9; i++) {

        f = &pageC[i];

        dispStrng(i);

      }

      dispNot();

      break;


    case 'A':

      if  ((eData.discretes & hotMask) > 0)  {

        pageD[6].fColor = red;

      }

      else {

        pageD[6].fColor = blue;

      }

      for (int i = 0; i < 11 ; i++) {

        f = &pageD[i];

        dispStrng(i);

      }

      matrix.drawCircle(56, 9, 1, getColorVal(green));

      matrix.setCursor (38, 16);

      if ((eData.discretes & doorMask) > 0) {

        matrix.setTextColor(getColorVal(magenta));

        matrix.print("Up");

      }

      else {

        matrix.setTextColor(getColorVal(green));

        matrix.print("Down");

      }

      matrix.setCursor (32, 0);

      if ((eData.discretes & fanMask) > 0) {

        matrix.setTextColor(getColorVal(red));

        matrix.print("Run");

      }

      else {

        matrix.setTextColor(getColorVal(green));

        matrix.print("Stop");

      }

      dispNot();

      break;


    case 'B':

      for (int i = 0; i < 10; i++) {

        f = &pageE[i];

        dispStrng(i);

      }

      dispNot();

      break;


    case 'F':

    default:

      f = &pageG[0];

      dispStrng(0);

      break;

  }


  delay(200);

  matrix.swapBuffers(true);

  loopCount++;

  if (loopCount > 300) {

    loopCount = 0;

  }

}