/* ////////////////////////////////////////////////////////////////// ARDUINO/Genuino Project "SUPPLYMOD-B", a +/-12.5V, 0.5A Bipolar Power Supply https://www.changpuak.ch/electronics/Arduino-SupplyMod-B.php Software Version 2.0 19.07.2025 by ALEXANDER SSE FRANK USEFUL: https://docs.arduino.cc/language-reference/de/en/functions/analog-io/analogReference/ ////////////////////////////////////////////////////////////////// */ #include #include #include // DISPLAY #define OLED_MOSI 9 #define OLED_CLK 8 #define OLED_DC 11 #define OLED_CS 12 #define OLED_RESET 10 Adafruit_SH1106 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); #if (SH1106_LCDHEIGHT != 64) #error("Height incorrect, please fix Adafruit_SH1106.h!"); #endif #include "Adafruit_AD569x.h" Adafruit_AD569x ad5693 ; float Volt = 5.000 ; // UNIT IS V unsigned int Current = 0 ; // UNIT IS mA const unsigned int CURR_NULL = 531 ; long int POTI_VAL = 0 ; long int POTI_OLD = 0 ; long int POTI_HYST = 2 ; bool POTI_NEW = true ; const int CAL_VOLT = 55 ; bool debug = true ; // ///////////////////////////////////////////////////////////// // Serial Communication Routines // ///////////////////////////////////////////////////////////// String incoming = "nil"; void EvaluateSerialInput() { int longines = 0 ; boolean handled = false ; if (Serial.available() > 0) { incoming = Serial.readString() ; // WHOIS ? if (incoming.startsWith("*IDN?")) { Serial.println("SUPPLYMOD-B 2.0 BY CHANGPUAK.CH\n") ; Serial.println("SYSTEM READY.") ; Serial.print("VOLTAGE : ") ; Serial.print(Volt,3) ; Serial.println(" V") ; Serial.print("CURRENT : +") ; Serial.print(Current, DEC) ; Serial.println(" mA") ; handled = true ; } // ASK FOR CURRENT if (incoming.startsWith("IOUT?")) { Serial.print(Current, DEC) ; Serial.println(" mA") ; handled = true ; } // SET VOLTAGE if (incoming.startsWith("VSET:")) { longines = incoming.length() ; incoming = incoming.substring(5,longines) ; UpDateVOLT(incoming.toFloat()) ; Serial.println("O.K."); handled = true ; } // NO SPEAK AMERICANO if (!handled) { Serial.println("OOOOPS - SOMETHING WRONG HERE ???") ; handled = true ; } } } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES DISPLAY. // ///////////////////////////////////////////////////////////////////// void DisplayValue(float WERT) { // SIGN if (WERT < 0.000) display.print("-") ; if (WERT > 0.000) display.print("+") ; if (WERT == 0.000) display.print(" ") ; // SIGN if (fabs(WERT) < 10.000) display.print(" ") ; // LEADING ZERO display.print(fabs(WERT), 3) ; } void UpDateDisplay() { display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 0); display.println("*** SUPPLYMOD-B ***"); display.drawLine(0, 12, 128, 12, WHITE); display.setTextSize(2) ; // VOLTAGE display.setCursor(18, 20) ; DisplayValue(Volt) ; display.print(" V") ; // CURRENT display.setCursor(54, 44) ; if(Current < 100) display.print(" ") ; if(Current < 10) display.print(" ") ; display.print(Current) ; display.print(" mA") ; display.display() ; } // ///////////////////////////////////////////////////////////////////// // SUBROUTINES DAC AD5693R // ///////////////////////////////////////////////////////////////////// float mapintfloat(int x,int i_min,int i_max,float o_min,float o_max) { return (x - (float)i_min) * (o_max - o_min) / ((float)i_max - (float)i_min) + o_min; } void UpDateVOLT(float VOLT) { unsigned int DAC_VAL ; DAC_VAL = (int)(2621.4 * VOLT) + 32768 + CAL_VOLT ; UpDateDAC(DAC_VAL) ; } void UpDateDAC(unsigned int DAC_VAL) { ad5693.writeUpdateDAC(DAC_VAL) ; } void UpDatePOTI() { // SAVE OLD VALUE POTI_NEW = false ; POTI_OLD = POTI_VAL ; // USE 2.5 V REFERENCE analogReference(EXTERNAL) ; // NANO EVERY ONLY delay(9) ; // READ ANALOG VALUE AND AVERAGE POTI_VAL = 0 ; int AVG = 16 ; for(int i=0; i POTI_HYST) POTI_NEW = true ; if(debug) Serial.println(POTI_VAL,DEC) ; } void UpDateCURRENT() { // USE 5 V REFERENCE (SUPPLY) analogReference(VDD) ; // NANO EVERY ONLY delay(9) ; unsigned int Current_RAW = 0 ; int AVG = 31 ; for(int i=0; i CURR_NULL) Current_TRUE = Current_RAW - CURR_NULL ; else Current_TRUE = CURR_NULL - Current_RAW ; Current = 2 * Current_TRUE ; // if(debug) Serial.println(Current,DEC) ; } // ///////////////////////////////////////////////////////////////////// // S E T U P // ///////////////////////////////////////////////////////////////////// void setup() { Serial.begin(115200) ; Wire.begin() ; Wire.setClock(100000) ; // INIT OLED display.begin(SH1106_SWITCHCAPVCC); // SHOW STARTUP SCREEN display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 0); display.println("*** SUPPLYMOD-B ***"); display.drawLine(0, 12, 128, 12, WHITE); display.setTextSize(1); display.setCursor(0, 21); display.println("BIPOLAR POWER SUPPLY"); display.setCursor(0, 33); display.println("FOR LABORATORY USE."); display.setCursor(0, 45); display.println("(C) ETH QUANTUMOPTICS"); display.setCursor(0, 57); display.println("BUILT 25.07.2025"); display.display(); delay(999) ; ad5693.begin(0x4C, &Wire) ; // Reset the DAC ad5693.reset() ; // Configure the DAC for normal mode, internal reference, and no 2x gain ad5693.setMode(NORMAL_MODE, true, false) ; delay(999) ; POTI_NEW = true ; UpDateVOLT(Volt) ; Serial.println("Supplymod V2.0 by Changpuak.ch (C) 07/2025") ; Serial.println("Device ready.\n") ; } // ///////////////////////////////////////////////////////////////////// // M A I N L O O P // ///////////////////////////////////////////////////////////////////// void loop() { EvaluateSerialInput() ; // READ POTENTIOMETER : POTI_VAL UpDatePOTI() ; // CALCULATE VOLTAGE // POTI_VAL = 0 ... 1023 EQUALS -12.5 TO +12.5 Volts if(POTI_NEW) { // UPDATE DAC Volt = mapintfloat(POTI_VAL,0,1023,-12.5,+12.5) ; UpDateVOLT(Volt) ; POTI_NEW = false ; } UpDateDisplay() ; UpDateCURRENT() ; delay(999) ; } // ///////////////////////////////////////////////////////////// // END OF FILE. // /////////////////////////////////////////////////////////////