Hardware components | ||||||
![]() |
| × | 1 | |||
| × | 1 | ||||
Software apps and online services | ||||||
![]() |
|
I had been building various projects using the Maxx7219 led matrix boards, some projects required me to twist my board around so that the output was "upright". I looked into the LedControl library and found that there was no command to rotate the display output so I sat down and altered the methods setRow, setColumn and setLed to output what would happen if you physically rotated the dispaly 90 degrees clockwise, 90 degrees anti-clockwise and 180 degrees. I added all the code into the original LedControl.cpp file surrounding each with #ifdef #endif statements. Now if I need to rotate the display I just comment out the unwanted #define and uncomment the one for the rotation I needed.
Hardware:The hardware consists of an Arduino Nano and a single Maxx7219 unit.
The wiring is set up to use the Nano SPI internal hardware.
The connections are:
Vcc to Nano 5V
Gnd to Nano Gnd
Din to Nano pin 11
Cs to Nano pin 10
Clk to Nano pin 13
Software:I have included a small demo program for this library it draws:
- a single dot at position 0, 0 (row, column)
- a single dot at position 2, 1 (row, column)
- 4 dots at the end of row 1
- 3 dots at the top of column 2
As you alter the library file you will see the pattern rotate.
Installation:Just drop in the file over the top of the existing LedControl.cpp file; on my machine this sits in the folder Arduino->libraries->LedControl->src.
Use:Build your project and look at the resulting display if it is Ok do nothing otherwise decide which way you need to rotate for it to look correct.
In the LedControl.cpp file (Arduino->libraries->LedControl->src) locate and comment out the wrong orientation and uncomment out the correct orientation, save your work and rebuild your project.
/*
* LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
* Copyright (c) 2007 Eberhard Fahle
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* This permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "LedControl.h"
// Modified to allow display rotation
#define normal
//#define clockwise_90
//#define anti_clockwise_90
//#define one_eighty
//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
LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
SPI_MOSI=dataPin;
SPI_CLK=clkPin;
SPI_CS=csPin;
if(numDevices<=0 || numDevices>8 )
numDevices=8;
maxDevices=numDevices;
pinMode(SPI_MOSI,OUTPUT);
pinMode(SPI_CLK,OUTPUT);
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
for(int i=0;i<64;i++)
status[i]=0x00;
for(int i=0;i<maxDevices;i++) {
spiTransfer(i,OP_DISPLAYTEST,0);
//scanlimit is set to max on startup
setScanLimit(i,7);
//decode is done in source
spiTransfer(i,OP_DECODEMODE,0);
clearDisplay(i);
//we go into shutdown-mode on startup
shutdown(i,true);
}
}
int LedControl::getDeviceCount() {
return maxDevices;
}
void LedControl::shutdown(int addr, bool b) {
if(addr<0 || addr>=maxDevices)
return;
if(b)
spiTransfer(addr, OP_SHUTDOWN,0);
else
spiTransfer(addr, OP_SHUTDOWN,1);
}
void LedControl::setScanLimit(int addr, int limit) {
if(addr<0 || addr>=maxDevices)
return;
if(limit>=0 && limit<8)
spiTransfer(addr, OP_SCANLIMIT,limit);
}
void LedControl::setIntensity(int addr, int intensity) {
if(addr<0 || addr>=maxDevices)
return;
if(intensity>=0 && intensity<16)
spiTransfer(addr, OP_INTENSITY,intensity);
}
void LedControl::clearDisplay(int addr) {
int offset;
if(addr<0 || addr>=maxDevices)
return;
offset=addr*8;
for(int i=0;i<8;i++) {
status[offset+i]=0;
spiTransfer(addr, i+1,status[offset+i]);
}
}
#ifdef normal
void LedControl::setLed(int addr, int row, int column, boolean state) {
int offset;
byte val=0x00;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7 || column<0 || column>7)
return;
offset=addr*8;
val=B10000000 >> column;
if(state)
status[offset+row]=status[offset+row]|val;
else {
val=~val;
status[offset+row]=status[offset+row]&val;
}
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setRow(int addr, int row, byte value) {
int offset;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7)
return;
offset=addr*8;
status[offset+row]=value;
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setColumn(int addr, int col, byte value) {
byte val;
if(addr<0 || addr>=maxDevices)
return;
if(col<0 || col>7)
return;
for(int row=0;row<8;row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,row,col,val);
}
}
#endif
#ifdef clockwise_90
// rotate display 90 degrees clockwise
void LedControl::setLed(int addr, int row, int column, boolean state) {
int temp=0;
temp=row;
row=column;
column=temp;
column=7-column;
int offset;
byte val=0x00;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7 || column<0 || column>7)
return;
offset=addr*8;
val=B10000000 >> column;
if(state)
status[offset+row]=status[offset+row]|val;
else {
val=~val;
status[offset+row]=status[offset+row]&val;
}
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setColumn(int addr, int col, byte value) {
int row=col;
//byte reversal code
byte temp=B00000000;
if(value&B10000000){temp|=1<<0;}
if(value&B01000000){temp|=1<<1;}
if(value&B00100000){temp|=1<<2;}
if(value&B00010000){temp|=1<<3;}
if(value&B00001000){temp|=1<<4;}
if(value&B00000100){temp|=1<<5;}
if(value&B00000010){temp|=1<<6;}
if(value&B00000001){temp|=1<<7;}
value=temp;
//end byte reversal code
int offset;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7)
return;
offset=addr*8;
status[offset+row]=value;
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setRow(int addr, int row, byte value) {
int col=row;
byte val;
if(addr<0 || addr>=maxDevices)
return;
if(col<0 || col>7)
return;
for(int row=0;row<8;row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,col,row,val);
}
}
#endif
#ifdef anti_clockwise_90
//rotate display 270 degrees (90 degrees counter clockwise)
void LedControl::setLed(int addr, int row, int column, boolean state) {
int temp=row;
row=column;
column=temp;
row=7-row;
int offset;
byte val=0x00;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7 || column<0 || column>7)
return;
offset=addr*8;
val=B10000000 >> column;
if(state)
status[offset+row]=status[offset+row]|val;
else {
val=~val;
status[offset+row]=status[offset+row]&val;
}
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setColumn(int addr, int col, byte value) {
int row=col;
row=7-row;
int offset;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7)
return;
offset=addr*8;
status[offset+row]=value;
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setRow(int addr, int row, byte value) {
int col=row;
byte val;
if(addr<0 || addr>=maxDevices)
return;
if(col<0 || col>7)
return;
for(int row=0;row<8;row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,col,row,val);
}
}
#endif
#ifdef one_eighty
// rotate display 180 degrees
void LedControl::setLed(int addr, int row, int column, boolean state) {
row=7-row;
column=7-column;
int offset;
byte val=0x00;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7 || column<0 || column>7)
return;
offset=addr*8;
val=B10000000 >> column;
if(state)
status[offset+row]=status[offset+row]|val;
else {
val=~val;
status[offset+row]=status[offset+row]&val;
}
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setRow(int addr, int row, byte value) {
row=7-row;
//byte reversal code
byte temp=B00000000;
if(value&B10000000){temp|=1<<0;}
if(value&B01000000){temp|=1<<1;}
if(value&B00100000){temp|=1<<2;}
if(value&B00010000){temp|=1<<3;}
if(value&B00001000){temp|=1<<4;}
if(value&B00000100){temp|=1<<5;}
if(value&B00000010){temp|=1<<6;}
if(value&B00000001){temp|=1<<7;}
value=temp;
//end byte reversal code
int offset;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7)
return;
offset=addr*8;
status[offset+row]=value;
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setColumn(int addr, int col, byte value) {
byte val;
if(addr<0 || addr>=maxDevices)
return;
if(col<0 || col>7)
return;
for(int row=0;row<8;row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,row,col,val);
}
}
#endif
// The seven segment display functions have not been altered
void LedControl::setDigit(int addr, int digit, byte value, boolean dp) {
int offset;
byte v;
if(addr<0 || addr>=maxDevices)
return;
if(digit<0 || digit>7 || value>15)
return;
offset=addr*8;
v=pgm_read_byte_near(charTable + value);
if(dp)
v|=B10000000;
status[offset+digit]=v;
spiTransfer(addr, digit+1,v);
}
void LedControl::setChar(int addr, int digit, char value, boolean dp) {
int offset;
byte index,v;
if(addr<0 || addr>=maxDevices)
return;
if(digit<0 || digit>7)
return;
offset=addr*8;
index=(byte)value;
if(index >127) {
//no defined beyond index 127, so we use the space char
index=32;
}
v=pgm_read_byte_near(charTable + index);
if(dp)
v|=B10000000;
status[offset+digit]=v;
spiTransfer(addr, digit+1,v);
}
void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
//Create an array with the data to shift out
int offset=addr*2;
int maxbytes=maxDevices*2;
for(int i=0;i<maxbytes;i++)
spidata[i]=(byte)0;
//put our device data into the array
spidata[offset+1]=opcode;
spidata[offset]=data;
//enable the line
digitalWrite(SPI_CS,LOW);
//Now shift out the data
for(int i=maxbytes;i>0;i--)
shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
//latch the data onto the display
digitalWrite(SPI_CS,HIGH);
}
//We always have to include the library
#include "LedControl.h"
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin xx is connected to the DataIn
pin xx is connected to the CLK
pin xx is connected to LOAD
We have 2 MAX72XX.
*/
// Matrix
#define PIN_DATAIN 11
#define PIN_CLK 13
#define PIN_LOAD 10
LedControl lc = LedControl(PIN_DATAIN, PIN_CLK, PIN_LOAD, 2);
/* we always wait a bit between updates of the display */
unsigned long delaytime=100;
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
}
void loop() {
//lc.clearDisplay(0);
lc.setLed(0,0,0,true);//setLed(int addr, int row, int column, boolean state)
lc.setLed(0,2,1,true);//setLed(int addr, int row, int column, boolean state)
//delay(1000);
//lc.clearDisplay(0);
lc.setRow(0,1,B00001111);//setRow(int addr, int row, byte value)
//delay(1000);
//lc.clearDisplay(0);
lc.setColumn(0,2,B00000111);//setColumn(int addr, int col, byte value)
delay(100000);
}
Comments
Please log in or sign up to comment.