Introduction: DIY Smart Electronic Ukulele With Arduino

About: Creative studio about education, art and technology based in Zaragoza, Spain. #TechnovationAragon #EtopiaKids #Explorer @Arduinodayzgz @Makeronilabs @innovart_cc

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 we want on the surface of the ukulele or adding some light effects.

To make that, is necessary to buy a ukulele kit.

We are going to explain how to assemble the instrument, and solve the different problems that could appear.

Step 1: Materials

Structure materials:

1- Body.

2-Neck.

3-Saddle

4-Rope Support

5-Bridge

6-String nut.

7-Fixing ring for machine head (x4).

8-Machine heads (x4).

9-Mounting screws for machine heads (x8).

10-Mounting screws for machine bridge (x2).

11-Cover caps for bridge mounting screws (x2).

12-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 costumize 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 choosen 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 a software called 'Inkscape' which we could obtain from this link: https://inkscape.org/es/descargas/.

    To use it, we must adjust the picture that we want use like we show in the second image. You could look that we have rotate the initial image to could adjust the cicle of the hand with the circle of the instrument. Like we have said before, you could put any image.

    Step 3: 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 logos. 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. We could obtain this software from: http://descargar.cnet.com/windows/t2-laser/3260-2...

    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 appears the cnc controls.
    The two pictures show the process and the result of the engraving with our laser cutter.

    Step 5: 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 would have to 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 odors 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 work in well ventilated spaces.

    Step 6: Hardware

    Our plaque with the Arduino, the acelerometer 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

    To give a special decoration to our ukulele, we could add light effects thanks to 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 a acelerometer (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 conexion between the three components: Arduino NANO, WS2812 and BMA220, like 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.

    <p>//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);
    }</p>

    Step 8: 3D Design

    First, you must size your hardware components to be sure about the correct. 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, which are also included as:

    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

    First we will place the saddleon 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 with glue, 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 Birdge

    The bridge is fixed by gluing 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

    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 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 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 make that, you could whatch that tutorial that explain you how put correctly the strings.

    Step 13: 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.

    Is needed that you tune the ukulele strings. I recomend you this app: GuitarTuna

    Step 14: Enjoy It

    Now, you only have to enjoy your ukulele.

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

    Twitter: @Innovart_cc

    Facebook: @Innovartcc

    Instagram: @Innovart_cc

    Web: Innovart.cc