DIY beam from an LED matrix. Dynamic display

8x8 LED Matrix Displays come in a variety of sizes and are fun to work with. Large industrial assemblies measure around 60 x 60 mm. However, if you are looking for much larger LED matrices, they are difficult to find.

In this project we will be building a really large LED matrix LED display that is made up of several large 8x8 LED modules connected in series with each other. Each of these modules measures approximately 144 x 144 mm.

The special thing about this display is that you can look at the background behind it if necessary. This gives you the freedom to use these displays creatively, such as placing them in front of glass panels so you can see what's happening behind the display.

For this project we will use 10mm. You can use other sizes. Commonly available sizes are 3mm, 5mm, 8mm, and 10mm.

Although the display is not designed to work with any microcontroller, we will use popular Arduino boards and connect it via SPI using only 3 signal wires.

To build this project, basic knowledge of electronics and component soldering is required, as well as some knowledge of using Arduino. Firmware .

Here you need to solder the LEDs together using the long LED legs. You can use any size and color of LED, but the leg length (more than 23mm) must be long enough to bend and solder them together. The LEDs are arranged in an 8x8 matrix, where the cathodes are soldered together for the rows, and the anodes are soldered together for the columns.

The MAX7219 driver controls the dynamic display of the LED matrix. When designed, each 8x8 LED matrix will be based on a circuit using the following components:

  • 1 x MAX7219
  • 1 x 10uF 16V electrolytic capacitor
  • 1 x 0.1 UF ceramic capacitor
  • 1 x 12 kOhm resistor (0.25 W)
  • 1 x 24-pin female DIP IC

Note that you may need to select a different resistor value to suit the LED you will be using. This resistor limits the maximum current on the MAX7219 that will be output to the LEDs.

And this video clearly shows how the LED matrix is ​​installed, electronic board controls and a simple test to run it using the popular Arduino UNO/Nano board.


One of the important advantages of this converter is that it practically does not need tuning, all tuning comes down to selecting the frequency-setting capacitor of the microcircuit, it is adjusted to the desired frequency, as the capacitance of this capacitor increases, the frequency decreases, and as it increases, it increases.

The advantages of LEDs are undeniable; today they are everywhere, including watches. We’ll look at the advantages and disadvantages of watches based on LED matrices in the article. At the end of the article, a detailed step-by-step guide is provided for making the device yourself.

What it is

Clocks on LED matrices are Digital Watch, in which matrices of many LEDs are used for display. The use of indicators of a different type is their only difference.

A matrix is ​​a collection of LEDs assembled together in a grid with a single anode or cathode. As a rule, the resolution of such indicators - the number of dots vertically and horizontally - is 8x8.

Why are such watches gaining popularity, advantages:

  1. Price. LED matrices are cheaper than seven-segment indicators of similar sizes.
  2. Brightness. LEDs are brighter than seven-segment indicators and are easier to see in areas exposed to sunlight. Many manufacturers also provide structural protection for the diode from exposure to the sun.
  3. Functionality. Using a matrix of LEDs, you can display not only numbers, but also various letters, punctuation marks, and symbols. Using a set of LED matrices, you can display some information in the form of a creeping line.

LED matrices also have disadvantages:

  • Increased control complexity. Due to the large number of elements (there are 64 in the standard matrix), it is easier to manage matrix indicators than seven-segment indicators. For this purpose, microcontrollers, dynamic indication and shift registers are used.
  • Viewing angle. The peculiarity of LEDs is that they focus light in one direction. This leads to the fact that the image on the LED matrix is ​​clearly visible only from a certain angle.
  • Intolerance to high temperatures. Heat reduces the efficiency of LEDs and shortens their lifespan.
  • Burnout of individual LEDs will lead to the effect of " dead pixel"and deterioration of image quality.

Homemade clocks on LED matrices

Despite the great popularity of watches based on LED matrices, there are not so many circuits for them on the RuNet. self-made. Let's look at the most popular one.

Required skills to assemble the device:

  • production of printed circuit boards;
  • soldering of elements: the circuit assumes SMD design, which means that the elements will be installed directly on the surface of the board;
  • microcontroller firmware: the circuit uses an ATMega16A microcontroller;
  • MK programming: this is not necessary, because for of this device The controller firmware is already available. This skill will be useful if you want to change the operating mode of the watch or expand its functionality, for example, by adding additional elements such as temperature or humidity sensors.

Tools you will need:

  • kit for making circuit boards;
  • MK programmer;
  • soldering iron

Let's take a closer look at the device diagram. The main control element is the ATMega16A microcontroller; it provides the following capabilities of the device:

  1. Countdown and calendar. Continues even when the power is turned off.
  2. Alarm. There are 9 of them here, you can program them to work by day of the week.
  3. Temperature measurement. The design of the clock allows you to install two temperature sensors for measurements in the room and outside.
  4. Creeping line mode. Displays the following information: day of the week, month, year, temperature.
  5. Clock correction.

Most of the functions are assigned to the microcontroller, which allows you to maximally unload the circuit and use a minimum number of elements.

The device uses only two microcircuits: a microcontroller and a TPIC6B595 shift register; you can also connect two DS18B20 temperature sensors - one outdoor and the other indoor.

Three 8x8 LED matrices are used for display. It is better to use a Schottky diode as diode D1. The diode in the circuit provides a transition to emergency power, and the Schottky diode has the lowest voltage drop and high switching speed.

Manufacturing process:


Some of the features when assembling a clock on an LED matrix with ATMega 16A are clearly described in the following video.

Clocks based on LED matrices have many advantages over devices with other types of display: they are cheaper, they are not illuminated by the sun, and they can be used to display large quantity information. There are a large number of watch models based on LED matrices, and everyone will find a device with the required functionality. Also, such watches are easy to make yourself, as you saw from step by step guide above, it does not require special tools or special skills.

If you suddenly need an LED matrix of a non-standard size or shape, then you can always assemble it with your own hands. We will look at making a matrix of ultraviolet diodes, creating a kind of money authenticity detector. This will allow you to check the authenticity of currency purchased from friends or on the street and be sure that you have not been deceived.

In this video we invite you to watch the process of creating such an LED matrix.

To work we need to prepare the following:
- bread board;
- 100 LEDs;
- soldering iron;
- 100 resistors;
- scotch;
- wire cutters;


Having prepared everything necessary, we begin to manufacture an LED matrix with dimensions of 100x100 mm.

To power the LEDs, we will use a voltage of 5 V, we use resistors with a nominal value of 470 Ohms, this is necessary to set the required current value of 20 mA passing through each LED.


To simplify the task of creating an LED matrix as much as possible, let's connect all the LEDs in parallel. However, with such a connection, it is very important to remember that each LED must have its own current-limiting resistor.

First we solder the LEDs onto the board. For convenience, we secure each line consisting of them with tape so that we have the opportunity to turn the board over and solder the entire line of LEDs at once.

We arrange all the LEDs on the board. Please note that these radioelements have anode and cathode terminals. To avoid mistakes, the longer output has a “+” sign. We tape them down to temporarily hold them in place.


Now we turn our board over, on the reverse side of which there are the leads of all the LEDs and slowly begin to solder them one after another.

After soldering the first row, so that the leads of the already soldered LEDs do not interfere further work You can bite it off with wire cutters. We remove the tape.

After all the LEDs are soldered and their leads are bitten off, we begin to arrange the resistors. They have no polarities, so it doesn't matter which way you put them.

Sometimes it is necessary to connect several seven-segment indicators or an LED matrix to the microcontroller, and dynamic indication is used to display information. The essence of dynamic display is the sequential display of information on indicators. The diagram below shows an example of connecting several seven-segment indicators (for example, with a common cathode) to implement dynamic indication; in general, taking into account the point, 8 segments are obtained, but in the old fashioned way they are called that way. All pins (anodes) of segments of the same name are connected together, a total of 8 lines that are connected to the microcontroller through resistors. The common cathode of each indicator is connected to the microcontroller via a transistor.


The indication algorithm is as follows: first we set the required logical levels on the lines depending on which segments need to be turned on on the first indicator (indication from left to right), with a high logical level to turn on, a low to turn off the segment. Next, we apply a high logical level to the base of transistor VT1, thereby connecting the common cathode of the first indicator to the common wire, at this moment those segments that have a logical one on the anodes light up. Through certain time(pause) we turn off the indicator by applying a low logical level to the base of the transistor, then again change the logical levels on the lines in accordance with the output information intended for the second indicator, and send a turn-on signal to transistor VT2. Thus, we switch all the indicators in order in a circular cycle, and that’s the whole dynamic indication.

To obtain a solid, flicker-free image, switching must be done at high speed; to avoid flickering of the LEDs, the refresh rate must be set to 70 Hz or more, I usually set it to 100 Hz. For the design discussed above, the pause is calculated as follows: for a frequency of 100 Hz, the period is 10 ms, there are 4 indicators in total; accordingly, the lighting time of each indicator is set at 10/4 = 2.5 ms. There are multi-digit seven-segment indicators in one housing, in which the segments of the same name are connected inside the housing itself; naturally, to use them it is necessary to use a dynamic indication.

To implement dynamic indication, you need to use interrupts when one of the timers overflows. Below is the code using the TMR0 timer:

