/* ////////////////////////////////////////////////////////////////// ARDUINO/Genuino Ptoject "Tanachaimod", a Bipolar Transistor Curve Tracer https://www.changpuak.ch/electronics/Arduino-Tanachaimod.php Software Version 1.9 16.07.2023 by ALEXANDER SSE FRANK The Serial Parser is from here : Easy_Diseqc V1.2, Monstein ETH Zurich, 20.06.2018 ////////////////////////////////////////////////////////////////// */ char tempbuf[80]; // keeps the command temporary until CRLF String buffer; bool debug = false ; float GATE_VOLT = 0.0 ; // Volts float BASE_CURR = 0.0 ; // mA float DRAIN_VOLT = 0.0 ; // Volts float SOURCE_VOLT = 0.0 ; // Volts float TEMP = 0.0 ; // Degrees Celsius bool TEST_BASE = false ; bool TEST_GATE = false ; bool TEST_DRAIN = false ; const float MAX_Base = +5.0 ; const float MIN_Base = -5.0 ; const float MAX_Gate = 10.0 ; const float MIN_Gate = -10.0 ; const float MAX_Drain = 10.0 ; const float MIN_Drain = -10.0 ; void Update_TEMP() { int RAW = analogRead(A7) ; TEMP = RAW * (5.0 / 10.230); // LM35 -> 10 mV per deg celsius if(TEMP > 150.0) TEMP = 150.0 ; if(TEMP < 0.0) TEMP = 0.0 ; } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES LTC2400, 24-Bit : ADC // ///////////////////////////////////////////////////////////////////// const float SHUNT_RESI = 2.500 ; // OHMS, CHANGE HERE FOR CALIBRATION const int ADC_CS = 7 ; const int ADC_DAT = 6 ; const int ADC_CLK = 5 ; const float ADC_REF = -2.5000000000 ; long V_RAW = 0 ; // 32 Bit const long OFFSET_ZERO = 8388608 ; const long FULL_SCALE = 16777216 ; int error = 0 ; float Read_ADC() { float SOURCE = 0.9 ; // START CONVERSION digitalWrite(ADC_CLK, LOW) ; digitalWrite(ADC_CS, LOW) ; // WAIT FOR BIT 31 TO GO LOW (WE HAVE A PULLUP THERE) while(digitalRead(ADC_DAT)) delayMicroseconds(1) ; // YES, THAT IS A DANGEROUS THING :-) V_RAW = shiftIn(ADC_DAT, ADC_CLK, MSBFIRST) ; error = 3 ; // SOMETHING WRONG HERE if ((V_RAW & 0xF0) == 0x30 ) error = 1 ; // OVER RANGE if ((V_RAW & 0xF0) <= 0x10 ) error = 2 ; // UNDER RANGE if ((V_RAW & 0xF0) == 0x20 ) error = 0 ; // IN RANGE, OK V_RAW = (V_RAW & 0x0F) << 8 ; V_RAW |= shiftIn(ADC_DAT, ADC_CLK, MSBFIRST) ; V_RAW = V_RAW << 8 ; V_RAW |= shiftIn(ADC_DAT, ADC_CLK, MSBFIRST) ; V_RAW = V_RAW << 8 ; V_RAW |= shiftIn(ADC_DAT, ADC_CLK, MSBFIRST) ; digitalWrite(ADC_CS, HIGH) ; V_RAW = V_RAW >> 4 ; SOURCE = ADC_REF * (V_RAW - OFFSET_ZERO) / FULL_SCALE ; if(error == 0) return SOURCE ; if(error > 0) { // CURRENT TOO HIGH !!! SET_DRAIN(0.0) ; Serial.print("CURRENT TOO HIGH. SET DRAIN TO 0.0 V") ; } if(error == 1) return +99.999 ; if(error == 2) return -99.999 ; } float mapFloat(float WERT, float INMIN, float INMAX, float OUTMIN, float OUTMAX) { return ((WERT - INMIN) * (OUTMAX - OUTMIN) / (INMAX - INMIN) + OUTMIN ) ; } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES DAC8555 BY TEXAS INSTRUMENTS // ///////////////////////////////////////////////////////////////////// const int DAC_LOD = A1 ; const int DAC_ENB = A0 ; const int DAC_RSE = 12 ; const int DAC_RES = 11 ; const int DAC_DAT = 10 ; const int DAC_CLK = 9 ; const int DAC_SYN = 8 ; void Write_DAC(int payload, byte dac) { digitalWrite(DAC_SYN, LOW) ; byte A = (dac << 1) ; byte B = (payload & 0xFF00) >> 8 ; byte C = (payload & 0x00FF) ; A |= 0x10 ; shiftOut(DAC_DAT, DAC_CLK, MSBFIRST, A) ; shiftOut(DAC_DAT, DAC_CLK, MSBFIRST, B) ; shiftOut(DAC_DAT, DAC_CLK, MSBFIRST, C) ; digitalWrite(DAC_SYN, HIGH) ; } // Vout = 4 * 5 V * DATA / 65536 - 2 * 5 V // BASE IS DAC#A void SET_BASE(float VAL) { byte DAC_SEL = 0x00 ; if(VAL < MIN_Base) VAL = MIN_Base ; if(VAL > MAX_Base) VAL = MAX_Base ; unsigned int VALUE = (unsigned int)mapFloat(VAL, MIN_Base, MAX_Base, 0.0, 65535.0 ) ; Write_DAC(VALUE, DAC_SEL) ; if(debug) { Serial.print("BASE mA : ") ; Serial.println(BASE_CURR, 3) ; Serial.print("DAC_SEL : ") ; Serial.println(DAC_SEL,DEC) ; Serial.print("PAYLOAD : ") ; Serial.println(VALUE,DEC) ; Serial.println("--------------------------------------") ; } } // CREATE A SAWTOOTH void TEST_BASE_SAWTOOTH() { float STEP = 0.1 ; BASE_CURR += STEP ; if(BASE_CURR > MAX_Base) BASE_CURR = MIN_Base ; SET_BASE(BASE_CURR) ; } // GATE IS DAC#B void SET_GATE(float VAL) { byte DAC_SEL = 0x01 ; if(VAL < MIN_Gate) VAL = MIN_Gate ; if(VAL > MAX_Gate) VAL = MAX_Gate ; unsigned int VALUE = (unsigned int)mapFloat(VAL, MIN_Gate, MAX_Gate, 0.0, 65535.0 ) ; Write_DAC(VALUE, DAC_SEL) ; if(debug) { Serial.print("GATE Volts : ") ; Serial.println(GATE_VOLT, 3) ; Serial.print("DAC_SEL : ") ; Serial.println(DAC_SEL,DEC) ; Serial.print("PAYLOAD : ") ; Serial.println(VALUE,DEC) ; Serial.println("--------------------------------------") ; } } // CREATE A SAWTOOTH void TEST_GATE_SAWTOOTH() { float STEP = 0.1 ; GATE_VOLT += STEP ; if(GATE_VOLT > MAX_Gate) GATE_VOLT = MIN_Gate ; SET_GATE(GATE_VOLT) ; } // DRAIN IS DAC#C void SET_DRAIN(float VAL) { byte DAC_SEL = 0x02 ; if(VAL < MIN_Drain) VAL = MIN_Drain ; if(VAL > MAX_Drain) VAL = MAX_Drain ; unsigned int VALUE = (unsigned int)mapFloat(VAL, MIN_Drain, MAX_Drain, 0.0, 65535.0 ) ; Write_DAC(VALUE, DAC_SEL) ; if(debug) { Serial.print("DRAIN Volts : ") ; Serial.println(DRAIN_VOLT, 3) ; Serial.print("DAC_SEL : ") ; Serial.println(DAC_SEL,DEC) ; Serial.print("PAYLOAD : ") ; Serial.println(VALUE,DEC) ; Serial.println("--------------------------------------") ; } } // CREATE A SAWTOOTH void TEST_DRAIN_SAWTOOTH() { float STEP = 0.1 ; DRAIN_VOLT += STEP ; if(DRAIN_VOLT > MAX_Drain) DRAIN_VOLT = MIN_Drain ; SET_DRAIN(DRAIN_VOLT) ; } // AUX IS DAC#D, DAC Sel = 0x03 void SET_AUX(int VAL) { byte DAC_SEL = 0x03 ; unsigned int VALUE = 0 ; if(VAL < 0) VALUE = 0 ; if(VAL > 65535) VALUE = 65535 ; Write_DAC(VALUE, DAC_SEL) ; if(debug) { Serial.print("AUX Volts : ") ; Serial.println(DRAIN_VOLT, 3) ; Serial.print("DAC_SEL : ") ; Serial.println(DAC_SEL,DEC) ; Serial.print("PAYLOAD : ") ; Serial.println(VALUE,DEC) ; Serial.println("--------------------------------------") ; } } // ///////////////////////////////////////////////////////////////////// // SETUP // ///////////////////////////////////////////////////////////////////// void setup() { Serial.begin(115200) ; // DAC pinMode(DAC_LOD, OUTPUT) ; pinMode(DAC_ENB, OUTPUT) ; pinMode(DAC_RSE, OUTPUT) ; pinMode(DAC_RES, OUTPUT) ; pinMode(DAC_DAT, OUTPUT) ; pinMode(DAC_CLK, OUTPUT) ; pinMode(DAC_SYN, OUTPUT) ; digitalWrite(DAC_RES, HIGH) ; digitalWrite(DAC_RSE, LOW) ; digitalWrite(DAC_ENB, LOW) ; digitalWrite(DAC_SYN, HIGH) ; // ADC pinMode(ADC_DAT, INPUT_PULLUP) ; pinMode(ADC_CS, OUTPUT) ; pinMode(ADC_CLK, OUTPUT) ; Serial.println("TANACHAIMOD 1.9 BY CHANGPUAK.CH") ; Serial.println("(C) 16.07.2023\n") ; Serial.println("READY.\n") ; pinMode(A7, INPUT) ; // TEMPERATURE FROM LM35 SET_BASE(0.0) ; SET_DRAIN(0.0) ; SET_GATE(0.0) ; } // ///////////////////////////////////////////////////////////////////// // MAIN LOOP // ///////////////////////////////////////////////////////////////////// void loop() { // ////////////////////////////////// // CHECK SERIAL while (Serial.available() > 0) // ////////////////////////////////// { int tmp; char st[20]; char rx = Serial.read(); // read a single character buffer += rx; //add character to the string buffer if ((rx == '\n') || (rx == '\r')) { buffer.toCharArray(tempbuf, 40); // //////////////////////////////////////////////// if (buffer.startsWith("SETGATE:")) { // extract voltage as floating point value sscanf(tempbuf,"SETGATE:%s",&st) ; GATE_VOLT = strtod(st,NULL) ; SET_GATE(GATE_VOLT) ; } else // //////////////////////////////////////////////// if (buffer.startsWith("SETBASE:")) { // extract voltage as floating point value sscanf(tempbuf,"SETBASE:%s",&st) ; BASE_CURR = strtod(st,NULL) ; SET_BASE(BASE_CURR) ; } else // //////////////////////////////////////////////// if (buffer.startsWith("SETDRAIN:")) { // extract voltage as floating point value sscanf(tempbuf,"SETDRAIN:%s",&st); DRAIN_VOLT = strtod(st,NULL); SET_DRAIN(DRAIN_VOLT) ; delay(9) ; SOURCE_VOLT = Read_ADC() ; } else // //////////////////////////////////////////////// if (buffer.startsWith("SOURCE?")) { SOURCE_VOLT = Read_ADC() ; Serial.println(SOURCE_VOLT ,5) ; } else // //////////////////////////////////////////////// if (buffer.startsWith("SHUNT?")) { Serial.println(SHUNT_RESI ,5) ; } else // //////////////////////////////////////////////// if (buffer.startsWith("TEMP?")) { Update_TEMP() ; Serial.print(TEMP,3) ; Serial.println(" °C") ; } else // //////////////////////////////////////////////// if (buffer.startsWith("DEBUG:OFF")) debug = false ; else // //////////////////////////////////////////////// if (buffer.startsWith("DEBUG:ON")) debug = true ; else // //////////////////////////////////////////////// if (buffer.startsWith("TESTBASE:ON")) { TEST_BASE = true ; SET_DRAIN(0.0) ; } else // //////////////////////////////////////////////// if (buffer.startsWith("TESTBASE:OFF")) TEST_BASE = false ; else // //////////////////////////////////////////////// if (buffer.startsWith("TESTGATE:ON")) { TEST_GATE = true ; SET_DRAIN(0.0) ; } else // //////////////////////////////////////////////// if (buffer.startsWith("TESTGATE:OFF")) TEST_GATE = false ; else // //////////////////////////////////////////////// if (buffer.startsWith("TESTDRAIN:ON")) TEST_DRAIN = true ; else // //////////////////////////////////////////////// if (buffer.startsWith("TESTDRAIN:OFF")) TEST_DRAIN = false ; else // //////////////////////////////////////////////// if (buffer.startsWith("HELP?")) { Serial.println("COMMANDS :") ; Serial.println("SETGATE:xx.xxx SETS THE GATE VOLTAGE TO xx.xxx") ; Serial.println("SETDRAIN:xx.xxx SETS THE DRAIN VOLTAGE TO xx.xxx") ; Serial.println("SETBASE:xx.xxx SETS THE BASE CURRENT TO xx.xxx") ; Serial.println("SOURCE? RETURNS THE VOLTAGE AT THE SOURCE PORT") ; Serial.println("TEMP? RETURNS THE TEMPERATURE OF THE HEATSINK.") ; Serial.println("DEBUG:ON SWITCHES INTO DEBUG-MODE") ; Serial.println("DEBUG:OFF SWITCHES INTO NO-DEBUG-MODE") ; Serial.println("TESTBASE:ON SWITCHES SAWTOOTH ON BASE PORT ON") ; Serial.println("TESTBASE:OFF SWITCHES SAWTOOTH ON BASE PORT OFF") ; Serial.println("TESTGATE:ON SWITCHES SAWTOOTH ON GATE PORT ON") ; Serial.println("TESTGATE:OFF SWITCHES SAWTOOTH ON GATE PORT OFF") ; Serial.println("TESTDRAIN:ON SWITCHES SAWTOOTH ON DRAIN PORT ON") ; Serial.println("TESTDRAIN:OFF SWITCHES SAWTOOTH ON DRAIN PORT OFF") ; } else // //////////////////////////////////////////////// if (buffer.startsWith("*IDN?")) { Serial.println("TANACHAIMOD 1.9 BY CHANGPUAK.CH") ; Serial.println("16.07.2023") ; } // //////////////////////////////////////////////// buffer = "" ; //erase buffer for next command } } if(TEST_BASE) TEST_BASE_SAWTOOTH() ; if(TEST_GATE) TEST_GATE_SAWTOOTH() ; if(TEST_DRAIN) TEST_DRAIN_SAWTOOTH() ; delay(9) ; } // ///////////////////////////////////////////////////////////// // END OF FILE. // /////////////////////////////////////////////////////////////