DesignSpark Electrical Logolinkedin
Menu Search
Ask a Question

Summer of Sound - DIY SMART ELECTRONIC UKULELE WITH ARDUINO

We are going to explain step by step how you can design your own ukulele and add some effects that will make it unique, like drawing something that you want on the surface of the ukulele or adding some light effects.

You can also find all the step by step information to create it on our Instructables website.

To make it, its necessary to first buy a ukulele kit. We are going to explain how to assemble the instrument and solve the different problems that could appear.

Picture of Materials

Picture of Materials

Step 1: Materials

Structure materials:

DIY ukelele mounting kit (it could be another different kit) formed of:

  • Body
  • Neck
  • Saddle
  • Rope Support
  • Bridge
  • String nut
  • Fixing ring for machine head (x4)
  • Machine heads (x4)
  • Mounting screws for machine heads (x8)
  • Mounting screws for machine bridge (x2)
  • Cover caps for bridge mounting screws (x2)
  • Strings (x4)

Electronic materials:

Others

  • Wood varnish
  • Velcro
  • Soldering tin
  • Protective plastic for varnishing
  • Hot melt silicone

Tools:

  • Laser engraving
  • Sandpaper
  • Star screwdriver
  • Paintbrush
  • Hot melt gun
  • Tin soldering iron

 

Step 2: Customize the Ukulele

To customize our ukulele we could make an engraving of a drawing with a laser cutter on the body. In the case of not having that tool, we could paint it.

The picture that we have chosen is the first that appears.

First of all, we have to design the drawing template to make the engraving.

To carry out that, we will use software called 'Inkscape'.

To use it, we must adjust the picture that we want to use as shown in the second image. We have rotated the initial image to align the circle of the hand with the circle of the instrument. As mentioned before, you could use any image you like.

 

Step 3: Vectorize an Image Using Inkscape

 

Picture of Vectorize an Image Using Inkscape

We’ll see how to create a vector file from a pixmap (jpg, png, whatever raster format that Inkscape can open).

Inkscape

Inkscape is an open-source vector graphics editor, and as the title implies, this is the tool that I’ll use to vectorise the images.

Vectorising steps

The steps are common for any vectorization we might want to do.

  1. Open the image in Inkscape
  2. Open the Trace Bitmap Tool Path->Trace Bitmap
  3. Play around the Trace Bitmap options
  4. Run the tracing
  5. Clean up the results (if necessary)

Note the “playing around” part. I’m not an expert on tracing, so I treat this tool as a black box with knobs and lights, twisting and changing until I get the best result.

 

Step 4: Logo Engraving

For this, it is important to have a silhouette of the surface on which the engraving of the drawing will be produced.

To make the engraving, we are going to use 'T2Laser' software available to try free at CNET.

Once we have opened the software, we have to load the image that we have created in the last step. Then, press the button "control laser", and the CNC controls appear. 

The two pictures show the process and the result of the engraving with our laser cutter

Step 5: Sanding and Varnishing

Picture of Sanding and Varnishing

To leave our ukulele bright and with a layer without roughness we can smoothly sand the two parts that make up our instrument with care because we can damage the drawing that has been made (if you have chosen to paint the ukulele, you should sand it first). Then we will varnish our two parts so that they obtain a darker color and the wood presents more resistance. We can use a normal wood varnish, it does not need to be special.

Once we have the varnish, we mix it with a little solvent so that it dissolves a little. Next, we apply the mixture with a brush on the neck and the body of the instrument and let it dry.

If we see that the product needs a second coat, we can sand the two parts a little and re-apply a layer of diluted varnish.

** PRECAUTIONS: The varnish is a chemical product, so it is necessary to perform this process in a ventilated place, wear a mask to avoid inhaling odours and protective goggles.

The materials that we need to be able to work correctly are those that appear in the photos. Mainly we will work with a brush, a varnish can (in our case red color), a little solvent and visual protection. And, above all, do this work in well-ventilated spaces.

Step 6: Hardware