;Implementation of dynamic display for 4 seven-segment indicators ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; swapf STATUS,W ; clrf STATUS ; movwf STATUS_TEMP ; ; bcf ind1 ;turn off the 1st indicator bcf ind2 ;turn off the 2nd indicator bcf ind3 ;turn off the 3rd indicator bcf ind4 ;turn off the 4th indicator; incf shet,F ;register increment shet movlw .5 ;check register contents shet xorwf shet,W ;for equality to the number 5 btfss STATUS,Z ; goto met1 ;the number in the shet register is not equal to 5 movlw .1 ;the number in the shet register is 5: writing the number 1 movwf shet ;into the shet register; met1 movlw .1 ;checking the contents of the register shet xorwf shet,W ;for equality to the number 1 btfss STATUS,Z ; goto met2 ;the number in the shet register is not equal to 1: go to met2 movf datind1,W ;the number in the shet register is 1: copying movwf PORTB ;the contents of the datind1 register to the PORTB register bsf ind1 ;turn on the 1st indicator met2 movlw .2 ;check register contents shet xorwf shet,W ;to equal the number 2 btfss STATUS,Z ; goto met3 ;the number in the shet register is not equal to 2: go to met3 movf datind2,W ;the number in the shet register is 2: copy movwf PORTB ;the contents of the datind2 register to the PORTB register bsf ind2 ;turn on the 2nd indicator goto exxit ;go to the mark exxit met3 movlw .3 ;checking the contents of the register shet xorwf shet,W ;for equality to the number 3 btfss STATUS,Z ; goto met4 ;the number in the shet register is not equal to 3: go to met4 movf datind3,W ;the number in the shet register is 3: copy movwf PORTB ;the contents of the datind3 register to the PORTB register bsf ind3 ;turn on the 3rd indicator goto exxit ;go to the mark exxit met4 movf datind4,W ;copying the contents of the datind3 register movwf PORTB ;to the PORTB register bsf ind4 ;turning on the 4th indicator; movlw .100 ;write the number 156 to the timer register TMR0 movwf TMR0 ; ; movwf STATUS ; swapf W_TEMP,F ; swapf W_TEMP,W ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Main program ................... movlw b"11010011" ;OPTION_REG, thereby setting the internal ;setting the prescaler coefficient to 1:16 ; clrf shet ;zeroing the shet register, before starting; TMR0 overflow interrupts, executed; clrf datind1 ;clearing the information output registers on clrf datind2 ;indicators, is equivalent to turning off clrf datind3 ;indicators, since the indicators have a common clrf datind4 ;cathode; bcf INTCON,T0IF ;reset TMR0 overflow interrupt flag bsf INTCON,T0IE ;enable TMR0 overflow interrupts bsf INTCON,GIE ;enable global interrupts; movlw b"00000110" ;an example of outputting the number 13.52 movwf datind1 ; movlw b"11001111" ; movwf datand2 ; movlw b"01101101" ; movwf datand3 ; movlw b"01011011" ; movwf datand4 ; ; . ................ ; ............. ; ............. ; ; end ;end of the entire program;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Implementation of dynamic display for 4 seven-segment indicators

;Clock generator frequency for example 4 MHz, machine cycle 1 µs

org 0000h ;start program execution from address 0000h

goto Start ;go to the Start label

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Interrupt routine

org 0004h ;start execution of the subroutine from address 0004h

movwf W_TEMP ;save key register values

swapf STATUS,W ;

movwf STATUS_TEMP ;

bcf ind1 ;turn off the 1st indicator

bcf ind2 ;turn off the 2nd indicator

bcf ind3 ;turn off the 3rd indicator

bcf ind4 ;turn off the 4th indicator

incf shet,F ;register increment shet

movlw .5 ;check the contents of the shet register

xorwf shet,W ;for equality to the number 5

btfss STATUS,Z ;

goto met1 ;number in shet register is not equal to 5

movlw .1 ;the number in the shet register is 5: writing the number 1

movwf shet ;to register shet

met1 movlw .1 ;checking the contents of the shet register

xorwf shet,W ;for equality to the number 1

btfss STATUS,Z ;

goto met2 ;the number in the shet register is not equal to 1: go to met2

movf datind1,W ;the number in the shet register is 1: copy

movwf PORTB ;contents of register datind1 into register PORTB

bsf ind1 ;turn on the 1st indicator

goto exxit ;go to exxit label

met2 movlw .2 ;checking the contents of the shet register

xorwf shet,W ;for equality to the number 2

btfss STATUS,Z ;

goto met3 ;the number in the shet register is not equal to 2: go to met3

movf datind2,W ;the number in the shet register is 2: copy

movwf PORTB ;contents of the datind2 register into the PORTB register

bsf ind2 ;turn on the 2nd indicator

goto exxit ;go to exxit label

met3 movlw .3 ;checking the contents of the shet register

