Direct Digital Synthesizer (DDS) (Part 4)

Part 1234567

Encoder library + LCD libray + DDS library + some more code = MicroDDS!

MicroDDS is a fancy little device which will allow you to generate multiple types of wave: Flat, Sine, Square, Triangle, Saw tooth, Random.

The hardware is limited to an Arduino Board, 1 LCD (2 lines, 16 characters), 1 rotary encoder, 14 precision resistors and one capacitor.

The MicroDDS functions, which are menu driven, include

  • Running mode (ON/OFF)
  • Frequency adjustment (1 Hz to 16000 Hz)
  • Wave type: Flat, Sine, Square, Triangle, Saw tooth, Random

Plug it to a DC power supply and have fun with it!

Check this page for code requests.

Known bugs, flaws, defects and lacks:

  • Default values of parameters are not recorded in EEPROM
  • Timer0 should be deactivated in order to improve the stability of signal frequency
  • Changing frequency while generator is running is slowed down because (Timing pb between encoder and DDS)
  • Missing custom wave: entering 256 data points from user interface may be boring! Have to restore a serial communication between application and any computer
  • Restore command processor for remote control of application
  • Your comment: …

Part 5

20 Comments

  1. Jean-Francois Theoret says:

    Hello Didier!

    I will be experimenting with rotary encoders (as soon as my Mouser order comes in…) and I was wondering how you wired them on this project’s picture. Your schematic shows it directly connected to PD5, PD6 and PD7, but in your picture, there are resistors and capacitors.

    I surmise the resistors are used as pull ups? And what about the capacitors? Could you please explain their use (they seem to be in series with the signal)? And how did you determine their value?

    Keep up the great work!!!

    Thanks!

    • Didier says:

      Good question!
      Alps (my favorite rotary encoders maker) recommends to filter the output from its component. I followed the recommendation for the first prototype in order to avoid to put a spanner in the works! But finally, after working on the debouncing question ‘by soft’, I tried the encoder w/o filters, and it proved to work perfectly. I would suggest that you do not use them if you want to get the best from the booster effect (counting frequency dependent on the rotating speed of the encoder); otherwise, please check the maker’s specifications.
      So, its your choice now!

  2. Jean-Francois Theoret says:

    Thanks for the answer!! I’ll check the Bourns datasheet, but I will surely evaluate it without the caps 🙂

    I have another question for you on the lines of the DDS – I’ve been toying around with the idea of signal generation, after reading your blog.

    For now, I wanted to test the limits of the Arduino system by just switching a pin ON and OFF as fast as I could with the following code (the NOPs are inserted to get a 50% duty cycle)

    [code]
    void loop() {
    cli();
    while (1) {
    PORTD |= 0x8;
    NOP;
    NOP;
    PORTD &= ~0x8;
    }
    }
    [/code]

    I’ve been trying it on two Arduinos I have:

    1. Arduino UNO with proper crystal;
    2. Arduino Bare Bones Board with 16MHz Resonator.

    I have however been getting very different results: please see the following scope traces:

    Arduino UNO:
    [IMG]http://i942.photobucket.com/albums/ad270/jftheoret/arduino_uno.png[/IMG]

    Arduino BBB:
    [IMG]http://i942.photobucket.com/albums/ad270/jftheoret/rbbb.png[/IMG]

    I would rather use the BBB version, but clearly the signal quality sucks. I am wondering if this is only due to the crystal. Have you encountered such a bad signal on one of your builds?

    To your opinion, if I build a BBB with a proper crystal instead of a resonator, will the signals be similar on the two devices?

    For what it’s worth, here were the test differences:
    1. Both were powered through USB, so I don’t think voltage regulation could be the cause here.
    2. The Uno was on its board, while the BBB was plugged in to a breadboard.
    3. The BBB as the Optiboot bootloader while the Uno is factory default.

    Thanks for any hint as to where this issue comes from!

  3. Didier says:

    The scope sucks :-° Sorry, real wierd joke 😉 HP products are really good (I spent 10 years there!)

    To my own opinion, the resonator/quartz as almost nothing todo with the poor quality of your signal. The breadbord can! Because you create a parasitic capacitance. What you can do is to attach a reasonable laod to your output pin, around 10k Ohms. This sould decrease the uncontrolled overshoot.

    I’l check that with my Rigol (uprated DS1052A)

  4. Jean-Francois Theoret says:

    (Yeah, I know, the ‘scope sucks – I actually have to pay to upgrade mine from 70 to 100 MHz ;-))

    Arrgh! Breadboard issue.

    Pulled it off the breadboard, redid the tests, and VOILÀ!

    Here are the results:

    http://i942.photobucket.com/albums/ad270/jftheoret/bbb_wo_breadboard.png
    http://i942.photobucket.com/albums/ad270/jftheoret/bbb_wo_breadboard1.png

    Thanks for your help 🙂

    • Didier says:

      That is nice!
      Consider a Pi filter between your PS and the microprocessor: starting from PS, 1µF pol., 2 to 5 ohms resistor in serie, and 0.1 µF non pol. next to the chip. It may help removing this little rumble (Not the overshoot).

  5. Zorrokuugen says:

    Hello, thank you so much for this proyect.

    How do I have to connect the ENCODER?? I see one, two, maybe three resistor and two other components in the picture.
    I had never worked with rotary encoders and I don’t know how to connect it. If you can help me I will very gratefull with you 🙂

  6. Didier says:

    Good point!
    In the beginning, I strictly followed Alps specifications and recommendations. adding an RC filter next to the contacts. Finally, I realized that they were not necessary, and that would even create some problems while using the “Booster” function (the quicker the rotation the higher the counting rate)

  7. Zorrokuugen says:

    Okey, so I don’t need all those components. But about the pins, I see four wires coming out of the ENCODER. Can you tell me what is what?
    Thank you so much 😉

  8. Didier says:

    Please check ALPS data sheets such as this one http://www.alps.com/WebObjects/catalog.woa/E/HTML/Encoder/Incremental/EC11/EC11B15242AE.shtml
    You will see the wiring of A, B and C which are related to roatry encoder itself + D and E which are related to the push contact! That’s five!

  9. Zorrokuugen says:

    Thank you. I have a common ENCODER with 3 pins. I tried tu use your code but it doesn’t work. But I found this one, and work. So, is very difficult to modify your code for my common encoder?
    THANKS 😉

    /* Rotary encoder read example */
    #define ENC_A A0
    #define ENC_B A1
    #define ENC_PORT PINC

    void setup()
    {
    /* Setup encoder pins as inputs */
    pinMode(ENC_A, INPUT);
    digitalWrite(ENC_A, HIGH);
    pinMode(ENC_B, INPUT);
    digitalWrite(ENC_B, HIGH);
    Serial.begin (9600);
    Serial.println(“Start”);
    }

    void loop()
    {
    static uint8_t counter = 0; //this variable will be changed by encoder input
    int8_t tmpdata;
    /**/
    tmpdata = read_encoder();
    if( tmpdata ) {
    Serial.print(“Counter value: “);
    Serial.println(counter, DEC);
    counter += tmpdata;
    }
    }

    /* returns change in encoder state (-1,0,1) */
    int8_t read_encoder()
    {
    static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
    static uint8_t old_AB = 0;
    /**/
    old_AB <<= 2; //remember previous state
    old_AB |= ( ENC_PORT & 0x03 ); //add current state
    return ( enc_states[( old_AB & 0x0f )]);
    }

  10. Zorrokuugen says:

    Thank you. I have a common ENCODER with 3 pins. I tried tu use your code but it doesn’t work. But I found this one, and work. So, is very difficult to modify your code for my common encoder?
    THANKS 😉

    /* Rotary encoder read example */
    #define ENC_A A0
    #define ENC_B A1
    #define ENC_PORT PINC

    void setup()
    {
    /* Setup encoder pins as inputs */
    pinMode(ENC_A, INPUT);
    digitalWrite(ENC_A, HIGH);
    pinMode(ENC_B, INPUT);
    digitalWrite(ENC_B, HIGH);
    Serial.begin (9600);
    Serial.println(“Start”);
    }

    void loop()
    {
    static uint8_t counter = 0; //this variable will be changed by encoder input
    int8_t tmpdata;
    /**/
    tmpdata = read_encoder();
    if( tmpdata ) {
    Serial.print(“Counter value: “);
    Serial.println(counter, DEC);
    counter += tmpdata;
    }
    }

    /* returns change in encoder state (-1,0,1) */
    int8_t read_encoder()
    {
    static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
    static uint8_t old_AB = 0;
    /**/
    old_AB <<= 2; //remember previous state
    old_AB |= ( ENC_PORT & 0×03 ); //add current state
    return ( enc_states[( old_AB & 0x0f )]);
    }

  11. Didier says:

    I got many questions regarding encoders. I plan to answer them globaly in a specfic post “INCREMENTAL ROTARY ENCODERS (PART 4)”. Thank you for your patience.

  12. Didier says:

    Please check the newly released post on encoders @ http://didier.longueville.free.fr/arduinoos/?p=2631

  13. ab.eccolo says:

    Hi Didier, This is an amazing project, I like it very much.
    Now I’m going to study how it works 🙂 (I’d need a wave generator to test my DIY arduino ‘s guitar compressor and this method of making waves seems perfect).

  14. ab.eccolo says:

    Of course Didier 🙂 The arduino audio compressor project that I’ll try to made is a complete analogic effect in witch the compression is drived by an ATmega and h11f1 optocoupler on the amplifier stage of signal.
    If something’ll works I’ll be proud to link it on this space 🙂

    Here the first waves putting together your great code (I think to have understand the trick of DDS :-)):
    http://imageshack.us/g/259/sinec.jpg/
    They are a sin wave and a triangle wave with frequency of 1KHz

    One questions: other people of DIY forum of guitar effects ask me for the code: could i give it to them so other diyers could work on the project?

    Thanks a lot

    • Didier says:

      One question: other people of DIY forum of guitar effects ask me for the code: could i give it to them so other diyers could work on the project?
      One answer: Please, no. I’ll be glad to send them myself after they have completed the minimal requirement, as you did, as explained in here: http://didier.longueville.free.fr/arduinoos/?page_id=896

      Congratulations for having completed your DDS module! You may describe what you you want to do with your compressor; this may give me ideas for future 100% digital, Arduino based solutions 😉

  15. ab.eccolo says:

    Ok no code will be released by me 🙂 I only tell them the link of this article (if they not yet already found :-))
    For the compressor my idea is the seguent:
    The sound of the guitar is divided in two path:
    The first in input to arduino to the signal
    The second to an operational amplifier drived by opto coupler on the retroacion path
    By selector (or other way) it will be fixed the ratio, treshold and release params of compression.
    With the sound sampled it’ll be possible to drive the optocoupler used as variable resistorr on the amp stage.
    That’s all 🙂

Leave a Reply

You must be logged in to post a comment.