Skip to content
Open
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
4 changes: 3 additions & 1 deletion apps/tuya.ai/your_desk_emoji/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,7 @@ config ENABLE_CHAT_DISPLAY
if (ENABLE_CHAT_DISPLAY)
rsource "./src/display/Kconfig"
endif

config ENABLE_AUDIO_CHAT
bool "enable audio chat mode"
default y
endmenu
7 changes: 4 additions & 3 deletions apps/tuya.ai/your_desk_emoji/config/T5AI_MINI.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
CONFIG_BOARD_CHOICE_T5AI=y
CONFIG_BOARD_CHOICE_T5AI_MINI=y
CONFIG_ENABLE_LIBLVGL=y
CONFIG_ENABLE_CHAT_DISPLAY=y
CONFIG_ENABLE_GUI_EMOJI=y
CONFIG_BOARD_CHOICE_T5AI=y
CONFIG_BOARD_CHOICE_T5AI_MINI=y
CONFIG_T5AI_MINI_EX_MODULE_ST7735S_XLT=y
CONFIG_ENABLE_LIBLVGL=y
15 changes: 11 additions & 4 deletions apps/tuya.ai/your_desk_emoji/src/tuya_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ tuya_iot_client_t ai_client;
#define PROJECT_VERSION "1.0.0"
#endif

#define DPID_VOLUME 3
#define DPID_VOLUME 6 // Changed from 3 to 6 to match cloud configuration
#define DPID_SERVO 5

bool _s_servo_busy = FALSE;
Expand Down Expand Up @@ -228,8 +228,9 @@ OPERATE_RET audio_dp_obj_proc(dp_obj_recv_t *dpobj)
switch (dp->id) {
case DPID_VOLUME: {
uint8_t volume = dp->value.dp_value;
PR_DEBUG("volume:%d", volume);
PR_NOTICE("=== RECEIVED VOLUME DP FROM APP: %d ===", volume);
ai_audio_set_volume(volume);
PR_NOTICE("=== VOLUME SET SUCCESSFULLY ===");
#if defined(ENABLE_CHAT_DISPLAY) && (ENABLE_CHAT_DISPLAY == 1)
char volume_str[20] = {0};
snprintf(volume_str, sizeof(volume_str), "%s%d", VOLUME, volume);
Expand Down Expand Up @@ -267,9 +268,15 @@ OPERATE_RET ai_audio_volume_upload(void)
dp_obj.type = PROP_VALUE;
dp_obj.value.dp_value = volume;

PR_DEBUG("DP upload volume:%d", volume);
PR_NOTICE("=== UPLOADING VOLUME DP TO CLOUD: %d ===", volume);

return tuya_iot_dp_obj_report(client, client->activate.devid, &dp_obj, 1, 0);
OPERATE_RET ret = tuya_iot_dp_obj_report(client, client->activate.devid, &dp_obj, 1, 0);
if (ret == OPRT_OK) {
PR_NOTICE("=== VOLUME UPLOAD SUCCESS ===");
} else {
PR_ERR("=== VOLUME UPLOAD FAILED: %d ===", ret);
}
return ret;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions apps/tuya.ai/your_otto_robot/SERVO_IMPROVEMENTS_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


2 changes: 2 additions & 0 deletions apps/tuya.ai/your_otto_robot/SERVO_PROTECTION_IMPROVEMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


22 changes: 15 additions & 7 deletions apps/tuya.ai/your_otto_robot/src/otto/oscillator.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,18 +275,26 @@ void oscillator_write(int idx, int position)

int angle = osc->pos + osc->trim;

// Apply safety limits for all servos
angle = MIN(MAX(angle, 0), 180);

// Additional safety limits for hand servos (indices 4 and 5)
// to prevent mechanical damage and reduce stress
if (idx == 4 || idx == 5) { // LEFT_HAND or RIGHT_HAND
angle = MIN(MAX(angle, 20), 160); // More restrictive range for hands
PR_DEBUG("Hand servo %d: angle limited to safe range [20-160]: %d", idx, angle);
}

// 计算占空比
// Calculate the duty cycle
uint32_t duty = (uint32_t)((0.5 + angle / 180.0 * 2.0) * 10000 / 20);

// 计算占空比百分比 (duty/10000 * 100)
//float duty_percent = (float)duty / 100.0f;
// (duty/10000 * 100)
float duty_percent = (float)duty / 100.0f;

// 合并的占空比打印信息 - 显示百分比
// PR_DEBUG("oscillator_write: idx=%d, pin=%d, pwm_channel=%d, pos=%d->angle=%d(trim:%d), duty=%d, duty_percent=%.1f%%",
// idx, osc->pin, osc->pwm_channel, position, angle, osc->trim, duty, duty_percent);
// Combined duty cycle printing information - Displays percentage
PR_DEBUG("oscillator_write: idx=%d, pin=%d, pwm_channel=%d, pos=%d->angle=%d(trim:%d), duty=%d, duty_percent=%.1f%%",
idx, osc->pin, osc->pwm_channel, position, angle, osc->trim, duty, duty_percent);

tkl_pwm_duty_set(osc->pwm_channel, duty);
tkl_pwm_start(osc->pwm_channel);
}
}
62 changes: 56 additions & 6 deletions apps/tuya.ai/your_otto_robot/src/otto/otto_movements.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,11 +759,12 @@ void otto_hand_wave(int period, int dir)
return;
}


