Sadržaj:

Drveni LED sat - analogni stil: 11 koraka (sa slikama)
Drveni LED sat - analogni stil: 11 koraka (sa slikama)

Video: Drveni LED sat - analogni stil: 11 koraka (sa slikama)

Video: Drveni LED sat - analogni stil: 11 koraka (sa slikama)
Video: Моя работа наблюдать за лесом и здесь происходит что-то странное 2024, Novembar
Anonim
Drveni LED sat - analogni stil
Drveni LED sat - analogni stil

To je drveni LED sat u analognom stilu. Ne znam zašto nisam vidio ovo prije … iako su digitalni tipovi vrlo česti. U svakom slučaju, evo nas!

Korak 1:

Image
Image
Image
Image

Projekt sata od šperploče započeo je kao jednostavan početni projekt za CNC usmjerivač. Gledao sam jednostavne projekte na internetu i pronašao ovu lampu (slika gore). Takođe sam vidio digitalne satove koji sjaje kroz drveni furnir (slika gore). Dakle, kombinacija dva projekta bila je očigledna ideja. Želeći da izazovem sebe, odlučio sam da za ovaj projekat ne koristim furnir, već samo komad drveta.

Korak 2: Dizajnirajte

Dizajn
Dizajn
Dizajn
Dizajn

Dizajnirao sam sat u Inkscape -u (slika gore). Dizajn je vrlo jednostavan po izboru. Odlučio sam se protiv usmjeravanja tragova za žice jer u ovom trenutku nisam bio siguran želim li ići s radijalnim ili obodnim ožičenjem. (Odlučio sam konačno krenuti s ožičenjem po obodu.) Jedan neopiksel ulazi u svaku od malih kružnih rupa za pokazivanje minuta i sati, s petminutnom preciznošću. Krug u sredini bit će usmjeren prema elektronici.

Korak 3: CNC

CNCing
CNCing
CNCing
CNCing
CNCing
CNCing
CNCing
CNCing

Dizajnirao sam staze alata na MasterCAM -u i koristio technoRouter za glodanje sata od šperploče od 3/4 inča. Za ovo koristim komad 15 "x15", uz minimalno trošenje. Trik je u tome da izvučete što je moguće više drva bez probijanja kroz drvo. Ostavljanje 0,05 "-0,1" dobar je izbor za svijetlo drvo. Ako niste sigurni, bolje je ostaviti više drva, jer uvijek možete brusiti drugu stranu. Na kraju sam uklonio malo previše drva s nekih dijelova, ali na sreću rezultati zbog toga ne trpe previše.

Napomena za korisnike koji nemaju pristup CNC -u:

Ovaj se projekt lako može izvesti bušilicom. Samo trebate postaviti zaustavljanje na mjestu gdje ostavljate oko 0,1 drva preostalog u podnožju. Morat ćete biti precizni, ali ne previše precizni. Na kraju krajeva, idealno je da nitko neće vidjeti da sve LED diode svijetle na u isto vrijeme, tako da se možete malo izvući.

Korak 4: Elektronika

Elektronika
Elektronika
Elektronika
Elektronika
Elektronika
Elektronika

Elektronika je prilično jednostavna. Postoji 24 neopiksela, dvanaest za prikazivanje sati i dvanaest za prikazivanje minuta, s petominutnom preciznošću. Arduino pro mini kontrolira neopiksele i dobiva točno vrijeme putem DS3231 modula sata stvarnog vremena (RTC). RTC modul ima rezervnu ćeliju u obliku novčića, tako da ne gubi vrijeme čak ni kad je napajanje isključeno.

Materijal:

Arduino pro mini (ili bilo koji drugi Arduino po tom pitanju)

DS3231 ploča za razbijanje

Neopikseli u pojedinačnim pločama za razbijanje

Korak 5: Montaža elektronike

Sklop elektronike
Sklop elektronike
Sklop elektronike
Sklop elektronike
Sklop elektronike
Sklop elektronike
Sklop elektronike
Sklop elektronike

Spojio sam neopiksele u niz, koristeći žice od 2,5 za prvih dvanaest LED dioda i žicu od 4 inča za sljedećih dvanaest. Mogao sam upotrijebiti nešto manje žice. Nakon što sam napravio niz, testirao sam ga, pazeći da lemljenje zglobovi su bili dobri. Dodao sam trenutni prekidač za uključivanje svih LED dioda, samo da se pokažem.

Korak 6: Suho trčanje

Suho trcanje
Suho trcanje
Suho trcanje
Suho trcanje
Suho trcanje
Suho trcanje
Suho trcanje
Suho trcanje

Nakon eksperimentiranja, stavljanja LED dioda u rupe i uključivanja svih njih, bio sam zadovoljan rezultatima. Pa sam malo brusila prednju stranu i nanijela PU sloj. Kasnije sam ošišao kaput, ali bilo bi dobro ostaviti ga ako vam se ne čini estetski neugodnim.

Korak 7: Epoksid

Epoksid
Epoksid
Epoksid
Epoksid

Nakon nekog testiranja sa LED pozicijom unutar rupa, zaključio sam da se najbolja diskusija postiže kada su LED diode udaljene oko 0,2 od kraja rupe. Kad ovo sami pokušate, svjetlina LED dioda će se jako razlikovati u Svaka rupa. Ne brinite oko ovoga; popravit ćemo to u kodu. To je zbog vrste svrdla koje sam koristio. Ako bih ovo ponovio, upotrijebio bih svrdlo s kuglastom rupom … Ali, u svakom slučaju, da bih dobio udaljenost, pomiješao sam malo epoksida i stavio po malo u svaku rupu.

Korak 8: Sve zajedno

Spajajući sve zajedno
Spajajući sve zajedno
Spajajući sve zajedno
Spajajući sve zajedno
Spajajući sve zajedno
Spajajući sve zajedno
Spajajući sve zajedno
Spajajući sve zajedno

LED diode će biti postavljene počevši od položaja kazaljke na satu u 12 sati koji se pomiče u smjeru suprotnom od kazaljke na satu kroz sve položaje kazaljki na satu, a zatim do minute, ponovo se pomičući od oznake od 60 minuta koja se pomiče u smjeru suprotnom od kazaljke na satu. To je tako da kada gledamo sprijeda LED uzorak se pojavljuje u smjeru kazaljke na satu.

Nakon što je epoksid očvrsnuo sat vremena, stavio sam još epoksida. Ovaj put sam LED diode stavio u rupe, pazeći da žice i lemne spojeve prekrijemo epoksidom. To omogućuje dobru difuziju svjetlosti i učvršćuje žice.

Korak 9: Kodirajte

Kod
Kod

Kôd je na GitHubu, slobodno ga izmijenite za svoju upotrebu. Kada uključite sve LED diode na isti nivo, jačina svjetlosti koja svijetli bit će vrlo različita u svakoj rupi. To je zbog različite debljine drveta u rupama i razlike u sjeni drveta. Kao što vidite, boja drveta prilično se razlikuje u mom komadu. Da bih ispravio ovu razliku u svjetlini, napravio sam matricu nivoa svjetline LED dioda. I smanjila svjetlinu svjetlijih LED dioda. To je proces pokušaja i grešaka i može potrajati nekoliko minuta, ali rezultati su vrijedni toga.

plywoodClock.ino

