LCD Problems

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
Botulism
Posts: 2
Joined: Sun Jul 14, 2019 3:43 am

LCD Problems

Post by Botulism » Sun Jul 14, 2019 3:54 am

My employer handed me a Pyboard and some accessories. I can make everything work except the LCD. I simply can't get any indicator I'm doing anything correctly. Can someone please provide some advice, sample code, preferred display if this one is a no-go, etc. to get me going?
The LCD specs:
http://www.newhavendisplay.com/specs/NH ... W-3V3M.pdf

User avatar
jimmo
Posts: 328
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: LCD Problems

Post by jimmo » Sun Jul 14, 2019 6:32 am

Hi,
Can you post a bit more detail about what you've tried so far. In particular what code you've tried and how it's wired up.
The LCD has an I2C device, so one really good indicator that things are on the right track is that it responds to a scan.

User avatar
Roberthh
Posts: 1468
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: LCD Problems

Post by Roberthh » Sun Jul 14, 2019 8:02 am

As @jimmo told, we need you to tell us, how you connected the LCD to PyBoard and which Python code you tried. Also,
looking at the data sheet, the display needs other components in addition to the Vdd, GND, SCL and SDA connections.
- a 1 µF capacitor between pins 7 and 8 (+ at 7)
- a capacitor of 0.47µf-2.2µF between pin 6 and 4.
And eventually, after powering on, the device needs a reset pulse at Pin 1, which has otherwise to be pulled up.
The pull-up resistors for SDA and SCL are populated on PyBoard. So you do not need to add them.

Botulism
Posts: 2
Joined: Sun Jul 14, 2019 3:43 am

Re: LCD Problems

Post by Botulism » Thu Jul 18, 2019 9:29 pm

Most of my experience is with the Parallax Propeller from many moons ago. That's why I got elected for this project. I used the SPI interface to talk to the Parallax displays, but never used any I2C until now.

Mechanically, I have the capacitors in the right spots and I did put the resisters in there until you noted the Pyboard already has them (I'm used to Propellers where I do everything).
Y11 - Pin 1
Y10 - Pin 3
Y9 - Pin 2

Main sources of information:
Page 12, http://www.newhavendisplay.com/specs/NH ... W-3V3M.pdf
page 41, http://www.newhavendisplay.com/app_notes/ST7036.pdf

- I don't understand the initialization sequence. The external reset is low, then high, then low? Or the other way around? For how long?
- When scanning for the address, would this work since I only have one address? address = i2c.scan()
- Page 12 of the spec sheet has an entire initialization sequence. Do I really need all that and do I understand the Pyboard equivalent?

I2C_Start(); == i2c = I2C('Y', freq=380000)
I2C_out(Slave);//Slave=0x78 == i2c.writeto(0x78) or i2c.writeto(slave) if slave = 0x78
I2C_out(Comsend);//Comsend =0x00 What's this command for?
I2C_out(0x38);
delay(10);
I2C_out(0x39);
delay(10);
I2C_out(0x14);
" "
I2C_Stop(); Needed? What's the equivalent?


This is the most I've come up with so far:
from pyb import Pin, ADC, UART # load resources
from machine import I2C
i2c = I2C('Y', freq=380000) # create I2C object on the X side
reset_pin = Pin('Y11', Pin.OUT) # configure Y11 as the external reset pin for the LCD
reset_pin.low() # set Y11 to Low
pyb.delay(1000) # pause for 1 second to allow everything to power on
reset_pin.high() # external reset
pyb.delay(10)
reset_pin.low()
pyb.delay(50) # wait >40uS after power up and external reset
i2c.writeto(0x78, 'hello') # write 'hello' to LCD at address 0x78

User avatar
jimmo
Posts: 328
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: LCD Problems

Post by jimmo » Fri Jul 19, 2019 2:16 am

Botulism wrote:
Thu Jul 18, 2019 9:29 pm
I don't understand the initialization sequence. The external reset is low, then high, then low? Or the other way around? For how long?
This is a fairly typical "active low" reset line. You can use it from software to force the device into a known state. The RST line is "active low" which means it will reset when you set it low, and therefore should be high the rest of the time. According to the datasheet, it must be low for 100uS to reset. For now I would just connect it to VCC (it probably has an internal pull-up to VCC anyway).

Botulism wrote:
Thu Jul 18, 2019 9:29 pm
- When scanning for the address, would this work since I only have one address? address = i2c.scan()
Scan returns a list of addresses that responded, so you want to grab the first element of this list. But this won't work in general, because there could be other devices on the bus. It's more useful for debugging, checking that the device exists.

An I2C will always have the same address, so once you know what it is, you can keep using that. Do you actually get anything back in scan?
Botulism wrote:
Thu Jul 18, 2019 9:29 pm
- Page 12 of the spec sheet has an entire initialization sequence. Do I really need all that and do I understand the Pyboard equivalent?

I2C_Start(); == i2c = I2C('Y', freq=380000)
I2C_out(Slave);//Slave=0x78 == i2c.writeto(0x78) or i2c.writeto(slave) if slave = 0x78
I2C_out(Comsend);//Comsend =0x00 What's this command for?
I2C_out(0x38);
delay(10);
I2C_out(0x39);
delay(10);
I2C_out(0x14);
" "
I2C_Stop(); Needed? What's the equivalent?
This is low level I2C. The code below that in the datasheet implements a bit-banging I2C driver. (!!)

It'd probably be helpful to read a bit more about how I2C works, but the basic idea is that you do transactions on the shared bus. The Start/Stop is the beginning/end of this transaction. The first byte is the address of who the master is talking to etc.

I've never had to manually set the I2C frequency before, you can probably leave it at the default.

I'm a bit confused by the delays, but I imagine they're trying to join multiple commands into the same transaction. There's a big long explanation of the 0x00 commsend byte on page 16 of the second PDF you linked to. Essentially it's interpreted as "this is a single byte command, and it's a command not a memory write". (The Co is explained there, and and Rs on page 25).

0x38 appears to mean "Function Set". See p25.

On MicroPython, you would typically use the high-level API, where the above code would look like

Code: Select all

i2c.writeto(addr_from_scan, b'\x00\x38')
i2c.writeto(addr_from_scan, b'\x00\x39')
i2c.writeto(addr_from_scan, b'\x00\x14\x78\x5e...')
Have a look at https://github.com/micropython/micropyt ... ssd1306.py which is a fairly typical driver for an I2C (or SPI) display.

Post Reply