Firmware Update

Firmware updated with appropriate pinouts for Rev3 boards. Timings also accelerated to
This commit is contained in:
DragonflyPS 2024-01-28 14:31:59 -08:00
parent e205849774
commit 4e116eae4f
19 changed files with 858 additions and 1 deletions

1
Firmware/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

18
Firmware/.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "Pico",
"includePath": [
"${workspaceFolder}/**",
"${env:PICO_SDK_PATH}/**"
],
"defines": [],
"compilerPath": "${env:PICO_INSTALL_PATH}/gcc-arm-none-eabi/bin/arm-none-eabi-gcc.exe",
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "linux-gcc-arm",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}

7
Firmware/.vscode/cmake-kits.json vendored Normal file
View File

@ -0,0 +1,7 @@
[
{
"name": "Pico ARM GCC",
"description": "Pico SDK Toolchain with GCC arm-none-eabi",
"toolchainFile": "${env:PICO_SDK_PATH}/cmake/preload/toolchains/pico_arm_gcc.cmake"
}
]

9
Firmware/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"recommendations": [
"marus25.cortex-debug",
"ms-vscode.cmake-tools",
"ms-vscode.cpptools",
"ms-vscode.cpptools-extension-pack",
"ms-vscode.vscode-serial-monitor"
]
}

58
Firmware/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,58 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Pico Debug (Cortex-Debug)",
"cwd": "${workspaceFolder}",
"executable": "${command:cmake.launchTargetPath}",
"request": "launch",
"type": "cortex-debug",
"servertype": "openocd",
"gdbPath": "arm-none-eabi-gdb",
"device": "RP2040",
"configFiles": [
"interface/cmsis-dap.cfg",
"target/rp2040.cfg"
],
"svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
"runToEntryPoint": "main",
"openOCDLaunchCommands": [
"adapter speed 5000"
]
},
{
"name": "Pico Debug (Cortex-Debug with external OpenOCD)",
"cwd": "${workspaceFolder}",
"executable": "${command:cmake.launchTargetPath}",
"request": "launch",
"type": "cortex-debug",
"servertype": "external",
"gdbTarget": "localhost:3333",
"gdbPath": "arm-none-eabi-gdb",
"device": "RP2040",
"svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
"runToEntryPoint": "main"
},
{
"name": "Pico Debug (C++ Debugger)",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceFolder}",
"program": "${command:cmake.launchTargetPath}",
"MIMode": "gdb",
"miDebuggerPath": "arm-none-eabi-gdb",
"miDebuggerServerAddress": "localhost:3333",
"debugServerPath": "openocd",
"debugServerArgs": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\"",
"serverStarted": "Listening on port .* for gdb connections",
"filterStderr": true,
"stopAtEntry": true,
"hardwareBreakpoints": {
"require": true,
"limit": 4
},
"preLaunchTask": "Flash",
"svdPath": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd"
}
]
}

30
Firmware/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
// These settings tweaks to the cmake plugin will ensure
// that you debug using cortex-debug instead of trying to launch
// a Pico binary on the host
"cmake.statusbar.advanced": {
"debug": {
"visibility": "hidden"
},
"launch": {
"visibility": "hidden"
},
"build": {
"visibility": "hidden"
},
"buildTarget": {
"visibility": "hidden"
}
},
"cmake.buildBeforeRun": true,
"cmake.configureOnOpen": true,
"cmake.configureSettings": {
"CMAKE_MODULE_PATH": "${env:PICO_INSTALL_PATH}/pico-sdk-tools"
},
"cmake.generator": "Ninja",
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"files.associations": {
"cc_charger.h": "c",
"stdlib.h": "c"
}
}

