Εμφάνιση αναρτήσεων με ετικέτα LCD. Εμφάνιση όλων των αναρτήσεων
Εμφάνιση αναρτήσεων με ετικέτα LCD. Εμφάνιση όλων των αναρτήσεων

Σάββατο 4 Ιουλίου 2015

LCD Display Library for Tiva and Stellaris Launchpads

Liquid Crystal Displays (LCDs) are great for creating impressive (and sometimes, useful!) microcontroller projects. The 16 characters / 2 lines display is very cheap and directly supported by the arduino LiquidCrystal library (also works in  MSP430 with Energia).

In this post we implement similar functionality for the Tiva C series and  Stellaris launchpads. This version of the library works in CCS and can be used with Stellaris LM4F120, TivaC TM4C123G and Tiva C Connected TM4C1294 launchpads with minimal changes.

LCD library in action. Also current state of Greek economy :)


You may download the complete project from my github page.

The HD44780 specification

LCDs that use the HD44780 drivers are commonly called COGs (Chip on Glass) as they contain all the necessary circuits to drive the LCD segments and communication with the host processor is generally limited to the following pins:
  • DB0 to DB7 Data bus. The bus is used to communicate commands or characters to be written to the screen, one byte at a time. To save MCU pins, the interface can be configured for 4 bit operation, where only the DB4 to DB7 lines are used.
  • An RS (Register Select) pin. Specifies whether the data bus is carrying a command to be executed or a character to be displayed. When RS is low,  data on the bus represents a command, otherwise it represents a character.
  • An EN pin. This is a strobe pin, It has to be pulsed Low-High-Low for the LCD to accept the data in the bus.

When using 4 bit mode, the above connections require 6 pins of your MCU.

The LCD display will also require additional pins to be connected to Vcc or GND, including:
  • Power and ground for the LCD and HD44780 ICs.
  • Power and ground for the LCD backlight (if applicable)
  • Ground connection of the R/W pin (to enable writing to the LCD).
  • A potentiometer between Vcc and GND to pin 5 for adjusting display contrast. 
Here is the pinout used in my version of the LCD library for the TivaC launchpad. Pin assignment can be easily reconfigured using the appropriate #define statements in display.h file:

LCD pin       TivaC
-------------------
DB4           PD0
DB5           PD1
DB6           PD2
DB7           PD3
RS            PE4
EN            PE5

The Code

Let's have a look at how the library works. It is based on the HD44780 spec and heavily influenced by a similar work for the MSP430 published in the Co-Random Thoughts blog. The display.h file defines some useful macros to represent the pins and ports we use:

#define RS GPIO_PIN_4 // Energia Pin 5
#define EN GPIO_PIN_5 // Energia Pin 6
#define D4 GPIO_PIN_0 // Energia Pin 23
#define D5 GPIO_PIN_1 // Energia Pin 24
#define D6 GPIO_PIN_2 // Energia Pin 25
#define D7 GPIO_PIN_3 // Energia Pin 26
#define ALLDATAPINS  D7 | D6 | D5 | D4
#define ALLCONTROLPINS RS | EN

#define DATA_PORT_BASE GPIO_PORTD_BASE
#define CMD_PORT_BASE GPIO_PORTE_BASE
#define DATA_PERIPH SYSCTL_PERIPH_GPIOD
#define CMD_PERIPH SYSCTL_PERIPH_GPIOE

The DATA_PORT_BASE points to Port D which is configured for the data bus. CMD_PORT_BASE points to Port E, configured for the RS and EN signals.

To start up the LCD in 4 bit data mode, we have to send the following command to the D4-D7 pins twice:

D7 D6 D5 D4
 0  0  1  0

For this, we need to pull RS low, send the command, strobe the LCD via the EN pin, wait a bit and repeat. After this step the LCD is switched to 4 bit mode. All subsequent 8bit commands / characters are sent as  a pair of nibbles.

Here is the relevant code in initLCD:

void initLCD(void)
{
SysCtlPeripheralEnable(DATA_PERIPH);
SysCtlPeripheralEnable(CMD_PERIPH);
GPIOPinTypeGPIOOutput(DATA_PORT_BASE,  ALLDATAPINS);
GPIOPinTypeGPIOOutput(CMD_PORT_BASE, ALLCONTROLPINS);
GPIOPinWrite(DATA_PORT_BASE, ALLDATAPINS ,0);
GPIOPinWrite(CMD_PORT_BASE, ALLCONTROLPINS ,0);

SysCtlDelay(10000);

setCmd();
SysCtlDelay(15000);
GPIOPinWrite(DATA_PORT_BASE, ALLDATAPINS, 0b0010);
pulseLCD();
GPIOPinWrite(DATA_PORT_BASE, ALLDATAPINS, 0b0010);
pulseLCD();

PulseLCD is a simple function that pulses EN to Low-High-Low states:

void pulseLCD()
{
// Go Low -> High -> Low
GPIOPinWrite(CMD_PORT_BASE, EN, 0);
GPIOPinWrite(CMD_PORT_BASE, EN, EN);
GPIOPinWrite(CMD_PORT_BASE, EN, 0);
}

Similarly the setCmd() and setData() functions switch the RS pin to low / high respectively.

After successfully initializing the LCD to 4bit mode, we sent a few more commands:

sendByte(0x28,FALSE);  // Set two lines
cursorOffLCD();       // Cursor invisible
sendByte(0x06, FALSE); // Set insert mode

After setting insert mode, the LCD is ready to accept characters for printing. The sendByte function sends a byte as a pair of nibbles:

void sendByte(char byteToSend, int isData)
{
if (isData)
setData();
else
setCmd();
SysCtlDelay(400);
GPIOPinWrite(DATA_PORT_BASE, ALLDATAPINS, byteToSend >>4);
pulseLCD();
GPIOPinWrite(DATA_PORT_BASE, ALLDATAPINS, byteToSend);
pulseLCD();
}

The high nibble is set first followed by the low nibble. The display is strobed to accept each nibble. RS is set accordingly for data (high) or command (low).
Timing is important: with the delays currently in the program, the LCD works fine when running at 25MHz frequency. If you need to run at the full 80MHz of the TivaC (or more for the TivaC Connected) you will need to introduce more SysCtlDelay statements  or the display will fail to catch and garbled text will be shown!

Printing to the LCD is  very simple: Just send the characters of your string one by one to the sendByte function:

void printLCD(char *text)
{
char *c;
c = text;

while ((c != 0) && (*c != 0))
{
sendByte(*c, TRUE);
c++;
}
}

The library implements a few more command of the HD44780 protocol. Here are a few interesting hex codes to try:

Function Definition    Hex Code
Set 4 bit mode         0x0
Scroll one char right  0x1E
Scroll one char left   0x18
Goto Home position     0x02
Go one char left       0x10
Go one char right      0x14
Underline cursor on    0x0E
Blinking cursor        0x0F
Invisible cursor       0x0C
Blank display          0x08
Clear display          0x01
Set next position      0x80+Address

More details are available in the HD44780 datasheet.

Happy coding!

Σάββατο 4 Απριλίου 2015

Intel Galileo: Linux, SSH, Static Addresses and Other Tips

I've recently acquired an Intel Galileo Gen 2 development board. Intel Galileo (just in case you haven't heard about it) is Intel's answer to the Arduino driven hobbyist community. In fact, Galileo is (or supposed to be) pin compatible with Arduino Uno: you can even use Uno shields on it. Galileo is programmed using the same IDE as the Arduino (albeit patched by Intel) and the sketches - once recompiled - are (supposedly) compatible: You can just move your LCD display circuit from your Uno to your Galileo, recompile and upload the program and it should work. Well, for the most part that is...



So why buy a Galileo instead of (or in addition to) a standard Uno or other AVR based Arduino? The Galileo is using an Intel SoC (System on-a Chip) running at no less than 400MHz. It is equivalent in power to some older Pentium CPU. There is more to it: There is 256MB of RAM on board, a micro-SD card slot, an Ethernet port and even a micro PCI-Express underneath for your WiFi card. Galileo is admittedly over-specified for an Arduino. And with good reason: Even without any SD inserted, Galileo runs a small Linux version inside it. You will notice it as it takes some good time to start and appear on the USB connection. And there is an even more complete Linux version available as an SD card image. Linux and Ethernet easily make this device an IoT (Internet of Things) development board.

How would you access the Linux part of Galileo? Let's examine two scenarios:
  1. Access the built-in Linux. This is what runs on the Galileo if you don't insert any SD card.
  2. Access the SD card Linux (Download it from here, along with any other utilities you need).

Accessing the Built-in Linux via Telnet

If you look at most of the Galileo tutorials you will find more than a few ways to access the Linux part of your Galileo:

  • Use a serial cable and a (custom made) connector for the serial out pins (gen 2) or 3.5mm jack (gen 1). This is easy to do but most PCs lack proper RS-232 these days and I find USB to serial as a last resort scenario.
  • Run a sketch to reconfigure the USB port as a serial terminal and use that for connecting. There are a couple of problems with this approach: although it will supposedly work on the built-in Linux, it stops accepting input after you connect through i.e. PuTTy. You will get a login prompt and a shell but that's about it. It won't execute any commands. It works a little better with the SD card version of Linux but there is another serious drawback: the sketch permanently reconfigures the USB port for serial connection and you lose the ability to upload sketches.
What if you really want to have both Linux *and* your sketches running at the same time?

It turns out that the built-in Linux does not have an ssh daemon, so we will have to use telnet. No big deal. And instead of going the serial route, let's try that nice Ethernet port. Ethernet is a lot more common these days: just plug your Galileo into your home switch then upload a sketch that looks like the following:

void setup() {
  system("ifconfig eth0 inet 192.168.0.10 netmask 255.255.255.0 up");
  system("telnetd");
}

void loop() {
}

Obviously, you will have to change 192.168.0.10 to an address that matches your home setup. If you are using DHCP (very common on home routers) just make sure you assign it a static address outside the scope of the DHCP server (I assume that as a good admin you've kept a couple of addresses from being automatically assigned, haven't you?)

You are now ready to telnet into your device! Use PuTTy from Windows or the command line telnet client from another Linux box. This is what you will get:



Login as 'root'. There is no password set.
Now that you are in, there is no need for the script to keep executing. Use the top command:

# top


Find the process id for /sketch/sketch.elf and just kill it (it usually is at the top of the list):

# kill 929

Or you could simply upload another sketch to execute. Unlike the USB serial approach, your upload ability is not affected in any way.

Play with the built-in Linux as long as you like: you will soon find out it is pretty limited in what it can do. And the moment you unplug your Galileo all the settings are lost: your sketches are erased and the nice static IP you've assigned is gone. You will have to rerun the above sketch after every reboot.

Sooner or later (probably sooner!) you will decide to migrate to the SD card version of Linux.

Accessing SD Card Linux via SSH and making settings permanent

So you've created an SD card image of Yocto Linux using Intel's instructions. And now you want to SSH into it.
  • First, be patient. The SD card Linux may take more time to boot than the built-in version. You will know it has booted successfully when the USB connects to your PC (if you use Windows, it will make a sound)
  • The SD card Linux provides an SSH service. Even better, you can make your IP address (and other settings) permanent.
  • You will have to consider security if you leave your Galileo running and connected to the Internet.
As you can imagine, the script to get SSH access is even easier than before:

void setup() {
  system("ifconfig eth0 inet 192.168.0.10 netmask 255.255.255.0 up");
}

void loop() {
}


The SSH server is already running on SD card Linux, no need to restart it. Just assign your static IP and you are good to go! You can now login and make your settings permanent.

Use top and kill (like we did before) to stop the sketch from running. It is no longer necessary.  You may as well remove it so it won't run at next boot. We will make the configuration changes permanent anyway:

# rm /sketch/sketch.elf

The first thing you will want to do is assign a root password:

# passwd
Changing password for root
Enter the new password (minimum of 5, maximum of 8 characters)
Please use a combination of upper and lower case letters and numbers.
New password:
Re-enter new password:
passwd: password changed.

Change the /etc/network/interfaces file to assign your static IP address permanently. (It seems the only available editor is vi...) Find the following line:

iface eth0 inet dhcp

and change it to:

iface eth0 inet static
   address 192.168.0.10
   netmask 255.255.255.0
   gateway 192.168.0.250

The gateway part is only needed if you intend to give Galileo Internet access. You will also need to reconfigure /etc/resolv.conf for this (we will do it after a few more steps). The address on the gateway part is of course your home router's IP.

The above setting is not enough though: Galileo uses the Network Connections Manager (conman) to configure the network interfaces and the above file is ignored in this case. We will have to revert to the older method:

# cd /etc/rc5.d
# rm S05conman
# ln -s ../init.d/networking S05networking

Now reboot your Galileo:

# shutdown -r now

When it comes up again, just connect via SSH. No need to rerun the sketch as the changes to the files are permanent.

If you wish to connect your Galileo to the Internet, add this line to /etc/resolv.conf:

nameserver 192.168.0.250

Where 192.168.0.250 should actually be your router address. Or another available DNS server (if in doubt, use Google's DNS: 8.8.8.8).  For this to work, you must also have a valid gateway line in /etc/network/interfaces.
While still logged in as root, you may wish to change the weird 'clanton' hostname to something more cool. Just edit the /etc/hostname file and replace the contents with the name of your choice. Hostname will change on the next reboot.
If you wish to have a message of the day (motd) appearing at every login, create an /etc/motd file with your desired contents.

Securing your Galileo Linux

At a minimum, you will want to take a few security measures if you decide to connect your Galileo to the Internet:
  • Give the root user a password. We've already done that.
  • Disallow root logins via SSH.
  • Create a standard user account for 'normal' use.
Creating a standard user acoount is easy:
# useradd -g root johndoe

(Johndoe is actually not a good choice for a username, but you get the idea!). It is best to make your user a member of the root group. The permissions on some devices (like /dev/null) are read-write for the root user and group only and will hinder your ability to use some commands like scp unless your account belongs to the root group. Give your new user a password:

# passwd johndoe
Changing password for johndoe
Enter the new password (minimum of 5, maximum of 8 characters) Please use a combination of upper and lower case letters and numbers.
New password:
Re-enter new password:
passwd: password changed.

This is a good time to check whether the new account works. Just open a new SSH connection and try to use the new user instead of root to connect. If it all works, continue by disabling the root login via SSH:
Edit /etc/ssh/sshd_config. Find the line that shows

PermitRootLogin yes

And change yes to no:

PermitRootLogin no

Or, alternatively, just comment out the entire line. The default setting for SSH is to not allow root logins.
Just reboot your Galileo and you are good to go:

# shutdown -r now

From now on, you will use your new user account to connect via ssh. You can always use:
$ su -

to switch to root when needed.
Sudo would have been a nice addition to this Linux version, but it is not available by default and I haven't researched package management yet!
You could create some fancy bash startup files for your account. You may also use my version (a slightly simplified version of what I use on my FreeBSD machines). Just login as the user you created and:

$ wget http://www.freebsdworld.gr/files/galileo-dot.tar.gz
$ tar xvzf galileo-dot.tar.gz

You may need to press 'A' to overwrite an existing file. Logout and login again to apply the changes.

Getting an LCD Screen to Work with Galileo

LCD screens are very popular with Arduino 'users' as they add a whole new dimension to projects. The 16 character, 2 line variant seems to be the most common and it is the one I currently have.
Since Galileo is Arduino Uno compatible, all you would have to do is move your LCD circuit from your Uno to Galileo (to the same GPIO pins), recompile your program for Intel and upload it. Well, supposedly.
Because I followed these exact steps and got just a blank LCD staring at me. Apparently you need to update the LCD Driver libraries with the ones found here.
After unzipping the file, replace all the contents of the libraries/LiquidCrystal folder (in your Arduino installation folder) with the contents of the archive.

Rebuild and upload your project - your screen should now be working!


Happy coding!