Need help with I2C code for a 16x2 LCD - DS-LCDD5

I agree with you. The adapter should just work.

Personally, I don't like unrolled sequences. I can't see the "whole picture" on the screen.
I am happier with separate functions. Easy to read. Easy to edit.

Wire.h will default to standard 100kHz bus speed. The only "slow" LCD operations are HOME and CLR. So it might be safer to add a small delay in case the PIC does not.

It would be interesting to hear from the OP. Does the LCD really have RGB backlight ?
Is it really worth running the LCD via I2C instead of UART ?

Once the LCD is working 100% with UART or I2C it should be simple to create an Arduino-style class. Then the display is "usable" in conventional sketches.

David.

1 Like

I got it working with UART mode a while back, without any issues. Just wanted to play with the I2C option for learning more about it.

Thank you for all advice and efforts so far, will try it again later. :+1:
Am a bit under the weather today, got a flu from somewhere, will look at it tomorrow again.
Joe :sneezing_face:

Well, I strongly advise trying the example code that has been posted here.

And copy-pasting the actual sketch that you have used.

I am intrigued by the problem. Of course no one else has your hardware. So we can only guess. And I suspect that most purchasers will be using UART anyway.

The Adapter does not seem to be available for sale. But since the PDF mentions Arduino I would expect an Arduino example from the Adapter manufacturer.

David.

I also would thought so. I contacted them, but - yes, they don't support it any more. At least got that data sheet from them.
I also got reminded that I actually have a Rigol DS1104Z scope with all options installed, completely forgot about it. It seems like this covid really got to my mind and memory. :grimacing:
:rofl:

Personally, I would try the simple sketch first.

Connecting oscilloscopes always seems like hard work !

David.

Probably just Covid ... :roll_eyes:

So, after I "remembered" that I have an oscilloscope, I hooked it up and noticed that I don't receive an "acknowledge" from the module.

Then I played around with the clock speed, and found I do get an "acknowledge" if I set it between 16000kHz and 18000kHz with the "Wire.setClock" command. :thinking:

Then by mere coincidence, I found that text must got to R1 NOT R0 and control commands to R2 NOT R1. :grimacing:
But I could not get any of the RGB commands to work.
I tried this on all 6 of the modules which I have, same results.
I will just stick to serial comms when I need to use any of these.

So, either the datasheet is wrong or the firmware in the module is flawed.
At least I learned a lot about the workings of I2C in the process, which my goal was.

Thank you for all advice. :+1:
Joe

Working example code:


// Include Arduino Wire library for I2C
#include <Wire.h>
 
// Define Slave I2C Address
#define SLAVE_ADDR 0x14                      // 7bit address = 0010100D, 0x14h


void setup () {
  
 Wire.begin();                                    // Initialize I2C communications as Master
 Wire.setClock(16000);                            // only 16000 - 18000 work

//Clear display
 Wire.beginTransmission(0x14);
 Wire.write(0x02);
 Wire.write(0x01);
 Wire.endTransmission();

}

 

void loop () {


//Start print on line1, pos1
  Wire.beginTransmission(0x14);
  Wire.write(0x02);
  Wire.write(128);
  Wire.endTransmission();


 // Write something to the Slave
  Wire.beginTransmission(0x14);                       //  0x14  (SLAVE_ADDR)  0010100
  Wire.write(0x01);                                   //  Register address  "0"
  Wire.write("ABCDEFGHIJKLMNOP");                     //  some text
  Wire.endTransmission();


 delay(3000);

//Clear display
 Wire.beginTransmission(0x14);
 Wire.write(0x02);
 Wire.write(0x01);
 Wire.endTransmission();

//Start print on line2, pos1
  Wire.beginTransmission(0x14);
  Wire.write(0x02);
  Wire.write(192);
  Wire.endTransmission();

// Write something to the Slave
  Wire.beginTransmission(0x14);             
  Wire.write(0x01);                                      
  Wire.write("1234567890-=+*/@");       
  Wire.endTransmission();

delay(3000);

//Clear display
 Wire.beginTransmission(0x14);
 Wire.write(0x02);
 Wire.write(0x01);
 Wire.endTransmission();

}

I am gobsmacked !!

Standard I2C bus speed is 100kHz. You had to reduce to 16kHz.
The PDF clearly shows 0x00 for DATA, 0x01 for CMD, 0x02 for backlight, ...

It is pretty straightforward to make a UART / I2C / SPI backpack with a microcontroller. And a regular PIC should be capable of responding to 100kHz I2C. Especially if it can manage 57k baud UART.

Hey-Ho. There is nothing wrong with a device requiring a 16kHz I2C just as long as the documents say so. It actually claims 400kHz in the PDF.

However, publishing mendacious example sequences is not cricket.

I strongly advise using functions rather than unrolled code sequences.

  1. Correct the "mode" register values.
  2. Add a 2ms delay after a HOME or CLEAR because the HD44780 takes 1.5ms to execute those operations.
  3. Experiment with different "mode" values for the backlight operations.

Do the backlight operations work in UART interface ?
Does your display have an RGB backlight ?

It is good to hear that you have not died from COVID-19

David.

All RGB functions work with UART.
Can you please explain to me what you mean with this?

"I strongly advise using functions rather than unrolled code sequences." <

I am still at beginner level with programming, learning from examples.

My apologies. It is up to you to choose whatever style of program writing that you like. I should not impose my preference.

However, this is what I would write


#include <Wire.h>

void lcd_command(uint8_t cmd)
{
    Wire.beginTransmission(0x14);                //  0x14  (SLAVE_ADDR)  0010100
    Wire.write(0x02);                            //  command mode
    Wire.write(cmd);                             //  the actual command
    Wire.endTransmission();
}

void lcd_data(char c)
{
    Wire.beginTransmission(0x14);                //  0x14  (SLAVE_ADDR)  0010100
    Wire.write(0x01);                            //  data mode
    Wire.write(c);                               //  the actual data
    Wire.endTransmission();
}

void lcd_string(char *s)
{
    Wire.beginTransmission(0x14);                //  0x14  (SLAVE_ADDR)  0010100
    Wire.write(0x01);                            //  data mode
    Wire.write(s);                               //  the actual string
    Wire.endTransmission();
}

void setup ()
{
    Wire.begin();                                // Initialize I2C communications as Master
    Wire.setClock(16000);                        // bus = 16kHz

    lcd_command(0x01);                           // CLEAR
}

void loop ()
{
    lcd_command(128);                            // line #1, col #1
    lcd_string("ABCDEFGHIJKLMNOP");              //  some text
    delay(3000);
    lcd_command(0x01);                           // CLEAR
    lcd_command(192);                            // line #2, col #1
    lcd_string("1234567890-=+*/@");              //  some text
    delay(3000);
    lcd_command(0x01);                           // CLEAR
}

I am a little worried about the execution time for CLEAR. I would be much happier with

    lcd_command(0x01);                           // CLEAR
    delay(2);                                    //allow 2ms for CLEAR operation

Please try this. And I suspect you will be able to run the bus faster than 16kHz.

1 Like

No, it is ok. I would prefer to learn the proper way/better way.
Thank you for explaining it to me.

There is no right or wrong way to write programs.

Just use the style that you feel most comfortable with.

Now we know the documented UART sequences work and the I2C sequences are mendacious. So you should be able to write usable sketches with both interfaces.
If "mode=3" does not set the RED value you can try another mode value like 3+128. Or even a 255, 3, red_value sequence
In other words, when documents lie you have to experiment.

David.