rm-hull / luma.oled

Python module to drive a SSD1306 / SSD1309 / SSD1322 / SSD1325 / SSD1327 / SSD1331 / SSD1351 / SH1106 OLED
https://luma-oled.readthedocs.io
MIT License
806 stars 161 forks source link

Control a SSD1351 RGB oled screen, with a FT232H Adafruit controller. SUCCESS #185

Closed elpimous closed 6 years ago

elpimous commented 6 years ago

Board : nvidia jetson tx2 (ARMv8) System : ubuntu 16.04 64bits Python 2.7 Linux kernel : 4.4.38

hello all, I'll have some questions, 'cause I'd like to control a SSD1351 oled RGB screen(s) For that, I have a FT232H board, who creates SPI and GPIO capacities, from usb.

I installed luma package :

cd ~/luma/
sudo python setup.py install

sudo python
from luma.oled.device import ssd1351
ImportError: No module named luma.oled.device

?? Do you have an idea ? Thanks, Vincent PS : Merry christmas to you all !!!

rm-hull commented 6 years ago

Follow the install instructions here https://luma-oled.readthedocs.io/en/latest/install.html to install with pip, rather than using setup.py

Don't forget to ensure the pre-reqs are met first!

Ft232h looks interesting ... Gonna have to get me one of those!

elpimous commented 6 years ago

Thanks rm-hull for your quick answer It works, good !! Yes, I can confirm : this small board is very nice.

Another question : the ssd1351 test contains : device = ssd1351(serial)

I need to control the oled screen with the FT232H spi and gpio :

from luma.oled.device import ssd1351
from luma.core.render import canvas

from baseline_data import get_json_data, primitives
from helpers import serial, setup_function, assert_invalid_dimensions  # noqa: F401

#------------ for FT232H module ------------------------------------------------------

# Import GPIO and FT232H modules.
import Adafruit_GPIO as GPIO
import Adafruit_GPIO.FT232H as FT232H

# Temporarily disable FTDI serial drivers to use the FT232H device.
FT232H.use_FT232H()

# Create an FT232H device instance.
ft232h = FT232H.FT232H()

# Create an FT232H SPI object with the specified chip select pin.
serial= FT232H.SPI(ft232h, cs=8)
ft232h_gpio = ft232h

# Create the SSD1351 oled display object.
SSD1351Obj = (spi=serial, gpio=ft232h_gpio, gpio_DC=9, gpio_RST=10)

#-------------------------------------------------------------------------------------

Error:

SSD1351Obj = (spi=serial, gpio=ft232h_gpio, gpio_DC=9, gpio_RST=10) File "", line 1 SSD1351Obj = (spi=serial, gpio=ft232h_gpio, gpio_DC=9, gpio_RST=10) ^ SyntaxError: invalid syntax

 """
    SSD1351 OLED screen content can be displayed.
    """
    device = ssd1351(serial)
    serial.reset_mock()
    device.show()
    serial.command.assert_called_once_with(175)

I plan to control 2 oleds screens as eyes for my robot, Alfred (a working eyes would be a very good present for chrismas, LOL Any help ?

rm-hull commented 6 years ago

Are you just missing the SSD1351 off the front of that last line? Eg

SSD1351Obj = ssd1351(spi=serial, gpio=ft232h_gpio, gpio_DC=9, gpio_RST=10)
elpimous commented 6 years ago

Hum, yes, but new problem. It asks for i2c ?! I didn't configure it 'cause I don't need it ! (I think I approach success, LOL)

from luma.oled.device import ssd1351

#------------ for FT232H module ------------------------------------------------------

# Import GPIO and FT232H modules.
import Adafruit_GPIO as GPIO
import Adafruit_GPIO.FT232H as FT232H

# Temporarily disable FTDI serial drivers to use the FT232H device.
FT232H.use_FT232H()

# Create an FT232H device instance.
ft232h = FT232H.FT232H()

# Pins
CS = 8 #C0
RESET = 9 #C1
DC = 10 #C2

# Create an FT232H SPI object with the specified chip select pin.
serial = FT232H.SPI(ft232h, cs=CS)
ft232h_gpio = ft232h
# Create the SSD1351 oled display object.
SSD1351Obj = ssd1351(spi=serial, gpio=ft232h_gpio, gpio_DC=DC, gpio_RST=RESET)

SSD1351Obj = ssd1351(i2c= None, spi=serial, gpio=ft232h_gpio, gpio_DC=DC, gpio_RST=RESET) Traceback (most recent call last): File "", line 1, in File "/usr/local/lib/python2.7/dist-packages/luma/oled/device.py", line 340, in init self.command(0xFD, 0x12) # Unlock IC MCU interface File "/usr/local/lib/python2.7/dist-packages/luma/oled/device.py", line 414, in command self._serial_interface.command(cmd) File "/usr/local/lib/python2.7/dist-packages/luma/core/interface/serial.py", line 89, in command 'I2C device not found on address: 0x{0:02X}'.format(self._addr)) luma.core.error.DeviceNotFoundError: I2C device not found on address: 0x3C

elpimous commented 6 years ago

next try :

>>> serial = spi(ft232h, gpio=ft232h_gpio, bus_speed_hz=8000000, transfer_size=4096, gpio_DC=DC, gpio_RST=RESET)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/luma/core/interface/serial.py", line 257, in __init__
    self._spi.open(port, device)
AttributeError: 'FT232H' object has no attribute 'open'

An idea ?

rm-hull commented 6 years ago

I think you need to create the serial interface and device as follows:

serial = spi(spi=FT232H.SPI(ft232h, cs=CS), gpio=ft232h_gpio, gpio_DC=..., gpio_RST=...)
device = ssd1351(serial)
elpimous commented 6 years ago

Hi. I finally had success !! Thanks a lot for help. Here is the mods for luma.oled use on ssd1351, with the FT232H controller :

Modify : luma/core/interface/serial.py : the SPI class :

    def __init__(self, spi=None, gpio=None, gpio_DC=10, gpio_RST=9):

        bitbang.__init__(self, gpio, 4096, DC=gpio_DC, RST=gpio_RST)

        try:
            #self._spi.open(port, device)
            self._spi = spi
        except (IOError, OSError) as e:
            if e.errno == errno.ENOENT:
                raise luma.core.error.DeviceNotFoundError('SPI device not found')
            else:  # pragma: no cover
                raise

save and close.

Now, on top on your python demo file, add this :

#------------ for FT232H module ------------------------------------------------------
from luma.core.interface.serial import spi
from luma.oled.device import ssd1351

# Import GPIO and FT232H modules.
import Adafruit_GPIO as GPIO
import Adafruit_GPIO.FT232H as FT232H

# Temporarily disable FTDI serial drivers to use the FT232H device.
FT232H.use_FT232H()

# Create an FT232H device instance.
ft232h = FT232H.FT232H()

# Pins initialization
CS = 8 #C0
RESET = 9 #C1
DC = 10 #C2

# Create an FT232H SPI object with the specified chip select pin.
serial = FT232H.SPI(ft232h, cs=CS)

# Create an FT232H GPIO object 
ft232h_gpio = ft232h

# Create the SSD1351 oled display object.
serial = spi(spi=FT232H.SPI(ft232h, cs=CS), gpio=ft232h_gpio, gpio_DC=DC, gpio_RST=RESET)
oled = ssd1351(serial)
#--------------------------------------------------------------------------------------

So, rename your device :

if __name__ == "__main__":
    try:
        #device = get_device()
        device = oled
        main()
    except KeyboardInterrupt:
        pass

Now, just power your oled screen with 5v offered by the Adafruit FT232H small board (limited to 500Mah) My robot, Alfred, is happy : it has 2 beautiful color eyes...

rm-hull commented 6 years ago

Glad you got it working! I have an FT232H on order now, so we shall see if we can officially support it in the library soon.

HashDefineElectronics commented 5 years ago

Hi All,

Rather than making chagnes to the core files, you might want to use python's class inheritance to create an SPI wrapper which implements the missing attributes. This way you can still update Luma when you need too and reuse the library on other project that doesn't use the FTDI library.

Note: My wrapper name in this case is called FTDI_WRAPPER_SPI and this example code is for driving a SSD1322 oled display.

from luma.core.interface.serial import spi
from luma.core.render import canvas
from luma.oled.device import ssd1322
import time

# Import GPIO and FT232H modules.
import Adafruit_GPIO as GPIO
import Adafruit_GPIO.FT232H as FT232H

# Temporarily disable the built-in FTDI serial driver on Mac & Linux platforms.
FT232H.use_FT232H()

# Create an FT232H object that grabs the first available FT232H device found.
ft232h = FT232H.FT232H()

# Pins initialization
CS = 5 #D5 Purple
RESET = 6 #D6 White
DC = 7 #D7 Blue

# This class wrapper implements the missing attributes required by the luma core interface
class FTDI_WRAPPER_SPI( FT232H.SPI ):
        def writebytes(self, data):
                self.write(data)

        def open(self, port, device):
                print 'Opened'

# Create an FT232H SPI object with the specified chip select pin.
serial = FTDI_WRAPPER_SPI(ft232h, cs=CS, max_speed_hz=8000000)

#serial.open = 
# Create an FT232H GPIO object 
ft232h_gpio = ft232h

SPI = spi(spi=serial, gpio=ft232h_gpio, gpio_DC=DC, gpio_RST=RESET)
device = ssd1322(SPI, rotate=0)

device.persist = False

with canvas(device) as draw:
        draw.rectangle(device.bounding_box, outline="black", fill="white")
        draw.text((10, 40), "Hello World", fill="black")

time.sleep(5)
TCB13 commented 2 years ago

For future reference, now there's a WCH CH347 based board for 5$ and the FT232H still cost around 15$.

https://www.cnx-software.com/2022/09/01/5-ch347-board-is-a-usb-2-0-bridge-to-i2c-spi-uart-jtag-and-gpio/