//Ardunio *DUE*code for controlling EVAL-AD5780 //Created by Carlos Kometter /////////////CHANGELOG////////////////// //v3- 5/20/2016 If a DAC does not intilizies, normalmode() is recall until everysingle dac is initilized. //v4- 6/15/2016 Initializes dacs durin power up ///////////////////////////////// #include #include "SPI.h" // necessary library for SPI communication int ldac = 11; int led = 30; int data = 32; int dac[4] = {4, 10, 12, 52}; const int Noperations = 8; String operations[Noperations] = {"NOP", "INITIALIZE", "SET", "GET_DAC", "RAMP1", "RAMP2", "*IDN?", "RDY?"}; //NOP, *IDN?, *RDY? RAMP int initialized = 0; namespace std { void __throw_bad_alloc() { Serial.println("Unable to allocate memory"); } void __throw_length_error( char const*e ) { Serial.print("Length Error :"); Serial.println(e); } } void setup() { Serial.begin(115200); while (! Serial); pinMode(ldac,OUTPUT); digitalWrite(ldac,LOW); //Load DAC pin for DAC. Make it LOW if not in use. pinMode(led,OUTPUT); digitalWrite(led,HIGH); for(int i =0; i <= 3; i++) { pinMode(dac[i],OUTPUT); digitalWrite(dac[i],HIGH); } SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setClockDivider(84); SPI.setDataMode(SPI_MODE1); } int indexOfOperation(String operation) { for(int index = 0; index < Noperations; index++) { if(operations[index] == operation) { return index; } } return 0; } int threeByteToInt(byte DB1,byte DB2, byte DB3) // This gives a 16 bit integer (between +/- 2^16) { return ((int)(((((DB1&15)<<8)| DB2)<<8)|DB3)>>2); } void intToThreeBytes(int decimal, byte *DB1, byte *DB2, byte *DB3) { *DB1 = (byte)((decimal >> 14) | 16); *DB2 = (byte)((decimal >> 6) & 0xFF); *DB3 = (byte)((decimal & 0x3F) << 2); } float threeByteToVoltage(byte DB1, byte DB2, byte DB3) { int decimal; float voltage; decimal = threeByteToInt(DB1,DB2,DB3); if (decimal <= 131071) { voltage = decimal*10.0/131071; } else { voltage = -(262144-decimal)*10.0/131072; } return voltage; } void voltageToDecimal(float voltage, byte *DB1, byte *DB2, byte *DB3) { int decimal; if (voltage >= 0) { decimal = voltage*131071/10; } else { decimal = voltage*131072/10 + 262144; } intToThreeBytes(decimal, DB1, DB2, DB3); } float setValue(int channelDAC, float voltage) { byte b1; byte b2; byte b3; voltageToDecimal(voltage, &b1, &b2, &b3); digitalWrite(data, HIGH); digitalWrite(channelDAC,LOW); SPI.transfer(b1); // send command byte to DAC SPI.transfer(b2); // MS data bits, DAC2 SPI.transfer(b3); //LS 8 data bits, DAC2 digitalWrite(channelDAC,HIGH); digitalWrite(data, LOW); return threeByteToVoltage(b1,b2,b3); } float writeDAC(int dacChannel, float voltage) { switch( dacChannel )//uses the first byte choose what to do. 0x00: set DACS with asynchronous update { case 0: // Write DAC; return setValue(dac[0],voltage); break; case 1: return setValue(dac[1],voltage); break; case 2: return setValue(dac[2],voltage); break; case 3: return setValue(dac[3],voltage); break; default: break; } } void autoRamp1(std::vector DB) { float v1 = DB[2].toFloat(); float v2 = DB[3].toFloat(); int nSteps = DB[4].toInt(); int dacChannel=DB[1].toInt(); if (v1 < -10 || v1 > 10 || v2 < -10 || v2 > 10) { Serial.println("RAMP_OVERRANGE"); return; } Serial.println("RAMPING"); for (int j=0; j DB) { float vi1 = DB[3].toFloat(); float vi2 = DB[4].toFloat(); float vf1 = DB[5].toFloat(); float vf2 = DB[6].toFloat(); int nSteps = DB[7].toInt(); byte b1; byte b2; int dacChannel1=DB[1].toInt(); int dacChannel2=DB[2].toInt(); if (vi1 < -10 || vi1 > 10 || vi2 < -10 || vi2 > 10 || vf1 < -10 || vf1 > 10 || vf2 < -10 || vf2 > 10) { Serial.println("RAMP_OVERRANGE"); return; } Serial.println("RAMPING"); for (int j=0; j=5) { Serial.print("ERROR INITIALIZING DAC"); Serial.println(i); } else if (o!=2) { i=i-1; attemps++; } } } void ID() { Serial.println("DCBOX_QUAD_AD5780(DOGWOOD)"); } void RDY() { Serial.println("READY"); } void debug() { digitalWrite(led,HIGH); delay(3000); digitalWrite(led,LOW); delay(3000); } void router(std::vector DB) { int operation = indexOfOperation(DB[0]); switch( operation )//uses the first byte choose what to do. 0x00: set DACS with asynchronous update { case 0: Serial.println("NOP"); break; case 1: // Write DAC; normalMode(); Serial.println("INITIALIZATION COMPLETE"); break; case 2: if(DB[2].toFloat() < -10 || DB[2].toFloat() > 10) { Serial.println("VOLTAGE_OVERRANGE"); break; } float v; v = writeDAC(DB[1].toInt(),DB[2].toFloat()); Serial.print("DAC "); Serial.print(DB[1]); Serial.print(" UPDATED TO "); Serial.print(v,5); Serial.println("V"); break; case 3: readDAC(dac[DB[1].toInt()]); break; case 4: autoRamp1(DB); Serial.println("RAMP_FINISHED"); break; case 5: autoRamp2(DB); Serial.println("RAMP_FINISHED"); break; case 6: ID(); break; case 7: RDY(); break; default: break; } } void loop() { Serial.flush(); String inByte = ""; std::vector comm; if(initialized == 0) { normalMode(); initialized = 1; Serial.println("INITIALIZATION COMPLETE"); } if(Serial.available()) { char received; while (received != '\r') { if(Serial.available()) { received = Serial.read(); if (received == '\n' || received == ' ') {} else if (received == ',' || received == '\r') { comm.push_back(inByte); inByte = ""; } else { inByte += received; } } } router(comm); } }