Author Topic: I2C Display Module (NHD-C160100-DiZ) for DIY Scientific Calculator Help  (Read 3937 times)

0 Members and 1 Guest are viewing this topic.

Offline adeptTopic starter

  • Regular Contributor
  • *
  • Posts: 65
Good evening everybody reading,

This is a project I've been developing for about 6 months. I am stuck because I can't get the display module (datasheet here) to work. I attached my schematic for the calculator and the schematic from the display module's datasheet.

I believe that the issue is with the hardware. I have measured the voltages and I am not liking what I'm seeing. I will record all the voltages here.

Pin No.
Symbol
External Connection
Functional Description
Voltage
1CSB
MPU
Active Low chip select
0.003 V
2RST
MPU
Active Low Reset signal
1.216V
3NC
-
No Connect
1.172V
4SCL
MPU
Serial clock input (requires pull-up)
2.012V @31.61kHz
5SDA
MPU
Serial data input (requires pull-up)
2.136V @31.61kHz
6VDD
Power Supply
Power supply for LCD and logic (+3.0V)
3.337V
7VSS
Power Supply
Ground
0.008V
8VOUT
Power Supply
Connect to 1uF cap to VSS or VDD
0.898V
9V4
Power Supply
1.0-2.2uF cap to Vss
0.530V
10V3
Power Supply
1.0-2.2uF cap to Vss
0.645V
11V2
Power Supply
1.0-2.2uF cap to Vss
0.634V
12V1
Power Supply
1.0-2.2uF cap to Vss
0.025V
13NC
-
No Connect
0.451V
14NC
-
No Connect
0.503V
If this information helps, I am using a level shifting module I ordered offline from here. I made sure to wire it in the correct high voltage-low voltage configuration.

And finally, if need be the code (almost straight from the datasheet) is here:
Code: [Select]
/*****************************************************/
const char Slave = 0x7E;     //slave address+Write bit
const char Comsend = 0x00;
const char Datasend = 0x40;
#define SDA  A4  //One of the Arduino I2C ports
#define SCL  A5

/******************************************************/
void setup()
{
  unsigned char text[12] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\n'};
  init_LCD();
  Show(text);
}// end setup

/******************************************************/
void loop()
{
  //empty
}// end Arduino loop

/*****************************************************/
void I2C_out(unsigned char j) //I2C Output
{
  int n;
  unsigned char d;
  d=j;
  for(n=0;n<8;n++){//send 8 bits
    if((d&0x80)==0x80) //get only the MSB
    digitalWrite(SDA, HIGH); //if MSB = 1, then SDA=1
    else digitalWrite(SDA, LOW); //if MSB = 0, then SDA=0
    delayMicroseconds(10);
    d=(d<<1); //shift data byte left
    digitalWrite(SCL, LOW);
    delayMicroseconds(10);
    digitalWrite(SCL, HIGH); //clock in data
    delayMicroseconds(10);
    digitalWrite(SCL, LOW);
    delayMicroseconds(10);
  }
  digitalWrite(SCL, HIGH);
  delayMicroseconds(10);
  while(digitalRead(SDA)==1){ //wait here until ACK
    digitalWrite(SCL, LOW);
    delayMicroseconds(10);
    digitalWrite(SCL, HIGH);
    delayMicroseconds(10);
  }
  digitalWrite(SCL, LOW);
}// end function I2C_out

/*****************************************************/
void I2C_Start(void)
{
  digitalWrite(SCL, HIGH);
  digitalWrite(SDA, HIGH);
  delayMicroseconds(10);
  digitalWrite(SDA, LOW);
  digitalWrite(SCL, LOW);
  delayMicroseconds(10);
}// end function I2C_Start

/*****************************************************/
void I2C_Stop(void)
{
  digitalWrite(SDA, LOW);
  digitalWrite(SCL, LOW);
  delayMicroseconds(10);
  digitalWrite(SCL, HIGH);
  digitalWrite(SDA, HIGH);
  delayMicroseconds(10);
}// end function I2C_Stop