xorwf shet,W ;for equality to the number 3

btfss STATUS,Z ;

goto met4 ;the number in the shet register is not equal to 3: go to met4

movf datind3,W ;the number in the shet register is 3: copy

movwf PORTB ;contents of the datind3 register into the PORTB register

bsf ind3 ;turn on the 3rd indicator

goto exxit ;go to exxit label

met4 movf datind4,W ;copying the contents of the datind3 register

movwf PORTB ;to register PORTB

bsf ind4 ;turn on the 4th indicator

exxit bcf INTCON,T0IF ;reset the TMR0 overflow interrupt flag

movlw .100 ;write the number 156 to the TMR0 timer register

swapf STATUS_TEMP,W ;restoring the contents of key registers

swapf W_TEMP,F ;

swapf W_TEMP,W ;

retfie ;exit interrupt routine

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Main program

Start ............. ;initial register setup

............. ;special purpose

.................

bsf STATUS,RP0 ;write binary number 11010011 to register

movlw b"11010011" ;OPTION_REG, thereby setting the internal

movwf OPTION_REG ;clock source for TMR0

bcf STATUS,RP0 ;turn on the prescaler before TMR0

;set the prescaler factor to 1:16

clrf shet ;zeroing the shet register before starting

;interrupts on TMR0 overflow, executed

;once, after turning on the power

clrf datind1 ;clearing registers for displaying information on

clrf datind2 ;indicators, equivalent to turning off

clrf datind3 ;indicators, since indicators with a common

clrf datind4 ;cathode

bcf INTCON,T0IF ;reset the TMR0 overflow interrupt flag

bsf INTCON,T0IE ;enable TMR0 overflow interrupts

bsf INTCON,GIE ;enable global interrupts

movlw b"00000110" ;example of output of the number 13.52

movlw b"11001111" ;

movlw b"01101101" ;

movlw b"01011011" ;

................. ;

................. ;

................. ;

end ;end of the entire program

In the main program, we first set up a timer using the OPTION_REG register; earlier I talked about using timers for . Next, we clear the shet register, intended for entering a count from 1 to 4, for each indicator. This register is incremented in the interrupt handling routine and adjusted there (it will count from 1 to 4), so this clearing is performed once after turning on the power. Using this register, we will determine which indicator to turn on and output data corresponding to it. The next step is to clear the information storage registers, four registers dataind1,2,3,4 corresponding to four indicators. Clearing is equivalent to turning off the indicators, since in the interrupt handling routine, the contents of these registers are transferred to the PORTB register, to which the anodes of the indicators are connected. This is necessary so that no garbage is displayed on the indicators after interrupts are enabled; in principle, this can be avoided if you immediately record the correct information for output. Next, we reset the timer overflow interrupt flag, enable TMR0 overflow interrupts, and finally, enable global interrupts.

In the interrupt processing subroutine, first of all we turn off all the indicators (by applying low logical levels to the bases of the transistors), because it is not known which of them is turned on. We increment the shet register, checking for equality to the number 5; if there is such a match, we write the number 1 into the register, since it is necessary to count from 1 to 4. Next, we check which number is in the shet register, using which we load data from information storage registers (dataind) for the corresponding indicator and turn it on. Then we reset the TMR0 overflow interrupt flag, write the number 100 to the timer (the calculation of this value is shown below) for a time delay and exit the interrupt handler. At the first interruption, the first indicator turns on, at the second interruption the second, and so on in a circular cycle. In the main program, all that remains is to load data into the information storage registers for each indicator. In the interrupt subroutine, do not forget to save and restore the values ​​of key registers, I wrote about this in the article about.

To output numbers, it is better to use a character generator in the form of a data table. For example, to display the number 3456 on indicators, it must be divided into digits, and it is better to use separate registers to store the numbers of digits (from 0 to 9), then run these registers through a character generator, thereby obtaining the correct bytes (loaded into the dataind registers) to ignite the corresponding segments.

Let us take the clock generator frequency to be 4 MHz, the machine cycle to be 1 μs. Let the update frequency of each indicator be 100 Hz (period T = 10 ms), respectively, the required time delay is 10/4 = 2.5 ms. We set the prescaler coefficient for TMR0 to 1:16, while the maximum possible delay is 256x16 = 4096 μs, and we need a pause of 2.5 ms. Let's calculate the number to be recorded in TMR0: 256-((256x2.5)/4.096) = 256-156.25 = 99.75. After rounding we get the number 100.

Below you can download a model for the Proteus program, firmware and source code with the implementation of dynamic indication on a 4-digit indicator with a common cathode using a PIC16F628A microcontroller. For example, the indicator displays the numbers 0000; 0001; 0002; 13.52; 9764.

Now let's look at connecting a matrix with a resolution of 8x8 pixels (LEDs). The structure of a matrix is ​​usually considered in terms of rows and columns. In the picture below, the cathodes of all LEDs are connected in each column, and the anodes in each row. The lines (8 lines, LED anodes) are connected to the microcontroller through resistors. Each column (LED cathodes) is connected to the microcontroller via 8 transistors. The indication algorithm is the same, first we set the necessary logical levels on the lines, in accordance with which LEDs should be lit in the column, then we connect the first column (indication from left to right). After a certain pause, we turn off the column, and change the logical levels on the lines to display the second column, then connect the second column. And so we switch all the columns one by one. Below is a diagram of connecting the matrix to the microcontroller.


In total, to connect such a matrix you will need 16 microcontroller pins, which is quite a lot, so to reduce the control lines it is better to use serial shift registers.

The most common serial register is the 74HC595 chip, which contains a shift register for loading data, and a storage register through which data is transferred to the output lines. Loading data into it is simple, we set logical 0 at the SH_CP clock input, then set the required logical level at the DS data input, after which we switch the clock input to 1, and the level value (at the DS input) is stored inside the shift register. At the same time, the data is shifted by one bit. Again we reset the SH_CP pin to 0, set the required level at the DS input and raise SH_CP to 1. After the shift register is fully loaded (8 bits), we set the ST_CP pin to 1, at this moment the data is transferred to the storage register and supplied to the output lines Q0... Q7, after which we reset the ST_CP output. During serial loading, the data is shifted from Q0 to Q7. Pin Q7' is connected to the last bit of the shift register; this pin can be connected to the input of the second chip, so you can load data into two or more chips at once. The OE pin switches the output lines to the third (high-resistance) state when a logic 1 is applied to it. The MR pin is designed to reset the shift register, that is, setting low logic levels at the outputs of the register flip-flops, which is equivalent to loading eight zeros. Below is a diagram of loading data into the 74NS595 chip, setting the value 11010001 on the output lines Q0...Q7, provided that initially there were zeros there:


Consider connecting an 8x8 matrix to a PIC16F628A microcontroller using two 74HC595 shift registers, the diagram is presented below:


The data is loaded into the DD2 chip (control of logical levels on the rows, LED anodes) then through the Q7’ pin it is transferred to DD3 (control of the columns), respectively, we first load the byte to enable the column, then the byte with the logical levels on the rows. Transistors that switch the columns of the matrix (LED cathodes) are connected to the output lines of DD3. Below is the program code for displaying an image on a matrix:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Implementation of dynamic display for a matrix with a resolution of 8x8 ;Clock generator frequency for example is 4 MHz, machine cycle 1 μs org 0000h ;start program execution from address 0000h goto Start ;go to the Start label ;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Interrupt handling subroutine org 0004h ;start execution of the subroutine from address 0004h movwf W_TEMP ;save the values ​​of key registers swapf STATUS,W ; clrf STATUS ; movwf STATUS_TEMP ; ; movwf FSR_osn ;to the FSR_osn register movf FSR_prer,W ;restoring a previously saved value movwf FSR ;FSR register from the FSR_prer register ;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;; ;loading the contents of the stolb register into the chip movf stolb,W ;copying the contents of the stolb register movwf var ;into the var register met2 btfsc var,0 ;set the ds output in accordance with btfss var,0 ; bcf ds ; bcf sh_cp ; rrf var,F ;shift the var register to the right, to prepare;the next bit goto met2 ;scetbit is not zero: move to the met2 label ;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;; ;loading the contents of the INDF register into the chip;74HC595 (serial shift register) movf INDF,W ;copying the contents of the INDF register movwf var ;to the var register movlw .8 ;writing the number 8 to the scetbit register, for counting movwf scetbit ;transmitted bits met1 btfsc var ,7 ;set the output ds in accordance with bsf ds ;the value of the 7th bit of the register var btfss var,7 ; bcf ds ; bsf sh_cp ;clock the sh_cp pin to latch the data bcf sh_cp ; rlf var,F ;shift register var to the left, to prepare the next bit decfsz scetbit,F ;decrement with register condition scetbit goto met1 ;scetbit is not equal to zero: jump to label met1 ; bsf st_cp ;clock the st_cp pin to transfer the loaded bcf st_cp ;bytes to the output lines of the 74HC595 chips; bcf STATUS,C ;reset bit C of the status register before shifting rrf stolb,F ;shift left of the stolb register; incf FSR,F ;increment of the FSR register, preparing the next;register for sending data to 74HC595 decfsz shet,F ;decrement with register condition shet goto exxit ;shet register is not equal to 0: transition to exxit movlw data1 ;shet register is equal to 0: writing the address first movwf FSR; information storage register in the FSR register movlw.8; writing the number 8 to the shet register, for maintaining movwf shet; column counts; exxit bcf INTCON,T0IF ;reset the TMR0 overflow interrupt flag movlw . 124 ;write the number 124 to the timer register TMR0 movwf TMR0 ; ; movf FSR,W ;saving the current value of the FSR register movwf FSR_prer ;into the FSR_prer register movf FSR_osn ,W ;restoring a previously saved value movwf FSR ;of the FSR register from the FSR_osn register; swapf STATUS_TEMP,W ;restoring the contents of key registers movwf STATUS ; swapf W_TEMP,F ; swapf W_TEMP,W ; ; retfie ;exit interrupt routine;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Main program Start ............. ;Initial setup of registers................. ;Special purpose..... ............ bsf STATUS,RP0 ;write the binary number 11010011 to the register movlw b"11010010" ;OPTION_REG, thereby setting the internal movwf OPTION_REG ;clock source for TMR0 bcf STATUS,RP0 ;turn on the prescaler before TMR0; set the prescaler ratio to 1:8; movlw .8 ;writing the number 8 to the shet register, before starting movwf shet ;TMR0 overflow interrupts, executed;once, after turning on the power movlw b"10000000" ;writing the binary number 10000000 to movwf stolb ;stolb register, to turn on the 1st column;executed once, after turning on the power; movlw data1 ;writing the address of the first register (movwf FSR_prer ;information storage registers) to the FSR_prer register is performed;once, after turning on the power; movlw .8 ;clearing 8 registers for outputting information to the movwf tmp ;matrix, equivalent to turning off movlw data1 ;matrix movwf FSR ; met3 clrf INDF ; incf FSR,F ; decfsz tmp,F ; goto met3 ; ; bcf INTCON,T0IF ;reset TMR0 overflow interrupt flag bsf INTCON,T0IE ;enable TMR0 overflow interrupts bsf INTCON,GIE ;enable global interrupts; m1 movlw data1 ;example of output of the letter R movwf FSR ; movlw b"00000000" ; movwf INDF ; incf FSR,F ; movlw b"01111111" ; movwf INDF ; incf FSR,F ; movlw b"00001001" ; movwf INDF ; incf FSR,F ; movlw b"00011001" ; movwf INDF ; incf FSR,F ; movlw b"00101001" ; movwf INDF ; incf FSR,F ; movlw b"01000110" ; movwf INDF ; incf FSR,F ; movlw b"00000000" ; movwf INDF ; incf FSR,F ; movlw b"00000000" ; movwf INDF ; ; ............. ; ............. ; ............. ; ; end ;end of the entire program;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Implementation of dynamic display for a matrix with a resolution of 8x8

;Clock generator frequency for example 4 MHz, machine cycle 1 µs

org 0000h ;start program execution from address 0000h

goto Start ;go to the Start label

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Interrupt routine

org 0004h ;start execution of the subroutine from address 0004h

movwf W_TEMP ;save key register values

swapf STATUS,W ;

movwf STATUS_TEMP ;

movf FSR,W ;save the current value of the FSR register

movwf FSR_osn ;to register FSR_osn

movf FSR_prer,W ;restore previously saved value

movwf FSR ;FSR register from FSR_prer register

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;74HC595 (serial shift register)

movf stolb,W ;copying the contents of the stolb register

movwf var ;to register var

movlw .8 ;write the number 8 to the scetbit register, for counting

movwf scetbit ;transmitted bits

met2 btfsc var,0 ;set the ds output in accordance with

bsf ds ;the value of the 7th bit of the var register

bsf sh_cp ;clock the sh_cp pin to latch the data

rrf var,F ;shift the var register to the right, for preparation

;next bit

decfsz scetbit,F ;decrement with register condition scetbit

goto met2 ;scetbit is not zero: go to met2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;74HC595 (serial shift register)

movf INDF,W ;copies the contents of the INDF register

movwf var ;to register var

movlw .8 ;write the number 8 to the scetbit register, for counting

movwf scetbit ;transmitted bits

met1 btfsc var,7 ;set the ds output in accordance with

bsf ds ;the value of the 7th bit of the var register

bsf sh_cp ;clock the sh_cp pin to latch the data

rlf var,F ;shift the var register to the left, for preparation

;next bit

decfsz scetbit,F ;decrement with register condition scetbit

goto met1 ;scetbit is not zero: go to met1

bsf st_cp ;clock the st_cp output to transmit loaded

bcf st_cp ;bytes to output lines of 74HC595 microcircuits

bcf STATUS,C ;reset bit C of the status register before shifting

rrf stolb,F ;shift left register stolb

incf FSR,F ;increment the FSR register, prepare the next

;register for sending data to 74HC595

decfsz shet,F ;decrement with register condition shet

