Introduction: Digital Potentiometer and LED Ring Driven by Arduino

This project aims to experiment with the digital control of a digital potentiometer type M62429 and an RGB LED ring. This is done by an Arduino Nano, which reads a Rotary Encoder.

The position of the Rotary Encoder gives the factor of division (attenuation) of the digital potentiometer but also the number of LEDs lit (as well as their color), thus making a visual estimate of the signal level.

The applications are in the audio field, for a sound control without potentiometric noises and a fast estimation of the sound level. Thus, for large attenuations the color of the LEDs is blue, for medium attenuations it will be green, and for small attenuations it will be red. For intermediate values, two colors can be displayed simultaneously.

For those interested in software, the routines of rotary encoder reading, LED ring control and serial communication with the digital potentiometer may be of interest. The software will be described in more detail this time.

Supplies

All electronic components can be purchased from AliExpress at low prices.

In your own laboratory you will find the necessary tools.

Step 1: Schematic Diagram

The entire assembly is powered by an adapter from the ac. mains to 9 ... 12Vdc. at J2 plug.

This voltage supplies the Arduino module to pin, 30 (Vin).

The Power supply for bredboard module also offers the + 5V voltage for the LED ring power supply.

In this case, I used the U3 module for convenience, it can be replaced with M7805 (+ 5V / 1A).

M62429 (U1) is powered from the 27 Arduino pin (+ 5V).

C1 ensures decoupling in ac. for U1.

Arduino's D3, D5 pins are programmed as PULLUP inputs. This is where the Rotary Encoder pulses apply.

The D7, D8 Arduino pins are programmed as outputs for the purpose of setting the M62429.

The input audio signal is applied to pin J3, and at J1 the attenuated output audio signal is obtained.

At pin D6 (programmed as output), Arduino delivers the signal that controls the LED ring with 8 LED.

The operating logic of the circuit is: at start-up the attenuation level is maximum (the audio system starts at minimum level). It illuminates only the first LED, in blue.

As the attenuation decreases (from the Rotary Encoder) the audio level increases through the M62429, more LEDs light up blue. By further reducing the attenuation, the LEDs turn green successively, then red. When the attenuation is minimal, (maximum signal level at the output) all LEDs light up red.

Because the M62429 catalog sheet is harder to find, it can be downloaded from here.

Step 2: List of Electronic Components, Measuring and Control Instruments, Other Tools.

Photo 1. Components and materials for the construction of the adjustment and display element.

  • Rotary encoder
  • RGB LED ring, 8 LED
  • Knob for rotary encoder
  • Plastic flat round, outer diameter 20 mm., inner diameter 6mm.
  • Plastic pieces 16X6 mm. -2 pcs.
  • Wires for connection

Photo 2. Components necessary for the basic electrical assembly.

  • Breadboard
  • Arduino Nano
  • Wires for connection
  • Power supply for Breadboard
  • IC: M62429 THT
  • C electr.: 22...47uF/16V
  • Male pins for making electrical ground (GND)

Photo 3. Measurement and control instruments

  • Dual trace oscilloscope Hantek DSO5102P. Any dual trace oscilloscope can be used.
    • Oscilloscope probe kit PP-150. These accompany the oscilloscope. Any probes suitable for the oscilloscope used can be used. - 2pcs.
    • Grundig TG40 type sinusoidal signal generator. Any 1KHz / 1200mVpp sinusoidal signal generator can be used.
    • Output cable for sinusoidal signal generator.
    • Network adapter that can provide 9 ... 12v / 200mA dc.

    Photo 4. Optional tools.

    • Laptop Fujitsu-Siemens with power supply and mouse
    • USB cable to connect the oscilloscope to the laptop.

    These are optional, only when you want to graphically record the results obtained.

    In addition to these, the following are required:

    • Glue gun
    • Tin and tin soldering tool.
    • Wire cutting pliers.
    • Tin sucker.
    • Digital multimeter (any type).
    • Lust for work.

    Step 3: Building the Adjustment Assembly.

    We start from the components in Photo 1.

    To start we will remove the Rotary Encoder from its PCB. We use a tin sucker.

    Then, using glue gun, we will assemble flat round plastic, the 2 pieces of plastic and
    RGB 8 LED ring as in photo 5 .

    Then we will assemble it on the Rotary Encoder by mounting its nut. We introduce the knob.

    Then, using the soldering tool, we will solder 3 wires for the Rotary Encoder and 3 for the LED ring.

    The final result can be seen in photo 5, 6, 7, being the same ensemble seen from different angles.

    Step 4: General Assembly and Putting in Function.

    The general assembly is done according to the schematic diagram and photo 8,9,10.

    Here is the simpler version, only with oscilloscope, without laptop.

    If we want to realize the laptop version, we can be guided by photo 11.

    Increased attention should be paid to power supply for breadboard (see photo 2).

    The following must be done here:

    -The jumpers on the board must be positioned on + 5V.

    -Using a soldering tool with tin, we to the central pin of the input jack a power supply that will supply Arduino with 9 ... 12V to Vin. (Photo 9, red wire).

    If everything is OK, when you press the button on the power supply, the LED on the board will light and the voltage at the board output must be + 5V (digital multimeter). Of course, we must supply with the mains adapter (photo 8).

    In photo 10, 11, you can see how the circuit works correctly, as a whole, after entering the program described in Step 6.

    It is recommended that the programming of the Arduino Nano board be done outside the circuit, the introduction of the board in the circuits being done later.

    Step 5: Experimental Results.

    The DSO5102P digital oscilloscope and laptop are used here for easier graphical recording of experimental results. Otherwise, they can be used: any double trace oscilloscope, any 1KHz / 1 ... 1.2Vpp sinusoidal signal generator (and no laptop needed).

    Here, the oscilloscope has been connected to the laptop with a suitable USB cable, from the USB

    connector on the back of the oscilloscope to a USB connector on the laptop.

    The TG40 generator is set to 1KHz and 1.1Vpp.

    The generator output is connected to terminal 1 of IC M62429 (digital potentiometer input). Also connected here is the test probe of the CH1 digital oscilloscope, for visualizing the input signal. The probe probe of the CH2 digital oscilloscope is connected to the pin2 IC M62429. Here,the signal from the digital potentiometer output is displayed.

    All GND connectors connect to male pins for GND, see photo 11.

    In photo 11 ... 16 you can see the estimated results of the measurements. It can be seen here that as the attenuation in the Rotary Encoder increases, the LED display changes, and the level of the output signal decreases (blue signal to oscilloscope), with a constant input signal level (yellow signal to oscilloscope).

    Photo 17 ... 21 shows more exact results, obtained by recording them with the help of the program that allows the connection of the oscilloscope to the laptop. Images are saved in BMP format, which allows for later recording and display.

    In all images the sensitivity on CH1 (yellow) is 200mV / div, which means a constant input signal of 1.1Vpp.

    For CH2 (Blue) the sensitivity is 100mV / div, except for photo 21, where it is 20mV / div.

    The time base of the oscilloscope is set to 200 us / div.

    The attenuation is calculated according to the formula A (dB) = 20lg (Uout / Uin).

    Photo 17: Uout=440mVpp A=-8dB

    Photo 20: Uout=155mVpp A=-18dB

    Photo 21: Due to the high attenuation, we have a low voltage level at the output, which is affected by noise. Estimated: Uout=40mVpp A=-28dB

    Step 6: Software

    /*Design by Stoica Tudor, Iul 2020. Rew Aug 2020.
    The program allows the control of a digital potentiometer type M62429
    and the estimated display of the sound level on an LED ring.*/

    int cNt=-1;//counter
    byte n; //n=0...23 there are 24 states of the system, for 24 attenuation
    //levels and 24 states of the LED display
    //8 states for Blue, 8 states for Green, 8 states for Red
    byte mn;// modulo
    #define dTa 7 // connect to DATA M62429
    #define cLk 8 // connect to CLOCK M62429
    #define rEnb 5 //Rot enc "B" to ground
    #define rEna 3 //Rot enc "A" to ground
    #include <FastLED.h>
    #define NUM_LEDS 8//the number of LEDs in the ring, here 8
    #define DATA_PIN 6//Arduino pin 6 that connects to the data input of the LED ring
    CRGB leds[NUM_LEDS];

    void setup() {
    pinMode(dTa, OUTPUT);
    pinMode(cLk, OUTPUT);
    pinMode(rEnb, INPUT_PULLUP);
    pinMode(rEna, INPUT_PULLUP);
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
    leds[0] = CRGB::Blue;//at start-up there is only one blue LED on, the others off,
    //corresponding to the maximum attenuation
    for(int i=1;i<NUM_LEDS;i++){
    leds[i] = CRGB::Black;
    FastLED.show();
    }
    }

    void loop() {
    n=roTen();//is assigned to the variable "n" one of the 24 values
    //that are associated with the Rotary Encoder position.

    mn=n%NUM_LEDS;

    switch (n){//depending on the value of the variable n,
    //choose one of the cases 0 ... 23,
    //and the LED ring will light up accordingly.

    case 0://lights the first LED blue, the others off
    leds[0] = CRGB::Blue;
    for(int i=mn+1 ;i<NUM_LEDS ;i++){
    leds[i] = CRGB::Black;
    }
    break;

    case 1:
    fBlue(mn);
    break;



    case 2:
    fBlue(mn);
    break;


    case 3:
    fBlue(mn);
    break;



    case 4:
    fBlue(mn);
    break;


    case 5:
    fBlue(mn);
    break;


    case 6:
    fBlue(mn);
    break;


    case 7://lights all LEDs blue
    for(int i=0 ;i<mn+1 ;i++){
    leds[i] = CRGB::Blue;
    }
    break;

    case 8://lights the first LED green, the others blue
    leds[0] = CRGB::Green;
    for(int i=mn+1 ;i<NUM_LEDS ;i++){
    leds[i] = CRGB::Blue;
    }
    break;


    case 9:
    fGreen(mn);
    break;



    case 10:
    fGreen(mn);
    break;


    case 11:
    fGreen(mn);
    break;



    case 12:
    fGreen(mn);
    break;



    case 13:
    fGreen(mn);
    break;


    case 14:
    fGreen(mn);
    break;


    case 15://lights all LEDs green
    for(int i=0 ;i<mn+1 ;i++){
    leds[i] = CRGB::Green;
    }
    break;



    case 16://lights the first LED red,the others green
    leds[0] = CRGB::Red;
    for(int i=mn+1 ;i<NUM_LEDS ;i++){
    leds[i] = CRGB::Green;
    }
    break;


    case 17:
    fRed(mn);
    break;



    case 18:
    fRed(mn);
    break;


    case 19:
    fRed(mn);
    break;



    case 20:
    fRed(mn);
    break;


    case 21:
    fRed(mn);
    break;


    case 22:
    fRed(mn);
    break;


    case 23://lights all LEDs red
    for(int i=0 ;i<mn+1 ;i++){
    leds[i] = CRGB::Red;
    }
    break;

    }

    FastLED.show();//lights the LEDs as appropriate case

    vOl(n);//call routine for drive M62429

    }


    //routine for blue lights LED1 up to LEDi(i<7),the others off
    void fBlue(byte x)
    {
    for( byte i=0 ;i<mn+1 ;i++){
    leds[i] = CRGB::Blue;
    }
    for( byte i=mn+1 ;i<NUM_LEDS ;i++){
    leds[i] = CRGB::Black;
    }
    }

    //routine for green lights LED1 up to LEDi(i<7),the others blue
    void fGreen(byte x)
    {
    for( byte i=0 ;i<mn+1 ;i++){
    leds[i] = CRGB::Green;
    }
    for( byte i=mn+1 ;i<NUM_LEDS ;i++){
    leds[i] = CRGB::Blue;
    }
    }

    //routine for red lights LED1 up to LEDi(i<7),the others green
    void fRed(byte x)
    {
    for( byte i=0 ;i<mn+1 ;i++){
    leds[i] = CRGB::Red;
    }
    for( byte i=mn+1 ;i<NUM_LEDS ;i++){
    leds[i] = CRGB::Green;
    }
    }

    // Rotary Encoder routine
    int roTen(){

    while(digitalRead(rEnb) & digitalRead(rEna)==1);


    switch(digitalRead(rEnb)) {

    case HIGH:
    while(digitalRead(rEna)==0);
    while(digitalRead(rEnb)==0);
    cNt ++;
    cNt=constrain(cNt,0,23);
    break;

    case LOW:
    while(digitalRead(rEnb)==0);
    while(digitalRead(rEna)==0);
    cNt --;
    cNt=constrain(cNt,0,23);
    break;

    }
    return cNt;
    }

    //Drive M62429 routine
    void vOl (uint8_t aTTn){
    uint16_t maTn []={//matrix with 24 elements, containing the binary words that
    //will program the attenuation level of M62429
    0x0604, 0x0784, 0x0788, 0x078C, 0x0790, 0x0794, 0x0798, 0x079C,
    0x07A0, 0x07A4, 0x07A8, 0x07AC, 0x07B0, 0x07B4, 0x07B8, 0x07BC,
    0x07C0, 0x07C4, 0x07C8, 0x07CC, 0x07D0, 0x0654, 0x06D4, 0x0754
    };

    // send out 11 control bits
    for (byte i = 0; i < 11; i++) {
    delayMicroseconds (2); // M62429P datasheet
    digitalWrite (dTa, 0);
    delayMicroseconds (2);// M62429P datasheet
    digitalWrite (cLk, 0);
    delayMicroseconds (2);// M62429P datasheet
    digitalWrite (dTa, (maTn[aTTn] >> i) & 0x01);
    delayMicroseconds (2);// M62429P datasheet
    digitalWrite(cLk, 1);
    }
    delayMicroseconds (2);// M62429P datasheet
    digitalWrite (dTa, 1);
    delayMicroseconds (2);// M62429P datasheet
    digitalWrite (cLk, 0);
    }

    Software can also be downloaded from:

    https://github.com/StoicaT/Digital-Potentiometer-a...

    To begin with, the FastLed and AdafruitNeoPixel libraries must be installed. These can be found at the following addresses:

    https://github.com/FastLED/FastLED

    https://github.com/adafruit/Adafruit_NeoPixel

    These will be downloaded as archives and installed in the Arduino IDE via: Sketch --> Include Library --> Add.Zip Library.

    Installing FastLED on some variants of Arduino IDE gave errors. One variant that worked well is Arduino IDE 1.6.5.

    At the beginning of the program, global variables are declared:

    cNt: (counter) variable of type int, necessary for the operation of the Rotary Encoder routine.

    n: byte variable type that describes the 24 possible states of the system.

    mn: byte variable type, modulo nrLED from n . Here, nrLED=8.

    Next, the hardware connections are defined, as in the wiring diagram, and the number of LEDs used in the ring (8).

    The FastLED library is included and it declares the number of LEDs (CRGB leds).

    Void Setup:

    - The corresponding pins are initialized as outputs or as PULLUP inputs.

    - FastLED is initialized with NEOPIXEL elements (mandatory and standard procedure).

    -The following lines represent a small routine that initially lights a single LED in blue, the others off (initial state LED ring).

    Void loop:

    -Call the roTen function that describes the operation of the Rotary Encoder and assign the value of this function to the variable n. So n depends on the value of the Rotary Encoder and has values between 0 and 23.

    -Calculate mn which is equal to n modulo 8, because there are 8 LEDs.

    -Follow the switch (n) ... case statement.

    Because n = 0 ... 23, there are 24 cases, case 0..case 23.

    These define the 24 LEDring lighting cases:

    Case0: LED 0 blue, all others off.

    Case1: LED 0, LED1 blue, all others off.

    ............

    Case7: all LEDs blue.

    Case8: LED 0 green, all others blue.

    Case9: LED0, LED1 green, all others blue.

    .................

    Case15: all LEDs green .

    Case16: LED0 red, all others green.

    Case17: LED0, LED1 red, all others green.

    ................

    Case23: all LEDs red.

    -Then the selected LEDring status is displayed with the FastLED.show statement.

    -At the end of the loop, the function vOl (n) is called, which communicates to M62429 the chosen attenuation, being here also a number of 24 states (n = 0 ... 23).

    Rotary Encoder routine roTen()

    Returns the integer value cNt (counter) in relation to the number of pulses given by the Rotary Encoder contacts.

    As long as contacts A and B of the Rotary Encoder are 1, the program flow is blocked in the while statement at the beginning of the function.

    As soon as one of the contacts switches to GND it exits the while loop and tests

    contact B with the switch statement.

    If it is contact B that is at GND, cNt (HIGH case) is incremented.

    If not, it means that A is at GND and decrements cNt (LOW case).

    In both cases, the cNt value is limited in the range 0 ... 23 with the constrain function.


    vOl() routine attenuation control function (volume) for M62429

    It is a Void function (which does not return anything).

    The function variable is aTTn of type uint8_t.

    The first part of the function builds the binary words for the M62429 command, and in the second part this word is sent serially to the M62429.

    Table1 shows how binary words are constructed according to M62429 datasheet.

    Such an organization is necessary because the M62429 has a special way of forming binary words (see datasheet, VOLUME CODE table).

    Here, D7 and D8 contain a fine attenuation adjustment, and D2 ... D6 a coarse adjustment.

    D0, D1 make a simultaneous or separate adjustment of the two channels. In this program, D0 = D1 = 0, for a simultaneous adjustment of the two channels.

    In DATA INPUT FORMAT (see Data Sheet) is given the bit alignment order.

    In Table 1 on the first column is the attenuation in -dB (you can choose 24 desired values), in the second column is the value of n, (n = 0 ..... n = 23) and then follow the values D10. ... D0 of the 11 bits required for programming.

    On the last column is written the value in Hexa of the number thus obtained. The value appears in 0xVVVV format, 16 bits. Because we only have 11 bits to program, the first 5 will be 0, so the data will be 0x0VVV.

    The data in Table 1 are used as elements of the maTn matrix, which has a line and 24 columns.

    The second part of the routine is intended for the serial transmission of a selected element from the matrix, which is done according to the data sheet, according to the RELATIONSHIP BETWEEN DATA AND CLOCK section.

    Thus, data and clock pulses are applied according to the datasheet, the corresponding bit is read, then binary word is rotated to the right with a bit and the operation is resumed a total of 11 times (for loop).

    For higher requirements, LEDring with 12 LED can be used.

    In this case, n = 0 ... 35, there will be 36 states of the system.

    So there will be 36 cases for switch (n) in the loop, and maTn will have 36 elements, so there will be 36 attenuation values available.

    The program is loaded on the Arduino Nano.


    And that's it.