Overview of the Serial Communication Protocol
Big Print
To create the block text on the display, the user calls bigPrint
, which accepts two arguments: text
, the string to display, and position
, a tuple of the upper left corner that marks the starting point at which the block numbers are placed on the screen. (Python classes expect the instance of a class itself, called self
, as the first argument of each class method. Therefore, it looks like each method takes one more argument than it actually does – even methods that take no arguments.)
Lines 95 and 96 break apart the position tuple and define x
and y
. The keen observer will note that the y coordinate is decoded from the first position in the tuple, which is the opposite of typical Cartesian coordinates. This is just the way curses handles coordinates. If your text seems to be going awry, it never hurts to check that you haven't swapped x
and y
at some point. Line 97 stores the starting y
position in originalY
which is reset after drawing each character.
Line 99 starts a set of loops to retrieve one character at a time from text
, the string to display. The next line checks to see if the program knows how to draw this character (i.e., it is defined in the self.digits
dictionary). If so, the drawing proceeds.
Starting on line 101, if you go back to the digit definitions in __init__
, the first line is always blank (created by the newline after the triple quotes). That way, the columns of the digits align so they are easier to read (and define). This flag is needed later to discard the blank line.
Each line in self.digits
is a full-size representation of the digit to be drawn. Therefore, line 102 (working right to left) uses split
to divide self.digit
at each newline. The index char
comes from the loop on line 99 – the character the program is working with right now. The for
then processes each character with the next block of code.
If firstLine
is true
, the flag is cleared (line 104) and the program continues. This discards the blank line at the top of the digit.
The outLine
variable is the string that is drawn to the screen. Lines 107-109 create content by walking down each character in line
(the big digit definition). If it is a pound sign (hash mark), the code adds chr(97)
to outLine
. ASCII character 97 is normally a lowercase a, but in "graphics" mode it is a solid block. If the character isn't a pound sign, the program passes through whatever is in the original string (probably a space).
Line 110 tells curses to put it all on the screen; that is, on the screen saved in self.screen
, it adds a string (addstr
). The first two arguments are the screen coordinates where the string is to appear (remember, the y coordinate is first). The third argument is the string to draw. I use a format
statement defined with {0:5s}
to make sure that five characters are always output. The final argument draws with graphics characters (curses.A_ALTCHARSET
) instead of text. The end of the block has some housekeeping to get ready for the next line and ultimately the next digit by incrementing y
, then checking to see whether five lines have been drawn. If so, it moves to the next digit and back to the top of the requested coordinates to draw the next digit before incrementing x
by 7
. If the program were drawing one character per "cell," it would only have to move over by one, but because each "cell" in this case is essentially a pixel it has to move over the full width of the character, plus a little to space things out.
Main Loop
The main loop (lines 116-134) calls all of the functions discussed so far. It starts by initializing looping
– the flag that signals whether to exit – to True
. The time.time
function gets the current time, and nextClock
is set to startTime + 1
before the loop starts on line 121.
In the loop, key
initializes before trying to get a key in a try
/except
block. If a key is available, the try
succeeds, and key
contains the value; otherwise, the except
block runs and does nothing (pass
).
Lines 128 and 129 check to see whether key
is a space. If so, looping
is set to False
. The next trip through the loop will terminate because looping
is the condition checked (line 121) to see whether it should continue or not.
The value of nextClock
(line 119) is when the clock needs to be refreshed. The loop is running much faster than once per second. So once the current time (time.time
) is greater than nextClock
, it is time to update the display. Line 132 gets the new time, and line 133 calls self.bigPrint
and formats the current time as hour:minute:second. Finally, line 135 increments nextClock
by one second so the loop knows when to refresh the display again.
By keeping track of when updates need to happen in the future, the main loop can keep doing other tasks (e.g., monitoring other communications channels, checking the status of a server, etc.) until it is time to redraw the display.
The final two lines run the program. Everything I've talked about so far won't do anything unless it is initialized and called. Line 136 creates an instance of the class in screen
, and screen.loop
(line 137) starts the main loop to set everything in motion.
Conclusion
In this article, I explored serial communications, starting with electrical specs and working all the way up to protocols and libraries. I also looked at different flavors of serial and how they can interact with one another. The next time you need to talk to a unique device or move data to or from a small-board computer like the Arduino, consider starting with these ideas and expanding them into your next project.
Infos
- RS-232: https://en.wikipedia.org/wiki/RS-232
- RS-485 on Wikipedia: https://en.wikipedia.org/wiki/RS-485
- Arduino: http://www.arduino.cc
- Python serial library: https://pythonhosted.org/pyserial
- Python curses library: https://docs.python.org/3/howto/curses.html
« Previous 1 2 3 4 5
Buy Linux Magazine
Direct Download
Read full article as PDF:
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
News
-
An All-Snap Version of Ubuntu is In The Works
Along with the standard deb version of the open-source operating system, Canonical will release an-all snap version.
-
Mageia 9 Beta 2 Ready for Testing
The latest beta of the popular Mageia distribution now includes the latest kernel and plenty of updated applications.
-
KDE Plasma 6 Looks to Bring Basic HDR Support
The KWin piece of KDE Plasma now has HDR support and color management geared for the 6.0 release.
-
Bodhi Linux 7.0 Beta Ready for Testing
The latest iteration of the Bohdi Linux distribution is now available for those who want to experience what's in store and for testing purposes.
-
Changes Coming to Ubuntu PPA Usage
The way you manage Personal Package Archives will be changing with the release of Ubuntu 23.10.
-
AlmaLinux 9.2 Now Available for Download
AlmaLinux has been released and provides a free alternative to upstream Red Hat Enterprise Linux.
-
An Immutable Version of Fedora Is Under Consideration
For anyone who's a fan of using immutable versions of Linux, the Fedora team is currently considering adding a new spin called Fedora Onyx.
-
New Release of Br OS Includes ChatGPT Integration
Br OS 23.04 is now available and is geared specifically toward web content creation.
-
Command-Line Only Peropesis 2.1 Available Now
The latest iteration of Peropesis has been released with plenty of updates and introduces new software development tools.
-
TUXEDO Computers Announces InfinityBook Pro 14
With the new generation of their popular InfinityBook Pro 14, TUXEDO upgrades its ultra-mobile, powerful business laptop with some impressive specs.