Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Using a DAC(mcp4821) with teensy that I have tested with an arduino uno.

Hybrid View

  1. #1
    Junior Member
    Join Date
    Oct 2020
    Posts
    14

    Using a DAC(mcp4821) with teensy that I have tested with an arduino uno.

    I am trying to get a dac working with the teensy 4.0 I have. I was successful getting it to work on an arduino uno, but it does not work on the teensy. I noticed in the documentation for spi that SPI.setClockDivider is outdated, so I tried using a bit of their SPI settings code, that in this version is commented out. I was using this tutorial http://www.kerrywong.com/2012/07/25/...p4821-mcp4822/ and everything is wired to the arduino like in that photo, except for the capacitor. When I change out the teensy I wire the pins to the same pin numbers as on the arduino. I was worried it might be the 3.3v instead of the 5v on the arduino but it works on 3.3 volts with the arduino. I'm a little out of my depth with digital communication stuff. Any help you could provide would be very helpful.

    Here is the code I was working with.

    #include <SPI.h>

    const int PIN_CS = 10;
    const int GAIN_1 = 0x1;
    const int GAIN_2 = 0x0;

    //SPISettings settingsA(2000000, MSBFIRST, SPI_MODE1);


    void setup()
    {
    pinMode(PIN_CS, OUTPUT);
    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV2);
    }

    //assuming single channel, gain=2
    void setOutput(unsigned int val)
    {
    byte lowByte = val & 0xff;
    byte highByte = ((val >> 8) & 0xff) | 0x10;

    PORTB &= 0xfb;
    SPI.transfer(highByte);
    SPI.transfer(lowByte);
    PORTB |= 0x4;
    }

    void setOutput(byte channel, byte gain, byte shutdown, unsigned int val)
    {
    byte lowByte = val & 0xff;
    byte highByte = ((val >> 8) & 0xff) | channel << 7 | gain << 5 | shutdown << 4;

    PORTB &= 0xfb;
    //SPI.beginTransaction(settingsA);
    SPI.transfer(highByte);
    SPI.transfer(lowByte);
    PORTB |= 0x4;
    }

    void loop()
    {
    //high-res triangular wave
    /*for (int i=0; i < 4096; i+=32)
    {
    //setOutput(0, GAIN_2, 1, i);
    setOutput(i);
    }*/
    setOutput(2000);
    }

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,080
    As a quick test, I ran this here on a Teensy 4.0. I don't have that particular DAC, so I just viewed the waveforms with my oscilloscope.

    Click image for larger version. 

Name:	file.png 
Views:	14 
Size:	58.3 KB 
ID:	22063

    Amazingly it seems to be working, except that SPI_CLOCK_DIV2 is giving 12 MHz SPI clock speed.

    If you change to SPI_CLOCK_DIV8, you'll get 2 MHz SPI clock (yes, I verified with my scope).

    You might also want to add a delay at the end of loop(). Teensy 4.0 is much faster than those old AVR chips. Without a delay the CS pin stays high for only about 60 ns.

  3. #3
    Junior Member
    Join Date
    Oct 2020
    Posts
    14
    That makes a lot of sense. I have tried your suggestion and am still not having any luck. here is my modified code, which still works for arduino uno, but not for teensy. Thanks a ton for the help. Also if I am going about this in an outdated way, or if you have a suggestion for a better solution I am all ears.

    #include <SPI.h>

    const int PIN_CS = 10;
    const int GAIN_1 = 0x1;
    const int GAIN_2 = 0x0;

    //SPISettings settingsA(2000000, MSBFIRST, SPI_MODE1);


    void setup()
    {
    pinMode(PIN_CS, OUTPUT);
    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV8);
    }

    //assuming single channel, gain=2
    void setOutput(unsigned int val)
    {
    byte lowByte = val & 0xff;
    byte highByte = ((val >> 8) & 0xff) | 0x10;

    PORTB &= 0xfb;
    SPI.transfer(highByte);
    SPI.transfer(lowByte);
    PORTB |= 0x4;
    }

    void setOutput(byte channel, byte gain, byte shutdown, unsigned int val)
    {
    byte lowByte = val & 0xff;
    byte highByte = ((val >> 8) & 0xff) | channel << 7 | gain << 5 | shutdown << 4;

    PORTB &= 0xfb;
    //SPI.beginTransaction(settingsA);
    SPI.transfer(highByte);
    SPI.transfer(lowByte);
    PORTB |= 0x4;
    }

    void loop()
    {
    //high-res triangular wave
    /*for (int i=0; i < 4096; i+=32)
    {
    //setOutput(0, GAIN_2, 1, i);
    setOutput(i);
    }*/
    setOutput(1000);
    delay(10);
    }

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,989
    Might help to see pictures of your setup.

    Maybe a wire missing or, soldering issues or...

    Also if it were me I would get away from using PORTB stuff here and instead just do digitalWrite(10, HIGH) or digitalWriteFast(10, HIGH)... and LOW...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •