diff --git a/.gitignore b/.gitignore index 5d381cc..78102b5 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,4 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +.vscode/ diff --git a/led.py b/Led/led.py similarity index 85% rename from led.py rename to Led/led.py index f0df155..b976b3a 100644 --- a/led.py +++ b/Led/led.py @@ -3,13 +3,18 @@ import RPi.GPIO as GPIO import time +import spidev def main(): LED = 26 + GPIO.setwarnings(False) + GPIO.setmode(GPIO.BCM) GPIO.setup(LED,GPIO.OUT) + spi = spidev.SpiDev() + try: while True: GPIO.output(LED,GPIO.HIGH) @@ -23,4 +28,3 @@ def main(): if __name__=='__main__': main() - diff --git a/Oled/SSD1306.py b/Oled/SSD1306.py new file mode 100644 index 0000000..c11ad61 --- /dev/null +++ b/Oled/SSD1306.py @@ -0,0 +1,172 @@ +import spidev +import RPi.GPIO as GPIO +import time + +# Constants +SSD1306_SETCONTRAST = 0x81 +SSD1306_DISPLAYALLON_RESUME = 0xA4 +SSD1306_DISPLAYALLON = 0xA5 +SSD1306_NORMALDISPLAY = 0xA6 +SSD1306_INVERTDISPLAY = 0xA7 +SSD1306_DISPLAYOFF = 0xAE +SSD1306_DISPLAYON = 0xAF +SSD1306_SETDISPLAYOFFSET = 0xD3 +SSD1306_SETCOMPINS = 0xDA +SSD1306_SETVCOMDETECT = 0xDB +SSD1306_SETDISPLAYCLOCKDIV = 0xD5 +SSD1306_SETPRECHARGE = 0xD9 +SSD1306_SETMULTIPLEX = 0xA8 +SSD1306_SETLOWCOLUMN = 0x00 +SSD1306_SETHIGHCOLUMN = 0x10 +SSD1306_SETSTARTLINE = 0x40 +SSD1306_MEMORYMODE = 0x20 +SSD1306_COLUMNADDR = 0x21 +SSD1306_PAGEADDR = 0x22 +SSD1306_COMSCANINC = 0xC0 +SSD1306_COMSCANDEC = 0xC8 +SSD1306_SEGREMAP = 0xA0 +SSD1306_CHARGEPUMP = 0x8D +SSD1306_EXTERNALVCC = 0x1 +SSD1306_SWITCHCAPVCC = 0x2 + +# Scrolling constants +SSD1306_ACTIVATE_SCROLL = 0x2F +SSD1306_DEACTIVATE_SCROLL = 0x2E +SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3 +SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26 +SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27 +SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29 +SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A + +class SSD1306(object): + """class for SSD1306 128*64 0.96inch OLED displays.""" + + def __init__(self,rst,dc,spi): + self.width = 128 + self.height = 64 + self._pages = 8 + self._buffer = [0]*(self.width*self._pages) + #Initialize DC RST pin + self._dc = dc + self._rst = rst + GPIO.setmode(GPIO.BCM) + GPIO.setwarnings(False) + GPIO.setup(self._dc,GPIO.OUT) + GPIO.setup(self._rst,GPIO.OUT) + #Initialize SPI + self._spi = spi + def command(self,cmd): + """Send command byte to display""" + GPIO.output(self._dc,GPIO.LOW) + self._spi.writebytes([cmd]) + def data(self,val): + """Send byte of data to display""" + GPIO.output(self._dc,GPIO.HIGHT) + self._spi.writebytes([val]) + def begin(self,vccstate=SSD1306_SWITCHCAPVCC): + """Initialize dispaly""" + self._vccstate = vccstate + self.reset() + self.command(SSD1306_DISPLAYOFF) # 0xAE + self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5 + self.command(0x80) # the suggested ra tio 0x80 + + self.command(SSD1306_SETMULTIPLEX) # 0xA8 + self.command(0x3F) + self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3 + self.command(0x0) # no offset + self.command(SSD1306_SETSTARTLINE | 0x0) # line #0 + self.command(SSD1306_CHARGEPUMP) # 0x8D + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x10) + else: + self.command(0x14) + self.command(SSD1306_MEMORYMODE) # 0x20 + self.command(0x00) # 0x0 act like ks0108 + self.command(SSD1306_SEGREMAP | 0x1) + self.command(SSD1306_COMSCANDEC) + self.command(SSD1306_SETCOMPINS) # 0xDA + self.command(0x12) + self.command(SSD1306_SETCONTRAST) # 0x81 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x9F) + else: + self.command(0xCF) + self.command(SSD1306_SETPRECHARGE) # 0xd9 + if self._vccstate == SSD1306_EXTERNALVCC: + self.command(0x22) + else: + self.command(0xF1) + self.command(SSD1306_SETVCOMDETECT) # 0xDB + self.command(0x40) + self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4 + self.command(SSD1306_NORMALDISPLAY) # 0xA6 + self.command(SSD1306_DISPLAYON) + def reset(self): + """Reset the display""" + GPIO.output(self._rst,GPIO.HIGH) + time.sleep(0.001) + GPIO.output(self._rst,GPIO.LOW) + time.sleep(0.010) + GPIO.output(self._rst,GPIO.HIGH) + def display(self): + """Write display buffer to physical display""" + self.command(SSD1306_COLUMNADDR) + self.command(0) #Cloumn start address + self.command(self.width-1) #Cloumn end address + self.command(SSD1306_PAGEADDR) + self.command(0) #Page start address + self.command(self._pages-1) #Page end address + #Write buffer data + GPIO.output(self._dc,GPIO.HIGH) + self._spi.writebytes(self._buffer) + def image(self, image): + """Set buffer to value of Python Imaging Library image.""" + if image.mode != '1': + raise ValueError('Image must be in mode 1.') + 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): + # Iterate through all x axis columns. + for x in range(self.width): + # 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 + 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).') + 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 + + + + diff --git a/Oled/animate.py b/Oled/animate.py new file mode 100644 index 0000000..e727305 --- /dev/null +++ b/Oled/animate.py @@ -0,0 +1,91 @@ +# Copyright (c) 2015 WaveShare +# Author: My MX +import math +import time + +import spidev as SPI +import SSD1306 + +from PIL import Image +from PIL import ImageFont +from PIL import ImageDraw + + +# Raspberry Pi pin configuration: +RST = 19 +DC = 16 +bus = 0 +device = 0 + +# 128x32 display with hardware SPI: +disp = SSD1306.SSD1306(rst=RST,dc=DC,spi=SPI.SpiDev(bus,device)) + +# Initialize library. +disp.begin() + +# Get display width and height. +width = disp.width +height = disp.height + +# Clear display. +disp.clear() +disp.display() + +# Create image buffer. +# Make sure to create image with mode '1' for 1-bit color. +image = Image.new('1', (width, height)) + +# Load default font. +font = ImageFont.load_default() + +# Alternatively load a TTF font. Make sure the .ttf font file is in the same directory as this python script! +# Some nice fonts to try: http://www.dafont.com/bitmap.php +# font = ImageFont.truetype('Minecraftia.ttf', 8) + +# Create drawing object. +draw = ImageDraw.Draw(image) + +# Define text and get total width. +text = 'SSD1306 ORGANIC LED DISPLAY. THIS IS AN OLD SCHOOL DEMO SCROLLER!! GREETZ TO: LADYADA & THE ADAFRUIT CREW, TRIXTER, FUTURE CREW, AND FARBRAUSCH' +maxwidth, unused = draw.textsize(text, font=font) + +# Set animation and sine wave parameters. +amplitude = height/4 +offset = height/2 - 4 +velocity = -2 +startpos = width + +# Animate text moving in sine wave. +print("Press Ctrl-C to quit.") +pos = startpos +while True: + # Clear image buffer by drawing a black filled box. + draw.rectangle((0,0,width,height), outline=0, fill=0) + # Enumerate characters and draw them offset vertically based on a sine wave. + x = pos + for i, c in enumerate(text): + # Stop drawing if off the right side of screen. + if x > width: + break + # Calculate width but skip drawing if off the left side of screen. + if x < -10: + char_width, char_height = draw.textsize(c, font=font) + x += char_width + continue + # Calculate offset from sine wave. + y = offset+math.floor(amplitude*math.sin(x/float(width)*2.0*math.pi)) + # Draw text. + draw.text((x, y), c, font=font, fill=255) + # Increment x position based on chacacter width. + char_width, char_height = draw.textsize(c, font=font) + x += char_width + # Draw the image buffer. + disp.image(image) + disp.display() + # Move position for next frame. + pos += velocity + # Start over if text has scrolled completely off left side of screen. + if pos < -maxwidth: + pos = startpos + # Pause briefly before drawing next frame. + time.sleep(0.1) diff --git a/Oled/dispchar.py b/Oled/dispchar.py new file mode 100644 index 0000000..d809710 --- /dev/null +++ b/Oled/dispchar.py @@ -0,0 +1,62 @@ +import time + +import spidev as SPI +import SSD1306 + +from PIL import Image +from PIL import ImageDraw +from PIL import ImageFont + +# Raspberry Pi pin configuration: +RST = 19 +# Note the following are only used with SPI: +DC = 16 +bus = 0 +device = 0 + +# 128x64 display with hardware SPI: +disp = SSD1306.SSD1306(RST, DC, SPI.SpiDev(bus,device)) + +# Initialize library. +disp.begin() + +# Clear display. +disp.clear() +disp.display() + +# Create blank image for drawing. +# Make sure to create image with mode '1' for 1-bit color. +width = disp.width +height = disp.height +image = Image.new('1', (width, height)) + +# Get drawing object to draw on image. +draw = ImageDraw.Draw(image) + +# Draw a black filled box to clear the image. +draw.rectangle((0,0,width,height), outline=0, fill=0) + +# Draw some shapes. +# First define some constants to allow easy resizing of shapes. +padding = 1 +top = padding +x = padding +# Load default font. +font = ImageFont.load_default() + +# Alternatively load a TTF font. +# Some other nice fonts to try: http://www.dafont.com/bitmap.php +#font = ImageFont.truetype('Minecraftia.ttf', 8) + +# Write two lines of text. +draw.text((x, top), 'This is first line', font=font, fill=255) +draw.text((x, top+10), 'This is second line', font=font, fill=255) +draw.text((x, top+20), 'This is third line', font=font, fill=255) +draw.text((x, top+30), 'This is fourth line', font=font, fill=255) +draw.text((x, top+40), 'This is fifth line', font=font, fill=255) +draw.text((x, top+50), 'This is last line', font=font, fill=255) + +# Display image. +disp.image(image) +disp.display() + diff --git a/Oled/happycat.ppm b/Oled/happycat.ppm new file mode 100644 index 0000000..922daac Binary files /dev/null and b/Oled/happycat.ppm differ diff --git a/Oled/image.py b/Oled/image.py new file mode 100644 index 0000000..56a23d2 --- /dev/null +++ b/Oled/image.py @@ -0,0 +1,36 @@ +# Copyright (c) 2015 WaveShare +# Author: My MX +import time + +import spidev as SPI +import SSD1306 + +from PIL import Image + + +# Raspberry Pi pin configuration: +RST = 19 +DC = 16 +bus = 0 +device = 0 + + +# 128x32 display with hardware I2C: +disp = SSD1306.SSD1306(rst=RST,dc=DC,spi=SPI.SpiDev(bus,device)) + +# Initialize library. +disp.begin() + +# Clear display. +disp.clear() +disp.display() + +# Load image based on OLED display height. Note that image is converted to 1 bit color. +image = Image.open('happycat.ppm').convert('1') + +# Alternatively load a different format image, resize it, and convert to 1 bit color. +#image = Image.open('happycat.png').resize((disp.width, disp.height), Image.ANTIALIAS).convert('1') + +# Display image. +disp.image(image) +disp.display() diff --git a/Oled/oled.py b/Oled/oled.py new file mode 100644 index 0000000..dc569f9 --- /dev/null +++ b/Oled/oled.py @@ -0,0 +1,55 @@ +import spidev as SPI +import SSD1306 +import time + +from PIL import Image,ImageDraw,ImageFont + +# Raspberry Pi pin configuration: +GPIO_RST = 19 +GPIO_DC = 16 +SPI_BUS = 0 +SPI_CS = 0 + +# 128x64 display with hardware SPI: +disp = SSD1306.SSD1306(GPIO_RST, GPIO_DC, SPI.SpiDev(SPI_BUS, SPI_CS)) + +# Initialize library. +disp.begin() + +# Clear display. +disp.clear() +disp.display() + +# Create blank image for drawing. +# Make sure to create image with mode '1' for 1-bit color. +width = disp.width +height = disp.height +image = Image.new('1', (width, height)) + +# Get drawing object to draw on image. +draw = ImageDraw.Draw(image) + +# Draw a black filled box to clear the image. +draw.rectangle((0,0,width,height), outline=0, fill=0) + +# Draw some shapes. +# First define some constants to allow easy resizing of shapes. +padding = 2 +shape_width = 20 + +top = padding +bottom = height - padding + +# Move left to right keeping track of the current x position for drawing shapes. +x = padding +y = top + +# Load default font. +font = ImageFont.load_default() + +# Write two lines of text. +draw.text((x, y), 'Hello, world', font=font, fill=255) + +# Display image. +disp.image(image) +disp.display() diff --git a/Oled/waveshare.bmp b/Oled/waveshare.bmp new file mode 100644 index 0000000..6550883 Binary files /dev/null and b/Oled/waveshare.bmp differ diff --git a/Oled/waveshare.py b/Oled/waveshare.py new file mode 100644 index 0000000..8cb9000 --- /dev/null +++ b/Oled/waveshare.py @@ -0,0 +1,36 @@ +# Copyright (c) 2015 WaveShare +# Author: My MX +import time + +import spidev as SPI +import SSD1306 + +#import Image +from PIL import Image + +# Raspberry Pi pin configuration: +RST = 19 +DC = 16 +bus = 0 +device = 0 + + +# 128x32 display with hardware I2C: +disp = SSD1306.SSD1306(rst=RST,dc=DC,spi=SPI.SpiDev(bus,device)) + +# Initialize library. +disp.begin() + +# Clear display. +disp.clear() +disp.display() + +# Load image based on OLED display height. Note that image is converted to 1 bit color. +image = Image.open('waveshare.bmp').convert('1') + +# Alternatively load a different format image, resize it, and convert to 1 bit color. +#image = Image.open('happycat.png').resize((disp.width, disp.height), Image.ANTIALIAS).convert('1') + +# Display image. +disp.image(image) +disp.display() diff --git a/gpio.py b/gpio.py deleted file mode 100644 index 7600065..0000000 --- a/gpio.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -import RPi.GPIO as GPIO -import time - -def main(): - LED = 26 - - GPIO.setmode(GPIO.BCM) - GPIO.setup(LED, GPIO.OUT) - - try: - while True: - GPIO.output(LED, GPIO.HIGH) - time.sleep(1) - GPIO.output(LED, GPIO.LOW) - time.sleep(1) - except: - print("except") - GPIO.output(LED, GPIO.HIGH) - GPIO.cleanup() - - -if __name__ == '__main__': - main() diff --git a/main.py b/main.py new file mode 100644 index 0000000..06e6051 --- /dev/null +++ b/main.py @@ -0,0 +1,33 @@ +import os +import sys +import time +import RPi.GPIO as GPIO +import spidev as SPI +sys.path.append(os.path.join(os.path.dirname(__file__),'Oled')) +import SSD1306 + +from PIL import Image,ImageDraw,ImageFont + +# Raspberry Pi pin configuration: +OLED_GPIO_RST = 19 +OLED_GPIO_DC = 16 +OLED_SPI_BUS = 0 +OLED_SPI_CS = 0 + +LED_GPIO_RED = 26 + +# 128x64 display with hardware SPI: +disp = SSD1306.SSD1306(OLED_GPIO_RST, OLED_GPIO_DC, SPI.SpiDev(OLED_SPI_BUS, OLED_SPI_CS)) + +def main(): + + try: + while True: + time.sleep(1) + except: + print("except") + +if __name__=='__main__': + main() + +