NANO controlled bench supply help please

I'm in the process of building a NANO controlled bench supply using information gleaned from the internet. I am running into an error that I can't figure out. Have researched the error but I am unable to figure it out. Keep in mind that I haven't written anything but BASIC and that was the late 60's. I am hoping someone here will be able to advise me as to what to do. If I were to upload the sketch, would anyone be kind enough to help? Asking a lot, I know, but at my wits end. Running IDE 2.3.8 on a Win11 box. The sketch is, to me, long at 553 lines but with a lot of comments. The specific error I'm getting at line 183 is "expected initializer before 'enc1ISR'". Line is "void IRAM_ATTR enc1ISR() {" I realize this is an out of context statement. If someone can assist, I can upload the entire sketch if that would help. I fear that once this is corrected, there may be other errors and I really don't want to be a burden to anyone. I hope I have given enough information to get assistance, if not, I do apologize.

Post your formatted code in a code block using the <CODE> button in the Reply box.
Post a wiring diagram and a schematic diagram.
Describe how it works, and how you expect it to work.

Probably indicates syntax error in a prior line. Check for missing line endings, like the semi-colon (;).

I can guarantee that without the whole sketch, it's unlikely that anyone can help. As children, none of us paid attention in mind reading class. :slightly_smiling_face:

Though I will say that IRAM_ATTR isn't usually something I expect to see in a sketch for a Nano. That's more of an ESP32 thing, I thought...

