工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

DIY Arduinoスノーフレーク:30個LEDディスプレイプロジェクト

部品と材料

Arduino Nano R3×1

プロジェクト概要

このスノーフレークは30個のLEDで構成され、Arduino Nanoマイクロコントローラーで個別に制御可能な17の独立したセグメントにグループ化されています。各LEDグループはPWMで調光可能で、美しいアニメーションを作成できます。

ツール

必要なのははんだごて、はんだ、ペンチだけです。

構造

まずパターンを選択します。私は素敵でシンプルな雪の結晶パターンを選び、Arduino Nanoが六角形のコア内部に収まるサイズで印刷しました。

配線を兼ねた支持構造は、0.8mmの真鍮ロッドをハンダで接続して作成。合計2mのロッドを使用しました。なぜフリーフォームなのか? ずっと挑戦してみたかったからで、忍耐と技術の試練になります。

まず単一のロッドを曲げてコアの六角形を作り、端をはんだ付け。さらに6本のロッドを六角形の頂点に追加してグランド配線を完成。すべてのLEDのカソードリードをここに接続して雪の結晶パターンを作ります。トリッキーだったのはSMD LEDの実装でしたが、段ボールと両面テープで作った治具で対応しました。

次にArduino Nanoマイクロコントローラーをコア構造の下に配置し、マイコンピンをすべてのLEDアノードリードに接続する3層の真鍮ロッド配線分のスペースを確保。これは膨大な忍耐を要しました。配線間のショートを避けつつ、電流制限抵抗も追加し、見た目もきれいにする必要があります。

葉のLEDはそれぞれ最寄りのArduino出力ピンに個別接続。枝のLEDは2個ずつグループ化してPWMピンに接続。コアのLEDも2個ずつグループ化して残りのピンに接続。Arduino NANOは出力ピンが18個しかありません(A6とA7は入力専用)。タッチセンサー用に1ピン必要なので、残り17ピンしかなく、コアLEDの2組をまとめて4個グループにしています。220Ω抵抗でピンあたり約8mAに制限、合計240mA(ATmega328チップの安全最大値は200mAと言われますが動作します)。

タッチセンサー

スノーフレークとインタラクトするため、もう1本の真鍮ロッドを追加して静電容量式タッチセンサーを作成。Paul Stoffregen氏の優れたライブラリとチュートリアルを見つけました。タッチセンサーでアニメーション変更、オン/オフ、タッチ時の輝きなど、様々なインタラクションが可能です。

最終注意点

はんだ付け前にすべてのダイオードをチェックすることを忘れないでください。後から交換するのは非常に困難です(破損や逆極性接続の場合)。

コード

当初はハードウェアPWMピンに接続された枝LEDのみ調光可能だと思っていました。しかし、すべてのピンをハードウェアPWMのように扱える素晴らしいソフトウェアPWMライブラリが存在しました! このセットアップでアニメーションの可能性が無限に広がります。以下のコードに初期アニメーションのいくつかを含めています。

snowflake.ino

#include "SoftPWM.h"
#include 

byte edgeLedPins[] = {13, A4, A5, 2, 8, 12};
byte middleLedPins[] = {10, 6, 3, 5, 9, 11};
byte innerLedPins[] = {A2, A3, A1, 4, 7, A1};
ADCTouchSensor touchSensor = ADCTouchSensor(A0, 1);

void setup() {
  Serial.begin(115200);
  SoftPWMBegin();
}

byte animation = 0;
long touchAt = 0;

void loop() {
  switch (animation) {
    case 0: _fill(100); break;
    case 1: shinyAnimation(); break;
    case 2: circleAnimation(); break;
    case 3: loopAnimation(); break;
    case 4: fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); animation++; break;
    case 5: smileAnimation(); break;
    default: animation = 0; break;
  }
  
  int touchValue = touchSensor.read();
  if (touchAt + 2000 < millis() && touchValue > 1000) {
    touchAt = millis();
    animation++;
    _fill(0);
  }
}

void fireworkAnimation() {
  for (int i = 0; i < 4; i++) { SoftPWMSet(innerLedPins[i], 100); delay(100); }
  SoftPWMSet(innerLedPins[4], 100);
  for (int i = 0; i < 6; i++) { SoftPWMSet(middleLedPins[i], 255); }
  delay(50);
  for (int i = 0; i < 6; i++) { SoftPWMSet(innerLedPins[i], 0); SoftPWMSet(edgeLedPins[i], 255); }
  delay(50);
  for (int i = 0; i < 6; i++) { SoftPWMSet(middleLedPins[i], 0); }
  delay(50);
  _fill(0);
}

void smileAnimation() {
  SoftPWMSet(innerLedPins[1], 100); SoftPWMSet(innerLedPins[3], 100);
  SoftPWMSet(middleLedPins[0], 255); SoftPWMSet(middleLedPins[5], 255);
  SoftPWMSet(edgeLedPins[2], 255); SoftPWMSet(edgeLedPins[3], 255);
  delay(2000);
  SoftPWMSet(innerLedPins[1], 0); SoftPWMSet(innerLedPins[3], 0);
  delay(100);
  SoftPWMSet(innerLedPins[1], 100); SoftPWMSet(innerLedPins[3], 100);
  delay(100);
  SoftPWMSet(innerLedPins[1], 0); SoftPWMSet(innerLedPins[3], 0);
  delay(100);
}

byte circleState[] = {100, 55, 10};
byte circleStateAnimation[] = {1, 1, 1};
void circleAnimation() {
  for (int i = 0; i < 3; i++) {
    if (circleState[i] >= 100) circleStateAnimation[i] = -1;
    else if (circleState[i] <= 10) circleStateAnimation[i] = 1;
    circleState[i] += circleStateAnimation[i];
  }
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(innerLedPins[i], circleState[0]);
    SoftPWMSet(middleLedPins[i], circleState[1]);
    SoftPWMSet(edgeLedPins[i], circleState[2]);
  }
  delay(5);
}

byte waveState[] = {100, 55, 10, 10, 55, 100};
byte waveStateAnimation[] = {1, 1, 1, -1, -1, -1};
void waveAnimation() {
  for (int i = 0; i < 6; i++) {
    if (waveState[i] >= 100) waveStateAnimation[i] = -1;
    else if (waveState[i] <= 10) waveStateAnimation[i] = 1;
    waveState[i] += waveStateAnimation[i];
  }
  for (int i = 0; i < 6; i+=2) {
    SoftPWMSet(innerLedPins[i], waveState[0]);
    SoftPWMSet(middleLedPins[i], waveState[1]);
    SoftPWMSet(edgeLedPins[i], waveState[2]);
    SoftPWMSet(innerLedPins[i+1], waveState[3]);
    SoftPWMSet(middleLedPins[i+1], waveState[4]);
    SoftPWMSet(edgeLedPins[i+1], waveState[5]);
  }
  delay(10);
}

byte loopCounter = 0; byte loopState = 150;
void loopAnimation() {
  SoftPWMSet(innerLedPins[loopCounter], loopState);
  SoftPWMSet(middleLedPins[loopCounter], loopState);
  SoftPWMSet(edgeLedPins[loopCounter], loopState);
  loopCounter = _nextIndex(loopCounter, 1);
  if (loopCounter == 0) { loopState = (loopState == 150 ? 0 : 150); }
  delay(100);
}

byte slowOnCounter = 0; byte slowOnState = 150;
void slowOnAnimation() {
  byte randomLed = random(0, 18);
  if (randomLed < 6) SoftPWMSet(innerLedPins[randomLed], slowOnState);
  else if (randomLed < 12) SoftPWMSet(middleLedPins[randomLed-6], slowOnState);
  else SoftPWMSet(edgeLedPins[randomLed-12], slowOnState);
  slowOnCounter++;
  if (slowOnCounter >= 50) { slowOnCounter = 0; slowOnState = (slowOnState == 150 ? 0 : 150); }
  delay(50);
}

byte shinyState[] = {0, 100, 0, 100, 0, 100};
byte shinyStateAnimation[] = {1, 1, 1, 1, 1, 1};
byte shinyCounter = 0;
void shinyAnimation() {
  for (int i = 0; i < 6; i++) {
    if (shinyState[i] >= 100) shinyStateAnimation[i] = -1;
    else if (shinyState[i] <= 0) shinyStateAnimation[i] = 1;
    shinyState[i] += shinyStateAnimation[i];
    SoftPWMSet(edgeLedPins[i], shinyState[i]);
  }
  shinyCounter++;
  if (shinyCounter > 10) {
    shinyCounter = 0;
    for (byte r = random(1, 3); r > 0; r--) {
      byte randomLed = random(0, 12);
      if (randomLed < 6) SoftPWMSet(innerLedPins[random(0, 6)], 255);
      else SoftPWMSet(middleLedPins[random(0, 6)], 255);
    }
  } else {
    for (int i = 0; i < 6; i++) {
      SoftPWMSet(innerLedPins[i], 20);
      SoftPWMSet(middleLedPins[i], 20);
    }
  }
  delay(30);
}

byte fadingState[] = {0, 100, 0, 100, 0, 100};
byte fadingStateAnimation[] = {1, 1, 1, 1, 1, 1};
void fadingAnimation() {
  for (int i = 0; i < 6; i++) {
    if (fadingState[i] >= 100) fadingStateAnimation[i] = -1;
    else if (fadingState[i] <= 0) fadingStateAnimation[i] = 1;
    fadingState[i] += fadingStateAnimation[i];
    SoftPWMSet(edgeLedPins[i], fadingState[i]);
    SoftPWMSet(middleLedPins[_nextIndex(i, 1)], fadingState[i]);
    SoftPWMSet(innerLedPins[i], 50);
  }
  delay(20);
}

void _fill(byte value) {
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(edgeLedPins[i], value);
    SoftPWMSet(middleLedPins[i], value);
    SoftPWMSet(innerLedPins[i], value);
  }
}

byte _prevIndex(short index, byte step) {
  index -= step;
  while (index < 0) index += 6;
  return index;
}

byte _nextIndex(short index, byte step) {
  index += step;
  while (index > 5) index -= 6;
  return index;
}

回路図

回路図画像を参照してください。

製造プロセス

  1. ローラーピン:エトルリア起源から現代の職人技へ
  2. 現代ボウリングピンの進化と職人技
  3. 古代フィビュラから現代製造へ:安全ピン完全解説
  4. Raspberry Pi I/Oブレイクアウトケーブルとプラグボードアダプターの自作:ステップバイステップガイド
  5. 動的LED三角アート: Arduino UNOで作る45個RGB LEDディスプレイ
  6. DHT11温湿度センサーで作る温度アラート – LEDとピエゾブザーで視覚/聴覚通知
  7. ボールグリッドアレイ(BGA)とは:仕組みと重要性
  8. ダウェルピンがプロジェクトの精度を守る:家具・棚・機械での活用法
  9. ダウェルピンの材質:木材、金属、プラスチックの特徴と用途
  10. ダウェルピン選定の5つの重要ポイント
  11. TinyML:エンジニアが結集し、超低消費電力システム向けAIを標準化