How to send proper commands to MAX7219?

Hi!

I pasted the relevant segment of my code below, i found it on the internet, i'm using a simple 4 digit, 7 segment LED display with a MAX7219.
I don't know however how to 'translate' between the manual for the IC and code.

For e.g. if i send the command 10 with a value of 0-15 i change the overall brightness of the display.
In the manual, on page 9 i found the corresponding table for the brightness change but i can't found the command 10 or anything else anywhere so i can't implement new functions in my code.

Now i want to turn off the display with code and then turn it on again, but i can't find the command for it.


Whole code is pasted too, but the relevant part is this:

void sendCommand(int command, int value) {
  digitalWrite(slaveSelect, LOW);
  SPI.transfer(command);
  SPI.transfer(value);
  digitalWrite(slaveSelect, HIGH);
}

Big code:

#include <SPI.h>

//#include "IRremote.hpp"
#include <SHT21.h>
#include <Arduino_LED_Matrix.h>
#include "animation.h"

ArduinoLEDMatrix matrix;
SHT21 sht;

const int buttonPin = 7;
const int potmeterPin = A1;
const int lightSensorPin = A0;
const int rgbRPin = 3; //PWM
const int rgbGPin = 5; //PWM
const int rgbBPin = 6; //PWM
const int irSensorPin = 4;
const int greenLedPin = 2;
const int buzzerPin = 8;
const int redLedPin = 9;
//A3 used for random seed generation!

const int slaveSelect = 12;
const int numberOfDigits = 4;

const int greenLedInterval = 500;
const int buzzerInterval = 100;
const int buttonInterval = 200;
const int LDRInterval = 100;
const int potInterval = 100;
const int pwmInterval = 1;
const int rgbFunInterval = 10;
const int displayRefreshInterval = 100;
const int irInterval = 5;
const int tempAndHumInterval = 500;

unsigned long currentMillis = 0;
unsigned long previousGreenLedMillis = 0;
unsigned long previousBuzzerMillis = 0;
unsigned long previousButtonMillis = 0;
unsigned long previousLDRMillis = 0;
unsigned long previousPotMillis = 0;
unsigned long previousPWMMillis = 0;
unsigned long previousRGBFun = 0;
unsigned long previousDisplayRefreshMillis = 0;
unsigned long previousIrMillis = 0;
unsigned long previousTempAndHumMillis = 0;

byte greenLedState = LOW;
byte buttonState = HIGH;
byte buzz = false;

int LDRValue;
int mappedLDRValue;
int potValue;
int mappedPotValue;
int pwmDuty;

int rgbRduty = 0;
int rgbGduty = 0;
int rgbBduty = 0;
byte rgbRUp = true;
byte rgbGUp = true;
byte rgbBUp = true;

float temp;
float humidity;

long randNumber;

//IRrecv irrecv(irSensorPin);
//decode_results results;

void setup() {
  Wire.begin();

  Serial.begin(9600);

  SPI.begin();

  //irrecv.enableIRIn();

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(potmeterPin, INPUT);
  pinMode(lightSensorPin, INPUT);
  pinMode(rgbRPin, OUTPUT);
  pinMode(rgbGPin, OUTPUT);
  pinMode(rgbBPin, OUTPUT);
  pinMode(irSensorPin, INPUT);
  pinMode(greenLedPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(redLedPin, OUTPUT);
  pinMode(slaveSelect, OUTPUT);

  digitalWrite(slaveSelect, LOW);
  sendCommand (12, 1); //normal mode (default is shutdown mode)
  sendCommand (15, 0); //display test off
  sendCommand (10, 0); //set light intensity (range is 0-15)
  sendCommand (11, numberOfDigits); //7219 digit scan limit command
  sendCommand (9, 255); //decode command, use standard 7-segment digits
  digitalWrite(slaveSelect, HIGH);

  randomSeed(analogRead(A3));

  matrix.loadSequence(dinosaur);
  matrix.begin();
  matrix.play(true);
}

void loop() {

  currentMillis = millis();

  //greenLedBlinking();
  buttonRead();
  LDR();
  potRead();
  //irReceiving();

  switchLED();
  pwm(redLedPin);
  //rgbFun();
  soundBuzzer();
  displayRefresh();

  readTempAndHum();

}

void greenLedBlinking() {
  if (greenLedState == LOW) {
    if(currentMillis - previousGreenLedMillis >= greenLedInterval) {
      greenLedState = HIGH;
      previousGreenLedMillis += greenLedInterval;
    } 
  } else {
    if(currentMillis - previousGreenLedMillis >= greenLedInterval) {
      greenLedState = LOW;
      previousGreenLedMillis += greenLedInterval;
    }
  }
}

void buttonRead() {
  if (currentMillis - previousButtonMillis >= buttonInterval) {
    if(digitalRead(buttonPin) == LOW) {

      buttonState = !buttonState;

      greenLedState = !greenLedState;

      buzz = true;
    }
    previousButtonMillis += buttonInterval;
  }
}

void LDR() {
  if(currentMillis - previousLDRMillis >= LDRInterval) {
    LDRValue = analogRead(lightSensorPin);

    mappedLDRValue = map(LDRValue, 1023, 0, 0, 15);

    previousLDRMillis += LDRInterval;
  }
}

void potRead() {
  if(currentMillis - previousPotMillis >= potInterval) {
    potValue = analogRead(potmeterPin);

    pwmDuty = potValue / 4;
    mappedPotValue = map(potValue, 0, 1023, 0, 100);

    previousPotMillis += potInterval;
  }
}

void switchLED() {
  digitalWrite(greenLedPin, greenLedState);
}

void pwm(int pwmPin) {
  if(currentMillis - previousPWMMillis >= pwmInterval) {
    analogWrite(pwmPin, pwmDuty);

    previousPWMMillis += pwmInterval;
  }
}

void rgbFun() {
  if(currentMillis - previousRGBFun >= rgbFunInterval) {
    randNumber = random(1, 4);
    
    switch(randNumber) {
      case 1:
        if(rgbRUp) {
          rgbRduty++;
          analogWrite(rgbRPin, rgbRduty);
          if(rgbRduty >= 255) rgbRUp = false;
        } else {
          rgbRduty--;
          analogWrite(rgbRPin, rgbRduty);
          if(rgbRduty <= 0) rgbRUp = true;
        }
        break;
      case 2:
        if(rgbGUp) {
          rgbGduty++;
          analogWrite(rgbGPin, rgbGduty);
          if(rgbGduty >= 255) rgbGUp = false;
        } else {
          rgbGduty--;
          analogWrite(rgbGPin, rgbGduty);
          if(rgbGduty <= 0) rgbGUp = true;
        }
        break;
      case 3:
        if(rgbBUp) {
          rgbBduty++;
          analogWrite(rgbBPin, rgbBduty);
          if(rgbBduty >= 255) rgbBUp = false;
        } else {
          rgbBduty--;
          analogWrite(rgbBPin, rgbBduty);
          if(rgbBduty <= 0) rgbBUp = true;
        }
        break;
    }

    previousRGBFun += rgbFunInterval;
  }
}

void soundBuzzer() {
  if(currentMillis - previousBuzzerMillis >= buzzerInterval) {
    if(buzz == true) {
      tone(buzzerPin, 1000);
      buzz = false;
    } else {
      noTone(buzzerPin);
    }
    previousBuzzerMillis += buzzerInterval;
  }
}

void displayRefresh() {
  if(currentMillis - previousDisplayRefreshMillis >= displayRefreshInterval) {

    sendCommand (10, map(potValue, 0, 1023, 0, 15)); //set light intensity (range is 0-15)
    displayNumber((int)temp*100+(int)humidity);

    previousDisplayRefreshMillis += displayRefreshInterval;
  }
}

void displayNumber (int number) {
  for (int i=0; i < numberOfDigits; i++) {
    byte character= number % 10; //get the value of the rightmost digit

    if (number == 0 && i > 0) {
      character = 0xf;
    }
      
    sendCommand(numberOfDigits-i, character);
    number= number/10;
    
  }
}

void sendCommand(int command, int value) {
  digitalWrite(slaveSelect, LOW);
  SPI.transfer(command);
  SPI.transfer(value);
  digitalWrite(slaveSelect, HIGH);
}

/*
void irReceiving() {
  if(currentMillis - previousIrMillis >= irInterval) {

    if (irrecv.decode(&results)) {
      Serial.println(results.value, DEC);
      dump(&results);
      irrecv.resume(); // Receive the next value
    }

    previousIrMillis += irInterval;
  }
}

//void dump(decode_results *results) {
  // Dumps out the decode_results structure.
  // Call this after IRrecv::decode()
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.print("Unknown encoding: ");
  }
  else if (results->decode_type == NEC) {
    Serial.print("Decoded NEC: ");
  }
  else if (results->decode_type == SONY) {
    Serial.print("Decoded SONY: ");
  }
  else if (results->decode_type == RC5) {
    Serial.print("Decoded RC5: ");
  }
  else if (results->decode_type == RC6) {
    Serial.print("Decoded RC6: ");
  }
  else if (results->decode_type == PANASONIC) {
    Serial.print("Decoded PANASONIC - Address: ");
    Serial.print(results->address, HEX);
    Serial.print(" Value: ");
  }
  else if (results->decode_type == LG) {
    Serial.print("Decoded LG: ");
  }
  else if (results->decode_type == JVC) {
    Serial.print("Decoded JVC: ");
  }
  else if (results->decode_type == AIWA_RC_T501) {
    Serial.print("Decoded AIWA RC T501: ");
  }
  else if (results->decode_type == WHYNTER) {
    Serial.print("Decoded Whynter: ");
  }

  Serial.print(results->value, HEX);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");
  
  for (int i = 1; i < count; i++) {
    if (i & 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.write('-');
      Serial.print((unsigned long) results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println();
}
*/

void readTempAndHum() {
  if(currentMillis - previousTempAndHumMillis >= tempAndHumInterval) {

    temp = sht.getTemperature();
    humidity = sht.getHumidity();

    previousTempAndHumMillis += tempAndHumInterval;
  }
}
2 Likes

Thanks, i found the OP codes for the MAX7219 in the source code for the linked library.

If anyone wondering:

//the opcodes for the MAX7221 and MAX7219
#define OP_NOOP   0
#define OP_DIGIT0 1
#define OP_DIGIT1 2
#define OP_DIGIT2 3
#define OP_DIGIT3 4
#define OP_DIGIT4 5
#define OP_DIGIT5 6
#define OP_DIGIT6 7
#define OP_DIGIT7 8
#define OP_DECODEMODE  9
#define OP_INTENSITY   10
#define OP_SCANLIMIT   11
#define OP_SHUTDOWN    12
#define OP_DISPLAYTEST 15

these are the OP codes according to table 2 in the data sheet.

I just wonder why you want to reinvent the wheel and do your implementation on your own.
There are several libraries out there for the MAX7219.

For example my MAX7219 library can use Software Bitbang (like LedControl) and HW-SPI.

See:
Arduino Noiasca LED Control with print method (MAX7219/MAX7221) (rothschopf.net)

Printing of numbers will get very easy with a simple

lc.print(foo);
1 Like

Also to help others confused by this, here is an article that will help: https://arduinoplusplus.wordpress.com/2019/06/08/using-the-max7219-in-your-projects-part-1/

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.