Picture of Hardware

Picture of Hardware

Picture of Hardware

Our plaque with the Arduino, the accelerometer and the wheel with LEDs are going to be introduced in a little bracket to avoid that all the components move in the instrument.

We have also added a battery holder and a switch to make it more comfortable and we do not wear out the battery when we are not using the instrument. We will attach this support with a piece of Velcro (it would also work with silicone and a hot melt gun) to the inner face of the ukulele body.


On the other hand, the LED wheel is smaller than the hole, so it would fall. A support has been designed so that it holds well and can perform its function

Step 7: Software

Picture of Software

Picture of Software

To give a special decoration to our ukulele, we could add light effects using a wheel of LEDs. We are going to use the WS2812, but you can use any other following the instructions of the datasheet. We will use an accelerometer (BMA220) too, that allow to us make an effect of the gravity.

In fact, we will have 4 plays of light, included in the computer library called 'Adafruit' of Arduino. To that, we must make a correct connection between the three components: Arduino NANO, WS2812 and BMA220, as appears in the first image.

The red wires are for power, the GND blacks and the rest are necessary connections for the correct operation.
The code that we used for the light kit is attached in a file called "play_of_light_v0.ino". Make sure you have included the necessary libraries for the correct operation of the program. The battery that we add external to the circuit must have a minimum voltage of 9V and we have to ensure that it is capable of giving the minimum current necessary to power the entire circuit.

//Variables contador e interrupción<br>int counter;
//Variables Ejemplo gravedad
#include  
#include 
#include 
#define NUMBER_OF_LEDS_ON_RING 16
#define NEOPIXEL_RING_DATA_PIN 9</p><p>byte Version[3];
int8_t x_data;
int8_t y_data;
int8_t z_data;
byte range=0x00;
float divi=16;
float x,y,z;
float pi = 3.14159265359;
float nx,ny,angle;
int led, previousLed;
QueueList  ledQueue;
Adafruit_NeoPixel neoring = Adafruit_NeoPixel(NUMBER_OF_LEDS_ON_RING, NEOPIXEL_RING_DATA_PIN, NEO_GRB + NEO_KHZ800);</p><p>//Variables Luces arcoiris
#include 
#ifdef __AVR__
#include 
#endif
#define PIN 9
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.</p><p>//Variables Rueda de colores
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library</p><p>#include 
#ifdef __AVR__
  #include 
#endif</p><p>// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN            9</p><p>// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      16</p><p>// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int delayval = 50; // delay for 50ms</p><p>//Variables colores aleatorios
#include 
#ifdef __AVR__
  #include 
#endif</p><p>#define PIN 9</p><p>#define NUM_LEDS 16</p><p>#define BRIGHTNESS 200</p><p>//Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);</p><p>byte neopix_gamma[] = {
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
    2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
    5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
   10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
   17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
   25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
   37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
   51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
   69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
   90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
  115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
  144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
  177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
  215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////</p><p>/METODO SETUP
void setup() 
{
  //Código: Dirección de la gravedad 
  neoring.begin();
  neoring.setBrightness(200);
  Serial.begin(9600); 
  Wire.begin(); 
  Wire.beginTransmission(0x0A); // address of the accelerometer 
  // range settings
  Wire.write(0x22); //register address
  Wire.write(range); //can be set at"0x00""0x01""0x02""0x03", refer to Datashhet on wiki
  // low pass filter  
  Wire.write(0x20); //register address
  Wire.write(0x05); //can be set at"0x05""0x04"......"0x01""0x00", refer to Datashhet on wiki
  Wire.endTransmission();</p><p>  //Codigo; Luces Arcoiris
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'</p><p>  //Código Rueda de colores
   // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  // End of trinket special code</p><p>  pixels.begin(); // This initializes the NeoPixel library.</p><p>  //Codigo Interrupcion
 counter = 1;</p><p> //Codigo Colores varios
 // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code
  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}</p><p>///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////</p><p>/Bucle infinito  
