Skip to content

Commit

Permalink
Merge branch 'feature/resolve_joystick_adc_jitter_issue' into 'master'
Browse files Browse the repository at this point in the history
feat(esp_joystick): eliminate joystick ADC jitter

Closes AEG-1578

See merge request ae_group/esp-box!110
  • Loading branch information
leeebo committed Jun 12, 2024
2 parents dbe8ef9 + 6b3993b commit 674f54a
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ void ble_hid_send_joystick_value(uint16_t joystick_buttons, uint8_t joystick_x,
buffer[3] = (joystick_y) - 1; /* LY */
buffer[4] = (joystick_z); /* RX */
buffer[5] = (joystick_rx) - 1; /* RY */
esp_hidd_dev_input_set(s_ble_hid_param.hid_dev, 0, HID_RPT_ID_CC_GP_IN, buffer, HID_CC_IN_RPT_GP_LEN);
esp_err_t ret = esp_hidd_dev_input_set(s_ble_hid_param.hid_dev, 0, HID_RPT_ID_CC_GP_IN, buffer, HID_CC_IN_RPT_GP_LEN);
if (ret != ESP_OK) {
ESP_LOGE(BLE_HID_TAG, "Failed to send key value via BLE-HID.");
}
return;
}

Expand Down
88 changes: 78 additions & 10 deletions examples/esp_joystick/joystick_controller/main/app/app_rocker.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,84 @@ esp_err_t rocker_adc_init(void)
return ESP_OK;
}

void get_rocker_adc_value(uint16_t rocker_value[4])
void get_rocker_adc_value_in_game_mode(uint16_t rocker_value[4])
{
adc_oneshot_read(game_mode_adc_handle, LEFT_HOTAS1_ADC_CHAN, &g_left_hotas1_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, LEFT_HOTAS2_ADC_CHAN, &g_left_hotas2_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, RIGHT_HOTAS1_ADC_CHAN, &g_right_hotas1_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, RIGHT_HOTAS2_ADC_CHAN, &g_right_hotas2_adc_raw[0][0]);
if (do_left_hotas1_adc_chan && do_left_hotas2_adc_chan && do_right_hotas1_adc_chan && do_right_hotas2_adc_chan) {
rocker_value[0] = g_left_hotas1_adc_raw[0][0];
rocker_value[1] = g_left_hotas2_adc_raw[0][0];
rocker_value[2] = g_right_hotas1_adc_raw[0][0];
rocker_value[3] = g_right_hotas2_adc_raw[0][0];
for (int i = 0; i < 4; i++) {
rocker_value[i] = 0;
}
int left_hotas1_adc_value[ADC_MEAS_WINDOW_SIZE] = {0};
int left_hotas2_adc_value[ADC_MEAS_WINDOW_SIZE] = {0};
int right_hotas1_adc_value[ADC_MEAS_WINDOW_SIZE] = {0};
int right_hotas2_adc_value[ADC_MEAS_WINDOW_SIZE] = {0};
for (int i = 0; i < ADC_MEAS_WINDOW_SIZE; i++) {
int left_hotas1_value = 0;
int left_hotas2_value = 0;
int right_hotas1_value = 0;
int right_hotas2_value = 0;
for (int j = 0; j < 10; j++) {
adc_oneshot_read(game_mode_adc_handle, LEFT_HOTAS1_ADC_CHAN, &g_left_hotas1_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, LEFT_HOTAS2_ADC_CHAN, &g_left_hotas2_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, RIGHT_HOTAS1_ADC_CHAN, &g_right_hotas1_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, RIGHT_HOTAS2_ADC_CHAN, &g_right_hotas2_adc_raw[0][0]);
if (do_left_hotas1_adc_chan && do_left_hotas2_adc_chan && do_right_hotas1_adc_chan && do_right_hotas2_adc_chan) {
left_hotas1_value += g_left_hotas1_adc_raw[0][0];
left_hotas2_value += g_left_hotas2_adc_raw[0][0];
right_hotas1_value += g_right_hotas1_adc_raw[0][0];
right_hotas2_value += g_right_hotas2_adc_raw[0][0];
}
}
left_hotas1_value = left_hotas1_value / 10;
left_hotas2_value = left_hotas2_value / 10;
right_hotas1_value = right_hotas1_value / 10;
right_hotas2_value = right_hotas2_value / 10;
left_hotas1_adc_value[i] = left_hotas1_value;
left_hotas2_adc_value[i] = left_hotas2_value;
right_hotas1_adc_value[i] = right_hotas1_value;
right_hotas2_adc_value[i] = right_hotas2_value;
}
for (int i = 0; i < ADC_MEAS_WINDOW_SIZE; i++) {
rocker_value[0] += left_hotas1_adc_value[i];
rocker_value[1] += left_hotas2_adc_value[i];
rocker_value[2] += right_hotas1_adc_value[i];
rocker_value[3] += right_hotas2_adc_value[i];
}
rocker_value[0] = rocker_value[0] / ADC_MEAS_WINDOW_SIZE;
rocker_value[1] = rocker_value[1] / ADC_MEAS_WINDOW_SIZE;
rocker_value[2] = rocker_value[2] / ADC_MEAS_WINDOW_SIZE;
rocker_value[3] = rocker_value[3] / ADC_MEAS_WINDOW_SIZE;
}

void get_rocker_adc_value_in_rc_mode(uint16_t rocker_value[4], uint8_t meas_count, float filter_coef)
{
float left_hotas1_filtered_value = (float)rocker_value[0];
float left_hotas2_filtered_value = (float)rocker_value[1];
float right_hotas1_filtered_value = (float)rocker_value[2];
float right_hotas2_filtered_value = (float)rocker_value[3];

float left_hotas1_value = 0.0F;
float left_hotas2_value = 0.0F;
float right_hotas1_value = 0.0F;
float right_hotas2_value = 0.0F;
for (int i = 0; i < meas_count; i++) {
adc_oneshot_read(game_mode_adc_handle, LEFT_HOTAS1_ADC_CHAN, &g_left_hotas1_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, LEFT_HOTAS2_ADC_CHAN, &g_left_hotas2_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, RIGHT_HOTAS1_ADC_CHAN, &g_right_hotas1_adc_raw[0][0]);
adc_oneshot_read(game_mode_adc_handle, RIGHT_HOTAS2_ADC_CHAN, &g_right_hotas2_adc_raw[0][0]);
if (do_left_hotas1_adc_chan && do_left_hotas2_adc_chan && do_right_hotas1_adc_chan && do_right_hotas2_adc_chan) {
left_hotas1_value += g_left_hotas1_adc_raw[0][0] / (meas_count * 1.0);
left_hotas2_value += g_left_hotas2_adc_raw[0][0] / (meas_count * 1.0);
right_hotas1_value += g_right_hotas1_adc_raw[0][0] / (meas_count * 1.0);
right_hotas2_value += g_right_hotas2_adc_raw[0][0] / (meas_count * 1.0);
}
}

left_hotas1_filtered_value = left_hotas1_filtered_value * filter_coef + (1 - filter_coef) * left_hotas1_value;
left_hotas2_filtered_value = left_hotas2_filtered_value * filter_coef + (1 - filter_coef) * left_hotas2_value;
right_hotas1_filtered_value = right_hotas1_filtered_value * filter_coef + (1 - filter_coef) * right_hotas1_value;
right_hotas2_filtered_value = right_hotas2_filtered_value * filter_coef + (1 - filter_coef) * right_hotas2_value;

rocker_value[0] = (int)left_hotas1_filtered_value;
rocker_value[1] = (int)left_hotas2_filtered_value;
rocker_value[2] = (int)right_hotas1_filtered_value;
rocker_value[3] = (int)right_hotas2_filtered_value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ extern "C" {
#define RIGHT_HOTAS2_ADC_CHAN ADC_CHANNEL_3

#define EXAMPLE_ADC_ATTEN 3
#define ADC_MEAS_WINDOW_SIZE 10

esp_err_t rocker_adc_init(void);
void get_rocker_adc_value(uint16_t rocker_value[4]);
void get_rocker_adc_value_in_game_mode(uint16_t rocker_value[4]);
void get_rocker_adc_value_in_rc_mode(uint16_t rocker_value[4], uint8_t meas_count, float filter_coef);

#ifdef __cplusplus
}
Expand Down
63 changes: 37 additions & 26 deletions examples/esp_joystick/joystick_controller/main/app_ui_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ static void game_pad_app_task(void *pvParameters)
}
}

