Go Down

Topic: Library for Electronic Assembly DOG Displays (Read 9558 times) previous topic - next topic

dasgrundprinzip

Jul 27, 2008, 08:47 pm Last Edit: Jul 27, 2008, 08:50 pm by dasgrundprinzip Reason: 1
Hi all.
My first post here and just with a library.  :)

I've made a library for the DOG series of Electronic Assembly. Because it's not a normal HD44780 controller. The library is written like the LCD4Bit library. And it's one of my sources.

Datasheet of the Display http://www.lcd-module.de/eng/pdf/doma/dog-me.pdf
Datasheet of the Controller ST7036 http://www.lcd-module.de/eng/pdf/zubehoer/st7036.pdf

I'll try to upload some pictures and the wiring diagram.

The Sketch:
Code: [Select]
// examples of the DOGM_LCD library

#include <DOGM_LCD.h>

// create an object with the type of your Display
// EA DOGM081x-A (1x8 chars)  -> 81
// EA DOGM162x-A (2x16 chars) -> 162
// ES DOGM163x-A (3x16 chars) -> 163
DOGM_LCD lcd = DOGM_LCD(163);

int i;
int x;
char string[3];


void setup() {
 lcd.init();
}

void loop() {
 // ##########
 lcd.gotoxy(2,1);
 lcd.printStr("Hello World!");
 delay(2000);
 
 // ##########  
 lcd.clear(); // clear the Display
 lcd.contrast(0); // set contrast to 0 (nothing to see)
 lcd.gotoxy(3,1);
 lcd.printStr("Fade in...");
 for (i=0; i<64; i++) {
   lcd.contrast(i);
   delay(50);
 }
 delay(2000);
 
 // ##########
 lcd.home(); // position of teh cursor at home (0,0)
 lcd.printStr("01234567890123456");

 lcd.gotoxy(0, 1);
 lcd.printStr("ABCDEFGHIJKLMNOP");

 lcd.gotoxy(0, 2);
 lcd.print(0x08); // print out some special chars
 lcd.print(0x09);
 lcd.print(0x0A);
 lcd.print(0x0B);
 lcd.print(0x0C);
 lcd.print(0x0D);
 lcd.print(0x0E);
 lcd.print(0x0F);
 lcd.print(0xF8);
 lcd.print(0xF9);
 lcd.print(0xFA);
 lcd.print(0xFB);
 lcd.print(0xFC);
 lcd.print(0xFD);
 lcd.print(0xFE);
 lcd.print(0xFF);
 
 delay(2000);
 
 for (i=63; i>=0; i--) {
   lcd.contrast(i);
   delay(50);
 }
 lcd.clear();
 lcd.contrast(32);
 
 // ##########
 for (x=0; x<100; x++) {
   itoa(x, string, 10);
   lcd.gotoxy(14,2);
   lcd.printStr(string);
   delay(50);
 }
}



The Header:
Code: [Select]
#ifndef DOGM_LCD_h
 #define DOGM_LCD_h

 #include <inttypes.h>

 class DOGM_LCD {
 public:
   DOGM_LCD(int type);
   void cmd_nibble(int nibble);
   void cmd(int value);
   void init();
   void clear();
   void home();
   void gotoxy(int x, int y);
   void printStr(char value[]);
   void print(int value);
   void contrast(int value);
 private:
   void pulse_enable();
   void chkbusy();
   void push_nibble(int nibble);
   void push_byte(int value);
 };
#endif



dasgrundprinzip

#1
Jul 27, 2008, 08:47 pm Last Edit: Jul 27, 2008, 08:48 pm by dasgrundprinzip Reason: 1
And the .cpp

Code: [Select]
/*
DOGM_LCD - v0.1 - 27.07.2008 - dasgrundprinzip.de

This is an Arduino library for the DOG series Display from Electronic Assembly.
http://www.lcd-module.de/deu/dog/dog.htm
Communication is 4-pin parallel mode.

Sources:
- LCD4Bit v0.1 from neillzero (http://abstractplain.net Library)
- Datasheet of ST7036 controller (http://www.lcd-module.de/eng/pdf/zubehoer/st7036.pdf)

Tested with a DOGM163W-A (3x16 chars) on an Arduino Decimila and Arduino 0010 Alpha

Usage:
see the examples folder of this library distribution.

*/

// ########## includes ##########
#include "DOGM_LCD.h"
extern "C" {
 #include <stdio.h>            //not needed yet
 #include <string.h>            //needed for strlen()
 #include <inttypes.h>
 #include "WConstants.h"      //all things wiring / arduino
}

// ########## pin assignment ##########
int RS = 12;      // Register Select
int RW = 11;      // Read/Write
int En = 2;            // Enable

//DB should be an unseparated group of pins - because of lazy coding in push_nibble()
int DB[] = {7, 8, 9, 10};  // DB4 .. DB7


// ########## global variables ##########
int lcd_type = 81; // just a ini-value. The LCD-Type is changed in the DOGM_LCD sketch.

// If you want to save the RW-pin of the microcontroller, just switch it off and tie the RW-pin of the LCD to GROUND.
// The only time the RW-pin is used, is for checking the BusyFlag. When RW is deactivated we'll use a 5ms dealy instead checking the BusyFlag.
int USING_RW = false;





// The type variable is set in the sketch
DOGM_LCD::DOGM_LCD(int type) {
 lcd_type = type;
}

// a short (1us) impuls on the Enable-Pin to clock the Data into the LCD.
void DOGM_LCD::pulse_enable(){
 digitalWrite(En,LOW);
 delayMicroseconds(1);
 digitalWrite(En,HIGH);
 delayMicroseconds(1);
 digitalWrite(En,LOW);
}


// checking the Busy Flag (DB7=1 -> busy). Only when RW is activated. Otherwise a delay of 5ms.
void DOGM_LCD::chkbusy(){
 if (USING_RW) {
   int busy;

   // D4-D7 as input
   pinMode(DB[0],INPUT);
   pinMode(DB[1],INPUT);
   pinMode(DB[2],INPUT);
   pinMode(DB[3],INPUT);
 
   do {
     digitalWrite(RS, LOW);
     digitalWrite(RW, HIGH);
     digitalWrite(En,HIGH); // get high-nibble
     delayMicroseconds(1);
     busy = digitalRead(DB[3]); // get DB7(BusyFlag)
     digitalWrite(En,LOW);
     delayMicroseconds(1);

     pulse_enable(); // get low-nibble and ignore it
   }
   while (busy);

   // D4-D7 as output
   pinMode(DB[0],OUTPUT);
   pinMode(DB[1],OUTPUT);
   pinMode(DB[2],OUTPUT);
   pinMode(DB[3],OUTPUT);
 }
 else delay(5);
}

//push a nibble of data through the the LCD's DB4~7 pins, clocking with the Enable pin.
//We don't care what RS and RW are, here.
void DOGM_LCD::push_nibble(int value){
 int val_nibble = value & 0x0F;  //clean the value.  (unnecessary)

 for (int i=DB[0]; i <= DB[3]; i++) {
   digitalWrite(i,val_nibble & 01);
   val_nibble >>= 1;
 }
 pulse_enable();
}

//push a byte of data through the LCD's DB4~7 pins, in two steps, clocking each with the enable pin.
void DOGM_LCD::push_byte(int value){
 int val_lower = value & 0x0F;
 int val_upper = value >> 4;
 push_nibble(val_upper);
 push_nibble(val_lower);
}

// Register Select to LOW -> it's a command. Push the nibble
void DOGM_LCD::cmd_nibble(int nibble) {
 digitalWrite(RS, LOW);
 if (USING_RW) { digitalWrite(RW, LOW); }
 push_nibble(nibble);
}

// Register Select to LOW -> it's a command. Push the byte
void DOGM_LCD::cmd(int value) {
 chkbusy();

 digitalWrite(RS, LOW);
 if (USING_RW) { digitalWrite(RW, LOW); }
 push_byte(value);
}

// initializing the LCD
void DOGM_LCD::init () {
 pinMode(En,OUTPUT);
 pinMode(RS,OUTPUT);
 if (USING_RW) { pinMode(RW,OUTPUT); }
 pinMode(DB[0],OUTPUT);
 pinMode(DB[1],OUTPUT);
 pinMode(DB[2],OUTPUT);
 pinMode(DB[3],OUTPUT);

 delay(40);

 cmd_nibble(0x03);                   // FUNCTION SET            DL=1 - 8bit
 delay(2);
 cmd_nibble(0x03);                   // FUNCTION SET       DL=1 - 8bit
 delayMicroseconds(30);
 cmd_nibble(0x03);                   // FUNCTION SET       DL=1 - 8bit
 delayMicroseconds(30);
 chkbusy();
 cmd_nibble(0x02);                   // FUNCTION SET            DL=0 - 4bit
 delayMicroseconds(30);
 cmd(0x29);                              // FUNCTION SET            DL=0 / N=1 / DH=0 / IS2=0 / IS1=1
 delayMicroseconds(30);

 cmd(0x14);                              // bias
 delayMicroseconds(30);
 cmd(0x70);                              // contrast set
 delayMicroseconds(30);
 cmd(0x52);                              // power/ICON/contrast
 delayMicroseconds(30);
 cmd(0x6A);                              // follower control
 delayMicroseconds(30);

 cmd(0x0C);                              // DISPLAY ON
 delayMicroseconds(30);
 cmd(0x01);                              // CLEAR DISPLAY
 delay(2);
 cmd(0x06);                              // ENTRY MODE SET
 delayMicroseconds(30);
}

// Clear Screen
void DOGM_LCD::clear(){
 cmd(0x01);
 delay(2);
}

// Cursor to Home position 0,0
void DOGM_LCD::home(){
 cmd(0x02);
 delayMicroseconds(30);
}

// move cursor to position x,y (1st Row and 1st column is position 0,0)
// for a 163 display : x = 0..15   y = 0..2
void DOGM_LCD::gotoxy(int x, int y) {
 int addr = 0x80;
 if (y<1) addr = 0x80+x;
 else switch (lcd_type) {
   case 81:
       addr = 0x80+x;
       break;;
     case 162:
       if (y>0) addr = 0xC0+x;
       break;;
   case 163:
       if (y==1) addr = 0x90+x;
       else if (y>1) addr = 0xA0+x;
       break;;
 }
 cmd(addr);
}

dasgrundprinzip

... and the rest of the .cpp

Code: [Select]
// Register Select to HIGH -> it's a data. Push the byte. With this function it is possible to dispaly special chars.
void DOGM_LCD::print(int value) {
 digitalWrite(RS, HIGH);
 if (USING_RW) { digitalWrite(RW, LOW); }

 push_byte(value);
}

// print the given string to the LCD at the current cursor position.  overwrites, doesn't insert.
void DOGM_LCD::printStr(char msg[]) {
 uint8_t i;  //fancy int.  avoids compiler warning when comparing i with strlen()'s uint8_t
 for (i=0;i < strlen(msg);i++){
   print(msg[i]);
 }
}

// The only possibility to change the contrast of the display. There's no potentiometer to do that!
// The contrast is initialized to 32. The posible range is 0..63.
void DOGM_LCD::contrast (int value) {
 if ((value >= 0x00) && (value <= 0x3F)) {
   int val_lower = value & 0x0F;
   int val_upper = value >> 4;
   cmd(0x29); // FUNCTION SET
   cmd(0x70|val_lower);
   cmd(0x50|val_upper);
 }
}

wayoda

Hi,
great this was on my task list, but never got beyond some (successful) tests.
I will try your code with my 2 Line display.

But here are already some hints :
If you have the time to do so, you should create a new page on the playground http://www.arduino.cc/playground/, write some documentation for it and upload the code to there.

For the device-selection in the constructor I would suggest adding 3 #define statements :
Code: [Select]

#define EA_DOGM081 81
#define EA_DOGM162 162
#define EA_DOGM163 163

