From 4e116eae4f8bd213f130087512b36e1a72d49255 Mon Sep 17 00:00:00 2001 From: DragonflyPS Date: Sun, 28 Jan 2024 14:31:59 -0800 Subject: [PATCH] Firmware Update Firmware updated with appropriate pinouts for Rev3 boards. Timings also accelerated to --- Firmware/.gitignore | 1 + Firmware/.vscode/c_cpp_properties.json | 18 ++ Firmware/.vscode/cmake-kits.json | 7 + Firmware/.vscode/extensions.json | 9 + Firmware/.vscode/launch.json | 58 +++++ Firmware/.vscode/settings.json | 30 +++ Firmware/.vscode/tasks.json | 29 +++ Firmware/CC_Charger.c | 219 ++++++++++++++++++ Firmware/CC_Charger.h | 50 ++++ Firmware/CLK.pio | 36 +++ Firmware/CMakeLists.txt | 31 +++ Firmware/TIMING.pio | 40 ++++ Firmware/main.c | 87 +++++++ Firmware/pico_sdk_import.cmake | 73 ++++++ Firmware/pulse_generator.c | 149 ++++++++++++ Firmware/pulse_generator.h | 19 ++ Powercore-V2.0 Motherboard/KiCAD/.gitignore | 1 + .../POWERCORE-V2.0_MOTHERBOARD-F_Paste.zip | Bin 0 -> 6544 bytes .../Powercore-V2.0_Motherboard.kicad_prl | 2 +- 19 files changed, 858 insertions(+), 1 deletion(-) create mode 100644 Firmware/.gitignore create mode 100644 Firmware/.vscode/c_cpp_properties.json create mode 100644 Firmware/.vscode/cmake-kits.json create mode 100644 Firmware/.vscode/extensions.json create mode 100644 Firmware/.vscode/launch.json create mode 100644 Firmware/.vscode/settings.json create mode 100644 Firmware/.vscode/tasks.json create mode 100644 Firmware/CC_Charger.c create mode 100644 Firmware/CC_Charger.h create mode 100644 Firmware/CLK.pio create mode 100644 Firmware/CMakeLists.txt create mode 100644 Firmware/TIMING.pio create mode 100644 Firmware/main.c create mode 100644 Firmware/pico_sdk_import.cmake create mode 100644 Firmware/pulse_generator.c create mode 100644 Firmware/pulse_generator.h create mode 100644 Powercore-V2.0 Motherboard/KiCAD/.gitignore create mode 100644 Powercore-V2.0 Motherboard/KiCAD/Gerbers/POWERCORE-V2.0_MOTHERBOARD-F_Paste.zip diff --git a/Firmware/.gitignore b/Firmware/.gitignore new file mode 100644 index 0000000..d163863 --- /dev/null +++ b/Firmware/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/Firmware/.vscode/c_cpp_properties.json b/Firmware/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..ada839e --- /dev/null +++ b/Firmware/.vscode/c_cpp_properties.json @@ -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 +} diff --git a/Firmware/.vscode/cmake-kits.json b/Firmware/.vscode/cmake-kits.json new file mode 100644 index 0000000..4b24eb7 --- /dev/null +++ b/Firmware/.vscode/cmake-kits.json @@ -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" + } +] diff --git a/Firmware/.vscode/extensions.json b/Firmware/.vscode/extensions.json new file mode 100644 index 0000000..03ba0af --- /dev/null +++ b/Firmware/.vscode/extensions.json @@ -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" + ] +} diff --git a/Firmware/.vscode/launch.json b/Firmware/.vscode/launch.json new file mode 100644 index 0000000..c370c53 --- /dev/null +++ b/Firmware/.vscode/launch.json @@ -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" + } + ] +} diff --git a/Firmware/.vscode/settings.json b/Firmware/.vscode/settings.json new file mode 100644 index 0000000..c11e238 --- /dev/null +++ b/Firmware/.vscode/settings.json @@ -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" + } +} diff --git a/Firmware/.vscode/tasks.json b/Firmware/.vscode/tasks.json new file mode 100644 index 0000000..a437c2f --- /dev/null +++ b/Firmware/.vscode/tasks.json @@ -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 + } + } + ] +} diff --git a/Firmware/CC_Charger.c b/Firmware/CC_Charger.c new file mode 100644 index 0000000..2713cbd --- /dev/null +++ b/Firmware/CC_Charger.c @@ -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); +} \ No newline at end of file diff --git a/Firmware/CC_Charger.h b/Firmware/CC_Charger.h new file mode 100644 index 0000000..1d5dc65 --- /dev/null +++ b/Firmware/CC_Charger.h @@ -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 \ No newline at end of file diff --git a/Firmware/CLK.pio b/Firmware/CLK.pio new file mode 100644 index 0000000..e07b67e --- /dev/null +++ b/Firmware/CLK.pio @@ -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); +} +%} \ No newline at end of file diff --git a/Firmware/CMakeLists.txt b/Firmware/CMakeLists.txt new file mode 100644 index 0000000..2102235 --- /dev/null +++ b/Firmware/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/Firmware/TIMING.pio b/Firmware/TIMING.pio new file mode 100644 index 0000000..61bf072 --- /dev/null +++ b/Firmware/TIMING.pio @@ -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); +} +%} \ No newline at end of file diff --git a/Firmware/main.c b/Firmware/main.c new file mode 100644 index 0000000..59a35ec --- /dev/null +++ b/Firmware/main.c @@ -0,0 +1,87 @@ +#include +#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); + } +} \ No newline at end of file diff --git a/Firmware/pico_sdk_import.cmake b/Firmware/pico_sdk_import.cmake new file mode 100644 index 0000000..65f8a6f --- /dev/null +++ b/Firmware/pico_sdk_import.cmake @@ -0,0 +1,73 @@ +# This is a copy of /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}) diff --git a/Firmware/pulse_generator.c b/Firmware/pulse_generator.c new file mode 100644 index 0000000..2c265fd --- /dev/null +++ b/Firmware/pulse_generator.c @@ -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); + +} \ No newline at end of file diff --git a/Firmware/pulse_generator.h b/Firmware/pulse_generator.h new file mode 100644 index 0000000..d6fac5f --- /dev/null +++ b/Firmware/pulse_generator.h @@ -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 \ No newline at end of file diff --git a/Powercore-V2.0 Motherboard/KiCAD/.gitignore b/Powercore-V2.0 Motherboard/KiCAD/.gitignore new file mode 100644 index 0000000..b406b04 --- /dev/null +++ b/Powercore-V2.0 Motherboard/KiCAD/.gitignore @@ -0,0 +1 @@ +POWERCORE-V2.0_MOTHERBOARD-backups/ \ No newline at end of file diff --git a/Powercore-V2.0 Motherboard/KiCAD/Gerbers/POWERCORE-V2.0_MOTHERBOARD-F_Paste.zip b/Powercore-V2.0 Motherboard/KiCAD/Gerbers/POWERCORE-V2.0_MOTHERBOARD-F_Paste.zip new file mode 100644 index 0000000000000000000000000000000000000000..e22de00d0d4646bd0e25dd97b7b146415490f208 GIT binary patch literal 6544 zcma)>WlS7wxTb-k1I1m7``~488)SgO;8LWxv=lE6?EnP^D^R4gKyi01P;7vK;uI;` zfx+EfHs6=sJ-a74XZQW{CU0`zd9LLBbLD|*J;A2Lz`(%A$aDpox_sOFkw=7q;Vh1U z!G(c=0o658)mPEgR~0lC1qxfg&^6Rh)mPS4(gzDFTSINUeH?&JwjQbGZte_7vInd0 zk1Oy=#pL9kj?OEs-HbYlsRW!kw*p-p&TJ;?G-s%f#pSHuMTnDoqVZD>klfh*=;+?? z=rFT2xyaqMdl>!lPf(E5a$?koXLDy*TUgj#omAXV=V7*c(@^Zf*W2SE{hTDR8wAVa zQ5{i0DDD0G^9>M?&c;@C3l8`Dtl+R#%E51&O%6j^FkU<|yC*6j+TBCtI)fiJPJ+*M z->E&E-;A{7j0%MXpYD16{0weSHy=o~hgD8nQr-z8ch2j!+e2w zckI7ZYn%@J?x^~9`9># z-toL+PR?5Lvg!=DpBG#kERXdyh0a$v(QKw4K6nPmx8Gdvw?%}|lOV^UJX;nPnJ-8X z$ffY#w}bVw>9=E-3tE3zuTqE(Y`h;=(4gQsrZ5KLgb1AF0}_+~$wMj*(;aQ`HYVi* zqs?=Hs~S>-GBKfqz*&tjqKDXIXm^D|W3iJ3J9BgHoy;2mu29I`jZK(Bu=L(R`$W_T z!lV9?O_yW{A$q>iQ zwfVG>+calFg!Dx{(G*c+-1O{k=}hl1WFC?I=WIMf1@ou8A* z<#(SHe~+suf+m5p?8+KGp>n_2hxiQwhH+0J+@-jV5DV(+was*ZG)`)i z0Awmz!-{M$$mUxmpL1%h0aU4uV=i4>VQ$dD2kZzbW5B9J``Ox@x4hy>K3h-DjybdS zAFvl9-wk+i5uu#9rhNKOVmFO!M3JF-ea(xYkw1o`ui(;8WwJNJK4A*NCtoP#SD?*K z$Ay#3d)!dR7Qk;{30(gI;CO9P9x^`=X#1s~j&(s}C5bwTF$o3|Ez_^2HY(cetT6Be z_~PC@!bS5Mxgsq21tn@{DhS;1UCda&yLyPHPgW*a8URap5dfWd(P^Fyv+_7k0q)^4 zQBCNm49NbphSIG8t|iiLl}}ZnqWJcmc!OxBw6UxGsgf^AfDt~=j_&aOWY!JrAI>uXtOk_Ff;_Ub9a zT^Z=m?cpj~2-)P^vJ0?$Jv~a5<$MY<-4Vw?U za)xvjz?d1^GFVYVMXY0z2+-T>^G_##+Xkn<*B#ukH{D1GzPK~cI2+IQR7bJqyim4)lVXu(E!F9>WS zkRA=Bens3`^b6gm%&ruP7N9deJYT2U1JViRVXx(S_5PPZ;&Tv+d^15oC+?c3U$-3b zi{+LSe-INly8dAR$==cP7EkjCTe0XKB96yHSkTboKx*Q9VTNxO`k(bakD$sDRl3eR zMZ(7h*2TQ8<19qjO@;@k#JtwyETq^?eAks&OozVSw zqXzt%G~~E8N%zA?4Y>U)z5{?vT{ZY>0$R=o%!V-DDn<^`wF@;L4+0K{+=4rLZoR%{ z@PYo#MCNI%=XJW5PaIy`rc$lrs;FkBtH3R zYzGUNsz$5Z2LM4b>Ul*039+ehl6_Cnf4ja00IY_x8eWf!`YuRBAe#vJFe^ira-+ff z^xUt01C<7cqrn_`uGzoN&3h?m5XA$1<>X1WlgRLBYcBOd|%vR=J2x zH8sVzmnlv0+FY4x{R_m3yM*>TnJ1#!%Iv=p^>||J6X&WY{&Cf2d#Yx8L6(0ELs1(C zD;BXpAc0(rNZn6oyl3v(*vg?nL{O$uC^F zjT}qmv{m}jgr!WSS1mDInl-zjr2HQC5?*A$_nhiG&-Mz|+^od++(i8?rC&nwltd8^;bO;Rg&)h<&zGP>FL(3T*Tg%pf6) ze%Q#WS=ViER3j8T#rrh*HJ-J%I{{8HzOTSpyiu@sbsfxO`%`XsBNVGu*Lc>vr=61= zKs+6h@ln||b_F~$4Kbj1(e6c4@D02odsj}0h0XcR_CulH5NWbMh-GH%=LE1)4+vz?azU!2NONp16d0<=S^{{Xg z9dUja`l5q+UJ1+Q8N?~gTSeE>;eWUM0dqS4&E0$>GbU*>5eNUa0!%8OlqgvY6YY9ra>O@&elPT_9)w zLrlq+8qwfq&f?wf8=Z~B9z zp8J3%E_bQL(5SmqM+>k_vLe5=f4T&9&#(F0fR+%NtzWUALbWxSxLiL3pYF!P}HOcm*BD_>z!xhru zwAJ!7N?|a0;f*oXXpI>9CduIZD2eYmoRnCU6&G1iJ{uj4GSt#``ZPAsbH5{qbU3WZ zq}4_?wcz=?^>Medz)qq@CfU@2QbiYrg1Afi0$c0$o;sGFRB4lNLaTVbLaLr(n$q69 z#GWr0KSh#&`dO{hjwe1$&)j6O;=#+^Uou#Shw)jR)Htx{j~@&TU?XuFLw#Uz5=Msk zRP9;%`RC~#lTA*H(l=Whs;HFt- zOncOGUB;#@)3QFW(7u@5>AH<|2+8pAt>HFQ#NA^E5>$>M3vD3W&nQvTaFccpOy_$m zEo2A!JM_skLq%H2Pw~LGRiz+d^uB@@}au_QK~zRflJUU0|IZ+g4cS7Lh>EFSi-kdsMLZCrgD_0S@-#KgSJBA?xHkPvd4 z*p}WF5)=}2Iv(bB4zJicRd`tO{d02ir|s#|!Blgca4m-qqz~^`*sC=>NLufmqDJfH zjsKNySkMi@S;y_V>;1{njq9~g6We3x?E&I%^^8JCQ0;*^q*uK((n6E#O25lGEv?&n z&Wdl;bS&oX5A*Hc$IPA3&bC8qW@6<1(i7ppH`S8!llKoroy*InJ&^~$&#MpQ&#OCR z7m1ymtNju^;3QFFrxLSKx^3vC?Uz9z{_QeL_wpqH7d!V~X&7>wl;y%U{Mru^CGTqk ze8XIOH5*61hT>_5x;@OYkc_N69Qf>9x}C0W)L#38mJfAC{H&P|bVly)FY_UrW1)W+ zgI|B!{d!ns{cv?UEfjxxe>uWj@Z!i@>^k84>BZ7Q^OGbe_bM4(XTVJCZuxmsSXFhV zq{7cfVVj&=^!8A#`+;9G5@C0`eQ+%99B}+De-Y zbbp5#uA0+vAL#Ea&vJN>_516RowxUu&|TXjt_)b~wvU z?viWt%24f(pEAomdeD4Au=h=+5Mvzd2IqbV7HGsPnxU1{?E@zg*FRPFaC~!Dq!6-y z8wJ2r)5k@#Lb%{M*|BVXYk9ruV>?n4XCy)CG?wavt*QK@1b6jG{4P->Kr}9^WwUGF zI*&aUS)H$z$=my91sr5v!!2nQvfZ6v#X-YS+*7I60 zS2GGP9$2od)vGyfACm+ttbaL1pXE-J=6tQ4ZX}yZZ0_YC*B_N&OL?NiGr%zwBU}oW zj*PSYzV=y}CnW>u%QGLHX3v_QrmK|^keBL3B3SAxvv$%loh6BX-s-@=y;y6*U+5zs zKAIRfzwPr~7@`O3eio=Eh<}XX>l}(fd~aF7xc|X!zEDcgytQ zUwNXwVRn9c;-J^bp8ZZ0%rK$vW%g;i%iv^!id*ypsabY-PyeeyYJomERo(XEc6yiD zTxYaBgmjj4Kx0%0%o^X?H)W$|%F8UCx;guMl7Bur&0l0<=lZuqqCHEsHia@qH; z&la&tM+&8?Ah1&{|B6kCSrLlBgqSG@F3d53NiF}Z80ZZng}x1}CGk1}&rRZvh$3K= z8P0j^iR5|b^UE1Yf`6EjjMrDG2})dH1^5`^-L z5a?-q!Io{LZJ0iirm!EH{=ui_k`U|FXzb}LWf!Y`v`3fnKGw_8_*hK4=mz%FwjaBk zs*nyC?O3Z?F$2inDh1=wcYWFVE{=4|9K0iE-Yq@*!$wij5eMlKi#;Q^a$<8V25vz5 zIZ&mlddJg?njd25W_gSTC>o+C870}eM>s8vPO-hK2f#6+DesG^!<*=>obn>&5!mRj zB1#tZ1!~ZjPZf~htW$y+jnUq;G3I|KJ*zLOo6>dW8u37o$Cgxnw;d6Z%b)n&+DV- zU9Y6L3_`lC*6Du(TK)t0 zYI0&F>T^6Bn7>)=hZWB2mIW?#fB4%*8?c)G#)bYa^TbQFQUm!NL-X{b z1nE-42PCSVGiDSvtFO`eao{vbhWBA3% z6pC;AassD9Du=$JneE8^Bpq`l!d>5Ia9CZ3n005rVXql-3{E;D1 zXbVyn85fO#o%gSqR_v@91H;qFA8mf+5YWuHSKDXVOJ}}Qp5gRgW@y-8YxS&^EbvDn zWuO7>T^eab#+kz_$IIfqSF%Op%PvQ%T~Y0^H$9;E?yM^KZ(6{lOI+J+n*Qqw8H~?m z@x-`j9$o_JgI?jDrwVgK_1I#1EU<}W>Z62MUeOLUC0F*+OA&M^Rs=D39swUpk+Jr+tzyYtZmVYa8n=YV;**oNsCCh{430U)-9d7x~e@9=c>_lVNq zRW_+WRn2>?$~?d+Q6&r)#O+)G>_Ug&&t@}RHGhid(*gH3%2?9dxh^hA4M*}-Y5FgZ zW657==f+nns; zTLi~)UY+4Kx&~u9xkGz@OO_l7H69<=F@>Vy3m@J#Ht~!Uz2G-HTgTG*N+27OVjpo# zpW<%ECVPG1cw;pZb}9d8_4IhJ4Qnj%iiO?jFFtE_2>a)EYB;}x@8Y|s=nU>EZ)dI^ zp<0+&lot@t-^YvqAhv=LXS#+xdU^1XK$L_n#aV1{OvM1_s6? I?LRgD1L?tjegFUf literal 0 HcmV?d00001 diff --git a/Powercore-V2.0 Motherboard/KiCAD/Powercore-V2.0_Motherboard.kicad_prl b/Powercore-V2.0 Motherboard/KiCAD/Powercore-V2.0_Motherboard.kicad_prl index 5f66ff5..fdd76fb 100644 --- a/Powercore-V2.0 Motherboard/KiCAD/Powercore-V2.0_Motherboard.kicad_prl +++ b/Powercore-V2.0 Motherboard/KiCAD/Powercore-V2.0_Motherboard.kicad_prl @@ -63,7 +63,7 @@ 36, 40 ], - "visible_layers": "8081100_ffffffff", + "visible_layers": "8081100_ffffffe0", "zone_display_mode": 0 }, "meta": {