if (1 == read_rocker_value_from_flash("hid_mode")) {
g_hid_mode = 1;
lv_obj_set_x(ui_hidModeSelectBtnPart, 22);
lv_label_set_text(ui_hidModeSelectLab, "BLE");
} else {
g_hid_mode = 0;
lv_obj_set_x(ui_hidModeSelectBtnPart, -22);
lv_label_set_text(ui_hidModeSelectLab, "USB");
}

box_rc_button_init();

if ( !(ROCKER_ADC_INIT_STATE & xEventGroupGetBits(g_init_event_grp))) {
Expand Down Expand Up @@ -170,7 +180,7 @@ static void game_pad_app_task(void *pvParameters)
while (1) {
while (1 == g_rocker_calibration_state) {
uint16_t rocker_adc_value[4] = {0};
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);

bsp_display_lock(0);
if (rocker_adc_value[0] >= left_rocker_x_adc_value[1]) {
Expand Down Expand Up @@ -281,10 +291,10 @@ static void rc_app_task(void *pvParameters)
right_rocker_y_adc_value[2] = read_rocker_value_from_flash("right_y_max");
}

uint16_t rocker_adc_value[4] = {0};
while (1) {
while (1 == g_rocker_calibration_state) {
uint16_t rocker_adc_value[4] = {0};
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_rc_mode(rocker_adc_value, 10, 0.6);

if (rocker_adc_value[0] >= left_rocker_x_adc_value[1]) {
rocker_x1 = (int)(((rocker_adc_value[0] - left_rocker_x_adc_value[1] * 1.0) / ((left_rocker_x_adc_value[2] - left_rocker_x_adc_value[1]) * 1.0)) * RC_ROCKET_RANGE);
Expand Down Expand Up @@ -407,19 +417,18 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
right_rocker_x_adc_value[1] = 0;
right_rocker_y_adc_value[1] = 0;

for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
for (int i = 0; i < 10; i++) {
get_rocker_adc_value_in_game_mode(rocker_adc_value);
left_rocker_x_adc_value[1] += rocker_adc_value[0];
left_rocker_y_adc_value[1] += rocker_adc_value[1];
right_rocker_x_adc_value[1] += rocker_adc_value[2];
right_rocker_y_adc_value[1] += rocker_adc_value[3];
printf("%d, %d, %d, %d\n", rocker_adc_value[0], rocker_adc_value[1], rocker_adc_value[2], rocker_adc_value[3]);
vTaskDelay(pdMS_TO_TICKS(10));
}
left_rocker_x_adc_value[1] = left_rocker_x_adc_value[1] / 5;
left_rocker_y_adc_value[1] = left_rocker_y_adc_value[1] / 5;
right_rocker_x_adc_value[1] = right_rocker_x_adc_value[1] / 5;
right_rocker_y_adc_value[1] = right_rocker_y_adc_value[1] / 5;
left_rocker_x_adc_value[1] = left_rocker_x_adc_value[1] / 10.0;
left_rocker_y_adc_value[1] = left_rocker_y_adc_value[1] / 10.0;
right_rocker_x_adc_value[1] = right_rocker_x_adc_value[1] / 10.0;
right_rocker_y_adc_value[1] = right_rocker_y_adc_value[1] / 10.0;
printf("left x-mid: %d, left y-mid: %d, right x-mid: %d, right y-mid: %d\n", left_rocker_x_adc_value[1], left_rocker_y_adc_value[1],
right_rocker_x_adc_value[1], right_rocker_y_adc_value[1]);
sprintf(rocker_value_str, "%d", left_rocker_x_adc_value[1]);
Expand All @@ -440,7 +449,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[0] > left_rocker_x_adc_value[1] - 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_x(ui_leftRockerCalibrateBtn, -18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -450,7 +459,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
left_rocker_x_adc_value[0] = 0;
// Update the left rocker X axis minimum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
left_rocker_x_adc_value[0] += rocker_adc_value[0];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand All @@ -470,7 +479,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[0] < left_rocker_x_adc_value[1] + 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_x(ui_leftRockerCalibrateBtn, 18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -479,7 +488,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
left_rocker_x_adc_value[2] = 0;
// Update the left rocker X axis maximum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
left_rocker_x_adc_value[2] += rocker_adc_value[0];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand All @@ -500,7 +509,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[1] < left_rocker_y_adc_value[1] + 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_y(ui_leftRockerCalibrateBtn, -18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -509,7 +518,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
left_rocker_y_adc_value[2] = 0;
// Update the left rocker Y axis maximum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
left_rocker_y_adc_value[2] += rocker_adc_value[1];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand All @@ -527,7 +536,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[1] > left_rocker_y_adc_value[1] - 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_y(ui_leftRockerCalibrateBtn, 18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -536,7 +545,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
left_rocker_y_adc_value[0] = 0;
// Update the left rocker Y axis minimum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
left_rocker_y_adc_value[0] += rocker_adc_value[1];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand All @@ -554,7 +563,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[2] > right_rocker_x_adc_value[1] - 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_x(ui_rightRockerCalibrateBtn, -18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -563,7 +572,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
right_rocker_x_adc_value[0] = 0;
// Update the right rocker X axis minimum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
right_rocker_x_adc_value[0] += rocker_adc_value[2];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand All @@ -582,7 +591,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[2] < right_rocker_x_adc_value[1] + 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_x(ui_rightRockerCalibrateBtn, 18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -591,7 +600,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
right_rocker_x_adc_value[2] = 0;
// Update the right rocker X axis maximum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
right_rocker_x_adc_value[2] += rocker_adc_value[2];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand All @@ -611,7 +620,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[3] < right_rocker_y_adc_value[1] + 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_y(ui_rightRockerCalibrateBtn, -18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -620,7 +629,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
right_rocker_y_adc_value[2] = 0;
// Update the right rocker Y axis maximum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
right_rocker_y_adc_value[2] += rocker_adc_value[3];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand All @@ -638,7 +647,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
lv_refr_now(NULL);
// Wait for the rocker to push into position
while (rocker_adc_value[3] > right_rocker_y_adc_value[1] - 600) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
lv_obj_set_y(ui_rightRockerCalibrateBtn, 18);
lv_refr_now(NULL);
vTaskDelay(pdMS_TO_TICKS(10));
Expand All @@ -647,7 +656,7 @@ void app_ui_event_rocker_calibration(lv_event_t *e)
right_rocker_y_adc_value[0] = 0;
// Update the right rocker Y axis minimum
for (int i = 0; i < 5; i++) {
get_rocker_adc_value(rocker_adc_value);
get_rocker_adc_value_in_game_mode(rocker_adc_value);
right_rocker_y_adc_value[0] += rocker_adc_value[3];
vTaskDelay(pdMS_TO_TICKS(10));
}
Expand Down Expand Up @@ -682,10 +691,12 @@ void app_ui_event_hid_mode_select(lv_event_t *e)
ESP_LOGI(GAME_PAD_APP_TAG, "BLE HID mode.");
lv_obj_set_x(ui_hidModeSelectBtnPart, 22);
lv_label_set_text(ui_hidModeSelectLab, "BLE");
flash_write_state("hid_mode", "1");
} else {
ESP_LOGI(GAME_PAD_APP_TAG, "USB HID mode.");
lv_obj_set_x(ui_hidModeSelectBtnPart, -22);
lv_label_set_text(ui_hidModeSelectLab, "USB");
flash_write_state("hid_mode", "0");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
targets:
- esp32s3
dependencies:
lvgl/lvgl:
version: "^8"
public: true
espressif/esp-now: "^2.4.0"
espressif/esp-box-3: "^1.1.2"
espressif/button: "^3.1.3"
Expand Down

0 comments on commit 674f54a

Please sign in to comment.