0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RISC-Vマイコン CH32V003でLチカボード Ver.1.0

Last updated at Posted at 2025-09-01
  • 作品概要

     •RISC-Vマイコン「CH32V003」を搭載した8×8 LED制御ボード
     •電源はコンパクトなCR2032コイン電池で駆動
     •英数字のスクロール表示が可能(プログラム制御)

  • 特徴

     •青色LEDが優しく光り、見ているだけで心が落ち着く
     •WCH-LinkEデバッガと接続することで書き込み・デバッグが可能
     •3Dプリンタ製の専用ケースで持ち運びもスマート

  • ハードウェアの主な仕様

    • マイコン:CH32V003(低消費電力・高性能なRISC-Vベース)
    • LED表示:8×8の青色LEDマトリクスを制御可能
    • 電源:CR2032ボタン電池で駆動、屋外でも気軽に持ち運び可能
    WCH-LinkEを使った書き込み・デバッグ対

  • RISC-Vマイコン CH32V003でLチカボード ボード概要

image.png

LED実装は、外部スイッチを下にしてアノード側が上側に来ます。

1756736038270.jpg

  • RISC-Vマイコン CH32V003でLチカボード 回路図

image.png

  • 書き込み方法と注意点

書き込み方法(WCH-LinkE使用)
• 接続ピン:
・5V 書き込み電源供給 供給する端子は5V側につないでください。
・GND                                
・SWDIO(デバッグ・書き込み用)
• 操作手順:
・WCH-LinkEと基板を接続
・スイッチを「WRITE」側に倒すことで書き込み可能

注意点
• PD7ピン(NRST)について:通常はリセット機能を持つNRSTピンですが、
本ボードではGPIOとして使用しています
・そのため、外部リセット信号は使用できません

  • サンプルコード

コード解説:CH32V003によるLED文字スクロール表示
このプログラムは、CH32V003マイコンを使って8×8の青色LEDマトリクスに英数字メッセージをスクロール表示するものです。Arduino記述で、視覚的に美しく、イベント展示にも最適です。

主な機能と構成

  • ピン設定
    ・行ピン(縦方向):PA1〜PD0
    ・列ピン(横方向):PC1〜PA2
    → マトリクスLEDの各ピクセルを制御するための配線

  • 表示文字列
    「HELLO NT TOKYO 2025.9.6. BLINKING WITH LOVE. DIY OR DIE」
    → メッセージをスクロール表示

  • フォント定義
    ・英大文字(A〜Z)、数字(0〜9)、スペース、ピリオドを8×8ドットで定義
    ・文字を左に90度回転させて、縦スクロールに対応

  • スクロール処理
    ・文字列をバッファに展開し、1列ずつ表示
    ・スクロール速度は scrollDisplay(100) で調整可能(100ms)


#include <Arduino.h>

// 行ピン (上端 PA1 → 下端 PD0)
const uint8_t rawPins[8] = { PA1, PD7, PD6, PD5, PD4, PD3, PD2, PD0 };

// 列ピン (左端 PC1 → 右端 PA2)
const uint8_t colPins[8] = { PC1, PC2, PC3, PC4, PC5, PC6, PC7, PA2 };

// 表示文字列
const char message[] =
  " HELLO NT TOKYO 2025.9.6. BLINKING WITH LOVE. DIY OR DIE  ";

// フォント定義(スペース、A~Z、0~9、ピリオド)
const uint8_t font[][8] = {
  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
  {0x3C,0x42,0x81,0x81,0xFF,0x81,0x81,0x81}, // A
  {0xFE,0x81,0x81,0xFE,0x81,0x81,0x81,0xFE}, // B
  {0x7E,0x81,0x80,0x80,0x80,0x80,0x81,0x7E}, // C
  {0xFC,0x82,0x81,0x81,0x81,0x81,0x82,0xFC}, // D
  {0xFF,0x80,0x80,0xFC,0x80,0x80,0x80,0xFF}, // E
  {0xFF,0x80,0x80,0xFC,0x80,0x80,0x80,0x80}, // F
  {0x7E,0x81,0x80,0x80,0x8F,0x81,0x81,0x7E}, // G
  {0x81,0x81,0x81,0xFF,0x81,0x81,0x81,0x81}, // H
  {0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x7E}, // I
  {0x1F,0x06,0x06,0x06,0x06,0x86,0x86,0x7C}, // J
  {0x81,0x82,0x84,0xF8,0x84,0x82,0x81,0x81}, // K
  {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFF}, // L
  {0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81}, // M
  {0x81,0xC1,0xA1,0x91,0x89,0x85,0x83,0x81}, // N
  {0x7E,0x81,0x81,0x81,0x81,0x81,0x81,0x7E}, // O
  {0xFE,0x81,0x81,0xFE,0x80,0x80,0x80,0x80}, // P
  {0x7E,0x81,0x81,0x81,0x89,0x85,0x82,0x7D}, // Q
  {0xFE,0x81,0x81,0xFE,0x84,0x82,0x81,0x81}, // R
  {0x7E,0x81,0x80,0x7E,0x01,0x81,0x81,0x7E}, // S
  {0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, // T
  {0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x7E}, // U
  {0x81,0x81,0x81,0x81,0x42,0x24,0x18,0x18}, // V
  {0x81,0x81,0x81,0x99,0xA5,0xC3,0x81,0x81}, // W
  {0x81,0x42,0x24,0x18,0x24,0x42,0x81,0x81}, // X
  {0x81,0x42,0x24,0x18,0x18,0x18,0x18,0x18}, // Y
  {0xFF,0x02,0x04,0x08,0x10,0x20,0x40,0xFF}, // Z
  {0x7E,0x81,0x89,0x91,0xA1,0xC1,0x81,0x7E}, // 0
  {0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x7E}, // 1
  {0x7E,0x81,0x01,0x02,0x0C,0x30,0x40,0xFF}, // 2
  {0x7E,0x81,0x01,0x1E,0x01,0x01,0x81,0x7E}, // 3
  {0x02,0x06,0x0A,0x12,0x22,0xFF,0x02,0x02}, // 4
  {0xFF,0x80,0x80,0xFE,0x01,0x01,0x81,0x7E}, // 5
  {0x3E,0x40,0x80,0xFE,0x81,0x81,0x81,0x7E}, // 6
  {0xFF,0x01,0x02,0x04,0x08,0x10,0x20,0x20}, // 7
  {0x7E,0x81,0x81,0x7E,0x81,0x81,0x81,0x7E}, // 8
  {0x7E,0x81,0x81,0x81,0x7F,0x01,0x02,0x7C}, // 9
  {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}  // .
};

const uint8_t* getFont(char c) {
  if (c == ' ')          return font[0];
  if (c >= 'A' && c <= 'Z') return font[c - 'A' + 1];
  if (c >= '0' && c <= '9') return font[c - '0' + 27];
  if (c == '.')          return font[37];
  return font[0];
}

// 90°左回転 (左右反転なし)
void rotateLeft90(const uint8_t* src, uint8_t* dst) {
  for (int y = 0; y < 8; y++) {
    dst[y] = 0;
    for (int x = 0; x < 8; x++) {
      // 元 [x][y] が新 dst[y][7-x] に来る
      if (src[x] & (1 << (7 -y))) {
        dst[y] |= (1 << ( x));
      }
    }
  }
}


uint8_t scrollBuffer[512];
int scrollLen = 0;  // 実際に書き込まれたデータ長

void buildScrollBuffer(const char* msg) {
  int len = strlen(msg), pos = 0;
  for (int i = 0; i < len; i++) {
    uint8_t tmp[8];
    rotateLeft90(getFont(msg[i]), tmp);
    // 文字データ 8列
    for (int c = 0; c < 8; c++) {
      if (pos < sizeof(scrollBuffer)) scrollBuffer[pos++] = tmp[c];
    }
    // 文字間隔 1列
    if (pos < sizeof(scrollBuffer)) scrollBuffer[pos++] = 0x00;
  }
  // 末尾スペースを文字間隔と同じ1列だけ追加
  if (pos < sizeof(scrollBuffer)) scrollBuffer[pos++] = 0x00;
  // 実データ長を記録
  scrollLen = pos;
}

void scrollDisplay(uint16_t speed) {
  int total = scrollLen;              // 修正:全長ではなく実データ長を使う

  // 0 → total-8 で左→右に流す
  for (int offset = 0; offset <= total - 8; offset++) {
    unsigned long start = millis();
    while (millis() - start < speed) {
      for (int row = 0; row < 8; row++) {
        digitalWrite(rawPins[row], LOW);
        for (int col = 0; col < 8; col++) {
          bool on = (scrollBuffer[offset + col] >> row) & 0x01;
          digitalWrite(colPins[col], on ? HIGH : LOW);
        }
        delayMicroseconds(1000);
        digitalWrite(rawPins[row], HIGH);
        for (int col = 0; col < 8; col++)
          digitalWrite(colPins[col], LOW);
      }
    }
  }
}

void setup() {
  for (int i = 0; i < 8; i++) {
    pinMode(rawPins[i], OUTPUT);  digitalWrite(rawPins[i], HIGH);
    pinMode(colPins[i], OUTPUT);  digitalWrite(colPins[i], LOW);
  }
  buildScrollBuffer(message);
}

void loop() {
  scrollDisplay(100);  // スクロール速度(ms)
}
  • ランダムにLEDを表示させるプログラム

コード解説:CH32V003で動く「ランダム点灯LEDマトリクス」
このプログラムは、CH32V003マイコンを使って8×8の青色LEDマトリクスにランダムな光のパターンを表示するものです。ArduinoIDEで、シンプルながら視覚的に心地よい「癒しの点滅」を実現しています。

#include <Arduino.h>

// RAWピン(行)
const uint8_t rawPins[8] = {PA1, PD7, PD6, PD5, PD4, PD3, PD2, PD0};
// カラムピン(列)
const uint8_t colPins[8] = {PC1, PC2, PC3, PC4, PC5, PC6, PC7, PA2};

// 表示用バッファ(8x8)
bool ledMatrix[8][8];

void setup() {
  // 初期化
  for (int i = 0; i < 8; i++) {
    pinMode(colPins[i], OUTPUT);
    digitalWrite(colPins[i], LOW); // 列はLOWで消灯

    pinMode(rawPins[i], OUTPUT);
    digitalWrite(rawPins[i], HIGH); // 行はHIGHで消灯
  }

  randomSeed(millis()); // ランダム初期化
}

void loop() {
  // ランダムに8か所選んで点灯
  clearMatrix();
  for (int i = 0; i < 8; i++) {
    int x = random(0, 8);
    int y = random(0, 8);
    ledMatrix[y][x] = true;
  }

  // 0.5秒間表示
  unsigned long start = millis();
  while (millis() - start < 500) {
    displayMatrix();
  }
}

// LEDマトリクスを表示(1行ずつスキャン)
void displayMatrix() {
  for (int y = 0; y < 8; y++) {
    digitalWrite(rawPins[y], LOW); // 行をLowに(点灯可能)

    for (int x = 0; x < 8; x++) {
      digitalWrite(colPins[x], ledMatrix[y][x] ? HIGH : LOW);
    }

    delay(2); // スキャン時間(ちらつき防止)

    // 行を戻す
    digitalWrite(rawPins[y], HIGH);
    for (int x = 0; x < 8; x++) {
      digitalWrite(colPins[x], LOW);
    }
  }
}

// バッファ初期化
void clearMatrix() {
  for (int y = 0; y < 8; y++) {
    for (int x = 0; x < 8; x++) {
      ledMatrix[y][x] = false;
    }
  }
}
  • LEDの接続

// 行ピン (上端 PA1 → 下端 PD0)
const uint8_t rawPins[8] = { PA1, PD7, PD6, PD5, PD4, PD3, PD2, PD0 };
// 列ピン (左端 PC1 → 右端 PA2)
const uint8_t colPins[8] = { PC1, PC2, PC3, PC4, PC5, PC6, PC7, PA2 };

image.png

  • PushSwitchの接続

PushSW=PD0に割り当て。
初期値 HI、Push LO
ボタンを押したらLOになるので
立下りエッジでスイッチ入力を判定する

image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?