コンテンツにスキップ

#612 JetRacerコントロールボード

Model Number Revison Description
--- 3.0.8 Jetson Orin Nano専用
JRB-CB3 3.0.8 B Jetson Nanoに対応

Rev3.0.4と主な変更点

追加

RCカーが電源ON時に、マルチプレクサへの信号を停止機能追加。

変更

受信機、サーボおよびESCの接続、逆接続防止のケーブルコネクタに変更。

削除

ブラシレスモータのセンサーを回転数計測削除。

9軸センサーBNO055を削除。

動作環境

Jetson Orin Nano 8GB 開発者キット および Jetson Nano 4GB開発者キット

JetRacerコントロールボード Rev2.0.21,Rev2.0.23,Rev2.0.28,Rev2.0.29にある固定する切り替えスイッチがありません。必要に応じてお客様が追加でファームウェアを変更し切り替えてください。

マイコンボードのファームウェアは焼き込み済みです。XIAOのWi-Fiアンテナは使用しません。

ファインスペック2.4G 電動RCドライブセット(45053)のみ動作確認済み。ただし、受信機とESCが一体型になっているモデルは、使用不可。

名称と役割

コントロール基板のオレンジ色LED

RCカーの電源がONになった時は、コントローラーボードにあるオレンジ色のLEDが発光します。RCの電圧レベルが低下した時、暗くなります。

コントロール基板カラーLED

カラーLED 色  状態 
ブルー 受信機から信号がない
グリーン プロポ操作可能
マゼンタ 自動走行可能

XIAO ESP32-S3

脱着可能です。ファームウェアは焼き込まれています。ファームウェア書き換え時は取り外してファームウェアを更新してください。

Version 1.1.5(Release 2024/12/25)

https://github.com/FaBoPlatform/FaBo/tree/master/0612_jetracer/arduino/firmware/Firmware%20_ESP32S3/esp32s3

各コネクタ

受信機、ESC,サーボ取り付けはつめがあるのに対しては逆接続は防げますが、爪のないコネクタは防げません。ご注意ください。

コントロールボード接続例

受信機の接続 受信機1の場合は、基板1ch、受信機2の場合は、基板2ch、受信機Bの場合は、基板3ch。

サーボとの接続は、基板Servo、ESCとの接続は基板ESCに接続します。4pinコネクタを使い、#405 JetRacer LEDの接続は、基板SPI-LEDコネクタに接続します。ドーターであるLED基板の方をINPUT側に接続します。

ズレて接続に注意

コントロール基板とJetsonを接続するときは、ズレて挿入していないか確認してから電源を入れましょう。故障の原因となります。

逆接続に注意

サーボ変換ケーブルまたは、爪のないサーボケーブルご使用で、3ピンコネクタの逆接続は破損の原因となります。電源投入前に確認しましょう。

基板接続の注意

コントロール基板の受信機のオスコネクタとコントロール基板のESCメスコネクタまたはサーボメスコネクタ通しの接続は故障の原因となりますのでご注意ください。

ブロック図

I/O

GNDは、JetsonとRCカーいずれも共通

I2Cポートピンアサイン

※B04B-PASK-1使用

Pin Number Function Description I/O
1 GND Common Ground
2 VCC Jetson Power(5V) Power
3 SDA Jetson I2Cデータ(3.3V) I/O
4 SCL Jetson I2Cクロック(3.3V) I/O

*I2Cのバス番号はJetson Nanoは1、Jetson Orin Nanoは7

FaBo i2c Brick 9軸加速度センサーを使用した例

SPI-LEDポートピンアサイン

※B04B-PASK-1使用

Pin Number Function Description I/O
1 GND Common Ground
2 VCC Jetson Power(5V) Power
3 CLK XIAO ESP32-S3 SCK(5V) OUTPUT
4 DATA XIAO ESP32-S3 MOSI(5V) OUTPUT

FaBo #405 JetRacer LEDを複数接続。

ESP32-S3コネクタのピンアサイン

XIAO接続

取り付け方法をお間違えなくようにご確認ください。

電圧レベル

本基板から出力されるPWMの電圧レベル(ST,TH)は3Vレベルになります。

GNDに関して

本基板は、JetsonのGNDとRCカーのGNDは接続されております。

PCA9685の外部水晶発振器について

FaBoのコントロール基板にあるPCA9685のすぐ横に外部の水晶発振器25MHzがありこちらの発振を使用しますとPCA9685の内部発振器よりタイミングのズレが少なく、周囲温度環境や電圧に影響を受けにくい正確な発振が得られます。(デフォルトでは無効になっています。)

このことによりステアリング量、スロットル量が安定化します。また、スロットルの中央値も安定化することにより車体にブレーキ信号からバック信号へ切り替えがより安定的になります。

一旦下記のコードを実行すると電源が切れるまで外部発振器が優先され内部発振には設定できません。ご注意ください。

サンプルコード

Fabo_PCA9685クラスをオーバーライドして組み込みます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#FaBo JetRacer REV3.0.8 25MHz外部発振器サンプルコード

import Fabo_PCA9685

