This project uses a serial 40x4 LCD display
with a Teensy board to realize a compact serial terminal receiver to be
connected to many systems with serial output such as our microcontroller systems
and GPS receivers.
The terminal connected to a GPS receiver.
The Teensy board
I used a Teensy 3.1 because it is very powerful,
its most important features are:
·
Processor:
MK20DX256 32 bit ARM Cortex-M4 72 MHz;
·
Flash Memory: 256k, RAM Memory: 64k, EEPROM: 1k;
·
I/O: 34, TTL 3.3V, 5V tolerant;
·
Analog In (16 bit, 13
effective): 21;
·
UART,I2C,SPI: 3,2,1;
and finally, it is very
inexpensive compared to its features. Now it has been replaced by
version 3.2, 100% compatible.
The
display
I have adopted a large alphanumeric display 40
columns by 4 rows, a DMC40457 of Optrex Corporation. As can be seen from the
following table, the connections of this type of display are very different
from the more common 16-column for two rows. Furthermore there is a second
enable signal, being necessary two HD44780 chip. The connector has 16 pins,
arranged in 2x8.
pin
|
function
|
pin
|
function
|
1
|
D7 Data Bus Line
|
2
|
D6 Data Bus Line
|
3
|
D5 Data Bus Line
|
4
|
D4 Data Bus Line
|
5
|
D3 Data Bus Line
|
6
|
D2 Data Bus Line
|
7
|
D1 Data Bus Line
|
8
|
D0 Data Bus Line
|
9
|
E1 -
Enable Signal #1
|
10
|
R/W
- Read/Write
|
11
|
RS
Register Select
|
12
|
VEE - Power Supply
|
13
|
VSS - Power Supply
(GND)
|
14
|
VCC - Power Supply
|
15
|
E2 -
Enable Signal #2
|
16
|
Not connected
|
There are also displays with LED backlight, in
which case the connector has 18 pin. The backlight will significantly increase
the consumption of the display.
To drive the LCD display dual chip, I used the
LiquidCrystalFast library by John Raines. It is not, at the time, capable of
driving the LCD display 40x4 with a faster 8-bit data bus, then I used the
4-bit data bus (D4..D7) plus 4 control bits (E1, E2, R / W , RS), eight bits
configured as outputs. The fields of the table with a yellow background
representing the used pins, then 8 bits + 3 for power supply.
The configuration of the display function has
the following syntax:
LiquidCrystalFast lcd(RS, RW, E1, E2, D4,
D5, D6, D7);
In our
case it becomes:
LiquidCrystalFast
lcd(21, 4, 2, 6, 17, 18, 19, 20);
If you don’t think of working with long lines you
can use smaller displays as a 20x4 with only a single HD44780 chip. In this
case you have to make some changes on the LCD wiring and program. You can now
use the library LiquidCrystal of the Arduino IDE.
Baud
rate selector
To select the baud rate I used three of the
four dip switches for a total of eight communication speed. The fourth can be
used to select other communication parameters. The following table shows the
positions of the first three dip switches and the corresponding baud
rates. Usually the dip switches with the
levers in the low position are closed (ON) which corresponds to logic zero.
The power supply
As already said, the Teensy provides the power
supply from USB, but I preferred to have more independence from grid power
using rechargeable batteries. The simplest and cheapest solution was to use a
commercial device which is now very widespread, usually called 'mobile power
bank'. It is used to give energy to our smartphone or tablet, when they used
batteries and are not close to grid socket. These devices incorporate, in a small
volume, one or more rechargeable batteries Lithium Polymer, a battery charger
(5V to 4.2V) and a switching power supply step-up to produce the 5V from 3.7V.
The internal battery charger uses an external power supply common with micro
USB connector, now standard for mobile phones and tablets, while the output 5V
are available on a standard USB type A connector
With power from Vin, as in our case, you must
include a switch that must be OFF when we insert the USB plug, otherwise you
may be trouble to the power supplies or you can burn the small fuse on the
Teensy board. On the same tour you can be interrupted with a cutter the thin
runway under the card (for more information see the www.pjrc.com/teensy/ site),
but no longer will be fed the other components of the system, such as the
display, when you using the USB interface.
The wiring diagram
This scheme includes some components that are
not used in this project as J2, J4 and J6 connectors, SD interface and the
Lithium battery for Teensy RTC. Because all pins on the Teensy connectors are
previously engaged, I used for the dip switches some signals from solder pads
on the back side of the board. As can be seen in the following figure, I wired
four signals (pins 24, 25, 26 and R) to a small connector J7, located on the
back of the Teensy board. The following figure shows the wiring diagram of dip
switch and pull-up resistors, mounted on the breadboard. The SW2 button is not
used in this project.
With minor changes to the wiring diagram and
the program you can connect the dip switches to the pins available on Teensy connectors and avoid
soldering the wires on the pad. For example, renouncing the SD interface, you
can use the pins 9, 10, 11 and 12.
The LCD40 board
For this project a breadboard has been used to
securing and connecting all components. The following photo shows the
arrangement of the components on the board and the frame used to support all
other components.
As already mentioned, some components on the board
are not used in this project. This is because I have made a versatile
development system with a large alphanumerical LCD, a SD card interface and a
real time clock for many applications as data logger for analog signals or for
GPS.
The power bank seen in the photo has been replaced because, while being of
good quality, disconnects the current after a few seconds since the system
consumes too little.
The program
To compile the program I used the Arduino IDE
(Version 1.8.1), adding the Teensyduino software add-on (Version 1:35), for more details visit the
website https://www.pjrc.com.
The setup() function, after initializing the
I/O read the status of the dip switches to set the baud rate of the terminal,
this value that is also printed on the display.
To realize a real serial terminal it would be
better to have an automatic scrolling of received lines, so a buffer is
necessary. I used a string array of 4x41 characters. A string size of 41 is
necessary to represent a line of a maximum of 40 characters because strings
have a null character (ASCII code 0) as a terminator.
For the first four lines received, the printing
proceeds from line 0 to line 3. Subsequently, each new line is printed on line
3 while the other three previous lines are shifted up. This operation is done
in the buffer: before transferring the last line received in the buffer#3, the
current content of the buffer#3 is put in buffer#2 and so on until the contents
of the buffer#1 is transferred to the buffer# 0. The whole behaves like a
multidimensional shift register. After this process all the buffers are printed
at one time on LCD.
The libraries for the controlling of the
display have a command to run the scroll, but it refers to the line, and it
does not work like the one proposed.
If a line exceeds 40 characters, the program
truncates it before transferring to the buffer.
To make the system faster, I decided to read a
line at a time instead of working on every single character.
As Teensy has more than one UART, unlike
Arduino Uno, HWSERIAL should be used in place of Serial for all serial
functions and the statement #define HWSERIAL Serial1 must be used to define the UART to be use (1
in our case).
The function HWSERIAL.readStringUntil('\n')
reads a line to the
terminator, which in our case is a CR / LF.
I used two types of strings: the linestr variable is a String class while
the string array is a character arrays type. So I used the function linestr.toCharArray(displayline[3],41); for the conversion.
Code
/*Serial terminal, print on a 40x4 LCD
display,
the library LiquidCrystalFast is used because it controls
also display with double enable pins as that used
Giovanni Carrera -
07/03/2017
*/
//
include the library code:
#include <LiquidCrystalFast.h>
// set this to the hardware serial port
used
#define HWSERIAL Serial1
const int Button = 22; // push button
const int DipSw1 = 23; // dip switch bit
1
const int DipSw2 = 24; // dip switch bit
2
const int DipSw3 = 25; // dip switch bit
3
const int DipSw4 = 26; // dip switch bit
4
const long baud_rate[9] = {1200, 2400,
4800, 9600, 19200, 38400, 57600, 115200};
String linestr;
char displayline[4][41];// display
buffers 4 rows x 40 characters
int r, i;
boolean ft_flag = true;// first time
flag
// initialize the library with the
numbers of the interface pins
//LiquidCrystalFast
lcd(RS, RW, E1, E2, D4, D5, D6, D7);
LiquidCrystalFast lcd(21, 4, 2, 6, 17,
18, 19, 20);
void setup() {
pinMode(DipSw1, INPUT); // set dip switch bits to input
pinMode(DipSw2, INPUT);
pinMode(DipSw3, INPUT);
pinMode(DipSw4, INPUT);
pinMode(Button, INPUT);
// set up the LCD's number of rows and columns:
lcd.begin(40, 4);
// Print a message to the LCD.
lcd.println("Serial terminal by GCar - 07/03/2017");
// read dip switches for baud rate coding
int brcode = digitalRead(DipSw1) + digitalRead(DipSw2) * 2 +
digitalRead(DipSw3) * 4;
lcd.print("Baud rate = ");
lcd.println(baud_rate[brcode]);
HWSERIAL.begin(baud_rate[brcode]);// for Teensy
delay(5000);
for (r = 0; r <= 3; r++) {
displayline[r][0] = 0; // clear buffer
}
LCDprint(); // clear display
}
void LCDprint() {
lcd.clear(); // clear diplay
for (r = 0; r <= 3; r++) {
lcd.setCursor(0, r); // set the cursor to column 0, line r
lcd.print(displayline[r]); // print all four lines
}
}
void loop() {
r = 0;
if (HWSERIAL.available() > 0) {
linestr = HWSERIAL.readStringUntil('\n');
if (ft_flag == true) {
linestr.toCharArray(displayline[r], 41);// store line in buffer
LCDprint();// print all four lines
r++;
if (r > 3) {
r = 0;
ft_flag = false;
}
}
else {
for (i = 0; i <= 40; i++) {
displayline[0][i] = displayline[1][i];// scroll, line#0 = line#1
displayline[1][i] = displayline[2][i];// scroll, line#1 = line#2
displayline[2][i] = displayline[3][i];// scroll, line#2 = line#3
}
linestr.toCharArray(displayline[3], 41);// store new line in line#3
LCDprint();// print all four lines
}
}
}