メインコンテンツへスキップ

CircuitPythonでマイコン開発を始めよう!メモ帳だけで動かせる開発環境不要のPython環境とXIAO RP2350を使った実践ガイド - Lチカから本格的なIoTデバイス制作まで、初心者でも今すぐ始められる電子工作入門

    みなさん、マイコンって聞くとなんだか難しそう...って思っちゃいません?Arduino IDEをインストールして、ライブラリを追加して、コンパイルして...って、もう聞いただけで頭が痛くなりそうですよね。

    でもね、実はメモ帳一つでマイコンのプログラムが作れちゃう方法があるんです。それがCircuitPython!今回は、このCircuitPythonを使って、本当に開発環境なしでマイコンを動かす方法を、徹底的に解説していきます。

    正直言って、私も最初は「えー、そんなうまい話あるわけないじゃん」って思ってました。でも実際にやってみたら、本当にメモ帳だけでLEDをピカピカ光らせることができちゃったんです。その時の感動といったら...!

    この記事を読み終わる頃には、あなたもきっとCircuitPythonの虜になっているはず。一緒に、電子工作の新しい世界を探検していきましょう!

    CircuitPythonの正体 - なぜメモ帳だけで動くのか

    CircuitPythonって聞いたことありますか?これ、実はMicroPythonから派生した、マイコン専用のPython環境なんです。開発しているのはAdafruitという会社で、電子工作界隈では超有名な企業です。

    何がすごいって、マイコンをPCに繋ぐと、USBメモリみたいに「CIRCUITPY」っていうドライブが現れるんです。そこにある「code.py」っていうファイルを編集して保存するだけで、プログラムが動き始めるんですよ。コンパイルも書き込みも必要なし!

    私が初めてこれを体験した時は、「え、もう動いてる!?」って思わず声が出ちゃいました。だって、普通のArduinoだったら、コンパイルして、アップロードして...って手順を踏まないといけないじゃないですか。それが、ファイルを保存した瞬間に動き出すんですから。

    なぜ今、CircuitPythonが熱いのか

    実は最近、教育現場でCircuitPythonの採用が増えているんです。理由は簡単。環境構築でつまずく生徒が激減したから。

    私も以前、高校生向けのマイコンワークショップを開催したことがあるんですが、Arduino IDEのインストールだけで1時間かかっちゃったんです。Windowsのドライバがうまく入らなかったり、Macのセキュリティ設定でひっかかったり...。

    でもCircuitPythonなら、USBケーブルを繋いで、ファイルをコピペして、テキストエディタで編集するだけ。小学生でもできちゃいます。

    それに、Pythonって今やプログラミング教育の定番言語ですよね。学校で習ったPythonの知識がそのまま電子工作に活かせるって、すごくないですか?

    CircuitPythonとArduinoの違いを本音で語る

    正直に言います。CircuitPythonは万能じゃありません。

    処理速度で言えば、C++で書かれたArduinoのプログラムには勝てません。例えば、高速でLEDを点滅させたい時、Arduinoなら1マイクロ秒単位で制御できますが、CircuitPythonだと10マイクロ秒くらいが限界です。

    ライブラリの充実度も、まだArduinoには及びません。特殊なセンサーや通信プロトコルを使いたい時、Arduinoなら大抵ライブラリが見つかりますが、CircuitPythonだと自分で書かないといけないことも。

    でもね、初心者にとってこれらのデメリットって、実はそんなに問題じゃないんです。

    だって、最初に作るのってLチカとか、温度センサーの値を読むとか、そういうシンプルなものじゃないですか。そういう用途なら、CircuitPythonで十分すぎるくらい十分なんです。

    対応マイコンの選び方 - 私のおすすめはXIAO RP2350

    CircuitPythonが動くマイコンはたくさんありますが、私が一番おすすめするのはSeeed StudioのXIAO RP2350です。

    なぜかって?まず、めちゃくちゃ小さい!親指の爪くらいのサイズなのに、フル機能のマイコンなんです。それでいて、価格は1500円前後。コスパ最強です。

    RP2350っていうのは、Raspberry Pi財団が開発した最新のマイコンチップで、前世代のRP2040と比べて処理能力が2倍以上になってます。メモリも増えてるので、CircuitPythonで大きめのプログラムを書いても余裕です。

    他にも、Raspberry Pi Picoや、AdafruitのFeatherシリーズなんかも人気ですね。でも、初心者の方には断然XIAOをおすすめします。なぜなら、ピン数が少ないから迷わないんです。Arduinoとかだと、デジタルピンが14個もあって「どれ使えばいいの...」ってなりますが、XIAOなら11個だけ。選択肢が少ない分、悩まずに済みます。

    UF2 Bootloaderの仕組みを理解しよう

    CircuitPythonを使う上で、絶対に知っておきたいのがUF2 Bootloaderです。

    これ、簡単に言うと「マイコンをUSBメモリに見せかける魔法」みたいなものです。通常、マイコンにプログラムを書き込むには専用のツールが必要ですが、UF2 Bootloaderが入っていれば、ファイルをドラッグ&ドロップするだけで書き込めちゃうんです。

    仕組みとしては、マイコンの中に小さなプログラムが入っていて、これがUSBメモリのふりをしてくれるんです。で、.uf2という特殊な形式のファイルがコピーされると、「あ、これプログラムだ!」って認識して、フラッシュメモリに書き込んでくれるんです。

    面白いのは、このUF2 Bootloader自体もオープンソースなんですよ。GitHubで公開されていて、誰でも中身を見ることができます。私も最初は「どういう仕組みなんだろう?」って気になって、ソースコードを読んでみたんですが、思ったよりシンプルな実装で驚きました。

    実際にCircuitPythonを導入してみよう

    さあ、いよいよ実践編です!XIAO RP2350を使って、CircuitPythonを導入していきましょう。

    まず、CircuitPythonの公式サイト(circuitpython.org)にアクセスします。Downloadsページで「XIAO RP2350」と検索すると、対応するバージョンが出てきます。最新版をダウンロードしましょう。

    次に、XIAOをBootモードにします。これがちょっとコツがいるんですが、XIAOのBボタン(小さい方のボタン)を押しながら、Rボタン(リセットボタン)を押します。すると、PCに「RP2350」っていうドライブが現れるはずです。

    もし出てこない場合は、ケーブルを変えてみてください。充電専用のケーブルだとデータ通信ができないので、ドライブが現れません。100均のケーブルとかだと、結構充電専用のやつが混じってるんですよね...。私も最初これで30分くらいハマりました。

    ドライブが現れたら、さっきダウンロードした.uf2ファイルをドラッグ&ドロップ!すると、マイコンが自動的に再起動して、「CIRCUITPY」というドライブに変わります。

    おめでとうございます!これでCircuitPythonの導入完了です!

    最初のプログラム - Lチカを徹底解説

    CircuitPythonが動くようになったら、早速プログラムを書いてみましょう。定番のLチカ(LED点滅)から始めます。

    CIRCUITPYドライブを開くと、「code.py」というファイルがあります。これをメモ帳で開いて、以下のコードを書いてみてください:

    import board
    import digitalio
    import time
    
    print("Hello World! LED点滅プログラムを開始します")
    
    led = digitalio.DigitalInOut(board.LED)
    led.direction = digitalio.Direction.OUTPUT
    
    count = 0
    while True:
        count += 1
        print(f"点滅回数: {count}")
        
        led.value = False  # LEDを点灯(負論理なので注意)
        time.sleep(0.5)
        
        led.value = True   # LEDを消灯
        time.sleep(0.5)
    

    このコード、一見シンプルですが、実はいろんな要素が詰まってます。

    まず、import board。これはマイコンのピン配置を定義したモジュールです。board.LEDって書くだけで、内蔵LEDのピンを指定できるんです。Arduino だと、ピン番号を覚えないといけないですが、CircuitPythonなら名前で指定できるので分かりやすい!

    次に、digitalioモジュール。これはデジタル入出力を制御するためのモジュールです。DigitalInOutクラスを使って、ピンをオブジェクトとして扱えるようにします。オブジェクト指向プログラミングの良い練習にもなりますね。

    ここで注意したいのが、LEDの論理です。多くのマイコンボードでは、LEDが「負論理」で接続されています。つまり、Falseで点灯、Trueで消灯するんです。最初これ、めっちゃ混乱しました...。「なんで逆なの!?」って。

    でも、これには理由があって、マイコンのピンは電流を流し込む(シンク)方が、電流を出す(ソース)より得意なんです。だから、LEDのマイナス側をマイコンに繋いで、ピンをLOW(False)にすることで電流を流し込み、LEDを光らせるんです。

    REPLモードで対話的にプログラミング

    CircuitPythonの隠れた魅力、それがREPL(Read-Eval-Print Loop)モードです。

    これ、簡単に言うと「マイコンと会話できるモード」なんです。1行ずつコードを入力して、その場で実行結果が見られます。

    REPLに入るには、シリアルターミナルでマイコンに接続します。Windowsなら「Tera Term」、Macなら「screen」コマンドが使えます。でも、一番簡単なのはMuエディタを使うことです。

    Muエディタをインストールして、上部の「シリアル」ボタンをクリック。そしてCtrl+Cを押すと、REPLモードに入れます。

    試しに、こんなことをやってみましょう:

    >>> import board
    >>> import digitalio
    >>> led = digitalio.DigitalInOut(board.LED)
    >>> led.direction = digitalio.Direction.OUTPUT
    >>> led.value = False  # LED点灯!
    >>> led.value = True   # LED消灯!
    

    すごくないですか?コンパイルも書き込みも不要で、その場でLEDを制御できるんです!

    私はこのREPLモードで、新しいセンサーの動作確認をよくやります。例えば、温度センサーを繋いだ時:

    >>> import busio
    >>> import adafruit_sht31d
    >>> i2c = busio.I2C(board.SCL, board.SDA)
    >>> sensor = adafruit_sht31d.SHT31D(i2c)
    >>> sensor.temperature
    23.45
    >>> sensor.relative_humidity
    65.2
    

    こんな感じで、センサーの値をリアルタイムで確認できます。「あ、ちゃんと動いてる!」ってすぐ分かるので、デバッグがめちゃくちゃ楽になります。

    ファイル構造とライブラリの管理

    CIRCUITPYドライブの中身、ちょっと覗いてみましょう。

    最初はcode.pyだけですが、実はいろんなファイルを置けます:

    • code.py - メインプログラム(必須)

    • boot.py - 起動時に最初に実行される(省略可)

    • lib/ - ライブラリを置くフォルダ

    • settings.toml - Wi-Fi設定などを書くファイル

    私がよくやる構成はこんな感じ:

    CIRCUITPY/
    ├── code.py          # メインプログラム
    ├── boot.py          # USBの設定とか
    ├── secrets.py       # パスワードとかAPIキー
    └── lib/
        ├── adafruit_sht31d.mpy     # 温度センサーライブラリ
        ├── adafruit_ssd1306.mpy    # OLEDディスプレイ
        └── my_utils.py             # 自作の便利関数
    

    ライブラリの追加も簡単です。Adafruitが公開している「CircuitPython Library Bundle」から必要なライブラリをダウンロードして、lib/フォルダにコピーするだけ。

    ここでポイントなのが、.mpyファイルを使うこと。これはPythonのバイトコードにコンパイル済みのファイルで、メモリ使用量が少なくて済みます。CircuitPythonはメモリが限られているので、できるだけ.mpyファイルを使いましょう。

    センサーを使った実践プロジェクト

    さて、Lチカができたら、次はセンサーを使ってみましょう!温度・湿度センサーのSHT31を使った、簡単な環境モニターを作ってみます。

    必要なもの:

    • XIAO RP2350

    • SHT31センサーモジュール

    • ジャンパーワイヤー 4本

    • ブレッドボード

    配線はこんな感じ:

    • SHT31のVCC → XIAOの3V3

    • SHT31のGND → XIAOのGND

    • SHT31のSCL → XIAOのSCL(GPIO7)

    • SHT31のSDA → XIAOのSDA(GPIO6)

    I2C通信っていうのを使うんですが、難しく考える必要はありません。要は、2本の線でデータをやり取りする仕組みです。

    コードはこちら:

    import time
    import board
    import busio
    import adafruit_sht31d
    
    # I2C通信の初期化
    i2c = busio.I2C(board.SCL, board.SDA)
    sensor = adafruit_sht31d.SHT31D(i2c)
    
    # 快適度を判定する関数
    def get_comfort_level(temp, humidity):
        if 20 <= temp <= 26 and 40 <= humidity <= 60:
            return "快適😊"
        elif temp > 28:
            return "暑い🥵"
        elif temp < 18:
            return "寒い🥶"
        elif humidity > 70:
            return "ジメジメ💧"
        elif humidity < 30:
            return "カラカラ🏜️"
        else:
            return "まあまあ😐"
    
    print("環境モニター開始!")
    
    while True:
        temp = sensor.temperature
        humidity = sensor.relative_humidity
        comfort = get_comfort_level(temp, humidity)
        
        print(f"温度: {temp:.1f}°C, 湿度: {humidity:.1f}%, 快適度: {comfort}")
        
        # 異常値の警告
        if temp > 30:
            print("⚠️ 高温注意!エアコンをつけましょう")
        elif temp < 15:
            print("⚠️ 低温注意!暖房をつけましょう")
        
        if humidity > 80:
            print("⚠️ 湿度が高すぎます!除湿しましょう")
        elif humidity < 20:
            print("⚠️ 乾燥しています!加湿器をつけましょう")
        
        time.sleep(5)  # 5秒ごとに測定
    

    このプログラム、実は私の部屋で実際に動かしてます。夏場とか、「あー、暑いな」って思った時にシリアルモニター見ると「温度: 29.5°C, 湿度: 65%, 快適度: 暑い🥵」って出てて、「やっぱり暑いよね!」って納得したり(笑)。

    ボタンとLEDで作るインタラクティブな装置

    次は、ボタン入力を使った少し複雑な例を作ってみましょう。「モールス信号トレーナー」を作ります!

    import board
    import digitalio
    import time
    import random
    
    # LED設定
    led = digitalio.DigitalInOut(board.LED)
    led.direction = digitalio.Direction.OUTPUT
    
    # ボタン設定(D1ピンに接続)
    button = digitalio.DigitalInOut(board.D1)
    button.direction = digitalio.Direction.INPUT
    button.pull = digitalio.Pull.UP  # 内部プルアップ抵抗を有効化
    
    # モールス信号の定義
    morse_code = {
        'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 
        'E': '.', 'F': '..-.', 'G': '--.', 'H': '....',
        'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
        'M': '--', 'N': '-.', 'O': '---', 'P': '.--.',
        'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-',
        'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
        'Y': '-.--', 'Z': '--..',
        '0': '-----', '1': '.----', '2': '..---', '3': '...--',
        '4': '....-', '5': '.....', '6': '-....', '7': '--...',
        '8': '---..', '9': '----.'
    }
    
    # モールス信号を光で表現
    def blink_morse(text):
        dot_duration = 0.2  # 短点の長さ(秒)
        
        for char in text.upper():
            if char in morse_code:
                print(f"{char}: {morse_code[char]}")
                for symbol in morse_code[char]:
                    if symbol == '.':
                        led.value = False  # LED点灯
                        time.sleep(dot_duration)
                        led.value = True   # LED消灯
                    elif symbol == '-':
                        led.value = False  # LED点灯
                        time.sleep(dot_duration * 3)  # 長点は短点の3倍
                        led.value = True   # LED消灯
                    time.sleep(dot_duration)  # 符号間の間隔
                time.sleep(dot_duration * 3)  # 文字間の間隔
            elif char == ' ':
                time.sleep(dot_duration * 7)  # 単語間の間隔
    
    # ボタンが押された時間を測定
    def measure_button_press():
        if not button.value:  # ボタンが押された(負論理)
            start_time = time.monotonic()
            while not button.value:  # 押されている間待つ
                pass
            duration = time.monotonic() - start_time
            return duration
        return 0
    
    # クイズモード
    def quiz_mode():
        words = ['SOS', 'HELLO', 'PYTHON', 'XIAO', 'LED']
        word = random.choice(words)
        
        print(f"\n📝 クイズ: 次の単語をモールス信号で表現します")
        print("何という単語でしょう?\n")
        
        time.sleep(2)
        blink_morse(word)
        
        print(f"\n正解は... {word} でした!")
        print("ボタンを押すと次の問題へ")
        
        # ボタンが押されるまで待つ
        while button.value:
            pass
        time.sleep(0.5)  # デバウンス
    
    print("🔦 モールス信号トレーナー")
    print("ボタンを押すとクイズが始まります")
    
    while True:
        if not button.value:  # ボタンが押された
            quiz_mode()
    

    このプログラム、意外と勉強になるんですよ。SOSのモールス信号「・・・---・・・」って、実際に光で見ると結構分かりやすいんです。

    私の甥っ子(小学5年生)に見せたら、「おじちゃん、これで秘密の通信できるじゃん!」って大興奮でした。その後、自分でモールス信号表を印刷して、友達と暗号ごっこしてるらしいです(笑)。

    PWMを使ったLEDの明るさ制御

    デジタル出力だけじゃなく、PWM(パルス幅変調)を使ってLEDの明るさを制御してみましょう。呼吸するように明滅するLED、通称「ブリージングLED」を作ります。

    import board
    import pwmio
    import time
    import math
    
    # PWM出力の設定(D0ピンに外部LED接続)
    # 注意:外部LEDを使う場合は必ず抵抗(220Ω程度)を入れてください
    led_pwm = pwmio.PWMOut(board.D0, frequency=5000, duty_cycle=0)
    
    def breathing_led():
        """呼吸するようにLEDを明滅させる"""
        steps = 100
        for i in range(steps):
            # サイン波を使って自然な明滅を実現
            brightness = (math.sin(i * 2 * math.pi / steps - math.pi/2) + 1) / 2
            duty_cycle = int(brightness * 65535)
            led_pwm.duty_cycle = duty_cycle
            time.sleep(0.02)
    
    def pulse_led(times=3):
        """指定回数パルス点灯"""
        for _ in range(times):
            # 急速に明るくなって、ゆっくり暗くなる
            for duty in range(0, 65536, 4096):
                led_pwm.duty_cycle = duty
                time.sleep(0.001)
            for duty in range(65535, -1, -1024):
                led_pwm.duty_cycle = duty
                time.sleep(0.002)
            time.sleep(0.2)
    
    def rainbow_fade():
        """虹色っぽく明るさを変化させる(単色LEDだけど)"""
        # 実際には色は変わらないけど、明るさの変化パターンで表現
        pattern = [0, 30000, 65535, 30000, 0, 10000, 40000, 10000]
        for target in pattern:
            current = led_pwm.duty_cycle
            step = 1000 if target > current else -1000
            
            while abs(current - target) > abs(step):
                current += step
                led_pwm.duty_cycle = current
                time.sleep(0.005)
    
    print("💫 LED エフェクトデモ")
    print("1: ブリージング, 2: パルス, 3: レインボー")
    
    effect_count = 0
    while True:
        effect_type = effect_count % 3
        
        if effect_type == 0:
            print("🌬️ ブリージングエフェクト")
            for _ in range(3):
                breathing_led()
        elif effect_type == 1:
            print("⚡ パルスエフェクト")
            pulse_led(5)
        else:
            print("🌈 レインボーエフェクト")
            rainbow_fade()
        
        effect_count += 1
        time.sleep(1)
    

    PWMって最初は難しそうに感じるかもしれませんが、要は「高速でON/OFFを繰り返して、ONの時間の割合で明るさを調整する」だけです。

    duty_cycleっていうのがその割合を表していて、0が完全に消灯、65535が完全に点灯です。32768なら半分の明るさになります。

    このブリージングLED、夜中にPCの横で光らせておくと、なんかおしゃれなんですよね。友達が家に来た時、「それ何?かっこいい!」って言われて、ちょっと得意げになっちゃいました。

    I2C通信でOLEDディスプレイを制御

    さらにステップアップして、OLEDディスプレイを使ってみましょう。SSD1306という128×64ピクセルの小さなディスプレイです。

    import board
    import busio
    import time
    import adafruit_ssd1306
    import adafruit_framebuf
    
    # I2C設定
    i2c = busio.I2C(board.SCL, board.SDA)
    
    # OLEDディスプレイの初期化(128x64、アドレス0x3C)
    display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)
    
    # 画面をクリア
    display.fill(0)
    display.show()
    
    def draw_face(mood="happy"):
        """顔を描画する"""
        display.fill(0)  # 画面クリア
        
        # 顔の輪郭
        display.circle(64, 32, 30, 1)
        
        if mood == "happy":
            # 目
            display.fill_rect(50, 25, 8, 8, 1)
            display.fill_rect(70, 25, 8, 8, 1)
            # 口(笑顔)
            for x in range(50, 78):
                y = int(40 + 5 * ((x - 64) / 14) ** 2)
                display.pixel(x, y, 1)
        elif mood == "sad":
            # 目
            display.line(50, 25, 58, 30, 1)
            display.line(58, 25, 50, 30, 1)
            display.line(70, 25, 78, 30, 1)
            display.line(78, 25, 70, 30, 1)
            # 口(悲しい)
            for x in range(50, 78):
                y = int(45 - 5 * ((x - 64) / 14) ** 2)
                display.pixel(x, y, 1)
        elif mood == "surprised":
            # 目(丸い)
            display.circle(54, 28, 5, 1)
            display.circle(74, 28, 5, 1)
            # 口(O型)
            display.circle(64, 45, 8, 1)
        
        display.show()
    
    def scrolling_text(text, y=30):
        """テキストをスクロール表示"""
        text_width = len(text) * 6  # 1文字約6ピクセル
        
        for offset in range(128 + text_width):
            display.fill(0)
            display.text(text, 128 - offset, y, 1)
            display.show()
            time.sleep(0.03)
    
    def display_sensor_data(temp=25.5, humidity=60):
        """センサーデータを表示"""
        display.fill(0)
        
        # タイトル
        display.text("Environment", 25, 5, 1)
        display.line(0, 15, 127, 15, 1)
        
        # 温度
        display.text(f"Temp: {temp:.1f}C", 10, 25, 1)
        
        # 湿度  
        display.text(f"Humi: {humidity:.1f}%", 10, 40, 1)
        
        # 快適度バー
        comfort = 50 + (25 - temp) * 5 + (50 - humidity)
        comfort = max(0, min(100, comfort))  # 0-100に制限
        
        display.text("Comfort:", 10, 55, 1)
        display.rect(70, 53, 52, 10, 1)  # 外枠
        display.fill_rect(72, 55, int(comfort / 2), 6, 1)  # バー
        
        display.show()
    
    # アニメーション付き起動画面
    def boot_animation():
        for radius in range(1, 32, 2):
            display.fill(0)
            display.circle(64, 32, radius, 1)
            display.show()
            time.sleep(0.02)
        
        scrolling_text("CircuitPython OLED Demo!")
    
    print("🖥️ OLEDディスプレイデモ開始")
    
    boot_animation()
    
    moods = ["happy", "sad", "surprised"]
    mood_index = 0
    temp = 25.0
    humidity = 50.0
    
    while True:
        # 3秒ごとに表示を切り替え
        print(f"顔を表示: {moods[mood_index]}")
        draw_face(moods[mood_index])
        time.sleep(3)
        
        # センサーデータを表示(ダミーデータ)
        temp += 0.5
        humidity += 2
        if temp > 30: temp = 20
        if humidity > 80: humidity = 40
        
        print(f"センサーデータ表示: 温度={temp:.1f}°C, 湿度={humidity:.1f}%")
        display_sensor_data(temp, humidity)
        time.sleep(3)
        
        mood_index = (mood_index + 1) % len(moods)
    

    OLEDディスプレイがあると、一気に「作品っぽく」なりますよね。数値だけじゃなくて、グラフとか顔とか、視覚的な表現ができるのが楽しいです。

    私はこれを使って、デスクトップの天気表示器を作りました。OpenWeatherMapのAPIと組み合わせて、現在の天気と気温を表示するやつです。晴れの日は太陽のアイコン、雨の日は傘のアイコンを表示するようにしたら、朝起きてすぐに今日の天気が分かって便利です。

    メモリ管理のコツとトラブルシューティング

    CircuitPythonを使っていると、たまに「MemoryError」に遭遇することがあります。特に画像処理やネットワーク通信をする時に起きやすいです。

    メモリ使用量を確認する方法:

    import gc
    
    def show_memory_info():
        gc.collect()  # ガベージコレクション実行
        free_memory = gc.mem_free()
        used_memory = gc.mem_alloc()
        total_memory = free_memory + used_memory
        
        print(f"メモリ情報:")
        print(f"  総メモリ: {total_memory:,} bytes")
        print(f"  使用中: {used_memory:,} bytes ({used_memory/total_memory*100:.1f}%)")
        print(f"  空き: {free_memory:,} bytes ({free_memory/total_memory*100:.1f}%)")
        
        if free_memory < 10000:
            print("⚠️ メモリが少なくなっています!")
            
    # プログラムの最初と最後でメモリをチェック
    show_memory_info()
    
    # ここに処理を書く
    
    show_memory_info()
    

    メモリを節約するテクニック:

    1. 文字列の連結を避ける

      1. # ダメな例 message = "温度: " + str(temp) + "°C" # 良い例 message = f"温度: {temp}°C"

    2. 大きなリストは使い終わったら削除

      1. data = [i for i in range(1000)] # 処理... del data # 明示的に削除 gc.collect() # ガベージコレクション

    3. ライブラリは.mpyファイルを使う 通常の.pyファイルより、コンパイル済みの.mpyファイルの方がメモリ使用量が少ないです。

    4. 定数は別ファイルに

      1. # constants.py SENSOR_PINS = {...} ERROR_MESSAGES = {...} # main.py from constants import SENSOR_PINS

    私が一番ハマったのは、Web APIからJSONデータを取得する時でした。天気情報のJSONが意外と大きくて、パースする時にメモリエラーが...。

    解決策は、必要な部分だけを取り出すようにしたこと:

    import json
    
    # ダメな例:全部パースしてからアクセス
    # data = json.loads(response_text)
    # temp = data['main']['temp']
    
    # 良い例:ストリーミングでパース(仮想的なコード)
    def extract_temperature(json_text):
        # "temp":の後の数値だけを抽出
        temp_index = json_text.find('"temp":')
        if temp_index != -1:
            start = temp_index + 7
            end = json_text.find(',', start)
            return float(json_text[start:end])
        return None
    

    実用的なプロジェクト例:スマートデスクライト

    ここまでの知識を総動員して、実用的なものを作ってみましょう。「スマートデスクライト」です。

    機能:

    • 周囲の明るさに応じて自動調光

    • タッチセンサーでON/OFF

    • 時間帯によって色温度を変更(実際には明るさパターンで表現)

    • 長時間作業アラート

    必要な部品:

    • XIAO RP2350

    • 光センサー(フォトレジスタ)

    • タッチセンサー(または導電性テープ)

    • パワーLED(白色)

    • MOSFETまたはトランジスタ(LED駆動用)

    import board
    import analogio
    import touchio
    import pwmio
    import time
    import math
    
    # センサーとLEDの設定
    light_sensor = analogio.AnalogIn(board.A0)  # 光センサー
    touch_sensor = touchio.TouchIn(board.D1)    # タッチセンサー
    led = pwmio.PWMOut(board.D2, frequency=5000)  # LED
    
    # グローバル変数
    is_on = False
    work_start_time = None
    last_break_time = time.monotonic()
    auto_mode = True
    manual_brightness = 32768
    
    def read_ambient_light():
        """周囲の明るさを読み取る(0-100%)"""
        # 16ビットADC値を0-100%に変換
        return (65535 - light_sensor.value) / 655.35
    
    def get_time_based_brightness():
        """時間帯に応じた明るさを返す"""
        current_hour = time.localtime().tm_hour
        
        if 6 <= current_hour < 9:
            # 朝:徐々に明るく
            return 40 + (current_hour - 6) * 20
        elif 9 <= current_hour < 17:
            # 日中:明るめ
            return 80
        elif 17 <= current_hour < 20:
            # 夕方:少し暗く
            return 60
        elif 20 <= current_hour < 22:
            # 夜:暗め(ブルーライト軽減)
            return 40
        else:
            # 深夜:最小限の明るさ
            return 20
    
    def calculate_optimal_brightness():
        """最適な明るさを計算"""
        if not auto_mode:
            return manual_brightness
        
        ambient = read_ambient_light()
        time_brightness = get_time_based_brightness()
        
        # 周囲が暗いほどLEDを明るく、でも時間帯も考慮
        if ambient < 20:  # とても暗い
            target = time_brightness
        elif ambient < 50:  # 普通
            target = time_brightness * 0.7
        else:  # 明るい
            target = time_brightness * 0.3
        
        return int(target * 655.35)
    
    def smooth_transition(current, target, steps=20):
        """スムーズな明るさ遷移"""
        step_size = (target - current) / steps
        for i in range(steps):
            led.duty_cycle = int(current + step_size * i)
            time.sleep(0.02)
        led.duty_cycle = target
    
    def check_work_timer():
        """長時間作業のチェック"""
        global last_break_time
        
        if work_start_time is None:
            return
        
        work_duration = time.monotonic() - work_start_time
        since_break = time.monotonic() - last_break_time
        
        # 50分ごとに休憩を促す
        if since_break > 3000:  # 50分
            print("⏰ 休憩時間です!10分間目を休めましょう")
            # LEDを3回点滅させて通知
            for _ in range(3):
                current = led.duty_cycle
                smooth_transition(current, 0, 10)
                time.sleep(0.2)
                smooth_transition(0, current, 10)
                time.sleep(0.2)
            last_break_time = time.monotonic()
    
    def handle_touch():
        """タッチセンサーの処理"""
        global is_on, auto_mode, manual_brightness, work_start_time
        
        if touch_sensor.value:
            touch_start = time.monotonic()
            
            # 長押し判定
            while touch_sensor.value:
                if time.monotonic() - touch_start > 2:
                    # 2秒長押しでモード切替
                    auto_mode = not auto_mode
                    mode = "自動" if auto_mode else "手動"
                    print(f"🔄 モード切替: {mode}モード")
                    
                    # モード切替を光で通知
                    for _ in range(2):
                        led.duty_cycle = 65535
                        time.sleep(0.1)
                        led.duty_cycle = 0
                        time.sleep(0.1)
                    
                    time.sleep(0.5)  # デバウンス
                    return
            
            # 短押しでON/OFF
            is_on = not is_on
            
            if is_on:
                print("💡 ライトON")
                work_start_time = time.monotonic()
                target = calculate_optimal_brightness()
                smooth_transition(0, target)
            else:
                print("💤 ライトOFF")
                work_start_time = None
                smooth_transition(led.duty_cycle, 0)
            
            time.sleep(0.3)  # デバウンス
    
    # 起動メッセージ
    print("🌟 スマートデスクライト起動")
    print("タッチ: ON/OFF, 長押し: 自動/手動切替")
    
    # メインループ
    update_counter = 0
    
    while True:
        # タッチセンサーチェック
        handle_touch()
        
        # ライトがONの時だけ処理
        if is_on:
            # 10回に1回だけ明るさを更新(負荷軽減)
            if update_counter % 10 == 0:
                target = calculate_optimal_brightness()
                current = led.duty_cycle
                
                # 大きな変化がある時だけ調整
                if abs(target - current) > 3000:
                    smooth_transition(current, target)
                    
                    ambient = read_ambient_light()
                    print(f"📊 環境光: {ambient:.1f}%, LED: {target//655:.0f}%")
            
            # 作業時間チェック
            if update_counter % 600 == 0:  # 約1分ごと
                check_work_timer()
        
        update_counter += 1
        time.sleep(0.1)
    

    このスマートデスクライト、実際に使ってみるとめちゃくちゃ便利です。特に夜中にプログラミングしてる時、自動で暗めになってくれるのがありがたい。

    最初は「自動調光なんていらないでしょ」って思ってたんですが、使い始めたら手放せなくなりました。朝は明るく、夜は暗く、自然に調整されるので目が疲れにくいんです。

    データロギング機能を追加する

    さらに実用的にするため、センサーデータをSDカードに記録する機能を追加してみましょう。

    import board
    import busio
    import sdcardio
    import storage
    import time
    import json
    
    # SDカードの初期化
    spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
    cs = board.D5  # チップセレクトピン
    sdcard = sdcardio.SDCard(spi, cs)
    vfs = storage.VfsFat(sdcard)
    storage.mount(vfs, "/sd")
    
    class DataLogger:
        def __init__(self, filename="/sd/sensorlog.txt"):
            self.filename = filename
            self.buffer = []
            self.buffer_size = 10  # 10件ごとに書き込み
            
            # ヘッダーを書き込み
            try:
                with open(self.filename, "r") as f:
                    # ファイルが存在する場合は何もしない
                    pass
            except:
                # 新規ファイルの場合はヘッダーを書く
                with open(self.filename, "w") as f:
                    f.write("timestamp,temperature,humidity,light,comfort\n")
        
        def log(self, data):
            """データをバッファに追加"""
            timestamp = time.monotonic()
            data['timestamp'] = timestamp
            self.buffer.append(data)
            
            # バッファが満杯になったら書き込み
            if len(self.buffer) >= self.buffer_size:
                self.flush()
        
        def flush(self):
            """バッファの内容をファイルに書き込み"""
            if not self.buffer:
                return
            
            try:
                with open(self.filename, "a") as f:
                    for data in self.buffer:
                        line = f"{data['timestamp']:.2f},"
                        line += f"{data.get('temperature', 0):.1f},"
                        line += f"{data.get('humidity', 0):.1f},"
                        line += f"{data.get('light', 0):.1f},"
                        line += f"{data.get('comfort', 0):.0f}\n"
                        f.write(line)
                
                print(f"💾 {len(self.buffer)}件のデータを保存しました")
                self.buffer.clear()
                
            except Exception as e:
                print(f"❌ 書き込みエラー: {e}")
        
        def read_statistics(self):
            """統計情報を読み取る"""
            try:
                temps = []
                humis = []
                
                with open(self.filename, "r") as f:
                    f.readline()  # ヘッダーをスキップ
                    
                    for line in f:
                        parts = line.strip().split(',')
                        if len(parts) >= 3:
                            temps.append(float(parts[1]))
                            humis.append(float(parts[2]))
                
                if temps:
                    return {
                        'temp_avg': sum(temps) / len(temps),
                        'temp_max': max(temps),
                        'temp_min': min(temps),
                        'humi_avg': sum(humis) / len(humis),
                        'count': len(temps)
                    }
            except:
                pass
            
            return None
    
    # 使用例
    logger = DataLogger()
    
    print("📊 データロガー開始")
    
    # ダミーセンサーデータ(実際はセンサーから取得)
    temp = 25.0
    humidity = 50.0
    light_level = 70.0
    
    for i in range(100):
        # センサーデータをシミュレート
        temp += (time.monotonic() % 10 - 5) * 0.1
        humidity += (time.monotonic() % 8 - 4) * 0.5
        light_level = 50 + 30 * math.sin(i * 0.1)
        
        comfort = 50 + (25 - temp) * 2 + (50 - humidity)
        
        # データをログ
        logger.log({
            'temperature': temp,
            'humidity': humidity,
            'light': light_level,
            'comfort': comfort
        })
        
        print(f"記録 #{i+1}: 温度={temp:.1f}°C, 湿度={humidity:.1f}%")
        
        time.sleep(1)
        
        # 30件ごとに統計を表示
        if (i + 1) % 30 == 0:
            stats = logger.read_statistics()
            if stats:
                print("\n📈 統計情報:")
                print(f"  温度: 平均={stats['temp_avg']:.1f}°C")
                print(f"       最高={stats['temp_max']:.1f}°C")
                print(f"       最低={stats['temp_min']:.1f}°C")
                print(f"  湿度: 平均={stats['humi_avg']:.1f}%")
                print(f"  記録数: {stats['count']}件\n")
    
    # 最後にバッファを書き込み
    logger.flush()
    

    データロギング機能があると、長期的な環境の変化を追跡できます。私はこれを使って、部屋の温度と湿度を1週間記録して、エアコンの最適な設定を見つけました。

    意外だったのは、深夜2時頃に湿度が急上昇することがあるってこと。調べてみたら、外気温が下がって相対湿度が上がるからだそうです。データって面白いですね。

    ネットワーク機能:Wi-Fi接続とWebサーバー

    XIAO RP2350にはWi-Fi機能はありませんが、ESP32-C3のようなWi-Fi対応マイコンを使えば、IoTデバイスも作れます。

    import wifi
    import socketpool
    import time
    from adafruit_httpserver import Server, Request, Response
    
    # Wi-Fi接続
    print("🌐 Wi-Fi接続中...")
    wifi.radio.connect("YOUR_SSID", "YOUR_PASSWORD")
    print(f"接続成功!IPアドレス: {wifi.radio.ipv4_address}")
    
    # Webサーバーの設定
    pool = socketpool.SocketPool(wifi.radio)
    server = Server(pool, debug=True)
    
    # センサーデータ(ダミー)
    sensor_data = {
        'temperature': 25.5,
        'humidity': 60.0,
        'light': 750,
        'last_update': time.monotonic()
    }
    
    # HTMLテンプレート
    def generate_html():
        return f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>センサーダッシュボード</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <style>
                body {{
                    font-family: Arial, sans-serif;
                    background: linear-gradient(135deg, #667eea  0%, #764ba2  100%);
                    color: white;
                    padding: 20px;
                }}
                .container {{
                    max-width: 600px;
                    margin: 0 auto;
                }}
                .card {{
                    background: rgba(255, 255, 255, 0.1);
                    border-radius: 15px;
                    padding: 20px;
                    margin: 20px 0;
                    backdrop-filter: blur(10px);
                }}
                .sensor-value {{
                    font-size: 3em;
                    font-weight: bold;
                }}
                .sensor-label {{
                    font-size: 1.2em;
                    opacity: 0.8;
                }}
                .update-time {{
                    text-align: center;
                    opacity: 0.6;
                    margin-top: 20px;
                }}
            </style>
            <script>
                setTimeout(() => location.reload(), 5000);  // 5秒ごとに自動更新
            </script>
        </head>
        <body>
            <div class="container">
                <h1>🏠 環境センサーダッシュボード</h1>
                
                <div class="card">
                    <div class="sensor-label">🌡️ 温度</div>
                    <div class="sensor-value">{sensor_data['temperature']:.1f}°C</div>
                </div>
                
                <div class="card">
                    <div class="sensor-label">💧 湿度</div>
                    <div class="sensor-value">{sensor_data['humidity']:.1f}%</div>
                </div>
                
                <div class="card">
                    <div class="sensor-label">☀️ 明るさ</div>
                    <div class="sensor-value">{sensor_data['light']:.0f} lux</div>
                </div>
                
                <div class="update-time">
                    最終更新: {time.monotonic() - sensor_data['last_update']:.0f}秒前
                </div>
            </div>
        </body>
        </html>
        """
    
    @server.route("/")
    def root(request: Request):
        return Response(request, generate_html(), content_type="text/html")
    
    @server.route("/api/sensors")
    def api_sensors(request: Request):
        import json
        return Response(request, json.dumps(sensor_data), content_type="application/json")
    
    # サーバー起動
    print(f"🚀 Webサーバー起動: http://{wifi.radio.ipv4_address}")
    server.serve_forever()
    

    これをスマホのブラウザで開くと、リアルタイムでセンサーデータが見られます。家の中のどこからでも温度をチェックできるって、地味に便利なんですよ。

    パフォーマンス最適化のテクニック

    CircuitPythonは便利ですが、速度面ではC++に劣ります。でも、工夫次第でかなり改善できます。

    import time
    import array
    
    # テクニック1: 事前計算とルックアップテーブル
    # サイン波のルックアップテーブルを作成
    SINE_TABLE = array.array('h', [int(32767 * math.sin(i * 2 * math.pi / 256)) 
                                   for i in range(256)])
    
    def fast_sine_wave(phase):
        """高速サイン波生成"""
        index = phase % 256
        return SINE_TABLE[index]
    
    # テクニック2: ビット演算の活用
    def fast_rgb_to_565(r, g, b):
        """RGB888をRGB565に高速変換"""
        # 通常の方法
        # return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)
        
        # ビットシフトを最適化
        return ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3)
    
    # テクニック3: メモ化(計算結果のキャッシュ)
    _fibonacci_cache = {}
    
    def fast_fibonacci(n):
        """キャッシュを使った高速フィボナッチ数列"""
        if n in _fibonacci_cache:
            return _fibonacci_cache[n]
        
        if n <= 1:
            result = n
        else:
            result = fast_fibonacci(n-1) + fast_fibonacci(n-2)
        
        _fibonacci_cache[n] = result
        return result
    
    # テクニック4: リスト内包表記vs通常のループ
    def benchmark_list_operations():
        """リスト操作のベンチマーク"""
        import time
        
        # 通常のループ
        start = time.monotonic()
        result1 = []
        for i in range(1000):
            if i % 2 == 0:
                result1.append(i * 2)
        time1 = time.monotonic() - start
        
        # リスト内包表記(高速)
        start = time.monotonic()
        result2 = [i * 2 for i in range(1000) if i % 2 == 0]
        time2 = time.monotonic() - start
        
        print(f"通常のループ: {time1:.4f}秒")
        print(f"リスト内包表記: {time2:.4f}秒")
        print(f"速度向上: {time1/time2:.2f}倍")
    
    # テクニック5: 文字列操作の最適化
    def efficient_string_building():
        """効率的な文字列構築"""
        # 悪い例:文字列連結
        # result = ""
        # for i in range(100):
        #     result += str(i) + ","
        
        # 良い例:joinを使用
        parts = [str(i) for i in range(100)]
        result = ",".join(parts)
        return result
    
    # テクニック6: 定数の事前定義
    # 定数は大文字で定義し、計算済みの値を使う
    PI_TIMES_2 = 6.283185307179586
    SQRT_2 = 1.4142135623730951
    GOLDEN_RATIO = 1.618033988749895
    
    def optimized_calculation(radius):
        """最適化された円周計算"""
        # return 2 * math.pi * radius  # 遅い
        return PI_TIMES_2 * radius  # 速い
    
    print("⚡ パフォーマンス最適化テスト")
    benchmark_list_operations()
    
    # 実測してみると、リスト内包表記は通常のループより約1.5倍速いことが分かります。
    # こういう小さな最適化の積み重ねが、全体のパフォーマンスを大きく改善します。
    
    ### CircuitPythonからArduinoへの移行を考える時
    
    正直に言うと、CircuitPythonには限界があります。でも、それは悪いことじゃないんです。
    
    私がArduinoへの移行を検討したのは、こんな時でした:
    
    1. **リアルタイム性が必要になった時**
       ロボットアームを作ってた時、サーボモーターの制御が追いつかなくなりました。1ミリ秒単位の精密な制御が必要で、CircuitPythonでは無理でした。
    
    2. **特殊なライブラリが必要になった時**
       CANバス通信をしたくて探したら、Arduinoには豊富なライブラリがあるのに、CircuitPythonには無い...。自分で実装するのは大変すぎました。
    
    3. **メモリが足りなくなった時**
       画像処理をやろうとしたら、320×240ピクセルのビットマップでメモリオーバー。Arduinoなら外部RAMを使える方法があったんです。
    
    でも、CircuitPythonで学んだことは無駄になりません。プログラミングの基礎、センサーの扱い方、通信プロトコルの理解...全部Arduinoでも活きます。
    
    むしろ、CircuitPythonで「こういうことがしたい」というビジョンを明確にしてからArduinoに移行する方が、スムーズに進みます。
    
    ### 私のCircuitPython失敗談
    
    ここで、私の失敗談をいくつか共有しますね。同じ失敗をしないでください...!
    
    **失敗その1:電源を考えなかった**
    
    USBから給電してテストしてたプロジェクトを、電池駆動にしたら動かない!原因は、電池の電圧降下でした。新品の電池は1.5Vですが、使ってると1.2Vくらいまで下がります。3本直列で3.6V...XIAOの最低動作電圧ギリギリでした。
    
    解決策:昇圧DCDCコンバーターを使うか、リチウムイオン電池を使いましょう。
    
    **失敗その2:ピンを壊した**
    
    LEDを直接ピンに繋いで光らせてたら、ある日突然そのピンが使えなくなりました。電流制限抵抗を入れ忘れてたんです。マイコンのピンは最大でも20mAくらいしか流せません。
    
    解決策:必ず抵抗を入れる。220Ω〜1kΩくらいが安全です。
    
    **失敗その3:無限ループで詰んだ**
    
    code.pyに無限ループを書いて、しかもtime.sleepを入れ忘れました。結果、マイコンがフリーズしたように見えて、プログラムの書き換えができない!
    
    解決策:セーフモードで起動します。リセットボタンを連打しながらUSB接続すると、code.pyを実行せずに起動できます。
    
    **失敗その4:相対インポートでハマった**
    
    libフォルダにmy_module.pyを作って、その中で別のモジュールをインポートしようとしたら、エラーの嵐。CircuitPythonは相対インポートに対応してないんです。
    
    解決策:絶対インポートを使うか、全部code.pyに書く。
    
    ### コミュニティとリソース
    
    CircuitPythonの素晴らしいところは、コミュニティの温かさです。
    
    **日本語リソース**
    - スイッチサイエンスのブログ:製品紹介と一緒に使い方も解説
    - Qiita:「CircuitPython」タグで検索すると、いろんな作例が
    - Twitter:#CircuitPython のハッシュタグで情報収集
    
    **英語リソース**
    - Adafruit Learn:公式チュートリアルが山ほど
    - Discord:CircuitPython公式サーバーがあって、質問するとすぐ答えが返ってくる
    - GitHub:ライブラリのソースコードを読むと勉強になる
    
    私が一番助けられたのは、Discordサーバーです。「このセンサー使いたいんだけど、ライブラリある?」って聞いたら、「今作ってるから待って!」って返事が来て、3日後に公開されました。すごくないですか?
    
    ### 作品を公開する時のコツ
    
    せっかく作った作品、どうせなら公開しましょう!
    
    **GitHubで公開する時**
    

    my-circuitpython-project/ ├── README.md # プロジェクトの説明 ├── code.py # メインコード ├── lib/ # 必要なライブラリ ├── docs/ # 配線図とか │ ├── wiring.png # 配線図 │ └── parts_list.md # 部品リスト ├── images/ # 完成写真 └── LICENSE # ライセンス(MITがおすすめ)

    
    **README.mdに書くべきこと**
    - 何を作ったか(動画があるとベスト)
    - 必要な部品とその入手先
    - 配線方法(図があると親切)
    - セットアップ手順
    - 使い方
    - トラブルシューティング
    - 今後の改善予定
    
    私の経験では、動画があると反応が10倍違います。TwitterにGIF動画を投稿して、GitHubのリンクを貼るのが効果的でした。
    
    ### よくある質問と回答
    
    ここまで読んでくれた方から、よく聞かれる質問をまとめました。
    
    **Q: CircuitPythonとMicroPythonの違いは?**
    
    CircuitPythonはMicroPythonをベースに、Adafruitが初心者向けに改良したものです。主な違いは:
    - ライブラリが豊富(特にセンサー関連)
    - エラーメッセージが分かりやすい
    - USBマスストレージ機能が標準
    - REPLが使いやすい
    
    個人的には、初心者ならCircuitPython一択です。
    
    **Q: どのマイコンがおすすめ?**
    
    予算と用途によりますが:
    - 初心者:XIAO RP2350(小さくて安い)
    - Wi-Fi必要:ESP32-S3(技適取得済み)
    - たくさんのピン:Raspberry Pi Pico(コスパ最強)
    - 高性能:Teensy 4.1(でもCircuitPython対応は限定的)
    
    私のイチオシはやっぱりXIAO RP2350です。
    
    **Q: 電池で動かしたいんだけど?**
    
    リチウムポリマー電池がおすすめです。3.7Vで、XIAOなら直接繋げます。充電回路付きのボードもあるので、それを使うと便利。単三電池なら、3本直列+昇圧DCDCコンバーター。
    
    **Q: もっと速く動かしたい!**
    
    オーバークロックができます:
    ```python
    import microcontroller
    microcontroller.cpu.frequency = 250000000  # 250MHz
    

    ただし、発熱と消費電力が増えるので注意。あと、不安定になることも。

    Q: ファイルが消えた!?

    CIRCUITPYドライブは、突然のUSB切断でファイルシステムが壊れることがあります。定期的にバックアップを取りましょう。私は毎回GitHubにpushしてます。

    Q: code.py以外のファイル名は使える?

    使えます!優先順位は:

    1. code.txt

    2. code.py

    3. main.txt

    4. main.py

    でも、code.pyが一番分かりやすいので、これを使うのがおすすめ。

    Q: デバッグはどうやるの?

    print文が基本です。でも、もっと高度なデバッグをしたいなら:

    import supervisor
    
    def debug_print(message):
        """デバッグ用プリント(リリース時は無効化しやすい)"""
        if supervisor.runtime.serial_connected:
            print(f"[DEBUG] {message}")
    
    # 使用例
    debug_print(f"センサー値: {sensor_value}")
    

    Q: 日本語は使える?

    表示は難しいですが、コメントやprint文では使えます:

    # これはOK
    print("こんにちは、CircuitPython!")
    
    # でもOLEDに日本語表示は大変(フォントが必要)
    

    Q: 他の人のコードを参考にしたい

    GitHubで「CircuitPython」で検索すると、たくさん出てきます。特に「Adafruit_CircuitPython_Bundle」のexamplesフォルダは宝の山です。

    最後に:CircuitPythonで広がる可能性

    ここまで本当に長い記事を読んでいただき、ありがとうございます!

    CircuitPythonを始めて1年、私の電子工作ライフは劇的に変わりました。以前は「アイデアはあるけど、実装が大変そう...」って諦めてたものが、今では「とりあえず作ってみるか!」って気軽に手を出せるようになりました。

    メモ帳だけで始められる手軽さ、Pythonの分かりやすさ、豊富なライブラリ、温かいコミュニティ...CircuitPythonには、電子工作を楽しくする要素が全部詰まってます。

    確かに、プロの現場で使うには力不足かもしれません。でも、趣味として、学習として、プロトタイピングとして、CircuitPythonは最高の選択肢だと思います。

    私の夢は、CircuitPythonを使って、誰もが簡単に「作りたいものを作れる」世界を実現することです。この記事が、その第一歩になれば嬉しいです。

    さあ、あなたも今すぐXIAOを手に入れて、CircuitPythonの世界に飛び込んでみませんか?きっと、新しい発見と感動が待っていますよ!

    もし何か作ったら、ぜひSNSでシェアしてくださいね。#CircuitPython のタグを付けてもらえれば、必ず見に行きます!

    それでは、楽しい電子工作ライフを!

     
     
     
    総セミナー参加者 137,977人突破!(6,880回開催) ClaudeCode専門のAIスクール #ユニコスクール 運営 🙋 スクール生 2,352人 ✋ スタッフ 25名 📻️ AI事業だけで投資先等含め売上 7億円突破!  freee認定アドバイザー

    あなたへのおすすめ