goto exxit ;shet register is not equal to 0: transition to exxit

movlw data1 ;shet register is 0: record the address of the first

movwf FSR ;information storage register in the FSR register

movlw .8 ;write the number 8 to the shet register, for keeping

movwf shet ;column counts

movlw b"10000000" ;writes the binary number 10000000 to

movwf stolb ; stolb register, to include the 1st column

exxit bcf INTCON,T0IF ;reset the TMR0 overflow interrupt flag

movlw .124 ;write the number 124 to the TMR0 timer register

movf FSR,W ;save the current value of the FSR register

movwf FSR_prer ;to register FSR_prer

movf FSR_osn ,W ;restore previously saved value

movwf FSR ;FSR register from FSR_osn register

swapf STATUS_TEMP,W ;restoring the contents of key registers

swapf W_TEMP,F ;

swapf W_TEMP,W ;

retfie ;exit interrupt routine

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Main program

Start ............. ;initial register setup

............. ;special purpose

.................

bsf STATUS,RP0 ;write binary number 11010011 to register

movlw b"11010010" ;OPTION_REG, thereby setting the internal

movwf OPTION_REG ;clock source for TMR0

bcf STATUS,RP0 ;turn on the prescaler before TMR0

;set the prescaler ratio to 1:8

movlw .8 ;write the number 8 to the shet register before starting

movwf shet ;interrupts on TMR0 overflow, executed

;once, after turning on the power

movlw b"10000000" ;writes the binary number 10000000 to

movwf stolb ; stolb register, to include the 1st column

Information with logical levels for the rows of each column is stored in 8 information storage registers, which are accessed through. The address of the first register is named data1. In addition to the initial entry of the shet and stolb registers, it is necessary to write the address of the first information storage register into the FSR_prer register (the register is data1, writing to FSR_prer is performed once, then it is adjusted in the handler), only after this allow TMR0 overflow interrupts.

Before enabling interrupts, it is advisable to clear the information storage registers, this operation performed using an additional tmp register (as a counter) and indirect addressing, clearing is equivalent to turning off the matrix.

In the interrupt handling subroutine, we load the contents of the stolb register into the DD2 chip (when you first enter the handler after interrupts are enabled, the register contains the number 10000000, as mentioned above). Loading begins with the least significant bit of the stolb register, which shifts in the direction from Q0 to Q7 (inside the DD2 chip) as it loads, the loading algorithm was discussed above, so I think it won’t be difficult to understand the code. Next, we load the contents of the INDF register into DD2, this is one of the information storage registers, the address of which is in the FSR (when you first enter the handler after enabling interrupts, the address of the first information storage register called data1 is in the FSR). Loading starts from the most significant bit of the INDF register. After loading the considered 2 bytes, we clock the st_cp output, thereby the loaded data is transferred to the output lines of the DD2, DD3 microcircuits. Thus, when you first enter the processor, the first column of the matrix is ​​switched, in which the LEDs light up, the anodes of which have a high logical level, in accordance with the contents of the data1 register (the first information storage register).

Next, we shift the stolb register to the right by one bit in order to prepare the second column of the matrix for commutation the next time we enter the interrupt handler. Before shifting, it is necessary to clear flag C of the STATUS register, since the shift occurs through this flag, and its state is not known at the time of the shift. After the shift, we increment the FSR register, preparing the next information storage register (after the data1 register) with logical row levels for the second column. Next, we decrement the shet register with the condition, and if it is not equal to zero, we reset the TMR0 overflow interrupt flag, write the number to the timer, and exit the interrupt handler.

The next time you enter the handler, the second column of the matrix will be included, and so on. When the shet register is reset to zero (after switching the 8th column), the number 8 is written to it for the next cycle of switching pillars, in addition, the value of the stolb register is adjusted, and the address of the first information storage register (data1) is written to the FSR register.

Let's calculate the time delay for the TMR0 timer, clock generator frequency 4 MHz, machine cycle 1 μs. To avoid flickering of the LEDs, we take the refresh rate of each column to be 100 Hz (period T = 10 ms), the time delay is 10/8 = 1.25 ms. We set the TMR0 prescaler factor to 1:8, with the maximum possible delay being 256x8 = 2048 μs. For a pause of 1.25 ms, the timer must count (256x1.25)/2.048 = 156.25 times, rounding up we get 156 counts. Accordingly, it is necessary to write the number 256-156 = 100 into the timer. But this is not quite the correct value, since it takes some time to execute the interrupt processing subroutine, in this case it takes about 190 μs, recalculated taking into account the prescaler coefficient we get 190/8 = 23.75 or 24 counts. The correct value to write to TMR0 is: 100+24=124.

In the main program we write 8 information storage registers, in accordance with what we want to display on the matrix. Below is a diagram explaining the output of information to the matrix for the above code.


In addition to shift registers, there are specialized drivers for outputting information to seven-segment indicators and LED matrices; in this case, the dynamic indication is implemented by the driver itself; all that remains is to send data to it for display. I reviewed one of these popular drivers in an article about .

Below, from the link you can download the firmware and source code for the PIC16F628A microcontroller, with the implementation of dynamic display on an 8x8 matrix using two 74HC595 shift registers, the connection diagram was discussed above. The letters R, L, the number 46, a smiley face, and just a pattern in the form of a cross are alternately displayed on the matrix; this animation is demonstrated in the video below.

with tags , . Read .

Assembling a ticker based on an LED matrix and Arduino is a simple task that can be done even at home. To make letters move on an LED display, you don’t need to be a programmer or have in-depth knowledge of electronics. In this article we will look at how to assemble a ticker from ready-made LED matrices and an Arduino Nano.

What will you need?

To implement the idea you will need very few details:

  • two LED modules consisting of four 8 by 8 pixel matrices;
  • holder for “Krone” size battery;
  • 9 volt battery (CR-9V, ER-9V or their equivalents);
  • two-pin switch;
  • connecting wires;
  • Arduino Nano board;
  • hot melt adhesive.

Scheme

On the printed circuit board of the LED module used there are 4 matrices measuring 8 by 8 pixels. Each LED display is controlled integrated circuit(IC) MAX7219. This IC is a controller for controlling LED displays, matrices with a common cathode and discrete LEDs in an amount of up to 64 pcs.

For a more comfortable perception of information displayed on the LED display, it is recommended to install several modules. To do this, they are combined into sequentially connected groups, that is, the output of the first module (out) is connected to the input of the second module (in). This assembly consists of two modules (16 matrices), the length of which is quite enough for easy reading of entire sentences.

Assembly

The matrix module may have a pin connection or contacts on the board in the form of printed conductors. The way they are connected depends on this. In the first case, to obtain reliable electrical contact, a harness of wiring with connectors is used, and in the second, jumpers will have to be installed and soldered.

But first you need to combine both modules into a single whole using hot glue. Thermoplastic adhesive does not conduct electricity, which means it can be safely applied to a printed circuit board. Glue is applied to the ends of both boards, pressed and left for several minutes. After hardening, the output contacts of the first block are connected to the input contacts of the second block according to the following diagram:

  • VCC - VCC
  • GND - GND
  • D IN – D OUT
  • CS–CS
  • CLK–CLK

On the back side printed circuit board Using hot glue, attach the Arduino Nano, battery compartment and switch. The parts are arranged in such a way that they can be used conveniently.
At the next stage, the Arduino is connected to the LED module by connecting the wires to the input of the first matrix. Depending on the module version, the operation is performed through a detachable connection or by soldering according to the diagram below:

  • VCC - 5V
  • GND - GND
  • D IN – PIN 11
  • CS – PIN 10
  • CLK - PIN 13.

At the final stage of assembly, you need to connect the battery power. To do this, the negative pin (black wire) from the crown compartment is connected to the GND pin of the Arduino. The positive contact (red wire) is connected to the switch, and then to pin No. 30 of the Arduino, designed to supply supply voltage from an unregulated source. In test mode, a do-it-yourself ticker can be powered via micro USB from the computer.
Having ensured the reliability of the fastenings and the quality of the electrical connections, proceed to assembling the housing. It can be made from an aluminum or plastic profile, since the circuit elements do not heat up. The color, dimensions, degree of protection and fastening of the case depend on the future purpose of the device. In the simplest case it will do protective screen from a construction plastic corner profile with a cutout for a switch.

Programming the ticker

The running line from Arduino and LED modules controlled by MAX7219 is almost ready. It's time to move on to the final program part. Must be installed on your computer software(software) for the Arduino used and the driver for it. Next you need to download two libraries and a sketch ( special program, which will be loaded and executed by the Arduino processor). The libraries are installed with the Arduino IDE closed in the “Documents – Arduino – Libraries” folder. Then they download and run the sketch and check the presence of libraries and the correctness of other data.

Sketch setup:

  • “number of horizontal displays” indicate the number of lines, in our case 1;
  • “number of vertical displays” indicate the number of matrices, in our case 8;
  • “string tape” indicates the inscription displayed on the display;
  • "int wait" specifies the output speed in milliseconds.

After checking the entered data, all you have to do is click on the “download” button. Then disconnect from the PC, insert the battery and start the device.

In conclusion, I would like to add that a do-it-yourself ticker can be assembled quite quickly even without Arduino skills. Therefore, there is no need to be afraid of this intricate board. It is also worth noting that you can make the creeping line longer by increasing the number of LED matrices.

Read also

Computer