robert-hh / SH1106

MicroPython driver for the SH1106 OLED controller
Other
157 stars 38 forks source link

Pi Pico #13

Closed smiffycom closed 3 years ago

smiffycom commented 3 years ago

Hi, i can't get this driver to work on the Pi Pico

I use; display = sh1106.SH1106_I2C(128, 64, i2c, Pin(16), 0x3c)

all I get is;

File "sh1106.py", line 21, in AttributeError: 'module' object has no attribute 'SH1106_I2C'

any ideas?

robert-hh commented 3 years ago

No. If you use e.g.:

import sh1106
from machine import I2C
i2c=I2C(0)
display = sh1106.SH1106_I2C(128, 64, i2c, Pin(16), 0x3c)

That should work. What is the result of:

import sh1106
dir(sh1106)
smiffycom commented 3 years ago

Hi Robert,

I have tried LOTS of times to use your library with no success. I have placed your code in /lib and the root of my Pico. neither works. I have tried nearly every combination imaginable it always comes back with

Traceback (most recent call last): File "", line 13, in File "sh1106.py", line 39, in ImportError: can't import name SH1106_I2C

I'm using this I2C declaration i2c = I2C(1,scl=Pin(19), sda=Pin(18), freq=400000) As this is where the device is connected, but I have tried the default.. still no joy

here's the results of a DIR

import sh1106 dir (sh1106) ['class', 'name', 'I2C', 'Pin', 'sh1106']

where to now?

Regards,

smiffy


From: robert-hh @.> Sent: 07 April 2021 10:36 To: robert-hh/SH1106 @.> Cc: smiffycom @.>; Author @.> Subject: Re: [robert-hh/SH1106] Pi Pico (#13)

Closed #13https://github.com/robert-hh/SH1106/issues/13.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/robert-hh/SH1106/issues/13#event-4561388082, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ANHFH7KNX32UYFJGHRDGX3TTHQRRJANCNFSM42O3FJ6A.

robert-hh commented 3 years ago

a) did you download the sh1106.py from this place: https://github.com/robert-hh/SH1106 b) what else is in the file system of your board? c) What is the name of the file you set up to test the driver. Is it by chance sh1106.py too? That must not be. You have to give it a different name.

smiffycom commented 3 years ago

a) Yes, downloaded it a dozen times b) just drivers for a few totally unrelated bits of hardware, and a few bits of code - there's loads of RAM available c) yes, your code is in /lib with edits for my I2C hardware, the program in /root is another name

in your code as posted; i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) I get Traceback (most recent call last): File "", line 3, in File "sh1106.py", line 5, in TypeError: 'id' argument required Line 5 being; i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) if I add the (0, i2c = I2C(0,scl=Pin(5), sda=Pin(4), freq=400000) I get the familiar

Traceback (most recent call last): File "", line 3, in File "sh1106.py", line 6, in AttributeError: 'module' object has no attribute 'SH1106_I2C' Line 6 being; display = sh1106.SH1106_I2C(128, 64, i2c, None, 0x3c)

smiffy


From: robert-hh @.> Sent: 10 April 2021 16:13 To: robert-hh/SH1106 @.> Cc: smiffycom @.>; Author @.> Subject: Re: [robert-hh/SH1106] Pi Pico (#13)

a) did you download the sh1106.py from this place: https://github.com/robert-hh/SH1106 b) what else is in the file system of your board? c) What is the name of the file you set up to test the driver. Is it by chance sh1106.py too? That must not be. You have to give it a different name.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/robert-hh/SH1106/issues/13#issuecomment-817151688, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ANHFH7N4CUHF6F2JK2OB4ITTIBTJPANCNFSM42O3FJ6A.

robert-hh commented 3 years ago

My code contains just an example of how to use the driver as comments. Obviously you have to adapt that for the target hardware. The initial example was for ESP8266. Are you sure that there is no other file called sh1106.py or sh1106.mpy in the file system? What is the value of sys.path? And, which firmware do you use? And to be sure, the driver must look like the lines below:

#
# MicroPython SH1106 OLED driver, I2C and SPI interfaces
#
# The MIT License (MIT)
#
# Copyright (c) 2016 Radomir Dopieralski (@deshipu),
#               2017 Robert Hammelrath (@robert-hh)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# Sample code sections
# ------------ SPI ------------------
# Pin Map SPI
#   - 3v - xxxxxx   - Vcc
#   - G  - xxxxxx   - Gnd
#   - D7 - GPIO 13  - Din / MOSI fixed
#   - D5 - GPIO 14  - Clk / Sck fixed
#   - D8 - GPIO 4   - CS (optional, if the only connected device)
#   - D2 - GPIO 5   - D/C
#   - D1 - GPIO 2   - Res
#
# for CS, D/C and Res other ports may be chosen.
#
# from machine import Pin, SPI
# import sh1106

# spi = SPI(1, baudrate=1000000)
# display = sh1106.SH1106_SPI(128, 64, spi, Pin(5), Pin(2), Pin(4))
# display.sleep(False)
# display.fill(0)
# display.text('Testing 1', 0, 0, 1)
# display.show()
#
# --------------- I2C ------------------
#
# Pin Map I2C
#   - 3v - xxxxxx   - Vcc
#   - G  - xxxxxx   - Gnd
#   - D2 - GPIO 5   - SCK / SCL
#   - D1 - GPIO 4   - DIN / SDA
#   - D0 - GPIO 16  - Res
#   - G  - xxxxxx     CS
#   - G  - xxxxxx     D/C
#
# Pin's for I2C can be set almost arbitrary
#
# from machine import Pin, I2C
# import sh1106
#
# i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
# display = sh1106.SH1106_I2C(128, 64, i2c, Pin(16), 0x3c)
# display.sleep(False)
# display.fill(0)
# display.text('Testing 1', 0, 0, 1)
# display.show()

from micropython import const
import utime as time
import framebuf

# a few register definitions
_SET_CONTRAST        = const(0x81)
_SET_NORM_INV        = const(0xa6)
_SET_DISP            = const(0xae)
_SET_SCAN_DIR        = const(0xc0)
_SET_SEG_REMAP       = const(0xa0)
_LOW_COLUMN_ADDRESS  = const(0x00)
_HIGH_COLUMN_ADDRESS = const(0x10)
_SET_PAGE_ADDRESS    = const(0xB0)

class SH1106:
    def __init__(self, width, height, external_vcc):
        self.width = width
        self.height = height
        self.external_vcc = external_vcc
        self.pages = self.height // 8
        self.buffer = bytearray(self.pages * self.width)
        fb = framebuf.FrameBuffer(self.buffer, self.width, self.height,
                                  framebuf.MVLSB)
        self.framebuf = fb
# set shortcuts for the methods of framebuf
        self.fill = fb.fill
        self.fill_rect = fb.fill_rect
        self.hline = fb.hline
        self.vline = fb.vline
        self.line = fb.line
        self.rect = fb.rect
        self.pixel = fb.pixel
        self.scroll = fb.scroll
        self.text = fb.text
        self.blit = fb.blit

        self.init_display()

    def init_display(self):
        self.reset()
        self.fill(0)
        self.poweron()
        self.show()

    def poweroff(self):
        self.write_cmd(_SET_DISP | 0x00)

    def poweron(self):
        self.write_cmd(_SET_DISP | 0x01)

    def rotate(self, flag, update=True):
        if flag:
            self.write_cmd(_SET_SEG_REMAP | 0x01)  # mirror display vertically
            self.write_cmd(_SET_SCAN_DIR | 0x08)  # mirror display hor.
        else:
            self.write_cmd(_SET_SEG_REMAP | 0x00)
            self.write_cmd(_SET_SCAN_DIR | 0x00)
        if update:
            self.show()

    def sleep(self, value):
        self.write_cmd(_SET_DISP | (not value))

    def contrast(self, contrast):
        self.write_cmd(_SET_CONTRAST)
        self.write_cmd(contrast)

    def invert(self, invert):
        self.write_cmd(_SET_NORM_INV | (invert & 1))

    def show(self):
        for page in range(self.height // 8):
            self.write_cmd(_SET_PAGE_ADDRESS | page)
            self.write_cmd(_LOW_COLUMN_ADDRESS | 2)
            self.write_cmd(_HIGH_COLUMN_ADDRESS | 0)
            self.write_data(self.buffer[
                self.width * page:self.width * page + self.width
            ])

    def reset(self, res):
        if res is not None:
            res(1)
            time.sleep_ms(1)
            res(0)
            time.sleep_ms(20)
            res(1)
            time.sleep_ms(20)

class SH1106_I2C(SH1106):
    def __init__(self, width, height, i2c, res=None, addr=0x3c,
                 external_vcc=False):
        self.i2c = i2c
        self.addr = addr
        self.res = res
        self.temp = bytearray(2)
        if res is not None:
            res.init(res.OUT, value=1)
        super().__init__(width, height, external_vcc)

    def write_cmd(self, cmd):
        self.temp[0] = 0x80  # Co=1, D/C#=0
        self.temp[1] = cmd
        self.i2c.writeto(self.addr, self.temp)

    def write_data(self, buf):
        self.i2c.writeto(self.addr, b'\x40'+buf)

    def reset(self):
        super().reset(self.res)

class SH1106_SPI(SH1106):
    def __init__(self, width, height, spi, dc, res=None, cs=None,
                 external_vcc=False):
        self.rate = 10 * 1000 * 1000
        dc.init(dc.OUT, value=0)
        if res is not None:
            res.init(res.OUT, value=0)
        if cs is not None:
            cs.init(cs.OUT, value=1)
        self.spi = spi
        self.dc = dc
        self.res = res
        self.cs = cs
        super().__init__(width, height, external_vcc)

    def write_cmd(self, cmd):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        if self.cs is not None:
            self.cs(1)
            self.dc(0)
            self.cs(0)
            self.spi.write(bytearray([cmd]))
            self.cs(1)
        else:
            self.dc(0)
            self.spi.write(bytearray([cmd]))

    def write_data(self, buf):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        if self.cs is not None:
            self.cs(1)
            self.dc(1)
            self.cs(0)
            self.spi.write(buf)
            self.cs(1)
        else:
            self.dc(1)
            self.spi.write(buf)

    def reset(self):
        super().reset(self.res)
KohliNaman commented 2 years ago

reopening this because @smiffycom didn't notify if the issue was resolved. check out my repo for the pico(primarily over spi but i2c should work) and lemme know if you have any issue(remember to make changes in main.py too)