class pca9685CLK(Fabo_PCA9685.PCA9685):
    EXTCLK = 0x40
    def Set_hz(self, hz):
            self.PWM_HZ = hz
            prescale=self.calc_prescale(hz)
            '''
            Hz設定。レジスタに書き込む値はprescaleの値となる
            prescale = calc_prescale(hz)
            '''
            oldmode = self.bus.read_byte_data(self.PCA9685_ADDRESS,self.MODE1)
            newmode = oldmode | self.SLEEP

            # スリープにする
            self.bus.write_byte_data(self.PCA9685_ADDRESS, self.MODE1, newmode)
            # 外部発振を有効化する。(新規追加)
            self.bus.write_byte_data(self.PCA9685_ADDRESS, self.MODE1, self.SLEEP | self.EXTCLK) 
            #周波数を設定
            self.bus.write_byte_data(self.PCA9685_ADDRESS, self.PRE_SCALE, prescale)
            #スリープを解除
            self.bus.write_byte_data(self.PCA9685_ADDRESS, self.MODE1, oldmode)
            time.sleep(self.WAIT_TIME)
            # リスタートする(必須)
            self.bus.write_byte_data(self.PCA9685_ADDRESS, self.MODE1, (oldmode | self.RESTART))  

続いてインスタンスのコード

ステアリングの中央値は車体ごとにエンドポイントを調整します。 60Hzのサーボ使用 Jetson Orin Nanoではi2cバスを7、Jetson Nanoは1を使用してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import time
import pkg_resources
import smbus
import time
import json


INITIAL_VALUE = 373
pwm_center = INITIAL_VALUE
pwm_right = INITIAL_VALUE + 100
pwm_left = INITIAL_VALUE - 100
pwm_stop = INITIAL_VALUE

SMBUS='smbus'
BUSNUM=7 #jetson Nanoは1
SERVO_HZ=60
bus = smbus.SMBus(BUSNUM)
PCA9685 = pca9685CLK(bus,INITIAL_VALUE,address=0x40)
PCA9685.Set_hz(SERVO_HZ)
一般的なサーボ周波数は60HzでPCA9685のPWM解像度(12ビット)は4096になります。そのため1ビットあたりの時間は約4.069uSになり 想定しているサーボ、ESCの中立の状態は1520uSであるので1520/4.069=約373となります。 あらかじめ、プロポのトリムを調整した状態でキャリブレーションお願いいたします。 ※無理な設定は故障の原因となる場合がありますのでご注意ください。 ※必ず車体は作業台の上もしくは安全を確保した状態で実行してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# PWMキャリブレーション プロポを動かさないでください。
data1 = bus.read_i2c_block_data(0x08, 0x01, 12)
raw1 = data1[0] << 24 | data1[1] << 16 | data1[2] << 8| data1[3]
raw2 = data1[4] << 24 | data1[5] << 16 | data1[6] << 8| data1[7]
raw3 = data1[8] << 24 | data1[9] << 16 | data1[10] << 8| data1[11]
print('Wave Length st {}(uS),th {}(uS),sw {}(uS)'.format(raw1,raw2,raw3))
#プロポの信号から中立状態にするPCA9685のPWMカウント値を算出。
freq = 60
resolution = 4096
pwm_center = int((raw1/1000000) / (1/freq/resolution))
pwm_stop = int((raw2/1000000) / (1/freq/resolution))
print(pwm_center)
if (330 <= pwm_center <= 430) and (330 <= pwm_stop <= 430):
    print("The value is within the normal range.")
else:
    pwm_center = 373
    pwm_stop = 373
    print("The values were abnormal, so the default settings have been restored.")

print('PCA9685 Count Value:center {},neutral {}'.format(pwm_center,pwm_stop))
ゲームパッドなどのF710を使用すると動作が確認しやすいです。サーボは70%程度の可動域になっています。ご使用のデバイスによって調整して下さい。 ステアリングトリムは、微調整にお使いください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import time         
import pygame
import os
from IPython.display import clear_output

#Displayをオフ
os.environ["SDL_VIDEODRIVER"] = "dummy"


pygame.init()
joy = pygame.joystick.Joystick(0)
joy.init()
time.sleep(0.5)

#ステアリングエンドポイント設定(デフォルト各70)
left_endpoint = pwm_center - 70
right_endpoint = pwm_center + 70
#ステアリングトリム(デフォルト0)
stTrim = 0

#トリム調整計算
left_endpoint = left_endpoint + stTrim
right_endpoint = right_endpoint + stTrim
pwm_center = pwm_center + stTrim

try:
    while True:
        leftStick = int( joy.get_axis(1)* 100 ) + pwm_stop
        rightStick = int( joy.get_axis(3)* 100 ) + pwm_center
        button0 = joy.get_button(0)
        button1 = joy.get_button(1)
        button2 = joy.get_button(2)
        button3 = joy.get_button(3)
        pygame.event.pump()

        #ステアリングエンドポイント
        if not(left_endpoint <= rightStick <= right_endpoint):
            if (left_endpoint >= rightStick):
                rightStick = left_endpoint
            if (right_endpoint <= rightStick):
                rightStick = right_endpoint

        print("left=%d  right=%d"%(leftStick, rightStick))

        PCA9685.set_channel_value(0, rightStick)
        PCA9685.set_channel_value(1, leftStick)

        if button0 == 1:
            print("Button_A")
        elif button1 == 1:
            print("Button_B")
        elif button2 == 1:
            print("Button_X")
        elif button3 == 1:
            print("Button_Y")

        time.sleep(0.01)
        clear_output(True)

except( KeyboardInterrupt, SystemExit):
    print( "Ctr + D pushed. EXIT!" )