Drive SC1602 and SC2004 with Raspberry Pi

As I program a driver of SC1602 with paying attention to readability, I even found a defective of SC1602.

As I told you already on the post, “A total beginner started to learn electronics with Raspberry Pi”, Nikkei Linux March 2013 was the beginning of using Raspberry Pi. This post became one of the biggest hit of my blog, and Google puts this post in the top 10 of search results using “Raspberry Pi” in Japanese. (As of September 22th, 2014)

I finished the story when I could turn an LED, but Nikkei’s article continues. Its next step is using an SC1602, a Liquid-crystal display. I have actually bought it with LED together. Because Nikkei’s article has a sample code, I could output some characters on the display. At that time, I couldn’t understand the instruction that came with SC1602 at all. I kept “decoding” the instruction little by little, and I could understand the whole stuff at last.

What is SC1602?

An SC1602 is a display which is used by machines. I searched what machines use SC1602.

Application 01Edy – Rakuten’s money card reader used at some stores in Japan

Application 02NEC’s reader at a convenience store

Application 03Ticketing machine at a parking lot

Application 04Coffee maker

Application 05Metro entrance (London)

Application 06Public phone (London)

Application 07Trash compactor (airplane)

Definition of SC1602

I don’t know about the history of SC1602. I searched but couldn’t find very well. SC1602 would be a generic name of these displays and the method to control these displays.

An SC1602 might be a device which has a Hitachi HD44780-compatible controller. HD44780 is released in 1980s and since then many manufactures released compatible devices.

Most LCDs sold at stores have HD44780. In general, because those LCDs are compatible, they are controlled in the same way, but there are some differences on data sending time and voltage. If you doubt their behavior, check the datasheet that comes with your LCD. – マイコン徹底入門

There is an article about Hitachi HD44780 LCD controller on Wikipedia, but they don’t have an article written in Japanese even it is developed by Hitachi Japan.

The one I bought at Marutsu was made by TINSHARP and says “Sunlike SC1602 compatible.” Suppose SC1602 is compatible to Hitachi HD44780, Marutsu’s LCD is compatible of compatible.

There are some family devices and they can be classified by size such as 10×4, 16×1, 16×2,16×4, 20×2, 20×4, 40×2, and 40×4. As you can see, SC1602 may be named because the size is 16×2.

SC1602s I bought

I bought some SC1602s and one SC2004.

SC1602 and SC2004SC2004 (left) and SC1602 (right)

I soldered pins to the displays…

2 kinds of headers… to plug and unplug. This is the Raspberry wires.

Wire exampleI was first using female pins.

Female PinBut I found that if I used female pins, I couldn’t solder when I create something.

Be careful! Vdd and GND are often assigned to pin number1 and 2, but it is sometimes opposite. If the Vdd and GND pins are connected to the other way, the LCD doesn’t work. Actually it might break. There may be various reasons for doing such a thing. This is regarded as a mystery.

Nikkei’s code

This is the beginning of Nikkei’s code.

GPIO_CLR = 0x1F <<7;        // Clear GPIO10 7-10(DB4-7)and GPIO 11(RS)
GPIO_CLR = 1 << 22;         // GP10 22 (E: Enable Signal) = 0


GPIO_SET = 3 <<7;           // Send 8bit connection config GP10 7-10 (DB4-7) 
                            // GP10 11(RS)=0
GPIO_SET = 1 << 22;         // Enable Signal = 1
usleep(20);                 // Enough wait (20μs)
GPIO_SET = 1 << 22;         // Enable Signal = 0

Even I had knowledge of C, I was amazed. The comment says the first line clears the GPIOs, and the program shifts bits. The program prepares 1F in hexadecimal, shifts it by 7 bits, and writes it to the I/O address of GPIOs.

What does 1F in hexadecimal mean? Why do I need to shift 7 bits? What is I/O address of GPIO? I was at this level and kept investigating one by one.

GPIO_CLR was defined in gpio_setup.h.