// Sat od šperploče
// Autor: tinkrmind
// Međunarodno pripisivanje 4.0 (CC BY 4.0). Slobodni ste da:
// Dijeljenje - kopiranje i ponovna distribucija materijala u bilo kojem mediju ili formatu
// Adapt - remiksirajte, transformirajte i nadograđujte materijal u bilo koju svrhu, čak i komercijalnu.
// Hurray!
#include
#include "RTClib.h"
RTC_DS3231 rtc;
#include "Adafruit_NeoPixel.h"
#ifdef _AVR_
#include
#endif
#definePIN6
Adafruit_NeoPixel strip = Adafruit_NeoPixel (60, PIN, NEO_GRB + NEO_KHZ800);
int hourPixel = 0;
int minutePixel = 0;
unsignedlong lastRtcCheck;
String inputString = ""; // niz za čuvanje dolaznih podataka
boolean stringComplete = false; // da li je niz potpun
int nivo [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
while (! Serijski); // za Leonardo/Micro/Zero
#endif
// Ovo je za Trinket 5V 16MHz, možete ukloniti ove tri linije ako ne koristite Trinket
#if definirano (_AVR_ATtiny85_)
if (F_CPU == 16000000) clock_prescale_set (clock_div_1);
#endif
// Kraj posebnog koda za sitnice
Serial.begin (9600);
strip.begin ();
strip.show (); // Pokretanje svih piksela na "isključeno"
if (! rtc.begin ()) {
Serial.println ("Nije moguće pronaći RTC");
while (1);
}
pinMode (2, INPUT_PULLUP);
// rtc.adjust (DateTime (F (_ DATE_), F (_ TIME_)));
if (rtc.lostPower ()) {
Serial.println ("RTC je izgubio napajanje, podesimo vrijeme!");
// sljedeći red postavlja RTC na datum i vrijeme sastavljanja ove skice
rtc.adjust (DateTime (F (_ DATE_), F (_ TIME_)));
// Ova linija postavlja RTC s eksplicitnim datumom i vremenom, na primjer za postavljanje
// 21. januara 2014. u 3 ujutro nazvali biste:
// rtc.adjust (DateTime (2017, 11, 06, 2, 49, 0));
}
// rtc.adjust (DateTime (2017, 11, 06, 2, 49, 0));
// lightUpEven ();
// while (1);
lastRtcCheck = 0;
}
voidloop () {
if (millis () - lastRtcCheck> 2000) {
DateTime now = rtc.now ();
Serial.print (now.hour (), DEC);
Serial.print (':');
Serial.print (now.minute (), DEC);
Serial.print (':');
Serial.print (now.second (), DEC);
Serial.println ();
pokazi vrijeme();
lastRtcCheck = millis ();
}
if (! digitalRead (2)) {
lightUpEven ();
}
if (stringComplete) {
Serial.println (inputString);
if (inputString [0] == 'l') {
Serial.println ("Nivo");
lightUpEven ();
}
if (inputString [0] == 'c') {
Serial.println ("Prikazivanje vremena");
pokazi vrijeme();
strip.show ();
}
if (inputString [0] == '1') {
Serial.println ("Uključivanje svih LED dioda");
lightUp (strip. Color (255, 255, 255));
strip.show ();
}
if (inputString [0] == '0') {
Serial.println ("Čišćenje trake");
clear ();
strip.show ();
}
// #3, 255 bi postavilo LED broj 3 na nivo 255, 255, 255
if (inputString [0] == '#') {
String temp;
temp = inputString.substring (1);
int pixNum = temp.toInt ();
temp = inputString.substring (inputString.indexOf (',') + 1);
int intenzitet = temp.toInt ();
Serial.print ("Postavka");
Serial.print (pixNum);
Serial.print ("do nivoa");
Serial.println (intenzitet);
strip.setPixelColor (pixNum, strip. Color (intenzitet, intenzitet, intenzitet));
strip.show ();
}
// #3, 255, 0, 125 bi postavilo LED broj 3 na nivo 255, 0, 125
if (inputString [0] == '$') {
String 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 ("Postavka");
Serial.print (pixNum);
Serial.print ("R do");
Serial.print (rIntensity);
Serial.print ("G do");
Serial.print (gIntensity);
Serial.print ("B do");
Serial.println (bIntensity);
strip.setPixelColor (pixNum, strip. Color (rIntensity, gIntensity, bIntensity));
strip.show ();
}
if (inputString [0] == 's') {
String temp;
int sat, minut;
temp = inputString.substring (1);
hour = temp.toInt ();
int rIndex = inputString.indexOf (',') + 1;
temp = inputString.substring (rIndex);
minute = temp.toInt ();
Serial.print ("Prikazuje se vrijeme:");
Serial.print (sat);
Serial.print (":");
Serijski.tisak (minut);
showTime (sat, minut);
kašnjenje (1000);
}
inputString = "";
stringComplete = false;
}
// kašnjenje (1000);
}
voidserialEvent () {
while (Serial.available ()) {
char inChar = (char) Serial.read ();
inputString += inChar;
if (inChar == '\ n') {
stringComplete = true;
}
kašnjenje (1);
}
}
voidclear () {
for (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, strip. Color (0, 0, 0));
}
}
voidshowTime () {
DateTime now = rtc.now ();
hourPixel = now.hour () % 12;
minutePixel = (now.minute () / 5) % 12 + 12;
clear ();
// strip.setPixelColor (hourPixel, strip. Color (40 + 40 * nivo [hourPixel], 30 + 30 * nivo [hourPixel], 20 + 20 * nivo [hourPixel]));
// strip.setPixelColor (minutePixel, strip. Color (40 + 40 * nivo [minutePixel], 30 + 30 * nivo [minutePixel], 20 + 20 * nivo [minutePixel])));
strip.setPixelColor (hourPixel, strip. Color (nivo [hourPixel], nivo [hourPixel], nivo [hourPixel]));
strip.setPixelColor (minutePixel, strip. Color (nivo [minutePixel], nivo [minutePixel], nivo [minutePixel])));
// lightUp (strip. Color (255, 255, 255));
strip.show ();
}
voidshowTime (int sat, int minut) {
hourPixel = sat % 12;
minutePixel = (minute / 5) % 12 + 12;
clear ();
// strip.setPixelColor (hourPixel, strip. Color (40 + 40 * nivo [hourPixel], 30 + 30 * nivo [hourPixel], 20 + 20 * nivo [hourPixel]));
// strip.setPixelColor (minutePixel, strip. Color (40 + 40 * nivo [minutePixel], 30 + 30 * nivo [minutePixel], 20 + 20 * nivo [minutePixel])));
strip.setPixelColor (hourPixel, strip. Color (nivo [hourPixel], nivo [hourPixel], nivo [hourPixel]));
strip.setPixelColor (minutePixel, strip. Color (nivo [minutePixel], nivo [minutePixel], nivo [minutePixel])));
// lightUp (strip. Color (255, 255, 255));
strip.show ();
}
voidlightUp (uint32_t boja) {
for (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, boja);
}
strip.show ();
}
voidlightUpEven () {
for (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, strip. Color (nivo , nivo , nivo ));
}
strip.show ();
}

pogledajte rawplywoodClock.ino hosted with ❤ by GitHub

Korak 10: Računalni vid - kalibracija

Računalni vid - kalibracija
Računalni vid - kalibracija
Računalni vid - kalibracija
Računalni vid - kalibracija

Svjesno sam odlučio da ne koristim furnir u ovom projektu. Da jesam, debljina drveta bi bila ista ispred svih LED dioda. No, budući da ispred svake LED diode imam različitu debljinu drveta i zato što boja drveta također varira, svjetlina LED diode je različita za svaku LED diodu. Da bi sve LED diode izgledale iste svjetline, smislio sam sjajan trik.

Napisao sam neki procesni kod (na GitHub -u) koji fotografira sat i analizira redom svjetlinu svake LED. Zatim mijenja snagu svake LED diode kako bi pokušao postići da svi imaju istu svjetlinu kao i prigušena LED. Znam da je ovo pretjerano, ali obrada slika je jako zabavna! Nadam se da ću kalibracijski kod razviti kao biblioteku.

Na gornjim fotografijama možete vidjeti svjetlinu LED -a prije i poslije kalibracije.

calibrateDispllay.pde

importprocessing.video.*;
importprocessing.serial.*;
Serijski myPort;
Snimanje video zapisa;
finalint numLed = 24;
int ledNum = 0;
// morate koristiti ove globalne varijable da biste koristili 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 prihvatljivaError = 3;
int gotovo;
int numPixelsInLed;
long ledIntensity;
int ledPower;
long targetIntensity = 99999999;
voidsetup () {
done = 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 (this, portName, 9600);
veličina (640, 480);
video = newCapture (ovo, širina, visina);
video.start ();
noStroke ();
smooth ();
kašnjenje (1000); // Pričekajte da se serijski port otvori
}
voiddraw () {
if (video.available ()) {
if (učinjeno [ledNum] == 0) {
clearDisplay ();
kašnjenje (1000);
video.read ();
slika (video, 0, 0, širina, visina); // Nacrtajte video zapis web kamere na ekran
saveFrame ("data/no_leds.jpg");
if (runNumber! = 0) {
if ((ledIntensity [ledNum] - targetIntensity)*100/targetIntensity> prihvatljiva greška) {
ledPower [ledNum] -= pow (0.75, runNumber)*100+1;
}
if ((targetIntensity - ledIntensity [ledNum])*100/targetIntensity> prihvatljiva greška) {
ledPower [ledNum] += pow (0.75, runNumber)*100 +1;
}
if (abs (targetIntensity - ledIntensity [ledNum])*100/targetIntensity <= prihvatljiva greška) {
učinjeno [ledNum] = 1;
print ("Led");
ispis (ledNum);
print ("gotovo");
}
if (ledPower [ledNum]> 255) {
ledPower [ledNum] = 255;
}
if (ledPower [ledNum] <0) {
ledPower [ledNum] = 0;
}
}
setLedPower (ledNum, ledPower [ledNum]);
kašnjenje (1000);
video.read ();
slika (video, 0, 0, širina, visina); // Nacrtajte video zapis web kamere na ekran
kašnjenje (10);
while (myPort.available ()> 0) {
int inByte = myPort.read ();
// ispis (char (inByte));
}
String imageName = "podaci/";
imageName+= str (ledNum);
imageName += "_ led.jpg";
saveFrame (imageName);
String originalImageName = "podaci/organizacija";
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 ();
pozadina (0);
loadPixels ();
ledIntensity [ledNum] = 0;
numPixelsInLed [ledNum] = 0;
for (int x = 0; x <širina; x ++) {
for (int y = 0; y <visina; y ++) {
PxPGetPixelDark (x, y, noLedImg.piksela, širina);
PxPGetPixelLed (x, y, ledImg.pikseli, širina);
PxPGetPixelOrg (x, y, originalImg.piksela, širina);
if ((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] ++;
} else {
rTemp = 0;
gTemp = 0;
bTemp = 0;
}
PxPSetPixel (x, y, rTemp, gTemp, bTemp, 255, pikseli, širina);
}
}
ledIntensity [ledNum] /= numPixelsInLed [ledNum];
if (targetIntensity> ledIntensity [ledNum] && runNumber == 0) {
targetIntensity = ledIntensity [ledNum];
}
updatePixels ();
}
ispis (ledNum);
print (',');
print (ledPower [ledNum]);
print (',');
println (ledIntensity [ledNum]);
ledNum ++;
if (ledNum == numLed) {
int donezo = 0;
for (int i = 0; i <numLed; i ++) {
donezo += gotovo ;
}
if (donezo == numLed) {
println ("GOTOVO");
for (int i = 0; i <numLed; i ++) {
ispis (i);
print ("\ t");
println (ledPower );
}
print ("int level [");
ispis (ledNum);
print ("] = {");
for (int i = 0; i <numLed-1; i ++) {
ispis (ledPower );
print (',');
}
ispis (ledPower [broj -1]);
println ("};");
lightUpEven ();
while (istina);
}
print ("Ciljni intenzitet:");
if (runNumber == 0) {
targetIntensity -= 1;
}
println (targetIntensity);
ledNum = 0;
runNumber ++;
}
}
}
voidPxPGetPixelOrg (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // dobivanje boja kao int iz piksela
aOrg = (ovaj piksel >> 24) & 0xFF; // moramo se pomaknuti i maskirati da bismo dobili svaku komponentu zasebno
rOrg = (ovaj piksel >> 16) & 0xFF; // ovo je brže od pozivanja red (), green (), blue ()
gOrg = (ovaj piksel >> 8) & 0xFF;
bOrg = ovaj piksel & 0xFF;
}
voidPxPGetPixelDark (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // dobivanje boja kao int iz piksela
aDark = (thisPixel >> 24) & 0xFF; // moramo se pomaknuti i maskirati da bismo dobili svaku komponentu zasebno
rDark = (thisPixel >> 16) & 0xFF; // ovo je brže od pozivanja red (), green (), blue ()
gDark = (thisPixel >> 8) & 0xFF;
bDark = thisPixel & 0xFF;
}
voidPxPGetPixelLed (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // dobivanje boja kao int iz piksela
aLed = (thisPixel >> 24) & 0xFF; // moramo se pomaknuti i maskirati da bismo dobili svaku komponentu zasebno
rLed = (thisPixel >> 16) & 0xFF; // ovo je brže od pozivanja red (), green (), blue ()
gLed = (thisPixel >> 8) & 0xFF;
bLed = thisPixel & 0xFF;
}
voidPxPSetPixel (intx, inty, intr, intg, intb, inta, int pixelArray, intpixelsWidth) {
a = (a << 24);
r = r << 16; // Pakiramo sve 4 komponente u jedan int
g = g << 8; // pa ih moramo premjestiti na njihova mjesta
boja argb = a | r | g | b; // binarna operacija "ili" dodaje ih sve u jedan int
pixelArray [x+y*pixelsWidth] = argb; // konačno postavljamo int sa te bojama u piksele
}

pogledajte rawcalibrateDispllay.pde hostirano sa ❤ od strane GitHub -a

Korak 11: Napomene o rastanku

Zamke koje treba izbjegavati:

* Drvom dobijate ono što plaćate. Zato nabavite kvalitetno drvo. Šperploča od breze je dobar izbor; bilo koje svijetlo masivno drvo također će se lijepo uklopiti. Pojeftinio sam drva i požalio sam zbog svoje odluke.

* Bolje je bušiti manje nego više. Par rupa je otišlo preduboko za moj komad. I epoksid se vidi kroz prednju stranu. Vrlo je uočljivo kada to primijetite.

* Koristite bušilicu s kugličnim krajem umjesto ravnog kraja. Nisam eksperimentirao sa završetkom loptice, ali sam prilično siguran da će rezultati biti mnogo bolji.

Koketiram sa idejom da ih prodam na Etsy -ju ili tindie -u. Bio bih vam zahvalan ako biste mogli komentarisati ispod ako mislite da ima smisla:)

Preporučuje se: