virt_flyのブログ -3ページ目

virt_flyのブログ

フライトシミュレーターソフトのFlightGearで仮想飛行を楽しむブログです。

郡山城跡と近鉄特急

↑郡山城の中堀に沿って走る近鉄特急。追手東隅櫓・東多門櫓が見えます。ちょっとピンボケ!写真のセンスもなくてすみません。

 

 

NHK大河ドラマ「豊臣兄弟」で脚光

 

NHKの大河ドラマ「豊臣兄弟」がいよいよ「本能寺の変」となりました。以前撮っていた郡山城跡の写真の出し時です。郡山城というのは奈良県大和郡山市にあった城。他にも、広島県安芸市吉田の郡山城が毛利氏の城として有名ですが、こちらは、豊臣秀長が天正13年(1585年)に城主となり、豊臣政権の畿内統治の拠点として大規模に整備したもの。3重の堀がめぐらされ、東西1.6㎞、南北1.5㎞、外堀の総延長が約6㎞といわれます。

 

中堀に沿って近鉄線が走っています。郡山城跡の最寄りの駅は、近鉄橿原線郡山駅です。冒頭の写真は、追手東隅櫓・東多門櫓の前を走る近鉄特急。

 

郡山城跡の石垣と水面

 

鉄御門跡を曲がって本丸に入ると、堀と石垣が現れます。

 

郡山城跡 追手東隅櫓と近鉄特急郡山城跡、追手東隅櫓と東多門櫓

 

右手前方(北の方角)を望むと、堀の先に櫓が見えます。追手門向櫓です。その後ろから一部をのぞかせているのが追手門。そちらに向かいます。

 

郡山城の追手東隅櫓と多門櫓

 

追手門向櫓と追手門の間に見えてきたのが、多門櫓です。

 

郡山城跡 追手東隅櫓・東多門櫓

 

気が付くと、右手にも櫓がありました。冒頭の写真にあった追手東隅櫓ですね。

 

郡山城 追手門と東隅櫓

 

追手門まで来ました。左右に大きな盆梅があります。門をくぐると、道は左折、坂になっています。

 

郡山城跡の建物と提灯

 

坂を登り切ると右手後にお城らしからぬ建物が建っています。それもそのはず、奈良市から旧県立図書館を移築し、現在は城址快感として利用されているもの。日露戦争の戦勝記念として奈良公園内に建てられたものだったとあって、和風な外観の洋風建築が明治な雰囲気を醸し出しています。とくに、今の建物では見かけることがない窓の装飾は素敵です。

 

郡山城天守台と石垣

 

元来た道を先に進むと、内堀を挟んで天守台の石垣が見えます。

 

郡山城跡の追手東隅櫓と東多門櫓

 

元来た道を左手にとると、内堀側にパラソル仕立ての屋外カフェがあり、反対側は多門櫓の裏となります。

 

郡山城の極楽橋と石垣

 

内堀に架かる橋にやってきました。なんで極楽橋というか知りませんが、天守曲輪に渡りましょう。

 

郡山城跡の柳澤神社と木々

 

天守曲輪には神社がありました。柳澤神社です。徳川綱吉の側用人で大老格まで務め、赤穂浪士を切腹させたことでも有名な柳澤吉保と、その子であり郡山藩主の吉里をしのんで、旧郡山藩士らが明治13年(1880年)に創建したもの。

 

神社の北側に天守台が見えます。神社の西側を通って天守台に向かいます。

 

郡山城跡の石垣と見学客郡山城跡の逆さ地蔵と石垣

 

天守台を北側に回り込むと、石垣の中に足を上に頭から斜めに差し込まれた「逆さ地蔵」をみることができます。写真では、小さな四角部分にある地蔵様の顔の部分を拡大し、露光もいじり見やすくしたものを添付しました。

 

築城の際、石垣に使う石が足りず、領内の寺の地蔵や墓石、平城旧跡から礎石まで持ってきたのだそうです。豊臣時代の石垣がそのままみられるのは貴重なようです。

 

今回はここまで。天守台にのぼるのは次回に回します。

 

プランターの丸ナスと紫の花プランターで育つキュウリの画像

↑プランターで育った丸ナス、キュウリ

 

 

我が家に実のなるものが増えた

 

日銀が金利を引き上げても円安は収まらず、政府も打つ手がないのか1ドル162円台に突入しようかという有り様。物価の高騰に止まる気配は見られません。株価は記録的な値上がりしているといっても、所詮庶民のもつわずかばかりの株ではたかが知れています。

 

ささやかな抵抗だと言って、妻が買ってきたナスとキュウリの苗が、種の場合とは違って十分な水やりのかいあって暑さの中でも無事生長し、この度実が生りました。

 

長ナスが実をつけた様子プランターで育つ丸ナス

↑長ナス、水ナス

 

最初に収穫できたのは丸ナスでしたが、次の実がなるのはなかなか時間がかかるもので、長ナス、水ナスはようやく実が大きくなりだしたばかり。一方、キュウリは生長が早く、毎日のように新鮮な野菜が食べられるというのはありがたいことです。

 

プランター菜園といえども、馬鹿にできません。ただし、土代や水やりなどの費用を考えれば、採算がとれるのか甚だ心もとないところです。

 

柿熟したマルベリーと葉木瓜の若実、庭に実る食べ物

↑富有柿、梅、木瓜

 

食べれるものが生る庭というのは、うれしいものです。我が家では富有柿を筆頭に、梅、木瓜、ブドウ、ブルーベリーが今実をつけています。マルベリーは少し前に実をつけていましたが、終わりました。残念ながらイチゴは雑草に駆逐されてしまったようです。今回これにはじめて野菜が加わることになりました。

 

プランターで育つ未熟な緑色のブドウブルーベリーの実が鈴なりマルベリーの実、葉、枝

↑ブドウ、ブルーベリー、マルベリー

 

RP2040 TYPE-C 16MBでTFTにキャラ画像表示

↑RP2040 TYPE-C 16MBを使い、混在する異なるサイズの画像を2インチTFTに連続表示(動画はGIF)

 

16MB使うにはCircuitpython

 

■Micropythonはフラッシュメモリーがいくらあっても2MBと見做す

 

Raspberry Pi Zeroに替えて、Picoを使ってパラパラアニメを作ろうと思ったら、画像はRAWファイルでも12~3枚が限度。無印のPicoのフラッシュメモリーが2MBしかないからです。

 

16MBあると思われるPico互換機のRP2040 TYPE-C 16MBが、以前Aliexpressで購入したまま眠っていましたので、これなら使えそうと考えました。

 

RP2040 TYPE-C 16MBボード

↑フラシュメモリーを16MBもつPico互換のRP2040 TYPE-C 16MB 眼がよく見えなくてハンダがひどいことになってます

 

早速MicropythonをインストールしてRAW画像を入れようとしたところ、12~3枚くらいで入らなくなってしまいました。これじゃPicoと同じ2MBじゃないか、騙されたのではと思ったものですが、どうやら無印Pico用のMicropythonはなべてフラッシュメモリーは2MBと見做すようになっているみたいです。

 

■専用のMicropythonをビルドする手もあるが

 

CircuitPythonを試すか、使えるMicropythonが探しても見つからないので自分でビルドしてつくる他なさそうです。専用のものを作っても管理が大変だし、ビルドは面倒でしょうから、CircuitPythonが使えたら手っ取り早く、無難でしょう。

 

Circuitpythonはあまりプログラミングしてこなかったし久しぶりでどこからダウンロードしてくればいいのかも忘れていたくらいなので、コード作成は生成AIに任せました。

 

RP2040 TYPE-C 16MBと2インチTFTディスプレイ

↑RP2040 TYPE-C 16MBでフラシュメモリー16MB を使うにはCircuitepython が手っ取り早い

 

結果は、Circuitpythonならインストールするだけで16MBを認識しすぐ使えることがわかり、またパラパラアニメも予定の28枚の画像を使って実現できました。

 

■GMT020-02専用のst7789ドライバーは無敵

 

なお、ディスプレイにはクセのある2インチTFT(GMT020-02)を使用しましたので、生成AIがコード作成にもたつきましたが、CircuitpythonとMicropythonでは違いがあるものの、以前紹介した自作専用のst7789ドライバーを示したところ、ハードの特性をつかみ、速やかにコード作成がすすみました。GMT020-02専用のst7789ドライバーはここでも貢献、無敵です。

 

RP2040でホログラム表示(GIF)

↑Pico(正確にはPico互換機)でも疑似透過ディスプレイでホログラムができました(動画はGIF) セリアのクリアキューブが各70㎜の正方体だったので目的にピッタリ

 

■混在するサイズの異なる画像を連続表示

 

愚痴ですが、ChatGPTには振り回されました。CircuitpythonはBMP画像しか扱えない、RAWも使えなくもないがBMPにしろというので用意したのに、途中からBMPはダメだRAW画像にせよと。しかも、以前作成してあったRAW画像がなぜか表示できないので、ChatGPTが用意した変換コードでRAW形式に作り替えたところ、なぜか縦長画像を生成していて、コードをどんなにいじろうともなおらない原因になっていたのです。以前作成してあったRAW画像もいつのまにか表示できるようになっていたり、他にも、Circuitpythonでは画像の回転や反転は不可能と言っていたのに、いつのまにか可能なことがまるわかりのコードを出してきたりと、相手がAIでも不信がわくというもの。

 

結局、コードはCopilotに書かせました。

 

シンプルなコードではつまらないので、RAW画像は240x240と240x320の両サイズ混在で連続表示を可能にするものとしました。そのため、大きなサイズの画像を表示した後に小さな画像を表示すると、小さくてカバーできず大きな画像の残像がはみだして覗き見苦しくなります。これを覆い隠すため、大きい画像と小さい画像との間に背景画像を挟んで表示させることにしますが、画像が変わるたびにいちいちすべて背景画像を描いていてはちらつきの元。したがって、小さい画像の表示の前に小さな画像を表示していた場合は間に背景画像は描かない、もちろん大きな画像を表示する場合にはその前の背景画像の描画は不要なので省くようにコードを記述しました。冒頭のGIFを参照ください。背景画像に歩き回るキャラクターの背景色(暗灰色)を使用したので、うまい具合にはみ出し部分の見分けはつかなくなっています。

 

import board
import busio
import digitalio
import time

# ============================
# ST7789 Driver
# ============================

class ST7789:
  def __init__(self, spi, width, height, reset, dc, cs):
    self.spi = spi
    self.width = width
    self.height = height

    self.reset = digitalio.DigitalInOut(reset)
    self.dc = digitalio.DigitalInOut(dc)
    self.cs = digitalio.DigitalInOut(cs)

    self.reset.direction = digitalio.Direction.OUTPUT
    self.dc.direction = digitalio.Direction.OUTPUT
    self.cs.direction = digitalio.Direction.OUTPUT

    self.cs.value = True
    self.dc.value = False

  def cmd(self, c):
    self.cs.value = False
    self.dc.value = False
    self.spi.write(bytes([c]))
    self.cs.value = True

  def data(self, d):     self.cs.value = False
    self.dc.value = True
    if isinstance(d, int):
      self.spi.write(bytes([d]))
    else:
      self.spi.write(d)
    self.cs.value = True

  def reset_display(self):
    self.reset.value = False
    time.sleep(0.05)
    self.reset.value = True
    time.sleep(0.05)

  def init(self):
    self.reset_display()

    self.cmd(0x11)
    time.sleep(0.12)

    self.cmd(0x36)
    self.data(0x00) #デフォルト
    #self.data(0xC0) #180度回転
    #self.data(0x40) #左右反転
    #self.data(0x80) #上下反転
    #self.data(0x20) #90度回転

    self.cmd(0x3A)
    self.data(0x55)

    self.cmd(0x21)
    self.cmd(0x29)
    time.sleep(0.02)

  def window(self, x0, y0, x1, y1):
    self.cmd(0x2A)
    self.data(x0 >> 8)
    self.data(x0 & 255)
    self.data(x1 >> 8)
    self.data(x1 & 255)

    self.cmd(0x2B)
    self.data(y0 >> 8)
    self.data(y0 & 255)
    self.data(y1 >> 8)
    self.data(y1 & 255)

    self.cmd(0x2C)


  def draw_raw_320_stream(self, filename):     # 240x320 全面表示(rowstart補正不要)
    self.window(0, 0, 239, 319)

    bufsize = 4096

    self.cs.value = False
    self.dc.value = True

    with open(filename, "rb") as f:
      while True:
        buf = f.read(bufsize)
        if not buf:
          break
        self.spi.write(buf)

    self.cs.value = True

  # 240x240 RAW を rowstart=40 に表示(ストリーミング)
  def draw_raw_240_stream(self, filename, rowstart=40):
    y0 = rowstart
    y1 = rowstart + 239

    self.window(0, y0, 239, y1)

    bufsize = 4096

    self.cs.value = False
    self.dc.value = True

    with open(filename, "rb") as f:
      while True:
        buf = f.read(bufsize)
        if not buf:
          break
        self.spi.write(buf)

    self.cs.value = True

  # 連続ループ再生(RAMを使わない)
  def play_sequence_stream(self, filelist, delay_ms=200, rowstart=40):
    while True:
      for filename in filelist:
       #self.draw_raw_240_stream(filename, rowstart=rowstart)
       self.draw_raw_320(filename)
       time.sleep(delay_ms / 1000)


# ============================
# Main Program
# ============================

spi = busio.SPI(clock=board.GP18, MOSI=board.GP19)
while not spi.try_lock():
  pass
spi.configure(baudrate=40000000, polarity=0, phase=0)

tft = ST7789(
  spi,
  240, 320, # ← パネルは 240×320
  reset=board.GP20,
  dc=board.GP16,
  cs=board.GP17
)

tft.init() # 表示したい RAW 画像のリスト files = [
  ("digit4.raw", 320),
  ("image01.raw", 240),
  ("digit3.raw", 320),
  ("image02.raw", 240),
  ("image03.raw", 240),
  ("image04.raw", 240),
  ("image05.raw", 240),
  ("digit2.raw", 320),
  ("digit1.raw", 320),
  ("digit0.raw", 320),
  ("digit_blank.raw", 320),
  ("image06.raw", 240)
]

# --- 背景を1回だけ描く ---
tft.draw_raw_320_stream("back_gray.raw")

previous_size = None

while True:
  for filename, size in files:

    # --- 背景描画の条件 ---
    # 1. 今回の画像が 240x320 の場合 → 描かない
    # 2. 今回が 240x240 で、前回が 240x320 の場合 → 描く
    # 3. 今回が 240x240 で、前回も 240x240 の場合 → 描かない(ちらつき防止)

    if size == 320:
      tft.draw_raw_320_stream(filename)
    else:
        # 前回が320 → 残像が出るので背景を描く
        tft.draw_raw_320_stream("back_gray.raw")

      # 240x240 を rowstart=40 で描く
      tft.draw_raw_240_stream(filename, rowstart=40)

    previous_size = size
    time.sleep(0.2)

このコードは、CopilotならびにChatGPTの助けを得て作成しました。