#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0

*(gpio+7) points address which is 7 units away from gpio. The gpio pointer is defined like this:

gpio = (volatile unsigned *)gpio_map;

This means the pointer is the same as gpio_map. Then what is gpio_map?

I kept investigating like this.

I found that this program is controlling BCM2835 directly with free use of bit orders I mentioned above.

1F means 11111 in binary. I get this by shifting 7 bits.

1111 1000 0000

The rightmost bit means GPIO0, and the second bit means GPIO1. Because I shifted bits by 7, GPIO7 to 11 are 1. Overwriting these bits to certain address where GPIO_CLR pointer clears those GPIOs.

This procedure lost my energy a lot. I could know how to drive SC1602, but is this the only way to drive?

Electronic DIY and programming

As I searched and read books, ALL people without exception called some libraries. Those libraries “manipulate” 0 and 1 freely. The ways to call those libraries are like these.


We will forget what these source codes mean when we look later. And we can’t call writeByte or lcdwrite unless we know them. Additionally we could miss that b is actually a function like writeByte and lcdwrite.

Even if we can call functions, we need to look up for 00111000 and 0x23. If we look later, this means we are in need of making new functions or fixing problems. We would be in trouble every time we look later.

I’m from the computer field, which would make me believe that people who wrote those codes are in the electronic field and they are still there. They might program because they can’t avoid programming.

Source code and readability

I kept improving the source code, and it became like this.

#include "SC1602.cpp"
int main (int argc, char *argv[])
    SC1602 *lcd;
    lcd = new SC1602;
    lcd << "Hello World!";

Only these few codes do from initializing the LCD to outputting a string. If we forget function names, eclipse helps us. We just need to type “lcd ->”. If you don’t know what I mean, read “Making Raspberry Pi program by cross-compiling C++ with Eclipse on CentOS”.

If you use SC2004, the code would be like this.

#include "SC1602.cpp"
#include "SC2004.cpp"
int main (int argc, char *argv[])
    SC1602 *lcd;
    lcd = new SC2004C;
    lcd << "Hello World!";

And the code of SC2004 is only this.

class SC2004 : public SC1602
    // SC2004-specific configuration
    SC2004 ()
        // Char number of 1 line
        DISPLAY_WIDTH = 20;
        // Char number shown in 1 line
        // Lines
        DISPLAY_HEIGHT = 4;
    unsigned int setDDRAM (unsigned char x, unsigned char y)
        unsigned char address = x;
        if (y == 0);  // Do nothing
        else if (y == 1) address += 0x40;
        else if (y == 2) address += 0x14;
        else if (y == 3) address += 0x54;
        return SUCCESS;

SC2004 “extends” SC1602. Because the way to control is the same as SC1602, we should use SC1602 as is, and “override” only the difference. This is why Object-orientation is convenient.

On the other hand, SC1602 is made to be overridden.

virtual unsigned int setDDRAM (unsigned char x, unsigned char y)

Code refactoring is necessary to override only the difference or to be overridden. This means if we are not interested in code refactoring, it is hard to make the original class (SC1602) to be overridden. I went back and forth between SC1602 and SC2004 when I refactor.

I couldn’t make codes like these at the first time. Object-orientation can be explained with a car and a motorcycle. These classes have common methods like “run”, “move speedometer”, and “refuel”. I could understand what they mean, but they could be just virtual example. The objects are just “data” on a computer, not physical “cars”. I haven’t dreamed that the Object-orientated language worked on physical devices like SC1602 and SC2004.

By the way, be careful that C++ is not always available on electronic DIY. I chose C++ because Microchip PIC32 series supports C++, and I took Object-orientation more than the cost and physical size of PIC32. Even I bought a Microchip PICKIT3, haven’t used it at all. The reason why I bought it is because I wanted to think what language can be ported from Raspberry Pi. I thought Microchip’s PIC was widely used in electronic DIY and it could be highly possible to use in the future.

SC1602 has a bug

The readable codes let me found malfunctioning on SC1602. I bought SC1602s at both Akizuki and Marutsu in Akihabara, and only Akizuki’s SC1602 seemed to have the malfunctioning.

The bug appears when the function code “left cursor shift” is called. When the cursor moves across the address 0x0 from right to left, SC1602 can’t handle DDRAM correctly.

Do you know what left cursor shift is? Strings can be displayed from right to left on SC1602, but you can invert the direction by calling the function code “5: Cursor / display Shift”. I have no idea when I need it. I guess the driver was made to handle letters that are written from right to left like Arabic.

Driver is a chip that controls the display. It might be soldered somewhere on the circuit board of SC1602. I called Sunlike Taiwan, and they said SC1602s sold at Akizuki have Sitronix ST7066U as driver. They also suggested choosing SPLC780D, but the problem is I can’t choose the driver. Kids can’t choose parents.

By the way, the Sunlike personnel said SC1602s sold at Marutsu have different drivers. This could be evidence of my investigation.

Another difference

Once SC1602 receive a function code, it needs time to execute the function. The time SC1602 needs is written in the specification. For example, “Clear Display” takes 1.5 milliseconds. The value may change like 1.52 or 1.64ms, but I don‘t know why. If Raspberry pi sends the next code without waiting, SC1602 ignores it. More precisely, SC1602 looks like ignoring.

I found that SC1602s’ response time is varying. Ones sold at Akizuki can respond in 0.5 milliseconds, and ones sold at Akizuki can respond in 0.4 milliseconds. In either case, nothing wrong happens if you wait 1.5 milliseconds.

No one writes code like “Do not wait for 1.5 milliseconds.” The problem is if we don’t know we need to do so, the program doesn’t wait for even 0.1 millisecond. This means we can never tell what causes problem unless we find it by chance. Additionally, if you output some debug string to the console, it takes more than 0.5 milliseconds, this could let the bug hide. I’ll explain this later.


I published the program that I used for verification. This is an extension of the one I posted before, “Drive RHT03 with Raspberry Pi“.

Download Tango (Japanese Edition Only) – November 3 Edition

About options

Options change what the program does. Some options are required, and some are not. There is no particular order. Options are case sensitive. Options are considered only once in the order they are listed in the Option List below. Because demo10 loops, you need to press [Ctrl] and [c] when you finish.


./tango db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11

Initializes SC1602 in 4 bit mode. A blink cursor appears on SC1602.

./tango db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 clear

Sends function code1 clear to SC1602. A blink cursor also appears on SC1602.

./tango db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 write=ABCDEFG

Sends string ABCDEFG to SC1602.

./ tango db0=18 db1=23 db2=24 db3=25 db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 info

Initializes SC1602 in 8 bit mode and shows configures in the console. A blink cursor appears on SC1602.

./ tango db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 write=ABCDEFG && ./ tango db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 noinit x=0 y=0 read=7

Sends string ABCDEFG to SC1602. If error code is 0, the cursor is move to address 0,0 (You can’t use home.) and then Raspberry Pi reads 1 char from SC1602 and outputs it in the console. Because this is done 7 times, the whole string will be output in the console.

If your LCD won’t work, just wire necessary ones.

SC1602 Raspberry Pi
DB0~DB3 No wire
DB4~DB7 GPIOs you wish
RS GPIO you wish
E GPIOs you wish

Options list

