diff --git a/.cproject b/.cproject
index 41efb61..a069fcc 100644
--- a/.cproject
+++ b/.cproject
@@ -14,21 +14,22 @@
-
+
-
-
+
+
-
+
-
-
+
+
+
-
-
+
+
@@ -60,21 +61,21 @@
-
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
@@ -107,4 +108,6 @@
+
+
\ 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()
+