Custom Characters for the ByVac 20x4 IASI-2 LCD



The HD44780 Controller used in the ByVac 20x4 IASI-2 Serial LCD module supports up to eight user-defined characters in the address range 0x00 to 0x07. The characters are "mirrored" at addresses 0x08 to 0x0f. As sending character 0x00 sometimes upsets the serial module, I tend to start from character address 0x01 or use the higher range. ("Normal" ASCII characters start with the space character at 0x20 ).

There are a variety of different serial interface modules available on the ByVac website, all of which are compatible with virtually every 16x2 and 20x4 LCD module out there provided it's based on the Hitachi HD44780 (or compatible) Controller. Serial modules are available with VT100 (standard terminal), dual I2C/VT100, and IASI-2 protocols. I tend to use the IASI-2 version and there's plenty of documentation on the seller's website.

Regrettably, the excellent documentation provided by ByVac for the Arduino will now need to be updated because Arduino have made some significant changes to the latest version of their IDE - version 1.0.

One of the principal changes is they no longer bundle WProgram.h with their installation package. Instead they've added a new file called Arduino.h. As #include <WProgram.h> is one of the most commonly included header files in program (sketch) examples on the web - and is even still used frequently in Arduino's own documentation - the result is confusing for Arduino newcomers, such as myself.

I copied WProgram.h and wiring.h (which the complier also complained about) from the website and copied them into the Arduino "core" library folder. In my case... c:\arduino\arduino-1.0\hardware\arduino\cores\arduino\. The ByVac examples then compiled and ran perfectly. (I only have a 16x2 display available at the moment so I modified the BV4108 example to suit).

Note that the ByVac example displays shown below need both rxPin and txPin connected to the Arduino (Pins 5 and 4 respectively in the ByVac BV4108 example).


Meanwhile, the code below shows how to send serial data to the ByVac 20x4 (or 16x2) IASI-2 Serial LCD module and how to program custom characters with the Aurduino Uno and display it on the LCD using the standard SoftwareSerial library, without using the ByVac libraries.

Please bear in mind, I'm very new to the Arduino programming environment so I make no claim that this code is the "best" - or even the correct - way to do it. This program (sorry, sketch) demonstrates what I've learned about the Arduino so far and I've typed it out before I forget!

As I'm not requesting any data be sent from the BV4108 controller, I don't need to connect the Arduino rxPin.

#include <SoftwareSerial.h>

#define rxPin 2
#define txPin 3

                  // lcdSerial(rxPin, txPin, [inverted: true | false])  // Default inverted = false

      SoftwareSerial lcdSerial(rxPin, txPin);     // Create an Object of type 'SoftwareSerial'
                                                 // Only the txPin (pin 3) is connected (to the LCD RX Pin)
void setup()  {
      analogReference(INTERNAL);                 // Set up analogue to test LM35DT temperature sensor.
                                                 // 1.1v reference.

      lcdSerial.begin(19200);                     // 9600, 14,400, 19,200 or 38,400 available on the ByVac LCD.
                                                 // Arduino recommend no higher than 9600.
      lcdSerial.print("\r");                      // Send 'CR' for the LCD to establish the speed.
      lcdSerial.print("ac1\r");                   // Clear display. Terminate data with 'CR' (0x0d)
      lcdSerial.print("acc\r");                   // Cursor Off
      byte alien1[8] = {                         // Create alien1 array with alien1 face (Binary example)
        B01110,                                  // -###-
        B10101,                                  // #-#-#
        B01110,                                  // -###-
        B11111,                                  // #####
        B01010,                                  // -#-#-
        B01010,                                  // -#-#-
        B11011,                                  // ##-##
        B00000                                   // -----
      createCustom('a', lcdSerial, 1, alien1);    // Write data to LCD CGRAM as character 1

      byte alien2[8] = {                         // Create alien2 array with alien2 face  (Decimal example)
         31, 21, 31, 31, 10, 10, 27, 0
      createCustom('a', lcdSerial, 2, alien2);    // Write data to LCD CGRAM as character 2
      byte alien3[8] = {                         // Create alien3 array with alien3 face
         31, 21, 27, 31, 10, 10, 27, 0 
      createCustom('a', lcdSerial, 3, alien3);    // Write data to LCD CGRAM as character 3

Custom Graphics designer application for Windows

void loop() {
     int sensor = analogRead(0);                 // Read the 0 - 1024 value from sensor 
     float temp = sensor * 0.09765625;           // Convert to C. Range of LM35DT is 0 - 100. 
                                                 // 100 / 1024 = 0.09765625 per degree.
                                                 // The map() function only does integers.

     lcdSerial.print("ac80\r");                   // LCD Cursor to row 1, col 1.
     lcdSerial.print("adHello World ");           // Basic text test.

     lcdSerial.write(1);                          // Display the three custom characters
     lcdSerial.write(2);                          // which where written to CGRAM
     lcdSerial.write(3);                          // locations 1, 2 and 3.

     lcdSerial.print("\r");                       // IASI-2 protocol requires the CR character
                                                 // to terminate the current input.
     lcdSerial.print("acc0\r");                   // LCD Cursor to row 2, col 1.
     lcdSerial.print("adTemp:  ");
     lcdSerial.print(temp, 1);                    // print the temperature to one decimal place
     lcdSerial.print(" ");
     lcdSerial.write(B11011111);                  // degree symbol (from the HD44780 LCD datasheet)
     lcdSerial.print("C \r");

//   createCustom(LCD device 'a' - 'z',  SoftwareSerial Object, CGRAM character number, CGRAM Data array)
//   Although I will generally only be using one LCD and, therefore, one SoftwareSerial Object, I've passed
//   the device address and the Object name to createCustom to, hopefully, increase its portability - until I
//   discover the proper way to do it!

void createCustom(char device, SoftwareSerial ser, char chrnum, byte cgramData[]) {

     ser.print(device);                          // Send the device address to the LCD. (default is 'a')
     switch(chrnum) {                            // Enumerate the LCD CGRAM location and send as a Command ('c')
       case 0: { ser.print("c40"); break; }      // followed by location as a Hex string.
       case 1: { ser.print("c48"); break; }
       case 2: { ser.print("c50"); break; }
       case 3: { ser.print("c58"); break; }
       case 4: { ser.print("c60"); break; }
       case 5: { ser.print("c68"); break; }
       case 6: { ser.print("c70"); break; }
       case 7: { ser.print("c78"); break; }
     ser.print("\r");                            // Terminate the input with CR.

     ser.print(device);                          // Send device address.              
     ser.print("d");                             // Tell the LCD that data is coming ('d').
     for(char i=0; i<8; i++)                     // Write the contents of the previously-created array
       ser.write(cgramData[i]);                  // to the GCRAM location.

     ser.print(device);                          // Reset the LCD memory to the normal display DDRAM.


Back to Index

This site and its contents are © Copyright 2005 - All Rights Reserved.