29
Firmware/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,29 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Flash",
"type": "shell",
"command": "openocd",
"args": [
"-f",
"interface/cmsis-dap.cfg",
"-f",
"target/rp2040.cfg",
"-c",
"adapter speed 1000; program {${command:cmake.launchTargetPath}} verify reset exit"
],
"problemMatcher": []
},
{
"label": "Build",
"type": "cmake",
"command": "build",
"problemMatcher": "$gcc",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

219
Firmware/CC_Charger.c Normal file
View File

@ -0,0 +1,219 @@
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/pwm.h"
#include "CC_Charger.h"
// Our assembled programs:
#include "CLK.pio.h"
#include "TIMING.pio.h"
//Pinout Definitions
//CC_Charger Timing:
#define CLK_PIN 6
#define LIMIT_PIN 9
#define BLANKING_PIN 15
//CC_Charger Control:
#define CC_CHARGER_EN_PIN 5
//Ideal Diode Controls:
#define DIODE_ON_PIN 4
//Gate Bias PWM:
#define GATE_BIAS_CLK_PIN 3
//PWM Voltage Sets:
#define CC_I_LIMIT_PIN 13
#define V_CAP_SET_PIN 12
//Telemetry:
#define VSENSE_TRIP_PIN 11
#define CAP_VSENSE_PIN 27
PIO pio;
int sm, sm_clk, sm_limit, sm_blanking;
uint offset_clk, offset_timing;
uint32_t default_clk_period = 133; //3.216usec
uint32_t default_limit_wait_time = 185; //3.024usec
uint32_t default_limit_on_time = 7; //0.136usec
uint32_t default_blanking_wait_time = 185; //0.112usec
uint32_t default_blanking_on_time = 12; //3.032usec
bool caps_charged = false;
void VSENSE_TRIP_callback(void) {
if(gpio_get_irq_event_mask(VSENSE_TRIP_PIN) & GPIO_IRQ_EDGE_RISE) {
gpio_acknowledge_irq(VSENSE_TRIP_PIN, GPIO_IRQ_EDGE_RISE);
//Flag that the caps have been charged
caps_charged = true;
//Turn off the CC_Charger
disable_CC_timing();
}
if(gpio_get_irq_event_mask(VSENSE_TRIP_PIN) & GPIO_IRQ_EDGE_FALL) {
gpio_acknowledge_irq(VSENSE_TRIP_PIN, GPIO_IRQ_EDGE_FALL);
//Flag that the caps are not fully charged
caps_charged = false;
}
}
void disable_CC_timing() {
gpio_put(DIODE_ON_PIN, false); //Turn off ideal diode
gpio_put(CC_CHARGER_EN_PIN, false); //Disable CC Charger gate driver
pio_sm_set_enabled(pio, sm_clk, false); //Disable CC Charger Clock
pio_sm_exec(pio, sm_clk, pio_encode_nop() | pio_encode_sideset_opt(1, 0)); //Set Clock output to 0
pio_sm_exec(pio, sm_clk, pio_encode_irq_set(false, 0));
pio_sm_set_enabled(pio, sm_limit, false); //Disable PWM limit SM
pio_sm_exec(pio, sm_limit, pio_encode_nop() | pio_encode_sideset_opt(1, 1)); //Set PWM limit to 1 (keeps !CLR on Flip Flop low)
pio_sm_set_enabled(pio, sm_blanking, false); //Disable Slope blanking/reset
pio_sm_exec(pio, sm_blanking, pio_encode_nop() | pio_encode_sideset_opt(1, 1)); //Set Slope blanking to (Allows the compensated current limit to decay to 0)
}
void enable_CC_timing() {
//Don't start the charger if the caps are already charged
if(caps_charged == false){
//Reset all PIOs to the start of the program:
pio_sm_exec(pio, sm_clk, pio_encode_jmp(offset_clk ));
pio_sm_exec(pio, sm_blanking, pio_encode_jmp(offset_timing));
pio_sm_exec(pio, sm_limit, pio_encode_jmp(offset_timing));
//Renable PIOs
pio_sm_set_enabled(pio, sm_limit, true);
pio_sm_set_enabled(pio, sm_blanking, true);
pio_sm_set_enabled(pio, sm_clk, true);
gpio_put(CC_CHARGER_EN_PIN, true); //Enable the CC Charger gate driver
gpio_put(DIODE_ON_PIN, true); //Turn on the ideal diode
}
}
void CLK_set_period(uint32_t period) {
pio_sm_put_blocking(pio, sm_clk, period); //Load new period into FIFO
pio_sm_exec(pio, sm_clk, pio_encode_pull(false, false)); //Pull new period into OSR
pio_sm_exec(pio, sm_clk, pio_encode_out(pio_isr, 32)); //Shift new period from OSR to ISR
pio_sm_put_blocking(pio, sm_clk, period/2); //Load new on time into FIFO
pio_sm_exec(pio, sm_clk, pio_encode_pull(false, false)); //Pull new on time into OSR
pio_sm_exec(pio, sm_clk, pio_encode_out(pio_x, 32)); //Shift new on time into X register
}
void SM_set_timing(PIO pio, uint sm, uint32_t wait_time, uint32_t on_time, bool enabled) {
pio_set_sm_mask_enabled(pio, sm_clk | sm_blanking | sm_limit, false);
// pio_sm_set_enabled(pio, sm, false); //Temporarily freeze SM
pio_sm_put_blocking(pio, sm, wait_time); //Load new wait time into FIFO
pio_sm_exec(pio, sm, pio_encode_pull(false, false)); //Pull new wait time into OSR
pio_sm_exec(pio, sm, pio_encode_out(pio_isr, 32)); //Shift new wait time into ISR
pio_sm_put_blocking(pio, sm, on_time); //Load new on time into FIFO
pio_sm_exec(pio, sm, pio_encode_pull(false, false)); //Pull new wait time into OSR
// pio_sm_set_enabled(pio, sm, enabled); //Renable SM
pio_set_sm_mask_enabled(pio, sm_clk | sm_blanking | sm_limit, enabled);
}
void LIMIT_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled) {
SM_set_timing(pio, sm_limit, wait_time, on_time, enabled); //Update timing registers in SM
}
void BLANKING_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled) {
SM_set_timing(pio, sm_blanking, wait_time, on_time, enabled); //Update timing registers in SM
}
void CC_Charger_init(int charger_current, int cap_voltage) {
//Select a PIO bank
pio = pio0;
//Load programs into PIO memory
offset_clk = pio_add_program(pio, &CLK_program);
offset_timing = pio_add_program(pio, &TIMING_program);
//Select state machines for each output
sm_clk = pio_claim_unused_sm(pio, true);
sm_limit = pio_claim_unused_sm(pio, true);
sm_blanking = pio_claim_unused_sm(pio, true);
//Initialize each state machine
CLK_program_init (pio, sm_clk, offset_clk, CLK_PIN );
TIMING_program_init (pio, sm_limit, offset_timing, LIMIT_PIN );
TIMING_program_init (pio, sm_blanking, offset_timing, BLANKING_PIN );
//Load in default timing
CLK_set_period (default_clk_period);
LIMIT_set_timing (default_limit_wait_time, default_limit_on_time, false);
BLANKING_set_timing (default_blanking_wait_time, default_blanking_on_time, false);
//Setup VSENSE_TRIP pin
gpio_init(VSENSE_TRIP_PIN);
gpio_set_dir(VSENSE_TRIP_PIN, GPIO_IN);
gpio_set_pulls(VSENSE_TRIP_PIN, false, true);
gpio_set_irq_enabled(VSENSE_TRIP_PIN, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
gpio_add_raw_irq_handler(VSENSE_TRIP_PIN, &VSENSE_TRIP_callback);
//Setup CC_CHARGER_EN pin
gpio_init(CC_CHARGER_EN_PIN);
gpio_set_dir(CC_CHARGER_EN_PIN, GPIO_OUT);
gpio_put(CC_CHARGER_EN_PIN, false);
//Setup PWM -> Analog pins
gpio_set_function(CC_I_LIMIT_PIN, GPIO_FUNC_PWM);
gpio_set_function(V_CAP_SET_PIN, GPIO_FUNC_PWM);
gpio_set_function(3, GPIO_FUNC_PWM);
uint v_i_set_pwm_slice = pwm_gpio_to_slice_num(V_CAP_SET_PIN);
pwm_set_wrap(v_i_set_pwm_slice, 1000);
pwm_set_chan_level(v_i_set_pwm_slice, pwm_gpio_to_channel(CC_I_LIMIT_PIN), charger_current);
pwm_set_chan_level(v_i_set_pwm_slice, pwm_gpio_to_channel(V_CAP_SET_PIN), cap_voltage);
pwm_set_enabled(v_i_set_pwm_slice, true);
//Setup Ideal Diode driver
gpio_init(DIODE_ON_PIN);
gpio_set_dir(DIODE_ON_PIN, GPIO_OUT);
gpio_put(DIODE_ON_PIN, false);
//Setup Gate Bias Charge Pump
gpio_set_function(GATE_BIAS_CLK_PIN, GPIO_FUNC_PWM);
uint bias_pwm_slice_num = pwm_gpio_to_slice_num(GATE_BIAS_CLK_PIN);
pwm_set_wrap(bias_pwm_slice_num, 2500);
pwm_set_chan_level(bias_pwm_slice_num, pwm_gpio_to_channel(GATE_BIAS_CLK_PIN), 1250);
pwm_set_enabled(bias_pwm_slice_num, true);
}

50
Firmware/CC_Charger.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef CC_CHARGER_H_INCLUDED
#define CC_CHARGER_H_INCLUDED
#include "pico/stdlib.h"
extern bool caps_charged;
/*! \brief Disable Constant Current Charger timing outputs, effectively turns off CC charger
\ingroup CC_Charger
*/
void disable_CC_timing();
/*! \brief Enable Constant Current Charger timing outputs, effectively turns on CC charger
\ingroup CC_Charger
*/
void enable_CC_timing();
/*! \brief Sets the CC charger clock period, indirectly sets the switching frequency of the CC charger
\ingroup CC_Charger
\param period Clock period = 3 * (1 + period) / Sys_clock (default 125MHz)
*/
void CLK_set_period(uint32_t period);
/*! \brief Sets the timing for the PWM limiting output
\ingroup CC_Charger
\param wait_time output low time = 2 * (1 + wait_time) / Sys_clock (default 125MHz)
\param on_time output high time = (1 + 2 * (1 * on_time)) / Sys_clock (default 125MHz)
*/
void LIMIT_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled);
/*! \brief Sets the timing for the PWM limiting output
\ingroup CC_Charger
\param wait_time output low time = 2 * (1 + wait_time) / Sys_clock (default 125MHz)
\param on_time output high time = (1 + 2 * (1 * on_time)) / Sys_clock (default 125MHz)
*/
void BLANKING_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled);
/*! \brief Setup the CC charger
\ingroup CC_Charger
*/
void CC_Charger_init(int charger_current, int cap_voltage);
/*! \brief Whether or not the output caps are at the set voltage
\ingroup CC_charger
*/
#endif

36
Firmware/CLK.pio Normal file
View File

@ -0,0 +1,36 @@
.program CLK
.side_set 1 opt
irq clear 0 side 1 ; Set IRQ for other signals to reference off of
mov y, isr ; ISR contains PWM period. Y used as counter.
irq 0
countloop:
jmp x!=y noset ; Set pin high if X == Y, keep the two paths length matched
jmp skip side 0
noset:
nop ; Single dummy cycle to keep the two paths the same length
skip:
jmp y-- countloop ; Loop until Y hits 0, then pull a restart the counter
% c-sdk {
static inline void CLK_program_init(PIO pio, uint sm, uint offset, uint pin) {
pio_sm_config c = CLK_program_get_default_config(offset);
// Map the state machine's OUT pin group to one pin, namely the `pin`
// parameter to this function.
sm_config_set_out_pins(&c, pin, 1);
// Set this pin's GPIO function (connect PIO to the pad)
pio_gpio_init(pio, pin);
// Set the pin direction to output at the PIO
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
sm_config_set_sideset_pins(&c, pin);
// Load our configuration, and jump to the start of the program
pio_sm_init(pio, sm, offset, &c);
// Set the state machine running
//pio_sm_set_enabled(pio, sm, true);
}
%}

31
Firmware/CMakeLists.txt Normal file
View File

@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.13)
include(pico_sdk_import.cmake)
project(main)
pico_sdk_init()
add_executable(main)
pico_generate_pio_header(main ${CMAKE_CURRENT_LIST_DIR}/CLK.pio)
pico_generate_pio_header(main ${CMAKE_CURRENT_LIST_DIR}/TIMING.pio)
target_sources( main
PRIVATE main.c
CC_Charger.c
pulse_generator.c)
# pull in common dependencies
target_link_libraries( main
pico_stdlib
hardware_pio
hardware_adc
hardware_pwm
pico_time)
pico_enable_stdio_uart(main 1)
pico_enable_stdio_usb(main 0)
# create map/bin/hex file etc.
pico_add_extra_outputs(main)

40
Firmware/TIMING.pio Normal file
View File

@ -0,0 +1,40 @@
.program TIMING
.side_set 1 opt
offStart:
wait 0 irq 0 side 0 ; Wait for clock rising edge
mov y, isr ; Wait time stored in ISR, Y register used as counter
waitloop:
jmp !y onStart ; When the timer runs out turn on the output pin and begin on time loop
jmp y-- waitloop ; If the off time hasn't elapsed, keep looping
onStart:
mov y, osr side 1 ; On time stored in OSR, Y register used as a counter
onloop:
jmp !y offStart ; When the timer runs out turn off the output pin and wait for clock edge
jmp y-- onloop ; If the on time hasn't yet elapsed, keep looping
% c-sdk {
static inline void TIMING_program_init(PIO pio, uint sm, uint offset, uint pin) {
pio_sm_config c = TIMING_program_get_default_config(offset);
// Map the state machine's OUT pin group to one pin, namely the `pin`
// parameter to this function.
sm_config_set_out_pins(&c, pin, 1);
// Set this pin's GPIO function (connect PIO to the pad)
pio_gpio_init(pio, pin);
// Set the pin direction to output at the PIO
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
sm_config_set_sideset_pins(&c, pin);
// Load our configuration, and jump to the start of the program
pio_sm_init(pio, sm, offset, &c);
// Set the state machine running
//pio_sm_set_enabled(pio, sm, true);
}
%}

87
Firmware/main.c Normal file
View File

@ -0,0 +1,87 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/time.h"
#include "hardware/pwm.h"
#include "CC_Charger.h"
#include "pulse_generator.h"
//Pinout definitions
#define CUT_nEN_PIN 0
//OUTPUT PULSE PARAMETERS (times in usecs)
#define OUTPUT_ON_TIME 20
#define OUTPUT_OFF_TIME 80
#define ISO_PULSE false
#define CAP_VOLTAGE_SETPOINT 65 //Don't set higher than 65
//CC Charger Parameters (don't change unless you know what you're doing)
#define CHARGER_CURRENT 850
//Math stuff DO NOT EDIT
#define CAP_VOLTAGE_PWM_LEVEL CAP_VOLTAGE_SETPOINT * 303 / 48
bool tripped = false;
void cut_on_off_irq(void) {
if(gpio_get_irq_event_mask(CUT_nEN_PIN) & GPIO_IRQ_EDGE_FALL) {
gpio_acknowledge_irq(CUT_nEN_PIN, GPIO_IRQ_EDGE_FALL);
cutting_enabled = true;
begin_output_pulses(OUTPUT_ON_TIME, OUTPUT_OFF_TIME, ISO_PULSE);
}
if(gpio_get_irq_event_mask(CUT_nEN_PIN) & GPIO_IRQ_EDGE_RISE) {
gpio_acknowledge_irq(CUT_nEN_PIN, GPIO_IRQ_EDGE_RISE);
cutting_enabled = false;
}
}
void default_gpio_callback(uint gpio, uint32_t event_mask) {
gpio_acknowledge_irq(gpio, event_mask);
return;
}
int main() {
// stdio_init_all(); //Start the Serial console
// gpio_init(CUT_nEN_PIN);
// gpio_set_dir(CUT_nEN_PIN, GPIO_IN);
// gpio_set_pulls(cut_NEN, true, false);
sleep_ms(1000);
// while(gpio_get(23)) {}
CC_Charger_init(CHARGER_CURRENT, CAP_VOLTAGE_PWM_LEVEL); //Setup the CC Charger Outputs
pulse_generator_init(10);
gpio_init(CUT_nEN_PIN);
gpio_set_dir(CUT_nEN_PIN, GPIO_IN);
gpio_set_pulls(CUT_nEN_PIN, true, false);
gpio_init(1);
gpio_set_dir(1, GPIO_OUT);
gpio_put(1, false);
irq_set_enabled(IO_IRQ_BANK0, true);
sleep_ms(1000);
gpio_set_irq_enabled(CUT_nEN_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
gpio_add_raw_irq_handler(CUT_nEN_PIN, &cut_on_off_irq);
while (true) {
// sleep_us(10);
// gpio_put(3, true);
// sleep_us(10);
// gpio_put(3, false);
}
}

View File

@ -0,0 +1,73 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
endif ()
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})

149
Firmware/pulse_generator.c Normal file
View File

@ -0,0 +1,149 @@
#include "pico/stdlib.h"
#include "pulse_generator.h"
#include "CC_Charger.h"
#include "hardware/pwm.h"
#define OUTPUT_EN_PIN 2
#define OUTPUT_CURRENT_TRIP_PIN 10
#define SPARK_THRESHOLD_PWM_PIN 14
bool cutting_enabled = true;
bool off_time_insufficient = false;
//Enum to keep track of where we are in the pulse sequence
enum pulse_state{ WAITING_FOR_IGNITION,
SPARK_ON,
SPARK_OFF};
enum pulse_state output_state = SPARK_OFF;
//Pulse definition waveforms
uint32_t pulse_on_time = 0;
uint32_t pulse_off_time = 0;
bool iso_pulse_mode = false;
uint32_t pulse_timeout_time = 0; //time in us
//Prototype functions
int64_t begin_off_time(alarm_id_t id, void *user_data);
//Set the CC timing to the standard charging parameters
int64_t change_CC_timing(alarm_id_t id, void *user_data){
LIMIT_set_timing(185, 7, true);
return 0;
}
void output_current_trip_irq(void) {
if (gpio_get_irq_event_mask(OUTPUT_CURRENT_TRIP_PIN) & GPIO_IRQ_EDGE_RISE) {
gpio_acknowledge_irq(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE);
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, false); //Turn off the interrupt on the ignition sense
output_state = SPARK_ON; //Update the pulse generator state
add_alarm_in_us(pulse_on_time, begin_off_time, NULL, true); //Set alarm to turn off the pulse after the pulse on time
}
}
int64_t begin_on_time(alarm_id_t id, void *user_data){
disable_CC_timing(); //Turn off the CC Charger
if(cutting_enabled) { //Check that cutting is still enabled
if(iso_pulse_mode) { //Check pulse mode is iso-pulse
output_state = WAITING_FOR_IGNITION; //Update pulse generator state
gpio_put(OUTPUT_EN_PIN, true); //Turn on output FET
add_alarm_in_us(pulse_timeout_time, begin_off_time, NULL, true); //Set the alarm in case of pulse timeout
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, true);//Configure detection of the spark
gpio_add_raw_irq_handler(OUTPUT_CURRENT_TRIP_PIN, &output_current_trip_irq);
} else { //If pulse mode is iso-tonic
output_state = SPARK_ON; //Update pulse generator state
gpio_put(OUTPUT_EN_PIN, true); //Turn on output FET
add_alarm_in_us(pulse_on_time-3, begin_off_time, NULL, true); //Set alarm for the off transition
}
}
return 0;
}
int64_t begin_off_time(alarm_id_t id, void *user_data){
if(output_state == WAITING_FOR_IGNITION || iso_pulse_mode == false) { //Spark has timed out or if iso pulse is off, restart pulse cycle
gpio_put(OUTPUT_EN_PIN, false); //Turn off output MOSFET
output_state = SPARK_OFF; //Update pulse generator state
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, false); //Disable the ignition sense irq
LIMIT_set_timing(97, 7, false); //Limit CC Charger PWM duty cycle to avoid inrush (was 97)
enable_CC_timing(); //Start CC Charger
add_alarm_in_us(15, change_CC_timing, NULL, true); //Setup the alarm to correct CC charger timing
add_alarm_in_us(pulse_off_time-11, begin_on_time, NULL, true); //Setup the alarm to turn on the output MOSFET after the off time
} else if(output_state == SPARK_ON && iso_pulse_mode == true) { //Spark is already ignited, ignore this timer callback
//Do nothing
}
return 0;
}
void first_begin_off_time() {
LIMIT_set_timing(97, 7, false); //Set the CC Charger PWM max duty cycle lower to prevent inrush
enable_CC_timing(); //Start the CC Charger
add_alarm_in_us(15-4, change_CC_timing, NULL, true); //Setup the alarm to correct CC charger timing
add_alarm_in_us(pulse_off_time-8, begin_on_time, NULL, true); //Setup the alarm to turn on the output MOSFET after the off time
}
void begin_output_pulses(uint32_t on_time, uint32_t off_time, bool iso_pulse) {
//Load in the pulse parameters
pulse_on_time = on_time;
pulse_off_time = off_time;
pulse_timeout_time = pulse_on_time / 2;
iso_pulse_mode = iso_pulse;
//Update pulse state based on pulse mode
if(iso_pulse_mode) {
output_state = WAITING_FOR_IGNITION;
} else {
output_state = SPARK_OFF;
}
first_begin_off_time();
}
void pulse_generator_init(uint32_t trip_current) {
gpio_init(OUTPUT_EN_PIN);
gpio_set_dir(OUTPUT_EN_PIN, GPIO_OUT);
gpio_init(OUTPUT_CURRENT_TRIP_PIN);
gpio_set_dir(OUTPUT_CURRENT_TRIP_PIN, GPIO_IN);
}

View File

@ -0,0 +1,19 @@
#ifndef PULSE_GENERATOR_H_INCLUDED
#define PULSE_GENERATOR_H_INCLUDED
#include "pico/stdlib.h"
extern bool cutting_enabled;
extern bool off_time_insufficient;
/*! \brief Start the EDM machine, ie, begin cutting
\ingroup pulse_generator
*/
void begin_output_pulses(uint32_t on_time, uint32_t off_time, bool iso_pulse);
/*! \brief Setup pins/dirs for the pulse generator
\ingroup pulse_generator
*/
void pulse_generator_init(uint32_t trip_current);
#endif

View File

@ -0,0 +1 @@
POWERCORE-V2.0_MOTHERBOARD-backups/

View File

@ -63,7 +63,7 @@
36,
40
],
"visible_layers": "8081100_ffffffff",
"visible_layers": "8081100_ffffffe0",
"zone_display_mode": 0
},
"meta": {