diff --git a/.vscode/settings.json b/.vscode/settings.json index ba8a705..1020abe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -40,6 +40,15 @@ "cleanup_mode.h": "c", "charge_mode.h": "c", "http_rest.h": "c", - "motors.h": "c" + "motors.h": "c", + "eeprom.h": "c", + "stdbool.h": "c", + "configuration.h": "c", + "uart.h": "c", + "common.h": "c", + "clocks.h": "c", + "pwm.h": "c", + "servo_gate.h": "c", + "semphr.h": "c" } } diff --git a/CMakeLists.txt b/CMakeLists.txt index ae62884..83b0e25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ target_link_libraries("${TARGET_NAME}" hardware_pio hardware_spi hardware_i2c + hardware_pwm FreeRTOS-Kernel FreeRTOS-Kernel-Heap4 u8g2 diff --git a/src/app.cpp b/src/app.cpp index 2966bb8..33bfca8 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -26,7 +26,7 @@ #include "rotary_button.h" #include "menu.h" #include "profile.h" - +#include "servo_gate.h" uint8_t software_reboot() { @@ -63,6 +63,9 @@ int main() // Initialize profile data profile_data_init(); + // Initialize the servo + servo_gate_init(); + #ifdef RASPBERRYPI_PICO_W // Load wireless settings wireless_init(); diff --git a/src/charge_mode.cpp b/src/charge_mode.cpp index d43d53c..de8232a 100644 --- a/src/charge_mode.cpp +++ b/src/charge_mode.cpp @@ -20,6 +20,7 @@ #include "neopixel_led.h" #include "profile.h" #include "common.h" +#include "servo_gate.h" uint8_t charge_weight_digits[] = {0, 0, 0, 0, 0}; @@ -28,6 +29,8 @@ charge_mode_config_t charge_mode_config; // Scale related extern scale_config_t scale_config; +extern servo_gate_t servo_gate; + const eeprom_charge_mode_data_t default_charge_mode_data = { .charge_mode_data_rev = EEPROM_CHARGE_MODE_DATA_REV, @@ -40,6 +43,11 @@ const eeprom_charge_mode_data_t default_charge_mode_data = { .decimal_places = DP_2, + // Precharges + .precharge_enable = false, + .precharge_time_ms = 1000, + .precharge_speed_rps = 2, + // LED related .neopixel_normal_charge_colour = urgb_u32(0, 0xFF, 0), // green .neopixel_under_charge_colour = urgb_u32(0xFF, 0xFF, 0), // yellow @@ -167,6 +175,11 @@ void charge_mode_wait_for_complete() { true ); + // If the servo gate is used then it has to be opened + if (servo_gate.gate_state != GATE_DISABLED) { + servo_gate_set_state(GATE_OPEN, false); + } + // Update current status char target_weight_string[WEIGHT_STRING_LEN]; float_to_string(target_weight_string, charge_mode_config.target_charge_weight, charge_mode_config.eeprom_charge_mode_data.decimal_places); @@ -260,7 +273,21 @@ void charge_mode_wait_for_complete() { last_error = error; } - vTaskDelay(pdMS_TO_TICKS(20)); // Wait for other tasks to complete + // Close the gate if the servo gate is present + if (servo_gate.gate_state != GATE_DISABLED) { + servo_gate_set_state(GATE_CLOSE, true); + } + + // Precharge + if (charge_mode_config.eeprom_charge_mode_data.precharge_enable && servo_gate.gate_state != GATE_DISABLED) { + motor_set_speed(SELECT_COARSE_TRICKLER_MOTOR, charge_mode_config.eeprom_charge_mode_data.precharge_speed_rps); + vTaskDelay(pdMS_TO_TICKS(charge_mode_config.eeprom_charge_mode_data.precharge_time_ms)); + + motor_set_speed(SELECT_COARSE_TRICKLER_MOTOR, 0); + } + else { + vTaskDelay(pdMS_TO_TICKS(20)); // Wait for other tasks to complete + } charge_mode_config.charge_mode_state = CHARGE_MODE_WAIT_FOR_CUP_REMOVAL; } @@ -365,6 +392,7 @@ void charge_mode_wait_for_cup_return() { snprintf(title_string, sizeof(title_string), "Return Cup"); + FloatRingBuffer data_buffer(5); while (true) { @@ -528,6 +556,9 @@ bool http_rest_charge_mode_config(struct fs_file *file, int num_params, char *pa // c7 (float): set_point_sd_margin // c8 (float): set_point_mean_margin // c9 (int): decimal point enum + // c10 (bool): precharge_enable + // c11 (int): precharge_time_ms + // c12 (float): precharge_speed_rps // ee (bool): save to eeprom @@ -551,6 +582,17 @@ bool http_rest_charge_mode_config(struct fs_file *file, int num_params, char *pa else if (strcmp(params[idx], "c9") == 0) { charge_mode_config.eeprom_charge_mode_data.decimal_places = (decimal_places_t) atoi(values[idx]); } + + // Pre charge related settings + else if (strcmp(params[idx], "c10") == 0) { + charge_mode_config.eeprom_charge_mode_data.precharge_enable = string_to_boolean(values[idx]); + } + else if (strcmp(params[idx], "c11") == 0) { + charge_mode_config.eeprom_charge_mode_data.precharge_time_ms = strtol(values[idx], NULL, 10); + } + else if (strcmp(params[idx], "c12") == 0) { + charge_mode_config.eeprom_charge_mode_data.precharge_speed_rps = strtof(values[idx], NULL); + } // LED related settings else if (strcmp(params[idx], "c1") == 0) { @@ -580,17 +622,19 @@ bool http_rest_charge_mode_config(struct fs_file *file, int num_params, char *pa sizeof(charge_mode_json_buffer), "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"c1\":\"#%06lx\",\"c2\":\"#%06lx\",\"c3\":\"#%06lx\",\"c4\":\"#%06lx\"," - "\"c5\":%.3f,\"c6\":%.3f,\"c7\":%.3f,\"c8\":%.3f,\"c9\":%d}", + "\"c5\":%.3f,\"c6\":%.3f,\"c7\":%.3f,\"c8\":%.3f,\"c9\":%d,\"c10\":\"%s\",\"c11\":%ld,\"c12\":%0.3f}", charge_mode_config.eeprom_charge_mode_data.neopixel_normal_charge_colour, charge_mode_config.eeprom_charge_mode_data.neopixel_under_charge_colour, charge_mode_config.eeprom_charge_mode_data.neopixel_over_charge_colour, charge_mode_config.eeprom_charge_mode_data.neopixel_not_ready_colour, - charge_mode_config.eeprom_charge_mode_data.coarse_stop_threshold, charge_mode_config.eeprom_charge_mode_data.fine_stop_threshold, charge_mode_config.eeprom_charge_mode_data.set_point_sd_margin, charge_mode_config.eeprom_charge_mode_data.set_point_mean_margin, - charge_mode_config.eeprom_charge_mode_data.decimal_places); + charge_mode_config.eeprom_charge_mode_data.decimal_places, + boolean_to_string(charge_mode_config.eeprom_charge_mode_data.precharge_enable), + charge_mode_config.eeprom_charge_mode_data.precharge_time_ms, + charge_mode_config.eeprom_charge_mode_data.precharge_speed_rps); size_t data_length = strlen(charge_mode_json_buffer); file->data = charge_mode_json_buffer; diff --git a/src/charge_mode.h b/src/charge_mode.h index 05bf2ae..f87e006 100644 --- a/src/charge_mode.h +++ b/src/charge_mode.h @@ -6,7 +6,7 @@ #include "common.h" -#define EEPROM_CHARGE_MODE_DATA_REV 7 // 16 byte +#define EEPROM_CHARGE_MODE_DATA_REV 8 // 16 byte #define WEIGHT_STRING_LEN 8 @@ -29,6 +29,11 @@ typedef struct { decimal_places_t decimal_places; + // Precharge + bool precharge_enable; + uint32_t precharge_time_ms; + float precharge_speed_rps; + // LED related settings uint32_t neopixel_normal_charge_colour; uint32_t neopixel_under_charge_colour; diff --git a/src/cleanup_mode.cpp b/src/cleanup_mode.cpp index 7c6f32a..cf3d080 100644 --- a/src/cleanup_mode.cpp +++ b/src/cleanup_mode.cpp @@ -13,12 +13,13 @@ #include "common.h" #include "charge_mode.h" #include "cleanup_mode.h" +#include "servo_gate.h" // Memory from other modules extern QueueHandle_t encoder_event_queue; extern charge_mode_config_t charge_mode_config; - +extern servo_gate_t servo_gate; extern AppState_t exit_state; extern QueueHandle_t encoder_event_queue; @@ -78,6 +79,11 @@ void cleanup_render_task(void *p) { u8g2_SetFont(display_handler, u8g2_font_profont11_tf); u8g2_DrawStr(display_handler, 5, 45, buf); + memset(buf, 0x0, sizeof(buf)); + sprintf(buf, "Servo Gate: %s", gate_state_to_string(servo_gate.gate_state)); + u8g2_SetFont(display_handler, u8g2_font_profont11_tf); + u8g2_DrawStr(display_handler, 5, 55, buf); + u8g2_SendBuffer(display_handler); vTaskDelayUntil(&last_render_tick, pdMS_TO_TICKS(20)); diff --git a/src/eeprom.h b/src/eeprom.h index 8bd5f09..3e819c3 100644 --- a/src/eeprom.h +++ b/src/eeprom.h @@ -15,6 +15,7 @@ #define EEPROM_NEOPIXEL_LED_CONFIG_BASE_ADDR 7 * 1024 // 7k #define EEPROM_ROTARY_BUTTON_CONFIG_BASE_ADDR 8 * 1024 // 8k #define EEPROM_PROFILE_DATA_BASE_ADDR 9 * 1024 // 9k +#define EEPROM_SERVO_GATE_CONFIG_BASE_ADDR 10 * 1024 // 10k #define EEPROM_METADATA_REV 2 // 16 byte diff --git a/src/html/web_portal.html b/src/html/web_portal.html index e943d43..06f086b 100644 --- a/src/html/web_portal.html +++ b/src/html/web_portal.html @@ -13,7 +13,7 @@ @@ -71,11 +71,17 @@
-
Scale
+
General Control
+ +
+ + +
+ @@ -251,6 +257,26 @@ +
+ +
+ Enable Pre-Charge (requires servo gate) + +
+ +
+ Pre-Charge Duration (ms) + +
+ +
+ Pre-Charge Speed (rps) + +
+ @@ -484,6 +510,50 @@ + +