From 5b329b710a71e55f0e2ceb3b989a75a46f76b9e1 Mon Sep 17 00:00:00 2001 From: "Christian L. V. Madsen" Date: Tue, 13 May 2025 17:51:47 +0200 Subject: [PATCH] some things are working but regulation is fucked! --- .cproject | 35 ++++---- .gitmodules | 4 + .settings/language.settings.xml | 4 +- .settings/org.eclipse.cdt.core.prefs | 6 ++ buck_emulator.c | 121 +++++++++++++++++---------- buck_emulator.h | 35 ++++++++ buck_specs.h | 38 +++++++++ cm_pid_regulator | 1 + file_print.c | 44 ++++++++++ file_print.h | 18 ++++ main.c | 93 ++++++++++++++++++++ plotscript/python_csv_plotter.py | 94 +++++++++++++++++++++ 12 files changed, 429 insertions(+), 64 deletions(-) create mode 100644 .gitmodules create mode 100644 .settings/org.eclipse.cdt.core.prefs create mode 100644 buck_emulator.h create mode 100644 buck_specs.h create mode 160000 cm_pid_regulator create mode 100644 file_print.c create mode 100644 file_print.h create mode 100644 plotscript/python_csv_plotter.py diff --git a/.cproject b/.cproject index 41efb61..a069fcc 100644 --- a/.cproject +++ b/.cproject @@ -14,21 +14,22 @@ - + - - + - + + \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..48eac84 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "cm_pid_regulator"] + path = cm_pid_regulator + url = https://OZ1CM@bitbucket.org/oz1cm/cm_pid_regulator.git + branch = master diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index 3ed5de8..99fdeb1 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000..bdcb26f --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1636823514/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1636823514/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1636823514/PATH/value=C\:\\mingw64\\bin;C\:\\Users\\chris\\.espressif\\tools\\xtensa-esp-elf-gdb\\14.2_20240403\\xtensa-esp-elf-gdb\\bin;C\:\\Users\\chris\\.espressif\\tools\\riscv32-esp-elf-gdb\\14.2_20240403\\riscv32-esp-elf-gdb\\bin;C\:\\Users\\chris\\.espressif\\tools\\xtensa-esp-elf\\esp-14.2.0_20241119\\xtensa-esp-elf\\bin;C\:\\Users\\chris\\.espressif\\tools\\esp-clang\\esp-18.1.2_20240912\\esp-clang\\bin;C\:\\Users\\chris\\.espressif\\tools\\riscv32-esp-elf\\esp-14.2.0_20241119\\riscv32-esp-elf\\bin;C\:\\Users\\chris\\.espressif\\tools\\esp32ulp-elf\\2.38_20240113\\esp32ulp-elf\\bin;C\:\\Users\\chris\\.espressif\\tools\\cmake\\3.30.2\\bin;C\:\\Users\\chris\\.espressif\\tools\\openocd-esp32\\v0.12.0-esp32-20241016\\openocd-esp32\\bin;C\:\\Users\\chris\\.espressif\\tools\\ninja\\1.12.1\\;C\:\\Users\\chris\\.espressif\\tools\\idf-exe\\1.0.3\\;C\:\\Users\\chris\\.espressif\\tools\\ccache\\4.10.2\\ccache-4.10.2-windows-x86_64;C\:\\Users\\chris\\.espressif\\tools\\dfu-util\\0.11\\dfu-util-0.11-win64;C\:\\Users\\chris\\.espressif\\tools\\qemu-xtensa\\esp_develop_9.0.0_20240606\\qemu\\bin;C\:\\Users\\chris\\.espressif\\tools\\qemu-riscv32\\esp_develop_9.0.0_20240606\\qemu\\bin;C\:\\Users\\chris\\.espressif\\python_env\\idf5.4_py3.8_env\\Scripts;E\:\\cm_programs\\espressif_idf\\esp-idf-v5.4\\tools;E\:/cm_programs/eclipse//plugins/org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_21.0.4.v20240802-1551/jre/bin/server;E\:/cm_programs/eclipse//plugins/org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_21.0.4.v20240802-1551/jre/bin;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Windows\\System32\\OpenSSH\\;C\:\\Program Files\\dotnet\\;C\:\\Program Files (x86)\\IVI Foundation\\VISA\\WinNT\\Bin\\;C\:\\Program Files\\IVI Foundation\\VISA\\Win64\\Bin\\;C\:\\Program Files (x86)\\IVI Foundation\\VISA\\WinNT\\Bin;E\:\\cm_programs\\git_extensions\\;C\:\\Program Files\\Microchip\\xc8\\v2.36\\bin;E\:\\cm_programs\\Git\\cmd;C\:\\Program Files\\TortoiseGit\\bin;C\:\\Program Files (x86)\\Windows Kits\\10\\Windows Performance Toolkit\\;C\:\\Users\\chris\\AppData\\Local\\Microsoft\\WindowsApps;C\:\\Users\\chris\\.dotnet\\tools;E\:\\cm_programs\\eclipse +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1636823514/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1636823514/appendContributed=true diff --git a/buck_emulator.c b/buck_emulator.c index dcefcfc..4ebf29a 100644 --- a/buck_emulator.c +++ b/buck_emulator.c @@ -4,59 +4,88 @@ * Created on: 12 May 2025 * Author: Christian Lind Vie Madsen */ +#include "buck_emulator.h" +static int isStructOk(BuckEmulator_t *inst){ -typedef struct { - float Vin; // Input voltage - float Vout; // Output voltage - float IL; // Inductor current - float L; // Inductance - float C; // Capacitance - float Rload; // Load resistance - float dt; // Time step (e.g., 25e-6) -} BuckConverter; + if(inst == NULL)return 0; -void simulate_step(BuckConverter *buck, float duty_cycle) { - float dIL = (buck->Vin * duty_cycle - buck->Vout) / buck->L; - buck->IL += dIL * buck->dt; + return 1; - float dVout = (buck->IL - buck->Vout / buck->Rload) / buck->C; - buck->Vout += dVout * buck->dt; } -/* -int main() { - BuckConverter buck = { - .Vin = 12.0, - .Vout = 0.0, - .IL = 0.0, - .L = 100e-6, - .C = 100e-6, - .Rload = 10.0, - .dt = 25e-6 - }; +static void buck_emulator_step(BuckEmulator_t *inst, float duty_cycle) { + + float dIL = (inst->Vin * duty_cycle - inst->Vout) / inst->L; + inst->IL += dIL * inst->dt; + + float dVout = (inst->IL - inst->Vout / inst->Rload) / inst->C; + inst->Vout += dVout * inst->dt; + + return; +} + +int buck_emulator_Run(BuckEmulator_t *inst){ + + if(!isStructOk(inst))return 1; + + float dutyCycle = 0.0; + + for(float t = 0.0; t < inst->simTime; t+=inst->dt){ + + if(inst->regulate_evt != NULL)dutyCycle = inst->regulate_evt(inst->Vout); + + + buck_emulator_step(inst, dutyCycle); + + if(inst->getResult_evt != NULL)inst->getResult_evt(dutyCycle,inst->Vout,t); + } + + return 0; + +} + +int buck_emulator_RegGetResultEvt(BuckEmulator_t *inst, getResult_evt_t getRes_evt){ + + if(!isStructOk(inst))return 1; + + if(getRes_evt != NULL){ + + inst->getResult_evt = getRes_evt; + return 0; + } + + return 1; +} + +int buck_emulator_RegRegulationEvt(BuckEmulator_t *inst, regulate_evt_t reg_evt){ + + if(!isStructOk(inst))return 1; + + if(reg_evt != NULL){ + + inst->regulate_evt = reg_evt; + return 0; + } + + return 1; +} + +int buck_emulator_init(BuckEmulator_t *inst, float Vin, float L, float C, float Rload, float dt, float sim_time){ + + if(!isStructOk(inst))return 1; + + inst->Vin = Vin; + inst->L = L; + inst->C = C; + inst->Rload = Rload; + inst->dt = dt; + + inst->Vout = 0.0; + inst->IL = 0.0; + + inst->simTime = sim_time; - float duty_cycle = 0.5; - float Vref = 5.0; - float error, previous_error = 0, integral = 0; - float Kp = 0.2, Ki = 1000; - for (int i = 0; i < 40000; ++i) { - error = Vref - buck.Vout; - integral += error * buck.dt; - duty_cycle = Kp * error + Ki * integral; - if (duty_cycle > 1.0) duty_cycle = 1.0; - if (duty_cycle < 0.0) duty_cycle = 0.0; - - simulate_step(&buck, duty_cycle); - - // For debug: - if (i % 1000 == 0) - printf("Time: %.3f ms, Vout: %.2f V, IL: %.2f A, Duty: %.2f\n", - i * buck.dt * 1000, buck.Vout, buck.IL, duty_cycle); - } - - return 0; } - */ diff --git a/buck_emulator.h b/buck_emulator.h new file mode 100644 index 0000000..f3fef1c --- /dev/null +++ b/buck_emulator.h @@ -0,0 +1,35 @@ +/* + * buck_emulator.h + * + * Created on: 13. maj 2025 + * Author: Christian L. V. Madsen (OZ1CM) + */ + +#ifndef BUCK_EMULATOR_H_ +#define BUCK_EMULATOR_H_ +#include +#include + +typedef float (*regulate_evt_t)(float Vout); +typedef int (*getResult_evt_t)(float duty, float Vout, float time); + +typedef struct { + + regulate_evt_t regulate_evt; + getResult_evt_t getResult_evt; + float simTime; + + float Vin; // Input voltage + float Vout; // Output voltage + float IL; // Inductor current + float L; // Inductance + float C; // Capacitance + float Rload; // Load resistance + float dt; // Time step (e.g., 25e-6) +} BuckEmulator_t; + +int buck_emulator_Run(BuckEmulator_t *inst); +int buck_emulator_RegGetResultEvt(BuckEmulator_t *inst, getResult_evt_t getRes_evt); +int buck_emulator_RegRegulationEvt(BuckEmulator_t *inst, regulate_evt_t reg_evt); +int buck_emulator_init(BuckEmulator_t *inst, float Vin, float L, float C, float Rload, float dt, float sim_time); +#endif /* BUCK_EMULATOR_H_ */ diff --git a/buck_specs.h b/buck_specs.h new file mode 100644 index 0000000..fbc0cf5 --- /dev/null +++ b/buck_specs.h @@ -0,0 +1,38 @@ +/* + * buck_specs.h + * + * Created on: 13. maj 2025 + * Author: Christian L. V. Madsen (OZ1CM) + */ + +#ifndef BUCK_SPECS_H_ +#define BUCK_SPECS_H_ + +// Voltages +#define VIN 20.0 // Volt +#define VOUT_TARGET 4.2 // Volt + + +// Component Values: +#define L_INDUCTOR 100e-6 // Henry +#define C_CAPACITOR 100e-6 // Farad + + +// Sample time +#define SAMPLE_TIME 25e-6 + + +// Load +#define R_LOAD 100 // Ohm + +// Simulation parameters +#define SIMULATION_TIME 1.0 // Seconds + + +// Plot specific +// OutputFile: +#define BUCK_OUTPUT_FILE "buck_regulation_emul.csv" +#define RUN_CMD "cmd.exe /c python ../plotscript/python_csv_plotter.py %s" + + +#endif /* BUCK_SPECS_H_ */ diff --git a/cm_pid_regulator b/cm_pid_regulator new file mode 160000 index 0000000..c3b9479 --- /dev/null +++ b/cm_pid_regulator @@ -0,0 +1 @@ +Subproject commit c3b9479903f3399910b0036da721ba70ee8df8b9 diff --git a/file_print.c b/file_print.c new file mode 100644 index 0000000..518f339 --- /dev/null +++ b/file_print.c @@ -0,0 +1,44 @@ +/* + * file_print.c + * + * Created on: 13. maj 2025 + * Author: Christian L. V. Madsen (OZ1CM) + */ +#include "file_print.h" +#include +#include +FILE *fpt; + +void cm_file_open(char *fileName, float vtarget){ + + fpt = fopen(fileName,"w+"); + fprintf(fpt,"time_s, Vout, Power, Vtarget = %.2f \n",vtarget); + +} + +void cm_file_close(){ + + fclose(fpt); + +} + +void cm_file_print(float duty,float Rload, float Vout, float time){ + + fprintf(fpt,"%.3f, %.2f, %.2f, %.2f\n", time, Vout, Vout/Rload, duty); + +} + +void showProcentInCmd(float time, float simulate_target_time){ + + float time_left = time / simulate_target_time; + + time_left *= 100; + + printf("\r Progress: %.1f%%", time_left); + + + + +} + + diff --git a/file_print.h b/file_print.h new file mode 100644 index 0000000..949a771 --- /dev/null +++ b/file_print.h @@ -0,0 +1,18 @@ +/* + * file_print.h + * + * Created on: 13. maj 2025 + * Author: Christian L. V. Madsen (OZ1CM) + */ + +#ifndef FILE_PRINT_H_ +#define FILE_PRINT_H_ + + + +void cm_file_open(char *fileName, float vtarget); +void cm_file_close(); +void cm_file_print(float duty,float Rload, float Vout, float time); +void showProcentInCmd(float time, float simulate_target_time); + +#endif /* FILE_PRINT_H_ */ diff --git a/main.c b/main.c index 7258432..008f30a 100644 --- a/main.c +++ b/main.c @@ -5,11 +5,104 @@ * Author: Christian Lind Vie Madsen */ #include +#include "buck_specs.h" +#include "buck_emulator.h" +#include "cm_pid_regulator/cm_pid_regulator.h" +#include "file_print.h" +#include +BuckEmulator_t buck_converter; +cm_pid_regulator_float_t Voltreg; + +float kp = 0.00075; +float ki = 0.00001; +float kd = 0.0; + + +float pid_regulator(float Vout){ + + static uint32_t run_ctr = 0; + static float duty = 0.0; + + if((run_ctr++ % 10) != 0)return duty; + + duty = cm_PIDRegulatorf_Compute(&Voltreg, VOUT_TARGET, Vout, SAMPLE_TIME*10); + + return duty; + +} + +int printResult(float duty, float Vout, float time){ + + showProcentInCmd(time, SIMULATION_TIME); + cm_file_print(duty,R_LOAD,Vout,time); + + return 0; +} int main(void){ + buck_emulator_init(&buck_converter, + VIN,L_INDUCTOR,C_CAPACITOR,R_LOAD,SAMPLE_TIME, SIMULATION_TIME); + buck_emulator_RegRegulationEvt(&buck_converter,(regulate_evt_t)pid_regulator); + buck_emulator_RegGetResultEvt(&buck_converter,(getResult_evt_t)printResult); + + cm_PIDRegulatorf_Init(&Voltreg, kp, ki, kd, 0.0, 1.0); + + cm_file_open(BUCK_OUTPUT_FILE,VOUT_TARGET); + + buck_emulator_Run(&buck_converter); + + cm_file_close(); + + + + // Run Python Plot: + char runcmd_string[255] = { 0 }; + + sprintf(runcmd_string, RUN_CMD, BUCK_OUTPUT_FILE); + + system(runcmd_string); + + return 0; } + +//(regulate_evt_t)pid_regulator + + +/* + * + * BuckConverter buck = { + .Vin = 12.0, + .Vout = 0.0, + .IL = 0.0, + .L = 100e-6, + .C = 100e-6, + .Rload = 10.0, + .dt = 25e-6 + }; + + float duty_cycle = 0.5; + float Vref = 5.0; + float error, previous_error = 0, integral = 0; + float Kp = 0.2, Ki = 1000; + + for (int i = 0; i < 40000; ++i) { + error = Vref - buck.Vout; + integral += error * buck.dt; + + duty_cycle = Kp * error + Ki * integral; + if (duty_cycle > 1.0) duty_cycle = 1.0; + if (duty_cycle < 0.0) duty_cycle = 0.0; + + simulate_step(&buck, duty_cycle); + + // For debug: + if (i % 1000 == 0) + printf("Time: %.3f ms, Vout: %.2f V, IL: %.2f A, Duty: %.2f\n", + i * buck.dt * 1000, buck.Vout, buck.IL, duty_cycle); + } + * */ diff --git a/plotscript/python_csv_plotter.py b/plotscript/python_csv_plotter.py new file mode 100644 index 0000000..6f8b52f --- /dev/null +++ b/plotscript/python_csv_plotter.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +""" +Spyder Editor + +This is a temporary script file. +""" +import sys +import matplotlib.pyplot as plt +import csv +import numpy as np + + + +# Initialize arrays +time_array = [] +temperature_array = [] +power_array = [] +fan_speed_array = [] + +temperature_end_offset = 10 # Optional, adjust as needed + +with open(sys.argv[1], newline='') as csvfile: + datareader = csv.reader(csvfile, delimiter=',', quotechar='|') + + for count, row in enumerate(datareader): + if count == 0: + # Labels row + time_name = row[0] + temp_name = row[1] + power_name = row[2] + plot_title = row[3] + #fan_speed_name = row[4] # Assuming fan speed is at index 5 + else: + time_array.append(float(row[0])) + temperature_array.append(float(row[1])) + power_array.append(float(row[2])) + fan_speed_array.append(float(row[3])) + + # Track min/max for scaling + if count == 1: + min_temp = float(row[1]) + max_temp = float(row[1]) + else: + temp_val = float(row[1]) + if temp_val > max_temp: + max_temp = temp_val + if temp_val < min_temp: + min_temp = temp_val + +# Begin plotting +fig1, ax1 = plt.subplots() +fig1.canvas.manager.set_window_title('DVT-Light Python Plotter V1.1') +fig1.suptitle(plot_title) + +# Plot Vout +color = 'tab:blue' +ax1.set_xlabel('time (s)') +ax1.set_ylabel('Vout', color=color) +ax1.plot(time_array, temperature_array, color=color, label='Vout') +ax1.tick_params(axis='y', labelcolor=color) +ax1.set_ylim(min_temp, max_temp + temperature_end_offset) +ax1.set_yticks(np.arange(min_temp, max_temp + temperature_end_offset, step=10)) +ax1.grid(True) + +# Plot Power (2nd y-axis) +ax2 = ax1.twinx() +color = 'tab:red' +ax2.set_ylabel('Current', color=color) +ax2.plot(time_array, power_array, color=color, label='Current') +ax2.tick_params(axis='y', labelcolor=color) + +# Plot Duty (3rd y-axis) +ax3 = ax1.twinx() +color = 'tab:purple' +ax3.spines["right"].set_position(("axes", 1.15)) # Offset 3rd y-axis +ax3.set_frame_on(True) +ax3.patch.set_visible(False) +for sp in ax3.spines.values(): + sp.set_visible(False) +ax3.spines["right"].set_visible(True) + +ax3.set_ylabel('Duty', color=color) +ax3.plot(time_array, fan_speed_array, color=color, linestyle=':', label='Duty') +ax3.tick_params(axis='y', labelcolor=color) + +# Combine legends +lines, labels = ax1.get_legend_handles_labels() +lines2, labels2 = ax2.get_legend_handles_labels() +lines3, labels3 = ax3.get_legend_handles_labels() +ax1.legend(lines + lines2 + lines3, labels + labels2 + labels3, loc='upper left') + +fig1.tight_layout() +plt.show() +