type or paste code here
```/*
 ============================================================
  0-30V / 3A Linear Bench Power Supply Controller
  Arduino Nano + 2x MCP4725 + INA219 + ST7735 TFT + 2x KY-040
 ============================================================
  Pin Map:
   SPI TFT:  RST=D8, DC=D9, CS=D10, MOSI=D11, SCK=D13
   I2C:      SDA=A4, SCL=A5
   ENC1 (V): CLK=D2(INT0), DT=D3, SW=D4
   ENC2 (I): CLK=D5, DT=D6, SW=D7
   LED_CV:   D12
   LED_CC:   A0
   Vout ADC: A1
 ============================================================
  Libraries needed (install via Library Manager):
   - Adafruit INA219
   - Adafruit GFX Library
   - Adafruit ST7735 and ST7789 Library
 ============================================================
*/

#include <Wire.h>
#include <Adafruit_INA219.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <EEPROM.h>

// ============================================================
//  PIN DEFINITIONS
// ============================================================
#define TFT_RST    8
#define TFT_DC     9
#define TFT_CS    10

#define ENC1_CLK   2    // Voltage encoder, uses INT0
#define ENC1_DT    3
#define ENC1_SW    4

#define ENC2_CLK   5    // Current encoder, polled
#define ENC2_DT    6
#define ENC2_SW    7

#define LED_CV    12
#define LED_CC    A0
#define ADC_VOUT  A1    // Vout sense via resistor divider

// ============================================================
//  I2C ADDRESSES
// ============================================================
#define DAC_V_ADDR   0x60   // MCP4725 voltage DAC  (A0=GND)
#define DAC_I_ADDR   0x61   // MCP4725 current DAC  (A0=VCC)
#define INA_ADDR     0x40   // INA219               (default)

// ============================================================
//  EEPROM MAP
// ============================================================
#define EE_DAC_V    0    // uint16_t: last voltage DAC value
#define EE_DAC_I    2    // uint16_t: last current DAC value
#define EE_CAL_V    4    // float:    voltage cal factor
#define EE_CAL_I    8    // float:    current cal factor

// ============================================================
//  HARDWARE CONSTANTS
// ============================================================
#define DAC_FULLSCALE   4095
#define VOUT_MAX        30.0f    // V
#define IOUT_MAX         3.0f   // A
#define RSHUNT           0.1f   // ohm

// ADC sense divider: R_fb_bot=10k, R_fb_top+VR1~66k --> ratio = 10/76 = 0.1316
// Calibrate with VR1 trimmer so ratio exactly gives VOUT_MAX at ADC=~4.0V
#define ADC_VOUT_DIVISOR  0.1365f   // adjust post-calibration if needed

// Current DAC: at I_MAX amps, DAC count = 2703 (= 3.3V/5.0V * 4095)
// This gives Vset_I_scaled = 3.3V * 3.9k/(39k+3.9k) = 0.300V = Vshunt at 3A
#define DAC_I_FULLCOUNT  2703

// ============================================================
//  CALIBRATION FACTORS (loaded from EEPROM at boot)
// ============================================================
float cal_V = 1.0f;
float cal_I = 1.0f;

// ============================================================
//  SETPOINTS AND MEASUREMENTS
// ============================================================
float vSet = 0.0f;
float iSet = 0.1f;
uint16_t dacV = 0;
uint16_t dacI = 0;

float vMeas = 0.0f;
float iMeas = 0.0f;
float pMeas = 0.0f;
bool  isCC  = false;

// ============================================================
//  ENCODER STATE
// ============================================================
volatile int enc1Delta = 0;        // signed count from ISR
int          enc2Delta = 0;        // signed count from polling

volatile uint8_t enc1PrevCLK = HIGH;
uint8_t          enc2PrevCLK = HIGH;

bool enc1Coarse = false;           // push ENC1_SW to toggle
bool enc2Coarse = false;           // push ENC2_SW to toggle

// ============================================================
//  DISPLAY TIMING
// ============================================================
#define MEAS_INTERVAL_MS    50
#define DISP_INTERVAL_MS   100
unsigned long tLastMeas = 0;
unsigned long tLastDisp = 0;

// ============================================================
//  OBJECTS
// ============================================================
Adafruit_ST7735 tft(TFT_CS, TFT_DC, TFT_RST);
Adafruit_INA219 ina219(INA_ADDR);

// ============================================================
//  EEPROM HELPERS
// ============================================================
void eeWriteFloat(int addr, float v) {
  uint8_t* p = (uint8_t*)&v;
  for (int i = 0; i < 4; i++) EEPROM.write(addr + i, p[i]);
}
float eeReadFloat(int addr) {
  float v;
  uint8_t* p = (uint8_t*)&v;
  for (int i = 0; i < 4; i++) p[i] = EEPROM.read(addr + i);
  return v;
}
void eeWriteU16(int addr, uint16_t v) {
  EEPROM.write(addr,   (uint8_t)(v & 0xFF));
  EEPROM.write(addr+1, (uint8_t)(v >> 8));
}
uint16_t eeReadU16(int addr) {
  return (uint16_t)EEPROM.read(addr) | ((uint16_t)EEPROM.read(addr+1) << 8);
}

// ============================================================
//  MCP4725 WRITE (fast, no EEPROM write to DAC)
// ============================================================
void dacWrite(uint8_t addr, uint16_t val) {
  if (val > DAC_FULLSCALE) val = DAC_FULLSCALE;
  Wire.beginTransmission(addr);
  Wire.write(0x40);                      // Write DAC register
  Wire.write((uint8_t)(val >> 4));       // D11..D4
  Wire.write((uint8_t)((val & 0xF)<<4)); // D3..D0
  Wire.endTransmission();
}

// ============================================================
//  SETPOINT CONVERSIONS
// ============================================================
uint16_t voltsToDac(float v) {
  v = constrain(v, 0.0f, VOUT_MAX);
  return (uint16_t)((v / VOUT_MAX) * DAC_FULLSCALE);
}

uint16_t ampsToDac(float a) {
  a = constrain(a, 0.0f, IOUT_MAX);
  return (uint16_t)((a / IOUT_MAX) * DAC_I_FULLCOUNT);
}

float dacToVolts(uint16_t d) {
  return (float)d / DAC_FULLSCALE * VOUT_MAX;
}

float dacToAmps(uint16_t d) {
  return (float)d / DAC_I_FULLCOUNT * IOUT_MAX;
}

// ============================================================
//  ENCODER 1 ISR (voltage, INT0 on D2)
// ============================================================

//attachInterrupt(digitalPinToInterrupt(ENC1_CLK), enc1ISR, CHANGE);
void IRAM_ATTR enc1ISR() {
  uint8_t clk = digitalRead(ENC1_CLK);
  if (clk != enc1PrevCLK) {
    enc1PrevCLK = clk;
    if (clk == LOW) {
      uint8_t dt = digitalRead(ENC1_DT);
      enc1Delta += (dt != clk) ? +1 : -1;
    }
  }
}

// ============================================================
//  ENCODER 2 POLL (current, polled in loop)
// ============================================================
void pollEnc2() {
  uint8_t clk = digitalRead(ENC2_CLK);
  if (clk != enc2PrevCLK) {
    enc2PrevCLK = clk;
    if (clk == LOW) {
      uint8_t dt = digitalRead(ENC2_DT);
      enc2Delta += (dt != clk) ? +1 : -1;
    }
  }
}

// ============================================================
//  PROCESS ENCODER CHANGES -> UPDATE SETPOINTS
// ============================================================
void processEncoders() {
  // --- Voltage encoder ---
  int d1;
  noInterrupts();
  d1 = enc1Delta;
  enc1Delta = 0;
  interrupts();

  if (d1 != 0) {
    float step = enc1Coarse ? 0.1f : 0.01f;
    vSet = constrain(vSet + d1 * step, 0.0f, VOUT_MAX);
    dacV = voltsToDac(vSet);
    dacWrite(DAC_V_ADDR, dacV);
    eeWriteU16(EE_DAC_V, dacV);
  }

  // --- Current encoder ---
  if (enc2Delta != 0) {
    float step = enc2Coarse ? 0.1f : 0.01f;
    iSet = constrain(iSet + enc2Delta * step, 0.0f, IOUT_MAX);
    enc2Delta = 0;
    dacI = ampsToDac(iSet);
    dacWrite(DAC_I_ADDR, dacI);
    eeWriteU16(EE_DAC_I, dacI);
  }

  // --- ENC1 pushbutton: toggle coarse/fine ---
  static uint8_t sw1Prev = HIGH;
  static uint32_t sw1Time = 0;
  uint8_t sw1 = digitalRead(ENC1_SW);
  if (sw1 == LOW && sw1Prev == HIGH && (millis() - sw1Time) > 150) {
    enc1Coarse = !enc1Coarse;
    sw1Time = millis();
  }
  sw1Prev = sw1;

  // --- ENC2 pushbutton: toggle coarse/fine ---
  static uint8_t sw2Prev = HIGH;
  static uint32_t sw2Time = 0;
  uint8_t sw2 = digitalRead(ENC2_SW);
  if (sw2 == LOW && sw2Prev == HIGH && (millis() - sw2Time) > 150) {
    enc2Coarse = !enc2Coarse;
    sw2Time = millis();
  }
  sw2Prev = sw2;
}

// ============================================================
//  MEASUREMENTS
// ============================================================
void takeMeasurements() {
  // Voltage from Arduino ADC (resistor divider on feedback network)
  // Average 4 samples for noise reduction
  uint32_t rawSum = 0;
  for (int i = 0; i < 4; i++) rawSum += analogRead(ADC_VOUT);
  float adcV = (rawSum / 4.0f) * (5.0f / 1023.0f);
  vMeas = (adcV / ADC_VOUT_DIVISOR) * cal_V;
  vMeas = max(0.0f, vMeas);

  // Current from INA219 shunt (low-side, 0.1 ohm)
  float shunt_mV = ina219.getShuntVoltage_mV();
  iMeas = (shunt_mV / 1000.0f / RSHUNT) * cal_I;
  iMeas = max(0.0f, iMeas);

  pMeas = vMeas * iMeas;

  // Mode detection: CC if current is at limit and voltage is below setpoint
  float iErr_abs = fabsf(iMeas - iSet);
  float vDrop    = vSet - vMeas;
  isCC = (iErr_abs < (0.05f * IOUT_MAX + 0.015f)) && (vDrop > 0.15f) && (iSet > 0.05f);
}

// ============================================================
//  LED UPDATE
// ============================================================
void updateLEDs() {
  digitalWrite(LED_CV, isCC ? LOW : HIGH);
  digitalWrite(LED_CC, isCC ? HIGH : LOW);
}

// ============================================================
//  TFT DISPLAY (partial-update to reduce flicker)
// ============================================================

// Helper: print a number field, erasing previous value
void printField(uint8_t x, uint8_t y, float val, uint8_t width, uint8_t decimals,
                uint16_t color, uint8_t textSize) {
  tft.setTextSize(textSize);
  tft.setTextColor(color, ST77XX_BLACK);  // background erase trick
  tft.setCursor(x, y);
  // Build right-justified string
  char buf[12];
  dtostrf(val, width, decimals, buf);
  tft.print(buf);
}

bool displayInitialized = false;

void initDisplay() {
  tft.fillScreen(ST77XX_BLACK);

  // Static labels
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(1);

  // Title bar
  tft.fillRect(0, 0, 128, 12, 0x2945);  // Dark blue bar
  tft.setCursor(4, 2);
  tft.print("BENCH PSU  0-30V/3A");

  // Labels
  tft.setCursor(2,  16); tft.print("Vout:");
  tft.setCursor(2,  52); tft.print("Iout:");
  tft.setCursor(2,  88); tft.print("P:");
  tft.setCursor(2, 105); tft.print("Vset:");
  tft.setCursor(66,105); tft.print("Iset:");

  // Units
  tft.setCursor(100, 24); tft.print(" V");
  tft.setCursor(100, 60); tft.print(" A");
  tft.setCursor(60,  88); tft.print(" W");

  // Mode box outline
  tft.drawRect(0, 120, 128, 40, ST77XX_WHITE);

  displayInitialized = true;
}

void updateDisplay() {
  if (!displayInitialized) initDisplay();

  // Output voltage (big, cyan)
  printField(2, 22, vMeas, 6, 2, ST77XX_CYAN, 3);

  // Output current (big, yellow)
  printField(2, 58, iMeas, 6, 3, ST77XX_YELLOW, 3);

  // Power (small, green)
  printField(20, 88, pMeas, 6, 2, ST77XX_GREEN, 1);

  // Setpoints (small)
  printField(30, 105, vSet, 5, 2, ST77XX_WHITE, 1);
  printField(94, 105, iSet, 5, 2, ST77XX_WHITE, 1);

  // Step size indicators
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_CYAN, ST77XX_BLACK);
  tft.setCursor(2, 113);
  tft.print(enc1Coarse ? "V:100mV" : "V: 10mV");
  tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK);
  tft.setCursor(70, 113);
  tft.print(enc2Coarse ? "I:100mA" : "I: 10mA");

  // Mode box (filled)
  static bool lastIsCC = false;
  if (isCC != lastIsCC || !displayInitialized) {
    tft.fillRect(1, 121, 126, 38, isCC ? ST77XX_RED : ST77XX_BLUE);
    tft.setTextSize(2);
    tft.setTextColor(ST77XX_WHITE);
    tft.setCursor(22, 131);
    tft.print(isCC ? "CC MODE" : "CV MODE");
    lastIsCC = isCC;
  }
}

// ============================================================
//  SERIAL CALIBRATION HANDLER
// ============================================================
void handleSerialCal() {
  if (!Serial.available()) return;
  String cmd = Serial.readStringUntil('\n');
  cmd.trim();

  if (cmd.startsWith("CAL_V ")) {
    float actual = cmd.substring(6).toFloat();
    if (actual > 0.5f && vMeas > 0.1f) {
      cal_V *= (actual / vMeas);
      Serial.print(F("cal_V = ")); Serial.println(cal_V, 6);
    } else Serial.println(F("ERR: need >0.5V on output"));
  }
  else if (cmd.startsWith("CAL_I ")) {
    float actual = cmd.substring(6).toFloat();
    if (actual > 0.005f && iMeas > 0.005f) {
      cal_I *= (actual / iMeas);
      Serial.print(F("cal_I = ")); Serial.println(cal_I, 6);
    } else Serial.println(F("ERR: need >5mA on output"));
  }
  else if (cmd == F("SAVE_CAL")) {
    eeWriteFloat(EE_CAL_V, cal_V);
    eeWriteFloat(EE_CAL_I, cal_I);
    Serial.println(F("Calibration saved to EEPROM."));
  }
  else if (cmd == F("SHOW_CAL")) {
    Serial.print(F("cal_V = ")); Serial.println(cal_V, 6);
    Serial.print(F("cal_I = ")); Serial.println(cal_I, 6);
  }
  else if (cmd == F("SHOW")) {
    Serial.print(F("Vset=")); Serial.print(vSet,2);
    Serial.print(F(" Iset=")); Serial.print(iSet,3);
    Serial.print(F(" Vout=")); Serial.print(vMeas,3);
    Serial.print(F(" Iout=")); Serial.print(iMeas,3);
    Serial.print(F(" P=")); Serial.print(pMeas,2);
    Serial.print(F(" Mode=")); Serial.println(isCC ? "CC" : "CV");
  }
  else if (cmd == F("ZERO")) {
    dacWrite(DAC_V_ADDR, 0);
    dacWrite(DAC_I_ADDR, 0);
    vSet = 0; iSet = 0;
    Serial.println(F("Output zeroed."));
  }
  else {
    Serial.println(F("Commands: CAL_V <v>  CAL_I <a>  SAVE_CAL  SHOW_CAL  SHOW  ZERO"));
  }
}

// ============================================================
//  SAFE RAMP: slowly increase DAC to avoid output surge
// ============================================================
void rampDacV(uint16_t target) {
  uint16_t current = 0;
  while (current < target) {
    current = min((uint16_t)(current + 20), target);
    dacWrite(DAC_V_ADDR, current);
    delay(10);
  }
}

// ============================================================
//  SETUP
// ============================================================
void setup() {
  Serial.begin(115200);
  Serial.println(F("\n=== Bench PSU Controller Boot ==="));

  // GPIO
  pinMode(ENC1_CLK, INPUT);
  pinMode(ENC1_DT,  INPUT);
  pinMode(ENC1_SW,  INPUT_PULLUP);
  pinMode(ENC2_CLK, INPUT);
  pinMode(ENC2_DT,  INPUT);
  pinMode(ENC2_SW,  INPUT_PULLUP);
  pinMode(LED_CV, OUTPUT);
  pinMode(LED_CC, OUTPUT);
  pinMode(ADC_VOUT, INPUT);
  digitalWrite(LED_CV, LOW);
  digitalWrite(LED_CC, LOW);

  // I2C
  Wire.begin();
  Wire.setClock(100000UL);   // 100 kHz

  // INA219 initialization
  if (!ina219.begin()) {
    Serial.println(F("WARNING: INA219 not found at 0x40!"));
  } else {
    // Configure for 32V bus, +/-320mV gain (covers 0-3.2A on 0.1 ohm shunt)
    // Manual config: Config reg 0x399F = 32V, gain/8, 12-bit avg x1, continuous
    Wire.beginTransmission(INA_ADDR);
    Wire.write(0x00);          // Config register
    Wire.write(0x39);          // 0x399F high byte: 32V bus, gain=8
    Wire.write(0x9F);          // low byte: 12-bit, continuous both
    Wire.endTransmission();
    // Calibration for 0.1 ohm shunt, 3A max
    // CAL = 0.04096 / (LSB * Rshunt) = 0.04096 / (9.155e-5 * 0.1) = 4473 = 0x1179
    Wire.beginTransmission(INA_ADDR);
    Wire.write(0x05);          // Calibration register
    Wire.write(0x11);
    Wire.write(0x79);
    Wire.endTransmission();
    Serial.println(F("INA219 configured OK."));
  }

  // TFT
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(0);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(0xFDA0);   // Orange
  tft.setTextSize(1);
  tft.setCursor(15, 65);
  tft.print("Bench PSU v1.0");
  tft.setCursor(20, 80);
  tft.print("Initializing...");
  delay(1000);

  // Load EEPROM calibration
  float cv = eeReadFloat(EE_CAL_V);
  float ci = eeReadFloat(EE_CAL_I);
  if (!isnan(cv) && cv > 0.5f && cv < 2.0f) cal_V = cv;
  if (!isnan(ci) && ci > 0.5f && ci < 2.0f) cal_I = ci;
  Serial.print(F("cal_V=")); Serial.print(cal_V,5);
  Serial.print(F(" cal_I=")); Serial.println(cal_I,5);

  // Load last setpoints
  uint16_t sv = eeReadU16(EE_DAC_V);
  uint16_t si = eeReadU16(EE_DAC_I);
  if (sv > DAC_FULLSCALE) sv = 0;
  if (si > DAC_I_FULLCOUNT) si = ampsToDac(0.1f); // default 100mA limit
  dacV = sv;
  dacI = si;
  vSet = dacToVolts(dacV);
  iSet = dacToAmps(dacI);

  // Safe power-on: set current limit first, then ramp voltage
  dacWrite(DAC_V_ADDR, 0);     // Start at 0V
  dacWrite(DAC_I_ADDR, dacI);  // Set current limit
  delay(100);
  rampDacV(dacV);              // Ramp to saved voltage

  // Attach interrupt for ENC1
  enc1PrevCLK = digitalRead(ENC1_CLK);
  attachInterrupt(digitalPinToInterrupt(ENC1_CLK), enc1ISR, CHANGE);

  // Initial display
  initDisplay();
  Serial.println(F("Ready. Type HELP for serial commands."));
}

// ============================================================
//  MAIN LOOP
// ============================================================
void loop() {
  unsigned long now = millis();

  // Always poll ENC2 and process both encoders
  pollEnc2();
  processEncoders();

  // Serial calibration commands
  handleSerialCal();

  // Measurements every MEAS_INTERVAL_MS
  if (now - tLastMeas >= MEAS_INTERVAL_MS) {
    tLastMeas = now;
    takeMeasurements();
    updateLEDs();
  }

  // Display update every DISP_INTERVAL_MS
  if (now - tLastDisp >= DISP_INTERVAL_MS) {
    tLastDisp = now;
    updateDisplay();
  }
}

I am so sorry, code has been posted. Thank you.

Change this

//attachInterrupt(digitalPinToInterrupt(ENC1_CLK), enc1ISR, CHANGE);
void IRAM_ATTR enc1ISR() {
  uint8_t clk = digitalRead(ENC1_CLK);

to

//attachInterrupt(digitalPinToInterrupt(ENC1_CLK), enc1ISR, CHANGE);
void enc1ISR() {
  uint8_t clk = digitalRead(ENC1_CLK);

(i.e. remove IRAM_ATTR).

It compiled for a classic Arduino Nano after that, though there were a few warnings (from various Adafruit libraries) with the compiler warning level set to ALL.

Project is a 0 to 30v 0 to 3a linear precise bench power supply with CV and CC control. All pretty much under the control of the NANO. Wiring consists of 2 DACs, 2 Rotary Encoders, INA219 current shunt, 2 LM358 op amps for CV CC control. Also LCD screen and digital pane meters for current and voltage readouts. I don't have a single schematic diagram as it's being built in modular form.

That did it. So this was an age thing, old vs newer syntax?
How do I turn on the "All Warnings"? I am very open to any other advice to be offered. This is a new endeavor for me. Thank you so much.

I don't think it's an old code/new code thing. IRAM_ATTR doesn't apply to the AVR core, just (AFAIK) to ESP32s. Somehow you got some syntax for another core snuck in there. AI involved?

If you're using arduino-cli, you just add --warnings all to the command line. I don't use the IDE in any form, but I imagine there's a check box or a pull down somewhere in preferences.

New problem. Screen is upside down and set rotation(2) not working. I'm sure it's operator error.

Yes, I admit it, AI involved. Claude to be exact.

That explains it. That's the kind of error that no human would ever make but AIs frequently will. They mix and match without regard to reality. Expect other weird and wacky errors in the code that will be next to impossible to find as you continue. And so I'll take my leave here, as I don't debug AI hallucinations.

From what I can determine you will have problems with over current and heavy (low impedance) fault The reason I am thinking this is you will not be able to respond to a fault in the time needed to protect your load. Posting an annotated schematic would help. Also explain if it will work in constant voltage/current modes.

Thank you for the help you have given and I apologize for using AI. As I said, this is all new to me.

It will be tomorrow before I can upload schematics as I have to scan them. The last power supplies that I really got involved with had tubes and a little bit higher than 5v output. Yes, CC and CV are designed in.
was thinking of crowbar protection as that can be included in the output section.

Be sure there is current limit that will not fail when the crowbar fires. When I did some lab power supply's a few years back I did the current and voltage control with analog but used the DACs to set them. They were on a HPIB Bus [IEEE 488 or General Purpose Interface Bus (GPIB)].

That's how this one works. Analog using LM358 using 1% resistors and then DAC to control.

Use tft.setRotation(0)

Got it, thank you. Much more readable.

Here's the block diagram. Schematics to follow tomorrow. Hope you don't mind mostly hand drawn.
PSU Block diagram.pdf (62.7 KB)