INHOUDSOPGAWE:

Houten LED -klok - analoog styl: 11 stappe (met foto's)
Houten LED -klok - analoog styl: 11 stappe (met foto's)

Video: Houten LED -klok - analoog styl: 11 stappe (met foto's)

Video: Houten LED -klok - analoog styl: 11 stappe (met foto's)
Video: Genie Leven Hacks die extreem goed werken ▶3 2024, November
Anonim
Hout LED -horlosie - analoog styl
Hout LED -horlosie - analoog styl

Dit is 'n analoog styl hout LED horlosie. Ek weet nie hoekom ek nog nie een hiervan gesien het nie, alhoewel die digitale tipes baie algemeen is. Anyhoo, hier gaan ons!

Stap 1:

Beeld
Beeld
Beeld
Beeld

Die laaghoutklokprojek het begin as 'n eenvoudige beginprojek vir die CNC -router. Ek het aanlyn na eenvoudige projekte gekyk en hierdie lamp gevind (foto hierbo). Ek het ook digitale horlosies gesien wat deur houtfineer skyn (foto hierbo). Die kombinasie van die twee projekte was dus 'n voor die hand liggende idee. Ek wou myself uitdaag en besluit om nie fineer te gebruik nie, maar slegs 'n stuk hout vir hierdie projek.

Stap 2: Ontwerp

Ontwerp
Ontwerp
Ontwerp
Ontwerp

Ek het die klok ontwerp in Inkscape (prent hierbo). Die ontwerp is baie eenvoudig uit eie keuse. Ek het besluit om geen spore vir die drade te plaas nie, want op hierdie stadium was ek onseker of ek met radiale of perimeterbedrading wou gaan. (Ek het besluit om uiteindelik met perimeterbedrading te gaan.) Elke neopixel gaan in elk van die klein sirkelvormige gaatjies om die minuut en uur te wys, met presisie van vyf minute. Die sirkel in die middel word uitgestuur om die elektronika te akkommodeer.

Stap 3: CNC

CNC -bewerking
CNC -bewerking
CNC -bewerking
CNC -bewerking
CNC -bewerking
CNC -bewerking
CNC -bewerking
CNC -bewerking

Ek het die gereedskappaaie op MasterCAM ontwerp en 'n technoRouter gebruik om die horlosie uit laaghout van 3/4 duim uit te maal. Ek gebruik 'n stuk van 15 x 15 cm hiervoor, met minimale vermorsing. Die truuk is om soveel as moontlik van die hout uit te trek sonder om deur die hout te breek. Die verlaat van 0,05 "-0,1" is 'n goeie keuse vir ligte hout. As u onseker is, is dit beter om meer hout in te laat, want u kan altyd die ander gesig skuur. Ek het uiteindelik 'n bietjie te veel hout uit sommige dele verwyder, maar gelukkig het die resultate nie te veel skade nie.

Opmerking vir gebruikers sonder toegang tot 'n CNC:

Hierdie projek kan maklik met 'n boorpers gedoen word. U hoef net die stop te plaas op 'n punt waar u ongeveer 0,1 hout aan die voet laat bly. U moet presies wees, maar nie te presies nie. Ideaal gesproke sal niemand al die LED's sien brand nie. op dieselfde tyd, sodat u met 'n klein bietjie kan wegkom.

Stap 4: Elektronika

Elektronika
Elektronika
Elektronika
Elektronika
Elektronika
Elektronika

Die elektronika is redelik eenvoudig. Daar is 24 neopixels, twaalf om die ure te wys en twaalf om die minute te wys, met presisie van vyf minute. 'N Arduino pro mini beheer die neopixels en dit kry akkurate tyd deur 'n DS3231 -real -time klok (RTC) -module. Die RTC -module het 'n muntstuk as rugsteun, sodat dit nie tyd verloor nie, selfs as die krag af is.

Materiaal:

Arduino pro mini (of enige ander Arduino vir die saak)

DS3231 uitbreekbord

Neopixels in individuele uitbreekborde

Stap 5: Elektroniese samestelling

Elektroniese vergadering
Elektroniese vergadering
Elektroniese vergadering
Elektroniese vergadering
Elektroniese vergadering
Elektroniese vergadering
Elektroniese vergadering
Elektroniese vergadering

Ek het die neopixels in 'n tou verbind, met drade van 2,5 vir die eerste twaalf LED's en vier-duim draad vir die volgende twaalf. Ek kon effens kleiner draadlengtes gebruik het. Nadat ek die tou gemaak het, het ek dit getoets en seker gemaak dat die soldeer Die gewrigte was goed. Ek het 'n kort skakelaar bygevoeg om al die LED's aan te skakel, net om te pronk.

Stap 6: Droogloop

Droogloop
Droogloop
Droogloop
Droogloop
Droogloop
Droogloop
Droogloop
Droogloop

Nadat ek geëksperimenteer het, LED's in die gate gesit en almal aangeskakel het, was ek tevrede met die resultate. Ek het dus die voorkant 'n bietjie geskuur en 'n PU -laag aangebring. Ek het die jas later afgeskuur, maar dit is 'n goeie idee om dit aan te hou as u dit nie esteties onaangenaam vind nie.

Stap 7: Epoksie

Epoksie
Epoksie
Epoksie
Epoksie

Na 'n paar toetse met die geleide posisie in die gate, het ek gedink dat die beste bespreking bereik kan word as die LED's ongeveer 0,2 van die einde van die gat af is. As u dit self probeer, sal die helderheid van die LED's baie anders wees as elke gat. Moenie bekommerd wees nie; ons sal dit in kode regmaak. Dit is as gevolg van die tipe boor wat ek gebruik het. As ek dit weer sou doen, sou ek 'n boorpunt vir die gate gebruik Maar in elk geval, om die afstand te bereik, het ek 'n bietjie epoxy gemeng en 'n bietjie in elke gaatjie gesit.

Stap 8: Alles saamvoeg

Om alles bymekaar te sit
Om alles bymekaar te sit
Om alles bymekaar te sit
Om alles bymekaar te sit
Om alles bymekaar te sit
Om alles bymekaar te sit
Om alles bymekaar te sit
Om alles bymekaar te sit

Die LED's word geplaas vanaf die 12-uur-handposisie wat teen die kloksgewys beweeg deur al die posisies van die uurwyser en dan na die minuutwyser, en weer vanaf die 60-minute-merk wat teen die kloksgewys beweeg. Dit is so dat as ons van voor af kyk, die LED -patroon kloksgewys verskyn.

Nadat die epoksie 'n uur lank genees het, gooi ek nog 'n bietjie epoksie in. Hierdie keer het ek die LED's in die gate geplaas en seker gemaak dat ek die drade en soldeerverbindings met die epoxy bedek het. Dit sorg vir goeie ligverspreiding en verseker die drade.

Stap 9: Kode

Kode
Kode

Die kode is op GitHub, en verander dit gerus vir u gebruik. As u al die LED's op dieselfde vlak aanskakel, sal die helderheid van die lig wat deurskyn, in elke gat baie verskil. Dit is te danke aan die verskillende dikte van die hout in die gate en die verskil in die skaduwee van die hout, soos u kan sien, wissel die houtkleur in my stuk baie. Om hierdie verskil in helderheid reg te stel, het ek 'n matriks gemaak van LED -helderheidsvlakke. En die helderheid van die helderder LED's verminder. Dit is 'n proef -en -fout proses en kan 'n paar minute neem, maar die resultate is die moeite werd.

laaghoutClock.ino

// Laaghoutklok
// Skrywer: tinkrmind
// Attribution 4.0 International (CC BY 4.0). U is vry om:
// Deel - kopieer en versprei die materiaal in enige medium of formaat
// Pas aan - hermeng, transformeer en bou voort op die materiaal vir enige doel, selfs kommersieel.
// Hoera!
#insluit
#sluit "RTClib.h" in
RTC_DS3231 rtc;
#sluit "Adafruit_NeoPixel.h" in
#ifdef _AVR_
#insluit
#endif
#definieerPIN6
Adafruit_NeoPixel strip = Adafruit_NeoPixel (60, PIN, NEO_GRB + NEO_KHZ800);
int uurPixel = 0;
int minutePixel = 0;
ongetekende lang lastRtcCheck;
String inputString = ""; // 'n string om inkomende data te bewaar
boolean stringComplete = false; // of die string voltooi is
int -vlak [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
terwyl (! Serial); // vir Leonardo/Micro/Zero
#endif
// Dit is vir Trinket 5V 16MHz, u kan hierdie drie reëls verwyder as u nie 'n snuistery gebruik nie
#as gedefinieer (_AVR_ATtiny85_)
as (F_CPU == 16000000) clock_prescale_set (clock_div_1);
#endif
// Einde van spesiale snuifkode
Serial.begin (9600);
strip.begin ();
strip.show (); // Initialiseer alle pixels na 'af'
as (! rtc.begin ()) {
Serial.println ("RTC kon nie gevind word nie");
terwyl (1);
}
pinMode (2, INPUT_PULLUP);
// rtc.adjust (DateTime (F (_ DATE_), F (_ TIME_)));
as (rtc.lostPower ()) {
Serial.println ("RTC het krag verloor, laat ons die tyd bepaal!");
// volgende reël stel die RTC op die datum en tyd waarop hierdie skets opgestel is
rtc.adjust (DateTime (F (_ DATE_), F (_ TIME_)));
// Hierdie reël stel die RTC met 'n eksplisiete datum en tyd, byvoorbeeld om in te stel
// 21 Januarie 2014 om 03:00 sou u skakel:
// rtc.adjust (DateTime (2017, 11, 06, 2, 49, 0));
}
// rtc.adjust (DateTime (2017, 11, 06, 2, 49, 0));
// lightUpEven ();
// terwyl (1);
lastRtcCheck = 0;
}
voidloop () {
if (millis () - lastRtcCheck> 2000) {
DateTime nou = rtc.now ();
Serial.print (nou.uur (), DEC);
Serial.print (':');
Serial.print (nou.minute (), DEC);
Serial.print (':');
Serial.print (nou.sekonde (), DEC);
Serial.println ();
showTime ();
lastRtcCheck = millis ();
}
as (! digitalRead (2)) {
lightUpEven ();
}
as (stringComplete) {
Serial.println (inputString);
if (inputString [0] == 'l') {
Serial.println ("Level");
lightUpEven ();
}
as (inputString [0] == 'c') {
Serial.println ("Tyd wys");
showTime ();
strip.show ();
}
if (inputString [0] == '1') {
Serial.println ("Alle LED's aanskakel");
lightUp (strip. Color (255, 255, 255));
strip.show ();
}
if (inputString [0] == '0') {
Serial.println ("skoonmaakstrook");
duidelik ();
strip.show ();
}
// #3, 255 sou die nommer 3 op vlak 255, 255, 255 stel
if (inputString [0] == '#') {
String temp;
temp = inputString.substring (1);
int pixNum = temp.toInt ();
temp = inputString.substring (inputString.indexOf (',') + 1);
int intensiteit = temp.toInt ();
Serial.print ("Setting");
Serial.print (pixNum);
Serial.print ("tot vlak");
Serial.println (intensiteit);
strip.setPixelColor (pixNum, strip. Color (intensiteit, intensiteit, intensiteit));
strip.show ();
}
// #3, 255, 0, 125 sou die nommer 3 op vlak 255, 0, 125 stel
if (inputString [0] == '$') {
String temp;
temp = inputString.substring (1);
int pixNum = temp.toInt ();
int rIndex = inputString.indexOf (',') + 1;
temp = inputString.substring (rIndex);
int rintensiteit = 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 tot");
Serial.print (rIntensiteit);
Serial.print ("G tot");
Serial.print (gIntensity);
Serial.print ("B tot");
Serial.println (bIntensiteit);
strip.setPixelColor (pixNum, strip. Color (rIntensity, gIntensity, bIntensity));
strip.show ();
}
if (inputString [0] == 's') {
String temp;
int uur, minuut;
temp = inputString.substring (1);
uur = temp.toInt ();
int rIndex = inputString.indexOf (',') + 1;
temp = inputString.substring (rIndex);
minuut = temp.toInt ();
Serial.print ("Tyd vertoon:");
Reeks.afdruk (uur);
Serial.print (":");
Reeks.afdruk (minuut);
showTime (uur, minuut);
vertraging (1000);
}
inputString = "";
stringComplete = vals;
}
// vertraging (1000);
}
voidserialEvent () {
terwyl (Serial.available ()) {
char inChar = (char) Serial.read ();
inputString += inChar;
as (inChar == '\ n') {
stringComplete = waar;
}
vertraging (1);
}
}
voidclear () {
vir (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, strip. Color (0, 0, 0));
}
}
voidshowTime () {
DateTime nou = rtc.now ();
hourPixel = nou.uur () % 12;
minutePixel = (nou.minute () / 5) % 12 + 12;
duidelik ();
// strip.setPixelColor (hourPixel, strip. Color (40 + 40 * level [hourPixel], 30 + 30 * level [hourPixel], 20 + 20 * level [hourPixel]));
// strip.setPixelColor (minutePixel, strip. Color (40 + 40 * vlak [minutePixel], 30 + 30 * vlak [minutePixel], 20 + 20 * vlak [minutePixel]));
strip.setPixelColor (hourPixel, strip. Color (level [hourPixel], level [hourPixel], level [hourPixel]));
strip.setPixelColor (minutePixel, strip. Color (vlak [minutePixel], vlak [minutePixel], vlak [minutePixel]));
// lightUp (strip. Color (255, 255, 255));
strip.show ();
}
voidshowTime (int uur, int minuut) {
hourPixel = uur % 12;
minutePixel = (minuut / 5) % 12 + 12;
duidelik ();
// strip.setPixelColor (hourPixel, strip. Color (40 + 40 * level [hourPixel], 30 + 30 * level [hourPixel], 20 + 20 * level [hourPixel]));
// strip.setPixelColor (minutePixel, strip. Color (40 + 40 * vlak [minutePixel], 30 + 30 * vlak [minutePixel], 20 + 20 * vlak [minutePixel]));
strip.setPixelColor (hourPixel, strip. Color (level [hourPixel], level [hourPixel], level [hourPixel]));
strip.setPixelColor (minutePixel, strip. Color (vlak [minutePixel], vlak [minutePixel], vlak [minutePixel]));
// lightUp (strip. Color (255, 255, 255));
strip.show ();
}
voidlightUp (uint32_t kleur) {
vir (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, kleur);
}
strip.show ();
}
voidlightUpEven () {
vir (uint16_t i = 0; i <strip.numPixels (); i ++) {
strip.setPixelColor (i, strip. Color (vlak , vlak , vlak ));
}
strip.show ();
}

sien rawplywoodClock.ino aangebied deur ❤ deur GitHub

Stap 10: Rekenaarvisie - kalibrasie

Rekenaarvisie - Kalibrasie
Rekenaarvisie - Kalibrasie
Rekenaarvisie - Kalibrasie
Rekenaarvisie - Kalibrasie

Ek het 'n bewuste keuse gemaak om nie fineer in hierdie projek te gebruik nie. As ek sou, sou die houtdikte voor alle LED's dieselfde gewees het. Maar omdat ek voor elke LED 'n ander dikte van die hout het en omdat die houtkleur ook baie wissel, is die LED -helderheid vir elke LED anders. Om al die LED's van dieselfde helderheid te laat lyk, het ek 'n slim truuk bedink.

Ek het 'n verwerkingskode (op GitHub) geskryf wat 'n foto van die horlosie neem en die helderheid van elke LED om die beurt ontleed. Dit verander dan die krag van elke LED om te probeer dat hulle almal dieselfde helderheid as die donkerste LED kry. Nou weet ek dat dit te veel is, maar beeldverwerking is baie pret! En ek hoop om die kalibreringskode as 'n biblioteek te ontwikkel.

U kan die LED -helderheid voor en na kalibrasie op die foto's hierbo sien.

kalibreerDispllay.pde

invoerverwerking.video.*;
invoerverwerking.reeks.*;
Seriële myPort;
Video opneem;
finalint numLed = 24;
int ledNum = 0;
// u moet hierdie globale veranderlikes hê om die PxPGetPixelDark () te gebruik
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 acceptableError = 3;
int gedoen;
int numPixelsInLed;
lang ledIntensiteit;
int ledPower;
lang targetIntensity = 99999999;
voidsetup () {
done = newint [numLed];
numPixelsInLed = newint [numLed];
ledIntensity = newlong [numLed];
ledPower = newint [numLed];
vir (int i = 0; i <numLed; i ++) {
ledPower = 255;
}
printArray (Serial.list ());
String portName = Serial.list () [31];
myPort = newSerial (hierdie, poortnaam, 9600);
grootte (640, 480);
video = newCapture (hierdie, breedte, hoogte);
video.start ();
noStroke ();
glad ();
vertraging (1000); // Wag totdat die seriële poort oopgemaak is
}
voiddraw () {
as (video.available ()) {
as (gedoen [ledNum] == 0) {
clearDisplay ();
vertraging (1000);
video.lees ();
beeld (video, 0, 0, breedte, hoogte); // Teken die webkamera -video op die skerm
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) {
gedoen [ledNum] = 1;
druk ("Led");
druk (ledNum);
druk ("klaar");
}
as (ledPower [ledNum]> 255) {
ledPower [ledNum] = 255;
}
as (ledPower [ledNum] <0) {
ledPower [ledNum] = 0;
}
}
setLedPower (ledNum, ledPower [ledNum]);
vertraging (1000);
video.lees ();
beeld (video, 0, 0, breedte, hoogte); // Teken die webkamera -video op die skerm
vertraging (10);
terwyl (myPort.available ()> 0) {
int inByte = myPort.read ();
// druk (char (inByte));
}
String imageName = "data/";
imageName+= str (ledNum);
imageName += "_ led.jpg";
saveFrame (imageName);
String originalImageName = "data/org";
originalImageName+= str (ledNum);
originalImageName += ". jpg";
as (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 ();
agtergrond (0);
loadPixels ();
ledIntensity [ledNum] = 0;
numPixelsInLed [ledNum] = 0;
vir (int x = 0; x <breedte; x ++) {
vir (int y = 0; y <hoogte; y ++) {
PxPGetPixelDark (x, y, noLedImg.pixels, breedte);
PxPGetPixelLed (x, y, ledImg.pixels, breedte);
PxPGetPixelOrg (x, y, originalImg.pixels, breedte);
as ((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] ++;
} anders {
rTemp = 0;
gTemp = 0;
bTemp = 0;
}
PxPSetPixel (x, y, rTemp, gTemp, bTemp, 255, pixels, breedte);
}
}
ledIntensity [ledNum] /= numPixelsInLed [ledNum];
if (targetIntensity> ledIntensity [ledNum] && runNumber == 0) {
targetIntensity = ledIntensity [ledNum];
}
updatePixels ();
}
druk (ledNum);
print (',');
print (ledPower [ledNum]);
print (',');
println (ledIntensity [ledNum]);
ledNum ++;
as (ledNum == numLed) {
int donezo = 0;
vir (int i = 0; i <numLed; i ++) {
donezo += klaar ;
}
as (donezo == numLed) {
println ("GEDOEN");
vir (int i = 0; i <numLed; i ++) {
druk (i);
druk ("\ t");
println (ledPower );
}
print ("int vlak [");
druk (ledNum);
print ("] = {");
vir (int i = 0; i <numLed-1; i ++) {
print (ledPower );
print (',');
}
print (ledPower [numLed -1]);
println ("};");
lightUpEven ();
terwyl (waar);
}
print ("Doelintensiteit:");
as (runNumber == 0) {
targetIntensity -= 1;
}
println (targetIntensity);
ledNum = 0;
runNumber ++;
}
}
}
voidPxPGetPixelOrg (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // haal die kleure as 'n int uit die pixels
aOrg = (hierdiePixel >> 24) & 0xFF; // ons moet skuif en masker om elke komponent alleen te kry
rOrg = (hierdiePixel >> 16) & 0xFF; // dit is vinniger as rooi (), groen (), blou ()
gOrg = (hierdiePixel >> 8) & 0xFF;
bOrg = thisPixel & 0xFF;
}
voidPxPGetPixelDark (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // haal die kleure as 'n int uit die pixels
aDark = (hierdiePixel >> 24) & 0xFF; // ons moet skuif en masker om elke komponent alleen te kry
rDark = (hierdiePixel >> 16) & 0xFF; // dit is vinniger as rooi (), groen (), blou ()
gDark = (hierdiePixel >> 8) & 0xFF;
bDark = thisPixel & 0xFF;
}
voidPxPGetPixelLed (intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel = pixelArray [x+y*pixelsWidth]; // haal die kleure as 'n int uit die pixels
aLed = (hierdiePixel >> 24) & 0xFF; // ons moet skuif en masker om elke komponent alleen te kry
rLed = (thisPixel >> 16) & 0xFF; // dit is vinniger as rooi (), groen (), blou ()
gLed = (hierdiePixel >> 8) & 0xFF;
bLed = thisPixel & 0xFF;
}
voidPxPSetPixel (intx, inty, intr, intg, intb, inta, int pixelArray, intpixelsWidth) {
a = (a << 24);
r = r << 16; // Ons verpak al 4 komponente in een int
g = g << 8; // daarom moet ons hulle na hul plekke verskuif
kleur argb = a | r | g | b; // binêre "of" operasie voeg hulle almal by tot een int
pixelArray [x+y*pixelsWidth] = argb; // uiteindelik stel ons die int met te kleure in die pixels
}

sien rawcalibrateDispllay.pde aangebied deur ❤ deur GitHub

Stap 11: Afskeidingsopmerkings

Slaggate om te vermy:

* Met hout kry u waarvoor u betaal. Koop dus hout van goeie gehalte. Berk laaghout is 'n goeie keuse; enige ligte soliede hout sal ook goed doen. Ek het die hout goedkoop en spyt oor my besluit.

* Dit is beter om minder as meer te boor. 'N Paar gate is te diep vir my stuk. En die epoksie verskyn op die voorkant. Dit is baie opvallend sodra u dit agterkom.

* Gebruik 'n boorpunt in plaas van 'n reguit punt. Ek het nog nie met die bal -eindpunt geëksperimenteer nie, maar ek is redelik seker dat die resultate baie beter sal wees.

Ek flirt met die idee om dit op Etsy of tindie te verkoop. Ek sal dit opreg waardeer as u hieronder kommentaar kan lewer as u dink dat dit sin maak:)

Aanbeveel: