Innholdsfortegnelse:

LED -klokke i tre - Analog stil: 11 trinn (med bilder)
LED -klokke i tre - Analog stil: 11 trinn (med bilder)

Video: LED -klokke i tre - Analog stil: 11 trinn (med bilder)

Video: LED -klokke i tre - Analog stil: 11 trinn (med bilder)
Video: Какого числа от 1 до 31, родился человек, такая у него и вся жизнь 2024, November
Anonim
LED -klokke i tre - analog stil
LED -klokke i tre - analog stil

Det er en analog LED -klokke i tre. Jeg vet ikke hvorfor jeg ikke har sett en av disse før..selv om de digitale typene er veldig vanlige. Anyhoo, her går vi!

Trinn 1:

Bilde
Bilde
Bilde
Bilde

Kryssfinerurprosjektet startet som et enkelt startprosjekt for CNC -ruteren. Jeg så på enkle prosjekter på nettet og fant denne lampen (bildet over). Jeg hadde også sett digitale klokker som skinner gjennom trefiner (bildet ovenfor). Så å kombinere de to prosjektene var en åpenbar idé. Jeg ønsket å utfordre meg selv og bestemte meg for ikke å bruke finer, men bare et stykke tre til dette prosjektet.

Trinn 2: Design

Design
Design
Design
Design

Jeg designet klokken i Inkscape (bildet over). Designet er veldig enkelt etter valg. Jeg bestemte meg for å legge spor etter ledningene fordi jeg på dette tidspunktet var usikker på om jeg ville gå med radial eller perimeter ledninger. (Jeg bestemte meg for å gå med perimeterledninger til slutt.) En neopiksel går i hvert av de små sirkulære hullene for å vise minutt- og timetiden, med fem minutters presisjon. Sirkelen i midten vil bli rutet ut for å imøtekomme elektronikken.

Trinn 3: CNCing

CNC -bearbeiding
CNC -bearbeiding
CNC -bearbeiding
CNC -bearbeiding
CNC -bearbeiding
CNC -bearbeiding
CNC -bearbeiding
CNC -bearbeiding

Jeg designet verktøypatene på MasterCAM, og brukte en technoRouter til å frese klokken fra 3/4 tommers kryssfiner. Jeg bruker et 15 "x15" stykke til dette, med minimal sløsing. Trikset er å rute ut så mye av treverket som mulig uten å bryte gjennom treverket. Å forlate 0,05 "-0,1" er et godt valg for lyst tre. Hvis du er usikker, er det bedre å la mer tre bli igjen, fordi du alltid kan pusse det andre ansiktet. Jeg endte med å fjerne litt for mye tre fra noen deler, men heldigvis lider ikke resultatene for mye på grunn av dette.

Merknad for brukere uten tilgang til en CNC:

Dette prosjektet kan enkelt utføres med en borepresse. Du trenger bare å sette stoppet på et punkt der du lar rundt 0,1 tre ligge igjen ved basen. Du må være presis, men ikke for presis. Tross alt er det ideelt at ingen vil se alle lysdiodene lyse kl. samtidig, slik at du kan slippe unna med en liten slop.

Trinn 4: Elektronikk

Elektronikk
Elektronikk
Elektronikk
Elektronikk
Elektronikk
Elektronikk

Elektronikken er ganske enkel. Det er 24 neopiksler, tolv for å vise timene og tolv for å vise minuttene, med fem minutters presisjon. En Arduino pro mini styrer neopikslene, og den får nøyaktig tid gjennom en DS3231 sanntidsklokke (RTC) -modul. RTC -modulen har en myntcelle som backup, så den mister ikke tid selv når strømmen er slått av.

Materiale:

Arduino pro mini (eller annen Arduino for den saks skyld)

DS3231 breakout board

Neopixels i individuelle breakout boards

Trinn 5: Elektronikkmontering

Elektronikkmontering
Elektronikkmontering
Elektronikkmontering
Elektronikkmontering
Elektronikkmontering
Elektronikkmontering
Elektronikkmontering
Elektronikkmontering

Jeg koblet neopikslene i en streng, ved å bruke 2,5 ledninger for de første tolv lysdiodene og fire-tommers ledning for de neste tolv. Jeg kunne ha brukt litt mindre ledningslengder. Etter å ha laget strengen, testet jeg den og sørget for at loddetinnet leddene var gode. Jeg la til en kort bryter for å slå på alle lysdiodene, bare for å vise meg frem.

Trinn 6: Tørrløp

Tørrløp
Tørrløp
Tørrløp
Tørrløp
Tørrløp
Tørrløp
Tørrløp
Tørrløp

Etter å ha eksperimentert, satt lysdioder i hullene og slått dem alle på, var jeg fornøyd med resultatene. Så jeg pusset forsiden litt og påførte et PU -strøk. Jeg endte opp med å slipe pelsen senere, men det er lurt å la den stå på hvis du ikke synes den er estetisk misfornøyd.

Trinn 7: Epoxy

Epoksy
Epoksy
Epoksy
Epoksy

Etter noen tester med led -posisjonen i hullene, skjønte jeg at den beste diskusjonen oppnås når lysdiodene er rundt 0,2 unna enden av hullet. Når du prøver dette selv, vil lysstyrken til lysdiodene være veldig forskjellig i hvert hull. Ikke bekymre deg for dette; vi fikser det i kode. Dette er på grunn av typen borekrone jeg brukte. Hvis jeg skulle gjøre dette igjen, ville jeg brukt en kulebor for hullene. Men uansett, for å få avstanden, blandet jeg litt epoxy og la litt i hvert hull.

Trinn 8: Sett alt sammen

Sette alt sammen
Sette alt sammen
Sette alt sammen
Sette alt sammen
Sette alt sammen
Sette alt sammen
Sette alt sammen
Sette alt sammen

Lysdiodene vil bli plassert fra klokken 12-timers håndposisjon som beveger seg mot urviseren gjennom alle timevisningsposisjonene og deretter til minuttviseren, igjen fra 60-minutters-merket som beveger seg mot klokken. Dette er slik at når vi ser forfra, ser LED -mønsteret ut med klokken.

Etter at epoksyen var herdet i en time, la jeg i litt mer epoxy. Denne gangen plasserte jeg lysdiodene i hullene, og passet på å dekke ledningene og loddeskjøtene med epoxy. Dette gir god lysdiffusjon og sikrer ledningene.

Trinn 9: Kode

Kode
Kode

Koden er på GitHub, du kan endre den for bruk. Når du slår på alle lysdiodene til samme nivå, vil lysstyrken på lyset som skinner gjennom være veldig forskjellig i hvert hull. Dette er på grunn av den forskjellige tykkelsen på treet i hullene og forskjellen i treets nyanse. Som du kan se varierer trefargen ganske mye i stykket mitt. For å bøte på denne forskjellen i lysstyrke, laget jeg en matrise med LED -lysstyrkenivåer. Og redusert lysstyrken til de lysere lysdiodene. Det er en prøve -og -feil -prosess og kan ta flere minutter, men resultatene er vel verdt det.

kryssfinerClock.ino

