8ビットI/Oエクスパンダ(MCP23008/MCP23S08)を用いたLEDアレイの点灯プログラム例

シリアルインターフェイス(I2C又はSPI)の8ビットI/OエクスパンダIC(MCP23008/MCP23S08:Microchip製)を用いて、LEDアレイ(OSX10201-R)を点灯させるプログラムを紹介する。

●使用したIC部品

MCP23008-I2C

MCP23008(I2C接続)

MCP23S08-SPI

MCP23S08(SPI接続)

シリアルインターフェイス8ビットI/OエクスパンダICは、I2Cインターフェイス(MCP23008)はmarutsuオンラインで1個\458、SPIインターフェイス(MCP23S08)は秋月電子通商で1個\200で入手した。

■主な仕様
・ポート数:8
・インターフェイス:I2CまたはSPI
・電源電圧min.:1.8V
・電源電圧max.:5.5V
・クロック周波数max.:10MHz
・出力電流max.:25mA

●LEDアレイ点灯回路図

・I2CによるLEDアレイ点灯回路

・SPIによるLEDアレイ点灯回路

●LEDアレイ点灯のプログラム例

 サンプルプログラムは、10LEDアレイの内8個を使って、指定した番号のLEDを点灯/消灯させる事例。

<プログラム事例>

・I2CによるLEDアレイ点灯モジュール(I2C_EXPANDA.py)

import RPi.GPIO as GPIO
import smbus
import time

# ピンの名前を変数として定義
DEV_RESET = 5
REG_IODIR = 0x00	# I/O方向レジスタ
REG_GPIO = 0x09		# PORT レジスタ(入出力)
REG_IOCON = 0x05	# 設定レジスタ
DEV_ADR = 0x20		# Device Address=0b010 0000(A2=0, A1=0, A0=0)

#=================================================================
class MCP23008:
	def __init__(self):
		# I2Cの初期化とMC23008デバイス設定
		self.I2C = smbus.SMBus(1)
		GPIO.setmode(GPIO.BCM)
		GPIO.setwarnings(False)
		GPIO.setup(DEV_RESET, GPIO.OUT, initial=GPIO.HIGH)	# Device Reset = 0
		# デバイスのリセット
		GPIO.output(DEV_RESET, GPIO.LOW)	# Device Reset = 0
		time.sleep(0.01)
		GPIO.output(DEV_RESET, GPIO.HIGH)
		# デバイスの初期設定
		self.I2C.write_byte_data(DEV_ADR, REG_IODIR, 0x00)	# IODIRレジスタ:データI/Oを出力に設定
		self.I2C.write_byte_data(DEV_ADR, REG_IOCON, 0x38)	# IOCONレジスタ(シーケンシャル禁止、アドレスピン許可)に設定
		# 全ビット消去
		self.bitStat = 0x00
		self.ALLOFF()

	def ON(self, no):
		if type(no) != list:
			no = [no]
		for bit in no:
			self.bitStat = self.bitStat | (0x01 << bit)
		self.I2C.write_byte_data(DEV_ADR, REG_GPIO, ~self.bitStat)
		
	def OFF(self, no):
		if type(no) != list:
			no = [no]
		for bit in no:
			self.bitStat = self.bitStat & ~(0x01 << bit)
		self.I2C.write_byte_data(DEV_ADR, REG_GPIO, ~self.bitStat)
		
	def ALLOFF(self):
		self.bitStat = 0x00
		self.I2C.write_byte_data(DEV_ADR, REG_GPIO, ~self.bitStat)

	def close(self):
		self.ALLOFF()
		GPIO.cleanup()

	def readDeviceStat(self):
		# データRead
		byteData = self.I2C.read_byte_data(DEV_ADR, REG_GPIO)
		return byteData

#/////////////////////////////////////////////////////////
if __name__ == '__main__':
	
	i2cExpanda = MCP23008()
	for ot in range(8):
		i2cExpanda.ON(ot)
		print(hex(i2cExpanda.readDeviceStat()).upper())
		time.sleep(2)
		i2cExpanda.OFF(ot)

	i2cExpanda.ON([0,1,2,3,4,5,6,7])
	time.sleep(2)
	i2cExpanda.OFF([1,3,5,7])
	time.sleep(2)
	i2cExpanda.ALLOFF()
	i2cExpanda.ON([0,1,2,3])
	time.sleep(2)
	i2cExpanda.ALLOFF()
	i2cExpanda.ON([4,5,6,7])
	time.sleep(2)
	i2cExpanda.close()

・SPIによるLEDアレイ点灯モジュール(SPI_EXPANDA.py)

import RPi.GPIO as GPIO
import time

# ピンの名前を変数として定義
SPICLK = 11
SPIMOSI = 10
SPIMISO = 9
SPICS = 8
DEV_RESET = 5

REG_IODIR = 0x00	# I/O方向レジスタ
REG_GPIO = 0x09		# PORT レジスタ(入出力)
REG_IOCON = 0x05	# 設定レジスタ
DEV_ADR = 0x00		# Device Address(A1=0, A0=0)

#=================================================================
class MCP23S08:
	def __init__(self):
		# SPIの初期化とMC23S08デバイス設定
		GPIO.setmode(GPIO.BCM)
		GPIO.setwarnings(False)
		GPIO.setup(SPICLK, GPIO.OUT)
		GPIO.setup(SPIMOSI, GPIO.OUT)
		GPIO.setup(SPIMISO, GPIO.IN)
		GPIO.setup(SPICS, GPIO.OUT, initial=GPIO.HIGH)	#CS Not Select
		GPIO.setup(DEV_RESET, GPIO.OUT, initial=GPIO.HIGH)	# Device Reset = 0
		# デバイスのリセット
		GPIO.output(DEV_RESET, GPIO.LOW)	# Device Reset = 0
		time.sleep(0.01)
		GPIO.output(DEV_RESET, GPIO.HIGH)
		# デバイスの初期設定
		self.writeDevice(REG_IODIR, 0x00)	# IODIRレジスタ:データI/Oを出力に設定
		self.writeDevice(REG_IOCON, 0x38)	# IOCONレジスタ(シーケンシャル禁止、アドレスピン許可)に設定
		# 全ビット消去
		self.bitStat = 0x00
		self.ALLOFF()

	def ON(self, no):
		if type(no) != list:
			no = [no]
		for bit in no:
			self.bitStat = self.bitStat | (0x01 << bit)
		self.writeDevice(REG_GPIO, ~self.bitStat)
		
	def OFF(self, no):
		if type(no) != list:
			no = [no]
		for bit in no:
			self.bitStat = self.bitStat & ~(0x01 << bit)
		self.writeDevice(REG_GPIO, ~self.bitStat)
		
	def ALLOFF(self):
		self.bitStat = 0x00
		self.writeDevice(REG_GPIO, ~self.bitStat)
		
	def close(self):
		self.ALLOFF()
		GPIO.cleanup()

	#====== Read/Write I/O Data========
	def readDeviceStat(self):
		# Read Mode 設定
		readRegister = [0x41 | (DEV_ADR << 1), REG_GPIO]	# Read Mode & Register
		GPIO.output(SPICS, GPIO.LOW)		# CS Active
		self.sendData(readRegister)
		# データRead
		bitData = 0
		for bt in range(8):		# MSBから8ビット受信
			GPIO.output(SPICLK, GPIO.HIGH)
			bitData <<= 1
			bitData |= GPIO.input(SPIMISO)
			GPIO.output(SPICLK, GPIO.LOW)
		GPIO.output(SPICS, GPIO.HIGH)		#CS Stand-By	
		return bitData

	#====== Write I/O Data ========
	def writeDevice(self, regNo, byteData):
		# Write Mode & Register & Data 設定
		writeRegData = [0x40 | (DEV_ADR << 1), regNo, byteData]
		GPIO.output(SPICS, GPIO.LOW)		# CS Active
		self.sendData(writeRegData)
		GPIO.output(SPICS, GPIO.HIGH)		#CS Stand-By
		return
		
	#====== Send Data To Device========
	def sendData(self, byteData):
		for outBit in byteData:
			for bt in range(8):		# MSBから8ビット送信
				GPIO.output(SPICLK, GPIO.LOW)
				GPIO.output(SPIMOSI,(outBit >> (7 - bt)) & 0x01)
				GPIO.output(SPICLK, GPIO.HIGH)

#/////////////////////////////////////////////////////////
if __name__ == '__main__':
	
	spiExpanda = MCP23S08()
	for ot in range(8):
		spiExpanda.ON(ot)
		print(hex(spiExpanda.readDeviceStat().upper())
		time.sleep(2)
		spiExpanda.OFF(ot)

	spiExpanda.ON([0,1,2,3,4,5,6,7])
	time.sleep(2)
	spiExpanda.OFF([1,3,5,7])
	time.sleep(2)
	spiExpanda.ALLOFF()
	spiExpanda.ON([0,1,2,3])
	time.sleep(2)
	spiExpanda.ALLOFF()
	spiExpanda.ON([4,5,6,7])
	time.sleep(2)
	spiExpanda.ALLOFF()
	spiExpanda.close()
	

●プログラム実行結果

I2C接続例

I2C-8ビットI/Oエクスパンダを利用したLEDアレイ点灯

SPI接続

I2C-8ビットI/Oエクスパンダを利用したLEDアレイ点灯