Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

DIY Arduino Sneeuwvlok: 30-LED displayproject

Onderdelen en benodigdheden

Onderdeel Aantal
Arduino Nano R3 1

Over dit project

De sneeuwvlok bestaat uit 30 LEDs gegroepeerd in 17 onafhankelijke segmenten die apart bestuurd kunnen worden door de Arduino Nano. Elke LED-groep kan met PWM gedimd worden voor mooie animaties.

Tools

Je hebt alleen een solderbout, soldeer en tang nodig.

Constructie

Kies eerst een patroon. Ik koos een mooie, simpele sneeuwvlokkristal en printte het in de grootte om de Arduino Nano in de hexagoon – de kern van de kristal – te laten passen.

DIY Arduino Sneeuwvlok: 30-LED displayproject

De ondersteuningsstructuur, die ook als bedrading fungeert, is gemaakt van 0,8mm messingstaven die met tin gesoldeerd zijn. Ik heb in totaal 2m staf gebruikt. Waarom freeform? Omdat ik dit altijd al wilde proberen en het een test is van je geduld en vaardigheid.

DIY Arduino Sneeuwvlok: 30-LED displayproject

Eerst maakte ik een kernhexagoon door een enkele staaf te buigen en de uiteinden te solderen. Door nog 6 staven aan de hoekpunten van de hexagoon toe te voegen is de massa-aardbedrading compleet; alle kathoden van de LEDs moeten nu aan deze structuur gesoldeerd worden om het sneeuwvlokpatroon te creëren. Het lastige deel was de SMD-LEDs toevoegen, maar ik hielp mezelf met een hulpmiddel van karton en dubbelzijdig tape.

DIY Arduino Sneeuwvlok: 30-LED displayproject

Vervolgens was het tijd om de Arduino Nano onder de kernstructuur te plaatsen, met voldoende ruimte ertussen voor 3 lagen messingstaf-bedadrading die de microcontrollerpinnen verbinden met alle anoden van de LEDs. Dit vereiste enorm veel geduld. Je moet niet alleen kortsluitingen tussen de draden vermijden, maar ook een stroombegrenzende weerstand toevoegen en het er mooi uit laten zien.

DIY Arduino Sneeuwvlok: 30-LED displayproject

De blad-LEDs zijn elk apart aangesloten op de dichtstbijzijnde Arduino-outputpin. De tak-LEDs zijn per twee gegroepeerd en aangesloten op PWM-pinnen. De kern-LEDs zijn ook per twee gegroepeerd en aangesloten op de overige pinnen. De Arduino Nano heeft slechts 18 outputpinnen (A6 en A7 zijn alleen input) en ik heb er één nodig voor de touchsensor, wat 17 pinnen overlaat. Daardoor zijn twee paren kern-LEDs samen aangesloten tot een groep van 4. Ik gebruik 220Ω weerstanden om de stroom per pin te beperken tot ~8mA. Dat is 240mA in totaal, wat iets hoog is voor de ATmega328-chip (veilige maximum is 200mA), maar het werkt.

Touchsensor

Om interactie met de sneeuwvlok mogelijk te maken, voegde ik een extra messingstaaf toe als capacitieve touchsensor. Ik vond een geweldige bibliotheek en tutorial van Paul Stoffregen. De touchsensor wordt gebruikt om met de 'arduinoflake' te interacteren: animatie wijzigen, aan/uit zetten, knipperen bij aanraking, etc.

DIY Arduino Sneeuwvlok: 30-LED displayproject

Eindnoot

Vergeet niet alle diodes te controleren vóór het solderen; het is heel lastig om ze later te vervangen als ze defect of omgekeerd gepoleerd zijn.

DIY Arduino Sneeuwvlok: 30-LED displayproject

Code

Oorspronkelijk dacht ik alleen de tak-LEDs (aangesloten op hardware-PWM-pinnen) te kunnen dimmen. Maar gelukkig bestaat er een geweldige software-PWM-bibliotheek waarmee ik alle pinnen kan gebruiken alsof ze hardware-PWM waren. Dit creëert oneindige animatiemogelijkheden! Bekijk de onderstaande code met de eerste animaties.

Code

snowflake.ino (Arduino)

#include "SoftPWM.h"
#include <ADCTouchSensor.h>

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;
}

Schema's

DIY Arduino Sneeuwvlok: 30-LED displayproject

Productieproces

  1. De Deegroller: Van Etrusken tot Moderne Vakmanschap
  2. De Evolutie en Vakmanschap van Moderne Bowlingpinnen
  3. Van Oude Fibulae tot Moderne Fabricage: De Veiligheidsspeld Uitgelegd
  4. Een Raspberry Pi I/O Breakout-kabel & Plugboard-adapter Bouwen – Stap-voor-stap Handleiding
  5. Dynamische LED-driehoekkunst: Bouw een 45-LED RGB-display met Arduino UNO
  6. DHT11 Temperatuur- & Vochtigheidsensor Project met LED-indicatoren en Piezo-luidspreker
  7. Ball Grid Array (BGA): wat het is en waarom het belangrijk is
  8. Hoe Doppen Uw Projecten Precies Houden: Toepassingen in Meubels, Planken en Machines
  9. Materialen voor Doppen: Hout, Metaal en Kunststof Uitgelegd
  10. 5 Belangrijke Factoren Voor Het Selecteren Van De Juiste Dwangpennen
  11. TinyML: Ingenieurs verenigen om AI te standaardiseren voor ultra-laag-vermogen systemen