SSブログ
NanoPi Neo ブログトップ

NanoPi NEO2 SPI LCD接続とか。 [NanoPi Neo]

NanoPi NEO2 メモ
参考にさせて頂いたページはこちら。⇒ NanoPi-NEOとMPDとOLEDで音楽再生サーバ
MPD関連は特に変更なし。
a.jpgd.jpgb.jpg
■ 主な変更点
・interface: i2c → SPI
・device: OLED ssd1306 → LCD ST7735S (これを使用)
・luma.lcd library

■ 使用libraryとか、OS imageとか
luma.lcd 0.5.0 python library
・Official rom image
 nanopi-neo2_ubuntu-core-xenial_4.11.2_20170605.zip
・RPi.GPIO 0.5.8 (上記、nanopi-neo2_ubuntu-core-xenial_4.11.2_20170605.zip に含まれる)
NanoHatOLED source

■ 注意点
ここの記述にあるように、 NanoPi用RPi.GPIOは"June 5, 2017" 以降のimage(2017/07/03時点 nanopi-neo2_ubuntu-core-xenial_4.11.2_20170605.zip のみ)に含まれているので、これ以外のイメージ(nanopi-neo2_ubuntu-oled_4.11.2_20170531.zip)などに含まれている RPi.GPIO 0.5.11では動作せず。

★ RPi.GPIO 0.58の控えと戻し(重要)
 1. ubuntu-core-xenial_4.11.2_20170605 imageインストール & OS初期設定
 2. RPi.GPIO 0.58の控え
    # cd /usr/local/lib/python2.7/dist-packages/
    # tar cvf  ~/RPi_0.58.tar RPi*

 3. NanoHatOLED インストール
  「NanoHat OLED関係を入れる」を参照
 4. luma.lcd インストール
 5. RPi.GPIO 0.58への戻し
  ※この時点で RPi.GPIO 0.5.11(NanoPiでは動かない...)にupdateされているハズなので戻す。
    # cd /usr/local/lib/python2.7/dist-packages/
    # rm -rf RPi*
    # tar xvf  ~/RPi_0.58.tar
    # pip list | grep RPi
    RPi.GPIO (0.5.8)
    #
■物理接続
--------------------------------------------------------------
 LCD          NanoPi Neo2 (CN1 Pin No.)
--------------------------------------------------------------
 VLED   ----  2    5V
 VCC    ----  17   3.3V
 DC/A0  ----  18   UART1_CTS/GPIOG9  (gpio_DC=18)
 SDA    ----  19   SPI0_MOSI/GPIOC0
 GND    ----  20   GND
 RST    ----  22   UART2_RX/GPIOA1  (gpio_RST=22)
 SCLK   ----  23   SPI0_CLK/GPIOC2
 CS     ----  24   SPI0_CS/GPIOC3
--------------------------------------------------------------
 
■ハマッたところ
serial = spi(bus_speed_hz=32000000, transfer_size=64, port=0, device=0, gpio=GPIO, gpio_DC=18, gpio_RST=22)
device = st7735(serial, h_offset=1, v_offset=2, rotate=1)

 1. h_offset=1, v_offset=2
  ⇒ 要画面表示位置調整
 2. transfer_size=64 指定必須
   ⇒ 未指定時4096がデフォだが64を指定しないとspi dev open後のデータ送信不可
 3. rotate=1 or 3 設定時は framebuffer="full_frame" 指定不可
   ⇒ エラーは出ないが画面表示ぐちゃぐちゃ

■code
/root/NanoPi-NEO_OLED_MPD/oled_mpd.py
#!/usr/bin/env python
# -*- encoding:utf8 -*-
#
#	apt-get install fonts-takao-pgothic
#	apt-get install python-mutagen python3-mutagen

import os
import sys
import time
import signal
import socket
import errno
import subprocess

import RPi.GPIO as GPIO
from luma.core.serial import spi
from luma.lcd.device import st7735
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

mpd_music_dir	= "/media/"
scroll_unit		= 1

title_height	= 18

font_title              = ImageFont.truetype('TakaoPGothic.ttf', 14, encoding='unic')
font_info		= ImageFont.truetype('TakaoPGothic.ttf', 11, encoding='unic')
font_audio		= ImageFont.load_default()
font_time		= ImageFont.truetype('TakaoPGothic.ttf', 27);
font_date		= ImageFont.truetype('TakaoPGothic.ttf', 16);

mpd_host		= 'localhost'
mpd_port		= 6600
mpd_bufsize		= 8192


def receive_signal(signum, stack):
	try:
		soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		soc.connect((mpd_host, mpd_port))
		soc.recv(mpd_bufsize)

		if signum == signal.SIGUSR1:
			print 'K1 pressed'
			soc.send('previous\n')
			soc.recv(mpd_bufsize)

		if signum == signal.SIGUSR2:
			print 'K2 pressed'
			soc.send('status\n')
			buff        = soc.recv(mpd_bufsize)
			state_list  = buff.splitlines()
			for line in range(0,len(state_list)):
				if state_list[line].startswith(r"state: "):
					info_state      = state_list[line].replace(r"state: ", "")
					print(info_state)
					if info_state == 'play' :
						soc.send('stop\n')
						soc.recv(mpd_bufsize)
					else:
						soc.send('play\n')
						soc.recv(mpd_bufsize)
		if signum == signal.SIGALRM:
			print 'K3 pressed'
			soc.send('next\n')
			soc.recv(mpd_bufsize)

	except socket.error as cerr:
		if cerr.errno == errno.EINTR:
			buff        = soc.recv(mpd_bufsize)
			print("Exception! :", sys.exc_info())
			pass

signal.signal(signal.SIGUSR1, receive_signal)
signal.signal(signal.SIGUSR2, receive_signal)
signal.signal(signal.SIGALRM, receive_signal)

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
serial = spi(bus_speed_hz=32000000, transfer_size=64, port=0, device=0, gpio=GPIO, gpio_DC=18, gpio_RST=22)
#device = st7735(serial, framebuffer="full_frame", h_offset=1, v_offset=2)
device = st7735(serial, h_offset=1, v_offset=2, rotate=1)

oled_width  = device.width
oled_height = device.height
# cover_size  = oled_height - title_height - 20
cover_size  = device.width - 12

# OLED image
image			= Image.new('RGB', (oled_width, oled_height))
draw			= ImageDraw.Draw(image)
draw.rectangle((0,0,oled_width,oled_height), outline=0, fill=0)

music_file     = ""
cover_image   = Image.new('RGB', (cover_size, cover_size))
title_image   = Image.new('RGB', (oled_width, title_height))
title_offset   = 0

# Draw opening image
try:
	device.display(Image.open('opening.png').resize((oled_width,oled_height)).convert('RGB'))
	time.sleep(0.4)
except:
        device.display(image)

soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.connect((mpd_host, mpd_port))
soc.recv(mpd_bufsize)
# soc.send('commands\n')
# rcv = soc.recv(mpd_bufsize)
# print("commands:")
# print("----- start ----------")
# print( rcv )
# print("----- end ----------\n")

while True:
	try:
		soc.send('currentsong\n')
		buff        = soc.recv(mpd_bufsize)
		song_list   = buff.splitlines()
		# print("currentsong:")
		# print("----- start ----------")
		# print( buff )
		# print("----- end ----------\n")
		soc.send('status\n')
		buff        = soc.recv(mpd_bufsize)
		state_list  = buff.splitlines()

		# print("status:")
		# print("----- start ----------")
		# print( buff )
		# print("----- end ----------\n")

		info_state      = ""
		info_audio      = ""
		info_elapsed    = 0
		info_duration   = 0
		info_title      = ""
		info_artist     = ""
		info_album      = ""
		info_file       = ""
	except socket.error as e:
		if e.errno == errno.EINTR:
			buff        = soc.recv(mpd_bufsize)
			print("Exception! :", sys.exc_info())
			continue

	for line in range(0,len(state_list)):
		if state_list[line].startswith("state: "):     info_state      = state_list[line].replace("state: ", "")
		if state_list[line].startswith("audio: "):     info_audio      = state_list[line].replace("audio: ", "")
		if state_list[line].startswith("elapsed: "):   info_elapsed    = float(state_list[line].replace("elapsed: ", ""))
		if state_list[line].startswith("time: "):      info_duration   = float(state_list[line].split(":")[2])

	for line in range(0,len(song_list)):
		if song_list[line].startswith("file: "):       info_file       = song_list[line].replace("file: ", "")
		if song_list[line].startswith("Artist: "):     info_artist     = song_list[line].replace("Artist: ", "")
		if song_list[line].startswith("Album: "):      info_album      = song_list[line].replace("Album: ", "")
		if song_list[line].startswith("Title: "):      info_title      = song_list[line].replace("Title: ", "")

	# clear the image
	draw.rectangle((0,0,oled_width,oled_height), outline=0, fill=0)

	if info_state != "stop":

		if info_title == "" :
			name    = info_file.split('/')
			name.reverse()
			info_title  = name[0]

			try:
				info_album  = name[1]
			except:
				info_album  = ""

			try:
				info_artist = name[2]
			except:
				info_artist = ""

		if info_file != music_file :

			music_file  = info_file;
			file_path   = mpd_music_dir + info_file
			cover_path  = mpd_music_dir + os.path.split(music_file)[0] + "/front.jpg"

			print('--------------------------------------------')
			print(file_path)

			try:

				from mutagen import File
				file = File(file_path) # mutagen can automatically detect format and typeof tags

				if hasattr(file,'tags') :

					# for FLAC
					if hasattr(file,'pictures') :
						print( 'type = pictures' )
						print( file.pictures )
						artwork = file.pictures[0].data

					# for mp3
					elif 'APIC:' in file :
						print( 'type = APIC' )
						artwork = file.tags['APIC:'].data

					# for m4a
					elif 'covr' in file :
						print( 'type = covr' )
