### Full Nevermore Configuration with Bluetooth/Serial Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc Comprehensive configuration example for a Nevermore filter, demonstrating options for Bluetooth address or serial connection, initial connection timeout, LED settings, and fan control parameters. It emphasizes not to copy-paste directly and to follow the setup guide. Warnings are included regarding default values and experimental BLE features. ```ini # DON'T JUST COPY PASTE THIS INTO THE PRINTER'S KLIPPER CONFIGURATION. # 1) Read the setup guide. # 2) *Don't uncomment default values unless you explicitly wish to change them.* # Doing so will prevent you from getting new defaults from future updates. # If name is omitted, will default to just `nevermore`. # You may specify multiple `[nevermore ...]` sections to define multiple filters. [nevermore custom_names_allowed] # Can omit if you have only one nevermore in range, but it is recommended you # specify the address. # See <> for more info. # NOTE: Providing an address will make startup slightly faster. # (If no address is provided then the system must spend extra time # verifying that there's only one nearby Nevermore.) # example - `bt_address: 43:43:A2:12:1F:AC` bt_address: # Use a serial connection instead of BLE. # Mutually exclusive w/ `bt_address`. # WARNING: Make sure you're using the 2nd interface (path ends with '-if02'), # *not* one which ends w/ `-if00`. serial: # seconds, 0 to disable, how long to wait at startup before failing if Klipper can't connect # If disabled (set to 0) the module will not error on startup if it cannot connect. # Disabling this requires that `bt_address` is set. # Cannot be used w/ `serial`. # # WARNING: **Do not disable unless you've fully tested everything in the filter.** # i.e. it should be ready for a serial # request on the Discord. # Disabling makes it difficult to decern if a problem is caused by connection issues # or something else. # WARNING: If you set this < 10 seconds you will likely have trouble connecting. # NOTE: **After** startup module will always quietly keep trying to reconnect if connection, # regardless of what value is set for `connection_initial_timeout`. # NOTE: It takes some amount of time to reliably scan & connect to Nevermore. # This varies on a few factors outside of your control, so the system # will reject unfeasibly small timeout values to keep you from screwing # yourself over. #connection_initial_timeout: # LED # For the optional LED feature. # Members generally behaves like the WS2812 Klipper module. # (e.g. supports heterogenous pixel chains) # # Values for commonly used LED strips (may be incorrect): # |=== # | Device | led_chain_count | led_colour_order # | Max BOM ring | 16 | GBR # | StealthMax v2 latch | 7 | GBR # |=== # # If the colours seem wrong, fiddle with `led_colour_order`. # Bear in mind that the device might also be a 4 component RGBW. #led_colour_order: GRB #led_chain_count: 0 # Fan Options # Various settings for the fan. # float \in [0, 1] - Fan power used when the automatic policy nor overridden #fan_power_passive: 0 # float \in [0, 1] - Fan power used when the automatic fan policy is active. # Useful if you'd prefer slower but quieter background/automatic filtering. # NOTE: Automatic fan power is scaled based on several factors. See Fan Control. #fan_power_automatic: 1 # float \in [0, 1] - Coefficient applied to the fan power. # i.e. Limits the maximum speed of the fan. Useful for managing noise. # e.g. At 0.75, requesting 100% power will run the fan at 75% power. #fan_power_coefficient: 1 ``` -------------------------------- ### Installation Script - Klipper Module Source: https://context7.com/ubwa/nevermore-controller/llms.txt This bash script automates the installation of the Nevermore Controller module on a printer's host system, such as a Raspberry Pi running MainsailOS. It clones the repository and copies necessary files to the Klipper directory, and offers to enable Bluetooth. It includes comments indicating the script's actions. ```Bash # SSH into printer (e.g., Raspberry Pi running Klipper) ssh pi@mainsailos.local # Clone repository cd ~ git clone https://github.com/SanaaHamel/nevermore-controller cd nevermore-controller # Run installation script ./install-klipper-module.bash # Script will: # 1. Copy nevermore.py to ~/klipper/klippy/extras/ # 2. Copy nevermore_utilities to ~/klipper/klippy/extras/ # 3. Offer to enable Bluetooth on MainsailOS (if detected) # 4. Restart Klipper service ``` -------------------------------- ### Example PRINT_START Macro with NEVERMORE_TEMPERATURE_WAIT Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc An illustrative example of how to integrate the `NEVERMORE_TEMPERATURE_WAIT` command into a Klipper `PRINT_START` macro to ensure chamber temperatures are within the desired range before commencing a print. ```gcode [gcode_macro PRINT_START] ... (other PRINT_START commands) NEVERMORE_TEMPERATURE_WAIT MINIMUM=20 MAXIMUM=50 ... (rest of PRINT_START commands) ``` -------------------------------- ### Klipper Configuration: Nevermore Connection Setup (INI) Source: https://context7.com/ubwa/nevermore-controller/llms.txt Configure the Nevermore controller within Klipper's printer.cfg for communication. Supports Bluetooth (recommended for Pico W) via BT address or USB serial connection. Allows custom naming for multiple controllers. ```ini # Bluetooth connection (recommended for Pico W) [nevermore] bt_address: 28:CD:C1:09:64:8F connection_initial_timeout: 20 # Alternative: USB serial connection (use -if02 interface) [nevermore] serial: /dev/serial/by-id/usb-Nevermore_Filter_E6616408432C432E-if02 # Optional: Custom name for multiple controllers [nevermore workshop_filter] bt_address: FA:KE:AD:RE:SS:01 ``` -------------------------------- ### Minimal Klipper Configuration for Nevermore Controller Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc This INI snippet configures the Nevermore module in Klipper for basic operation, including optional USB serial setup and fan power parameters optimized for DELTA BFB0712HF fans. It requires Klipper with Python 3.7+ and persists changes to flash after ~10 seconds. Limitations include manual adjustments for non-standard fans and no automatic default updates without reset. ```ini # This minimal config is *MINIMAL*. # There are many extra features that might be worth checking out! # (e.g. chamber temperature waiting) [nevermore] # If you're using USB instead of BT, uncomment and specify the correct serial device. # WARNING: Make sure it's the `-if02` interface, not `-if00`. #serial: /dev/serial/by-id/usb-Nevermore_Filter__-if02 # These `fan_power_*` entries are for a DELTA BFB0712HF (StealthMax BOM) # If you have a different fan then play with these numbers to the satisfaction. # See full config documentation for details. # (e.g. See `fan_power_automatic` if you'd prefer very quiet background filtering.) fan_power_coefficient: 0.8 # lower max power to keep things much more quiet # If the fan isn't a DELTA BFB0712HF (StealthMax BOM), you'll probably want to add # fan_power_minimum: ??? ``` -------------------------------- ### Compiler Cache and Project Setup (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Configures the build system to use 'ccache' for compiler caching if available, enhancing build performance. It also sets the project name and supported languages (C, C++, ASM). ```cmake find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") endif() project(nevermore-controller C CXX ASM) ``` -------------------------------- ### Update Nevermore Controller Firmware via OTA (Python) Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc This script allows updating the Nevermore controller's firmware over-the-air (OTA). It supports updating to the latest release, a specific release tag, or a custom UF2 build file. Ensure you have the necessary Python environment and the `bleak` library installed. Custom builds may be unstable and require a USB recovery flash. ```python import subprocess # Example: Update to a specific tag subprocess.run(['./tools/update_ota.py', '--tag', 'v0.15.1']) # Example: Apply a custom UF2 build # wget -O picowota_ota-custom.uf2 "" # subprocess.run(['./tools/update_ota.py', '', '--file', './picowota_ota-custom.uf2']) ``` -------------------------------- ### LED Effect Integration with Nevermore Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc Example of integrating Nevermore with Klipper's LED effect system, specifically for 'panel_idle' state. This uses WS2812 NeoPixel compatible LEDs and defines a 'comet' and 'breathing' layer for visual effects. Refer to Klipper LED Effect documentation for more details. ```ini # led-effects are supported, here's an example: [led_effect panel_idle] autostart: true frame_rate: 24 leds: nevermore layers: comet 1 0.5 add (0.0, 0.0, 0.0),(1.0, 0.0, 0.0),(1.0, 1.0, 0.0),(1.0, 1.0, 1.0) breathing 2 1 top (0,.25,0) ``` -------------------------------- ### Configure Nevermore Temperature Plotting Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc This configuration block enables temperature plotting for the Nevermore intake sensor, specifically tracking VOC (Volatile Organic Compounds). Ensure the 'NevermoreSensor' type is correctly defined in your Klipper setup. ```ini [temperature_sensor nevermore_intake_VOC] sensor_type: NevermoreSensor sensor_kind: intake plot_voc: true ``` -------------------------------- ### Perform OTA Update of Nevermore Controller (Shell) Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc This shell script performs an over-the-air (OTA) update for the Nevermore controller firmware. It switches to the project directory, pulls updates, and applies the latest image. Requires an OTA-capable UF2 (version 0.3 or later) and may install dependencies on first run. Limitations include potential slowness depending on device capabilities and needing Bluetooth or serial connection. ```sh # switch to the nevermore-controller installation cd ~/nevermore-controller # fetch updates for klipper module and tools git pull # download & apply latest controller image ./tools/update_ota.py ``` -------------------------------- ### Wait for Chamber Temperature Using Nevermore Gcode Source: https://context7.com/ubwa/nevermore-controller/llms.txt This macro waits for the chamber temperature to reach a specified target using Nevermore intake sensors before starting a print. It heats the bed first, then calls NEVERMORE_TEMPERATURE_WAIT with a timeout if sensors are unavailable. Requires Klipper with Nevermore configured. ```gcode [gcode_macro PRINT_START] gcode: {% set BED_TEMP = params.BED|float %} {% set CHAMBER_TEMP = params.CHAMBER|default(30)|float %} # Heat bed M190 S{BED_TEMP} # Wait for chamber (timeout after 10 min if sensors unavailable) NEVERMORE_TEMPERATURE_WAIT MINIMUM={CHAMBER_TEMP} UNAVAILABLE_TIMEOUT=600 # Stabilization delay G4 P30000 # Continue with print start... ``` -------------------------------- ### C++ - Initialize Display Source: https://context7.com/ubwa/nevermore-controller/llms.txt This snippet configures and initializes the display system. It sets a desired UI mode and then initializes the display with that UI. It also demonstrates adjusting the display brightness and changing the UI at runtime (requiring a reboot to apply the change). ```C++ #include "display.hpp" #include "settings.hpp" void display_example() { using namespace nevermore; // Set display UI before initialization settings::g_active.display_ui = DisplayUI::GC9A01_SMALL_PLOT; // Initialize display with configured UI if (display::init_with_ui()) { printf("Display initialized successfully\n"); } else { printf("Display initialization failed\n"); } // Adjust brightness display::brightness(0.9f); // 90% // Change UI at runtime (requires reboot to take effect) display::set_ui(DisplayUI::GC9A01_CLASSIC); printf("UI changed, reboot to apply\n"); } ``` -------------------------------- ### CMake Executable Target: Sensorium OTA Combined Source: https://github.com/ubwa/nevermore-controller/blob/main/tools/sensorium/CMakeLists.txt Creates an executable target 'nevermore-sensorium-ota' for combined OTA updates. It links against the 'nevermore-sensorium' library, sets a board-specific output name, and uses picowota to build the combined OTA image. ```cmake add_executable(nevermore-sensorium-ota) set_target_properties(nevermore-sensorium-ota PROPERTIES OUTPUT_NAME "ota-nevermore-sensorium_${NEVERMORE_BOARD}") target_link_libraries(nevermore-sensorium-ota PRIVATE nevermore-sensorium) pico_add_extra_outputs(nevermore-sensorium-ota) picowota_build_combined(nevermore-sensorium-ota picowota) ``` -------------------------------- ### Klipper Configuration: Nevermore Display and LEDs (INI) Source: https://context7.com/ubwa/nevermore-controller/llms.txt Set up display brightness, UI style, and NeoPixel LED strip configurations. Supports custom LED effects using Klipper's standard WS2812 implementation. ```ini [nevermore] # Display settings display_brightness: 1.0 # 0.0-1.0 display_ui: GC9A01_CLASSIC # Options: GC9A01_CLASSIC, GC9A01_SMALL_PLOT, GC9A01_NO_PLOT # NeoPixel configuration led_colour_order: GBR # Color order for LED strip led_chain_count: 16 # Number of LEDs (StealthMax ring) # LED effects work like standard Klipper WS2812 [led_effect panel_idle] autostart: true frame_rate: 24 leds: nevermore layers: comet 1 0.5 add (0.0,0.0,0.0),(1.0,0.0,0.0),(1.0,1.0,0.0),(1.0,1.0,1.0) breathing 2 1 top (0,0.25,0) ``` -------------------------------- ### Picowota Subdirectory and Target Properties (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Adds the 'picowota' subdirectory to the build and configures its properties. It enables Bluetooth SPP and USB CDC, and sets the application store size to 16 KiB (4 slots of 4 KiB each). ```cmake add_subdirectory(picowota) add_picowota(picowota) set_property(TARGET picowota PROPERTY PICOWOTA_BT_SPP "${NEVERMORE_PICO_W_BT}") set_property(TARGET picowota PROPERTY PICOWOTA_USB_CDC true) # each slot is 4 KiB (== erase sector size), want 4 slots to cycle set_property(TARGET picowota PROPERTY PICOWOTA_APP_STORE_SIZE 16) ``` -------------------------------- ### CMake: Picowota Declarations and Firmware Sharing Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This snippet uses 'picowota' specific CMake functions. 'picowota_app_store_declare' declares the 'picowota' application store for the 'nevermore-controller' target. 'picowota_share_cyw43_firmware' likely makes the CYW43 firmware available for use with the controller. ```cmake picowota_app_store_declare(nevermore-controller picowota) picowota_share_cyw43_firmware(nevermore-controller) ``` -------------------------------- ### Pico SDK and Board Header Path Configuration (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Configures the include path for board-specific headers used by the Pico SDK. It adds the `src/config/boards` directory to `PICO_BOARD_HEADER_DIRS` if it's not already present. ```cmake set(SRC_DIR_BOARDS "${CMAKE_CURRENT_LIST_DIR}/src/config/boards") if(NOT ("${SRC_DIR_BOARDS}" IN_LIST PICO_BOARD_HEADER_DIRS)) list(APPEND PICO_BOARD_HEADER_DIRS "${SRC_DIR_BOARDS}") endif() set(PICO_CXX_ENABLE_EXCEPTIONS 1) pico_sdk_init() ``` -------------------------------- ### CMake: Executable Targets for Nevermore Controller Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This section defines two executable targets: 'nevermore-controller-no-bootloader' and 'nevermore-controller-ota'. Both are linked against the main 'nevermore-controller' library and have specific output names set. 'pico_add_extra_outputs' and 'picowota_build_no_bootloader_with_app_store' or 'picowota_build_combined' are used to finalize their build configurations for different deployment scenarios. ```cmake add_executable(nevermore-controller-no-bootloader) set_target_properties(nevermore-controller-no-bootloader PROPERTIES OUTPUT_NAME "nevermore-controller_${NEVERMORE_BOARD}") target_link_libraries(nevermore-controller-no-bootloader PRIVATE nevermore-controller) pico_add_extra_outputs(nevermore-controller-no-bootloader) picowota_build_no_bootloader_with_app_store(nevermore-controller-no-bootloader picowota) add_executable(nevermore-controller-ota) set_target_properties(nevermore-controller-ota PROPERTIES OUTPUT_NAME "ota-nevermore-controller_${NEVERMORE_BOARD}") target_link_libraries(nevermore-controller-ota PRIVATE nevermore-controller) pico_add_extra_outputs(nevermore-controller-ota) picowota_build_combined(nevermore-controller-ota picowota) ``` -------------------------------- ### CMake Build Configuration for Nevermore Sensorium Library Source: https://github.com/ubwa/nevermore-controller/blob/main/tools/sensorium/CMakeLists.txt Defines the 'nevermore-sensorium' library by specifying source files, include directories, compile options, and definitions. It also links against necessary Pico SDK libraries and custom modules based on build configurations. ```cmake cmake_minimum_required(VERSION 3.20) # vars pulled from parent context: # SRC_DIR_BOARDS # PICO_BOARD_HEADER_DIRS set(PROJECT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) set(SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/src) # Touch outputs of config files so the rest of config knows there'll be associated outputs file(GLOB_RECURSE SRC_IN ${SRC_DIR}/*.in) foreach(in_file ${SRC_IN}) cmake_path(REMOVE_EXTENSION in_file LAST_ONLY) if(NOT EXISTS ${in_file}) file(TOUCH "${in_file}") endif() endforeach() file(GLOB_RECURSE SRC_H ${SRC_DIR}/*.h) file(GLOB_RECURSE SRC_C ${SRC_DIR}/*.c) file(GLOB_RECURSE SRC_HPP ${SRC_DIR}/*.hpp) file(GLOB_RECURSE SRC_CPP ${SRC_DIR}/*.cpp) set(SRC_FILES ${SRC_H} ${SRC_C} ${SRC_HPP} ${SRC_CPP} "${PROJECT_ROOT_DIR}/src/sdk/i2c_hw.cpp" "${PROJECT_ROOT_DIR}/src/utility/i2c.cpp" ) add_library(nevermore-sensorium ${SRC_FILES}) target_include_directories(nevermore-sensorium PUBLIC "${SRC_DIR}" # for stuff we're stealing from nevermore-controller (e.g board configs & utils) "${PROJECT_ROOT_DIR}/src" ) target_compile_options(nevermore-sensorium PUBLIC -Wall # disable useless warnings -Wno-psabi -Wno-trigraphs ) target_compile_definitions(nevermore-sensorium PUBLIC # board config/defs NEVERMORE_BOARD="${NEVERMORE_BOARD}" NEVERMORE_BOARD_HEADER="config/pins/${NEVERMORE_BOARD}.hpp" NEVERMORE_PICO_W_BT=${NEVERMORE_PICO_W_BT} # logging options NEVERMORE_BLUETOOTH_DEBUG=$ NEVERMORE_BLUETOOTH_LOW_LEVEL_DEBUG=$ NEVERMORE_I2C_DEBUG=$ PARAM_ASSERTIONS_ENABLE_ALL=1 PICO_USE_MALLOC_MUTEX=1 WANT_HCI_DUMP=1 ) target_link_libraries( nevermore-sensorium PUBLIC # Pico SDK hardware_i2c hardware_pwm hardware_spi hardware_watchdog pico_btstack_ble pico_stdio_uart pico_stdio_usb pico_stdlib pico_time # Others picowota_client ) if(${PICO_BOARD} STREQUAL "pico_w") target_link_libraries(nevermore-sensorium PUBLIC pico_cyw43_arch_poll) endif() if(${NEVERMORE_PICO_W_BT}) target_link_libraries(nevermore-sensorium PUBLIC pico_btstack_cyw43) endif() target_compile_definitions(nevermore-sensorium PUBLIC USBD_MANUFACTURER="Nevermore" USBD_PRODUCT="Sensorium ${NEVERMORE_BOARD}" CYW43_LWIP=0 ) ``` -------------------------------- ### FetchContent for External Libraries (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Declares and fetches external libraries such as FreeRTOS and LVGL using Git repositories. It specifies the repository URL, branch/tag, and shallow clone option. The `SOURCE_SUBDIR` for FreeRTOS is intentionally invalid to prevent auto-inclusion. ```cmake cmake_minimum_required(VERSION 3.20) include(FetchContent) include(cmake/pico_sdk_import.cmake) FetchContent_Declare( freertos_kernel GIT_REPOSITORY https://github.com/FreeRTOS/FreeRTOS-Kernel.git GIT_TAG smp # V202110.00-SMP GIT_SHALLOW ON SOURCE_SUBDIR "this path doesn't exist. it is here to disable the auto build inclusion" ) FetchContent_Declare( lvgl GIT_REPOSITORY git@github.com:lvgl/lvgl.git GIT_TAG release/v8.3 GIT_SHALLOW ON ) FetchContent_MakeAvailable(lvgl) ``` -------------------------------- ### CMake OTA (Over-The-Air) Update Configuration Source: https://github.com/ubwa/nevermore-controller/blob/main/tools/sensorium/CMakeLists.txt Configures Over-The-Air update capabilities using 'picowota'. It declares the application for storing OTA data and shares the CYW43 firmware. This configuration applies to the 'nevermore-sensorium' library. ```cmake picowota_app_store_declare(nevermore-sensorium picowota) picowota_share_cyw43_firmware(nevermore-sensorium) ``` -------------------------------- ### Configure GPIO pin assignments for custom hardware Source: https://context7.com/ubwa/nevermore-controller/llms.txt Customizes GPIO pin assignments using the pin configuration tool. Supports interactive configuration, resetting to defaults, viewing current/default configurations, and applying configurations from files. Works over both Bluetooth and serial connections. ```bash # Interactive pin configuration cd ~/nevermore-controller ./tools/pin-config.py --bt-address 28:CD:C1:09:64:8F # Reset to board defaults (if pins are misconfigured) ./tools/pin-config.py --serial /dev/ttyACM0 --reset-default # View current configuration ./tools/pin-config.py --bt-address 28:CD:C1:09:64:8F --echo-current # View default configuration ./tools/pin-config.py --echo-default # Apply configuration from file ./tools/pin-config.py --file custom-pins.jsonc --bt-address 28:CD:C1:09:64:8F ``` -------------------------------- ### CMake: Link Libraries for Nevermore Controller Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This CMake snippet links various public libraries to the 'nevermore-controller' target. It includes Pico SDK components, FreeRTOS, lvgl, and other essential libraries. Conditional linking is used for Pico W specific libraries and Bluetooth support based on build variables. ```cmake target_link_libraries( nevermore-controller PUBLIC # Pico SDK hardware_adc hardware_dma hardware_flash hardware_i2c hardware_pio hardware_pwm hardware_spi hardware_watchdog pico_btstack_ble pico_rand pico_stdio_uart # pico_stdio_usb pico_stdlib pico_time pico_flash pico_unique_id tinyusb_board tinyusb_device # Others FreeRTOS-Kernel FreeRTOS-Kernel-Heap4 lvgl::lvgl picowota_client ) if(${PICO_BOARD} STREQUAL "pico_w") target_link_libraries(nevermore-controller PUBLIC pico_cyw43_arch_sys_freertos) endif() if(${NEVERMORE_PICO_W_BT}) target_link_libraries(nevermore-controller PUBLIC pico_btstack_cyw43) endif() ``` -------------------------------- ### CMake Executable Target: Sensorium No Bootloader Source: https://github.com/ubwa/nevermore-controller/blob/main/tools/sensorium/CMakeLists.txt Creates an executable target 'nevermore-sensorium-no-bootloader' which is based on the 'nevermore-sensorium' library. It sets a custom output name including the board type and adds extra outputs required for the build. ```cmake add_executable(nevermore-sensorium-no-bootloader) set_target_properties(nevermore-sensorium-no-bootloader PROPERTIES OUTPUT_NAME "nevermore-sensorium_${NEVERMORE_BOARD}") target_link_libraries(nevermore-sensorium-no-bootloader PRIVATE nevermore-sensorium) pico_add_extra_outputs(nevermore-sensorium-no-bootloader) picowota_build_no_bootloader_with_app_store(nevermore-sensorium-no-bootloader picowota) ``` -------------------------------- ### Library Configuration Paths and Dependencies (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Defines source directories for library configurations and modifies the 'lvgl' target. It adds a configuration header directory and links 'lvgl' with 'pico_time' for millisecond ticking. ```cmake set(SRC_DIR ${CMAKE_SOURCE_DIR}/src) # HACK: libs often include a config header (e.g. lvgl, btstack, etc) set(SRC_CONFIG_DIR ${SRC_DIR}/config/lib) # modify lvgl to add config header path & sdk dependencies target_include_directories(lvgl PRIVATE ${SRC_CONFIG_DIR}) # add `pico_time` dependency so lvgl can get a millisecond tick target_link_libraries(lvgl pico_time) ``` -------------------------------- ### CMake Bluetooth GATT Header Generation Source: https://github.com/ubwa/nevermore-controller/blob/main/tools/sensorium/CMakeLists.txt Uses the 'pico_btstack_make_gatt_header' CMake function to generate a Bluetooth GATT header file from a specified .gatt file. This is a private target for the 'nevermore-sensorium' library. ```cmake pico_btstack_make_gatt_header(nevermore-sensorium PRIVATE ${SRC_DIR}/sensorium.gatt) ``` -------------------------------- ### Define hardware pin assignments in JSONC format Source: https://context7.com/ubwa/nevermore-controller/llms.txt JSONC format for defining hardware pin assignments for custom board layouts. Includes configurations for I2C buses, SPI bus, fan control, accessories, display pins, touch sensor, and status LED. Supports comments and optional fields. ```jsonc { // I2C buses for sensors (intake, exhaust, or generic) "i2c": [ { "kind": "intake", // "intake", "exhaust", or "generic" "clock": 21, // GPIO pin number "data": 20, "baud_rate": 400000 // optional, 0 = default }, { "kind": "exhaust", "clock": 19, "data": 18 } ], // SPI bus for display (optional) "spi": [ { "kind": "display", // "display" or "generic" "clock": 2, "send": 3, "recv": 4, // can be null if not needed "select": null, // chip select, null if not needed "baud_rate": 62500000 } ], // Fan control (arrays allow alternatives) "fan_pwm": [13], "fan_tachometer": [15], // Accessories (null = not used) "neopixel_data": [12], "photocatalytic_pwm": 10, "vent_servo_pwm": 14, "cooler_pwm": null, // Display pins "display_command": 5, "display_reset": 6, "display_brightness_pwm": 7, // Touch sensor "touch_interrupt": 8, "touch_reset": 9, // Status LED (optional) "led_status_voc_calibration": null } ``` -------------------------------- ### C++ - Manage Settings Source: https://context7.com/ubwa/nevermore-controller/llms.txt This code accesses and persists controller configuration settings. It reads and modifies settings like fan power, display brightness, and VOC gating threshold, then persists these settings to flash memory. It depends on `settings.hpp` and uses the `persist()` function. ```C++ #include "settings.hpp" #include void settings_example() { using namespace nevermore::settings; // Access global active settings auto& settings = g_active; // Read current configuration printf("Fan passive power: %u%%\n", settings.fan_power_passive.as_uint8() / 2); printf("Fan coefficient: %u%%\n", settings.fan_power_coefficient.as_uint8() / 2); printf("VOC gating: %u\n", settings.voc_gating_threshold); // Modify settings settings.fan_power_coefficient = BLE::Percentage8(160); // 80% settings.display_brightness = BLE::Percentage8(180); // 90% settings.voc_gating_threshold = 250; // Persist to flash (saves after ~10 seconds, or immediately before reboot) persist(); printf("Settings queued for persistence\n"); // Check configuration flags if (settings.sensors_fallback) { printf("Sensor fallback enabled\n"); } } ``` -------------------------------- ### CMake: Generate PIO Headers and GATT Header Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This code uses Pico SDK CMake functions to generate header files for PIO (Programmable I/O) programs and a GATT (Generic Attribute Profile) header. 'pico_generate_pio_header' processes PIO assembly files, and 'pico_btstack_make_gatt_header' generates C code from a .gatt definition file, both associated with the 'nevermore-controller' target. ```cmake pico_btstack_make_gatt_header(nevermore-controller PRIVATE ${SRC_DIR}/nevermore.gatt) pico_generate_pio_header(nevermore-controller ${SRC_DIR}/lib/pio_i2c.pio) pico_generate_pio_header(nevermore-controller ${SRC_DIR}/ws2812.pio) ``` -------------------------------- ### CMake: Set USBD Definitions for Nevermore Controller and Picowota Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This snippet sets compile definitions for the USBD (USB Device) manufacturer and product strings. These definitions are applied to both the 'nevermore-controller' library and the 'picowota' target, ensuring consistent USB identification across related components. The product string is dynamically set based on the 'NEVERMORE_BOARD' variable. ```cmake target_compile_definitions(nevermore-controller PUBLIC USBD_MANUFACTURER="Nevermore" USBD_PRODUCT="Filter ${NEVERMORE_BOARD}" ) target_compile_definitions(picowota PUBLIC USBD_MANUFACTURER="Nevermore" USBD_PRODUCT="Filter ${NEVERMORE_BOARD}" ) ``` -------------------------------- ### CMake Custom Target for Generating Build Info Source: https://github.com/ubwa/nevermore-controller/blob/main/tools/sensorium/CMakeLists.txt Creates a custom CMake target 'nevermore-sensorium-generate-build-info' that executes a Python script to generate build information files. It specifies input files and designates output files that are generated by the script. ```cmake list(TRANSFORM SRC_IN REPLACE "(.*)\.in$" "\1" OUTPUT_VARIABLE SRC_IN_BYPRODUCTS) # cmake-format: off add_custom_target( nevermore-sensorium-generate-build-info COMMAND ${CMAKE_COMMAND} -D EXTRA_MODULES_DIR=${PROJECT_ROOT_DIR}/cmake -D NEVERMORE_BOARD=${NEVERMORE_BOARD} -P ${PROJECT_ROOT_DIR}/cmake/configure_files.cmake -- ${SRC_IN} BYPRODUCTS ${SRC_IN_BYPRODUCTS} ) # cmake-format: on add_dependencies(nevermore-sensorium nevermore-sensorium-generate-build-info) ``` -------------------------------- ### CMake: Configure Project Files Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This snippet uses CMake's file commands to ensure that configuration files with a .in extension exist. It iterates through source files ending in .in, removes the extension, and creates empty files if they don't already exist. This is likely used to prepare input files for subsequent configuration steps. ```cmake file(GLOB_RECURSE SRC_IN CONFIGURE_DEPENDS "${SRC_DIR}/*.in") foreach(in_file ${IN_FILE}) cmake_path(REMOVE_EXTENSION in_file LAST_ONLY) if(NOT EXISTS ${in_file}) file(TOUCH "${in_file}") endif() endforeach() ``` -------------------------------- ### Query Nevermore Controller Status Gcode Source: https://context7.com/ubwa/nevermore-controller/llms.txt Queries connection status and info for Nevermore controllers via console output. Can specify controller by name. Outputs status like connected, fan RPM, temps, VOC. ```gcode # Check all nevermore controllers NEVERMORE_STATUS # Check specific controller NEVERMORE_STATUS NEVERMORE=workshop_filter # Output example: # nevermore: connected=True, fan_rpm=2450, intake_temp=28.5°C, # intake_voc=185, exhaust_voc=145 ``` -------------------------------- ### CMake: Generate Build Info Custom Target Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This CMake code defines a custom target 'nevermore-controller-generate-build-info'. It executes a CMake script ('configure_files.cmake') to process input files and generate output files. The BYPRODUCTS directive specifies the generated files, which are essential for the main 'nevermore-controller' target's build process. ```cmake list(TRANSFORM SRC_IN REPLACE "(.*)\.in$" "\1" OUTPUT_VARIABLE SRC_IN_BYPRODUCTS) # cmake-format: off add_custom_target( nevermore-controller-generate-build-info COMMAND ${CMAKE_COMMAND} -D EXTRA_MODULES_DIR=${CMAKE_CURRENT_SOURCE_DIR}/cmake -D NEVERMORE_BOARD=${NEVERMORE_BOARD} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files.cmake -- ${SRC_IN} BYPRODUCTS ${SRC_IN_BYPRODUCTS} ) # cmake-format: on add_dependencies(nevermore-controller nevermore-controller-generate-build-info) ``` -------------------------------- ### FreeRTOS Configuration and Port Selection (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Configures FreeRTOS settings, including heap size and the target port. It dynamically selects the FreeRTOS port based on whether cross-compilation is enabled, defaulting to GCC_POSIX and switching to GCC_ARM_CA9 for cross-compiling. ```cmake set(FREERTOS_HEAP "4" CACHE STRING "" FORCE ) set(FREERTOS_PORT "GCC_POSIX" CACHE STRING "" FORCE ) # Select the native compile PORT set(FREERTOS_KERNEL_PATH "${CMAKE_BINARY_DIR}/_deps/freertos_kernel-src") if(CMAKE_CROSSCOMPILING) # Select the cross-compile PORT set(FREERTOS_PORT "GCC_ARM_CA9" CACHE STRING "" FORCE ) endif() FetchContent_MakeAvailable(freertos_kernel) include(cmake/FreeRTOS_Kernel_import.cmake) ``` -------------------------------- ### Manage VOC Sensor Calibration Gcode Source: https://context7.com/ubwa/nevermore-controller/llms.txt Manages VOC sensor calibration checkpoints and resets for environment changes. Includes enabling/disabling calibration. Requires sensor hardware, uses NEVERMORE_SENSOR_CALIBRATION_CHECKPOINT and_RESET. ```gcode # After baseline calibration (clean air for 10 minutes) NEVERMORE_SENSOR_CALIBRATION_CHECKPOINT M118 Sensor calibration saved # Reset calibration after moving printer to new location NEVERMORE_SENSOR_CALIBRATION_RESET M118 Calibration reset - allow 24h for new baseline # Disable calibration during prints (auto-managed, rarely needed manually) NEVERMORE_VOC_CALIBRATION ENABLED=0 # Re-enable after print NEVERMORE_VOC_CALIBRATION ENABLED=1 ``` -------------------------------- ### CMake: Define Nevermore Controller Library Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This snippet defines the main library for the nevermore-controller project. It uses GLOB_RECURSE to gather source files (.h, .c, .hpp, .cpp) and then adds them to a library target named 'nevermore-controller'. It also configures include directories and public compile options, including specific warning flags. ```cmake file(GLOB_RECURSE SRC_H CONFIGURE_DEPENDS "${SRC_DIR}/*.h") file(GLOB_RECURSE SRC_C CONFIGURE_DEPENDS "${SRC_DIR}/*.c") file(GLOB_RECURSE SRC_HPP CONFIGURE_DEPENDS "${SRC_DIR}/*.hpp") file(GLOB_RECURSE SRC_CPP CONFIGURE_DEPENDS "${SRC_DIR}/*.cpp") set(SRC_FILES ${SRC_H} ${SRC_C} ${SRC_HPP} ${SRC_CPP}) add_library(nevermore-controller ${SRC_FILES}) target_include_directories(nevermore-controller PUBLIC "${SRC_DIR}" "${SRC_CONFIG_DIR}" ) target_compile_options(nevermore-controller PUBLIC -Wall # disable useless warnings -Wno-psabi -Wno-trigraphs ) ``` -------------------------------- ### Access Nevermore Controller Console Logs via Minicom (Bash) Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc This command uses `minicom` to access the console logs of the Nevermore controller over a serial connection (USB or UART). It configures the baud rate and output to a timestamped format. Ensure the device is connected and the correct serial port is identified. Logs can be saved to a file using the `-C` option. ```bash # Connect via USB minicom -c on -b 115200 -O timestamp=extended -D /dev/serial/by-id/usb-Nevermore_Filter___if00 # Connect via UART (replace with your UART adapter's serial device) # minicom -c on -b 115200 -O timestamp=extended -D /dev/ttyUSB0 # Save logs to a file # minicom -c on -b 115200 -O timestamp=extended -D /dev/serial/by-id/usb-Nevermore_Filter___if00 -C controller.log ``` -------------------------------- ### CMake: Set Compile Definitions for Nevermore Controller Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt This CMake snippet sets various public compile definitions for the 'nevermore-controller' library. These definitions configure board-specific settings, Bluetooth debug options, feature flags, task priorities, host names, and Pico SDK related definitions. They are crucial for tailoring the build to different hardware configurations and feature sets. ```cmake target_compile_definitions(nevermore-controller PUBLIC # board config/defs NEVERMORE_BOARD="${NEVERMORE_BOARD}" NEVERMORE_BOARD_HEADER="config/pins/${NEVERMORE_BOARD}.hpp" NEVERMORE_PICO_W_BT=${NEVERMORE_PICO_W_BT} # logging options NEVERMORE_BLUETOOTH_DEBUG=$ NEVERMORE_BLUETOOTH_LOW_LEVEL_DEBUG=$ NEVERMORE_I2C_DEBUG=$ # feature options NEVERMORE_SETTINGS_PERSISTENCE=$ # UGLY: Also defines the value of `nevermore::Priority::Communication`. # We want a priority above almost anything else. # Leaves 3 slots above (Max, USBD, Startup) CYW43_TASK_PRIORITY=28 CYW43_HOST_NAME="Nevermore" CYW43_LWIP=0 # default is 4. # Current users: tinyusb w/ DCD (1), stdio w/ USB (1), CYW43 driver (1), WS2812 (1), CST816S (1), GC9A01 (1) PICO_MAX_SHARED_IRQ_HANDLERS=6 PARAM_ASSERTIONS_ENABLE_ALL=1 PICO_USE_MALLOC_MUTEX=1 WANT_HCI_DUMP=1 CFG_TUSB_CONFIG_FILE="config/lib/tusb_config.h" ) ``` -------------------------------- ### Debug and Feature Options (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Defines build options for enabling various debug logging levels for Bluetooth and I2C, as well as a feature option for settings persistence. These options control the verbosity of logs and whether settings are saved to flash. ```cmake # debug logging options option(NEVERMORE_BLUETOOTH_DEBUG "bluetooth debug logging (noisy)" OFF) option(NEVERMORE_BLUETOOTH_LOW_LEVEL_DEBUG "bluetooth low level debug logging (very noisy)" OFF) option(NEVERMORE_I2C_DEBUG "I2C debug logging" OFF) # feature options option(NEVERMORE_SETTINGS_PERSISTENCE "settings are saved/restored from flash" ON) ``` -------------------------------- ### Klipper Configuration: Nevermore Automatic Fan Policy (INI) Source: https://context7.com/ubwa/nevermore-controller/llms.txt Configure automatic filtration policies based on VOC levels and cooldown periods. Includes settings for VOC thresholds, print mode activation based on bed temperature, and sensor fallback options. ```ini [nevermore] # VOC-based policies fan_policy_voc_passive_max: 250 # VOC index threshold (1-500) fan_policy_voc_improve_min: 0 # Intake-exhaust VOC delta fan_policy_cooldown: 900 # Continue filtering N seconds after trigger # Print mode trigger print_mode_min_bed_target: 60 # Minimum bed temp (°C) for print mode # Sensor configuration voc_gating_threshold: 250 # Suspend calibration above this VOC sensors_fallback: false # Use opposite side if sensors unavailable sensors_fallback_exhaust_mcu: false # Use MCU temp as exhaust fallback ``` -------------------------------- ### C/C++ Standard and Compilation Settings (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Sets the C and C++ standards for the project to C11 and C++23, respectively. It also disables C++ extensions and enables the generation of compile_commands.json for better IDE integration. ```cmake set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_EXTENSIONS OFF) # -std=c++ instead of -std=gnu++ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) ``` -------------------------------- ### Verify Bluetooth Power and Scan for Devices Source: https://github.com/ubwa/nevermore-controller/blob/main/README.adoc Commands to check if Bluetooth is powered on and to scan for nearby devices. Useful for diagnosing connectivity issues. ```shell bluetoothctl power on bluetoothctl scan on ``` -------------------------------- ### Excluding LVGL Demo Targets (CMake) Source: https://github.com/ubwa/nevermore-controller/blob/main/CMakeLists.txt Prevents the `lvgl_demos` and `lvgl_examples` targets from being built or linked, even if not explicitly used. This ensures a cleaner build process by removing unnecessary components. ```cmake # Completely exclude `lvgl_demos` & `lvgl_examples` from being built. # Even if they're not linked it's annoying. set_target_properties(lvgl_demos lvgl_examples PROPERTIES EXCLUDE_FROM_ALL TRUE) ``` -------------------------------- ### Klipper Configuration: Nevermore Fan Control (INI) Source: https://context7.com/ubwa/nevermore-controller/llms.txt Define fan behavior for the Nevermore controller, including passive and active power levels, minimum run and kick-start values, and thermal limiting parameters to protect activated carbon filters. ```ini [nevermore] # Power levels (0.0-1.0) fan_power_passive: 0 # Idle power fan_power_automatic: 1 # Active filtering power fan_power_coefficient: 0.8 # Max power limit (noise reduction) # Startup characteristics (absolute values, not scaled) fan_power_minimum: 0.175 # DELTA BFB0712HF minimum run fan_power_kick_start_minimum: 0.18 # DELTA BFB0712HF startup fan_kick_start_time: 0.5 # Kick-start duration in seconds # Thermal limiting (protects activated carbon) fan_thermal_limit_temperature_min: 50 # °C where limiting starts fan_thermal_limit_temperature_max: 60 # °C where fully applied fan_thermal_limit_coefficient: 0 # 0=stop at max, 1=disable limiting ``` -------------------------------- ### BLE GATT - Configure Fan Policy Source: https://context7.com/ubwa/nevermore-controller/llms.txt Enables setting automatic fan activation policies via BLE. This includes configuring cooldown periods, maximum VOC passive thresholds, minimum VOC improvement thresholds, and VOC gating thresholds. ```APIDOC ## BLE GATT - Configure Fan Policy ### Description Set automatic fan activation policies via BLE characteristics. This allows for fine-tuning fan behavior based on environmental factors and desired response times. ### Method BLE GATT Write Operations ### Endpoint N/A (BLE GATT Characteristics) ### Parameters #### BLE Characteristics - **`comm.fan_policy_cooldown`**: Characteristic to set the fan cooldown period in seconds (uint16). - **`comm.fan_policy_voc_passive_max`**: Characteristic to set the maximum VOC threshold for passive filtering (uint16). Value of 250 triggers filtering. - **`comm.fan_policy_voc_improve_min`**: Characteristic to set the minimum VOC improvement required for fan activation (uint16). Value of 0 disables this check. - **`comm.config_voc_gating_threshold`**: Characteristic to configure the VOC gating threshold, which stops calibration when exceeded (uint16). ### Request Example ```python # Set cooldown period (15 minutes = 900 seconds) await comm.fan_policy_cooldown.write((900).to_bytes(2, 'little')) # Set VOC passive max threshold (250 = trigger filtering) await comm.fan_policy_voc_passive_max.write((250).to_bytes(2, 'little')) # Configure VOC gating threshold await comm.config_voc_gating_threshold.write((250).to_bytes(2, 'little')) ``` ### Response #### Success Response No explicit response data, operations are confirmed by subsequent reads or behavior changes. #### Response Example N/A ```