For a long long time I've wanted something that I could use to replace a 1602 LCD with something bigger. Much bigger. I've made a large number of four inch (100mm) seven segment displays, lots of two inch ones, plenty of one inch ones, hundreds of 0.75 inch too. But these have all manner of compromises when it comes to display anything other than numbers. Trying to display "m" or "w" is nigh on impossible, you can display two "n""n" or two "u""u" but they look worse than pretending that an "m" can be displayed as a single "n" and "w" can be replaced with "u". So, in this fallow period we have at work I started thinking again. I ordered some 5x7 LED dot matrix displays, I thought I could connect them up to a 16F1829 driving the 7 "Rows" (through some series 100R resistors) from seven pins, driving the 5 columns from five further pins. Another pin I dedicated to driving a single separate LED positioned between the dot matrix displays to provide a decimal point, this means that an entire display is not wasted by only displaying a decimal point. Optionally, this pin could be used to activate a buzzer for those devices either at the start of the assembled display or at the end. It could also be ignored.
Each 5x7 display has one 16F1829. Expensive I know, but the MAX7219 for driving 8x8 displays costs about £7 from Farnell, 16F1829 cost around £1.50. The serial in of the first device connects to the "host" processor with its serial out connecting to the serial in on the next, which in turn connects to the next, and so on for as many as you might want, up to 54 with the software as it stands, though this could be increased if really needed.
I originally planned to do the font decoding in one master device, sending the values for each of the columns that make up the matrix to each "slave". This would mean sending six bytes to each display slave. I realised that If I sent only the Ascii value to each slave, I would only need to send two bytes, the first byte is the address of the display and the second the Ascii value for it to display. One advantage of sending the five bytes of row data is that the displays could show more characters across the entire cluster. As each letter averages just 3 rows wide, this plus a single row space over an eight display cluster could allow ten characters to be displayed.
The display addresses start at 200. If a display receives two values with the first value greater than 199 it then checks to see if that value is 200, if it is it copies the second value (if in the range 32 to 129) to the display after decoding the font. If the address is greater than 200, the data is sent to the next display, having deducted 1 from the address value. This way the data percolates along the display, with the address being deducted by one at each step until either the display elements stop ( and it is "lost") or the address eventually becomes equal to 200. To display a capital letter "A" on the first display you would need to send 200 followed by 65. To display "A" on the third display you would send 202, 65. On arrival at the first display the address would be 202 so it is ignored, reduced by one to 201 and then 201, 65 is passed to the next (second) display. Again it is ignored, reduced by one to 200 and 200, 65 is passed to the next (third) display. Now at the third display, the address is 200 so 65 is loaded into the display after being decoded into the data for the display rows and columns.
To activate the decimal point, send the address and then either 128 (decimal point on) or 129 (decimal point off). The current software does not reset the decimal point when "ClearDisplay" is called, nor does setting the decimal point on or off change any currently displayed character.
I considered having all the display 16F1829 connected to the same serial data line, and hard coding a specific address into each device. I went away from this approach as I reasoned that each display device would still have to look at the address and data to see if it was intended for it before discarding it or acting upon it which didn't seem to gain anything and meant I'd have to keep track of each devices programmed address, making sure they were fitted in the correct sequence and so on. I also wondered about have an address "decoder" that would take the incoming serial and then send it out to individual devices, on individual serial out ports with individual connections directly to each. I wasn't sure how many serial outputs I could have on each device using the software serial and also thought this made things even more complicated, especially so at the hardware end. My next thought was to have a 'select' pin, dedicated to each display but again, this meant either having another slave on board, or the host microprocessor dedicating a number of pins for this or potentially some further hardware that selected the target device under control of the host. Again, complicating the hardware design.
I've built a truly messy prototype with 5 displays. I've ordered some PCBs which are again 5 displays wide, for the current project I have in mind, 5 should be enough. I may get an 8x2 PCB designed with some smaller displays, I may not.
The font table I used for decoding the Ascii character into the row data was shamelessly borrowed from one of the GLCD header files. I have changed the US Dollar symbol into a UK Pound so that character 36 displays "£" but it is otherwise untouched and uses the index table form the same header file to lookup where the data is held within the font table itself.
The serial interrupt was also shamelessly borrowed from an example on how to fill a circular buffer using an interrupt. I've modified this to capture only the two bytes I need.
The software should hopefully be reasonably self explanatory. Each display can be connected up and with a 4k7 connected to the serial in port to either ground or 5V to stop it from picking up random data, the message "Check serial" should scroll across the 5x7 display. I labelled the output ports for the displays as "Row1", "Row2" and so on. These should be wired to the LED "Row1", "Row2" and the columns are also labelled "Col1", "Col2" in the same way. I used common cathode displays but I have included routines for common anode display types. Near the start of the program there is a "#Define CommonCathode" declaration. If this is replaced with "#Define CommonAnode" the required changes should me made. Don't use both, odd effects could occur. I've not tried the Common Anode type of display, but hopefully it should work.
A video of the messy prototype is linked, along with the source for the receiver(s) - one receiver needed for each 5x7 display, and a demonstration transmitter. The transmitter uses a 12F1840. Only because I was running out of room on my breadboard! I was using (another) 16F1829 for the transmitter and it can be seen lying down and resting at the side of the breadboard.
Sorry for the poor video. My 'phone seems to constantly lose focus which is very annoying...
A video of the display running the demonstration code in action. Sorry about the mess, sorry about the camera keeping trying to focus on the wiring not the displays.
When the PCBs turn up, I'll post another, hopefully better, video.
I've made some refinements to the software. This has sped up the serial communications and reduced some of the time taken to propagate the serial data down the displays, this in turn reduces some flicker of the displays caused by the serial interrupt halting the display multiplexing momentarily.
Updated source attached to the original post.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've received the PCBs to make up a 5 element display to this design. As promised, I've taken another video. The video is "better" but the camera on my 'phone still seems to jump in and out of focus at will. I apologise for that.
On the PCB I made provision for four left-aligned decimal points for displaying numerals, one of these is illuminated during the numbers countdown.
As it wouldn't make sense to have a "leading" decimal point (or a lagging one if it comes to that) The rightmost display has a 12V piezo buzzer connected in place of the decimal point LED. Although it is a 12V unit, the ones we use work well enough with a 5V signal direct from the PIC that I've stopped using a buffer transistor for them. The buzzer is "bipped" for 10mS in between each frame to demonstrate it working.
I've made some additional improvements to the software of both the transmitter and the receiver which I've updated in the original post.
The software has the capacity to address 55 display elements. I've built another unit, with ten elements. Having more displays does mean that refreshing or updating the displays takes longer as the data must be passed from the first display, down the line until the target display is reached. It is possible to update individual display elements, without affecting those displays before or after the target. This is demonstrated when the "Be smart, stay apart" message is shown.
In the demonstration for the five character display, a "countdown" is performed. The displays I made, all have the "first" element on the left with the "last" on the right. The least significant digit is then displayed on the "first" display and as the countdown is run, it is the least significant digit which changes the most. This gives greater update speed as only those digits which have changed are updated. The "£" symbol in the last display is sent only once and never changes during the countdown. The "tens" only changes once, the "units" change sixteen times (I think!). The decimal point is sent only once. The "tenths" are updated 159 times (I reckon...). But the "hundreths" change 1599 times (I really haven't worked this out. I could be wrong, but you get where I'm going with this). By having the display element which changes most, as the first element means that display updates can be performed quicker and with less visual disturbance to the other display elements. For left to right scrolling of words, it makes little difference which end is the "first" as every display element must be updated for every character.
I should add that the size of the displays is 50mm high (2 Inch). These have super bright red LED pixels and are indeed bright given that they are multiplexed and refreshed continuously.
Here is a picture and a short video of the ten element display. The picture was taken "mid scroll" so doesn't make grammatical sense. It was part way through writing "stay safe,support the NHS" and it is partially displaying "tay safe,s".
For a long long time I've wanted something that I could use to replace a 1602 LCD with something bigger. Much bigger. I've made a large number of four inch (100mm) seven segment displays, lots of two inch ones, plenty of one inch ones, hundreds of 0.75 inch too. But these have all manner of compromises when it comes to display anything other than numbers. Trying to display "m" or "w" is nigh on impossible, you can display two "n""n" or two "u""u" but they look worse than pretending that an "m" can be displayed as a single "n" and "w" can be replaced with "u". So, in this fallow period we have at work I started thinking again. I ordered some 5x7 LED dot matrix displays, I thought I could connect them up to a 16F1829 driving the 7 "Rows" (through some series 100R resistors) from seven pins, driving the 5 columns from five further pins. Another pin I dedicated to driving a single separate LED positioned between the dot matrix displays to provide a decimal point, this means that an entire display is not wasted by only displaying a decimal point. Optionally, this pin could be used to activate a buzzer for those devices either at the start of the assembled display or at the end. It could also be ignored.
Each 5x7 display has one 16F1829. Expensive I know, but the MAX7219 for driving 8x8 displays costs about £7 from Farnell, 16F1829 cost around £1.50. The serial in of the first device connects to the "host" processor with its serial out connecting to the serial in on the next, which in turn connects to the next, and so on for as many as you might want, up to 54 with the software as it stands, though this could be increased if really needed.
I originally planned to do the font decoding in one master device, sending the values for each of the columns that make up the matrix to each "slave". This would mean sending six bytes to each display slave. I realised that If I sent only the Ascii value to each slave, I would only need to send two bytes, the first byte is the address of the display and the second the Ascii value for it to display. One advantage of sending the five bytes of row data is that the displays could show more characters across the entire cluster. As each letter averages just 3 rows wide, this plus a single row space over an eight display cluster could allow ten characters to be displayed.
The display addresses start at 200. If a display receives two values with the first value greater than 199 it then checks to see if that value is 200, if it is it copies the second value (if in the range 32 to 129) to the display after decoding the font. If the address is greater than 200, the data is sent to the next display, having deducted 1 from the address value. This way the data percolates along the display, with the address being deducted by one at each step until either the display elements stop ( and it is "lost") or the address eventually becomes equal to 200. To display a capital letter "A" on the first display you would need to send 200 followed by 65. To display "A" on the third display you would send 202, 65. On arrival at the first display the address would be 202 so it is ignored, reduced by one to 201 and then 201, 65 is passed to the next (second) display. Again it is ignored, reduced by one to 200 and 200, 65 is passed to the next (third) display. Now at the third display, the address is 200 so 65 is loaded into the display after being decoded into the data for the display rows and columns.
To activate the decimal point, send the address and then either 128 (decimal point on) or 129 (decimal point off). The current software does not reset the decimal point when "ClearDisplay" is called, nor does setting the decimal point on or off change any currently displayed character.
I considered having all the display 16F1829 connected to the same serial data line, and hard coding a specific address into each device. I went away from this approach as I reasoned that each display device would still have to look at the address and data to see if it was intended for it before discarding it or acting upon it which didn't seem to gain anything and meant I'd have to keep track of each devices programmed address, making sure they were fitted in the correct sequence and so on. I also wondered about have an address "decoder" that would take the incoming serial and then send it out to individual devices, on individual serial out ports with individual connections directly to each. I wasn't sure how many serial outputs I could have on each device using the software serial and also thought this made things even more complicated, especially so at the hardware end. My next thought was to have a 'select' pin, dedicated to each display but again, this meant either having another slave on board, or the host microprocessor dedicating a number of pins for this or potentially some further hardware that selected the target device under control of the host. Again, complicating the hardware design.
I've built a truly messy prototype with 5 displays. I've ordered some PCBs which are again 5 displays wide, for the current project I have in mind, 5 should be enough. I may get an 8x2 PCB designed with some smaller displays, I may not.
The font table I used for decoding the Ascii character into the row data was shamelessly borrowed from one of the GLCD header files. I have changed the US Dollar symbol into a UK Pound so that character 36 displays "£" but it is otherwise untouched and uses the index table form the same header file to lookup where the data is held within the font table itself.
The serial interrupt was also shamelessly borrowed from an example on how to fill a circular buffer using an interrupt. I've modified this to capture only the two bytes I need.
The software should hopefully be reasonably self explanatory. Each display can be connected up and with a 4k7 connected to the serial in port to either ground or 5V to stop it from picking up random data, the message "Check serial" should scroll across the 5x7 display. I labelled the output ports for the displays as "Row1", "Row2" and so on. These should be wired to the LED "Row1", "Row2" and the columns are also labelled "Col1", "Col2" in the same way. I used common cathode displays but I have included routines for common anode display types. Near the start of the program there is a "#Define CommonCathode" declaration. If this is replaced with "#Define CommonAnode" the required changes should me made. Don't use both, odd effects could occur. I've not tried the Common Anode type of display, but hopefully it should work.
A video of the messy prototype is linked, along with the source for the receiver(s) - one receiver needed for each 5x7 display, and a demonstration transmitter. The transmitter uses a 12F1840. Only because I was running out of room on my breadboard! I was using (another) 16F1829 for the transmitter and it can be seen lying down and resting at the side of the breadboard.
Sorry for the poor video. My 'phone seems to constantly lose focus which is very annoying...
https://youtu.be/Kqu1vtvOS5Q
Last edit: mkstevo 2020-06-15
A video of the display running the demonstration code in action. Sorry about the mess, sorry about the camera keeping trying to focus on the wiring not the displays.
When the PCBs turn up, I'll post another, hopefully better, video.
https://youtu.be/Kqu1vtvOS5Q
I've made some refinements to the software. This has sped up the serial communications and reduced some of the time taken to propagate the serial data down the displays, this in turn reduces some flicker of the displays caused by the serial interrupt halting the display multiplexing momentarily.
Updated source attached to the original post.
I've received the PCBs to make up a 5 element display to this design. As promised, I've taken another video. The video is "better" but the camera on my 'phone still seems to jump in and out of focus at will. I apologise for that.
On the PCB I made provision for four left-aligned decimal points for displaying numerals, one of these is illuminated during the numbers countdown.
As it wouldn't make sense to have a "leading" decimal point (or a lagging one if it comes to that) The rightmost display has a 12V piezo buzzer connected in place of the decimal point LED. Although it is a 12V unit, the ones we use work well enough with a 5V signal direct from the PIC that I've stopped using a buffer transistor for them. The buzzer is "bipped" for 10mS in between each frame to demonstrate it working.
I've made some additional improvements to the software of both the transmitter and the receiver which I've updated in the original post.
https://youtu.be/sGTqE4EOZ38
The software has the capacity to address 55 display elements. I've built another unit, with ten elements. Having more displays does mean that refreshing or updating the displays takes longer as the data must be passed from the first display, down the line until the target display is reached. It is possible to update individual display elements, without affecting those displays before or after the target. This is demonstrated when the "Be smart, stay apart" message is shown.
In the demonstration for the five character display, a "countdown" is performed. The displays I made, all have the "first" element on the left with the "last" on the right. The least significant digit is then displayed on the "first" display and as the countdown is run, it is the least significant digit which changes the most. This gives greater update speed as only those digits which have changed are updated. The "£" symbol in the last display is sent only once and never changes during the countdown. The "tens" only changes once, the "units" change sixteen times (I think!). The decimal point is sent only once. The "tenths" are updated 159 times (I reckon...). But the "hundreths" change 1599 times (I really haven't worked this out. I could be wrong, but you get where I'm going with this). By having the display element which changes most, as the first element means that display updates can be performed quicker and with less visual disturbance to the other display elements. For left to right scrolling of words, it makes little difference which end is the "first" as every display element must be updated for every character.
I should add that the size of the displays is 50mm high (2 Inch). These have super bright red LED pixels and are indeed bright given that they are multiplexed and refreshed continuously.
Here is a picture and a short video of the ten element display. The picture was taken "mid scroll" so doesn't make grammatical sense. It was part way through writing "stay safe,support the NHS" and it is partially displaying "tay safe,s".
https://youtu.be/IsFJDxxkzCk