Pages: [1]   Go Down
Author Topic: Simple sketch for "analog" output from digital pins using PDM  (Read 795 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hiya all!  smiley-lol

I've written a simple function to output analog samples through the arduino uno's digital pins using pulse density modulation.

To use, just call it from the loop() section of your sketch. As it works fully in software, the more times you can call it per second, the better it will work!... heh, heh... hopefully your loop runs really fast smiley-roll-sweat  smiley-razz

So, without further ado:

Code:
/*
    playPdmSample8( pin, sample, sampleRate_ms )
   
    Plays back the appropriate sample on the indicated pin
    and returns the number of samples to increment for playback
    at the given sample rate.
   
    Maintains data for each pin -- you could use all fourteen at once!

    pin              - the digital pin to use as output
    sample           - the 8-bit sample to play
    sampleRate_ms    - number of samples to play per ***MILLISECOND***
*/

static unsigned long playPdmSample8(int pin, byte sample, unsigned long sampleRate_ms) {
    // Pulse density modulation data (pin-dependent)
    static byte            err[14]    = {};
    static byte            out[14]    = {};
   
    // Sample rate data
    static unsigned long   time[14]   = {micros()};   // Relative starting time ***IN MICROSECONDS***
    static unsigned long   sampleIncr = 0;            // Number of samples to be incremented to maintain sample rate
   
    sampleIncr = (sampleRate_ms * (micros() - time[pin])) >> 10; // The bit shift is a hackish divide-by-1000
   
    if(sampleIncr >= 1) {
        // Output a sample using pulse density modulation
       
        if(sample > err[pin]) {
            if(out[pin] == 0) {
                digitalWrite(pin, HIGH);
                out[pin] = 255;
            }
        } else {
            if(out[pin] == 255) {
                digitalWrite(pin, LOW);
                out[pin] = 0;
            }
        }
       
        err[pin] += (out[pin] - sample);
       
       
        // Reset the time
        time[pin] = micros();
    }
   
    return(sampleIncr);
}


Hopefully you find this marginally useful or at least marginally interesting!  smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just a demo  smiley :

Code:
const int    LED = 13;
byte         sinLUT[256];

void setup() {
    pinMode(LED, OUTPUT);
   
    for(long i = 0; i < sizeof(sinLUT); i++) {
        sinLUT[i] = (255.0 * (sin((6283.0 * i) / ((sizeof(sinLUT)-1) * 1000.0)) + 1.0)) / 2;
    }
}

void loop() {
    // output at 1 kHz sample rate
    playPdmSample8(LED, sinLUT[byte(millis() >> 2)], 1);
}

/* ... code for the playPdmSample8 function ... */

You should see your onboard LED fade at a 1 Hz sine wave smiley
Logged

Pages: [1]   Go Up
Jump to: