SSD1306 with SPI on LoPy4? (/topic/1541/solved-ssd1306-with-spi on WiPy)
flexypepo last edited by
RE: SSD1306 with SPI?](/topic/1541/solved-ssd1306-with-spi)
Using the ssd1306 driver (https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py), I'll try to get the Adafruit 128x32 OLED SSD1306-SPI working with LoPy4. No luck thusfar.
The OLED display is wired to my LoP4 (via Expansion board 3.0) as follows:
SSD1306 -> LoPy4 -> Exp.bord
Vin -> 3.3V
GND -> GND
DATA -> MOSI,P11 -> G22
CLK -> CLK,P10 -> G17
DC -> P9 -> G16
RST -> P8 -> G15
CS -> P12 -> G28
This is the code I'm using to test, and for which I got error
'TypeError: function expected at most 5 arguments, got 6'
from machine import Pin, SPI
from ssd1306 import SSD1306_SPI as ssd
spi = SPI(0, mode=SPI.MASTER, baudrate=1000000, polarity=0, phase=0)
dc = Pin('P9', mode=Pin.OUT) # G16
rst = Pin('P8', mode=Pin.OUT) # G15
cs = Pin('P12', mode=Pin.OUT) # G28
oled = ssd(128, 32, spi, dc, rst, cs)
Is it wired correctly?
Is the ssd130 module from micropython.org correct to use for LoPy4? There are 6, and not 5, arguments needed for the SSD1306_SPI constructor.
When I leave out any of the pin-arguments (dc or rst), I'll got following error:
'TypeError: object with buffer protocol required'
Does anyone has a tip or pointer how to get the display working with the LoPy4?
Pycom MicroPython 1.18.0.r1 [v1.8.6-849-9569a73] on 2018-07-20
throwaway last edited by throwaway
The argument related issues are related to an issue with using a native class as a base class. See here:
This doesn't work in Pycom's MicroPython release 1.18 (current stable) but the fix from the above linked issue has been incorporated into the development release 1.20 (currently at rc4).
Additionally, the Pycom MicroPython flavor has a different I2C API than the official MicroPython, lacking the I2C methods
write(). There you need to apply the changes outlined in this old thread as well:
Specifically, you'll need to replace the
def write_data(self, buf): self.i2c.writeto(self.addr, bytearray([0x40]) + buf)
(I see that you've already discussed the issue with Pycom's MicroPython flavor using
framebuf.MVLSBwhere as the constant is named
framebuf.MONO_VLSBin the official MicroPython).
The SSD1306 driver in Pycom's MicroPython flavor has never worked and is still using non-existant APIs and constants even in the release-candidate tree: https://github.com/pycom/pycom-micropython-sigfox/blob/release-candidate/drivers/display/ssd1306.py
If you get noisy display you might have an SH1106 display. I'm using the below piece of code successfully with random eBay 0.96" and 1.3" I2C OLED displays. It's been a few years since I looked into this but IIRC the SH1106 module's internal memory layout is for 132 pixel strides but the screen only supports 128. So the noise in the form of random black pixels come from the fact that those extra two pixels on the left and on the right side are not accounted for (the display is centered somehow).
from ssd1306 import SSD1306 class SH1106_I2C(SSD1306): def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False): self.i2c = i2c self.addr = addr self.temp = bytearray(2) super().__init__(width, height, external_vcc) # Parent does show() but is using the SSD1306 implementation.. self.show() def write_cmd(self, cmd): self.temp = 0x80 # Co=1, D/C#=0 self.temp = cmd self.i2c.writeto(self.addr, self.temp) def write_data(self, buf): self.i2c.writeto(self.addr, bytearray([0x40]) + buf) def poweron(self): pass def show(self): for page in range(8): self.write_cmd(0xb0 | page) self.write_cmd(0x02) # Start addr low column self.write_cmd(0x10) # Start addr high column mv = memoryview(self.buffer) self.write_data(mv[128*page: 128 + 128*page]) from sh1106 import SH1106_I2C i2c = I2C(0, I2C.MASTER, baudrate=400000) d = SH1106_I2C(128, 64, i2c) d.text('ping', 1, 2) d.show()
@flexypepo Yes, that's rigth. The API for Pin changed a while ago from pin.high() to pin.value(1) or just pin(1). The latter is, what the genuine driver at https://github.com/micropython/micropython/tree/master/drivers/display uses.
flexypepo last edited by
@robert-hh Thanks for your information. I've tried the change to 'framebuf.MVLSB', but it did not helped. Neither connecting the Vin of OLED-display to +5V instead of +3V on Expansion board.
However, using a two-year old 'ssd1306' module of Tony DiCola (https://github.com/adafruit/micropython-adafruit-ssd1306), the OLED came to life! Only change in ssd1306 module, was to use 'aPin'.value(1) instead of 'aPin'.high(). Idemdito for 'aPin'.low()..
I've not yet investigated what the differences are in the drivers, especially related to the 'strange' error message about the number of arguments. For the moment, I continue with this (slightly modified) ssd1306 driver, and will see what will happen.
Thanks for the pointer about the P8-pin. I'll change it when I'm start to use the SD-card. I'm new to LoPy4 development, and found the P- and G-names very confusing. I have some experiences with micropython on a couple of ESP32 boards. Its a challenge (or pity?) to handle the various flavours of Micopython (Adafruit, Loboris, Pycom, vanilla micropython). Sigh.
Best regards, Peter
@flexypepo I would not expect it to work right away, but the differences should be small. One I stumbled over is in line 35 of ssd1306.py, which reads:
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
The last argument should be framebuf.MVLSB with Pycom's flavor of micropython.
The other thing I noticed is the use of Pins. P8 is used for the SD card data. So if you use the SD card, you must not use P8 for other purposes.
And yes, you need all 6 arguments, since the signals mentioned by them are needed.
Edit: I do not know why this error you mention is flagged. I would expect something else.