// Kryssfinerur
// Forfatter: tinkrmind
// Attribution 4.0 International (CC BY 4.0). Du står fritt til å:
// Del - kopier og distribuer materialet i et hvilket som helst medium eller format
// Tilpass - remiks, transformer og bygg på materialet for ethvert formål, også kommersielt.
// Hurra!
#inkludere
#include "RTClib.h"
RTC_DS3231 rtc;
#include "Adafruit_NeoPixel.h"
#ifdef _AVR_
#inkludere
#slutt om
#definerePIN6
Adafruit_NeoPixel strip = Adafruit_NeoPixel (60, PIN, NEO_GRB + NEO_KHZ800);
int timePixel = 0;
int minutePixel = 0;
unsignedlong lastRtcCheck;
String inputString = ""; // en streng for å lagre innkommende data
boolsk stringComplete = false; // om strengen er fullført
int nivå [24] = {31, 51, 37, 64, 50, 224, 64, 102, 95, 255, 49, 44, 65, 230, 80, 77, 102, 87, 149, 192, 67, 109, 68, 77};
voidsetup () {
#ifndef ESP8266
mens (! Seriell); // for Leonardo/Micro/Zero
#slutt om
// Dette er for Trinket 5V 16MHz, du kan fjerne disse tre linjene hvis du ikke bruker en Trinket
#if definert (_AVR_ATtiny85_)
hvis (F_CPU == 16000000) clock_prescale_set (clock_div_1);
#slutt om
// Slutt på spesiell kode for smykker
Serial.begin (9600);
strip.begin ();
strip.show (); // Initialiser alle piksler til "av"
hvis (! rtc.begin ()) {
Serial.println ("Kunne ikke finne RTC");
mens (1);
}
pinMode (2, INPUT_PULLUP);
// rtc.adjust (DateTime (F (_ DATE_), F (_ TIME_)));
if (rtc.lostPower ()) {
Serial.println ("RTC mistet strøm, lar oss angi tiden!");
// følgende linje angir RTC til dato og klokkeslett denne skissen ble kompilert
rtc.adjust (DateTime (F (_ DATE_), F (_ TIME_)));
// Denne linjen angir RTC med en eksplisitt dato og klokkeslett, for eksempel å angi
// 21. januar 2014 klokken 03.00 vil du ringe:
// rtc.adjust (DateTime (2017, 11, 06, 2, 49, 0));
}
// rtc.adjust (DateTime (2017, 11, 06, 2, 49, 0));
// lightUpEven ();
// mens (1);
lastRtcCheck = 0;
}
voidloop () {
if (millis () - lastRtcCheck> 2000) {
DateTime nå = rtc.now ();
Serial.print (nå. Time (), DEC);
Serial.print (':');
Serial.print (nå. Minutt (), DEC);
Serial.print (':');
Serial.print (nå. Sekund (), DEC);
Serial.println ();
showTime ();
lastRtcCheck = millis ();
}
hvis (! digitalRead (2)) {
lightUpEven ();
}
if (stringComplete) {
Serial.println (inputString);
if (inputString [0] == 'l') {
Serial.println ("Nivå");
lightUpEven ();
}
if (inputString [0] == 'c') {
Serial.println ("Viser tid");
showTime ();
strip.show ();
}
if (inputString [0] == '1') {
Serial.println ("Slå på alle lysdioder");
lightUp (strip. Color (255, 255, 255));
strip.show ();
}
if (inputString [0] == '0') {
Serial.println ("Clearing strip");
klar();
strip.show ();
}
// #3, 255 ville sette led nummer 3 til nivå 255, 255, 255
if (inputString [0] == '#') {
Streng temp;
temp = inputString.substring (1);
int pixNum = temp.toInt ();
temp = inputString.substring (inputString.indexOf (',') + 1);
int intensitet = temp.toInt ();
Serial.print ("Setting");
Serial.print (pixNum);
Serial.print ("til nivå");
Serial.println (intensitet);
strip.setPixelColor (pixNum, strip. Color (intensitet, intensitet, intensitet));
strip.show ();
}
// #3, 255, 0, 125 ville sette led nummer 3 til nivå 255, 0, 125
if (inputString [0] == '$') {
Streng temp;
temp = inputString.substring (1);
int pixNum = temp.toInt ();
int rIndex = inputString.indexOf (',') + 1;
temp = inputString.substring (rIndex);
int rIntensity = temp.toInt ();
intgIndex = inputString.indexOf (',', rIndex + 1) + 1;
temp = inputString.substring (gIndex);
intgIntensity = temp.toInt ();
int bIndex = inputString.indexOf (',', gIndex + 1) + 1;
temp = inputString.substring (bIndex);
int bIntensity = temp.toInt ();
Serial.print ("Setting");
Serial.print (pixNum);
Serial.print ("R til");
Serial.print (rIntensity);
Serial.print ("G til");
Serial.print (gIntensity);
Serial.print ("B til");
Serial.println (bIntensity);
strip.setPixelColor (pixNum, strip. Color (rIntensity, gIntensity, bIntensity));
strip.show ();
}
if (inputString [0] == 's') {
Streng temp;
int time, minutt;
temp = inputString.substring (1);
time = temp.toInt ();
int rIndex = inputString.indexOf (',') + 1;
temp = inputString.substring (rIndex);
minutt = temp.toInt ();
Serial.print ("Viser tid:");
Serial.print (time);
Serial.print (":");
Serial.print (minutt);
visningstid (time, minutt);
forsinkelse (1000);
}
inputString = "";
stringComplete = false;
}
// forsinkelse (1000);
}
voidserialEvent () {
mens (Serial.available ()) {
char inChar = (char) Serial.read ();
inputString += inChar;
hvis (inChar == '\ n') {
stringComplete = true;
}
forsinkelse (1);
}
}
voidclear () {
for (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, strip. Color (0, 0, 0));
}
}
voidshowTime () {
DateTime nå = rtc.now ();
timePixel = nå. time () % 12;
minutePixel = (nå. minutt () / 5) % 12 + 12;
klar();
// strip.setPixelColor (hourPixel, strip. Color (40 + 40 * level [hourPixel], 30 + 30 * level [hourPixel], 20 + 20 * level [hourPixel]));
// strip.setPixelColor (minutePixel, strip. Color (40 + 40 * level [minutePixel], 30 + 30 * level [minutePixel], 20 + 20 * level [minutePixel]));
strip.setPixelColor (hourPixel, strip. Color (level [hourPixel], level [hourPixel], level [hourPixel]));
strip.setPixelColor (minutePixel, strip. Color (level [minutePixel], level [minutePixel], level [minutePixel]));
// lightUp (strip. Color (255, 255, 255));
strip.show ();
}
voidshowTime (int time, int minutt) {
timePixel = time % 12;
minuttPiksel = (minutt / 5) % 12 + 12;
klar();
// strip.setPixelColor (hourPixel, strip. Color (40 + 40 * nivå [hourPixel], 30 + 30 * level [hourPixel], 20 + 20 * level [hourPixel]));
// strip.setPixelColor (minutePixel, strip. Color (40 + 40 * level [minutePixel], 30 + 30 * level [minutePixel], 20 + 20 * level [minutePixel]));
strip.setPixelColor (hourPixel, strip. Color (level [hourPixel], level [hourPixel], level [hourPixel]));
strip.setPixelColor (minutePixel, strip. Color (level [minutePixel], level [minutePixel], level [minutePixel]));
// lightUp (strip. Color (255, 255, 255));
strip.show ();
}
voidlightUp (uint32_t farge) {
for (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, farge);
}
strip.show ();
}
voidlightUpEven () {
for (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, strip. Color (nivå , nivå , nivå ));
}
strip.show ();
}

se rawplywoodClock.ino hostet av ❤ av GitHub

Trinn 10: Datasyn - Kalibrering

Datasyn - Kalibrering
Datasyn - Kalibrering
Datasyn - Kalibrering
Datasyn - Kalibrering

Jeg tok et bevisst valg om å ikke bruke finer i dette prosjektet. Hvis jeg hadde gjort det, ville tretykkelsen vært den samme foran alle lysdioder. Men fordi jeg har en annen tykkelse av tre foran hver LED og fordi trefargen også varierer mye, er LED -lysstyrken forskjellig for hver LED. For å få alle lysdiodene til å synes å ha samme lysstyrke, utviklet jeg et lurt triks.

Jeg skrev en behandlingskode (på GitHub) som tar et bilde av klokken, og analyserer lysstyrken til hver LED etter tur. Det varierer deretter effekten til hver LED for å prøve å få dem alle til å ha samme lysstyrke som den svakeste LED -en. Nå vet jeg at dette er overkill, men bildebehandling er veldig gøy! Og jeg håper å utvikle kalibreringskoden som et bibliotek.

Du kan se LED -lysstyrken før og etter kalibrering på bildene ovenfor.

calibrateDispllay.pde

importprocessing.video.*;
importprocessing.serial.*;
Seriell myPort;
Ta opp video;
finalint numLed = 24;
int ledNum = 0;
// du må ha disse globale variablene for å bruke PxPGetPixelDark ()
int rDark, gDark, bDark, aDark;
int rLed, gLed, bLed, aLed;
int rOrg, gOrg, bOrg, aOrg;
int rTemp, gTemp, bTemp, aTemp;
PImage ourImage;
int runNumber = 0;
int akseptabel feil = 3;
int gjort;
int numPixelsInLed;
lang ledIntensity;
int ledPower;
lang targetIntensity = 99999999;
voidsetup () {
ferdig = newint [numLed];
numPixelsInLed = newint [numLed];
ledIntensity = newlong [numLed];
ledPower = newint [numLed];
for (int i = 0; i <numLed; i ++) {
ledPower = 255;
}
printArray (Serial.list ());
String portName = Serial.list () [31];
myPort = newSerial (dette, portnavn, 9600);
størrelse (640, 480);
video = newCapture (dette, bredde, høyde);
video.start ();
noStroke ();
glatt();
forsinkelse (1000); // Vent til seriell port åpnes
}
voiddraw () {
if (video.available ()) {
if (done [ledNum] == 0) {
clearDisplay ();
forsinkelse (1000);
video.read ();
bilde (video, 0, 0, bredde, høyde); // Tegn webkameravideoen på skjermen
saveFrame ("data/no_leds.jpg");
if (runNumber! = 0) {
if ((ledIntensity [ledNum] - targetIntensity)*100/targetIntensity> acceptableError) {
ledPower [ledNum] -= pow (0,75, runNumber)*100+1;
}
if ((targetIntensity - ledIntensity [ledNum])*100/targetIntensity> acceptableError) {
ledPower [ledNum] += pow (0,75, runNumber)*100 +1;
}
if (abs (targetIntensity - ledIntensity [ledNum])*100/targetIntensity <= acceptableError) {
ferdig [ledNum] = 1;
print ("Led");
print (ledNum);
print ("ferdig");
}
if (ledPower [ledNum]> 255) {
ledPower [ledNum] = 255;
}
hvis (ledPower [ledNum] <0) {
ledPower [ledNum] = 0;
}
}
setLedPower (ledNum, ledPower [ledNum]);
forsinkelse (1000);
video.read ();
bilde (video, 0, 0, bredde, høyde); // Tegn webkameravideoen på skjermen
forsinkelse (10);
mens (myPort.available ()> 0) {
int inByte = myPort.read ();
// print (char (inByte));
}
String imageName = "data/";
imageName+= str (ledNum);
imageName += "_ led.jpg";
saveFrame (imageName);
String originalImageName = "data/org";
originalImageName+= str (ledNum);
originalImageName += ". jpg";
if (runNumber == 0) {
saveFrame (originalImageName);
}
PImage noLedImg = loadImage ("data/no_leds.jpg");
PImage ledImg = loadImage (imageName);
PImage originalImg = loadImage (originalImageName);
noLedImg.loadPixels ();
ledImg.loadPixels ();
originalImg.loadPixels ();
bakgrunn (0);
loadPixels ();
ledIntensity [ledNum] = 0;
numPixelsInLed [ledNum] = 0;
for (int x = 0; x <bredde; x ++) {
for (int y = 0; y <høyde; y ++) {
PxPGetPixelDark (x, y, noLedImg.pixels, bredde);
PxPGetPixelLed (x, y, ledImg.pixels, bredde);
PxPGetPixelOrg (x, y, originalImg.pixels, bredde);
hvis ((rOrg+gOrg/2+bOrg/3)-(rDark+gDark/2+bDark/3)> 75) {
ledIntensity [ledNum] = ledIntensity [ledNum]+(rLed+gLed/2+bLed/3) -(rDark+gDark/2+bDark/3);
rTemp = 255;
gTemp = 255;
bTemp = 255;
numPixelsInLed [ledNum] ++;
} annet {
rTemp = 0;
gTemp = 0;
bTemp = 0;
}
PxPSetPixel (x, y, rTemp, gTemp, bTemp, 255, piksler, bredde);
}
}
ledIntensity [ledNum] /= numPixelsInLed [ledNum];
if (targetIntensity> ledIntensity [ledNum] && runNumber == 0) {
targetIntensity = ledIntensity [ledNum];
}
updatePixels ();
}
print (ledNum);
skrive ut(', ');
print (ledPower [ledNum]);
skrive ut(', ');
println (ledIntensity [ledNum]);
ledNum ++;
if (ledNum == numLed) {
int donezo = 0;
for (int i = 0; i <numLed; i ++) {
donezo += ferdig ;
}
hvis (donezo == numLed) {
println ("DONE");
for (int i = 0; i <numLed; i ++) {
print (i);
print ("\ t");
println (ledPower );
}
print ("int nivå [");
print (ledNum);
print ("] = {");
for (int i = 0; i <numLed-1; i ++) {
print (ledPower );
skrive ut(', ');
}
print (ledPower [numLed -1]);
println ("};");
lightUpEven ();
mens (sant);
}
print ("Målintensitet:");
if (runNumber == 0) {
targetIntensity -= 1;
}
println (targetIntensity);
ledNum = 0;
runNumber ++;
}
}
}
voidPxPGetPixelOrg (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // å få fargene som en int fra pikslene
aOrg = (thisPixel >> 24) & 0xFF; // vi må skifte og maskere for å få hver komponent alene
rOrg = (thisPixel >> 16) & 0xFF; // dette er raskere enn å ringe rødt (), grønt (), blått ()
gOrg = (thisPixel >> 8) & 0xFF;
bOrg = thisPixel & 0xFF;
}
voidPxPGetPixelDark (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // å få fargene som en int fra pikslene
aDark = (thisPixel >> 24) & 0xFF; // vi må skifte og maskere for å få hver komponent alene
rDark = (thisPixel >> 16) & 0xFF; // dette er raskere enn å ringe rødt (), grønt (), blått ()
gDark = (thisPixel >> 8) & 0xFF;
bDark = thisPixel & 0xFF;
}
voidPxPGetPixelLed (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // å få fargene som en int fra pikslene
aLed = (thisPixel >> 24) & 0xFF; // vi må skifte og maskere for å få hver komponent alene
rLed = (thisPixel >> 16) & 0xFF; // dette er raskere enn å ringe rødt (), grønt (), blått ()
gLed = (thisPixel >> 8) & 0xFF;
bLed = thisPixel & 0xFF;
}
voidPxPSetPixel (intx, inty, intr, intg, intb, inta, int pixelArray, intpixelsWidth) {
a = (a << 24);
r = r << 16; // Vi pakker alle 4 komponentene i ett int
g = g << 8; // så vi må flytte dem til stedene deres
farge argb = a | r | g | b; // binær "eller" operasjon legger dem alle til en int
pixelArray [x+y*pixelsWidth] = argb; // endelig satte vi int med te farger inn i pikslene
}

se rawcalibrateDispllay.pde hostet av ❤ av GitHub

Trinn 11: Delingsmerknader

Fallgruver å unngå:

* Med tre får du det du betaler for. Så skaff deg tre av god kvalitet. Bjørkfiner er et godt valg; ethvert lyst massivt tre vil også gjøre det bra. Jeg billet ut på skogen og angrer på beslutningen min.

* Det er bedre å bore mindre enn mer. Et par hull gikk for dypt for stykket mitt. Og epoksyen viser seg gjennom på forsiden. Det er veldig merkbart når du merker det.

* Bruk en borkronebor i stedet for en rett ende. Jeg har ikke eksperimentert med ballenden, men jeg er ganske sikker på at resultatene blir mye bedre.

Jeg flørte med tanken på å selge disse på Etsy eller tindie. Jeg setter stor pris på om du kan kommentere nedenfor hvis du synes det er fornuftig:)

Anbefalt: