//Bench Supply Code //Copyright Nathan Monroe //June 2015 #include #include #include LiquidCrystal lcd(A0, A1, 4, 3, 2, A3); int dac_on=1; //DAC feature is enabled. #define adc_add 0b1001001 //I2C addresses #define dac1_add 0b0001110 #define dac2_add 0b0001101 #define ON 1 #define OFF 0 #define LCD_BL_PIN A2 #define fault_pin 9 #define V10 16444 //count for 10V in ADC #define V1 1645 //count for 1V in ADC #define V100m 164 //count for 100mv in ADC #define V10m 17 //count for 10mv in ADC #define V1m 1 //count for 1mV in ADC - .608mV per count. #define I1 10923 //count for 1A in ADC #define I100m 1092 //count for 100mA in ADC #define I10m 109 //count for 10mA in ADC #define I1m 11 //count for 1mA in ADC - .09mA per count. #define overcurrent_threshold 31200 //1.95V = 2.85A //#define overcurrent_threshold 32767 //disable feature until crowbar is fixed. float onecountV = 0.000608; //A for one bit of voltage UPDATE THIS float onecountI = 0.000091; //A for one bit of current UPDATE THIS //float I1offset = 0.001; //float I2offset = 0.004; float I1offset = 0.000; float I2offset = 0.000; char outstr[7]; unsigned int a = 0; unsigned int b = 0; String Vtens = "0"; String Vones = "0"; String Vhundms = "0"; String Vtenms = "0"; String Vms = "0"; int Vremainder = 0; String Iones = "0"; String Ihundms = "0"; String Itenms = "0"; String Ims = "0"; int Iremainder = 0; int active_channel = 0; //active channel being used by ADC unsigned int output[4] = {0,0,0,0}; //Vout1, Iout1, Iout2, Vout2 String content = ""; //for dac char character; unsigned int dac_value = 0; void init_adc(){ Wire.beginTransmission(adc_add); Wire.write(0x01); //Config register Wire.write(0b01000101); //config high byte. Input = Ain0. FS=2.048V. Single shot mode. Wire.write(0b11101100); //config low byte. 860MSPS. Traditional comparator. Fault active high. Latching. One conversion to assert comparator. Wire.endTransmission(); Wire.beginTransmission(adc_add); Wire.write(0x02); //low threshold register Wire.write(0x00); //low threshold high byte Wire.write(0x00); //low threshold low byte Wire.endTransmission(); Wire.beginTransmission(adc_add); Wire.write(0x03); //high threshold register Wire.write(0x79); //high threshold high byte- 31200 counts = 1.95V = 2.85A Wire.write(0xE0); //high threshold low byte Wire.endTransmission(); } void set_adc_channel(int channel) { Wire.beginTransmission(adc_add); Wire.write(0x01); //Config register if (channel == 0) { Wire.write(0b11000101); //V_out1. Start conversion. } if (channel == 1) { Wire.write(0b11010101); //I_out1. Start conversion. } if (channel == 2) { Wire.write(0b11100101); //I_out2. Start conversion. } if (channel == 3) { Wire.write(0b11110101); //V_out2. Start conversion. } Wire.write(0b11101100); //config low byte. 860MSPS. Traditional comparator. Fault active high. Latching. One conversion to assert comparator. Wire.endTransmission(); } unsigned int adc_isready(){ Wire.beginTransmission(adc_add); Wire.write(0x01); //Config register Wire.endTransmission(); Wire.requestFrom(adc_add, 2); a = Wire.read(); b = Wire.read(); if (a >128) return 1; //highest bit of config register is conversion status. else return 0; } unsigned int adc_read() { Wire.beginTransmission(adc_add); Wire.write(0x00); //Conversion register Wire.endTransmission(); Wire.requestFrom(adc_add, 2); a = Wire.read(); return (a<<8) | Wire.read(); } String floatIcount2str(int i, int chan) { if (chan==1) dtostrf((i*onecountI-I1offset), 6, 3, outstr); else dtostrf((i*onecountI-I2offset), 6, 3, outstr); return outstr; } String floatVcount2str(int v) { dtostrf(v*onecountV, 6, 3, outstr); return outstr; } /* String Vcount2str(int v){ Vremainder = v; Vtens = "0"; Vones = "0"; Vhundms = "0"; Vtenms = "0"; Vms = "0"; if ( Vremainder > V10) { Vtens = "1"; Vremainder = Vremainder - V10; } else Vtens = " "; Vones = String(Vremainder / V1); Vremainder = Vremainder%V1; Vhundms = String(Vremainder / V100m); Vremainder = Vremainder%V100m; Vtenms = String(Vremainder / V10m); Vremainder = Vremainder%V10m; Vms = String((Vremainder*6) / 10); if (Vtens.equals("1")) return Vtens + Vones + "." + Vhundms + Vtenms + Vms; else return Vones + "." + Vhundms + Vtenms + Vms; } String Icount2str(int i){ Iremainder = i; Iones = "0"; Ihundms = "0"; Itenms = "0"; Ims = "0"; Iones = String(Iremainder / I1); Iremainder = Iremainder%I1; Ihundms = String(Iremainder / I100m); Iremainder = Iremainder%I100m; Itenms = String(Iremainder / I10m); Iremainder = Iremainder%I10m; Ims = String((Iremainder*6) / 10); return Iones + "." + Ihundms + Itenms + Ims; } */ void update_display(){ lcd.setCursor(8,0); //lcd.clear(); //clears screen, sets cursor to 0,0 //lcd.print("Chan 1:"); lcd.print(floatVcount2str(output[0])); //convert count to volts, display on screen //lcd.print("Volts"); lcd.setCursor(8,1); //lcd.print("Chan 1:"); lcd.print(floatIcount2str(output[1],1)); //convert count to amps, display on screen //lcd.print("Amps"); lcd.setCursor(8,2); //lcd.print("Chan 2:"); lcd.print(floatVcount2str(output[3])); //convert count to volts, display on screen //lcd.print("Volts"); lcd.setCursor(8,3); //lcd.print("Chan 2:"); lcd.print(floatIcount2str(output[2],2)); //convert count to amps, display on screen //lcd.print("Amps"); } void init_display() { lcd.clear(); //clears screen, sets cursor to 0,0 lcd.print("Chan 1:"); lcd.print(" "); //8 spaces: _XX.XXX_ lcd.print("Volts"); lcd.setCursor(0,1); lcd.print(" "); lcd.print(" "); //8 spaces: _XX.XXX_ lcd.print("Amps"); lcd.setCursor(0,2); lcd.print("Chan 2:"); lcd.print(" "); //8 spaces: _XX.XXX_ lcd.print("Volts"); lcd.setCursor(0,3); lcd.print(" "); lcd.print(" "); //8 spaces: _XX.XXX_ lcd.print("Amps"); } void set_dac(int dac, unsigned int set) { //12 bits, 0-5V. Gain of 4.25. Each LSB is 5.188mV. if (dac==1) Wire.beginTransmission(dac1_add); if (dac==2) Wire.beginTransmission(dac2_add); if ((dac==1) | (dac==2)) { byte out = set >>8; Wire.write(out); //set high byte of DAC. PD bits 00 for normal operation. out = set & 0xFF; Wire.write(out); //use only lowest 8 bits of set variable. Wire.endTransmission(); } } void process_dac(){ content=""; //format is CVVVV- C is channel (1 or 2), VVVV is VV.VV in volts, implied decimal. while (Serial.available() > 0) { character = Serial.read(); content.concat(character); } dac_value=0; if(content[1] == 49) dac_value = dac_value+1927; //tens place dac_value = dac_value + ((content[2]-48)*193); //ones place dac_value = dac_value + (((content[3]-48)*10)+(content[4])/5); //decimal part set_dac(content[0]-48, dac_value); } void setup() { Serial.begin(9600); Wire.begin(); init_adc(); pinMode(A0, OUTPUT); //pins normally used as ADCs, reconfigure as digital outputs. pinMode(A1, OUTPUT); pinMode(A2, OUTPUT); pinMode(A3, OUTPUT); pinMode(fault_pin, INPUT); lcd.begin(20,4); init_display(); digitalWrite(LCD_BL_PIN, 1); } void loop(){ /* active_channel=1; set_adc_channel(active_channel); if(adc_isready()) { lcd.clear(); lcd.print(String(adc_read(), DEC)); set_adc_channel(active_channel); //update_display(); delay(100); } */ // if(adc_isready()) { output[active_channel] = adc_read(); active_channel = (active_channel+1)%4; set_adc_channel(active_channel); if(active_channel==0) update_display(); delay(100); // } if(digitalRead(fault_pin)) { lcd.clear(); lcd.print("Overcurrent"); lcd.setCursor(0,1); if (output[1] > output[2]) lcd.print("Channel 1"); else lcd.print("Channel 2"); lcd.setCursor(0,3); lcd.print("... you suck."); //while(true){ // digitalWrite(LCD_BL_PIN, ~digitalRead(LCD_BL_PIN)); // delay(1000); //} } if(dac_on) process_dac(); /* if (output[1] > overcurrent_threshold){ lcd.clear(); lcd.print("Overcurrent"); lcd.setCursor(0,1); lcd.print("Channel 1"); lcd.setCursor(0,3); lcd.print("You suck"); while(true){ digitalWrite(LCD_BL_PIN, ~digitalRead(LCD_BL_PIN)); delay(1000); } } if (output[2] > overcurrent_threshold){ lcd.clear(); lcd.print("Overcurrent"); lcd.setCursor(0,1); lcd.print("Channel 2"); lcd.setCursor(0,3); lcd.print("You suck"); while(true){ digitalWrite(LCD_BL_PIN, ~digitalRead(LCD_BL_PIN)); delay(1000); } } */ }