/*****************************************************/
void Show(unsigned char *text)
{
  int n,i;
  char page=0xB0;//first page
  for(i=0;i<13;i++){//100 pixels = 12.5 pages
    I2C_Start();
    I2C_out(Slave);
    I2C_out(Comsend);
    I2C_out(page);
    I2C_out(0x10); //column address Y9:Y6
    I2C_out(0x01);
    //column address Y5:Y2
    I2C_Stop();
    I2C_Start();
    I2C_out(Slave);
    I2C_out(Datasend);
    for(n=0;n<160;n++){
      I2C_out(*text);
      //send data 4 times for grayscaling
      I2C_out(*text);
      I2C_out(*text);
      I2C_out(*text);
      ++text;
      //point to next byte of data
      delay(10);
    }
    I2C_Stop();
    page++;
    //move to next page
  }
}// end function Show

/****************************************************
*           Initialization                          *
*****************************************************/
void init_LCD()
{
  I2C_Start();
  I2C_out(Slave);
  I2C_out(Comsend);
  I2C_out(0x48);    //partial display duty ratio
  I2C_out(0x64);    // 1/100 duty
  I2C_out(0xA0);    //ADC select
  I2C_out(0xC8);    //SHL select
  I2C_out(0x44);    //initial Com0 register
  I2C_out(0x00);    //scan from Com0
  I2C_out(0xAB);    //OSC on
  I2C_out(0x26);    //
  I2C_out(0x81);    //set electronic volume
  I2C_out(0x15);    //vopcode=0x1C
  I2C_out(0x56);    //set 1/11 bias
  I2C_out(0x64);    //3x
  delay(2);
  I2C_out(0x2C);    //
  I2C_out(0x66);    //5x
  delay(2);
  I2C_out(0x2E);    //
  delay(2);
  I2C_out(0x2F);    //power control
  I2C_out(0xF3);    //bias save circuit
  I2C_out(0x00);    //
  I2C_out(0x96);    //frc and pwm
  I2C_out(0x38);    //external mode
  I2C_out(0x75);    //
  I2C_out(0x97);    //3frc, 45 pwm
  I2C_out(0x80);    //start 16 level grayscale settings
  I2C_out(0x00);    //
  I2C_out(0x81);    //
  I2C_out(0x00);    //
  I2C_out(0x82);    //
  I2C_out(0x00);    //
  I2C_out(0x83);    //
  I2C_out(0x00);    //
  I2C_out(0x84);    //
  I2C_out(0x06);    //
  I2C_out(0x85);    //
  I2C_out(0x06);    //
  I2C_out(0x86);    //
  I2C_out(0x06);    //
  I2C_out(0x87);    //
  I2C_out(0x06);    //
  I2C_out(0x88);    //
  I2C_out(0x0B);    //
  I2C_out(0x89);    //
  I2C_out(0x0B);    //
  I2C_out(0x8A);    //
  I2C_out(0x0B);    //
  I2C_out(0x8B);    //
  I2C_out(0x0B);    //
  I2C_out(0x8C);    //
  I2C_out(0x10);    //
  I2C_out(0x8D);    //
  I2C_out(0x10);    //
  I2C_out(0x8E);    //
  I2C_out(0x10);    //
  I2C_out(0x8F);    //
  I2C_out(0x10);    //
  I2C_out(0x90);    //
  I2C_out(0x15);    //
  I2C_out(0x91);    //
  I2C_out(0x15);    //
  I2C_out(0x92);    //
  I2C_out(0x15);    //
  I2C_out(0x93);    //
  I2C_out(0x15);    //
  I2C_out(0x94);    //
  I2C_out(0x1A);    //
  I2C_out(0x95);    //
  I2C_out(0x1A);    //
  I2C_out(0x96);    //
  I2C_out(0x1A);    //
  I2C_out(0x97);    //
  I2C_out(0x1A);    //
  I2C_out(0x98);    //
  I2C_out(0x1E);    //
  I2C_out(0x99);    //
  I2C_out(0x1E);    //
  I2C_out(0x9A);    //
  I2C_out(0x1E);    //
  I2C_out(0x9B);    //
  I2C_out(0x1E);    //
  I2C_out(0x9C);    //
  I2C_out(0x23);    //
  I2C_out(0x9D);    //
  I2C_out(0x23);    //
  I2C_out(0x9E);    //
  I2C_out(0x23);    //
  I2C_out(0x9F);    //
  I2C_out(0x23);    //
  I2C_out(0xA0);    //
  I2C_out(0x27);    //
  I2C_out(0xA1);    //
  I2C_out(0x27);    //
  I2C_out(0xA2);    //
  I2C_out(0x27);    //
  I2C_out(0xA3);    //
  I2C_out(0x27);    //
  I2C_out(0xA4);    //
  I2C_out(0x2B);    //
  I2C_out(0xA5);    //
  I2C_out(0x2B);    //
  I2C_out(0xA6);    //
  I2C_out(0x2B);    //
  I2C_out(0xA7);    //
  I2C_out(0x2B);    //
  I2C_out(0xA8);    //
  I2C_out(0x2F);    //
  I2C_out(0xA9);    //
  I2C_out(0x2F);    //
  I2C_out(0xAA);    //
  I2C_out(0x2F);    //
  I2C_out(0xAB);    //
  I2C_out(0x2F);    //
  I2C_out(0xAC);    //
  I2C_out(0x32);    //
  I2C_out(0xAD);    //
  I2C_out(0x32);    //
  I2C_out(0xAE);    //
  I2C_out(0x32);    //
  I2C_out(0xAF);    //
  I2C_out(0x32);    //
  I2C_out(0xB0);    //
  I2C_out(0x35);    //
  I2C_out(0xB1);    //
  I2C_out(0x35);    //
  I2C_out(0xB2);    //
  I2C_out(0x35);    //
  I2C_out(0xB3);    //
  I2C_out(0x35);    //
  I2C_out(0xB4);    //
  I2C_out(0x38);    //
  I2C_out(0xB5);    //
  I2C_out(0x38);    //
  I2C_out(0xB6);    //
  I2C_out(0x38);    //
  I2C_out(0xB7);    //
  I2C_out(0x38);    //
  I2C_out(0xB8);    //
  I2C_out(0x3A);    //
  I2C_out(0xB9);    //
  I2C_out(0x3A);    //
  I2C_out(0xBA);    //
  I2C_out(0x3A);    //
  I2C_out(0xBB);    //
  I2C_out(0x3A);    //
  I2C_out(0xBC);    //
  I2C_out(0x3C);    //
  I2C_out(0xBD);    //
  I2C_out(0x3C);    //
  I2C_out(0xBE);    //
  I2C_out(0x3C);    //
  I2C_out(0xBF);    //
  I2C_out(0x3C);    //end grayscale settings
  I2C_out(0x38);    //
  I2C_out(0x74);    //
  I2C_out(0xAF);    //display on
  I2C_Stop();
}// end function init_LCD

/*****************************************************/

Thanks for taking the time to help,
Stephen Jenkins
System Operations Engineer
Website
Email
« Last Edit: June 23, 2015, 03:37:41 am by adept »
 

Offline ale500

  • Frequent Contributor
  • **
  • Posts: 415
I have a couple of questions, check-list for you :

- Why are you using 5 V to power the uC ? Many of those can be powered with 3.3 V. It may not run at 20 MHz, but when you need 20 MHz maybe another type of controller may be a better fit. I made my first functional calculator with an ATMega32, and getting the power down (~1 mA) means running at 1 MHz and a bit more sleep tricks, faster was not really needed, it depends on your algorithms.
If your choice of 8 bit uC is size, it means not a huge battery too, wasting power on 5 V and 20 MHz... may not be the best fit.It also has an internal oscillator, you may not need an external crystal.
- Does the I2C code work ? (Do you see your stream of data ?)
- Do you see the correct start of transmission and acknowledge response from the display ?, I2C is open-drain, that means that when the LCD (and Memory chip) want to answer you have to set the pin to input, because the attiny doesn't (seem) to have open-drain output pins. (Not many level-converters support bidirectional operation...).
 

Offline adeptTopic starter

  • Regular Contributor
  • *
  • Posts: 65

Thank you very much for your reply ale500. Here is a few answers you can take a look at.

Quote
Why are you using 5 V to power the uC ?
I have to run at 20 MHz. I wrote a custom 64 bit floating point math library for the uC but it runs pretty slow. I am using the ATTiny because I have a lot laying around and I am looking for a challenge.

Quote
Does the I2C code work ? (Do you see your stream of data ?)
I see a waveform I can measure with my frequency counter in my multimeter but I don't have any other way to see if I have a proper data stream. That would be incredibly helpful if I did though.

Quote
(Not many level-converters support bidirectional operation...).
Supposedly the one I bought does. Is there a way to check for sure with a DMM? (I'm thinking maybe just tie the pins to the power supply and make a truth table.)

And also I'm using an Arduino at the moment, not the ATTiny. I found it cumbersome to code on the ATTiny and run everything on it. Figured I'd keep the number of failure points lower that way too.
 

Offline ale500

  • Frequent Contributor
  • **
  • Posts: 415
You may want to test your I2C code, having a second uC around can simplify the test. A multimeter is not the best test tool. Just write a receiver for i2c, and output the data via UART to the PC, so you can see what you are sending. Maybe you can invest a bit of money in a small logic analyzer, a 8 channel unit would do. That way you save loads of time :).

What do you mean with "pretty slow" ? does MUL take more than 1 second ? or does COS take more than 1 second ? Did you write it in assembler ?

 

Offline eneuro

  • Super Contributor
  • ***
  • Posts: 1528
  • Country: 00
- Does the I2C code work ? (Do you see your stream of data ?)
I'd rather use first simple I2C RTC clock, which might be quite nice additional feature even in scientific calculator (eg. calculate sun position on the sky-do not ask why ;) ).
Try to talk to something simply first than LCD.
This what I've did sometime ag for MPu6050  I2C 3 axis accelerometer/gyro module I've made optoisolaed I2C interface betweem PC Linux serial port, so MPu side can be powered at any voltage including 3.3V or 5V , so now I can test I2C device directly from PC Linux with a few lines of C code, to ensure that there is no level shifting issues, etc ;)

BTW: Sometimes mistaken I2C address can ruin your day when working with I2C dongles, so ensure you have correct write/read I2C adresses implemented in your code, but I hope OP already did it and it is hardware issue not software  ;)
« Last Edit: June 23, 2015, 12:10:28 pm by eneuro »
12oV4dWZCAia7vXBzQzBF9wAt1U3JWZkpk
“Let the future tell the truth, and evaluate each one according to his work and accomplishments. The present is theirs; the future, for which I have really worked, is mine”  - Nikola Tesla
-||-|-
 

Offline adeptTopic starter

  • Regular Contributor
  • *
  • Posts: 65
Quote
I'd rather use first simple I2C RTC clock
Wouldn't that require extra hardware to work? If not you should elaborate more because I would be interested.

Quote
Try to talk to something simply first than LCD.
I got this from you too ale500. So in progress now is a little Arduino "logic analyzer" sketch. I'm going to use one of the many already available.

Quote
BTW: Sometimes mistaken I2C address can ruin your day when working with I2C dongles, so ensure you have correct write/read I2C adresses implemented in your code
Yep, definitely have it right.

Quote
What do you mean with "pretty slow" ? does MUL take more than 1 second ? or does COS take more than 1 second ? Did you write it in assembler ?
I'm not sure of real time in terms of seconds. It's much faster than an entire second. I mean that it's slow in that it's about 30 lines of code for a 64 bit multiply. And it's written in C because it made it easier thanks to 64 bit integers being supported. If you want to see the code it'll be until I get home tonight.

Now that I've answered those questions, does anybody know what voltages the built in LCD inverter outputs to those caps? I looked in the data sheet and can't find anything...
 

Offline eneuro

  • Super Contributor
  • ***
  • Posts: 1528
  • Country: 00
Quote
I'd rather use first simple I2C RTC clock
Wouldn't that require extra hardware to work? If not you should elaborate more because I would be interested.
I meant ensur efirst you have AVR ATTiny I2C software working with something else, eg. I2C RTC directly without any voltage shifting, so basicly use spare AVR, write a few lines of code to talk to RTC using your I2C AVR library (the same you use for I2C LCD), but take pull ups on breadboard or prototype PCB and connect I2C dongle without voltage level shifting, to ensure your I2C library on AVR is working, since you should be able to talko to other I2C device.
Than replace it with LCD module run AVR at lower speed and 3.3V, so still no voltage level shifting and ensure first there is no bugs in software and everything works if connected directly only with pullup resistors for I2C ;)
12oV4dWZCAia7vXBzQzBF9wAt1U3JWZkpk
“Let the future tell the truth, and evaluate each one according to his work and accomplishments. The present is theirs; the future, for which I have really worked, is mine”  - Nikola Tesla
-||-|-
 

Offline ale500

  • Frequent Contributor
  • **
  • Posts: 415
Exactly, make sure that the I2C code works first, for a test 3.3 V is not that bad. And make it work, make it fast, make it good is the strategy, I think, don't be concerned about the speed at this point, you may have to re-write a a portion in assembler anyways :)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf