0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MaixCubeのハードウェア調査

Posted at

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()


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?