Merge Feature/ai tuning port#101
Open
eamars wants to merge 34 commits into
Open
Conversation
New files ported from Jump73/OpenTrickler-v2 (rp2350 branch): - ai_tuning.c/h: AI/ML auto-tuning system with drop telemetry, adaptive step-halving and Gaussian Process PID refinement, records last 10 drops with coarse/fine Kp/Kd history - rest_ai_tuning.c/h: REST API endpoints for AI tuning session - error.c/h: centralized error handling system (100+ error codes, 8-entry circular buffer, reports to LED/display/REST) - rest_errors.c/h: REST API for error querying and clearing - flash_storage.c/h: flash-based persistence for ML history (4KB sector at end of 2MB flash, faster than I2C EEPROM) - app_state.c/h: application state management for mode transitions - display_config.c/h: display type/rotation/brightness persistence - styles.css.h, favicon.ico.h, web_portal_basic.html.h: web resources Modified files: - src/gng_scale.c: fix partial-frame carryover on timeout — reset buffer index and flush stale RX data at start of each poll cycle; add 200ms response timeout with mutex-protected scale_write() - src/rest_endpoints.c: register AI tuning, error, display_config endpoints; add flash_storage_init/ai_tuning_init/rest_ai_tuning_init calls; add /basic, /styles.css, /favicon.ico handlers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace missing encoder.h with mini_12864_module.h in ai_tuning.c and rest_ai_tuning.c - Add acquire/release_display_buffer_access() declarations to display.h - Add EEPROM_AI_TUNING_CONFIG_BASE_ADDR to eeprom.h - Add coarse_time_target_ms and total_time_target_ms fields to eeprom_charge_mode_data_t - Remove duplicate display_rotation_t from display_config.h (use mini_12864_module.h) - Remove duplicate exit_state definition from menu.c (owned by app_state.c) - Add app_state.h include to menu.c Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- charge_mode_wait_for_complete() now consults ai_tuning_get_motor_mode() and ai_tuning_get_next_params() to inject tuned Kp/Kd into the PID loop - Phase 2 (FINE_ONLY): coarse pre-charge using session->coarse_kp_best before fine PID loop runs - Motors skipped per AI motor mode (COARSE_ONLY skips fine, FINE_ONLY skips normal coarse) - ai_tuning_record_drop() called after each charge with full telemetry - ai_tuning_record_charge() called during normal charges when ml_data_collection_enabled is true - RST during AI tuning calls ai_tuning_cancel() - charge_mode_menu() exits after cup removal when ai_tuning_is_complete() - charge_mode.h: add ml_data_collection_enabled field, bump EEPROM rev to 10 - profile.h: export profile_get_selected_idx() declaration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- charge_mode.cpp: extend JSON response with c14 (coarse_time_target_ms), c15 (total_time_target_ms), c16 (ml_data_collection_enabled) - web_portal.html: add AI tuning live panel (aiTuningMainPanel) and ML suggestions banner to trickler section; add full AI Tuning settings page with profile/target/time-target fields, status display, start/ cancel/apply/clear-history controls, advanced Kp/Kd range config, and ML data collection toggle; add AI Tuning nav item; add all supporting JS functions (loadAiTuningPage, refreshAiTuningStatus, pollAiTuningMainPanel, aiTuningStart/Cancel/Apply/ClearHistory, aiTuningSaveThresholds, aiToggleMlDataCollection, aiTuningSaveAdvancedConfig) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… sync
- Profile selectors: dynamically populated with profile names from
/rest/profile_summary; AI tuning and Settings profiles stay in sync
(change in one updates the other via onAiTuningProfileChanged /
onQuickProfileSelectConfirmed)
- Live panel: add Phase badge (Phase 1: Coarse / Phase 2: Fine), Drop
count, Testing Kp/Kd, Last drop result (+overthrow, time)
- Settings page redesign matching OpenTrickler-v2:
- Info alert at top
- Thresholds form (c5 Coarse Stop, c6 Fine Stop, c14 Coarse Time,
c15 Total Time) with Apply Thresholds button
- Status badge + drop count
- Cycle Report log (scrollable, appends each drop result)
- Current Test Parameters stat boxes (4 values, shown when active)
- Recommended Parameters stat boxes in success colour (shown on complete)
- Avg Overthrow + Avg Time statistics
- Scale Zero / Tare button
- Start / Cancel / Apply Recommended Parameters buttons
- Advanced Settings collapsed table (Kp/Kd Min/Max + Noise Margin)
- ML Data Collection section: toggle, drop count, ML suggestions
(Fine Kp/Kd) with Apply ML Suggestions, collapsible Drop History
table with #/Profile/Overthrow/Time columns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 'mlRecommendationBanner' (green alert) on trickler page shown when ML data collection has accumulated enough drops for suggestions - Banner click calls onMlRecommendationClicked(): navigates to Settings > AI Tuning and scrolls to the ML suggestions section where user can review Fine Kp/Kd and apply to profile - pollAiTuningMainPanel() checks /rest/ai_tuning_history every ~5s (every 10th 500ms tick) to detect new suggestions without hammering REST - AI Tuning complete banner (mlSuggestionsBanner) and ML recommendation banner (mlRecommendationBanner) are now independent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Define _aiCfgDefaults matching ai_tuning.c #define values: Coarse Kp [0.01..1.0], Coarse Kd [0.01..2.0], Fine Kp [0.01..5.0], Fine Kd [0.01..20.0], Noise Margin 0.05 - aiLoadAdvancedConfig() now uses firmware value when non-zero, falls back to hardcoded default — fields are never blank on first open - aiTuningSaveAdvancedConfig() reuses shared _aiCfgFieldMap to avoid duplication Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Apply firmware defaults (c5=5, c6=0.03, c14=500ms, c15=3000ms) when REST response values are zero or undefined — same pattern used for Advanced Settings fields. Also populate defaults on fetch error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dropdown under "Charge Control" shows all named profiles and switches the active firmware profile immediately on selection. All profile selectors (trickler, AI tuning, settings) stay in sync with each other. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add current_profile_idx to ai_tuning_history_t (HISTORY_REV 4→5) - ai_tuning_record_charge() auto-clears history when profile_idx differs from the last recorded profile, so each profile gets a fresh ML session; stale flash data from old rev is also discarded - Expose profile_idx in /rest/ai_tuning_history JSON response Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Firmware: - Defer ai_tuning_record_charge() to charge_mode_wait_for_cup_removal() matching v2 pattern — flash_safe_execute was timing out during active charge loop with WiFi stack running on core 1 - Use settled scale reading (after 1s delay) for overthrow calculation instead of immediate post-charge reading Web UI: - Auto-refresh ML history count every 5s while on AI Tuning settings page (start on page open, stop on navigate away) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Auto-refresh now calls full aiLoadHistory() (badge + table + suggestions all stay in sync) instead of partial badge-only fetch - ML Recommendation banner requires both has_suggestions=true AND count>=3 so it won't show after a clear or when stale has_suggestions is in flash Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cache profile list after first fetch so subsequent page navigations (Trickler, AI Tuning, Settings) populate dropdowns instantly without waiting for a new HTTP request. RP2040's single-threaded HTTP server was serializing 4-5 concurrent fetches, leaving dropdowns empty for several seconds. Profile index stays in sync on every profile change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- REST: Fix circular buffer iteration order in http_rest_ai_tuning_history() to return drops in chronological order (oldest first). When buffer is full, start from next_idx; when partial, start from 0. - JS aiLoadHistory(): use Array.isArray() guard for drops, check count===0 (matching v2 pattern) to avoid early return when drops parse incorrectly, update _mlHasSuggestions for shared use by pollAiTuningMainPanel. - JS pollAiTuningMainPanel(): eliminate duplicate /rest/ai_tuning_history fetch when setInterval is already polling (on AI Tuning settings page) — reuse cached _mlHasSuggestions value instead. - Fix banner assignment: mlRecommendationBanner (green) is now correctly controlled by AI session isComplete; mlSuggestionsBanner (blue) by ML data collection suggestions (_mlHasSuggestions). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… change - Remove AI Tuning banners from Trickler page (mlSuggestionsBanner, mlRecommendationBanner) — user requested these be disabled on this page. Also removed the associated _tick polling loop that was hammering REST. - Fix profile dropdown showing #N instead of name: call loadProfileDropdowns() when entering Settings page so names are available immediately from cache. - Clear ML drop history when profile changes in onTricklerProfileChanged, onQuickProfileSelectConfirmed, onAiTuningProfileChanged — each profile has independent learning data and switching should reset the history. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
confirm() can block or fail silently on embedded/mobile browsers. Clear now works immediately without confirmation popup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix critical bug: in COARSE_ONLY mode (Phase 1), PID loop now exits at coarse_stop_threshold instead of fine_stop_threshold. Previously with no fine motor running, the loop would never exit when there was no overshoot. - Defer AI telemetry recording to cup_removal (1s settle) for accurate weight, matching v2 logic. Phase 1 overthrow now computed against coarse stop point. - Add charge mode state steps widget (Wait/Charging/Remove Cup/Return Cup) to AI Tuning settings page, updated by _pollAiTuningSettingsPage via Promise.all. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- In COARSE_ONLY (Phase 1) and FINE_ONLY (Phase 2) modes, stop motor when PID output <= 0 instead of forcing min_speed. Matches v2 behavior — without this the motor kept running at min_speed past the target causing huge overshoot. - Fix _pollAiTuningSettingsPage: replace Promise.all (stops on any error) with sequential fetch — charge_mode_state failure no longer kills AI status polling. Polling now retries after 1s on error instead of stopping permanently. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tches v2) Previously RP2040 used a single measurement + fixed-speed + fixed-time pre-charge for Phase 2 (FINE_ONLY). v2 uses a full PID loop with recommended_coarse_kp/kd from Phase 1, stopping when precharge_error < coarse_stop_threshold, then 1s settle. The fixed-time approach could massively overshoot, leaving the fine PID starting from beyond the coarse stop point. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add pulse mode (c18-c21): short motor bursts near target instead of continuous PID, helps with slow scales; threshold 0.3-1.0 gr range - Add auto-zero on cup return (c17): optionally force-zeros scale when cup is returned to tray - Add scale fail safety: emergency stop motors after 10 consecutive failed scale reads (~2s) in both main charge loop and pre-charge loop - Bump EEPROM_CHARGE_MODE_DATA_REV 10→12 for new fields - Expand JSON buffer 512→640 bytes for c17-c21 fields - Add Pulse Mode and Auto-Zero UI to Charge Mode settings page Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two new EEPROM-persisted settings (rev 13): - stabilization_enabled: true = fixed wait, false = adaptive SD-based (up to 3s) - stabilization_time_ms: fixed wait duration when enabled (default 2000ms) Replaces the hard-coded 1000ms vTaskDelay in charge_mode_wait_for_cup_removal() with the configurable logic so scale readings used for overthrow/underthrow decisions and ML recording are reliably settled. Adds c22/c23 REST parsing, JSON response fields, and UI controls in web_portal.html. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LWIP_HTTPD_MAX_CGI_PARAMETERS defaulted to 16, silently dropping all params beyond the 16th in a GET request. The charge mode form sends 24 params (c1-c23 + ee), so c17 onwards (auto-zero, pulse mode, stabilization, EEPROM save) were never received by the server. Also raise LWIP_HTTPD_MAX_REQUEST_URI_LEN from 128 to 512 to prevent URL truncation for large forms. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a shield/checkmark icon button between Settings and Purge that jumps directly to the AI Tuning settings page with one tap, without requiring the user to open Settings first. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ML History: - AI_TUNING_HISTORY_SIZE: 10 → 50 records (continuous recording per profile) - ML suggestion threshold: 10 → 3 drops in web UI - JSON buffer: 2048 → 4096 bytes for larger history response - History rev bumped to 6 Stabilization timing: - Add CHARGE_MODE_STABILIZING (state 5) between charging and cup removal - After motors stop → state=STABILIZING, display shows "Stabilizing..." - After wait completes → state=WAIT_FOR_CUP_REMOVAL, display shows "Remove Cup" - Web UI steps bar shows "Settling..." during state 5, "Remove Cup" after - Both main charge view and AI tuning charge view updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- First suggestion shown only after 10 normal-dispensing drops recorded - Suggestion recalculates at each subsequent 10-drop milestone (20, 30, ...) - After applying (history reset to 0), requires 10 new drops again - AI auto-tuning path (ai_tuning_record_drop) is unaffected Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New driver (ohaus_scale.c/h) with tare command T\r\n and sign-aware float parser for Ohaus output format (e.g. "ST,GS, + 0.0000 g") - Register SCALE_DRIVER_OHAUS_PR = 9 in enum, set_scale_driver() and get_scale_driver_string() - Add "Ohaus PR Series" option to web UI scale driver selector - Fix NULL dereference in http_rest_scale_action when force_zero is NULL (Generic Scale Driver has no tare command) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pioasm generated stepper.pio.h with pio_version=1 but RP2040 has PIO hardware version 0. pio_add_program() returns PICO_ERROR_VERSION_MISMATCH causing motor init to fail at boot with "PIO ERR" on display. Add .pio_version 0 to stepper.pio source so pioasm regenerates the header correctly. RP2350 was unaffected (PIO version 1 hardware). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ohaus_scale.c: add strtof fallback parser for output without explicit sign (e.g. "ST,GS, 0.5000 g\r\n"), matching ESP32 implementation - lwipopts_examples_common.h: increase MEM_SIZE 4000->8000 to reduce lwIP heap exhaustion causing intermittent HTTP failures - web_portal.html: clear form fields before fetch to avoid showing stale values; add .catch() error handlers to showSettingsSection and putForm - scale.c: call set_scale_driver() and set_scale_baudrate() in scale_config_save() so display menu driver changes take effect immediately on EEPROM save without requiring reboot Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- charge_mode.cpp: change fine stop condition < to <= so motor stops exactly at threshold (e.g. error=0.03 stops at 23.30, not 23.30001) - charge_mode.cpp: update defaults: coarse_stop=4, coarse_time=7000ms, total_time=15000ms - ai_tuning.c: start AI tuning from existing profile Kp/Kd values (clamped to min/max range) instead of always starting from midpoint; fall back to midpoint only for new/empty profiles - web_portal.html: fix "Failed to save settings: Failed to fetch" alert when rebooting - show friendly reboot message instead of error Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Just my 2c. Could you please not call it AI auto tuning as there is no AI involved. It is basically just heuristic auto-tuning. My vote is "PID Auto-tuning" or just "Auto-tuning". |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is just an comparison between the base and the AI tuning port.