const int wave_amplitude = 30;
const int wave_cycles = 5;
const int raise_time = 300;
// Reduced parameters to protect servo from overheating
const int wave_amplitude = 20; // Reduced from 30 to 20 degrees (33% less stress)
const int wave_cycles = 3; // Reduced from 5 to 3 cycles (40% less work)
const int raise_time = 400; // Increased from 300ms for smoother motion
const int wave_time = period / 10;
const int rest_time = 100; // Add rest time between cycles for cooling


const int left_raised = 170;
Expand All @@ -789,19 +790,24 @@ void otto_hand_wave(int period, int dir)


for (int cycle = 0; cycle < wave_cycles; cycle++) {

// Wave inward
if (wave_left)
positions[LEFT_HAND] = left_raised - wave_amplitude;
if (wave_right)
positions[RIGHT_HAND] = right_raised + wave_amplitude;
otto_move_servos(wave_time, positions);


// Wave outward
if (wave_left)
positions[LEFT_HAND] = left_raised + wave_amplitude;
if (wave_right)
positions[RIGHT_HAND] = right_raised - wave_amplitude;
otto_move_servos(wave_time, positions);

// Add rest time between cycles to prevent overheating
if (cycle < wave_cycles - 1) { // Don't rest after last cycle
tal_system_sleep(rest_time);
}
}

if (wave_left)
Expand All @@ -811,3 +817,47 @@ void otto_hand_wave(int period, int dir)
otto_move_servos(raise_time, positions);
}

//---------------------------------------------------------
//-- Hand servos sleep mode to prevent overheating
//---------------------------------------------------------
void otto_hands_sleep(void)
{
if (!g_otto.has_hands) {
return;
}

PR_DEBUG("Putting hand servos to sleep to prevent overheating");

// Stop PWM signal to hand servos
if (g_otto.oscillator_indices[LEFT_HAND] != -1) {
oscillator_stop(g_otto.oscillator_indices[LEFT_HAND]);
}
if (g_otto.oscillator_indices[RIGHT_HAND] != -1) {
oscillator_stop(g_otto.oscillator_indices[RIGHT_HAND]);
}

PR_DEBUG("Hand servos are now in sleep mode");
}

//---------------------------------------------------------
//-- Wake up hand servos
//---------------------------------------------------------
void otto_hands_wake(void)
{
if (!g_otto.has_hands) {
return;
}

PR_DEBUG("Waking up hand servos");

// Resume PWM signal to hand servos
if (g_otto.oscillator_indices[LEFT_HAND] != -1) {
oscillator_play(g_otto.oscillator_indices[LEFT_HAND]);
}
if (g_otto.oscillator_indices[RIGHT_HAND] != -1) {
oscillator_play(g_otto.oscillator_indices[RIGHT_HAND]);
}

PR_DEBUG("Hand servos are now awake");
}

18 changes: 17 additions & 1 deletion apps/tuya.ai/your_otto_robot/src/otto/otto_movements.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
#define BIG 30 /**< Large movement amplitude */

// -- Servo speed limit default (degrees per second)
#define SERVO_LIMIT_DEFAULT 240
#define SERVO_LIMIT_DEFAULT 120 /**< Default servo speed limit: 120 deg/s (reduced for safety) */
#define SERVO_LIMIT_HAND 60 /**< Hand servo speed limit: 60 deg/s (slower for heavy load) */

// -- Servo indexes for easy access
#define LEFT_LEG 0 /**< Left leg servo index */
Expand All @@ -42,6 +43,10 @@
/**< Default hand home position angle */
#define HAND_HOME_POSITION 45

// Hand servo safety angle limits to prevent mechanical damage
#define HAND_ANGLE_MIN 20 /**< Minimum safe angle for hand servos */
#define HAND_ANGLE_MAX 160 /**< Maximum safe angle for hand servos */


/**
* @brief Otto robot structure containing all servo and state information
Expand Down Expand Up @@ -301,6 +306,17 @@ void otto_enable_servo_limit(int speed_limit_degree_per_sec);
*/
void otto_disable_servo_limit(void);

/**
* @brief Put hand servos to sleep (stop PWM) to prevent overheating
* Useful when hands are not being used for extended periods
*/
void otto_hands_sleep(void);

/**
* @brief Wake up hand servos (restart PWM)
*/
void otto_hands_wake(void);

/**
* @brief Execute complex servo movement with oscillation parameters
* @param amplitude Array of amplitudes for each servo in degrees
Expand Down
10 changes: 10 additions & 0 deletions apps/tuya.ai/your_otto_robot/src/otto/otto_robot_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ void otto_power_on()
otto_init(PIN_LEFT_LEG, PIN_RIGHT_LEG, PIN_LEFT_FOOT, PIN_RIGHT_FOOT, -1, -1);

// otto_set_trims(0, 0, 0, 0, 0, 0);
// Set slower speed limit for legs and feet (120 deg/s)
otto_enable_servo_limit(SERVO_LIMIT_DEFAULT);

// Move legs and feet to home position
Expand All @@ -346,6 +347,15 @@ void otto_power_on()
PR_DEBUG("Initializing hands...");
otto_init_hands_only_wrapper();

// Set much slower speed limit for hand servos to prevent overheating (60 deg/s)
PR_DEBUG("Setting hand servo speed limit to %d deg/s (slower for protection)", SERVO_LIMIT_HAND);
if (g_otto.oscillator_indices[LEFT_HAND] != -1) {
oscillator_set_limiter(g_otto.oscillator_indices[LEFT_HAND], SERVO_LIMIT_HAND);
}
if (g_otto.oscillator_indices[RIGHT_HAND] != -1) {
oscillator_set_limiter(g_otto.oscillator_indices[RIGHT_HAND], SERVO_LIMIT_HAND);
}

// Set trim values for all servos from KV storage
otto_set_trims_from_kv();

Expand Down