EA DOGXL160-W on Arduino Uno Rev 3 need Tutorial/Help

Hi

my first project in the Arduino world is to connect an EA DOGXL160-W to the Arduino Uno Rev 3

This model has no backlight.

So I can connect it directly to my Arduino without any other parts?

It can work with 5V without resistors?

What its the simplest connection?

Thanks for your advice

So I can connect it directly to my Arduino without any other parts?

No. According to the controller datasheet it is not allowed to use 5V levels at the inputs.

It can work with 5V without resistors?

You can use a 74HC4050 for level adaption.

What its the simplest connection?

SPI with 74HC4050

You can take some ideas from our schematic here:

However note that software development for this display is continued here:
http://code.google.com/p/u8glib/

Oliver

Edit: Use 4-Wire 8 Bit SPI Mode

Oh, thanks

This seems to be a little tricky (for an new user)

I looked at the 74HC4050 datashet, but still don't understand how to connect it.

Will an LM 1117 T3,3 not be easier?

I looked at the 74HC4050 datashet, but still don't understand how to connect it.

Will an LM 1117 T3,3 not be easier?

The digital output at the output pins of the Arduino are 0 volt (for logical LOW) and something next to 5 volt (for logical HIGH). However the DOGXL160 expects 0 volt (for LOW) and 3.3 volt for HIGH. You have to reduce the high volatage level from 5 volt to 3.3 volt. You could do this with some resistors, but you can also do this with the HC4050. The HC4050 offers six simple drivers. For the 4-wire SPI mode you will only need four of these six drivers. Each of these drivers will do a voltage level adaption for the four digital lines from the Arduino to the DOGXL160 display: Connect the Arduino digital output to the input of the HC4050 and connect the corresponding output of the HC4050 to the DOGXL160. Connect the power supply of the HC4050 to the 3.3 volt output of the Arduino. You do NOT need a voltage regulator like the LM 1117, because a 3.3 volt power source is provided by the Arduino.

Oliver

Thanks, for your detailed description.

Now I understand, its not only the main power supply, but also the data inputs.
To use resistors I have to figure out how much mA are drawn on each data input
So it can done with one right resistor on each input?

The problem Is I have no Level shifter.
Its always so expensive to order single parts.

Trying both ways also wold help me to learn.

I see, it would be hard to learn at the beginning.

Maybe I should follow some video tutorials on breadboards first.

But, I should not give up :slight_smile:

Adding the DOGXL160 display to the Arduino is already an advanced project, but i think it is doable.

Oliver

Oh, i missed the question in your previous e-mail:

So it can done with one right resistor on each input?

Unfortunately, you need at least two resitors per digital output pin, because you need to create a voltage divider.
Full theorie is here, TIP #12:

You may need some more caps and one resitor for the DOGXL160 display (for the internal charge pump, see the EA datasheet for the DOGXL160). Perhaps you find some more parts, which are missing so you can order also the HC4050 chip.

Oliver

One more point: The 3.3 power supply from the Arduino is fine for the DOGXL160 and the HC4050 together.
However, if you decide to use the HC4050, you must connect the input pins of the two unused buffers of the HC4050 to ground. Otherwise the HC4050 consumes too much power, exceeding the current which can be delivered by the 3.3 power supply.
Rule: Always connect unused digital pins to some well defined logic level (such as ground).

Oliver

I order now some HC4050 and other parts maybe I don't need them, but i will have a little stock for future. :slight_smile:

Also a multimeter and a regular 5v 16x1 display.

Are there any better (easier) daylight readable displays around?

Hi,

I connected the EA DOGXL160-W but i can't seem to be able to write data. Commands work just fine, but data isn't being displayed.
My setup for data is something like:

displayCmd_SET_PAGE_ADDRESS(page);
displayCmd_SET_COLUMN_ADDRESS(column);
lcdWrite(DATA, myData); // myData is a byte

For testing purposes, I write all my data that way without using the auto-incrementing addresses(but they are set).
The only thing i see if the display should show myData are some weired random pixels that seem to be some state the buffers are in(always the same pixels).

Can anybody help?

We probably need to see the full source. Which lib do you use?

Oliver

I don't use any lib, wanted to write my own. I use the SPI library @1MHz

Here's the code (no optimization yet, wanted to get it to work first :wink: )

void displayCmd_SET_COLUMN_ADDRESS(byte column)
{
byte lsb = column & B00001111;
byte msb = (column & B11110000) >> 4;
lcdWrite(COMMAND, (msb | B00010000));
lcdWrite(COMMAND, (lsb | B00000000));

}

void displayCmd_SET_PAGE_ADDRESS(byte page)
{
page = page & B00011111;
byte command = page | B01100000;
lcdWrite(COMMAND, command);
}

void lcdWrite(byte mode, byte data)
{
digitalWrite(csPin, LOW); // Selects the chip
digitalWrite(cdPin, mode); // Selects wether data or command is being sent
SPI.transfer(data); // 1byte of data/command
digitalWrite(csPin,HIGH); // Deselects the chip
}

Grüße

If this is the full source, then i would say, that the following things are missing:

  • setup()
  • loop()
  • DOGXL160 setup code
  • Definition of DATA
  • Definition of myData

You could place everything into a

code block

See the # symbol...

Oliver

Ok, here's the full source. I just wrote it so there is really nothing optimized :stuck_out_tongue:
(And I'm new to Arduino)

#include <snesController.h>
#include <SPI.h>

#define COMMAND 0
#define DATA 1
//New Controller
//  Latch: Pin 3
//  Clock: Pin 2
//  Data: Pin 5
snesController controller(3, 2, 5);

// Controller
static unsigned long ioReadWriteDelay; // Stores the delay time for ioReads/Writes
int *data;           // States of the controller buttons
boolean buttons[12]; 
int dataOld[2];        // previous states of the controller buttons

//  Display
const int csPin = 7; // Chip Select pin
const int rstPin = 9; // Reset pin
const int mosiPin = 11; // Mosi Pin
const int cdPin = 12; // Clock/Command Mode pin
const int clkPin = 13; // Clock pin
const int pixels[2] = {160, 104}; // X-Dimension, Y-Dimension


void setup() 
{
  // Display Setup:
  // Chip Select pin setup
  pinMode (csPin, OUTPUT);    // Setting the pin as an output
  digitalWrite(csPin, HIGH);  // Normally high

  // Reset pin setup
  pinMode (rstPin, OUTPUT);   // Setting the pin as an output
  digitalWrite(rstPin, HIGH); // Normally high

  // Command/Data pin setup
  pinMode (cdPin, OUTPUT);    // Setting the pin as an output
  digitalWrite(cdPin, HIGH);  // Just to define any state, not necessary
  
  // Clock pin setup
  pinMode (clkPin, OUTPUT);    // Setting the pin as an output
  digitalWrite(clkPin, HIGH);  // Just to define any state, not necessary
 
   // Mosi pin setup
  pinMode (mosiPin, OUTPUT);    // Setting the pin as an output
  digitalWrite(mosiPin, HIGH);  // Just to define any state, not necessary
  
  // OS Setup:
  
  ioReadWriteDelay = micros();
  Serial.begin(9600);
  
  // SPI setup ( http://arduino.cc/en/Reference/SPI )
  SPI.begin();                         // initializing SPI
  SPI.setBitOrder(MSBFIRST);           // MSB is sent first
  SPI.setClockDivider(SPI_CLOCK_DIV16); // 4MHz Clock (16MHz/divider)
  SPI.setDataMode(SPI_MODE3);          // Clock normally hight, data on positive edge.
  
  delay(2500); // The display needs around 5ms to boot, using 20ms just to be safe
  
  display_init(pixels[0], pixels[1]); // Initializes the display
}

void loop()
{
  
  if((long)(micros() - ioReadWriteDelay) >= 0)
  {
    ioReadWriteDelay += 16742;  // do it again later [µs].
    // Checks if more than ioReadWriteDelay [ms] has passed since last excecution of the code inside, also works if the timer overflows.
    data = controller.readButtons(); // Read connected controllers
    
    
    if (data[0] != dataOld[0])
    {
      /*Serial.write(highByte(data[0])); // Upper 8 bits
      Serial.write(lowByte(data[0]));  // Lower 8 bits
      Serial.write(highByte(data[1])); // Upper 8 bits
      Serial.write(lowByte(data[1]));  // Lower 8 bits
      Serial.println();*/                       // To indicate a completed transmission 
      dataOld[0] = data[0];
      
      if((data[0] & 1) == 0)
      {
       // lcdWrite(COMMAND, B10100101); // Set all pixels ON
      }
      else
      {
       // lcdWrite(COMMAND, B10100100); // reset pixels to stored value
      }
    }
  }
}

void display_init(byte width, byte height)
{
  
  displayCmd_SET_COM_END(height);       // Defines the dimensions of the display
  displayCmd_SET_LCD_MAPPING_CONTROL(); // Orientation and order of pixels
  displayCmd_SET_SCROLL_LINE(0);        // Disable scrolling
  displayCmd_SET_PANEL_LOADING();       // Sets display capacitance
  displayCmd_SET_LCD_BIAS_RATIO();      // Sets bias ratio
  displayCmd_SET_VBIAS_POTENTIOMETER(); // Sets contrast
  displayCmd_SET_RAM_ADDRESS_CONTROL(); // Sets Auto-Increment
  displayCmd_SET_INVERSE_DISPLAY(false);// Display non-inverse data
  displayCmd_SET_LCD_GRAY_SHADE();      // Set gray shade
  //displayCmd_SET_DISPLAY_ENABLE(true);  // Enable display
  //displayCmd_SET_DISPLAY_ENABLE(false); // Disable display
  
  for(int k = 1; k <= (height / 4); k++)
  {
    for(int i = 0; i < width; i++)
    {
      
      //Serial.print(k);
      //Serial.print(" ");
      //Serial.println(i);
      displayCmd_SET_PAGE_ADDRESS(k);
      displayCmd_SET_COLUMN_ADDRESS(i);
      lcdWrite(DATA, B11111111); // Write Data to reset
    }
  }
  
  displayCmd_SET_DISPLAY_ENABLE(true);  // Enable display
  //lcdWrite(COMMAND, B10100101); // Set all pixels ON*/
  //delay(300);
  //lcdWrite(COMMAND, B10100100);
  //delay(300);
}

void displayCmd_SET_COM_END(byte height)
{
  /*
  This command programs the ending COM electrode.
  CEN defines the number of used COM electrodes, and it should correspond to the number of pixel-rows in the LCD.
  */
  byte address = height - 1;
  lcdWrite(COMMAND, B11110001); // SET COM END Line 1
  lcdWrite(COMMAND, address);   // Address of last row
}

void displayCmd_SET_LCD_MAPPING_CONTROL()
{
  /*
  This command is used to program LC[2:0] for COM (row) mirror (MY), SEG (column) mirror (MX).
  */
  lcdWrite(COMMAND, B11000110); // SEG (column), COM (row), mirror
  //lcdWrite(COMMAND, B11000000); // This would be used to turn the display upside-down
}

void displayCmd_SET_SCROLL_LINE(byte scroll)
{
  /*
  Set the scroll line number.
  */
  byte lsb = B01000000 | (B00001111 & scroll);        // Combining command and 4 LSB's
  byte msb = B01010000 | ((B01110000 & scroll) >> 4); // Combining command and 3 MSB's
  lcdWrite(COMMAND, lsb);                             // 4 LSB
  lcdWrite(COMMAND, msb);                             // 3 MSB
}

void displayCmd_SET_PANEL_LOADING()
{
  /*
  Set PC[1:0] according to the capacitance loading of LCD panel.
  */
  lcdWrite(COMMAND, B00101011); // Sets Capacitance to 28-38nF
}

void displayCmd_SET_LCD_BIAS_RATIO()
{
  /*
  Bias ratio definition
  */
  lcdWrite(COMMAND, B11101011); // Sets Bias to 1/12
}

void displayCmd_SET_VBIAS_POTENTIOMETER()
{
  /*
  Program VBIAS Potentiometer (PM[7:0]).
  */
  lcdWrite(COMMAND, B10000001); // Command
  lcdWrite(COMMAND, B01011111); // Contrast value
}

void displayCmd_SET_RAM_ADDRESS_CONTROL()
{
  /*
  Program registers AC[2:0] for RAM address control.
  */
  lcdWrite(COMMAND, B10001001); // Set auto-increment
}

void displayCmd_SET_DISPLAY_ENABLE(boolean enable)
{
  /*
  This command is for programming register DC[2].
  When DC[2] is set to 0, the IC will put itself into Sleep mode.
  When any of the DC[2] bits is set to 1, UC1610 will first exit from Sleep Mode, restore the power and then turn on COM drivers and SEG drivers. There is no other explicit user action or timing sequence required to enter or exit the Sleep mode.
  */
  byte command = B10101110;
  if(enable)
  {
    command += 1;
  }
  lcdWrite(COMMAND, command); // Enable/Disable display
}

void displayCmd_SET_COLUMN_ADDRESS(byte column)
{
  byte lsb = column & B00001111;
  byte msb = (column & B11110000) >> 4;
  lcdWrite(COMMAND, (msb | B00010000));
  lcdWrite(COMMAND, (lsb | B00000000));
  
}

void displayCmd_SET_PAGE_ADDRESS(byte page)
{
  page = page & B00011111;
  byte command = page | B01100000;
  lcdWrite(COMMAND, command);
}

void displayCmd_SET_INVERSE_DISPLAY(boolean enable)
{
  /*
  Display the inverse of stored data, this has no effect on the data being stored
  */
  byte command = B10100110;
  if(enable)
  {
    command += 1;
  }
  lcdWrite(COMMAND, command); // Inverse/Regular display
}

void displayCmd_SET_LCD_GRAY_SHADE()
{
  /*
  Program gray scale register (LC[6:5]). This register controls the voltage RMS separation between the two gray shade levels (data “01” and data “10”)
  */
  lcdWrite(COMMAND, B11010011); // 40% gray shade levels
}







void lcdWrite(byte mode, byte data)
{
  //Serial.println("CS Low");
  digitalWrite(csPin, LOW);  // Selects the chip
  digitalWrite(cdPin, mode); // Selects wether data or command is being sent
  //delayMicroseconds(5);
  
  SPI.transfer(data);        // 1byte of data/command
  //delay(2000);
  //Serial.println("CS High");
  digitalWrite(csPin,HIGH);  // Deselects the chip
  //digitalWrite(cdPin, ~mode);
  //delayMicroseconds(5);
}

void resetLcd()
{
  // This function is used to reset the display
  digitalWrite(rstPin, LOW);  // Enabling the reset
  delay(5);                   // 5ms delay just to make sure
  digitalWrite(rstPin, HIGH); // Disabling the reset
  delay(20);                  // The display needs some time to reset, this prevents other code being executed too early
}

Hi

Looks much better. I have not verified the display setup, but what i miss, is a call to the reset procedure.
Maybe i missed that.

Did you check if the signals are generated?

Is your HW setup ok? Did you follow the HW setup guide from EA? Did you select the correct mode?

Oliver

The reset procedure is not being used, just for testing.

I just checked the data with serial output, but i see nothing wrong there.

Since the commands are accepted, i think the hardware setup is ok. Things like turning all pixels on work.
(I followed the hw setup from EA)

Another point is: You need to use multi byte commands to select row and column. But your low level byte output modifies the CS line, which will reset the communication unit of the controller. It might happen that multibyte commands are not recogniced because of this.

I suggest to handle CS outside the low level byte procedure and keep the chip enabled for more than one byte.

Oliver

Yeah, i thought about doing that later but since every command(i could check via SPI or looking at the display) worked i didn't implement it yet.

Doesn't the display accept multibyte commands if the CS pin goes high in between them? I'll fix that tomorrow and report back.

Doesn't the display accept multibyte commands if the CS pin goes high in between them?

Good question. Maybe, maybe not.

BTW: Google Code Archive - Long-term storage for Google Code Project Hosting. supports DOGXL160 displays...

Oliver

Yeah, but since I'm just starting with the Arduino I'd rather do it myself to learn a bit more.
I'll test the multibyte thing tomorrow and report back.

Danke schonmal!