Components and supplies
AS1115 3-Character Red LED 7-Segment Hexidecimal Display
Arduino UNO
Project description
Code
Setting things up
c_cpp
The main class of our interest will be the Display - it's responsible for setup of MAX chips and provides API for painting. Before we start painting it's necessary to set thing up. Code below creates 2D array containing Select Slave lines and initializes display. The display itself consist of 3 rows, each one has 8 LED Modules. Obviously you can choose any responsible size, but I will stick to this one. The layout of mentioned 2D array corresponds to physical display: each LED Module has dedicated MAX chip, and each chip has dedicated Select Slave line. First dimension of our array indicates physical row on display, second dimension indicates LED Module within this row, and the value itself contains PIN number for Select Slave line. There is one more method worth mentioning: log_setup(). Whole project has quiet precise logger - so that you can see what is actually happening. By default it's disabled, in order to enable it check out its documentation: https://github.com/maciejmiklas/ArdLog
Communication with MAX72xxx
c_cpp
We are using standard SPI library and Select Slave line on MAX chip for addressing. MAX is configured in LED Matrix mode - so there is nothing special. The setup method can be found in: Display::setup()
Examples - Scrolling Text Mixed
c_cpp
This example is similar to one above, but this time we will display several scrolling areas: https://youtu.be/nanXzz2FVsY We have created few instances of ScrollingText8x8, each one containing different text and position on the display. In order to play animation you have to call cycle() on each instance, but you have to call only once flush(). Each call on cycle() will update it's part of the display and flush will send changed display to MAX chips.
Examples - Requires Libs
c_cpp
Examples are using ArdLog, so you have to import this lib into Arduino IDE. Here are instructions: https://github.com/maciejmiklas/ArdLog
Communication with MAX72xxx
c_cpp
We are using standard SPI library and Select Slave line on MAX chip for addressing. MAX is configured in LED Matrix mode - so there is nothing special. The setup method can be found in: Display::setup()
Examples - Single Scrolling Text
c_cpp
This time we are going to display area containing text that will scroll from left to right. Link below contains youtube video - you can start it by clicking on it. https://youtu.be/0sQ3GSuFi54 The initialization of the display is the same as in examples above, so it's omitted here. In order to display scrolling text we are using ScrollingText8x8. In setup() we are creating instance of this class and calling method scroll(...). This part only initializes scrolling, but does not play the animation itself. In order to play the animation you have to call cycle() and flush() in main loop and you must not have any additional delays there, otherwise you might get jagged animation. During creation of ScrollingText8x8 we have provided speed of animation - actually it's a delay of 50ms per frame. Now calling cycle() in main loop will produce frames of animation according to provided delay. When the time comes the method cycle() will update display and finally method flush() will send updated content to MAX chips. The whole implementation of ScrollingText8x8 is non blocking and it consumes CPU only when there is something to be done. Internally it's using simple State Machine. There is one last thing: you have to keep text used for animation in global variable in order to avoid garbage collection. It's not being copied in scroll() to avoid memory fragmentation.
Compiling
batchfile
We are using standard Arduino libraries, so they are already available, the only exception is ArdLog. You have to import this LIB into your IDE. This basically means, that you have to download right release: https://github.com/maciejmiklas/ArdLog/releases/tag/v1.0.0 and unzip it into folder, where you usually place external libraries. In case of standard Arduino IDE on Mac it's ~/Documents/Arduino/libraries. On the end you should have following structure:
Examples - Simple Bitmap
c_cpp
In this example we will display simple static bitmap with 8x8 pixels: https://github.com/maciejmiklas/LEDDisplay/blob/master/doc/img/dispV.jpg Here is the Arduino sketch: SimpleBitmap, now lest go over it: First we have to initialize display, as we have done in above in chapter Setting things up. Next we have to create data that can hold our bitmap - it will have 8x2 bytes. This gives us up to 8 lines and 16 horizontal pixels. But the size of our bitmap is 9x8 pixels (width x height) and this will be also the size of the painted rectangle. It should be as small as possible, so that you could place another bitmap right next to it. The display will obviously only paint the rectangle given by width/height and not whole data array. This is normal, that data array can hold more pixels than accrual size of out bitmap, because size of data is a multiplication o 8 and bitmap not necessary.
Painting on the display
c_cpp
Display consists of a few LED Modules, but form API perspective they are connected together into one continuous canvas. You can place on this canvas bitmap on any position given by standard x,y coordinates. The paint method has following syntax: paint(pixel_t x, pixel_t y, pixel_t width, pixel_t height, uint8_t data). It allows you to paint a bitmap on given coordinates with limited width and height. So you can for example paint a bitmap on (3,4) that has 25x3 pixels. It might be larger than a actual display size - in this case it will get trimmed. This is obvious and simple, but there is one catch - you have to provide right data. This is 2D array, where first dimension indicates vertical and second horizontal position on the display. Technically speaking data is flat array of pointers and each pointer points to array that represents one horizontal line on the display. Moving over first dimension of data traverses over lines of the display. The second dimension of data represents horizontal pixels within single line, where each byte represents 8 pixels. Since our display consist of simple LEDs they can be either in on or off state, so each pixel is not being represented by one byte, but by one bit. In order to cover 16 pixels in horizontal position we need two bytes, 24 pixels require 3 bytes, and so on. For example to fully cover display consisting of 8x3 LED kits (one used in our examples) we would need data[3][8]. Usually you will take array small enough to fit your bitmap and not one that will cover up whole display. The paint(...) method updates internal buffer, in order to send content of this buffer to MAX chips you have to call flush(). The idea behind is to give you possibility to display few bitmaps on the display and after that paint the result. You can program few independent routines, that will update different part of the display and flush all changes at once. Communication with MAX chips is not very fast and sending content of the whole display with every flush() is time consuming. You might be able to speed up this process by enabling double buffering (set DEOUBLE_BUFFER in Display.h to true). In this case flush() method will send only bytes that have changed, so you can call flush() with every loop and do not have to worry about loosing performance. The only drawback is increased usage of RAM: we are creating 2D array that allocates 8 bytes per each LED Kit plus few pointers that are usually required to maintain arrays. 2D arrays in this project have reduced memory footprint, because in order to create dynamic 2D array, we are creating actually 2 arrays with calculated offset (see: alloc2DArray8(....) in Util.h).
Compiling
batchfile
We are using standard Arduino libraries, so they are already available, the only exception is ArdLog. You have to import this LIB into your IDE. This basically means, that you have to download right release: https://github.com/maciejmiklas/ArdLog/releases/tag/v1.0.0 and unzip it into folder, where you usually place external libraries. In case of standard Arduino IDE on Mac it's ~/Documents/Arduino/libraries. On the end you should have following structure:
Examples - Requires Libs
c_cpp
Examples are using ArdLog, so you have to import this lib into Arduino IDE. Here are instructions: https://github.com/maciejmiklas/ArdLog
Examples - Static Text
c_cpp
Now we will display static text, actually those are going to be two independent lines. https://github.com/maciejmiklas/LEDDisplay/blob/master/doc/img/dispStatic.jpg Here you can find Arduino sketch containing whole example: StaticText. Your sketch needs setup method as we've already seen above (chapter: Setting things up), so we will not discus it again. In order to display text you should use StaticText8x8. Font is defined in: Font8x8, each character has 8x8 pixels. Your code could look like this one (plus initialization stuff from Setting things up):
Setting things up
c_cpp
The main class of our interest will be the Display - it's responsible for setup of MAX chips and provides API for painting. Before we start painting it's necessary to set thing up. Code below creates 2D array containing Select Slave lines and initializes display. The display itself consist of 3 rows, each one has 8 LED Modules. Obviously you can choose any responsible size, but I will stick to this one. The layout of mentioned 2D array corresponds to physical display: each LED Module has dedicated MAX chip, and each chip has dedicated Select Slave line. First dimension of our array indicates physical row on display, second dimension indicates LED Module within this row, and the value itself contains PIN number for Select Slave line. There is one more method worth mentioning: log_setup(). Whole project has quiet precise logger - so that you can see what is actually happening. By default it's disabled, in order to enable it check out its documentation: https://github.com/maciejmiklas/ArdLog
Examples - Simple Bitmap
c_cpp
In this example we will display simple static bitmap with 8x8 pixels: https://github.com/maciejmiklas/LEDDisplay/blob/master/doc/img/dispV.jpg Here is the Arduino sketch: SimpleBitmap, now lest go over it: First we have to initialize display, as we have done in above in chapter Setting things up. Next we have to create data that can hold our bitmap - it will have 8x2 bytes. This gives us up to 8 lines and 16 horizontal pixels. But the size of our bitmap is 9x8 pixels (width x height) and this will be also the size of the painted rectangle. It should be as small as possible, so that you could place another bitmap right next to it. The display will obviously only paint the rectangle given by width/height and not whole data array. This is normal, that data array can hold more pixels than accrual size of out bitmap, because size of data is a multiplication o 8 and bitmap not necessary.
Painting on the display
c_cpp
Display consists of a few LED Modules, but form API perspective they are connected together into one continuous canvas. You can place on this canvas bitmap on any position given by standard x,y coordinates. The paint method has following syntax: paint(pixel_t x, pixel_t y, pixel_t width, pixel_t height, uint8_t data). It allows you to paint a bitmap on given coordinates with limited width and height. So you can for example paint a bitmap on (3,4) that has 25x3 pixels. It might be larger than a actual display size - in this case it will get trimmed. This is obvious and simple, but there is one catch - you have to provide right data. This is 2D array, where first dimension indicates vertical and second horizontal position on the display. Technically speaking data is flat array of pointers and each pointer points to array that represents one horizontal line on the display. Moving over first dimension of data traverses over lines of the display. The second dimension of data represents horizontal pixels within single line, where each byte represents 8 pixels. Since our display consist of simple LEDs they can be either in on or off state, so each pixel is not being represented by one byte, but by one bit. In order to cover 16 pixels in horizontal position we need two bytes, 24 pixels require 3 bytes, and so on. For example to fully cover display consisting of 8x3 LED kits (one used in our examples) we would need data[3][8]. Usually you will take array small enough to fit your bitmap and not one that will cover up whole display. The paint(...) method updates internal buffer, in order to send content of this buffer to MAX chips you have to call flush(). The idea behind is to give you possibility to display few bitmaps on the display and after that paint the result. You can program few independent routines, that will update different part of the display and flush all changes at once. Communication with MAX chips is not very fast and sending content of the whole display with every flush() is time consuming. You might be able to speed up this process by enabling double buffering (set DEOUBLE_BUFFER in Display.h to true). In this case flush() method will send only bytes that have changed, so you can call flush() with every loop and do not have to worry about loosing performance. The only drawback is increased usage of RAM: we are creating 2D array that allocates 8 bytes per each LED Kit plus few pointers that are usually required to maintain arrays. 2D arrays in this project have reduced memory footprint, because in order to create dynamic 2D array, we are creating actually 2 arrays with calculated offset (see: alloc2DArray8(....) in Util.h).
Examples - Single Scrolling Text
c_cpp
This time we are going to display area containing text that will scroll from left to right. Link below contains youtube video - you can start it by clicking on it. https://youtu.be/0sQ3GSuFi54 The initialization of the display is the same as in examples above, so it's omitted here. In order to display scrolling text we are using ScrollingText8x8. In setup() we are creating instance of this class and calling method scroll(...). This part only initializes scrolling, but does not play the animation itself. In order to play the animation you have to call cycle() and flush() in main loop and you must not have any additional delays there, otherwise you might get jagged animation. During creation of ScrollingText8x8 we have provided speed of animation - actually it's a delay of 50ms per frame. Now calling cycle() in main loop will produce frames of animation according to provided delay. When the time comes the method cycle() will update display and finally method flush() will send updated content to MAX chips. The whole implementation of ScrollingText8x8 is non blocking and it consumes CPU only when there is something to be done. Internally it's using simple State Machine. There is one last thing: you have to keep text used for animation in global variable in order to avoid garbage collection. It's not being copied in scroll() to avoid memory fragmentation.
Examples - Scrolling Text Mixed
c_cpp
This example is similar to one above, but this time we will display several scrolling areas: https://youtu.be/nanXzz2FVsY We have created few instances of ScrollingText8x8, each one containing different text and position on the display. In order to play animation you have to call cycle() on each instance, but you have to call only once flush(). Each call on cycle() will update it's part of the display and flush will send changed display to MAX chips.
Downloadable files
Driving single LED Matrix Module
I've used the MAX7219 and 788BS LED Matrix, this is the one with common anode. The schematic below illustrates wiring of LEDs, MAX and Arduino
Driving single LED Matrix Module
The wiring
Each 3-PIN connector on schematic below symbolizes one module described in previous chapter (LED Matrix + MAX72xx), now we've connected all those modules together. All MAX722xx chips share common MOSI and SCK lines, MISO is not used, each chip occupies separate Slave Select line. All MAX722xx chips share common MOSI and SCK lines, MISO is not used, each chip occupies separate Slave Select line. All MAX722xx chips share common MOSI and SCK lines, MISO is not used, each chip occupies separate Slave Select line. The position of LED Matrix on the schematic above directly corresponds to their location on the physical display that I've used for testing. Additionally each module has description indicating it's position and Select Slave line, so for example: (2,1) SS: 35 gives us second module on third row (counting from zero) and PIN:35 on Arduino for Select Slave line. Here is the image in original size: https://github.com/maciejmiklas/LEDDisplay/blob/master/doc/fritzing/LED_Display_schem.png
The wiring
Driving single LED Matrix Module
I've used the MAX7219 and 788BS LED Matrix, this is the one with common anode. The schematic below illustrates wiring of LEDs, MAX and Arduino
Driving single LED Matrix Module
Driving single LED Matrix Module - different view
This one is equivalent, but instead of single LEDs we have PIN layout of LED Module It might happen, that your LED Module has common cathode, in this case you have to rewire connection to MAX chip. You just have to keep in mind, that MAX hat two sets of pins, that are relevant here: Dig0-Dig7 are supposed to be connected to cathodes (-) and SegA-SegG to anodes(+). Additionally such change will swap rows with columns within sine LED module.
Driving single LED Matrix Module - different view
Connecting all LED Matrix together
In the previous chapter we've seen how to connect single LED Module with MAX chip. Now we will connect multiple LED Modules together into one large display. Below is the physical display that I've used for testing and examples. Each LED Module has label indicating its position and Select Slave line.
Connecting all LED Matrix together
The wiring
Each 3-PIN connector on schematic below symbolizes one module described in previous chapter (LED Matrix + MAX72xx), now we've connected all those modules together. All MAX722xx chips share common MOSI and SCK lines, MISO is not used, each chip occupies separate Slave Select line. All MAX722xx chips share common MOSI and SCK lines, MISO is not used, each chip occupies separate Slave Select line. All MAX722xx chips share common MOSI and SCK lines, MISO is not used, each chip occupies separate Slave Select line. The position of LED Matrix on the schematic above directly corresponds to their location on the physical display that I've used for testing. Additionally each module has description indicating it's position and Select Slave line, so for example: (2,1) SS: 35 gives us second module on third row (counting from zero) and PIN:35 on Arduino for Select Slave line. Here is the image in original size: https://github.com/maciejmiklas/LEDDisplay/blob/master/doc/fritzing/LED_Display_schem.png
The wiring
Driving single LED Matrix Module - different view
This one is equivalent, but instead of single LEDs we have PIN layout of LED Module It might happen, that your LED Module has common cathode, in this case you have to rewire connection to MAX chip. You just have to keep in mind, that MAX hat two sets of pins, that are relevant here: Dig0-Dig7 are supposed to be connected to cathodes (-) and SegA-SegG to anodes(+). Additionally such change will swap rows with columns within sine LED module.
Driving single LED Matrix Module - different view
Connecting all LED Matrix together
In the previous chapter we've seen how to connect single LED Module with MAX chip. Now we will connect multiple LED Modules together into one large display. Below is the physical display that I've used for testing and examples. Each LED Module has label indicating its position and Select Slave line.
Connecting all LED Matrix together
Comments
Only logged in users can leave comments
miklas
0 Followers
•2 Projects
8
0