void loop() { 
  //Caso 1: Juego de luces de la gravedad;
  if(counter == 1){
    for(int i=0;i<100;i++){
    switch(range)  //change the data dealing method based on the range u've set
    {
    case 0x00:divi=16;  break;
    case 0x01:divi=8;  break;
    case 0x02:divi=4;  break;
    case 0x03:divi=2;  break;
    default: Serial.println("range setting is Wrong,range:from 0to 3.Please check!");while(1); 
    }
    AccelerometerInit(); 
   delay(100);
  
   nx=x/2;
   ny=y/2;
   angle=atan((ny/nx))*180/pi;
   if(angle > 0.0){
    if(nx<0.0)
    angle+=180;
   }
   else{
    if(ny > 0.0)
      angle+=180;
      else
        angle += 360;
   }//end else
  
   if(angle == 360.0)
    angle = 0.0;
   led = circularize(angle / (360 / NUMBER_OF_LEDS_ON_RING));
  
    // make led movement smooth
    if(previousLed == led){ 
      // nothing to do 
    }
    else if (counterClockwiseDistanceBetweenLeds(previousLed, led) <= 8)
      led = circularize(previousLed + 1);
    else 
      led = circularize(previousLed - 1);
  
    ledQueue.push(led);
    makeLightShow();
    previousLed = led;
    delay(25);
  }
    counter = 2;
  }//End if counter==1
  //Caso 2: Codigo del juego de luces del arcoiris
  else if(counter == 2){
    for(int j=0; j<5;j++){
    // Some example procedures showing how to display to the pixels:
  colorWipe1(strip.Color(255, 0, 0), 50); // Red
  colorWipe1(strip.Color(0, 255, 0), 50); // Green
  colorWipe1(strip.Color(0, 0, 255), 50); // Blue
  colorWipe1(strip.Color(0, 0, 0, 255), 50); // White RGBW
  // Send a theater pixel chase in...
  theaterChase(strip.Color(127, 127, 127), 50); // White
  theaterChase(strip.Color(127, 0, 0), 50); // Red
  theaterChase(strip.Color(0, 0, 127), 50); // Blue</p><p>  rainbow(5);
  rainbowCycle(5);
  theaterChaseRainbow(5);
    }
  counter = 3;
  }//End if counter==2
  //Caso 3: Luces Aleatorias 
  else if(counter == 3){
    for(int k=0;k<50;k++){
    // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.
  int a=random(255);
  int b=random(255);
  int c=random(255);
  for(int i=0;i</p><p>    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(a,b,c)); // Moderately bright green color.</p><p>    pixels.show(); // This sends the updated pixel color to the hardware.</p><p>    delay(delayval); // Delay for a period of time (in milliseconds).
  }
   a=random(255);
   b=random(255);
   c=random(255);
  for(int i=NUMPIXELS;i>0;i--){</p><p>    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(a,b,c)); // Moderately bright green color.</p><p>    pixels.show(); // This sends the updated pixel color to the hardware.</p><p>    delay(delayval); // Delay for a period of time (in milliseconds).
  }
 }
 counter = 4;
  }
 else if(counter == 4){
  for(int g=0;g<=6;g++){
   // Some example procedures showing how to display to the pixels:
    colorWipe(strip.Color(255, 0, 0), 50); // Red
    colorWipe(strip.Color(0, 255, 0), 50); // Green
    colorWipe(strip.Color(0, 0, 255), 50); // Blue
    colorWipe(strip.Color(0, 0, 0, 255), 50); // White
  
    whiteOverRainbow(20,75,5);  
  
    pulseWhite(5); 
  
    // fullWhite();
    // delay(2000);
  
    rainbowFade2White(3,3,1);</p><p>  }
  counter = 1;
 }
}
///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////</p><p>/Metodos del Ejemplo de la gravedad  
void AccelerometerInit() 
{ 
  Wire.beginTransmission(0x0A); // address of the accelerometer 
  // reset the accelerometer 
  Wire.write(0x04); // X data
  Wire.endTransmission(); 
  Wire.requestFrom(0x0A,1);    // request 6 bytes from slave device #2
  while(Wire.available())    // slave may send less than requested
  { 
    Version[0] = Wire.read(); // receive a byte as characte
  }  
  x_data=(int8_t)Version[0]>>2;
  
  Wire.beginTransmission(0x0A); // address of the accelerometer 
  // reset the accelerometer 
  Wire.write(0x06); // Y data
  Wire.endTransmission(); 
  Wire.requestFrom(0x0A,1);    // request 6 bytes from slave device #2
  while(Wire.available())    // slave may send less than requested
  { 
    Version[1] = Wire.read(); // receive a byte as characte
  }  
  y_data=(int8_t)Version[1]>>2;
   
  Wire.beginTransmission(0x0A); // address of the accelerometer 
  // reset the accelerometer 
  Wire.write(0x08); // Z data
  Wire.endTransmission(); 
  Wire.requestFrom(0x0A,1);    // request 6 bytes from slave device #2
   while(Wire.available())    // slave may send less than requested
  { 
    Version[2] = Wire.read(); // receive a byte as characte
  }  
   z_data=(int8_t)Version[2]>>2; 
   
   x=(float)x_data/divi; 
   y=(float)y_data/divi;
   z=(float)z_data/divi;
   Serial.print("X=");   
   Serial.print(x);         // print the character
   Serial.print("  "); 
   Serial.print("Y=");   
   Serial.print(y);         // print the character
   Serial.print("  "); 
   Serial.print("Z=");           // print the character
   Serial.println(z);   
} </p><p>int circularize(int pos){
  if(pos >= NUMBER_OF_LEDS_ON_RING)
    return(pos - NUMBER_OF_LEDS_ON_RING);
  else if(pos < 0)
    return(pos + NUMBER_OF_LEDS_ON_RING);
  else
    return(pos);
}</p><p>int distance;
int counterClockwiseDistanceBetweenLeds(int prevPos, int nextPos){
  distance = nextPos - prevPos;
  if(distance < 0)
    distance += NUMBER_OF_LEDS_ON_RING;
    
  return(distance); 
}</p><p>int ledPosition, currentQueueSize;
#define NUMBER_OF_LEDS_TO_SHINE 10
int brightnessStep = 255/NUMBER_OF_LEDS_TO_SHINE;</p><p>void makeLightShow(){
  for(int j = 0; j < NUMBER_OF_LEDS_ON_RING; j++)
    neoring.setPixelColor(j, 0, 0, 0);
    
  currentQueueSize = ledQueue.count();
  for(int k = 0; k < currentQueueSize; k++){
    ledPosition = ledQueue.pop();
    neoring.setPixelColor(ledPosition, 0, (brightnessStep * k), 0); 
    if((k == 0 && currentQueueSize < NUMBER_OF_LEDS_TO_SHINE) || k > 0)
      ledQueue.push(ledPosition);
      
  }
  neoring.show();
}</p><p>///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////</p><p>/Metodos del juego de luces del arcoiris
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i</p><p>void rainbow(uint8_t wait) {
  uint16_t i, j;</p><p>  for(j=0; j<256; j++) {
    for(i=0; i</p><p>// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;</p><p>  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}</p><p>//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();</p><p>      delay(wait);</p><p>      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}</p><p>//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      strip.show();</p><p>      delay(wait);</p><p>      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}</p><p>// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}</p><p>///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////</p><p>/Metodos Rueda de colores</p><p>       // int elegirColor = random(0x000000,0xffffff);//Se elige aleatoriamente entre toda la gama de colores comprendida entre 0x000000 y 0xFFFFFF
        //CylonEyeColor=HtmlColor(elegirColor);
    //int elegirColor = random(1,7);//Podemos elegir aleatoriamente entre los 7 colores que hay debajo0xf0ffff
//    if(elegirColor == 1) CylonEyeColor=HtmlColor(0xff0000);//Rojo
//    if(elegirColor == 2) CylonEyeColor=HtmlColor(0x00ff00);//Verde
//    if(elegirColor == 3) CylonEyeColor=HtmlColor(0x0000ff);//Azul
//    if(elegirColor == 4) CylonEyeColor=HtmlColor(0xffff00);//Amarillo
//    if(elegirColor == 5) CylonEyeColor=HtmlColor(0x200020);//Morado
//    if(elegirColor == 6) CylonEyeColor=HtmlColor(0x00ffff);//Azul Claro
//    if(elegirColor == 7) CylonEyeColor=HtmlColor(0x100010);//Rosa
//CylonEyeColor=HtmlColor(0x000000);</p><p>///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////</p><p>/Metodos luces varias</p><p>// Fill the dots one after the other with a color
void colorWipe1(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i</p><p>void pulseWhite(uint8_t wait) {
  for(int j = 0; j < 256 ; j++){
      for(uint16_t i=0; i</p><p>  for(int j = 255; j >= 0 ; j--){
      for(uint16_t i=0; i</p><p>void rainbowFade2White(uint8_t wait, int rainbowLoops, int whiteLoops) {
  float fadeMax = 100.0;
  int fadeVal = 0;
  uint32_t wheelVal;
  int redVal, greenVal, blueVal;</p><p>  for(int k = 0 ; k < rainbowLoops ; k ++){
    
    for(int j=0; j<256; j++) { // 5 cycles of all colors on wheel</p><p>      for(int i=0; i< strip.numPixels(); i++) {</p><p>        wheelVal = Wheel(((i * 256 / strip.numPixels()) + j) & 255);</p><p>        redVal = red(wheelVal) * float(fadeVal/fadeMax);
        greenVal = green(wheelVal) * float(fadeVal/fadeMax);
        blueVal = blue(wheelVal) * float(fadeVal/fadeMax);</p><p>        strip.setPixelColor( i, strip.Color( redVal, greenVal, blueVal ) );</p><p>      }</p><p>      //First loop, fade in!
      if(k == 0 && fadeVal < fadeMax-1) {
          fadeVal++;
      }</p><p>      //Last loop, fade out!
      else if(k == rainbowLoops - 1 && j > 255 - fadeMax ){
          fadeVal--;
      }</p><p>        strip.show();
        delay(wait);
    }
  
  }</p><p>  delay(500);</p><p>  for(int k = 0 ; k < whiteLoops ; k ++){</p><p>    for(int j = 0; j < 256 ; j++){</p><p>        for(uint16_t i=0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, strip.Color(0,0,0, neopix_gamma[j] ) );
          }
          strip.show();
        }</p><p>        delay(2000);
    for(int j = 255; j >= 0 ; j--){</p><p>        for(uint16_t i=0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, strip.Color(0,0,0, neopix_gamma[j] ) );
          }
          strip.show();
        }
  }</p><p>  delay(500);</p><p>}</p><p>void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength ) {
  
  if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;</p><p>  int head = whiteLength - 1;
  int tail = 0;</p><p>  int loops = 3;
  int loopNum = 0;</p><p>  static unsigned long lastTime = 0;</p><p>  while(true){
    for(int j=0; j<256; j++) {
      for(uint16_t i=0; i= tail && i <= head) || (tail > head && i >= tail) || (tail > head && i <= head) ){
          strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
        }
        else{
          strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
        }
        
      }</p><p>      if(millis() - lastTime > whiteSpeed) {
        head++;
        tail++;
        if(head == strip.numPixels()){
          loopNum++;
        }
        lastTime = millis();
      }</p><p>      if(loopNum == loops) return;
    
      head%=strip.numPixels();
      tail%=strip.numPixels();
        strip.show();
        delay(wait);
    }
  }
  
}
void fullWhite() {
  
    for(uint16_t i=0; i</p><p>// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle1(uint8_t wait) {
  uint16_t i, j;</p><p>  for(j=0; j<256 * 5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}</p><p>void rainbow1(uint8_t wait) {
  uint16_t i, j;</p><p>  for(j=0; j<256; j++) {
    for(i=0; i</p><p>// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel1(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3,0);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3,0);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0,0);
}</p><p>uint8_t red(uint32_t c) {
  return (c >> 16);
}
uint8_t green(uint32_t c) {
  return (c >> 8);
}
uint8_t blue(uint32_t c) {
  return (c);
}

 

Step 8: 3D Design

Picture of 3D Design

Picture of 3D Design

First, you must size your hardware components precisely. If they are same as ours, you can use the same files that we lend you.

Both supports have been designed with a 3D printer, these are also included at:

ukelele_support_arduino_v0.stl: https://www.tinkercad.com/things/1aAGZ1xFptA-ukel...

ukelele_support_WS2812_v0.stl: https://www.tinkercad.com/things/1aAGZ1xFptA-ukel...

Finally, the light will be like the two last pictures.

Step 9: Mounting the Neck

Picture of Mounting the NeckPicture of Mounting the Neck

First, we will place the saddle on the neck. The holes that the screws need to hold it are not there, so we'll have to make them, marking where they should go and carefully, with an auger, making the hole.

The same applies to the holes where the screws that hold the neck itself to the body of the instrument. It is not necessary to do them since there are no screws for this fastening, but if we want to do it, there would be no problem.

IMPORTANT: leave 5mm of space between the start of the mast and the start of the tuning fork, because in that hole the nut will be placed.

We will glue the nut in the direction indicated by the figure.

Finally, we will introduce the 4 pins in the holes that are at the beginning of the mast, holding each pin with 2 short screws as shown in the image.

Step 10: Mounting the Bridge

Picture of Mounting the Birdge
Picture of Mounting the Birdge

The bridge is fixed by glueing and with the two long screws in a central position on the body. It is advisable to mark with a pencil the correct position in the body. We will take the distances that are marked in the image.

We will apply glue at the union of the two components. We fix the two parts carefully with the help of a tightening screw until the joint has dried. We will make the two holes for the screws with a 1.5mm drill bit for wood. Fix the bridge with the two long screws in the body. And finally, we put the protective caps on the heads of the screws.

Step 11: Body and Neck Assembly

Picture of Body and Neck Assembly

Picture of Body and Neck Assembly

To assemble the two parts, we have holes in the head of the body, where the neck will fit with two projections it has. We can glue them with traditional glue or with the hot melt gun. To have a greater fixation, you can make the holes that are in the end of the tuning fork to join it to the body.

Step 12: Put in the Ukulele Strings

Finally, we have to place the strings so that our instrument is finished.

Previously we will insert the fixing rings of the pins in the projections of these that go through the mast. To place the strings, we took the 4 strings that came with the kit. First, you have to distinguish each string because they are not all the same. You have to tie one end of each string (the two thick ones with a normal knot, and the two thin ones with a double one) and insert the strings into the slots of the bridge.

Then we will place the strings in such a way that:

• First position: G string (second thickest string).

• Second position: C string (thicker string).

• Third position: E string (second thinner string).

• Fourth position: A string (thinner string).

Thread the strings into the holes of the provided plug. Try to fix each rope by giving two or three turns on the pin. Tension the strings without applying too much force and check the distance between the strings and the saddle.

If you have any doubt about how to make that, you could watch the tutorial that explains how you put the strings on correctly.

Step 13: Testing

Picture of Testing

Finally, we have to see if the ukulele has been properly assembled in such a way that the ideal distance on the first fret is 0.1mm and on the twelfth, it is approximately 1.2mm.

You will need to tune the ukulele strings. I recommend this app: GuitarTuna

 

Step 14: Enjoy It

Now, you only have to enjoy your ukulele!

If you want to know more information about us, you can find us:

Twitter: @Innovart_cc

Facebook: @Innovartcc

Instagram: @Innovart_cc

Web: Innovart.cc

Luis_Innovart has not written a bio yet…

5 Oct 2018, 15:03