Daftar Isi:

Jam LED Kayu - Gaya Analog: 11 Langkah (dengan Gambar)
Jam LED Kayu - Gaya Analog: 11 Langkah (dengan Gambar)

Video: Jam LED Kayu - Gaya Analog: 11 Langkah (dengan Gambar)

Video: Jam LED Kayu - Gaya Analog: 11 Langkah (dengan Gambar)
Video: SANGAT MUDAH CARA SETTING JAM TANGAN LED KARAKTER ANAK #shorts 2024, Juli
Anonim
Jam LED Kayu - Gaya Analog
Jam LED Kayu - Gaya Analog

Ini adalah jam LED kayu gaya analog. Saya tidak tahu mengapa saya belum pernah melihat salah satu dari ini sebelumnya..meskipun tipe digital sangat umum. Anyhoo, ini dia!

Langkah 1:

Gambar
Gambar
Gambar
Gambar

Proyek jam kayu lapis dimulai sebagai proyek awal sederhana untuk router CNC. Saya sedang melihat proyek sederhana secara online dan menemukan lampu ini (gambar di atas). Saya juga melihat jam digital yang bersinar melalui veneer kayu (gambar di atas). Jadi, menggabungkan dua proyek adalah ide yang jelas. Mencari untuk menantang diri sendiri, saya memutuskan untuk tidak menggunakan veneer tetapi hanya sepotong kayu untuk proyek ini.

Langkah 2: Desain

Desain
Desain
Desain
Desain

Saya mendesain jam di Inkscape (gambar di atas). Desainnya sangat sederhana berdasarkan pilihan. Saya memutuskan untuk tidak merutekan jejak untuk kabel karena pada titik ini saya tidak yakin apakah saya ingin menggunakan kabel radial atau perimeter. (Akhirnya saya memutuskan untuk menggunakan kabel perimeter.) Satu neopiksel masuk ke masing-masing lubang melingkar kecil untuk menunjukkan waktu menit dan jam, dengan presisi lima menit. Lingkaran di tengah akan dialihkan untuk mengakomodasi elektronik.

Langkah 3: CNCing

CNCing
CNCing
CNCing
CNCing
CNCing
CNCing
CNCing
CNCing

Saya merancang jalur alat di MasterCAM, dan menggunakan technoRouter untuk menggiling jam dari kayu lapis 3/4 inci. Saya menggunakan potongan 15"x15" untuk ini, dengan pemborosan minimal. Triknya adalah mengeluarkan kayu sebanyak mungkin tanpa menembus kayu. Meninggalkan 0,05"-0,1" adalah pilihan yang baik untuk kayu ringan. Jika Anda tidak yakin, lebih baik sisakan lebih banyak kayu, karena Anda selalu bisa mengampelas sisi lainnya. Saya akhirnya membuang terlalu banyak kayu dari beberapa bagian, tetapi untungnya hasilnya tidak terlalu buruk karena ini.

Catatan untuk pengguna tanpa akses ke CNC:

Proyek ini dapat dengan mudah dilakukan dengan mesin bor. Anda hanya perlu mengatur stop pada titik di mana Anda meninggalkan sekitar 0,1 kayu yang tersisa di pangkalan. Anda harus tepat, tetapi tidak terlalu tepat. Lagi pula, idealnya tidak ada yang akan melihat semua LED menyala di saat yang sama, sehingga Anda bisa lolos dengan sedikit slop.

Langkah 4: Elektronik

Elektronik
Elektronik
Elektronik
Elektronik
Elektronik
Elektronik

Elektronik cukup sederhana. Ada 24 neopiksel, dua belas untuk menunjukkan jam dan dua belas untuk menunjukkan menit, dengan presisi lima menit. Arduino pro mini mengontrol neopiksel dan mendapatkan waktu yang akurat melalui modul DS3231 real time clock (RTC). Modul RTC memiliki sel koin sebagai cadangan, sehingga tidak kehilangan waktu bahkan ketika listrik mati.

Bahan:

Arduino pro mini (atau Arduino lainnya dalam hal ini)

Papan breakout DS3231

Neopiksel di papan breakout individu

Langkah 5: Perakitan Elektronik

Perakitan Elektronik
Perakitan Elektronik
Perakitan Elektronik
Perakitan Elektronik
Perakitan Elektronik
Perakitan Elektronik
Perakitan Elektronik
Perakitan Elektronik

Saya menghubungkan neopiksel dalam sebuah string, menggunakan kabel 2,5 untuk dua belas led pertama dan kabel empat inci untuk dua belas berikutnya. Saya bisa menggunakan panjang kabel yang sedikit lebih kecil. Setelah membuat string, saya mengujinya, memastikan soldernya sambungannya bagus Saya menambahkan sakelar sesaat untuk menyalakan semua led, hanya untuk pamer.

