The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
I'm having a bear of a time trying to work with the MCP4922 12 bit DAC (data sheet) but I have no idea if the problem is how I wired it, or the SPI implementation or something else.
I don't have a logic analyzer yet, but I do have on order the one Chris recommended in a different thread.
1. Does anyone have an example of using the MCP4921 or MCP4922 DAC with the netduino?
2. If not, any suggestions on how to test to see where the fault is?
I've been coding for decades, but electronics is still pretty new to me. The test equipment I have right now is a BK Precision 2709B meter and a Rigol DS1052E scope. I don't see anything on the scope, even in the clock output (I thought I'd see something there at a minimum).
Code:
namespace NetduinoDacTest
{
enum Dac
{
DacA = 0,
DacB = 1
}
public class Program
{
public static void Main()
{
OutputPort ldacPin = new OutputPort(Pins.GPIO_PIN_D9, true);
OutputPort shutdownPin = new OutputPort(Pins.GPIO_PIN_D8, true);
SPI.Configuration config = new SPI.Configuration(
Pins.GPIO_PIN_D10, // chip select is D10
false, // active is low, according to DAC spec
0, // setup time
0, // hold time
false, // clock idle state is low
true, // data is sampled on rising clock edge
100, // clock rate in KHZ
SPI.SPI_module.SPI1);
SPI dacSpi = new SPI(config);
// output samples
ushort sample;
ushort message;
Random rnd = new Random();
while (true)
{
sample = (ushort)rnd.Next(4095); // random noise for now
message = BuildSingleSpiMessage(sample, Dac.DacA);
// need to set LDAC to high in case I wanted to output to both DACs at once (stereo)
ldacPin.Write(true);
dacSpi.Write(new ushort[] { message });
// need to set LDAC to low
ldacPin.Write(false);
}
}
// assumes that the sample value provided is only 12 bits (0-4095)
private static ushort BuildSingleSpiMessage(ushort sample, Dac selectedDac)
{
// bits 0-11 are sample
ushort message = sample;
// bit 12: output power down control. Set to 1 to allow output
message = (ushort)(message | 0x1000);
// bit 13: output gain. We'll allow a set to 1 to have normal 1:1 output
message = (ushort)(message | 0x2000);
// bit 14: Vref Buffer. We'll assume unbuffered, so zero
message = (ushort)(message & 0x4000);
// bit 15: dac A or Dac B. Zero is A, 1 is B.
if (selectedDac == Dac.DacA)
message = (ushort)(message & 0x8000);
else
message = (ushort)(message | 0x8000);
return message;
}
}
}
DAC Pins:
1. Vdd -> Netduino 3.3v, with a .1uf cap as recommended
2. NC (empty)
3. CS -> Netduino D10
4. SCK -> Netduino D13
5. SDI -> Netduino D12
6. NC (empty)
7. NC (empty)
8. LDAC -> Netduino D9 (for synchronization of the two DACs when I end up finally using
9. SHDN -> Netduino D8 (not sure if I need this wiring and logic)
10. VOUTB -> empty for now
11. VREFB -> empty for now
12. AVss -> Netduino Ground
13 VREFA -> Netduino 3.3v
14. VOUTA -> Scope
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
At first glance, SDI should be connected to Netduino D11 (SPI MOSI), not D12. Also, if you want to send 12 bit values to the DAC, you should take a a look at the ExtendedSPIConfiguration class: http://forums.netdui...ch__1#entry6888
Another thought: the clock rate can be much higher than 100 kHz according to the datasheet (up to 20 Mhz).
At first glance, SDI should be connected to Netduino D11 (SPI MOSI), not D12. Also, if you want to send 12 bit values to the DAC, you should take a a look at the ExtendedSPIConfiguration class: http://forums.netdui...ch__1#entry6888
Another thought: the clock rate can be much higher than 100 kHz according to the datasheet (up to 20 Mhz).
Cheers,
-Fabien.
Thanks, especially for the MOSI/MISO Pin. I was reading the last letter and thinking that was the I/O. I just looked up the definitions of the terms
Additionl info:
The DAC is 12 bits, but the messages are 16 bits (4 config bits plus 12 data bits), so I should be good with the default SPI class.
I just tried it at 100khz, 1mhz, 5mhz, 10mhz and 20mhz (assuming the Netduino actually sends clocks that high). FWIW, I don't even see a clock signal coming from the netduino when I hook the scope up to D13. Maybe I'm reading it incorrectly or something. I'm pretty new to the hardware side of things.
I tried this both on my regular netduino (now flashed with latest firmware) and my netduino plus with the latest 4.1.1.0 alpha.
Am I missing something really dumb? Does SPI need to be turned "on" or something?
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
Hi Pete,
Could you please try this with the v4.1.0.5 firmware? It may be a glitch in the alpha 5 firmware (which we just fixed and will be posting soon).
Chris
Could you please try this with the v4.1.0.5 firmware? It may be a glitch in the alpha 5 firmware (which we just fixed and will be posting soon).
Chris
My regular netduino had 4.1.0.5, but I just flashed the Plus I'm working with now to be sure. This is what I now have on the board:
SolutionReleaseInfo.solutionVersion: 4.1.0.5
SolutionReleaseInfo.solutionVendorInfo: Netduino Plus by Secret Labs LLC
SoftwareVersion.BuildDate: Nov 7 2010
SoftwareVersion.CompilerVersion: 400771
No dice on getting SPI and the DAC to work.
When I hook the scope up to the SCLK on the netduino, I expect to see a pulse, but I get nothing. (Tried a different wire to, just to be sure <g>)
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
Pete,
How are you triggering your scope? Are you triggering on the first level change? The clock will only run while data is being transmitted...
You may want to trigger on the chip select line, if your oscilloscope will capture a long enough signal.
Chris
Ok, for a sanity check, I just ported my code to the FEZ Panda (I love .NET!), and got the same non-results. That likely means one of the following:
1. Wiring is wrong (doesn't explain clock issue, though)
2. My program logic is wrong
3. My testing procedure is wrong and I'm looking at the wrong thing or at it the wrong way
So, my first question: With the above code, if I hook a scope up to SCLK on the netduino, should I see a pulse at the specified clock frequency? What is the voltage range of the clock pulse? Is it 0.0 to 3.3 or 0.0 to 2.0 or something else?
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
So, my first question: With the above code, if I hook a scope up to SCLK on the netduino, should I see a pulse at the specified clock frequency? What is the voltage range of the clock pulse? Is it 0.0 to 3.3 or 0.0 to 2.0 or something else?
Hi Pete,
Yes, but only while data is being sent. The CLK signal will be 0 to 3.3V.
Looking at datasheets it seems that SPI communication protocol should be the same of DAC you're using.
Our DAC driver is simply:
public class MCP4822_DAC
{
// SPI bus reference
SPI _spi = null;
// ctor requires a pre-initialized SPI bus
public MCP4822_DAC(SPI spi)
{
_spi = spi;
}
public void SetOut(OutputChannelEnum Channel, ushort Value)
{
Debug.Print("DAC SetOut: " + Channel + "," + Value);
if (Value > 4095) throw new ArgumentException("Out of range (0-4095)", "Value");
ushort[] tx = new ushort[1] {Value};
if (Channel == OutputChannelEnum.ChannelB) tx[0] |= (1 << 15);
tx[0] |= (1 << 12);
_spi.Write(tx);
}
}
public enum OutputChannelEnum
{
ChannelA,
ChannelB
}
We initialize the driver as following:
SPI.Configuration spiConfig = new SPI.Configuration(
(Cpu.Pin)FEZ_Pin.Digital.UEXT6, // CS Pin
false, // CS active when LOW
0, // CS setup time
0, // CS hold time
false, // SCK idle when LOW
true, // MISO/MOSI sampling on rising edge of SCK
250, // 250 KHz
SPI.SPI_module.SPI2);
// SPI bus
SPI spi = new SPI(spiConfig);
MCP4822_DAC dac = new MCP4822_DAC(spi);
@Innovactive
Thanks. The code is similar. I removed some of the extra statements in mine to make it more like what you have.
Can you share your pinout?
(awesome car setup, btw)
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
How are you triggering your scope? Are you triggering on the first level change? The clock will only run while data is being transmitted...
You may want to trigger on the chip select line, if your oscilloscope will capture a long enough signal.
Chris
Thanks Christ.
I hooked the scope up to CS and got nothing. Maybe I'm just using it wrong. #noob
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
Arrrgghh! OMG I'm an idiot.
I'm almost too ashamed to post what I was doing, but I will anyway.
I was connecting the wrong test lead to the signal.
This is what happens when you let a noob play with cool toys
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
BTW, I still don't actually have any *output*, but at least I can see the clock and CS signals
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
My waveform isn't perfect (need to figure out what's up with the bottoming out), but it's definitely coming from code and running through the DAC
I had some code issues as well as just the dumb testing issue I mentioned above. Thanks everyone for the help
Pete
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.
How would this work if you had two DACs? The SPI config only takes one cs pin. I tried creating another SPI object with a different cs pin but that errored.
Thanks
Ron
How would this work if you had two DACs? The SPI config only takes one cs pin. I tried creating another SPI object with a different cs pin but that errored.
Thanks
Ron
Hi Ron,
You might need to dispose of the first SPI object before creating the second one. I know...lots of GC action going on there.
How would this work if you had two DACs? The SPI config only takes one cs pin. I tried creating another SPI object with a different cs pin but that errored.
You can use a general I/O pin (i.e. OutputPort) for custom-controlled CS pin. It is not necessary to use ChipSelect_Port in SPI.Configuration at all (pass Pin.GPIO_NONE).
The Neduino microcontroller directly supports up to 15 SPI peripheral devices (with decoding on four chip select lines, up to 4 without decoding), but unfortunately this feature is not accessible neither in the current .NET Micro Framework firmware (not implemented) nor on Netduino boards (pins not broken out). The SPI class represents the hardware interface module, so you can instantiate only one object (it is not per slave device). The microcontroller has two SPI interfaces, the second one is used internally for SD card on Netduino Plus.
The managed code route won't work for sound synthesis. Once Chris has the source up on codeplex and I can do a custom firmware build, I'll try porting that part to native code. Here's as far as I got in managed code:
Pete Brown - http://10rem.net (NETMF, C++, Windows, C64, and general geekery) Twitter: @pete_brown I work for Microsoft. Opinions expressed here are my own and do not necessarily reflect those of my employer,our partners or customers.