Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add servo gate #47

Merged
merged 16 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ target_link_libraries("${TARGET_NAME}"
hardware_pio
hardware_spi
hardware_i2c
hardware_pwm
FreeRTOS-Kernel
FreeRTOS-Kernel-Heap4
u8g2
Expand Down
5 changes: 4 additions & 1 deletion src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include "rotary_button.h"
#include "menu.h"
#include "profile.h"

#include "servo_gate.h"


uint8_t software_reboot() {
Expand Down Expand Up @@ -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();
Expand Down
52 changes: 48 additions & 4 deletions src/charge_mode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion src/charge_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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;
Expand Down
8 changes: 7 additions & 1 deletion src/cleanup_mode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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));
Expand Down
1 change: 1 addition & 0 deletions src/eeprom.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
97 changes: 95 additions & 2 deletions src/html/web_portal.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<style>
/* Exclude the pixels taken by the bottom nav bar */
.exclude-bottom-nav {
padding-bottom: 74px;
padding-bottom: 64px;
}
</style>
</head>
Expand Down Expand Up @@ -71,11 +71,17 @@
</section>

<div class="grid grid-cols-1 gap-2 px-4">
<div class="divider">Scale</div>
<div class="divider">General Control</div>
<div class="grid grid-cols-1 gap-2">
<button class="btn btn-neutral" onclick="scaleForceZero()">Scale Zero</button>

<div class="grid grid-cols-2 gap-2">
<button class="btn btn-neutral" onclick="servoGateSetState(2)">Gate Open</button>
<button class="btn btn-neutral" onclick="servoGateSetState(1)">Gate Close</button>
</div>
</div>
</div>

</div>
</section>

Expand Down Expand Up @@ -251,6 +257,26 @@
</select>
</div>

<div class="divider"></div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Enable Pre-Charge (requires servo gate)</span>
<select class="select select-bordered" name="c10">
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Pre-Charge Duration (ms)</span>
<input type="number" class="input input-bordered" name="c11" step="1">
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Pre-Charge Speed (rps)</span>
<input type="number" class="input input-bordered" name="c12" step="0.001">
</div>

<button class="btn btn-neutral settings-apply-btn">Apply</button>
</form>
</section>
Expand Down Expand Up @@ -484,6 +510,50 @@
</form>
</section>

<section class="settings-page" id="settings-servo-gate" name="Servo Gate" style="display: none;">
<form id="servoGateConfigForm" action="/rest/servo_gate_config" class="grid grid-cols-1 gap-3">
<div class="grid grid-cols-1 gap-1">
<span class="label-text">Servo Gate Enable</span>
<select class="select select-bordered" name="c0">
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Shutter 0 Close Duty Cycle</span>
<input type="number" class="input input-bordered" name="c1" step="0.001">
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Shutter 0 Open Duty Cycle</span>
<input type="number" class="input input-bordered" name="c2" step="0.001">
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Shutter 1 Close Duty Cycle</span>
<input type="number" class="input input-bordered" name="c3" step="0.001">
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Shutter 1 Open Duty Cycle</span>
<input type="number" class="input input-bordered" name="c4" step="0.001">
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Shutter Close Speed (%/s)</span>
<input type="number" class="input input-bordered" name="c5" step="0.001">
</div>

<div class="grid grid-cols-1 gap-1">
<span class="label-text">Shutter Open Speed (%/s)</span>
<input type="number" class="input input-bordered" name="c6" step="0.001">
</div>

<button class="btn btn-neutral settings-apply-btn">Apply</button>
</form>
</section>

<!-- System Control Page -->
<section class="settings-page" id="settings-system-control" name="System Control" style="display: none;">
<form id="systemControlForm" action="/rest/system_control" class="grid grid-cols-1 gap-3">
Expand Down Expand Up @@ -555,6 +625,7 @@
<li><a class="text-lg" onclick="onSettingsLinkClicked('settings-fine-motor')">Fine Motor</a></li>
<li><a class="text-lg" onclick="onSettingsLinkClicked('settings-neopixel-led')">Neopixel LED</a></li>
<li><a class="text-lg" onclick="onSettingsLinkClicked('settings-button')">Buttons</a></li>
<li><a class="text-lg" onclick="onSettingsLinkClicked('settings-servo-gate')">Servo Gate</a></li>
<li><a class="text-lg" onclick="onSettingsLinkClicked('settings-system-control')">System Control</a></li>
</ul>
</div>
Expand Down Expand Up @@ -730,6 +801,12 @@ <h3 class="font-bold text-lg">Error</h3>
ENTER: 1,
});

const ServoGateState = Object.freeze({
GATE_DISABLED: 0,
GATE_CLOSE: 1,
GATE_OPEN: 2,
});

var pollSetTimeoutId;

// Set Charge Mode Set Point with REST interface
Expand Down Expand Up @@ -991,6 +1068,22 @@ <h3 class="font-bold text-lg">Error</h3>
});
}

function servoGateSetState(state) {
const uri = `/rest/servo_gate_state?g0=${encodeURIComponent(state)}`;

// Call the scale action URI
fetch(uri)
.then(response => {
return response.json();
})
.then(data => {
// console.log(data);
})
.catch(error => {
console.error("Error applying servo gate state");
});
}

// Switch pages
function onNavButtonClicked(button) {
const sectionTrickler = document.getElementById("sectionTrickler");
Expand Down
Loading