#                       print dir( file.tags['covr'][0])
						artwork = file.tags['covr'][0]

					else:
						print('NoPicture!, dump tags')
						print( file.tags )

					with open('front.jpg', 'wb') as img:
						img.write(artwork) # write artwork to new image

					cover_path  = "front.jpg"

				else:
					print( 'type = NO TAGS')

			except:
				print("Exception! :", sys.exc_info())
				## print( file.tags )
				continue

			print( cover_path )
			cover_draw  = ImageDraw.Draw(cover_image)
			####### cover_draw.rectangle((0,0,cover_size-1,cover_size-1), outline="white", fill=0)
			if os.path.isfile( cover_path ) :
				front_image = Image.open(cover_path).convert('RGB').resize((cover_size-1,cover_size-1),Image.ANTIALIAS)
				cover_image.paste( front_image.convert('RGB'), (0,0))
			else:
				text_x, text_y = font_audio.getsize("NoImage")
				cover_draw.text(((cover_size-text_x)/2, (cover_size - text_y)/2 ), "NoImage", font=font_audio, fill="white")
			# Generate title image
			title_width, dmy_y   = font_title.getsize(unicode(info_title,'utf-8'))
			title_offset    = oled_width / 2;
			title_image     = Image.new('RGB', (title_width, title_height))
			title_draw      = ImageDraw.Draw(title_image)
			title_draw.rectangle((0,0, title_width, title_height), outline=0, fill=0)
			title_draw.text((0,0), unicode(info_title,'utf-8'), font=font_title, fill="white")

		# Title
		x   = 0
		y   = cover_size + 2
		if oled_width < title_image.width :
			if title_image.width < -title_offset :
				title_offset    = oled_width / 2

			if title_offset < 0 :
				x   = title_offset

                        time.sleep(0.04)
			title_offset    = title_offset - scroll_unit

		image.paste(title_image, (x,y))
		x   = 0;

		# Current playback position
		y =  cover_size
		r	= (oled_width * info_elapsed / info_duration) if 0 < info_duration else oled_width
		draw.line((x, y, r, y ), fill="red")

		# Cover Image
		y   += 2;
		image.paste( cover_image, (5,0))

		# artist name, album name, audio format
		### x   = cover_size + 3;
		x   = 0
		y   += title_height -5;
		draw.text((x, y), unicode(info_artist,'utf-8'), font=font_info, fill="lime")
		draw.text((x, y + (oled_height - 10 - y) / 2), unicode(info_album,'utf-8'), font=font_info, fill="cyan")
		draw.text((x, oled_height - 10), unicode(info_audio,'utf-8'), font=font_audio, fill="navy")
	else:

		music_file  = ""

		draw.text((2, 4),time.strftime("%A"),		font=font_date,fill="skyblue")
		draw.text((2,21),time.strftime("%e %b %Y"),	font=font_date,fill="skyblue")
		draw.text((2,77),time.strftime("%X"),		font=font_time,fill="white")

	device.display(image)


   ★参考コード
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感
NanoPi Neo ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。