Options behavior
help display usage and quits this program. All other options will be ignored. “usage” can be also instead.
debug output debug information.
SC2004 handle LCD as SC2004. (If not defined, SC1602 is drived)
noadjust omit the adjustment of cursor position after LCD moves the cursor. More details are written later.
noinit omit initialization. Noinit is supposed to be usesd with read.
nosave omit suspend. This affects to energy consumption, but not to function.More details are written later.
db0=[2..31] declare GPIO number to wire DB0.
db1=[2..31] declare GPIO number to wire DB1. (required with db0)
db2=[2..31] declare GPIO number to wire DB2. (required with db0)
db3=[2..31] declare GPIO number to wire DB3. (required with db0)
db4=[2..31] declare GPIO number to wire DB4. (required)
db5=[2..31] declare GPIO number to wire DB5. (required)
db6=[2..31] declare GPIO number to wire DB6. (required)
db7=[2..31] declar GPIO number to wire DB7. (required)
rw=[2..31] declare GPIO number to wire R/W. (required even when unwired.)
rs=[2..31] declare GPIO number to wire RS. (required)
e=[2..31] declares GPIO number to wire E. (required)
info shows configuration
Function Code 1 and 2
clear=[0..1000000] clear LCD. Cursor position and display position are also reset. You can declar the wait time. (The unit is microseconds, and default is 1520.)
return Cursor position and display position are reset.
Function Code 3 Entry Mode
direction=[0,1] declare direction to move cursor or display. 0:Left, 1:Right (default)
shift=[0,1] declares what to move. 0:Cursor (default), 1:DisplayIf display is declared, cursor doesn’t look moving, but its position (internal position called DDRAM) keeps changing.
demo1 demonstrate the Entry Mode.
demo2 demonstrate string output from right to left.
Function Code 4 Display On/Off
display=[0,1] Turns on/off the display. 0:off, 1:on (default)
cursor=[0,1] set the shape of the cursor. 0:None, 1:_ (default)
blink=[0,1] set how to blink the cursor. 0:always on, 1:Square and blink (default)
demo3 demonstrates Display On/Off
Function Code 5 Cursor/display Shift
demo4 demonstrates Cursor/display Shift
demo5 demonstrates string scrolling
Function Code 6 Function Set
line=[0,1] set line number. 0:1 line, 1:2 lines (default)
font=[0,1] set dot size of font. 0:5×8 (default), 1:5×11
demo6 demonstrate both combinations.
Function Code 7 Set CGRAM
char1 set and displays smilly.
char2 set and displays bowling signs.
char3 set and displays battery signs.
Function Code 8 Set DDRAM
x=[0..] set horizontal position of cursor.
y=[0..] set vertical position of cursor.
demo7 demonstrate cursor movements.
Function Code 9 Read Busy Flag/Address Counter
demo8 demonstrate reading busy flag.
demo9 demonstrate reading address counter.
Function Code 10 Write Data
write=ABC display string “ABC”.
demo10 display strings that are typed.
Function Code 11 Read Data
read=[0..] read string at where the cursor is and displays the string. If number is defined, the same amount of characters are read.
chardef reads user char definitions and shows them.

Verified components

I used the following devices.

  • Raspberry Pi Model B
  • OS 2014-01-07-wheezy-raspbian
  • LCDs are shown below.
No Vendor Manufacture Model Lot No. Vdd Pin No. Backlight
1 RS Components Powertip PC1602-LRS-H 921932019 2 yes
2 Akizuki Denshi Unknown SC1602BS*B-XA-GB-K 1006-005-109 1 no
3 Akizuki Denshi Unknown SC2004CBWB-XA-GB-G 1102-003-034 2 yes
outline character 20×04
4 Marutsu Linkman TC1602E-06T 134600012052 1 yes

Command to verify the left cursor malfunction

Use the command below to see how DDRAM changes.

./tango lcdbas db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 noadjust direction=0 demo9

The console appears.

[0,0 (0000)]

This means [Cursor position x, Cursor position y (DDRAM Address)]

If your console is [0,0 (007F)], then your Pi couldn’t read the DDRAM Address. Make sureGPIO10 is wired to RS.

Type one key and press Enter. See what the address changes.

Correct Movement Defective Movement
[0,0 (0000)] [0,0 (0000)]
[39,1 (0067)] [39,1 (007F)]
[38,1 (0066)] [38,1 (007E)]
[37,1 (0065)] [37,1 (007D)]
[36,1 (0064)] [36,1 (007C)]
[35,1 (0063)] [35,1 (007B)]
[34,1 (0062)] [34,1 (007A)]
[33,1 (0061)] [33,1 (0079)]
[32,1 (0060)] [32,1 (0078)]
[17,1 (0051)] [17,1 (0069)]
[16,1 (0050)] [16,1 (0000)]
[15,1 (004F)] [15,1 (007F)]

These are what SC1602s look like after typing a to h.

Correct ResultSC1602-MarutsuDefective Result



No Vendor Model Result
1 RS Components PC1602-LRS-H defective
2 Akizuki Denshi SC1602BS*B-XA-GB-K defective
3 Akizuki Denshi SC2004CBWB-XA-GB-G defective
4 Marutsu TC1602E-06T fine

Marutst’s SC1602 outputs only an ‘a’. This is because other characters are put at the addresses shown below. The gray part is out of display width, but can be displayed if you scroll.

SC1602 AddressingOn the other SC1602s, the cursor jumps to DDRAM addresses that don’t exist. But characters can be displayed at 0x00 to 0x07.

The cursor positions x and y are correct because the program counts. Once the position is determined, we can get the correct DDRAM address by using the matrix above. To avoid this malfunction, we can simply overwrite the DDRAM address.

Command to check the wait time of Clear Display

This command executes Clear Display and then prints “ABCDEFG”. But the wait time is shortened intentionally from 1520 microseconds to 500 microseconds.

./tango lcdbas db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 clear=500 write=ABCDEFG

The result can be correct once a 10 times.

SC1602-Waittime-01SC1602 misses the first character once a 10 times.

SC1602-Waittime-02So, What happens another once a 10 times?

SC1602-Waittime-03The string doesn’t make sense. But the string itself is always the same. This means if I get “ $4DTd”, I get “ $4DTd” again.

Verifying Energy Suspention

In addition, I verified the suspension effect.

Connect a multimeter between your Raspberry Pi and SC1602 in series.

Energy-Consumption-CheckExecute commands. They just display a string.

./tango lcdbas db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 write=ABCDEFG
./tango lcdbas db4=4 db5=17 db6=27 db7=22 rw=10 rs=9 e=11 write=ABCDEFG nosave

If “nosave” is not used, GPIOs except E (DB, R/W, RS) are set to direction INPUT, voltage HIGH and pull UP. If “nosave” is used, GPIOs remain direction OUTPUT, voltage HIGH or LOW and pull UP or DOWN.


No Vendor Model Without suspention With suspention Reduced %
1 RS Components PC1602-LRS-H 0.92mA 0.39mA 58%
2 Akizuki Denshi SC1602BS*B-XA-GB-K 0.71mA 0.26mA 64%
3 Akizuki Denshi SC2004CBWB-XA-GB-G 31.46mA 31.07mA 1.1%
4 Marutsu TC1602E-06T 0.88mA 0.43mA 52%

All the LCDs could reduce 0.5mA of current. Thus the energy consumption is cut to half. SC2004CBWB-XA-GB-G has the same result; however, because its current is originally high, there is no relative effect at all.

If you are interested in this post, check all posts of “Raspberry Pi and Electronics DIY ”. For example, I posted these articles.

  • Drive RHT03 with Raspberry Pi
    RHT03 is a hygrometer of MaxDetect. Today, I report how to control an RHT03 with a Raspberry Pi. It was great effort because I am
  • Drilling a Raspberry Pi case
    I drilled my Raspberry Pi case to take GPIO pins out of case. I needed knowledge of DIY (Do it yourself) of both wood and metal.
  • Making Raspberry Pi program by cross-compiling C++ with Eclipse on CentOS
    On the post written in the end of June, “A total beginner started to learn electronics with Raspberry Pi”, I wrote a shell script to turn on an LED ramp. Shell scripting is easy to start, but I thought using C language might increase possibility.

This post is also available in: Japanese

Leave a Reply

Your comment will be sent to me via e-mail so that I don't miss it.