DOGM_LCD lcd=DOGM_LCD(EA_DOGM163);


The link to the product-page points to the german version here is the english translation http://www.lcd-module.de/eng/dog/dog.htm

Eberhard

mem

Here are some more hints, I hope they are helpful

I was curious to know if you compared the performance the library when using  RW to check when the panel is ready vs a hard coded delay. My guess is that it takes much longer to execute the code that checks if the panel is ready than a hard coded 5ms delay used if USING_RW set false. So the panel will always be ready on the first read and the delay will be much more than 5ms. But I haven't actually tried it and would be happy to be proved wrong.

I realize the code was derived from the playground lcd4bit code but  you can get some extra performance in your library by eliminating the 1us delays in pulse_enable(). The Enable pulse will be at least 4us long without any added delays because each digitalWrite takes around 2us.

pulse_enable is called a number of times for each character written so minimsing the delay should enhance the performance.

dasgrundprinzip

#5
Jul 28, 2008, 09:24 pm Last Edit: Jul 28, 2008, 09:27 pm by dasgrundprinzip Reason: 1
Hi wayoda,
would be interesting if I'm right with the adresses for the 2nd line. Where would you place the define statements? In the Arduino-Code or maybe in the header-file?

Hi mem,
I just tested your suggestions and commented out the 1us delay in the pulse_enable() ... working. And I commented out the 5ms delay.
void DOGM_LCD::chkbusy() {}
And it's working already. What I want to try is, to count the time during the do{...}while(busy) and display it on the LCD, or something like that.
But the next two days I'm away on a construction job (I hope you know what I mean - in german it's called "auf Montage sein"). So maybe on thursday or friday.

And the next step is to test the SPI-mode. And the documentation of course. And then I'll start my little project.  ;D

theqtisch

Hm, I searched the Arduino site and unfortunately I only found this after I finished my first attempt at writing a library for the DOG-M displays.

The good side of this: I started off with SPI. So, if you would like, you could take my working SPI code and merge it into your library?

Here's the link to my github project:http://github.com/halfbyte/lcddogmspi/tree/master

HULK

#7
Aug 26, 2008, 12:42 pm Last Edit: Aug 26, 2008, 12:43 pm by HULK Reason: 1
Can not find any prices on the DOG display, any hints?
Hope they are not to expensive, they are a great product.


HULK

Hi,

I received a price list from Electronic Assembly.
The price is good, hope it is ok to list prices at this forum.

Article no. / product type /      price: | 1- | 25- | 100- pieces/EURO
-----------------------------------------------------
EA DOGL128B-6       128x64      à 20,50 / 15,38 / 13,33 EUR,      STN, blue negative
EA DOGL128E-6       128x64      à 20,50 / 15,38 / 13,33 EUR, STN, Y-green positive
EA DOGL128L-6       128x64      à 20,50 / 15,38 / 13,33 EUR, STN, reflektive, pos.
EA DOGL128S-6       128x64      à 20,50 / 15,38 / 13,33 EUR, FSTN, black negative
EA DOGL128W-6 128x64            à 20,50 / 15,38 / 13,33 EUR, FSTN, black positive

LED backlights:

LED68x51-W            white                  à 15,50 / 11,63 / 10,08 EUR
LED68x51-G            yellow-green      à   6,50 /  4,88 /   4,23 EUR
LED68x51-B            blue                  à 15,50 / 11,63 / 10,08 EUR
LED68x51-R            red                        à   6,50 /  4,88 /   4,23 EUR LED68x51-A            amber                  à   6,50 /  4,88 /   4,23 EUR
LED68x51-E            green                  à 15,50 / 11,63 / 10,08 EUR
LED68x51-RGB      multicolour            à 24,50 / 18,38 / 15,93 EUR

accessory:

EA FL-20P       socket             à  1.50|  1.20|  1.05 EUR  
2 pieces for each display
Touch Panel 128-2 will come soon
EA WF100-04S, connector                  à 1,50 / 1,13 / 0,98 EUR

Go Up