Вопрос такой возник.
Пытался поизучать протокол работы oled дисплея ssd1306 128x64, по шине i2c. В MX линукс подключил переходник который,
появился как i2c-10, ну и через библиотеку smbus2 передаю команды. Из кода видно что хочу вывести текст в первой и последней строке дисплея. Выводится последняя строка на месте первой. Первая строка вообще не выводится.
К тому же строка обтекается белым фоном, которым залит дисплей.
Что я делаю не так, может кто разбирался ранее с такими вещами? Практического применения не вижу (просто мне так удобно изучить тему), на контроллерах этот дисплей с их библиотеками прекрасно работает.
from smbus2 import SMBus # Из C библиотеки SSD1306_I2C_ADDRESS = 0x3C # 011110+SA0+RW - 0x3C or 0x3D SSD1306_EXTERNALVCC = 0x1 SSD1306_SETLOWCOLUMN = 0x00 SSD1306_SETHIGHCOLUMN = 0x10 SSD1306_MEMORYMODE = 0x20 SSD1306_COLUMNADDR = 0x21 SSD1306_PAGEADDR = 0x22 SSD1306_SETSTARTLINE = 0x40 SSD1306_DEFAULT_ADDRESS = 0x78 SSD1306_SETCONTRAST = 0x81 SSD1306_CHARGEPUMP = 0x8D SSD1306_SEGREMAP = 0xA0 SSD1306_DISPLAYALLON_RESUME = 0xA4 SSD1306_DISPLAYALLON = 0xA5 SSD1306_NORMALDISPLAY = 0xA6 SSD1306_INVERTDISPLAY = 0xA7 SSD1306_SETMULTIPLEX = 0xA8 SSD1306_DISPLAYOFF = 0xAE SSD1306_DISPLAYON = 0xAF SSD1306_SETPAGE = 0xB0 SSD1306_COMSCANINC = 0xC0 SSD1306_COMSCANDEC = 0xC8 SSD1306_SETDISPLAYOFFSET = 0xD3 SSD1306_SETDISPLAYCLOCKDIV = 0xD5 SSD1306_SETPRECHARGE = 0xD9 SSD1306_SETCOMPINS = 0xDA SSD1306_SETVCOMDETECT = 0xDB SSD1306_SWITCHCAPVCC = 0x02 SSD1306_NOP = 0xE3 HORIZONTAL_ADDRESSING_MODE = 0x00 VERTICAL_ADDRESSING_MODE = 0x01 PAGE_ADDRESSING_MODE = 0x02 class SSD1306Base(object): def __init__(self, width, height): self.i2c = SMBus(10) self.width = width self.height = height self._pages = height//8 self._buffer = [0]*(width*self._pages) def _initialize(self): raise NotImplementedError def command(self, c): control = 0x00 # Co = 0, DC = 0 self.i2c.write_i2c_block_data(SSD1306_I2C_ADDRESS, control,[c]) def begin(self, vccstate=SSD1306_SWITCHCAPVCC): """Initialize display.""" # Save vcc state. self._vccstate = vccstate # initialize display. self._initialize() # Turn on the display. self.command(SSD1306_DISPLAYON) def display(self): self.command(0x00) self.command(SSD1306_COLUMNADDR) self.command(0) # Column start address. (0 = reset) self.command(self.width-1) # Column end address. self.command(SSD1306_PAGEADDR) self.command(0) # Page start address. (0 = reset) self.command(self._pages-1) # Page end address. # Write buffer data. for i in range(0, len(self._buffer), 16): control = 0x40 # Co = 0, DC = 0 self.i2c.write_i2c_block_data(SSD1306_I2C_ADDRESS, control,self._buffer[i:i+16]) def image(self, image): """Set buffer to value of Python Imaging Library image. The image should be in 1 bit mode and a size equal to the display size. """ imwidth, imheight = image.size if imwidth != self.width or imheight != self.height: raise ValueError('Image must be same dimensions as display ({0}x{1}).'.format(self.width, self.height)) pix = image.load() # Iterate through the memory pages index = 0 for page in range(self._pages): for x in range(self.width):#128 # Set the bits for the column of pixels at the current position. bits = 0 # Don't use range here as it's a bit slow for bit in [0, 1, 2, 3, 4, 5, 6, 7]: bits = bits << 1 bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1 # Update buffer byte and increment to next byte. self._buffer[index] = bits index += 1 self.save(image) def save(self, image): """save contents of buffer for further analysis""" with open("out.bin", "wb") as f: f.write(bytes(self._buffer)) image.save("out_raw.bmp") def clear(self): """Clear contents of image buffer.""" self._buffer = [0]*(self.width*self._pages) def set_contrast(self, contrast): """Sets the contrast of the display. Contrast should be a value between 0 and 255.""" if contrast < 0 or contrast > 255: raise ValueError('Contrast must be a value from 0 to 255 (inclusive).') self.command(SSD1306_SETCONTRAST) self.command(contrast) def dim(self, dim): """Adjusts contrast to dim the display if dim is True, otherwise sets the contrast to normal brightness if dim is False. """ # Assume dim display. contrast = 0 # Adjust contrast based on VCC if not dimming. if not dim: if self._vccstate == SSD1306_EXTERNALVCC: contrast = 0x9F else: contrast = 0xCF class SSD1306_128_64(SSD1306Base): def __init__(self): # Call base class constructor. super(SSD1306_128_64, self).__init__(128,64) def _initialize(self): initial = [SSD1306_DISPLAYOFF, SSD1306_MEMORYMODE, HORIZONTAL_ADDRESSING_MODE, SSD1306_COMSCANDEC, SSD1306_SETSTARTLINE | 0x00, SSD1306_SETCONTRAST, 0x7F, SSD1306_SEGREMAP | 0x01, SSD1306_NORMALDISPLAY, SSD1306_SETMULTIPLEX, 63, SSD1306_SETDISPLAYOFFSET, 0x00, SSD1306_SETDISPLAYCLOCKDIV, 0x80, SSD1306_SETPRECHARGE, 0x22, SSD1306_SETCOMPINS, 0x12, SSD1306_SETVCOMDETECT, 0x20, SSD1306_CHARGEPUMP, 0x14, SSD1306_DISPLAYALLON_RESUME, SSD1306_DISPLAYON] for i in initial: self.command(i) from PIL import Image from PIL import ImageFont from PIL import ImageDraw disp = SSD1306_128_64() disp.begin() disp.clear() disp.display() image = Image.new('1', (128, 64)) draw = ImageDraw.Draw(image) font = ImageFont.truetype('arial.ttf', 18) draw.text((0, 50),'Hello', font=font, fill=255) draw.text((0, 10),'Hello10', font=font, fill=255) disp.image(image) disp.display()