MaixCubeのハードウェアについて
回路図 https://dl.sipeed.com/MAIX/HDK/Sipeed-Maix-Cube/Maix-Cube-2757/Maix-Cube-2757(Schematic).pdf
前面のLED
2個ついているが、同時に点灯する。レバースイッチの位置でR、G、Bそれぞれに点灯させるサンプル
import utime
from Maix import GPIO
from board import board_info
from fpioa_manager import fm
LED_R = 13
LED_G = 12
LED_B = 14
fm.register(LED_R, fm.fpioa.GPIOHS0, force=True)
fm.register(LED_G, fm.fpioa.GPIOHS1, force=True)
fm.register(LED_B, fm.fpioa.GPIOHS2, force=True)
fm.register(board_info.PIN11, fm.fpioa.GPIO0, force=True)
fm.register(board_info.PIN10, fm.fpioa.GPIO1, force=True)
fm.register(board_info.BOOT_KEY, fm.fpioa.GPIO2, force=True)
led_r = GPIO(GPIO.GPIOHS0, GPIO.OUT)
led_g = GPIO(GPIO.GPIOHS1, GPIO.OUT)
led_b = GPIO(GPIO.GPIOHS2, GPIO.OUT)
input0 = GPIO(GPIO.GPIO0, GPIO.IN)
input1 = GPIO(GPIO.GPIO1, GPIO.IN)
input2 = GPIO(GPIO.GPIO2, GPIO.IN)
i = 0
status = 0
while i<20:
print("-----input0:", input0.value())
print("-----input1:", input1.value())
print("-----input2:", input2.value())
led_r.value(input0.value())
led_g.value(input1.value())
led_b.value(input2.value())
i+=1
utime.sleep_ms(500)
fm.unregister(board_info.LED_R, fm.fpioa.GPIOHS0)
fm.unregister(board_info.LED_G, fm.fpioa.GPIOHS1)
fm.unregister(board_info.LED_B, fm.fpioa.GPIOHS2)
fm.unregister(board_info.PIN11, fm.fpioa.GPIO0)
fm.unregister(board_info.PIN10, fm.fpioa.GPIO1)
fm.unregister(board_info.BOOT_KEY, fm.fpioa.GPIO2)
背面のフラッシュLED
かなり明るい
import utime
from Maix import GPIO
from board import board_info
from fpioa_manager import fm
WLED_EN = 32
fm.register(WLED_EN, fm.fpioa.GPIOHS0, force=True)
fm.register(board_info.PIN10, fm.fpioa.GPIO0, force=True)
wled_en = GPIO(GPIO.GPIOHS0, GPIO.OUT)
input = GPIO(GPIO.GPIO0, GPIO.IN)
i = 0
status = 0
while i<20:
print("-----input:", input.value())
wled_en.value(input.value())
i+=1
utime.sleep_ms(500)
fm.unregister(WLED_EN, fm.fpioa.GPIOHS0)
fm.unregister(board_info.PIN10, fm.fpioa.GPIO0)
3軸加速度センサー (MSA301)
import time
from machine import I2C
MSA301_CMD = 0
MSA301_DATA = 1
MSA301_ADDR = 0x26
def acc_init(i2c):
partID = i2c.readfrom_mem(MSA301_ADDR, 0x01, 1, mem_size=8)
if (partID != b'\x13'):
print("MSA301 not found")
i2c.writeto_mem(MSA301_ADDR, 0x11, 0x0E, mem_size=8) # power_mode: normal
def acc_read(i2c):
accX = i2c.readfrom_mem(MSA301_ADDR, 0x02, 2, mem_size=8)
accY = i2c.readfrom_mem(MSA301_ADDR, 0x04, 2, mem_size=8)
accZ = i2c.readfrom_mem(MSA301_ADDR, 0x06, 2, mem_size=8)
print("x=", int.from_bytes(accX, 'little') / 4,
"y=", int.from_bytes(accY, 'little') / 4,
"z=", int.from_bytes(accZ, 'little') / 4)
i2c = I2C(I2C.I2C0, mode=I2C.MODE_MASTER, freq=400000, scl=30, sda=31, addr_size=7)
time.sleep(1)
acc_init(i2c)
while True:
acc_read(i2c)
time.sleep(1)
電源管理 (AXP173)
takeruさんのコードを参考にさせて頂きました。
# M5StickVの電源管理方法
# https://github.com/sipeed/MaixPy/blob/master/components/boards/m5stick/src/m5stick.c
# https://github.com/sipeed/MaixPy/blob/master/projects/maixpy_m5stickv/builtin_py/pmu.py
# https://pdf1.alldatasheet.com/datasheet-pdf/view/757469/ETC2/AXP173.html
# 参考: M5StickC https://github.com/m5stack/M5StickC/blob/master/src/AXP173.cpp
from machine import I2C, Timer
import machine
import lcd
# import pmu
class PMUError(Exception):
pass
class NotFoundError(PMUError):
pass
class OutOfRange(PMUError):
pass
def __chkPwrKeyWaitForSleep__(timer):
global __pmuI2CDEV__, __preButPressed__ #<- Do not do this :(
__pmuI2CDEV__.writeto(52, bytes([0x46]))
pek_stu = (__pmuI2CDEV__.readfrom(52, 1))[0]
__pmuI2CDEV__.writeto_mem(52, 0x46, 0xFF, mem_size=8) #Clear IRQ
#Prevent loop in restart, wait for release
if __preButPressed__ == -1 and ((pek_stu & (0x01 << 1)) or (pek_stu & 0x01)):
return
if __preButPressed__ == -1 and ((pek_stu & (0x01 << 1)) == False and (pek_stu & 0x01) == False):
__preButPressed__ = 0
if (pek_stu & 0x01):
__pmuI2CDEV__.writeto_mem(52, 0x31, 0x0F, mem_size=8) #Enable Sleep Mode
__pmuI2CDEV__.writeto_mem(52, 0x12, 0x00, mem_size=8) #Turn off other power source
if (pek_stu & (0x01 << 1)):
machine.reset()
class axp173():
def __init__(self, i2cDev=None):
if i2cDev == None:
try:
self.i2cDev = I2C(I2C.I2C0, freq=400000, scl=30, sda=31)
except:
raise PMUError("Unable to init I2C0 as Master")
else:
self.i2cDev = i2cDev
self.axp173Addr = 52
global __pmuI2CDEV__, __preButPressed__
__pmuI2CDEV__ = self.i2cDev
__preButPressed__ = -1
scanList = self.i2cDev.scan()
if self.axp173Addr not in scanList:
raise NotFoundError
def __writeReg(self, regAddr, value):
self.i2cDev.writeto_mem(self.axp173Addr, regAddr, value, mem_size=8)
def __readReg(self, regAddr):
self.i2cDev.writeto(self.axp173Addr, bytes([regAddr]))
return (self.i2cDev.readfrom(self.axp173Addr, 1))[0]
def enableADCs(self, enable):
if enable == True:
self.__writeReg(0x82, 0xFF)
else:
self.__writeReg(0x82, 0x00)
def enableCoulombCounter(self, enable):
if enable == True:
self.__writeReg(0xB8, 0x80)
else:
self.__writeReg(0xB8, 0x00)
def stopCoulombCounter(self):
self.__writeReg(0xB8, 0xC0)
def clearCoulombCounter(self):
self.__writeReg(0xB8, 0xA0)
def __getCoulombChargeData(self):
CoulombCounter_LSB = self.__readReg(0xB0)
CoulombCounter_B1 = self.__readReg(0xB1)
CoulombCounter_B2 = self.__readReg(0xB2)
CoulombCounter_MSB = self.__readReg(0xB3)
return ((CoulombCounter_LSB << 24) + (CoulombCounter_B1 << 16) + \
(CoulombCounter_B2 << 8) + CoulombCounter_MSB)
def __getCoulombDischargeData(self):
CoulombCounter_LSB = self.__readReg(0xB4)
CoulombCounter_B1 = self.__readReg(0xB5)
CoulombCounter_B2 = self.__readReg(0xB6)
CoulombCounter_MSB = self.__readReg(0xB7)
return ((CoulombCounter_LSB << 24) + (CoulombCounter_B1 << 16) + \
(CoulombCounter_B2 << 8) + CoulombCounter_MSB)
def getCoulombCounterData(self):
return 65536 * 0.5 * (self.__getCoulombChargeData() -\
self.__getCoulombDischargeData) / 3600.0 / 25.0
def getVbatVoltage(self):
Vbat_LSB = self.__readReg(0x78)
Vbat_MSB = self.__readReg(0x79)
return ((Vbat_LSB << 4) + Vbat_MSB) * 1.1 #AXP173-DS PG26 1.1mV/div
def getUSBVoltage(self):
Vin_LSB = self.__readReg(0x56)
Vin_MSB = self.__readReg(0x57)
return ((Vin_LSB << 4) + Vin_MSB) * 1.7 #AXP173-DS PG26 1.7mV/div
def getUSBInputCurrent(self):
Iin_LSB = self.__readReg(0x58)
Iin_MSB = self.__readReg(0x59)
return ((Iin_LSB << 4) + Iin_MSB) * 0.625 #AXP173-DS PG26 0.625mA/div
def getConnextVoltage(self):
Vcnx_LSB = self.__readReg(0x5A)
Vcnx_MSB = self.__readReg(0x5B)
return ((Vcnx_LSB << 4) + Vcnx_MSB) * 1.7 #AXP173-DS PG26 1.7mV/div
def getConnextInputCurrent(self):
IinCnx_LSB = self.__readReg(0x5C)
IinCnx_MSB = self.__readReg(0x5D)
return ((IinCnx_LSB << 4) + IinCnx_MSB) * 0.625 #AXP173-DS PG26 0.625mA/div
def getBatteryChargeCurrent(self):
Ichg_LSB = self.__readReg(0x7A)
Ichg_MSB = self.__readReg(0x7B)
return ((Ichg_LSB << 5) + Ichg_MSB) * 0.5 #AXP173-DS PG27 0.5mA/div
def getBatteryDischargeCurrent(self):
Idcg_LSB = self.__readReg(0x7C)
Idcg_MSB = self.__readReg(0x7D)
return ((Idcg_LSB << 5) + Idcg_MSB) * 0.5 #AXP173-DS PG27 0.5mA/div
def getBatteryInstantWatts(self):
Iinswat_LSB = self.__readReg(0x70)
Iinswat_B2 = self.__readReg(0x71)
Iinswat_MSB = self.__readReg(0x72)
#AXP173-DS PG32 0.5mA*1.1mV/1000/mW
return ((Iinswat_LSB << 16) + (Iinswat_B2 << 8) + Iinswat_MSB) * 1.1 * 0.5 / 1000
def getTemperature(self):
Temp_LSB = self.__readReg(0x5E)
Temp_MSB = self.__readReg(0x5F)
#AXP173-DS PG26 0.1degC/div -144.7degC Biased
return (((Temp_LSB << 4) + Temp_MSB) * 0.1) - 144.7
def setK210Vcore(self, vol):
if vol > 1.05 or vol < 0.8:
raise OutOfRange("Voltage is invaild for K210")
DCDC2Steps = int((vol - 0.7) * 1000 / 25)
self.__writeReg(0x23, DCDC2Steps)
def getKeyStuatus(self): # -1: NoPress, 1: ShortPress, 2:LongPress
but_stu = self.__readReg(0x46)
if (but_stu & (0x1 << 1)):
return 1
else:
if (but_stu & (0x1 << 0)):
return 2
else:
return -1
def setEnterSleepMode(self):
self.__writeReg(0x31, 0x0F) #Enable Sleep Mode
self.__writeReg(0x12, 0x00) #Turn off other power source
def enablePMICSleepMode(self, enable):
if enable == True:
self.__writeReg(0x36, 0x27) #Turnoff PEK Overtime Shutdown
self.__writeReg(0x46, 0xFF) #Clear the interrupts
self.butChkTimer = Timer(Timer.TIMER2, Timer.CHANNEL0, mode=Timer.MODE_PERIODIC, period=500, callback=__chkPwrKeyWaitForSleep__)
else:
self.__writeReg(0x36, 0x6C) #Set to default
try:
self.butChkTimer.stop()
del self.butChkTimer
except:
pass
class App():
def main(self):
self.setup()
while(True):
self.loop()
def setup(self):
lcd.init(freq=15000000, type=2)
lcd.rotation(2)
self.counter = 0
self.axp173 = axp173()
self.axp173.enableADCs(True)
self.axp173.enableCoulombCounter(True)
self.printRegs()
# LCDの明るさ
# self.axp173.__writeReg(0x91, 0x80) # 上位4bit 7から15
# # self.axp173.setScreenBrightness(7) # <- 0x28じゃなくて0x91が正しい https://github.com/sipeed/MaixPy/pull/153
# バッテリ充電ON/OFF https://twitter.com/michan06/status/1168104180445106180
reg0x33 = self.axp173.__readReg(0x33)
reg0x33 |= (1<<7) # ON
#reg0x33 &= ~(1<<7) # OFF
self.axp173.__writeReg(0x33, reg0x33)
# REG 33H:充電制御1
# デフォルト:C8H
#
# bit7 充電機能により、内部および外部チャネルを含む制御ビットが可能 0:オフ、1:オン
# bit6:5 充電目標電圧設定
# 00:4.1V;
# 01:4.15V;
# 10:4.2V;
# 11:4.36V
# bit4 充電終了電流設定
# 0:充電電流が設定値の10%未満になったら充電を終了
# 1:充電電流が設定値の15%未満になったら充電を終了します
# bit3-0 内部パス充電電流設定 default=1000(780mA)
# 0000: 100 mA; 0001: 190 mA; 0010: 280 mA; 0011: 360 mA;
# 0100: 450 mA; 0101: 550 mA; 0110: 630 mA; 0111: 700 mA;
# 1000: 780 mA; 1001: 880 mA; 1010: 960 mA; 1011:1000 mA;
# 1100:1080 mA; 1101:1160 mA; 1110:1240 mA; 1111:1320 mA;
# 0xC0(0b11000000) なら「充電オン、充電目標電圧=4.2V、充電終了電流=10%、充電電流=100mA」
reg0x33 = self.axp173.__readReg(0x33)
reg0x33 = (reg0x33 & 0xF0) | 0x01 # 200mA
self.axp173.__writeReg(0x33, reg0x33)
# REG 34H:充電制御2
# デフォルト:41H
# 7 プリチャージタイムアウト設定Bit1
# 00:30分; 01:40分;
# 10:50分; 11:60分
# 6 プリチャージタイムアウト設定Bit0
# 5-3 外部パス充電電流設定範囲300-1000mA、100mA /ステップ、デフォルト300mA
# 2 充電中の外部パスイネーブル設定0:オフ; 1:オープン
# 1 定電流モードでのタイムアウト設定Bit1 00:7時間; 01:8時間; 10:9時間; 11:10時間RW0
# 0 定電流モードでのタイムアウト設定Bit0
# REG 01H:電源装置の動作モードと充電状態の表示
# 0x70なら「温度超過なし、充電中、バッテリーあり、バッテリーアクティベーションモードに入っていない、実際の充電電流は予想電流と等しい、モードA」
#
# bit7 AXP173が過熱しているかどうかを示します 0:温度超過なし; 1:温度超過
# bit6 充電表示 0:充電していない、または充電が完了している、 1:充電中
# bit5 バッテリーの存在表示 0:バッテリーはAXP173に接続されていません; 1:バッテリーはAXP173に接続されていま
# bit4 予約済み、変更不可
# bit3 バッテリーがアクティブモードかどうかを示します 0:バッテリーアクティベーションモードに入っていない; 1:バッテリーアクティベーションモードに入っている
# bit2 充電電流が目的の電流よりも小さいかどうかを示します 0:実際の充電電流は予想電流と等しい; 1:実際の充電電流は予想電流よりも小さい
# bit1 AXP173スイッチモード表示 0:モードA; 1:モードB
# bit0 予約済み、変更不可
# self.axp173.setK210Vcore(0.8)
def loop(self):
self.printRegs()
self.counter += 1
print("counter=%04d vbat=%6.1fmV USB=%6.1fmV,%5.1fmA EX=%6.1fmV,%5.1fmA Bat=+%5.1fmA,-%5.1fmA,%5.1fmW %4.1fC" % (
self.counter,
self.axp173.getVbatVoltage(),
self.axp173.getUSBVoltage(),
self.axp173.getUSBInputCurrent(),
self.axp173.getConnextVoltage(),
self.axp173.getConnextInputCurrent(),
self.axp173.getBatteryChargeCurrent(),
self.axp173.getBatteryDischargeCurrent(),
self.axp173.getBatteryInstantWatts(),
self.axp173.getTemperature()
))
lcd.clear(lcd.BLACK)
lcd.draw_string(2, 5, "hello maixpy %d" % (self.counter), lcd.WHITE, lcd.RED)
lcd.draw_string(2, 20, "vbat=%.1fmV" % (self.axp173.getVbatVoltage()), lcd.WHITE, lcd.BLUE)
lcd.draw_string(2, 35, "USB=%.1fmV,%.1fmA" % (self.axp173.getUSBVoltage(), self.axp173.getUSBInputCurrent()), lcd.GREEN, lcd.BLACK)
lcd.draw_string(2, 50, "EX=%.1fmV,%.1fmA" % (self.axp173.getConnextVoltage(), self.axp173.getConnextInputCurrent()), lcd.WHITE, lcd.BLACK)
lcd.draw_string(2, 65, "Bat=+%.1fmA,-%.1fmA,%.1fmW" % (
self.axp173.getBatteryChargeCurrent(),
self.axp173.getBatteryDischargeCurrent(),
self.axp173.getBatteryInstantWatts()),
lcd.BLACK, lcd.YELLOW)
lcd.draw_string(2, 80, "%.1fC" % (self.axp173.getTemperature()), lcd.RED, lcd.WHITE)
time.sleep(1)
#if self.counter % 5 == 0 and self.axp173.getBatteryChargeCurrent() < 15.0:
# self.resetCharge()
# VBatの計算あってる?
#reg0x78 = self.axp173.__readReg(0x78)
#reg0x79 = self.axp173.__readReg(0x79)
#print("reg0x78=%02X reg0x79=%02X" % (reg0x78, reg0x79))
#vbat = (reg0x78 << 4) + reg0x79
#print(vbat, vbat*1.1)
def printRegs(self):
s = ""
for addr in [0x28, 0x12, 0x33, 0x34, 0x01]:
value = self.axp173.__readReg(addr)
s += 'REG{:02X}H=0x{:02X} ({:08b}) '.format(addr, value, value)
print(s)
def resetCharge(self):
print("*** resetCharge ***")
reg0x33 = self.axp173.__readReg(0x33)
reg0x33 = (reg0x33 & 0xF0) | 0x01 # 200mA
reg0x33 &= ~(1<<7) # OFF
self.axp173.__writeReg(0x33, reg0x33)
reg0x33 = self.axp173.__readReg(0x33)
print("reg0x33=%02X" % (reg0x33))
time.sleep(1)
reg0x33 = self.axp173.__readReg(0x33)
reg0x33 |= (1<<7) # ON
self.axp173.__writeReg(0x33, reg0x33)
reg0x33 = self.axp173.__readReg(0x33)
print("reg0x33=%02X" % (reg0x33))
App().main()