Langkah 6: Lari Kering

Lari Kering
Lari Kering
Lari Kering
Lari Kering
Lari Kering
Lari Kering
Lari Kering
Lari Kering

Setelah bereksperimen, memasang LED di lubang dan menyalakan semuanya, saya puas dengan hasilnya. Jadi saya mengampelas bagian depan sedikit dan menerapkan lapisan PU. Saya akhirnya mengampelas mantel nanti, tetapi ada baiknya untuk membiarkannya jika Anda tidak menganggapnya tidak menyenangkan secara estetika.

Langkah 7: Epoxy

Epoksi
Epoksi
Epoksi
Epoksi

Setelah beberapa pengujian dengan posisi led di dalam lubang, saya pikir diskusi terbaik dicapai ketika LED sekitar 0,2 dari ujung lubang. Ketika Anda mencobanya sendiri, kecerahan LED akan sangat berbeda dalam setiap lubang. Jangan khawatir tentang ini; kami akan memperbaikinya dalam kode. Ini karena jenis mata bor yang saya gunakan. Jika saya melakukannya lagi, saya akan menggunakan mata bor ujung bola untuk lubangnya Tapi, bagaimanapun, untuk mendapatkan jarak saya mencampur beberapa epoksi dan menaruh sedikit di setiap lubang.

Langkah 8: Menyatukan Semuanya

Menyatukan Semuanya
Menyatukan Semuanya
Menyatukan Semuanya
Menyatukan Semuanya
Menyatukan Semuanya
Menyatukan Semuanya
Menyatukan Semuanya
Menyatukan Semuanya

LED akan ditempatkan mulai dari posisi jarum jam 12 bergerak berlawanan arah jarum jam melalui semua posisi jarum jam dan kemudian ke jarum menit, sekali lagi bergerak dari tanda 60 menit bergerak berlawanan arah jarum jam. Hal ini agar ketika kita melihat dari depan muncul pola LED searah jarum jam.

Setelah epoksi sembuh selama satu jam, saya menambahkan epoksi lagi. Kali ini, saya menempatkan LED di lubang, memastikan untuk menutupi kabel dan sambungan solder dengan epoksi. Hal ini membuat difusi cahaya yang baik dan mengamankan kabel.

Langkah 9: Kode

Kode
Kode

Kode ada di GitHub, silakan memodifikasinya untuk Anda gunakan. Saat Anda menyalakan semua LED ke tingkat yang sama, kecerahan cahaya yang masuk akan sangat berbeda di setiap lubang. Ini karena perbedaan ketebalan kayu di lubang dan perbedaan naungan kayu, Seperti yang Anda lihat, warna kayu sedikit bervariasi di bagian saya. Untuk memperbaiki perbedaan kecerahan ini, saya membuat matriks tingkat kecerahan led. Dan mengurangi kecerahan LED yang lebih terang. Ini adalah proses coba-coba dan dapat memakan waktu beberapa menit, tetapi hasilnya sepadan.

kayu lapisJam.ino

// Jam Kayu Lapis
// Penulis: tinkrmind
// Atribusi 4.0 Internasional (CC BY 4.0). Anda bebas untuk:
// Bagikan - salin dan distribusikan ulang materi dalam media atau format apa pun
// Adaptasi - remix, ubah, dan bangun materi untuk tujuan apa pun, bahkan secara komersial.
// Hore!
#termasuk
#sertakan"RTClib.h"
RTC_DS3231 rtc;
#include"Adafruit_NeoPixel.h"
#ifdef _AVR_
#termasuk
#berakhir jika
#definePIN6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
int jamPixel = 0;
int menitPixel = 0;
unsignedlong lastRtcCheck;
String masukanString = ""; // string untuk menampung data yang masuk
boolean stringLengkap = false; // apakah string sudah selesai
int level[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};
kekosongan () {
#ifndef ESP8266
while (!Serial); // untuk Leonardo/Mikro/Nol
#berakhir jika
// Ini untuk Trinket 5V 16MHz, Anda dapat menghapus tiga baris ini jika Anda tidak menggunakan Trinket
#jika ditentukan (_AVR_ATtiny85_)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#berakhir jika
// Akhir dari kode khusus perhiasan
Serial.begin(9600);
strip.mulai();
strip.tampilkan(); // Inisialisasi semua piksel ke 'mati'
jika (! rtc.begin()) {
Serial.println("Tidak dapat menemukan RTC");
sementara (1);
}
pinMode(2, INPUT_PULLUP);
// rtc.adjust(DateTime(F(_DATE_), F(_TIME_)));
jika (rtc.lostPower()) {
Serial.println("RTC kehilangan daya, ayo atur waktunya!");
// baris berikut menetapkan RTC ke tanggal & waktu sketsa ini dikompilasi
rtc.adjust(DateTime(F(_DATE_), F(_TIME_)));
// Baris ini menetapkan RTC dengan tanggal & waktu eksplisit, misalnya untuk mengatur
// 21 Januari 2014 jam 3 pagi Anda akan menelepon:
// rtc.adjust(DateTime(2017, 11, 06, 2, 49, 0));
}
// rtc.adjust(DateTime(2017, 11, 06, 2, 49, 0));
// lightUpEven();
// sementara (1);
lastRtcCheck = 0;
}
batal () {
if (milis() - lastRtcCheck >2000) {
DateTime sekarang = rtc.now();
Serial.print(sekarang.jam(), DES);
Serial.print(':');
Serial.print(sekarang.menit(), DEC);
Serial.print(':');
Serial.print(sekarang.detik(), DES);
Serial.println();
waktu pertunjukan();
lastRtcCheck = milis();
}
if (!digitalRead(2)) {
lightUpEven();
}
if (stringLengkap) {
Serial.println(inputString);
if (inputString[0] == 'l') {
Serial.println("Tingkat");
lightUpEven();
}
if (inputString[0] == 'c') {
Serial.println("Waktu tayang");
waktu pertunjukan();
strip.tampilkan();
}
if (inputString[0] == '1') {
Serial.println("Menyalakan semua LED");
lightUp(strip. Color(255, 255, 255));
strip.tampilkan();
}
if (inputString[0] == '0') {
Serial.println("Mengosongkan strip");
jernih();
strip.tampilkan();
}
// #3, 255 akan mengatur nomor led 3 ke level 255, 255, 255
if (inputString[0] == '#') {
Suhu tali;
temp = inputString.substring(1);
int pixNum = suhu.toInt();
temp = inputString.substring(inputString.indexOf(', ') + 1);
int intensitas = suhu.toInt();
Serial.print("Setelan ");
Serial.print(pixNum);
Serial.print("ke tingkat ");
Serial.println(intensitas);
strip.setPixelColor(pixNum, strip. Color(intensitas, intensitas, intensitas));
strip.tampilkan();
}
// #3, 255, 0, 125 akan mengatur nomor led 3 ke level 255, 0, 125
if (inputString[0] == '$') {
Suhu tali;
temp = inputString.substring(1);
int pixNum = suhu.toInt();
int rIndex = inputString.indexOf(', ') + 1;
temp = inputString.substring(rIndex);
int rIntensitas = suhu.toInt();
intgIndex = inputString.indexOf(', ', rIndex + 1) + 1;
suhu = inputString.substring(gIndex);
intgIntensitas = suhu.toInt();
int bIndex = inputString.indexOf(', ', gIndex + 1) + 1;
suhu = inputString.substring(bIndex);
int bIntensitas = suhu.toInt();
Serial.print("Setelan ");
Serial.print(pixNum);
Serial.print("R ke ");
Serial.print(rIntensitas);
Serial.print("G ke ");
Serial.print(gIntensitas);
Serial.print("B ke ");
Serial.println(bIntensitas);
strip.setPixelColor(pixNum, strip. Color(rIntensitas, gIntensitas, bIntensitas));
strip.tampilkan();
}
if (inputString[0] == 's') {
Suhu tali;
int jam, menit;
temp = inputString.substring(1);
jam = suhu.toInt();
int rIndex = inputString.indexOf(', ') + 1;
temp = inputString.substring(rIndex);
menit = temp.toInt();
Serial.print("Waktu tayang: ");
Serial.print(jam);
Serial.print(":");
Serial.print(menit);
showTime(jam, menit);
penundaan (1000);
}
inputString = "";
stringLengkap = salah;
}
// tunda(1000);
}
voidserialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringLengkap = benar;
}
penundaan (1);
}
}
batalkan() {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip. Color(0, 0, 0));
}
}
voidshowWaktu() {
DateTime sekarang = rtc.now();
jamPixel = sekarang.jam() % 12;
menitPixel = (sekarang.menit() / 5) % 12 + 12;
jernih();
// 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.tampilkan();
}
voidshowTime(int jam, int menit) {
jamPixel = jam % 12;
menitPixel = (menit / 5) % 12 + 12;
jernih();
// 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.tampilkan();
}
voidlightUp(warna uint32_t) {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, warna);
}
strip.tampilkan();
}
voidlightUpEven() {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip. Color(level, level, level));
}
strip.tampilkan();
}

lihat rawplywoodClock.ino dihosting dengan ❤ oleh GitHub

Langkah 10: Visi Komputer - Kalibrasi

Visi Komputer - Kalibrasi
Visi Komputer - Kalibrasi
Visi Komputer - Kalibrasi
Visi Komputer - Kalibrasi

Saya membuat pilihan sadar untuk tidak menggunakan veneer dalam proyek ini. Jika saya punya, ketebalan kayu akan sama di depan semua LED. Tapi, karena saya memiliki ketebalan kayu yang berbeda di depan setiap LED dan karena warna kayu juga sangat bervariasi, kecerahan LED berbeda untuk setiap LED. Untuk membuat semua LED tampak memiliki kecerahan yang sama, saya membuat trik yang bagus.

Saya menulis beberapa kode pemrosesan (di GitHub) yang mengambil foto jam, dan menganalisis kecerahan setiap LED secara bergantian. Kemudian memvariasikan daya ke setiap LED untuk mencoba membuat semuanya memiliki kecerahan yang sama dengan LED paling redup. Sekarang, saya tahu ini berlebihan, tetapi pemrosesan gambar sangat menyenangkan! Dan, saya berharap untuk mengembangkan kode kalibrasi sebagai perpustakaan.

Anda dapat melihat kecerahan LED sebelum dan sesudah kalibrasi pada foto di atas.

kalibrasiDisplay.pde

