hira のすべての投稿

R152 で大月から浜松へ

突然実施

第三日曜日は、地区の朝礼が8時からある、連絡事項の後、掃除。

それが終わり、天気を確認したら、台風が去って温帯低気圧に変わり、晴天。
大月は、今回の台風では、あまり雨が降らなかった。

アトピーでバイクに長い間乗って無かったのもあって、少し遠出してみる事にした。
※アトピーが直った訳では無いが、今の季節、バイクで走っていれば、そこそこ涼しいし別の事に集中してる方が気が楽な事もある。

ルートは事前に考えていた

今回は、R152 よりも、R20 から R152 に至る途中の道が主で、「富士見パノラマリゾート」手前から、「入笠山」を抜ける林道を通り、R152 に連絡出来る。
※上記写真は、そのルート上で何とも整った風景を観たので撮影したもの。
※入笠山周辺は、マイカーの規制があるので、注意が必要なようだ、途中停車も出来ない区間がある。
※警備に止められた場合は、「伊那」に抜けると言えば大丈夫なようだ。
※規制は8時~3時までのようだ。

浜松行は急に決めた

R152 に合流したのが2時過ぎ、このまま R152 を戻って諏訪から R20 で帰るのも何だかなぁと思い、前から思っていた R152 で浜松まで行く事にした。
帰りは遅くなると思うが、どうしようも無く眠くなったらルートインとかに泊まれば良いと軽く考えてた。

WR250X は長距離のツーリングに適さない

WR250X の燃料タンクは7.4リッター程、大体5リッター消費で給油ランプが点く。
リッター30キロ程は走るので、150キロで給油が必要となる。

以前に、山中で給油しようと思ったら、GS が休みで、仕方なくそのまま戻ったが途中でガス欠になった・・
仕方なく数キロバイクを押したが、宛にしていた GS は、やはり営業しておらず、難儀していた。
※バイクを置いて、自宅まで何とか戻り、ステップワゴン(トランポ仕様にしている)を取りに行こうと考えていた。
農作業をしていたやさしい方に耕運機用に備蓄していたガソリンを別けてもらい自宅まで戻れた経緯がある。

一応、1リットル入る携行缶は持っているが、+30キロでは、場所や時間によっては無理がある。
※二つあれば安心感があるが、それなりに重い・・

結局、150キロの範囲で、大きな街にアクセス出来るようなプランじゃないとマズイ事になる・・
※夜は営業していない場合もある、大きな都市なら、セルフで24HのGSもあるが、小さい集落では夕方にはGSは閉まってしまう。

今回、R152 は「通行止め」区間があった・・

R152 は、一応「国道」だが、途中狭く、離合も困難な場所がある、一方、整備された区間は、道幅も広く、綺麗で、走っていて気持ちが良い。
そして、非常に空いている。

最初に、「地蔵峠」手前のクネクネで不通になっており「全面通行止め」となっていた。
仕方なく、戻って、県道59号との分岐(大鹿村役場)まで戻り、一旦、R153 まで出て、ガソリンを補給した。
懲りずに、県道251号を通り、「喬木 I.C.」から「程野 I.C.」を経て R152 に合流したw
※この自動車専用道路は、ほぼトンネルで、無料区間となっていた。(5キロ程)

二度目の通行止め・・

次に、「兵越峠」を抜ける手前でやはり「全面通行止め」となっていた・・・
規制看板の手前でバイクを止め文面を読んでいたら、地元の車が上がっていったので、アレ?、通れるのかな?と思い、付いていった。
そしたら、上から降りて来たキャンピングカーが、「全面通行止め」で先には行けない「浜松に抜けられない」と教えてくれた。
何でも、3日前くらいに起こったらしい・・・

うーーん、ここまで来てかぁーと思ったが仕方無いので、少し戻り、R418、県道1号を進み、「佐久間ダム」の標識がある分岐まで来た。
この時、既に暗くなっており、あまり良く考えずに「ダムの方に向かったらマズイ」のでは?と思ってしまった。
※ここで、停車して地図を確認すれば良かったが、電波の状況とか、残燃料とか、暗かったとか、面倒にも思って、あまり考えずに県道426号に行ってしまった・・
これが、今回の大失敗となった・・・
県道426号はかなりの難所で、何とか R151 までたどり着いたが、この段階で7時位?
こんな山の中だが、集落に 24H のファミマがあり、簡単な食事をした。(ファミリーマート 北設楽東栄町店)

燃料給油が急務

現在の距離(燃料消費量)から、早急に GS を見つけないとならない・・・
色々検討したが「豊橋」辺りまで抜けないと 24H のセルフは無いかもしれない、携行缶に1リッターあるので、何とかギリギリ間に合う計算。
途中、集落に GS はあったが、やはり閉まっていた。

「新庄市」に入ったら、大きな都市で、24H のセルフがあり、給油出来た、この時10時前、携行缶のガソリンは使わなかった。
※6.44リッター給油(残り800cc)

自宅に戻る

給油して、少し休んだら、気力が戻り、疲労感も少ない(クラッチ側の手も痛くない)ので、到着は夜中になるけど、自宅まで戻る事にした。
※自粛期間だし、宿泊するのも気が重い、途中色々なホテルの駐車場を見たが、かなり車が停まっていたので、宿泊してる人は意外に多いようだ。

まず、R301 で浜松(浜名湖)まで抜けた。
ここで、ファミマで休憩して、ルート検索を行ったが、大月まで戻るのに「高速で5時間」、「下道で6時間」だった。
高速使っても1時間しか変わらない?
うーーん、高速だと、WR250X は結構色々辛い!、また、途中で眠くなったら、SA まで我慢しないとならないしと思い、下道で帰る事にした。
帰りは、R1、R139 とシンプルなルートだ。

途中眠くなったらコンビニで休めるし、R1 沿いなら GS も沢山ある。

R1 は高速道路だった!

今回初めて浜松から R1 を利用したが、自動車専用道路となっており、高速道路と大差無い・・
制限速度は60キロだが、60で走ってるとバンバン抜かれるが、この時間空いているし、かなり快適、速度以外は東名と変わらない。
WR250X は、高速で100キロ連続とかだと、エンジンの回転をかなり上げないとならないし、風圧がそれなりにあり疲れる。
※70~80くらいが丁度良い。(メーターは、1割くらい低く表示するので、66キロくらいで、正確に60キロだと思う)

途中何回か休憩をして、R139に合流、富士市でガソリン補給。(午前2時、5.34リットル)
※ここから大月まで90キロ程度、給油は必要無い。

R139 で大月までー

寒くなるだろうから、今回珍しく持参したバイク用レインスーツを上下着た。

R139 はこの時間、ほぼ車はいない、そして凄く寒い!、14度。

あまりに寒いので、富士吉田で24H営業のなか卯で、少し早い朝食(牛丼とうどんのせっと)を食べ、自宅に戻ったのが4時位。

まとめ

今回、それなりに疲れたが、峠を満喫した、軽量バイクの楽しみは、狭い林道w

R152 は面白い、狭い林道と、そこそこ広い整備された道で、緩急があり飽きないし、昼間でも下手なマイカーが少ない!
昼間なら、休憩スポットも色々ある。

また、細々と整備も進められており、完成が待たれる・・

二度の通行止めで、消化不良の面もあるので、通行止め解消の折には、もう一度通っていない部分を含め挑戦したい!
次は、もっと早く出発して、宿泊を前提にしたい。

RX マイコン I2C モニター

I2C モニター

RX マイコンのサンプルで中途のプロジェクトを更新した。

I2C デバイスを接続して、操作を行うサンプルだが、雛形は作ったが、中身は無い状態だった。
※サンプルはそれなりに多いので、作ったつもりで忘れている事もあるw

それを、ある程度実装した。

※実験は、RX72T ボードで行った、IICA ペリフェラルを利用している。


対話形式で、I2C デバイスと通信する

とりあえず、最低限必要なコマンドを実装。

コマンド パラメーター 機能
scan start end I2C デバイスをスキャンする
adr address 操作を行う I2C デバイスのアドレスを設定
r num I2C からデータを受け取る(recv)
s data... I2C へデータを書き込む(send)

操作画面

操作の入出力は、シリアル接続されたターミナルで行う。

接続したデバイスは、DS3231 のモジュールで、24C32(EEPROM)も載っている。

起動時:

Start I2C sample for 'RX72T' 200[MHz]
SCI Baud rate (set):  115200
SCI Baud rate (real): 115287 (0.08 [%])
CMT rate (set):  100 [Hz]
CMT rate (real): 100 [Hz] (0.00 [%])
I2C Start ok: (intrrupt level = 0)
#

スキャン:

# scan
Ditect I2C address: 0x57 ( 87, 0b1010111)
Ditect I2C address: 0x68 (104, 0b1101000)
  Ditect I2C Device(s): 2
#

書き込みと読出し:

# adr 0x68
# s 0
# r 16
43 39 03 06 03 09 21 00 00 00 00 00 00 00 00 88

# s 0
# r 16
50 39 03 06 03 09 21 00 00 00 00 00 00 00 00 88

#
  • I2C アドレス設定(0x68)
  • アドレスレジスタを設定(0)
  • 16バイトの読出し
  • 秒カウンタが変化している。(43 ---> 50)

まとめ

とりあえず、動作しているので、コミットしてある。

まだまだ、初期段階なので、今後拡張していきたい。

IICA の割り込みモードも完成させたい。

Makefile を共通化

Makefile 共通化

RX マイコンの各プロジェクトで、Makefile で共有出来る部分を抜き出して、共通化を行った。

今まで、同じような「手順」を各プロジェクト毎にコピーしていたが、二度手間だし、プロジェクト数が多く、作業が大変だった。
※Makefile を複数に別けたく無かったとゆーこだわりがあったのだが、現在のように手順がそこそこ複雑だと、そうする「こだわり」はあまり意味が無い。

共通部分

# -*- tab-width : 4 -*-
#=======================================================================
#   @file
#   @brief  RX microcontroller share Makefile
#   @author 平松邦仁 (hira@rvf-rc45.net)
#   @copyright  Copyright (C) 2021 Kunihito Hiramatsu @n
#               Released under the MIT license @n
#               https://github.com/hirakuni45/RX/blob/master/LICENSE
#=======================================================================

# System include path for each environment
ifeq ($(OS),Windows_NT)
SYSTEM := WIN
# C++.boost root
LOCAL_PATH  =   /mingw64
else
  UNAME := $(shell uname -s)
  ifeq ($(UNAME),Linux)
    SYSTEM := LINUX
    LOCAL_PATH = /usr/local
  endif
  ifeq ($(UNAME),Darwin)
    SYSTEM := OSX
    OSX_VER := $(shell sw_vers -productVersion | sed 's/^\([0-9]*.[0-9]*\).[0-9]*/\1/')
    LOCAL_PATH = /opt/local
  endif
endif

まず、これは、Windows、Linux、OS-X の環境を判断して、微妙な違いを吸収する。
※一番重要な事は、boost のパスを各環境で同じように扱う事。


LIB_ROOT    =   ../../rxlib/lib

INC_SYS     =   ../../rxlib/include $(LOCAL_PATH)/include

PROG_VERIFY = --verify
  • LIB_ROOT は、RX マイコン専用ライブラリのパスを設定している。
  • INC_SYS は、RX マイコン専用ライブラリのインクルードパスと、ローカルのインクルードパス(boost)などを設定している。
  • PROG_VERIFY は、rx_prog でフラッシュ書き込みする際に、「VERIFY」を行う場合のキーワードとなっている。
  • RX24T は、通常の手順で、VERIFY が行われない為、無効にする必要がある。

ifeq ($(RX_DEF),SIG_RX24T)
  RX_CPU = RX24T
  RX_OPT = v2
  LDSCRIPT  =   ../../RX24T/$(DEVICE).ld
  PROG_VERIFY =
endif

ifeq ($(RX_DEF),SIG_RX64M)
  RX_CPU = RX64M
  RX_OPT = v2
  LDSCRIPT  =   ../../RX64M/$(DEVICE).ld
endif

ifeq ($(RX_DEF),SIG_RX71M)
  AS_OPT    +=  --defsym MEMWAIT=1
  RX_CPU = RX71M
  RX_OPT = v2
  LDSCRIPT  =   ../../RX71M/$(DEVICE).ld
endif

ifeq ($(RX_DEF),SIG_RX65N)
  LIB_ROOT += ../../RX600/drw2d
  INC_APP +=  ../../RX600/drw2d/inc/tes
  USER_LIBS += drw2d
  RX_CPU = RX65N
  RX_OPT = v2
  LDSCRIPT  =   ../../RX65x/$(DEVICE).ld
endif

ifeq ($(RX_DEF),SIG_RX66T)
  RX_CPU = RX66T
  RX_OPT = v3
  LDSCRIPT  =   ../../RX66T/$(DEVICE).ld
endif

ifeq ($(RX_DEF),SIG_RX72T)
  RX_CPU = RX72T
  RX_OPT = v3
  LDSCRIPT  =   ../../RX72T/$(DEVICE).ld
endif

ifeq ($(RX_DEF),SIG_RX72N)
  LIB_ROOT += ../../RX600/drw2d
  INC_APP +=  ../../RX600/drw2d/inc/tes 
  USER_LIBS += drw2d
  RX_CPU = RX72N
  RX_OPT = v3
  LDSCRIPT  =   ../../RX72N/$(DEVICE).ld
endif

ifeq ($(RX_DEF),SIG_RX72M)
  LIB_ROOT += ../../RX600/drw2d
  INC_APP +=  ../../RX600/drw2d/inc/tes
  USER_LIBS += drw2d
  RX_CPU = RX72M
  RX_OPT = v3
  LDSCRIPT  =   ../../RX72M/$(DEVICE).ld
endif

この条件文で、RX マイコン毎に異なる設定を行っている。
現状では、「SIG_xxx」のキーワード毎に行っているが、将来的には、DEVICE で IC の型番を設定しているので、それに従って行うのが妥当だと思う。

※型番で行えば、ピン数の違いによる変更をソースコードへ伝達する事が出来る。

RX71M だけは、ちょっと特殊で、スーパーバイザーモードでしかアクセス出来ないレジスタがある。
そこで、そのレジスタを、start.s アセンブラブログラム内で行っている。「--defsym MEMWAIT=1」

FreeRTOS の場合、ユーザーモードに移行しない事が重要だが、それは、各プロジェクト毎に設定する。

# for FreeRTOS option
AS_OPT      =   --defsym NOT_USER=1

# Renesas GNU-RX gcc compiler version check
TARGET_ISA_TEXT := $(shell rx-elf-gcc --target-help | grep ISA)

# Renesas GNU-RX (8.3.0) compiler 
ifeq ($(TARGET_ISA_TEXT),)
  # for gcc-7.5.0 current gcc source build
  AS_DEFS       =   -mcpu=rx600
  CC_DEFS       =   -mcpu=rx600 -Wa,-mcpu=rxv2
  CP_DEFS       =   -mcpu=rx600
