Skip to content

Commit

Permalink
Merge pull request #47 from eamars/add_servo
Browse files Browse the repository at this point in the history
Add servo gate
  • Loading branch information
eamars authored May 6, 2024
2 parents 8bbad2d + 363ee36 commit 69c5558
Show file tree
Hide file tree
Showing 15 changed files with 607 additions and 12 deletions.
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

0 comments on commit 69c5558

Please sign in to comment.