オンボードMCU

Robot HATは、ArteryのAT32F415CBT7マイクロコントローラーを搭載しています。これは、最大クロック周波数が150MHzのARM Cortex-M4プロセッサーです。マイクロコントローラーには、256KBのフラッシュメモリと32KBのSRAMがあります。

オンボードのPWMとADCは、マイクロコントローラによって駆動されます。Raspberry Piとマイクロコントローラ間の通信は、I2Cインターフェイスを通じて確立されます。通信に使用されるI2Cアドレスは0x14(7ビットアドレス形式)です。

紹介

オンボードMCUのRESETピンは、Raspberry PiのGPIO 5、または robot_hat.PinMCURST に接続されています。MCUは7ビットアドレスの 0x14 を使用しています。

ADC

レジスタアドレスは3バイトで、0x170000から0x140000までがADCチャンネル0から3です。ADCの精度は12ビットで、値は0から4095までです。robot_hat.ADC で詳細を確認してください。

アドレス

説明

0x170000

ADCチャンネル0

0x160000

ADCチャンネル1

0x150000

ADCチャンネル2

0x140000

ADCチャンネル3

0x130000

ADCチャンネル4(バッテリーレベル)

例:

チャンネル0のADC値を読む:

from smbus import SMBus
bus = SMBus(1)

# smbus only support 8 bit register address, so write 2 byte 0 first
bus.write_word_data(0x14, 0x17, 0)
msb = bus.read_byte(0x14)
lsb = bus.read_byte(0x14)
value = (msb << 8) | lsb

PWM

PWMは1バイトのレジスタと2バイトの値を持っています。

PWM周波数の変更

周波数はプリスケーラと周期で定義されます。

周波数を設定するには、まず設定したい周期を定義する必要があります。Arduinoでは通常255、PCA9685では4095です。

CPUクロックは72MHzです。そこから、希望の周波数に応じたプリスケーラを計算できます

プリスケーラ = 72MHz / (周期 + 1) / 周波数 - 1

周期にこだわらない場合は、周波数から周期とプリスケーラの両方を計算する方法があります。 robot_hat.PWM.freq() を参照してください。

パルス幅

チャンネルのパルス幅を制御するのは簡単で、値をレジスタに書き込むだけです。

しかし 値とは何か?PWMを50%のパルス幅に設定したい場合、周期が正確に何であるかを知る必要があります。上記の計算に基づき、周期を4095に設定した場合、パルス値を2048に設定すると、約50%のパルス幅になります。

アドレス

説明

0x20

PWMチャンネル0 オン値 を設定

0x21

PWMチャンネル1 オン値 を設定

0x22

PWMチャンネル2の オン値 を設定

0x23

PWMチャンネル3の オン値 を設定

0x24

PWMチャンネル4の オン値 を設定

0x25

PWMチャンネル5の オン値 を設定

0x26

PWMチャンネル6の オン値 を設定

0x27

PWMチャンネル7の オン値 を設定

0x28

PWMチャンネル8の オン値 を設定

0x29

PWMチャンネル9の オン値 を設定

0x2A

PWMチャンネル10の オン値 を設定

0x2B

PWMチャンネル11の オン値 を設定

0x2C

モーター2の速度 オン値 を設定

0x2D

モーター1の速度 オン値 を設定

プリスケーラー

0x40から始まるレジスタはPWMプリスケーラーを設定するためのもので、範囲は0〜65535です。全14チャンネルに対してタイマーは4つのみです。 PWMタイマー(重要) を参照してください。

アドレス

説明

0x40

タイマー0の プリスケーラー を設定

0x41

タイマー1の プリスケーラー を設定

0x42

タイマー2の プリスケーラー を設定

0x43

タイマー3の プリスケーラー を設定

周期

0x44から始まるレジスタはPWM周期を設定するためのもので、範囲は0〜65535です。全14チャンネルに対してタイマーは4つのみです。 PWMタイマー(重要) を参照してください。

アドレス

説明

0x44

タイマー0の 周期 を設定

0x45

タイマー1の 周期 を設定

0x46

タイマー2の 周期 を設定

0x47

タイマー3の 周期 を設定

PWMタイマー(重要)

PWMタイマーとは何ですか?PWMタイマーは、PWMチャンネルをオン・オフするためのツールです。

MCUにはPWM用のタイマーが4つしかありません:つまり、同じタイマーで異なるチャンネルの周波数を設定することはできません。

例:チャンネル0に周波数を設定すると、チャンネル1、2、3に影響が及びます。チャンネル2の周波数を変更すると、チャンネル0、1、3が上書きされます。

これは、常に周波数を変更するパッシブブザーと固定周波数50Hzが必要なサーボを同時に制御したい場合のような状況です。この場合、それらを2つの異なるタイマーに分けるべきです。

タイマー

PWMチャンネル

タイマー0

0, 1, 2, 3

タイマー1

4, 5, 6, 7

タイマー2

8, 9, 10, 11

タイマー3

12, 13(モーター用)

from smbus import SMBus
bus = SMBus(1)

# Set timer 0 period to 4095
bus.write_word_data(0x14, 0x44, 4095)
# Set frequency to 50Hz,
freq = 50
# Calculate prescaler
prescaler = int(72000000 / (4095 + 1) / freq) - 1
# Set prescaler
bus.write_word_data(0x14, 0x40, prescaler)

# Set channel 0 to 50% pulse width
bus.write_word_data(0x14, 0x20, 2048)

MCUをリセット

現在のファームウェアは固定3バイトの値を読み取り、その後ADC値を返すかPWMを制御できます。そのためADCレジスタは最後の2バイトが0の3バイトが必要です。

そして、通信の途中でプログラムが中断されると、ファームウェアが固まってデータがずれる可能性があります。3バイトのデータ待ちにはタイムアウトも設定しています。

そのような場合は、MCUをリセットする必要があります。リセットするには、robot_hatコマンドを使用できます:

robot_hat reset_mcu

または、Pythonコードで行うこともできます:

from robot_hat import reset_mcu
reset_mcu()

あるいは、リセットピン(GPIO 5)を10ms引き下げてから、さらに10ms引き上げるだけで、それが reset_mcu が行うことです。

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.OUT)
GPIO.output(5, GPIO.LOW)
time.sleep(0.01)
GPIO.output(5, GPIO.HIGH)
time.sleep(0.01)