else # Renesas GNU-RX gcc 8.3.0
  AS_DEFS       =   -misa=$(RX_OPT)
  CC_DEFS       =   -misa=$(RX_OPT)
  CP_DEFS       =   -misa=$(RX_OPT)
endif

これは、Renesas GNU-RX gcc コンパイラと、プレーンな gcc コンパイラで、オプションが異なるので、それを自動判別する。


# You should not have to change anything below here.
AS          =   rx-elf-as
CC          =   rx-elf-gcc
CP          =   rx-elf-g++
AR          =   rx-elf-ar
LD          =   rx-elf-ld
OBJCOPY     =   rx-elf-objcopy
OBJDUMP     =   rx-elf-objdump
SIZE        =   rx-elf-size

AFLAGS      =   $(AS_OPT) $(AS_DEFS)
CFLAGS      =   -std=gnu99 $(CC_OPT) $(OPTIMIZE) $(CC_DEFS) $(DEFS)
PFLAGS      =   -std=c++17 $(CP_OPT) $(OPTIMIZE) $(CP_DEFS) $(DEFS)
FLAGS       = $(AS_OPT) $(AS_DEFS) $(CC_OPT) $(CP_OPT) $(OPTIMIZE) $(CC_DEFS) $(CP_DEFS) $(DEFS)

# FLAGS_CMP := $(shell cat $(TARGET).opt)

override LDFLAGS = $(MCU_TARGET) -nostartfiles -Wl,-Map,$(TARGET).map -T $(LDSCRIPT)

OBJCOPY_OPT =   --srec-forceS3 --srec-len 32

OBJECTS =   $(addprefix $(BUILD)/,$(patsubst %.s,%.o,$(ASOURCES))) \
            $(addprefix $(BUILD)/,$(patsubst %.c,%.o,$(CSOURCES))) \
            $(addprefix $(BUILD)/,$(patsubst %.cpp,%.o,$(PSOURCES)))

DOBJECTS =  $(addprefix $(BUILD)/,$(patsubst %.c,%.o,$(CSOURCES))) \
            $(addprefix $(BUILD)/,$(patsubst %.cpp,%.o,$(PSOURCES)))

DEPENDS =   $(patsubst %.o,%.d, $(DOBJECTS))

# all, clean: optional make command
.PHONY: all clean clean_depend run text
.SUFFIXES :
.SUFFIXES : .hpp .s .h .c .cpp .d .o

all: $(BUILD) $(TARGET).elf text

$(TARGET).elf: $(OBJECTS) $(LDSCRIPT) Makefile
    $(CC) $(LDFLAGS) $(LIBINCS) -o $@ $(OBJECTS) $(LIBS)
    $(SIZE) $@

$(BUILD)/%.o: %.s
    mkdir -p $(dir $@); \
    $(AS) -c $(AOPT) $(AFLAGS) $(AINCS) -o $@ $<

$(BUILD)/%.o : %.c
    mkdir -p $(dir $@); \
    $(CC) -c $(COPT) $(CFLAGS) $(CINCS) $(CCWARN) -o $@ $<

$(BUILD)/%.o : %.cpp
    mkdir -p $(dir $@); \
    $(CP) -c $(POPT) $(PFLAGS) $(PINCS) $(CPWARN) -o $@ $<

$(BUILD)/%.d: %.c
    mkdir -p $(dir $@); \
    $(CC) -MM -DDEPEND_ESCAPE $(COPT) $(CFLAGS) $(APPINCS) $< \
    | sed 's/$(notdir $*)\.o:/$(subst /,\/,$(patsubst %.d,%.o,$@) $@):/' > $@ ; \
    [ -s $@ ] || rm -f $@

$(BUILD)/%.d: %.cpp
    mkdir -p $(dir $@); \
    $(CP) -MM -DDEPEND_ESCAPE $(POPT) $(PFLAGS) $(APPINCS) $< \
    | sed 's/$(notdir $*)\.o:/$(subst /,\/,$(patsubst %.d,%.o,$@) $@):/' > $@ ; \
    [ -s $@ ] || rm -f $@

clean:
    rm -rf $(BUILD) $(TARGET).elf $(TARGET).mot $(TARGET).lst $(TARGET).map

clean_depend:
    rm -f $(DEPENDS)

これは、gcc の設定で、従属規則を自動生成する仕組みを内包する。


lst: $(TARGET).lst

%.lst: %.elf
    $(OBJDUMP) -h -S $< > $@

# Rules for building the .text rom images

text: mot lst

lst: $(TARGET).lst
mot: $(TARGET).mot
bin: $(TARGET).bin

%.lst: %.elf
    $(OBJDUMP) -h -S $< > $@

%.mot: %.elf
    $(OBJCOPY) $(OBJCOPY_OPT) -O srec $< $@

%.bin: %.elf
    $(OBJCOPY) -O binary $< $@

これは、リンカーで実行バイナリーを作成後、リストファイル、モトローラーファイル、バイナリーファイルを作成する手順だ。


# Serial Flash write 
run:
    $(MAKE)
    rx_prog -d $(RX_CPU) --progress --erase --write $(PROG_VERIFY) $(TARGET).mot

最後は、シリアル接続で、フラッシュ書き込みを行うツールの設定などになっている。

個別部分

上記のように、共通出来る部分を追い出したので、個別部分はシンプルとなった。

# -*- tab-width : 4 -*-
#=======================================================================
#   @file
#   @brief  RX72N Makefile
#   @author 平松邦仁 (hira@rvf-rc45.net)
#   @copyright  Copyright (C) 2020, 2021 Kunihito Hiramatsu @n
#               Released under the MIT license @n
#               https://github.com/hirakuni45/RX/blob/master/LICENSE
#=======================================================================
TARGET      =   raytracer_sample

DEVICE      =   R5F572NN

RX_DEF      =   SIG_RX72N

BUILD       =   release
# BUILD     =   debug

VPATH       =   ../../

ASOURCES    =   common/start.s

CSOURCES    =   common/init.c \
                common/vect.c \
                common/syscalls.c

PSOURCES    =   RAYTRACER_sample/main.cpp \
                graphics/font8x16.cpp \
                graphics/color.cpp \
                common/stdapi.cpp

USER_LIBS   =

USER_DEFS   =

INC_APP     =   . ../ ../../

AS_OPT      =

CP_OPT      =   -Wall -Werror \
                -Wno-unused-variable \
                -Wno-unused-function \
                -fno-exceptions

CC_OPT      =   -Wall -Werror \
                -Wno-unused-variable \
                -fno-exceptions

ifeq ($(BUILD),debug)
    CC_OPT += -g -DDEBUG
    CP_OPT += -g -DDEBUG
    OPTIMIZE = -O0
endif

ifeq ($(BUILD),release)
    CC_OPT += -DNDEBUG
    CP_OPT += -DNDEBUG
    OPTIMIZE = -O3
endif

-include ../../common/makefile

-include $(DEPENDS)

これは、RX72T の RAYTRACER_sample の Makefile で、基本、リンクするファイルの記述が殆どだ。

リリースビルドと、デバッグビルドの違いで切り替える部分は共通化しなかった。
最適化を変えたり、プロジェクト毎に微妙な違いを許容する事が出来るように配慮した。


まとめ

共通化する過程で、オプションなどを変更した場合に、フルコンパイルが自動で行えるように出来ないか検討したが、make を完全に理解していない為、思ったように作れなかった・・

これは今後の課題にしたいと思う。

RX72T ボード出来たが、残念な結果・・

RX72T ボードが到着

PCBgogo からボードが届いて、早速組み立て動かしたが、色々と問題がある・・

何故、10枚作ったのか(かなり確認したので、パーフェクトと思っていたが・・・)

まぁそれでも、ツギハギすれば何とかなる程度ではあるけど・・

  • GPTW コネクタのピンアサインが間違っている・・
  • マイクロ USB コネクタのフットプリントを自作したが、ピンアサインが逆・・

※以前に、CP2102N の基板を作った時に使った、マイクロ USB のコネクタと同じフットプリントを使ったのだが逆だった・・
良く調べると、マイクロ USB コネクタには、二種類あり、上下が逆になっていた・・・
何も考えずに、ボトムマウントを買って取り付けてしまった・・・

フラットパッケージのハンダが難しい

今回初めて、自作基板に 0.5mm ピッチのデバイスをハンダ付けしたが、これが意外と難しい。

  • 今までは、金メッキされた変換基板にハンダ付けしていたが、それに比べて難しい
  • ハンダメッキが均一ではなく、部品の位置を決めるのが難しい
  • 視力が落ちて、ルーペなどを使わないと、細かい作業が出来ない

それでも、何とかコツを攫んでハンダ付けした。
※何かツールを用意しないと、量産は時間がかかりそうだ・・・
部品を吸引などして掴んで、微調整するハンドルがあれば良いのだが・・

0.5mm ピッチだと、ブリッジはするが、ハンダ吸い取り線とフラックスを使えば、何とかリカバリーは出来るようだ。

自作基板でも、部品を正確に配置する事が出来れば、殆ど問題は起こらないと感じた。
それと、部品を正確に置けても、その状態で固定するのが難しい、何か「ジグ」が必要だと痛感した。

1603 の部品(抵抗、コンデンサ)は、コツを攫めば簡単だが、綺麗(位置を正確に決める)に付けるのは難しい。

とりあえず、動作はしている

LED 点滅や、シリアル通信などを行って、問題なく動作する事を確認した。

SD カードの確認を行おうと思ったが、電源切り替え IC が行方不明で止まっている・・
※確かに買ったハズだが、何処を探しても見つからない・・・

エミュレータの接続は OK

ルネサスの評価ボードの回路を参考に、エミュレーター関係のコネクターを設けている。
E1 を接続して、フラッシュの書き込みを行ってみたが、問題無かった。

また、シリアル接続で内蔵フラッシュの書き込みも問題無い。

IICA の確認を優先

IICA(I2C) の確認を優先している。
IICA ドライバーは、ポーリングは出来ていたが、割り込みを使うドライバーは未完だった。

そこで、これを完成させる事から始めようと思う。

RX24T である程度確認していたが、RX72T では、グループ割り込みを使う必要がある。
※RX24T では通常割り込み。

グループ割り込みのハンドリングがイマイチだったので、RX マイコンフレームワーク全体で関係する部分を修正した。

まとめ

USB が逆だったのは、かなりショックだったが、部品が二種類(トップ、ボトムマウント)ある事に気が回らなかった・・・

マイクロ USB コネクタを基板にダメージを与えないで外す事が難しそうだ・・・
※低融点ハンダを買う必要があるようだ・・・

RX72T ボードを試作

RX72T が安い!

いつもお世話になっている Chip1Stop で100ピン、PGA、USB の RX72T が 10 個で @600 程だった。
丁度、RX72T の実験ボードが必要だったので、ボードの制作も考えて10個購入した。

RX72T は 200MHz 動作で、TFU(三角関数演算器)内蔵なので、CP が非常に高い。
※現状、RX24TやRX66Tと同程度か、むしろ安い!
RAM(128KB)がもう少し多ければと思うが・・・

いつも、デバイスは買ったものの、ボードを作るのが後回しになり、新型のRXマイコンが出て、モチベーションが駄々下がり、結局肥やしになる事多数、今回は、ちゃんと最後まで作る事を誓った。

基本設計

基本的には、あまり欲張らずに、そこそこの完成度とする事でボードの設計が楽になると考えた。

  • RSPI で SD カードをサポートする。
  • GPTW ポートを出す(ブラシレスモーター制御向け)
  • CAN をサポート
  • IICA(I2C)をサポート
  • RS-485 をサポート
  • Renesas エミュレータ接続をサポート
  • USB マスター、クライアントをサポート
  • シリアルポートを複数サポート
  • D/A 出力
  • アナログ入力

など、複数の用途を盛り込んだ。
やはり、ポートの配分に苦労したが、何とか回路設計は満足いくものになった。

プロジェクトは、github に KiCAD のプロジェクトとして置いてある。

ルート(ブロック):

全回路図(PDF)


最近、アトピーが酷くなって、甲府にある、漢方の病院に通院している。(既に3か月になる・・)
なかなか良くならず(時間がかかると言われた)、集中出来ないので、本業はお休みしている。
起きていると、痒みが強いので、なるべく安静にしている、この苦しみは、患った人にしか理解してもらえない・・

KiCAD の利用

KiCAD で基板を制作するのは、2度行ったので、かなり経験値が高くなった。
それでも、本格的なマイコンボードは初なので、色々ハードルがあると思える。

最近のKiCADは本当に完成度が高く、回路部品、フットプリント、など、自分で制作する事が少なくなった。

自分は、特殊なパーツ(主に秋月)に関して、部品や、footprint を作成している。

問題なのは、「二層基板で十分品質の高い電源を引けるか?」なのだが、部品配置をある程度行い、オートルーターに食わせてみたら、塩梅良かったので、電源を手動で引いて、オートルーターで自動配線、評価を繰り返していった。

オートルーターは、かなり細かい設定が出来るものの、全自動で引いても、思ったようにはいかない。

  • 部品の配置を良く吟味する。
  • 重要なトラックを手動で引く。(オートルーターが引ける余地を残し、配慮する)
  • 電源関係も重要な部分は自分で引く。

これだけ行えば、後はオートルーター任せで何とかなる事が判った。

まとめ

とりあえず、大体出来たが、もう少し煮詰めてから、基板屋に発注する事にしたい。

追記 2021-08-14 07:26:06 Saturday

電源の手動ライン、部品位置など見直して、再度オートルートを行った、今回は、最適化が終了するまでオートルーターを動かし続けた。
※ルートは、数分で終了したが、最適化には、この基板規模で1日くらいはかかっている・・・

そこで判明したのは、部品名が基板外形の外にあると、そこが、基板外形の最大エリアとして認識する事だ・・

最適化には時間がかかるので、手動で上記二本のトラックを修正した。

もう一度、確認を行い、ベタアースを追加してから基板の発注を行いたいと思う。

追記 2021-08-14 17:31:52 Saturday

下記 PCB でガーバーを作成し、基板屋(PCBgogo)に注文しました。

  • 基板サイズ 120mmx80mm
  • 枚数10枚
  • 銅箔2oz
  • 配送 OCS(DHLより$5安い)

で、7200円程、@720円

内燃機関に関する覚書

はじめに

いつもは、電子工作が中心な内容で、趣味のバイク関係がほんの少しの内容だが、最近の流れに伴った、事をつらつらと・・

CO2 と温暖化問題

この問題に関して、殆どの人はマスコミから流れてくる情報を100%信じていると思う。

そもそも、大気の0.02%しか無い CO2 が増えたから温暖化する科学的な根拠はいまだに示されていない。
※色々なメカニズムやデータは示されていても100人が納得するような根拠は乏しい物が殆ど。

以前にハワイのデータとして、「CO2 が増えたら、温度が上がった」グラフを観た事があるが、良く観ると・・
「温度が上がったら、CO2 が増えた」ように見え、実際、そうだった。
※温度が上がると海水に溶けている CO2 が揮発され、CO2 濃度が上がったものと推測される。

温暖化の CO2 犯人説は、IPCCが言っているポエムでしか無いと思われるが、何故か、この言説がまかり通っている。

これは、環境問題では無く、政治問題で、裏に隠れている本質は、世界の人口が増え過ぎた為に起こっているものと思う。
自然環境が劣化していると感じる大きなファクターは、人口が増えすぎた為に起こっているものと思われる。

大きな都市では、昔に比べて、ゲリラ豪雨(夏場)など、気象の変化が頻繁に起こると思われている。
この本質も、自動車だけでは、無い、エアコンの室外機の排熱が大きく関与しているものと思う。
※人口が少ない過疎地では、ゲリラ豪雨のような気候変動は少ない。
※エアコンの室外機は、今では、一部屋に1つはある勘定で、それが全て稼働していないとしても、都市部では莫大な熱量になる。

日本政府は、温暖化を理由に大きな税金を動かしている。
もし、本当にに CO2 が温暖化の要因なら、その税金分を発展途上国の為に使ったら、CO2 の削減を日本で減らす1000~10000倍は減らす事が可能と思う。
しかし、そのようには絶対にしないので、CO2 を根本的に減らそうとは思っていない事は明白だと思う。
単に税金を使う為の屁理屈に過ぎない。

分別とリサイクル

これも多くの人が騙されている問題と思う。

普通に考えて、分別したり、リサイクルしたら、多くのエネルギーや資源を浪費するので、環境には害悪でしかない。
※CO2 も余分に消費する。

たとえば、ペットボトルをリサイクルすると、余分に、多くのコストやエネルギー(コスト=エネルギー)がかかる。
※これは税金で負担されている。

  • 分別で余分にかかる輸送コスト
  • ペットボトルの清掃コスト(これがかなり大きい)
  • ペットボトルを分解して、材料にするコスト

これは、原油の精製から出てくる材料より多くのコストとエネルギーを消費し、しかも、製品の品質は、リサイクル品の方が低い。

それでは、どうすれば良いか?
現在の技術では、「燃やす」以外に経済的な方法は無い(将来、より良い方法が生まれるかもしれないが・・)
※焼却場では、分別により、水分が多いゴミが集中して、燃えにくくなっており、燃料をかけている場合があると聞く。


金属に関しては、分別して、回収した方が良いとの話もあるが、途中(改修や輸送など)で税金が使われているので、何とも言えない。
※これもある程度利権があるので、うさん臭い処がかなりある。


内燃機関は悪か?

欧州では、内燃機関自動車を廃止して電動自動車にシフトすると言っているが、それで、万事解決するような事項では無いのは誰でも判る。

  • 電気は多くの場合、火力発電所で作られるので化石燃料を使う。
  • 太陽光発電は、生み出すエネルギーが小さすぎて実用にはならない。
  • 原子力発電は、化石燃料よりウランの枯渇が速いと思われるし、放射性廃棄物を処理する事が出来ないので、やはり実用的とは思えない。
  • 送電線でロスする分と、リチウムイオンを主体とするバッテリーを製造する事による「環境負荷」が大きい。
  • バッテリー劣化による交換サイクルなどもかなり大きな環境負荷となる。
  • 原油を精製すると、軽油やガソリンは必ず一定量出てくるので、将来内燃機関の自動車が無くなったら、別の問題が発生する。

※将来、自動車に使われなくなった軽油やガソリンは、発電所で使われるものと思う。

他にも沢山あるが、「電動」が「内燃機関」より優れているとは(現状では)到底思えない。

なぜ、「電動」にシフトするのか?

多分、問題の一つは、現状で、高性能な内燃機関(ハイブリッド車)を全ての部品を製造して量産出来る国は日本しかない。

これが大きいものと思う。
こんな事を言うと、ドイツやアメリカでも内燃機関の自動車を製造していると言う人がいるが、「全ての部品」となると、やはり日本しかない。

たとえば、エンジンの中で、バルブ(排気、吸気)について考えても、ほぼ日本の独壇場で、高性能(長寿命で壊れない)な金属材料を作れる工場は日本にしか無い(日立金属だと思われる)。
※「たたら」による鋼の製錬をルーツ(日本刀の材料)に持っていると言われる。
※チタンバルブは、価格が高いのと、寿命が短いので量産車には利用出来ない。

中国はかなり長い間、単独で内燃機関の材料の製造、設計、組み立て、などを行う努力をしたが、日本の製造技術に追いつく事が出来ないのであきらめた、そこから「電動」にシフトしだした。
※中国単独で製造したエンジンの寿命は、日本製の 1/5 とか 1/10 程度しか無い。
※中国の高性能内燃機関自動車の多くは日本製のエンジンを OEM している。
※欧州やアメリカは、かなり前にお手上げ状態となっていて、日本製の部品を輸入したり、電動自動車に舵を切ったと思われる。

これら事実から、このまま内燃機関のハイブリッド車が支流になったら、自国の産業が死滅してしまうので、脱炭素とからめて高性能な内燃機関の日本車を排除する政治的な戦略を進めているものと思う。
このような「手練手管」は白人の独壇場だ、日本人はお花畑な人が多く、「人は卑劣な事をしないものだ」と思っているので簡単に騙される。

まとめ

マスゴミや、腐った政治家の言う言説を鵜呑みにしないで、自分で考えたり、調べたりしないと、間違った方向に誘導されてしまう事になるのではないか?

「自動車」メーカーが CO2 の削減とか言っていたり、電動自動車シフトに抵抗する様子が無いので、
多分、このままでは、内燃機関は駆逐され、将来は、嗜好品になり、クローズドコースだけでしか利用出来ないような世界になるのだろうか・・

RXマイコン、クロックプロファイルクラスの導入

クロック設定を見直す

C++ でRXマイコンフレームワークを作り始めた頃、あまり考えずに、適当に作った部分が、未だに「悪い」見本として残っている。

RXマイコンのクロックジェネレータは、意外と複雑で、面倒な設定を要するデバイスとなっており、柔軟性も必要なのに、かなり適当な創りとなっている。

そこで、これを見直して、もう少し「サッパリ」としたより良い物に変更する。
意外と広範囲な修正になる事から、今まで、見なかった事にしてきたものの、「痛い」部分は速いうちに処置した方が良いので、修正を行った。

以前の設定

以前は、「Makefile」と「main.cpp」の両方で微妙な設定を行っていた・・・

Makefile の設定:

USER_DEFS   =   SIG_RX71M \
                F_ICLK=240000000 \
                F_PCLKA=120000000 F_PCLKB=60000000 F_PCLKC=60000000 F_PCLKD=60000000 \
                F_FCLK=60000000 F_BCLK=120000000

main.cpp:

#if defined(SIG_RX71M)
    typedef device::system_io<12'000'000, 240'000'000> SYSTEM_IO;

...

int main(int argc, char** argv)
{
    SYSTEM_IO::setup_system_clock();

ベースクリスタルの周波数は、ソースコードに埋め込んであるのに、クロックジェネレータの分周器による周期は「Makefile」で環境変数で設定してある・・・

これは、初期の実験コードで色々やっていた時、テスト的に行ったものが、「標準」となってしまい、見直す事が先延ばしになり現在に至ったもの。
第三者を交えて、コードレビューを行えば、かなり早い段階で「ツッコミ」を入れられたと思うが、の機会が無く、そのままになっていた・・

改修後

改修後、クロック設定プロファイルクラスを新規に作り、そこに定数として設定してある。

#pragma once
//=====================================================================//
/*! @file
    @brief  RX71M グループ・クロック。プロファイル @n
            クロックジェネレータで発生させる周波数の定義
    @author 平松邦仁 (hira@rvf-rc45.net)
    @copyright  Copyright (C) 2021 Kunihito Hiramatsu @n
                Released under the MIT license @n
                https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>

namespace device {

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  クロック・プロファイル・クラス
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    class clock_profile {
    public:
        static const uint32_t   BASE        =  12'000'000;      ///< 外部接続クリスタル
        static const uint32_t   PLL_BASE    = 240'000'000;      ///< PLL ベースクロック

        static const uint32_t   ICLK        = 240'000'000;      ///< ICLK 周波数
        static const uint32_t   PCLKA       = 120'000'000;      ///< PCLKA 周波数
        static const uint32_t   PCLKB       =  60'000'000;      ///< PCLKB 周波数
        static const uint32_t   PCLKC       =  60'000'000;      ///< PCLKC 周波数
        static const uint32_t   PCLKD       =  60'000'000;      ///< PCLKD 周波数
        static const uint32_t   FCLK        =  60'000'000;      ///< FCLK 周波数
        static const uint32_t   BCLK        = 120'000'000;      ///< BCLK 周波数
    };
}

このソースは、各プラットホーム毎に切り替えて、他ソースから参照するようにしてある。

クリスタルが特殊な場合は、このファイルに追加して、環境変数で切り替えれば良いだろうと思う。

PLL_BASE の周波数は、BASE 周波数の倍率(0.5単位)で割り切れる必要がある。
当然、他の周期も、PLL_BASE からの分周比で割り切れる周波数を設定する必要がある。

また、mainの最初で、クロック周波数を切り替える関数名は、

typedef device::system_io<> SYSTEM_IO;

int main(int argc, char** argv)
{
    SYSTEM_IO::boost_master_clock();

とした。

※RX71M は、クロック設定の特定レジスタが、スーパーバイザモードでアクセスする必要があり、その部分を「start.s」で行っている為、「Makefile」にアセンブラに渡す変数がある。

AS_OPT      =   --defsym MEMWAIT=1

クロックジェネレーターの周波数を参照する場合、以下のように行える。

    auto iclk = device::clock_profile::ICLK / 1'000'000;
    utils::format("Start test for '%s' %d[MHz]\n") % system_str_ % iclk;

内臓高速発信器を利用する場合

typedef device::system_io<device::system_base::OSC_TYPE::HOCO> SYSTEM_IO;

内蔵高速発信器は、通常、16MHz、18MHz、20MHzがあり、「BASE」にどの周波数を使うか指示する。

まとめ

かなり広範囲な修正だったが、それだけの価値はあると思う。

RXマイコン、割り込み関係整理

RX72T で CAN の検証で気がついた・・

RX72T で CAN の動作確認をした際、思ったように動作しない・・
※以前に CAN のサンプルを作成する際、RX64M 1 台で行っており、複数台で互いに通信する確認はしていなかった・・

  • データ送信しても、データが送られない。
  • データの受信もしない。

この感じは、割り込みぽぃなぁーと思い、
割り込み関係を確認したら、単純に CAN 関係割り込みが設定されていないだけだった・・
※本来、割り込みが正しく設定されない場合、初期化時にエラーを返す必要がある・・

  • 標準割り込みは、ちゃんと実装していない事を思い出す。
  • 新規にペリフェラルのマネージャーを実装した時に、追加していた。
  • なので、デバイスによりバラバラで、統一性が無い・・・
  • ここらで、ちゃんと実装しておこうと思う。

RX64M では、CAN 関係は、選択型割り込みBなので、問題無かった。
RX66T/RX72T では、CAN の割り込みは通常ベクターなので、通常ベクターの登録関数に CAN 関係の割り込みを追加する必要がある。
通常割り込みで、厄介なのは、割り込みベクター番号から、IER、IPR などの割り込み設定関係へのアクセスでは規則性が無い場合がある。
その為、対応する通常ベクターを全て実装しておく必要がある・・・
※単純には、割り込みベクター番号から、IER、IPR レジスターを推定出来ない・・

また、IPR は、シェアされて共通になっている場合もある。


割り込み関係の整理

初期の実装では、割り込み設定は、ペリフェラル別に行っていた。
※初期の実装では、ペリフェラルの定義に、割り込みベクターを「定数」として含めていなかったので、個別に対応する必要があった。
現在の実装では、割り込みベクター型や番号は、ペリフェラルの定義を参照する事で得られるようになっている。

↓現在のSCIクラステンプレートの実装:

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  SCI 定義基底クラス
        @param[in]  base    ベース・アドレス
        @param[in]  per     ペリフェラル型
        @param[in]  txv     送信割り込みベクター
        @param[in]  rxv     受信割り込みベクター
        @param[in]  INT     送信終了割り込みベクター型
        @param[in]  tev     送信終了割り込みベクター
        @param[in]  pclk    PCLK 周波数
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    template <uint32_t base, peripheral per, ICU::VECTOR txv, ICU::VECTOR rxv,
        typename INT, INT tev, uint32_t pclk>
    struct sci_t {

        static const auto PERIPHERAL = per; ///< ペリフェラル型
        static const auto TX_VEC = txv;     ///< 受信割り込みベクター
        static const auto RX_VEC = rxv;     ///< 送信割り込みベクター
        static const auto TE_VEC = tev;     ///< 送信終了割り込みベクター
        static const uint32_t PCLK = pclk;  ///< PCLK 周波数

SCI などでは、割り込みを使う場合、受信と送信、同時に使う仕様なので、それでも良かった。
しかし、割り込みベクター別に設定を行うべきなので、その仕様を改めた。

        //-----------------------------------------------------------------//
        /*!
            @brief  割り込みレベルを設定する
            @param[in]  per 周辺機器タイプ
            @param[in]  lvl 割り込みレベル(0の場合、割り込み禁止)
            @return 成功なら「true」
        */
        //-----------------------------------------------------------------//
        static bool set_level(peripheral per, uint8_t lvl) noexcept
        {
            bool ena = lvl != 0 ? true : false;
            switch(per) {

            case peripheral::SCI1:
                ICU::IPR.RXI1 = lvl;
                ICU::IER.RXI1 = ena;
                ICU::IPR.TXI1 = lvl;
                ICU::IER.TXI1 = ena;
                break;
            case peripheral::SCI5:
                ICU::IPR.RXI5 = lvl;
                ICU::IER.RXI5 = ena;
                ICU::IPR.TXI5 = lvl;
                ICU::IER.TXI5 = ena;
                break;

↑以前の実装では、ペリフェラル毎に割り込みを設定していた・・(今後、廃止する予定)

↓今後、割り込みベクター毎に登録する・・

        //-----------------------------------------------------------------//
        /*!
            @brief  割り込みレベルを設定する
            @param[in]  vec 割り込み要因
            @param[in]  lvl 割り込みレベル(0の場合、割り込み禁止)
            @return 成功なら「true」
        */
        //-----------------------------------------------------------------//
        static bool set_level(ICU::VECTOR vec, uint8_t lvl) noexcept
        {
            bool ena = lvl != 0 ? true : false;
            switch(vec) {

            case ICU::VECTOR::RXI1:
                ICU::IER.RXI1 = 0;
                ICU::IPR.RXI1 = lvl;
                ICU::IER.RXI1 = ena;
                break;
            case ICU::VECTOR::TXI1:
                ICU::IER.TXI1 = 0;
                ICU::IPR.TXI1 = lvl;
                ICU::IER.TXI1 = ena;
                break;

かなり、大掛かりな修正なので、時間がかかりそう・・・


作業実績

RX24T RX64M RX71M RX65N RX72N RX66T RX72T
icu.hpp O O O O O O O
icu_mgr.hpp O O O O O O O

all_compile (Debug)

Pass.

all_compile (Release)

Pass.

追記 (2021-05-11 08:12:55 Tuesday)

  • ハードウェアーマニュアルを良く読むと、IR レジスタ、IER レジスタは、割り込み要因の番号と一致するようだ。
  • IPR レジスタに関しては、割り込み要因番号が32以下の場合と、特定のレジスタ(RX24T)の場合に、例外的なアクセスを行えば良いらしい。

そこで、IPR クラスの [] オペレーターによるアクセスを少々工夫する事で、余分なコードを削減する事が出来た。

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  IPR レジスタ @n
                    全て、下位4ビットが有効
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        template <uint32_t base>
        struct ipr_t {

...

            //-------------------------------------------------------------//
            /*!
                @brief  []オペレータ
                @param[in]  vec     標準割り込みベクター型
                @return IPR レジスターの参照
            */
            //-------------------------------------------------------------//
            volatile uint8_t& operator [] (VECTOR vec) noexcept {
                uint32_t idx = 0;
                switch(vec) {
                case VECTOR::BUSERR: idx = 0; break;
                case VECTOR::RAMERR: idx = 0; break;
                case VECTOR::FIFERR: idx = 1; break;
                case VECTOR::FRDYI:  idx = 2; break;
                case VECTOR::SWINT2: idx = 3; break;
                case VECTOR::SWINT:  idx = 3; break;
                case VECTOR::CMI0:   idx = 4; break;
                case VECTOR::CMI1:   idx = 5; break;
                case VECTOR::CMWI0:  idx = 6; break;
                case VECTOR::CMWI1:  idx = 7; break;

                default: idx = static_cast<uint32_t>(vec); break;
                }
                return *reinterpret_cast<volatile uint8_t*>(base + idx);
            }
        };
        typedef ipr_t<0x00087300> IPR_;
        static IPR_ IPR;

icu_mgr クラスの「set_level()」関数では、以下のようにシンプルとなった。

        //-----------------------------------------------------------------//
        /*!
            @brief  割り込みレベルを設定する
            @param[in]  vec 通常割り込みベクター型
            @param[in]  lvl 割り込みレベル(0の場合、割り込み禁止)
        */
        //-----------------------------------------------------------------//
        static void set_level(ICU::VECTOR vec, uint8_t lvl) noexcept
        {
            bool ena = lvl != 0 ? true : false;
            ICU::IER.enable(vec, 0);
            ICU::IPR[vec] = lvl;
            ICU::IER.enable(vec, ena);
        }

RX72N Envision Kit での開発(その7)GPTW を使う

GPTW とは?

  • RX66T、RX72T、RX72N には、汎用 PWM 機能(GPTW)が備わっています。
  • 一般に PWM 生成は MTU を使いますが、GPTW はさらに細かい設定が可能で、MTU の拡張版的な扱いのようです。
  • カウンタは32ビットになっており、高いクロックでの駆動が可能なようになっています。
  • RX66T、RX72T は GPTW は 10 チャネル、RX72N には 4 チャネルあります。
  • RX66T、RX72T はより高いクロック(PCLKC、最大160MHz、200MHz)を分周器のクロックとして使えます。
  • RX72N は(PCLKA、最大120MHz)を分周器のクロックとして利用します。
  • 「汎用」とありますが、かなり細かい設定が可能で、主に FET や IGBT などのパワーデバイスの制御に向いています。
  • RX66T、RX72T には、さらに、高分解能波形成型器を通す事で、より細かい PWM 波形を生成できます。
  • インプットキャプチャーや、位相入力(エンコーダー入力)などにも使えます。
  • A/D コンバーターを同期して動かす事が出来るので、正確な電圧、電流の検出が行えます。

GPTW 用ポートの設定クラスを作る。

  • 最近の RX マイコンは、ポートのアサインを行う候補が増えて、より柔軟性が増したと思えます。

  • そこで、「port_map_gptw」クラスを新規に追加して、専用クラスを用意しました。

  • 候補のポリシーは、ハードウェアーマニュアルにある「MPC」にある説明に沿った物にしてあります。

  • 自分のフレームワークでは、別プログラムで設定を生成しないので、判りやすさと柔軟性を与える為、「候補」(ORDER)型を使い、設定します。

  • ポートマッピングオーダー型

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  ポート・マッピング・オーダー型
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        enum class ORDER : uint8_t {
            BYPASS,     ///< ポートマップの設定をバイパスする場合
            FIRST,      ///< 第1候補
            SECOND,     ///< 第2候補
            THIRD,      ///< 第3候補
            FOURTH,     ///< 第4候補
            FIFTH,      ///< 第5候補
            SIXTH,      ///< 第6候補
            SEVENTH,    ///< 第7候補
        };
  • GPTW0 A チャネルのポート候補
        static bool gptw0_(CHANNEL ch, bool ena, ORDER opt) noexcept
        {
            bool ret = true;
            uint8_t sel = ena ? 0b011110 : 0;
            switch(ch) {
            /// GTIOC0A (入出力)
            ///       224 176 144 100
            /// P23     ○   ○   ○   ○
            /// P83     ○   ○   ○   ×
            /// PA5     ○   ○   ○   ○
            /// PD3     ○   ○   ○   ○
            /// PE5     ○   ○   ○   ○
            /// PH6     ○   ×   ×   ×
            case CHANNEL::A:
                switch(opt) {
                case ORDER::FIRST:
                    PORT2::PMR.B3 = 0;
                    MPC::P23PFS.PSEL = sel;
                    PORT2::PMR.B3 = ena;
                    break;
                case ORDER::SECOND:
                    PORT8::PMR.B3 = 0;
                    MPC::P83PFS.PSEL = sel;
                    PORT8::PMR.B3 = ena;
                    break;
                case ORDER::THIRD:
                    PORTA::PMR.B5 = 0;
                    MPC::PA5PFS.PSEL = sel;
                    PORTA::PMR.B5 = ena;
                    break;
                case ORDER::FOURTH:
                    PORTD::PMR.B3 = 0;
                    MPC::PD3PFS.PSEL = sel;
                    PORTD::PMR.B3 = ena;
                    break;
                case ORDER::FIFTH:
                    PORTE::PMR.B5 = 0;
                    MPC::PE5PFS.PSEL = sel;
                    PORTE::PMR.B5 = ena;
                    break;
                case ORDER::SIXTH:
                    PORTH::PMR.B6 = 0;
                    MPC::PH6PFS.PSEL = sel;
                    PORTH::PMR.B6 = ena;
                    break;
                default:
                    ret = false;
                    break;
                }
                break;

制御クラス(gptw_mgr)

  • MTU のマネージャークラスと同じような構成にして、「gptw_mgr」クラスを実装しました。
  • 現状では、PWM 波形を出力するだけですが、テンプレートを使い設定を参照する事で、複数のマイコンでもシンプルな構成にする事が出来ます。

動作モード

  • 動作モードとして、以下の型があります。(今後拡張予定)
  • 現状、のこぎり波以外は実装されていません。
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  動作モード型
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        enum class MODE : uint8_t {
            PWM_S_HL,       ///< のこぎり波 PWM (AB: H --> L) 
            PWM_S_LH,       ///< のこぎり波 PWM (AB: L --> H)
            PWM_S_HL_LH,    ///< のこぎり波 PWM (A: H --> L, B: L --> H)
            PWM_S_LH_HL,    ///< のこぎり波 PWM (A: L --> H, B: H --> L)
            SINGLE,         ///< ワンショット・パルス
            PWM_T1,         ///< 三角波 PWM 1(谷32ビット転送)
            PWM_T2,         ///< 三角波 PWM 2(山/谷32ビット転送)
            PWM_T3,         ///< 三角波 PWM 3(谷64ビット転送)
        };

出力制御と型

  • 出力制御では、以下の型のどれかを設定出来ます。
  • RX66T、RX72T では「反転出力」を指定出来ます。
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  出力型 @n
                    ※反転出力は、RX66T、RX72T の場合にのみ有効
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        enum class  OUTPUT : uint8_t {
            NONE,   ///< 無効

            A,      ///< A を利用
            B,      ///< B を利用
            AB,     ///< AB

            NA,     ///< 反転 A を利用
            NB,     ///< 反転 B を利用
            NA_B,   ///< 反転 A, 正 B を利用
            A_NB,   ///< 正 A, 反転 B を利用
            NA_NB,  ///< 反転 A, 反転 B を利用
        };

gptw_mgr テンプレートクラス

  • gptw_mgr テンプレートのプロトタイプは以下のようになっています。
  • パラメータとして、GPTW のチャネル型、割り込み時に起動させる事が可能なファンクタクラスを指定します。
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  GPTW マネージャー・クラス
        @param[in]  GPTWn   GPTW[n] ユニット
        @param[in]  CMTASK  コンペアマッチタスク型
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    template <class GPTWn, class CMTASK = utils::null_task>
        class gptw_mgr : public gptw_base {

...

    };
  • gptw_mgr の宣言では、以下のようにします。(RX72N GPTW1 を使った場合)
  • RX72N Envision Kit では、PMod コネクタ CN6 に (7)PD0、(8)PD1 がアサインされており、GPTW1 の出力をマッピング出来ます。
    /// PMOD Connector: PD0(CN6-7), PD1(CN6-8)
    typedef device::GPTW1 GPTW_CH;
    const auto ORDER_A = device::port_map_gptw::ORDER::FOURTH;
    const auto ORDER_B = device::port_map_gptw::ORDER::FOURTH;

    typedef device::gptw_mgr<GPTW_CH, utils::null_task> GPTW;
    GPTW    gptw_;

GPTW の開始

  • プロトタイプは以下のようになっています。
  • 周期は、整数値で周波数を指定します。
  • RX72T、RX72N ではベースクロックが異なりますが、その定義は、GPTx インスタンスで指定されている為、自動で最適な値を計算します。
  • ポート候補で、A、B 出力の「候補」を指定します。
  • 「バッファー動作」は、DUTY 設定をバッファリングする事で、DUTYを変更した場合にノイズが出ません。
  • 通常、PWM 周期とは非同期に DUTY を変更すると思うので、標準でバッファー動作になっています。
  • 設定に反故があると「false」を返して失敗します。
        //-----------------------------------------------------------------//
        /*!
            @brief  開始
            @param[in]  mode    動作モード
            @param[in]  out     出力型
            @param[in]  freq    周期
            @param[in]  ord_a   ポート候補A
            @param[in]  ord_b   ポート候補B
            @param[in]  ilvl    割り込みレベル(0 なら割り込み無し)
            @param[in]  buffer  バッファー動作を無効にする場合「false」
            @return 設定が適正なら「true」
        */
        //-----------------------------------------------------------------//
        bool start(MODE mode, OUTPUT out, uint32_t freq, typename port_map_gptw::ORDER ord_a, typename port_map_gptw::ORDER ord_b,
            uint8_t ilvl = 0, bool buffer = true) noexcept

  • GPTW の開始では、動作モード、出力ポート候補、PWM 周波数、などを指定します。
  • モードは、PWM_S_HL(初期'H' で 'L' になる)
  • 出力は AB
  • 周期は 100KHz
  • 初期状態で、33%、66%のデューティー幅のパルスを出力します。
    {  // GPTW の開始 (PWM / AB 出力)
        uint32_t freq = 100'000;  // 100KHz
        if(gptw_.start(GPTW::MODE::PWM_S_HL, GPTW::OUTPUT::AB, freq, ORDER_A, ORDER_B)) {
            utils::format("GPTW%d start: freq: %u\n") % GPTW::value_type::CHANNEL_NO % freq;
            duty_a_ = 0.33f;
            gptw_.set_duty_a(duty_a_);
            duty_b_ = 0.66f;
            gptw_.set_duty_b(duty_b_);
        } else {
            utils::format("GPTW%d start fail...\n") % GPTW::value_type::CHANNEL_NO;
        }
    }

DUTY の変更

  • サンプルでは、ターミナルを接続して、コマンド入力で、A、B チャネルの DUTY を指定できるようにしてあります。
  • a duty(0 to 1.0)
  • b duty(0 to 1.0)
  • help
Start GPTW sample for 'RX72N Envision Kit' 240[MHz]
SCI PCLK: 60000000
SCI Baud rate (set):  115200
SCI Baud rate (real): 115384 (0.16 [%])
CMT rate (set):  100 [Hz]
CMT rate (real): 100 [Hz] (0.00 [%])
GPTW1 start: freq: 100000
# a
A: duty: 0.330
# b
B: duty: 0.660
# b 0.5
#

まとめ

  • PWM 波形の出力は、意外と複雑なので、マネージャークラスの介入が欠かせません。
  • 出来る範囲で、柔軟な設定が可能なように工夫してありますが、十分ではありません。
  • 足りない設定は、gptw_mgr クラスの構成に習って、改修すれば良いと思います。
  • ソースコードはコメントも多く、動作の概要を掴みやすいように実装されています。
  • 詳細な解説が無くてもソースコードやサンプルコードを少し眺めれば理解できるものと思います。
  • gpt_mgr クラスは、単一のソースなので、他のコードを余り意識しなくても構造が判ると思います。
  • 他に「RX600/gptw.hpp」、「RX72N/port_map_gptw.hpp」を参照する必要があるかもしれません。
  • 「レジスター名」はハードウェアーマニュアルと同一にしてあるので、何かの機能を追加する場合に実装しやすいと思います。

GPTW_sample

WR250X のクラッチ修理(その2)

やっと修理出来たー

※ブレーキペダルが邪魔なので、外してある。

随分時間が経ってしまったが、やっと、クラッチの修理をした。


金属プレートの計測

クラッチ板は減るのは理解出来る、だけど、こんな「硬い」金属プレートが減るの?
ノギスで測ると、殆ど差が判らないので、マイクロメーターで計測してみた。

その「差」わずかに0.04mm、6枚で0.24mm、こんなの誤差のように思う・・

以前に「金属プレートを交換する意味」として、熱が入り歪む場合があると聞いたので、定盤に乗せて歪みを計ってみた。

※この状態で、プレートを回すと、歪みがあれば、数値が動くと思われる。

全く問題無い・・・

だけど、折角買ったので、新品に交換しておく・・・


クラッチスプリングを強化スプリングへ

色々調べると、WR250R、とWR250Xではスプリングが異なるようだー
※WR250Rの方が強化スプリング

そこで、強化スプリングへ交換した。

YZ125と同じ物との事で、純正ではないサードパーティー製を購入(少し安い!)

強化スプリングの方が自由長がかなり短い・・


クラッチホルダーの交換はスルー

一応、クラッチホルダーも購入したが、何だか勿体ないので、交換はしないで、とりあえず、この状態で様子を見た。

直った!

少し走ってみたが、以前のようにパワーをかけてもクラッチが滑る気配は全く無くなった。

多分、「強化スプリング」が利いているものと思う、それにしても微妙な不具合だなぁー

試走

とりあえず、近くの峠でガツンとアクセルを開けてみて滑らないか試してみたが全く問題無い。

ただ、やっぱ多少クラッチは重いかも・・

いつものコースで一回りしてみた。

  • 県道30号
  • 県道33号
  • 県道18号
  • 国道139号

やっぱりクラッチが滑らないと快適に走れて気持ちイイ~