Closed heavydetail closed 5 years ago
Could you send a link to the device you bought?
Looking at the video you linked to, it looks like the screen resolution is 128x64, whereas the SSD1322 is geared for 256x64 as the default - this is the one I own:
Regarding the settings, it might be that you just need to alter the config and add something like:
--width=128
--height=64
for whatever the correct resolution is. If that doesn't solve it, then try jiggling the Display divide clockratio/freq
and 'mux ratio' - these are the key params IIRC.
As to the SPI clock speed, I would start with a low value to start with and make sure it is stable, then increase it until it becomes unstable. I do recall that blasting some of these with high MHz is futile, and doesnt really affect the frame rate dramatically.
Hi, link to the datasheet is in the first post, here is the manufacturers page to the display: https://www.newhavendisplay.com/nhd2712864wdy3-p-9542.html
Yes its a 128x64 resolution device. I have tried your suggestions to no avail. (setting width, height and spi-bus-speed=500000 being the lowest we can specify). I will try around with freq and mux substituting the stuff in their datasheets, lets see. At the moment I am not sure if i somehow killed the display and will need to retest it with an arduino or so.
Are you sure the init sequence is correct? Again, I am seeing major differences in the manufacturer suggested init and the one in your device.py routine.
The init sequence works for the 256x64 SSD1322 device I and a few others own, and it was derived according to the SSD1322 datasheet listed here: https://luma-oled.readthedocs.io/en/latest/intro.html.
When you tried the 128x64 settings, and said "I have tried your suggestions to no avail.", what did the screen display?
If you can upload pictures of the output of the luma.examples demo.py script (this shows the reference image), this would help immensely.
I tried setting the screen size back when it was partially working and it didnt change anything on the output. (Even if I dont supply w/h the example output tells me its running in 128x64 )
Now the display doesnt respond at all at the moment, thats why I need to verify whether its dead before trying other things :/ Yes I am trying to get to the point of it displaying any example again.
So something else is kind of off here, in the datasheet it says /CS is active LOW, when I measure its at HIGH.
I tried specifiying in config spi-cs-high=false but it has no effect?
Removing the CS lead drops me back to 0.6v for some reason... which was enough to activate the chip and I could see something again, but just for a short while!? Garbage, but still - I'll keep investigating ;)
@heavydetail any news?
Nope. Couldn't get it to work. It wasn't the CS pin either. That one works as expected or so I think...
Next step would be to get a logic analyzer and check if everything is correctly transmitted or try to change the init routine again like I mentioned in before posts, but I couldn't get it to work, maybe/probably doing something wrong, but I checked the wiring about a hundred times.
Its weird because sometimes if I start an example and cancel and run in quick succession it would start up the display and show garbled stuff until it freezes. I am guessing that I somehow randomly hit the right init routine?
But also, I have not yet checked with I2C, maybe that works instead of SPI, wasn't my spec tho.
When it works its a great looking display tho, also the metal frame makes it quite sturdy and good to build into projects, so I'd still like to get it to work ;) If you have suggestions I am willing to try and report back. Maybe you can try to change the init routine to my suggestions according to the datasheet? I tried but maybe did it wrong.
I'm attempting to use this same 128x64 NHD display with a PIC24 and can't get the display to come on either. You mentioned a few different initialization sequences- Which one did you use when you got the rotating cube to show up?
The original one included in luma, but it worked very seldomly too, I think that the rotating cube is hitting the init sequence sometimes or more often than other examples.
I still believe we should be using a different init sequence that someone would need to code up properly according to the datasheet since I didn't manage to or missed something. maybe you can try to replace with my/datasheet routine and check if it works for your controller.
I agree with your hypothesis that it's likely the initialization sequence. I tried a variant of the initialization sequence in luma.oled and was able to get some streaking across the screen:
uDelay(200);
setCommandLock(0x12); //unlock
setSleepMode(0x00); //turn display off
setDisplayClock(0xF2);
setMUXRatio(0x3F);
setDisplayOffset(0x00);
setDisplayStartLine(0x00);
setRemapFormat(0x14,0x11);
setGPIO(0x00);
functionSelection(0x01); //internal VDD reg
setVSL(0xA0,0xFD);
setDefaultGrayScale();
setPhaseLength(0xF0);
setMasterContrastCurrent(0x0F);
setContrastCurrent(0x9F);
setPreCharge(0x1F);
setVCOMH(0x00);
setDisplayMode(0x02);
setSleepMode(0x01); //turn display on
exitPartialDisplay();
uDelay(200);
Maybe you can give this a shot and see if your screen becomes responsive again? I'm still tinkering with the sequence myself
I have the NHD-2.7-12864WDW3 and was able to get the SSD1322 driver to work with the following modifications of the ssd1322 class:
self.reset_display()
self.command(0xFD, 0x12) # Unlock IC
self.command(0xAE) # Display off
self.command(0xB3, 0x91) # Display divide clockratio/freq
self.command(0xCA, 0x3F) # Set MUX ratio
self.command(0xA2, 0x00) # Display offset
self.command(0xAB, 0x01) # Display offset
self.command(0xA0, 0x16, 0x11) # Set remap & dual COM Line
self.command(0xC7, 0x0F) # Master contrast (reset)
self.command(0xC1, 0x9F) # Set contrast current
self.command(0xB1, 0xF2) # Set default greyscale table
self.command(0xBB, 0x1F) # Pre-charge voltage
self.command(0xB4, 0xA0, 0xFD) # Display enhancement A (External VSL)
self.command(0xBE, 0x04) # Set VcomH
self.command(0xA6) # Normal display (reset)
self.command(0xAF) # Exit partial display
I added a new method called reset_display to the device class in luma.core.device.py
def reset_display(self):
from luma.core.util import usleep
self._serial_interface.assert_reset() # pull low
usleep(400)
self._serial_interface.negate_reset() # Keep RESET pulled high
usleep(400)
I also added usleep
to luma.core.util.py
def usleep(x):
time.sleep(x/1000000.0)
Finally, I added two new methods to bitbang class in luma.core.interface.serial.py.
def assert_reset(self):
if self._RST is not None:
self._gpio.output(self._RST, self._gpio.LOW)
def negate_reset(self):
if self._RST is not None:
self._gpio.output(self._RST, self._gpio.HIGH)
I used the following command line config:
--display=ssd1322 --interface=spi --width=256 --height=64 --spi-bus-speed=16000000
When I used a width of 128, there were horizontal bars (64bit wide) on each side of the display. This was pretty odd, since newhaven lists the display as 128x64. Once I changed the width parameter to 256 the full display was used.
I think I'm still having issues with the fonts that came with luma.examples. I haven't tried any other fonts. I'm not sure if the default fonts are usable with 256x64 since the wiki does not confirm working with 256x64.
Here is an pic of the default font, C&C Red Alert [INET].ttf, used in sys_info.py
Here is an pic of the font tiny.ttf used in sys_info.py
great quality pics btw
The ttf fonts need to be slightly bigger font size, else the anti aliasing will make them look like your second pic. Have a look at the terminal example for some decent fonts to use, or try and source some 8px bitmap fonts instead
I will take onboard your init settings and create a ssd1322_nhd subclass or something. However, your comment about 128px width and having to set with --width=256 doesn't seem right.
Could you take a pic of the display whilst running the perf_loop.py demo - this has the reference image (text and colored geometric shapes) I use to help diagnose issues
Are there any recommendations where I can source 8px bitmap fonts?
rm-hull,
Per your recommendation, I ran perfloop.py with width configured to 128 and 256. Here are the results:
--width=128
--width=256
I tried a total of 7 fonts. 5 of the fonts were the same fonts and sizes used in terminal.py. I download two fronts from www.dafont.com called 8bit-wonder and pixelmix. Both fonts were listed as 8px. Links to fonts 8bit-wonder and pixelmix.
Here are the results of the fonts:
tiny.ttf size=6
ProggyTiny.ttf size=16
creep.bdf size=16
miscfs_.ttf size=12
FreePixel.ttf size=12
8bit_wonder.ttf size=8
pixelmix.ttf size=12
Ok, so none of those images look right - at a guess, it looks like there is a different memory mapping in use and it is one picking one nibble rather than both.
kennethajonesii - would you be able to post a gist or the full text here of your luma/core/util.py with your changes?
I'm having the same issues and tried your changes, but am getting errors due to usleep - I think I put it in the wrong place.
Thanks for your help.
You can replace usleep with:
time.sleep(x/1000000.0)
Here is the modified util.py
# -*- coding: utf-8 -*-
# Copyright (c) 2017-18 Richard Hull and contributors
# See LICENSE.rst for details.
import time
def usleep(x):
time.sleep(x/1000000.0)
class mutable_string(object):
def __init__(self, value):
assert value.__class__ is str
self.target = value
def __getattr__(self, attr):
return self.target.__getattribute__(attr)
def __getitem__(self, key):
return self.target[key]
def __setitem__(self, key, value):
assert value.__class__ is str
tmp = list(self.target)
tmp[key] = value
self.target = "".join(tmp)
def __delitem__(self, key):
tmp = list(self.target)
del tmp[key]
self.target = "".join(tmp)
def __len__(self):
return len(self.target)
def __iter__(self):
return iter(self.target)
def __str__(self):
return str(self.target)
def __repr__(self):
return repr(self.target)
def __eq__(self, other):
return str(self.target) == str(other)
def __hash__(self):
return hash(self.target)
class observable(object):
"""
Wraps any container object such that on inserting, updating or deleting,
an observer is notified with a payload of the target. All other special
name methods are passed through parameters unhindered.
"""
def __init__(self, target, observer):
self.target = target
self.observer = observer
self.observer(self.target)
def __getattr__(self, attr):
return self.target.__getattribute__(attr)
def __getitem__(self, key):
return self.target.__getitem__(key)
def __setitem__(self, key, value):
self.target.__setitem__(key, value)
self.observer(self.target)
def __delitem__(self, key):
self.target.__delitem__(key)
self.observer(self.target)
def __len__(self):
return self.target.__len__()
def __iter__(self):
return self.target.__iter__()
def __str__(self):
return self.target.__str__()
def __repr__(self):
return self.target.__repr__()
Thanks. That helps a bunch. I was missing: import time
Did you keep these clear/show functions after the init sequnce in device.py?
self.clear() self.show()
Here is the entire mod of the ssd1322:
self.reset()
self.command(0xFD, 0x12) # Unlock IC
self.command(0xAE) # Display off
self.command(0xB3, 0x91) # Display divide clockratio/freq
self.command(0xCA, 0x3F) # Set MUX ratio
self.command(0xA2, 0x00) # Display offset
self.command(0xAB, 0x01) # Display offset
self.command(0xA0, 0x16, 0x11) # Set remap & dual COM Line
self.command(0xC7, 0x0F) # Master contrast (reset)
self.command(0xC1, 0x9F) # Set contrast current
self.command(0xB1, 0xF2) # Set default greyscale table
self.command(0xBB, 0x1F) # Pre-charge voltage
self.command(0xB4, 0xA0, 0xFD) # Display enhancement A (External VSL)
self.command(0xBE, 0x04) # Set VcomH
self.command(0xA6) # Normal display (reset)
self.command(0xAF) # Exit partial display
self.contrast(0x7F) # Reset
self.clear()
self.show()
Thanks again. I'm still getting nothing but black screen.
If I run a python script with the default SSD1306 I get the screen to light up once in awhile, but not every time. Super strange. Might be a power problem as the RasPI I'm using is complaining about under-voltage
Prior to your changes I was seeing the similar compressed stuff on screen, but again, it would not work every time I tried the script. Very frustrating.
EDIT: I'm also looking at some C code for this display and noticed this:
0xAB, 0x01 # Select external VDD
And I am using the external power pin (labeled IDD on the datasheet). I tried this just now, but no change. Gotta solve my power issue first I guess.
What is the manufacture and brand of your display?
What are your command line arguments?
Can you post a pic of your wiring?
Can you post you ssd1322 class?
Same display as what you posted NHD-2.7-12864WDW3
python examples/3d_box.py -d=ssd1322 -i=spi --width=128 --height=64 --gpio-reset=15 --gpio-data-command=14 --spi-bus-speed=16000000
I'll try to post a picture of wiring later when I'm in front of the pi again.
EDIT - looking at your pictures - you have pin 20 tied to ground - is that needed? The data sheet lists that pin as "MPU Interface select signal"
The ssd1322 class matches what you had previously posted. I need to re-install luma on my pi3 to re-test this so I'll
FWIW - I think some of my problem is due to power. After having this trouble I swapped the jumper on the display to "option #1" and gave the BC_VDD a 5V (4A) supply. This didn't seem to make a difference with luma, so I tried this with an fbtft framebuffer driver I was able to get the display working for a short time, but then had some other issues.
okernon,
According to the data sheet, pins 19 and 20 configure the MPU interface. I have my display configured 4-wire serial interface. I'm assuming your using 3-wire which I believe won't work. 3-wire mode doesn't use DC signal; however, this signal is needed since the SSD 1322 driver sends both command and data packets. Page 5 of the data sheet explains the MPU interface selections.
Change the width argument to 256. I know the NHD-2.7-12864WDY3 is 128x64; however, the SSD1322 driver is designed for 256x64. Newhaven changed from SSD1325 (designed for 128x64) to SSD1322 for their NHD-2.7-12864xxxx products around June of 2017. Essentially they are using a 256x64 controller for a 128x64 display. Using a width of 128 will make your images look like this:
This is why the fonts looks crappy, only half of the pixels are being activated. I was able to get the fonts to look have way decent; however, I had to use font sizes of 16 or more. I have since abandoned the use of the NHD-2.7-12864; I didn't want to create/re-write a driver for this single display. I can confirm NHD-2.8-25664 and NHD-3.12-25664 display working beautifully with luma.oled driver.
I would start off by using a single 3.3V source and attempt to get the display working. You can power the display directly from a raspberry pi or beagle bone. Once you know the code is working, I would then try using a separate source for the BC_VDD. When using BC_VDD, it does require configuring some on-board jumpers. Reference Independent Supply Voltage for Boost Converter on page 5 of the data sheet.
FWIW - I am using 4-wire SPI.
I'm setting this up again from scratch and will post pictures soon. I did notice from your photo that you have all the ground pins connected, whereas I was only sending pins 1 and 10 to ground.
If pins 19 and 20 weren't tie to logic 0 (usually ground) and VDD, then those pins are floating. You won't have a guarantee of the interface mode. Re-wire your setup and the only pins you can leave not counted are the one labeled N.C. (3, 9, 15, and 18). All VSS pins must be connect to ground.
Shoot me an email if you need further assistance.
@kennethajonesii I'm all setup again and not having any luck at all. Blank screen. Perhaps it would be best to contact you directly as this is getting far afield of the original post. I set my email to public for a bit if you could email me from my profile. Thx
I too just picked up an NHD-2.7-12864WDW3 and got it running on my RPi 3 B+ with similar issues. There appears to be several discrepancies in the Luma init routine when comparing to routines from other graphics libraries like U8glib/U8G2. According to U8G2's SSD1322 routine variant for the NHD-2.7 (linked here) only every second x-pixel is used, and every 4th column is addressable. So yes that is why @kennethajonesii perfloop.py doesn't look right when scaled to 256. Its trying to light pixels that are not physically connected to the COF.
I have been trying the past few days to achieve higher framerates when rendering greyscale video using PyAV to avail. Seems to cap out at ~15fps no matter the size/format of video, even animated gifs too. 30fps videos run fine in 1-bit monochrome and on the emulator however. Unsure if its a display or an SPI bottleneck.
I will try using the U8G2 routine to see if that works, but I think the fix has to be done in Luma.core .
(P.S. Im a longtime Arduino/AVR guy just now crossing over to the darkside. Still learning the ropes to Linux/Debian and what not. Kinda wished I crossed over sooner! )
Hello Guys my display was corrupted problem please tell me this code error
self.command(0xFD, 0x12) # Unlock IC
self.command(0xAE) # Display off (all pixels off)
self.command(0xB3, 0x91) # Display divide clockratio/freq
self.command(0xCA, 0x3F) # Set MUX ratio
self.command(0xA2, 0x00) # Display offset
self.command(0xAB, 0x01)
self.command(0xA1, 0x00) # Display start Line
self.command(0xA0, 0x16, 0x11) # Set remap & dual COM Line
self.command(0xB5, 0x00) # Set GPIO (disabled)
self.command(0xAB, 0x01) # Function select (internal Vdd)
self.command(0xB4, 0xA0, 0xFD) # Display enhancement A (External VSL)
self.command(0xC7, 0x0F) # Master contrast (reset)
self.command(0xB1, 0xF2) # Set default greyscale table
self.command(0xB1, 0xF2) # Phase length
self.command(0xB4, 0xA0, 0xFD) # Display enhancement B (reset)
self.command(0xBB, 0x1F) # Pre-charge voltage
self.command(0xB6, 0x08) # 2nd precharge period
self.command(0xBE, 0x04) # Set VcomH
self.command(0xA6) # Normal display (reset)
#self.command(0xA1)
self.command(0xA9) # Exit partial display
I'm working with some friends on a project and they've also chosen this ssd1322 display from NHD. I've got a fix in place whereby I've created a new class of display called ssd1322_nhd
. It's a little hacky but it works. I've got this repo forked and I can make a pull request or just post my code here. If you're interested in either, please let me know.
a pull request, so we can take a look, would be nice.
A new version of luma.oled (v3.2.0) has been released with a specific driver for the newhaven device (ssd1322_nhd
) courtesy of @doug-burrell
I’ve been having some issues with the same 2.7 New Haven display. Initially the modified _nhd class seemed to work. But grey ramps were messed up and anitalised text looked seriously wonky. I see that the class was writing out byte values rather than nibble encoded 4bit / 16 grey levels. After some experimentation it looks very much like there’s something interesting going on here.
I /think/ every other nibble controls the alternate scan of the pixel. Very strange. Anyway if I write out data for wxh (rather than wxh/2) and duplicate every pixel into both the upper and lower nibble everything looks great - the ramps now display correctly and text renders as expected - where’s previously values like 240 (prior to send to device) would snap to an incredibly low display value which looks effectively black).
If I write a zero nibble then a 4 but it displays dim but full screen. Same if I write a high nibble then zero. So clearly it needs 8bits per pixel. But it’s doing something with both the top and bottom nibble for that same pixel- seemingly it’s a dual scan on the pixel which I don’t get with the mechanics of how oleds work for precharge cycles etc. but nonetheless it appears to work a /lot/ better.
So sorry to reopen this but I think the nhd init routine / display routines are still wrong for things that aren’t pure black / white.
this is the working ramps. I can upload more images to show the diffs as needed.
I will try and tidy up the copious init routine hacks and submit a PR.
George
RPi3 B+ Linux 4.9.79-v7+ #1086 armv7l GNU/Linux
I got this new display recently for a project and have been trying to get started with it and luma.oled. Datasheet here: https://www.mouser.com/ds/2/291/NHD-2.7-12864WDY3-1116258.pdf It has an SSD1322 controller that I am trying to access via SPI on the raspi.
config is as such:
Here is a video a first trial where it kind of worked, but now it doesn't react at all to any of the examples. It is clearly not initialized and driven in the right way. The rotating cube was the only example doing anything surprisingly for some moments, unclear why. https://www.youtube.com/watch?v=jjIOZmPjGdw
Here is the recommended init from the datasheet:
In luma/oled/device.py in the SSD1322 init function there are many differences to this, so I am wondering if this is the culprit of my problems?
Here is an edit I attempted but its still not working at all, the display is not activated and I am unsure about some additional steps in the initialization that I got rid of.
The question is, do we need to differntiate this display from the other SSD1322 driven ones, is my display "special" or broken or is this init routine generally wrong for the SSD1322 controller or did I do something wrong with SPI on the RPi... I am not very clear on how fast we can drive this display (10Mhz? it sometimes worked for a few seconds at a time as seen in the video with 16Mhz)
I am glad about any pointers you can give me to get this display running and if I/we can find a solution I'll send a pull request if necessary.