importprocessing.video.*;
importprocessing.serial.*;
Port saya serial;
Menangkap video;
finalint numLed =24;
int ledNum =0;
// Anda harus memiliki variabel global ini untuk menggunakan PxPGetPixelDark()
int rDark, gDark, bDark, aDark;
int rLed, gLed, bLed, aLed;
int rOrg, orgOrg, orgOrg, aOrg;
int rTemp, gTemp, bTemp, aTemp;
PGambar Gambar kami;
int runNumber =0;
int kesalahan yang dapat diterima =3;
int selesai;
int numPixelsInLed;
panjang ledIntensitas;
int ledPower;
intensitas target panjang = 99999999;
voidsetup() {
selesai =newint[jumlahLed];
numPixelsInLed =newint[numLed];
ledIntensity =newlong[numLed];
ledPower =newint[numLed];
untuk (int i=0; i<numLed; i++) {
ledPower =255;
}
printArray(Serial.list());
String portName =Serial.list()[31];
myPort =newSerial(ini, portName, 9600);
ukuran (640, 480);
video =newCapture(ini, lebar, tinggi);
video.mulai();
tidak ada Stroke();
halus();
penundaan (1000); // Tunggu hingga port serial terbuka
}
batal menarik() {
if (video.available()) {
if (selesai[ledNum] ==0) {
clearDisplay();
penundaan (1000);
video.baca();
gambar(video, 0, 0, lebar, tinggi); // Gambarkan video webcam ke layar
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 <= AcceptError) {
selesai[ledNum] =1;
print("Lampu");
cetak (nomor led);
print("selesai");
}
if (ledPower[ledNum] >255) {
ledPower[ledNum] =255;
}
if (ledPower[ledNum] <0) {
ledPower[ledNum]=0;
}
}
setLedPower(ledNum, ledPower[ledNum]);
penundaan (1000);
video.baca();
gambar(video, 0, 0, lebar, tinggi); // Gambarkan video webcam ke layar
penundaan (10);
while (myPort.available() >0) {
int inByte = myPort.read();
//cetak(char(dalamByte));
}
String namagambar="data/";
imageName+=str(ledNum);
imageName +="_led.jpg";
saveFrame(namagambar);
String originalImageName ="data/org";
originalImageName+=str(ledNum);
originalImageName +=".jpg";
if (runNumber ==0) {
saveFrame(NamaGambarasli);
}
PImage noLedImg =loadImage("data/no_leds.jpg");
PImage ledImg =loadImage(imageName);
PImage originalImg =loadImage(originalImageName);
noLedImg.loadPixels();
ledImg.loadPixels();
originalImg.loadPixels();
latar belakang (0);
memuatPixel();
ledIntensity[ledNum] =0;
numPixelsInLed[ledNum] =0;
for (int x =0; x<lebar; x++) {
untuk (int y =0; y<tinggi; y++) {
PxPGetPixelDark(x, y, noLedImg.pixels, lebar);
PxPGetPixelLed(x, y, ledImg.pixels, lebar);
PxPGetPixelOrg(x, y, originalImg.pixels, lebar);
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);
suhu = 255;
gTemp=255;
bTemp=255;
numPixelsInLed[ledNum]++;
} lain {
suhu = 0;
gTemp=0;
bTemp=0;
}
PxPSetPixel(x, y, rTemp, gTemp, bTemp, 255, piksel, lebar);
}
}
ledIntensity[ledNum] /= numPixelsInLed[ledNum];
if (targetIntensity > ledIntensity[ledNum] && runNumber ==0) {
targetIntensity = ledIntensity[ledNum];
}
perbarui piksel();
}
cetak (nomor led);
cetak(',');
print(ledPower[ledNum]);
cetak(',');
println(Intensitas led[Jumlah led]);
ledNum++;
if (nomor led == nomor led) {
int selesai =0;
for (int i=0; i<numLed; i++) {
selesai += selesai;
}
if (donezo == numLed) {
println("SELESAI");
untuk (int i=0; i<numLed; i++) {
cetak(i);
print("\t");
println(Daya led);
}
print("tingkat int[");
cetak (nomor led);
cetak("] = {");
untuk (int i=0; i<numLed-1; i++) {
cetak(ledPower);
cetak(',');
}
print(ledPower[numLed -1]);
println("};");
lightUpEven();
sementara (benar);
}
print("Intensitas sasaran: ");
if (runNumber ==0) {
targetIntensitas -=1;
}
println(intensitas target);
ledNum = 0;
runNumber++;
}
}
}
voidPxPGetPixelOrg(intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel=pixelArray[x+y*pixelsWidth]; // mendapatkan warna sebagai int dari piksel
aOrg = (piksel ini >>24) &0xFF; // kita perlu menggeser dan menutupi untuk mendapatkan masing-masing komponen saja
rOrg = (piksel ini >>16) &0xFF; // ini lebih cepat daripada memanggil red(), green(), blue()
gOrg = (thisPixel >>8) &0xFF;
bOrg = piksel ini &0xFF;
}
voidPxPGetPixelDark(intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel=pixelArray[x+y*pixelsWidth]; // mendapatkan warna sebagai int dari piksel
aDark = (thisPixel >>24) &0xFF; // kita perlu menggeser dan menutupi untuk mendapatkan masing-masing komponen saja
rDark = (piksel ini >>16) &0xFF; // ini lebih cepat daripada memanggil red(), green(), blue()
gDark = (piksel ini >>8) &0xFF;
bDark = piksel ini &0xFF;
}
voidPxPGetPixelLed(intx, inty, int pixelArray, intpixelsWidth) {
int thisPixel=pixelArray[x+y*pixelsWidth]; // mendapatkan warna sebagai int dari piksel
aLed = (piksel ini >>24) &0xFF; // kita perlu menggeser dan menutupi untuk mendapatkan masing-masing komponen saja
rLed = (piksel ini >>16) &0xFF; // ini lebih cepat daripada memanggil red(), green(), blue()
gLed = (thisPixel >>8) &0xFF;
bLed = piksel ini &0xFF;
}
voidPxPSetPixel(intx, inty, intr, intg, intb, inta, int pixelArray, intpixelsWidth) {
a =(a<<24);
r = r <<16; // Kami mengemas semua 4 komponen menjadi satu kesatuan
g = g <<8; // jadi kita perlu memindahkan mereka ke tempatnya
warna argb = a | r | g | B; // operasi biner "atau" menambahkan semuanya menjadi satu int
pixelArray[x+y*pixelsWidth]= argb; // akhirnya kita atur int dengan warna te ke dalam piksel
}

lihat rawcalibrateDispllay.pde dihosting dengan ❤ oleh GitHub

Langkah 11: Keterangan Perpisahan

Jebakan yang harus dihindari:

* Dengan kayu, Anda mendapatkan apa yang Anda bayar. Jadi, dapatkan kayu berkualitas baik. Kayu lapis birch adalah pilihan yang baik; kayu solid ringan apa pun juga akan cocok. Saya merugi di atas kayu dan menyesali keputusan saya.

* Lebih baik mengebor lebih sedikit daripada lebih banyak. Beberapa lubang masuk terlalu dalam untuk bagian saya. Dan epoksi terlihat di bagian depan. Ini sangat terlihat setelah Anda menyadarinya.

* Gunakan mata bor ujung bola alih-alih ujung lurus. Saya belum bereksperimen dengan ujung bola, tapi saya yakin hasilnya akan jauh lebih baik.

Saya tergoda dengan ide menjual ini di Etsy atau tindie. Saya akan sangat menghargai jika Anda bisa berkomentar di bawah jika menurut Anda masuk akal:)

Direkomendasikan: