VS Code + PlatformIOでATtiny1604に簡単書き込み!SerialUPDIでLチカとLCD表示

VS Code + PlatformIOでATtiny1604に簡単書き込み!SerialUPDIでLチカとLCD表示
スポンサーリンク

秋月電子で販売されている ATtiny1604 は、1個100円程度で手に入る小型・高性能なAVRマイコンです。
Arduino互換の環境も整っており、低消費電力でI/Oも豊富です。

今回は VS Code + PlatformIO を使って、

  • SerialUPDIによる書き込み
  • Lチカ動作確認
  • I2C接続LCD(AQM1602、SSD1306)表示

を順に試してみます。初心者でも簡単に再現できる内容です。

スポンサーリンク

開発環境の準備

  • VS Code と PlatformIO(拡張機能) のインストール
  • 新規プロジェクト作成
    • attiny1604 (自分の好きなプロジェクト名を設定する)
    • Board:ATtiny1604 (選択)
    • Framework:Arduino
    • Location(保存先)を確認して「Finish」

これでプロジェクトフォルダが自動で作成されます。

フォルダーの構成

PlatformIO は、プロジェクトフォルダごとに独立して環境を持っています

Documents/
  ├─ ATtiny1604/
  │   ├─ platformio.ini   // 構成ファイル
  │   └─ src/main.cpp     // ここにプログラムを書いて実行します
  ├─ LCD_Test/
  │   ├─ platformio.ini
  │   └─ src/main.cpp

高度な構成

ATtiny1604/
├─ platformio.ini         ← 設定ファイル
├─ src/
│   └─ main.cpp           ← ← ← 実際に書くプログラム
├─ lib/
│   └─ MyLibrary/
│       ├─ MyLibrary.h    // 自作ライブラリーのヘッダーファイルを置く場所
│       └─ MyLibrary.cpp  // 自宅ライブラリーのCPPファイルを置く場所です
└─ include/               ← (必要ならヘッダを置く場所)

platformio.ini の設定例

PlatformIO では、設定ファイル platformio.ini に書き込み方法やライブラリをまとめて指定します。

[env:attiny1604]
platform = atmelmegaavr
board = ATtiny1604
framework = arduino
upload_protocol = serialupdi
upload_port = COM3  // 自分の環境に合わせる
lib_deps =
    asukiaaa/ST7032_asukiaaa

設定のポイント

  • upload_protocol = serialupdi
    → ATtiny1604は1本線のUPDI通信で書き込みます。
    書き込みにはUSBシリアル変換モジュールと1kΩ抵抗で作る簡易UPDIアダプタが使えます。
  • lib_deps
    → ライブラリを自動インストール。ここではI2C液晶(AQM1602)用の「ST7032_asukiaaa」を指定。

SerialUPDI書き込みについて

SerialUPDI(シリアル・ユーピーディーアイ) はATtiny0/1系で採用されている新しい書き込み方式です。
詳しい説明はこちらの私のブログで確認してください

🔌配線例

USBシリアル変換モジュールATtiny1604ピン
TX → 1kΩ抵抗 → UPDIPA0 (UPDIピン)
GNDGND
5Vまたは3.3V電源VCC

これで書き込み準備完了です。

Lチカで動作確認

src/main.cpp に以下を保存。

// ATtiny1604 PA3ピン Lチカ
// megaTinyCoreではピン番号ではなく "PIN_PA3" を使用します
#include <Arduino.h>  // これを必ず最初に入れる!
#include <Wire.h>

void setup() {
  pinMode(PIN_PA3, OUTPUT);  // PA3を出力に設定
}

void loop() {
  digitalWrite(PIN_PA3, HIGH);  // LED点灯
  delay(500);                   // 500ms待機
  digitalWrite(PIN_PA3, LOW);   // LED消灯
  delay(500);                   // 500ms待機
}

ビルド アップロード

VSCODEの下部画面にビルドとuploadボタンがありますので実行してください。

PA3に接続したLEDが点滅すれば書き込み成功です。

I2C液晶接続(AQM1602 / SSD1306)

💡配線(I2C共通)

信号ATtiny1604ピン備考
SDAPB1I2Cデータ線
SCLPB0I2Cクロック線
VCC3.3Vまたは5Vモジュールに合わせる
GNDGND共通グラウンド

配線図

サンプルコード(AQM1602)

#include <Arduino.h>
#include <Wire.h>
#include <ST7032_asukiaaa.h>

ST7032_asukiaaa lcd;

void setup() {
  lcd.begin(16, 2);
  lcd.setContrast(12);
  lcd.print("Hello!");
}

void loop() {}

OLED(SSD1306)で文字表示

adafruit/Adafruit SSD1306
adafruit/Adafruit GFX Library
上記のライブラリーを使って動かしましたが表示されませんでした、しかし以前私がブログで紹介した、自作フォントを使ったプログラムで表示ができました。

フォントヘッダーファイル(SimpleFont.h)

PlatformIO では、プロジェクト内に lib フォルダを作り、その中にライブラリ、ヘッダーファイルを置くのが標準です。
今回のフォルダー構成は下記のようになります。

ATtiny1604/
 ├─ src/
 │   └─ main.cpp
 ├─ lib/
 │   └─ SimpleFont/
 │       └─ SimpleFont.h  // ここにヘッダーファイル
 └─ platformio.ini
#ifndef SIMPLEFONT_H
#define SIMPLEFONT_H
// 5x7 縦向きフォント A-Z, 0-9
const uint8_t font5x7[][7] = {
  // A-Z (26文字)
  { 0b01110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001 },  // A
  { 0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b11110 },  // B
  { 0b01110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001, 0b01110 },  // C
  { 0b11100, 0b10010, 0b10001, 0b10001, 0b10001, 0b10010, 0b11100 },  // D
  { 0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b11111 },  // E
  { 0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b10000 },  // F
  { 0b01110, 0b10001, 0b10000, 0b10111, 0b10001, 0b10001, 0b01110 },  // G
  { 0b10001, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001 },  // H
  { 0b01110, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b01110 },  // I
  { 0b00001, 0b00001, 0b00001, 0b00001, 0b10001, 0b10001, 0b01110 },  // J
  { 0b10001, 0b10010, 0b10100, 0b11000, 0b10100, 0b10010, 0b10001 },  // K
  { 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111 },  // L
  { 0b10001, 0b11011, 0b10101, 0b10001, 0b10001, 0b10001, 0b10001 },  // M
  { 0b10001, 0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001 },  // N
  { 0b01110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01110 },  // O
  { 0b11110, 0b10001, 0b10001, 0b11110, 0b10000, 0b10000, 0b10000 },  // P
  { 0b01110, 0b10001, 0b10001, 0b10001, 0b10101, 0b10010, 0b01101 },  // Q
  { 0b11110, 0b10001, 0b10001, 0b11110, 0b10100, 0b10010, 0b10001 },  // R
  { 0b01111, 0b10000, 0b10000, 0b01110, 0b00001, 0b00001, 0b11110 },  // S
  { 0b11111, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100 },  // T
  { 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01110 },  // U
  { 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01010, 0b00100 },  // V
  { 0b10001, 0b10001, 0b10001, 0b10001, 0b10101, 0b11011, 0b10001 },  // W
  { 0b10001, 0b10001, 0b01010, 0b00100, 0b01010, 0b10001, 0b10001 },  // X
  { 0b10001, 0b10001, 0b01010, 0b00100, 0b00100, 0b00100, 0b00100 },  // Y
  { 0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b10000, 0b11111 },  // Z
  // 0-9 (10文字)
  { 0b01110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b01110 },  // 0
  { 0b00100, 0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b01110 },  // 1
  { 0b01110, 0b10001, 0b00001, 0b00110, 0b01000, 0b10000, 0b11111 },  // 2
  { 0b11110, 0b00001, 0b00001, 0b01110, 0b00001, 0b00001, 0b11110 },  // 3
  { 0b00010, 0b00110, 0b01010, 0b10010, 0b11111, 0b00010, 0b00010 },  // 4
  { 0b11111, 0b10000, 0b11110, 0b00001, 0b00001, 0b10001, 0b01110 },  // 5
  { 0b00110, 0b01000, 0b10000, 0b11110, 0b10001, 0b10001, 0b01110 },  // 6
  { 0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b10000, 0b10000 },  // 7
  { 0b01110, 0b10001, 0b10001, 0b01110, 0b10001, 0b10001, 0b01110 },  // 8
  { 0b01110, 0b10001, 0b10001, 0b01111, 0b00001, 0b00010, 0b01100 },  // 9
  // a-z (26文字)
  { 0b00000, 0b00000, 0b01110, 0b00001, 0b01111, 0b10001, 0b01111 },  // a
  { 0b10000, 0b10000, 0b10110, 0b11001, 0b10001, 0b10001, 0b11110 },  // b
  { 0b00000, 0b00000, 0b01110, 0b10001, 0b10000, 0b10001, 0b01110 },  // c
  { 0b00001, 0b00001, 0b01101, 0b10011, 0b10001, 0b10001, 0b01111 },  // d
  { 0b00000, 0b00000, 0b01110, 0b10001, 0b11110, 0b10000, 0b01110 },  // e
  { 0b00110, 0b01001, 0b01000, 0b11100, 0b01000, 0b01000, 0b01000 },  // f
  { 0b00000, 0b01111, 0b10001, 0b10001, 0b01111, 0b00001, 0b01110 },  // g
  { 0b10000, 0b10000, 0b10110, 0b11001, 0b10001, 0b10001, 0b10001 },  // h
  { 0b00100, 0b00000, 0b01100, 0b00100, 0b00100, 0b00100, 0b01110 },  // i
  { 0b00010, 0b00000, 0b00110, 0b00010, 0b00010, 0b10010, 0b01100 },  // j
  { 0b10000, 0b10000, 0b10010, 0b10100, 0b11000, 0b10100, 0b10010 },  // k
  { 0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b01110 },  // l
  { 0b00000, 0b00000, 0b11010, 0b10101, 0b10101, 0b10101, 0b10101 },  // m
  { 0b00000, 0b00000, 0b10110, 0b11001, 0b10001, 0b10001, 0b10001 },  // n
  { 0b00000, 0b00000, 0b01110, 0b10001, 0b10001, 0b10001, 0b01110 },  // o
  { 0b00000, 0b00000, 0b11110, 0b10001, 0b11110, 0b10000, 0b10000 },  // p
  { 0b00000, 0b00000, 0b01111, 0b10001, 0b01111, 0b00001, 0b00001 },  // q
  { 0b00000, 0b00000, 0b10110, 0b11001, 0b10000, 0b10000, 0b10000 },  // r
  { 0b00000, 0b00000, 0b01110, 0b10000, 0b01110, 0b00001, 0b11110 },  // s
  { 0b01000, 0b01000, 0b11100, 0b01000, 0b01000, 0b01001, 0b00110 },  // t
  { 0b00000, 0b00000, 0b10001, 0b10001, 0b10001, 0b10011, 0b01101 },  // u
  { 0b00000, 0b00000, 0b10001, 0b10001, 0b01010, 0b01010, 0b00100 },  // v
  { 0b00000, 0b00000, 0b10001, 0b10001, 0b10101, 0b10101, 0b01010 },  // w
  { 0b00000, 0b00000, 0b10001, 0b01010, 0b00100, 0b01010, 0b10001 },  // x
  { 0b00000, 0b00000, 0b10001, 0b10001, 0b01111, 0b00001, 0b01110 },  // y
  { 0b00000, 0b00000, 0b11111, 0b00010, 0b00100, 0b01000, 0b11111 },  // z
  { 0b00000, 0b00100, 0b00100, 0b11111, 0b00100, 0b00100, 0b00000 },  // +
  { 0b00000, 0b00000, 0b00000, 0b11111, 0b00000, 0b00000, 0b00000 },  // -
  { 0b00000, 0b00000, 0b11111, 0b00000, 0b11111, 0b00000, 0b00000 },  // =
  { 0b11000, 0b11001, 0b00010, 0b00100, 0b01000, 0b10011, 0b00011 },  // %
  { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00110, 0b00110 },   // .
  { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000 }  // スペース
};
#endif

main.cpp

#include <Wire.h>
#include "SimpleFont.h" 
const char* mySt = "Hello World!";
#define OLED_ADDR 0x3C
const uint8_t init_cmds[] = {
  0xAE, 0x20, 0x00, 0xB0, 0xC8, 0x00, 0x10,
  0x40, 0x81, 0x7F, 0xA1, 0xA6, 0xA8, 0x3F,
  0xA4, 0xD3, 0x00, 0xD5, 0xF0, 0xD9, 0x22,
  0xDA, 0x12, 0xDB, 0x20, 0x8D, 0x14, 0xAF
};
void sendCommand(uint8_t cmd) {
  Wire.beginTransmission(OLED_ADDR);
  Wire.write(0x00);
  Wire.write(cmd);
  Wire.endTransmission();
}
void sendData(uint8_t data) {
  Wire.beginTransmission(OLED_ADDR);
  Wire.write(0x40);
  Wire.write(data);
  Wire.endTransmission();
}
void initOLED() {
  Wire.begin();
  delay(100);
  for (uint8_t i = 0; i < sizeof(init_cmds); i++) {
    sendCommand(init_cmds[i]);
  }
}
void setCursor(uint8_t x, uint8_t page) {
  sendCommand(0xB0 + page);
  sendCommand(0x00 + (x & 0x0F));
  sendCommand(0x10 + (x >> 4));
}
void clearDisplay() {
  for (uint8_t page = 0; page < 8; page++) {
    setCursor(0, page);
    for (uint8_t i = 0; i < 128; i++) {
      sendData(0x00);
    }
  }
}
void drawCharVertical(char c, uint8_t x, uint8_t page) {
  uint8_t index;
   if (c >= 'A' && c <= 'Z') {
    index = c - 'A'; // 0〜25
  } else if (c >= '0' && c <= '9') {
    index = 26 + (c - '0'); // 26〜35
  } else if (c >= 'a' && c <= 'z') {
    index = 36 + (c - 'a'); // 36〜61
  } else {
    // 特殊記号追加する
    switch (c) {
      case '+': index = 62; break;
      case '-': index = 63; break;
      case '=': index = 64; break;
      case '%': index = 65; break;
      case '.': index = 66; break;
      case ' ': index = 67; break;
      default: return; // 未定義文字は無視
    }
  }
  for (int col = 0; col < 5; col++) {
    uint8_t colBits = 0;
    for (int row = 0; row < 7; row++) {
      if (font5x7[index][row] & (1 << (4 - col))) {
        colBits |= (1 << row);
      }
    }
    setCursor(x + col, page);
    sendData(colBits);
  }
  setCursor(x + 5, page);
  sendData(0x00); // スペース
}
void drawStringVertical(const char* str, uint8_t x, uint8_t page) {
  while (*str) {
    drawCharVertical(*str, x, page);
    x += 6; // 5ドット+スペース
    str++;
  }
}
void setup() {
  initOLED();
  clearDisplay();
  drawStringVertical("HELLO123456789--", 0, 2);
   drawStringVertical("Hlloa+-=%.", 0, 4);  // テスト用
   drawStringVertical(mySt, 0, 6);
}
void loop() {
}

🧾まとめ

VS Code + PlatformIO を使えば、
ATtiny1604のような小型マイコンにも簡単にプログラムを書き込めます。

upload_protocol = serialupdi の設定で、
USBシリアル変換器と1本線UPDIケーブルだけで書き込み可能。

Lチカで動作を確認し、I2C接続の液晶やOLEDを表示すれば、
ATtiny1604の入門から実用までを1台で体験できます。

タイトルとURLをコピーしました