• 0
Sign in to follow this  
contraption

problems with PMOD DA2 on Arduino Leonardo

Question

Hi, I've been trying to get the PMOD DA2 (just Channel 1 for now) working on a fleet of Arduino Leonardos via the ICSP header. I'm getting bizarre (jumpy, non-monotonic) voltages out of it and I'm stumped. Things get particularly squirrely around outputting 2048 counts (half scale) - I do believe that my upper/lower byte math is correct, so i think the issue is with the SPI writing/sequencing.

Has anyone had any luck putting a DA2 on a Leonardo via ICSP? 

I've attached my (not working) test sketch. Any idea what's wrong? I poked around the web and this forum, but can't seem to find any working examples or advice.

This is my first attempt at using the ICSP port, so it's possible that I've not done it properly.

For a moment I did think that specifically defining MSBFIRST would fix it, but it didn't. I'm also not 100% sure about the clock phase and polarity settings (SPI_MODE3) - what you see in the code is from an example that I found (here: https://www.hackster.io/56141/using-the-pmod-da2-with-arduino-uno-e47768 - but that doesn't seem to work for me either).

/************************************************************************
* FILENAME: PMOD_DA2

* Leonardo Pins:

* Chip Select (CS): Leonardo DIO Pin 10 (to DA2 pin 1)
* Serial Clock (SCK): Leonardo ICSP Pin 3 (to DA2 pin 4) 
* MOSI (Data): Leonardo ICSP Pin4 (to DA2 pin 2)

************************************************************************/

Ideas or suggestions?

Where'd I go wrong?

Bruce

PMOD_DA2.ino

EDIT:

I've attached a scope trace of the output when I use the following code (snippet) - ramping to 4000 counts in 250 count increments:

// OUTPUT & RAMP VARIABLES
const int           AnalogMaxValue = 4000;  // hardcoded max DAC value, proportional to FLOW RATE (motor velocity), range is 0 to 4095
const int           AnalogStepSize = 250;
const int            StepDelayTime = 10;    // [milliseconds] delay between analog updates during ramp-up, milliseconds
const int          SPI_write_delay = 5 ;    // [milliseconds] (delay after writing data, before asserting ChipSelect)

int                     upper_byte = 0x00;  // upper byte of speed command, to be sent via SPI port to PMOD_DA2
int                     lower_byte = 0x00;  // lower byte of speed command, to be sent via SPI port to PMOD_DA2
int                              i = 0;     // test variable

void setup()
{
 // set up pin definitions
 pinMode(PMOD_CS_Pin, OUTPUT);             // PMOD chip select (for Channel #1, Channel #2 is not being used)

 // set up SPI port
 SPI.begin(); // initialization of SPI port
 SPI.setDataMode(SPI_MODE3); // configuration of SPI communication in mode 3
 SPI.setClockDivider(SPI_CLOCK_DIV16); // configuration of clock at 1MHz
 SPI.setBitOrder(MSBFIRST);
 Write_To_DAC(0);  // write zero to the DAC via SPI to initialize
}

void loop() { 
  for(i=0; i<=AnalogMaxValue; i=i+AnalogStepSize){
    Write_To_DAC( i );  // write the Analog value to the DAC via SPI
    delay(StepDelayTime);
  }
}

PMOD_DA2 output.png

Edited by contraption
more detail, added scope pic

Share this post


Link to post
Share on other sites

2 answers to this question

Recommended Posts

  • 0

Hi @contraption,

You'll actually be in SPI Mode 1 (clock idles low and the data is sampled on the falling edge of the clock) since that's what the IC for the DA2 needs. This is what I used on the ICSP header for an Arduino Uno (I don't have a Leonardo available).
 

Spoiler



#include <SPI.h>

int maxValue = 0x0FA0; //4000 in decimal
int stepSize = 0xFA; //250 in decimal
int upperByte = 0x00;
int lowerByte = 0x00;
uint16_t totalByte = 0x0000; //16 bit hex storage
int chipSelectPin = 10;


void setup() {
  Serial.begin(9600);
  Serial.println("testing");
  pinMode(chipSelectPin, OUTPUT);
  digitalWrite(chipSelectPin, HIGH);
  SPI.begin();
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE1));
  //send all 0's to get set normal operation mode and an output value of 0
  totalByte = 0x0000;
  Serial.print("totalByte");Serial.println(totalByte);
  upperByte = totalByte >> 8;
  lowerByte = uint8_t(totalByte);
  Serial.print("upperByte: ");Serial.println(upperByte);
  Serial.print("lowerByte: ");Serial.println(lowerByte);
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(upperByte);
  SPI.transfer(lowerByte);
  digitalWrite(chipSelectPin, HIGH);
  
}

void loop() {
  delay(1);
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(upperByte);
  SPI.transfer(lowerByte);
  digitalWrite(chipSelectPin, HIGH);
  delay(1);
  Serial.print("upperByte before: ");Serial.println(upperByte, HEX);
  Serial.print("lowerByte before: ");Serial.println(lowerByte, HEX);
  Serial.print("totalByte before: ");Serial.println(totalByte, HEX);
  totalByte += 250;
  if(totalByte > 0x0FA0){
    totalByte = 0x0000;
  }
  upperByte = totalByte >> 8;
  lowerByte = uint8_t(totalByte);
  Serial.print("upperByte after: ");Serial.println(upperByte, HEX);
  Serial.print("lowerByte after: ");Serial.println(lowerByte, HEX);
  Serial.print("totalByte after: ");Serial.println(totalByte, HEX);
  Serial.println('\n');
  
}


 

Let me know if you have any questions.

Thanks,
JColvin

Share this post


Link to post
Share on other sites
  • 0
On 2/13/2019 at 12:58 PM, JColvin said:

Hi @contraption,

You'll actually be in SPI Mode 1 (clock idles low and the data is sampled on the falling edge of the clock) since that's what the IC for the DA2 needs. This is what I used on the ICSP header for an Arduino Uno (I don't have a Leonardo available).
 

  Hide contents

 



#include <SPI.h>

int maxValue = 0x0FA0; //4000 in decimal
int stepSize = 0xFA; //250 in decimal
int upperByte = 0x00;
int lowerByte = 0x00;
uint16_t totalByte = 0x0000; //16 bit hex storage
int chipSelectPin = 10;


void setup() {
  Serial.begin(9600);
  Serial.println("testing");
  pinMode(chipSelectPin, OUTPUT);
  digitalWrite(chipSelectPin, HIGH);
  SPI.begin();
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE1));
  //send all 0's to get set normal operation mode and an output value of 0
  totalByte = 0x0000;
  Serial.print("totalByte");Serial.println(totalByte);
  upperByte = totalByte >> 8;
  lowerByte = uint8_t(totalByte);
  Serial.print("upperByte: ");Serial.println(upperByte);
  Serial.print("lowerByte: ");Serial.println(lowerByte);
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(upperByte);
  SPI.transfer(lowerByte);
  digitalWrite(chipSelectPin, HIGH);
  
}

void loop() {
  delay(1);
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(upperByte);
  SPI.transfer(lowerByte);
  digitalWrite(chipSelectPin, HIGH);
  delay(1);
  Serial.print("upperByte before: ");Serial.println(upperByte, HEX);
  Serial.print("lowerByte before: ");Serial.println(lowerByte, HEX);
  Serial.print("totalByte before: ");Serial.println(totalByte, HEX);
  totalByte += 250;
  if(totalByte > 0x0FA0){
    totalByte = 0x0000;
  }
  upperByte = totalByte >> 8;
  lowerByte = uint8_t(totalByte);
  Serial.print("upperByte after: ");Serial.println(upperByte, HEX);
  Serial.print("lowerByte after: ");Serial.println(lowerByte, HEX);
  Serial.print("totalByte after: ");Serial.println(totalByte, HEX);
  Serial.println('\n');
  
}

 

 

 

 

Let me know if you have any questions.

Thanks,
JColvin

Awesome, MODE1 worked! Thanks. 

That'll teach me that code I find on the internet isn't always correct! (example used MODE3)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this