analogWrite (DAC) Examples?

I’m trying and (Google is) failing to find some good examples that use analogWrite() – true analog, not PWM. Does anyone have any ideas?

Reference and examples here:

pinMode(DAC1, OUTPUT);
analogWrite(DAC1, 1024);
// sets DAC pin to an output voltage of 1024/4095 * 3.3V = 0.825V.

1 Like

I’ve posted some PoC for playing some raw audio via analogWrite()

I’d seen that, but I was actually wondering about practical applications. So far I’ve seen music and sound, which are admittedly pretty good…

Thanks, ScruffR. I got it to play an 880 Hz sound, although I did need to reset the Photon before it would talk to the cloud again, I think because the system mode was manual.

I was trying to see what this – (from your post on Audio, SD cards and speakers?) was all about, but the link just brings me to my apps in the web ide.

Not quite sure what you mean by practical, but take a look at my APRS library. I use analogWrite to generate a Bell 202 modem (1200 baud) tone using AFSK to encode data for radio transmission. Typical use is for building a High Altitude Balloon tracker, or tracking anything.

Sorry for that, I have since removed the app but totally forgot about the link to it.
I’ll try to see if I can find it somewhere.

@mprogers, I’ve found my project. I filed it as Pull Request with @jvanier’s particle-speaker library

Since the PR hasn’t been merged yet, you’d need to manually import the adapted library files to have the example work.
If you need help with that, just tag me again.

@jvanier has just merged my PR and now you can use the sample directly from the library 1.1.0

You will need to provide your sounds in a sound.h header tho’, since USE THIS EXAMPLE does not copy over the provided sound.h.
Alternatively you can select sound.h and hit USE THIS EXAMPLE and just copy this minimal code to the end of it

#include "speaker.h"        

const int audioFrequency = 22050; // Hz

Speaker speaker((uint16_t*)sound, sizeof(sound) / sizeof(sound[0]));
void setup() {
1 Like

Thank you! I can see many places where this would be useful (especially once I get the amplifier they’d mentioned: right now I can barely hear it). I don’t see where it’s actually calling analogWrite(), though – what’s the mechanism that’s making it walk through the buffer? As usual, I know there’s something I don’t know, I just don’t know what it is that I don’t know :smile:

The speaker library is not using analogWrite() but the underlying (low level) function that’s also used by analogWrite() but in a more sophisitcated way.

In order to provide constant timing, the controller is setup to directly feed the contents of the sound buffer to the pin each time a hardware timer expires.
This is called DMA (direct memory access) and keeps the application thread free for other purposes without ever needing to care about analogWrite().

Speaker::setupHW() is the function that does all the preperation work

If you want to do it “manually” via analogWrite() you should be able to get some results with the code I linked to in my first reply. But since the writing is performed on the application thread, I chose to go for SYSTEM_MODE(MANUAL) to avoid the cloud tasks interfering with the timing.
But you can try AUTOMATIC mode, as the actual output happens in an interrupt routine (SparkIntervalTimer), so the impact should (hopefully) not be too big.

In regards of volume, what speaker are you using?
Since the GPIO can only drive up to 20mA@3.3V, you may get better results with a smaller speaker with higher impedance.
Although having a dedicated amplifier is never a bad idea.

Thanks for the explanation, this gives me a good starting point. As far as the speaker is concerned, it’s just a little piezo-speaker, the only one that I had close at hand.

I’m using a 32 Ohm 30mm speaker which is loud enough for normal hearing experience in an otherwise quietish environment.