From dcb86c6b4684d584845ca11d5d51845be0406d71 Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Mon, 6 Apr 2026 19:11:29 -0400 Subject: [PATCH 01/13] Got planting done --- app/CMakeLists.txt | 3 +- app/esp32s3_devkitc_procpu.overlay | 14 ---- app/include/dig.h | 6 ++ app/include/imu.h | 32 --------- app/include/motor.h | 2 + app/include/place.h | 14 ++++ app/include/tamp.h | 8 +++ app/include/types.h | 2 - app/src/dig.c | 23 +++++-- app/src/imu.c | 100 ----------------------------- app/src/motor.c | 7 ++ app/src/place.c | 27 ++++++++ app/src/tamp.c | 18 ++++++ 13 files changed, 103 insertions(+), 153 deletions(-) delete mode 100644 app/include/imu.h create mode 100644 app/include/place.h create mode 100644 app/include/tamp.h delete mode 100644 app/src/imu.c create mode 100644 app/src/place.c create mode 100644 app/src/tamp.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 1c2133e..2c729b9 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -12,7 +12,8 @@ target_sources(app PRIVATE src/drive.c src/dig.c src/crsf.c - src/imu.c + src/place.c + src/tamp.c ) target_include_directories(app PRIVATE include) \ No newline at end of file diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index 11b68e0..537f91c 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -53,20 +53,6 @@ /* ← lsm6dso does NOT belong here */ }; -/* lsm6dso goes here instead */ -&i2c0 { - status = "okay"; - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - clock-frequency = ; - - lsm6dso: lsm6dso@6b { - compatible = "st,lsm6dso"; - reg = <0x6b>; - status = "okay"; - }; -}; - // CRSF serial, baud rate at 420000 &uart1 { status = "okay"; diff --git a/app/include/dig.h b/app/include/dig.h index a85105b..429994d 100644 --- a/app/include/dig.h +++ b/app/include/dig.h @@ -1,8 +1,14 @@ #ifndef DIG_H #define DIG_H #include "types.h" +#include "place.h" + +#define DIG_LOWER_TIME_MS 5000 +#define POST_DIG_DRIVE_TIME_MS 5000 int dig(mcu_t *mcu); int move_dig_motor(mcu_t *mcu); +int post_dig_drive(mcu_t *mcu); + #endif // DIG_H \ No newline at end of file diff --git a/app/include/imu.h b/app/include/imu.h deleted file mode 100644 index fb2d1b3..0000000 --- a/app/include/imu.h +++ /dev/null @@ -1,32 +0,0 @@ -// imu.h -#ifndef IMU_H -#define IMU_H - -#include -#include -#include -#include -#include -#include - -typedef struct { - float x; - float y; - float z; -} accel_data_t; - -typedef struct { - float x; - float y; - float z; -} gyro_data_t; - -const struct device *get_lsm6dso_device(void); - -int configure_sensor(const struct device *dev); - -int read_imu_data(const struct device *dev, - accel_data_t *accel, - gyro_data_t *gyro); - -#endif /* IMU_H */ \ No newline at end of file diff --git a/app/include/motor.h b/app/include/motor.h index 408166a..5477fe7 100644 --- a/app/include/motor.h +++ b/app/include/motor.h @@ -3,6 +3,8 @@ #include "types.h" #include "drive.h" +#define PUL_PER_REV 400 + /* API */ int init_motor(mcu_t *mcu); int move_motor(mcu_t *mcu); diff --git a/app/include/place.h b/app/include/place.h new file mode 100644 index 0000000..6e49d34 --- /dev/null +++ b/app/include/place.h @@ -0,0 +1,14 @@ +#ifndef PLACE_H +#define PLACE_H +#include "types.h" +#include "motor.h" +#include "servo.h" + +#define SOIL_TIME_OPEN_MS 5000 //TODO: Figure out value + +int place(mcu_t *mcu); +int place_plant(mcu_t *mcu); +int place_dirt(mcu_t *mcu); + + +#endif //PLACE_H \ No newline at end of file diff --git a/app/include/tamp.h b/app/include/tamp.h new file mode 100644 index 0000000..24164a9 --- /dev/null +++ b/app/include/tamp.h @@ -0,0 +1,8 @@ +#ifndef TAMP_H +#define TAMP_H +#include "types.h" + +int tamp(mcu_t *mcu); +int tamp_soil(mcu_t *mcu); + +#endif //TAMP_H \ No newline at end of file diff --git a/app/include/types.h b/app/include/types.h index 2ca0c27..39abf45 100644 --- a/app/include/types.h +++ b/app/include/types.h @@ -8,10 +8,8 @@ typedef enum { Bootup, Idle, Drive, - LowerDrill, Dig, Place, - Replace, Tamp, } state_t; diff --git a/app/src/dig.c b/app/src/dig.c index 84a8669..4264b08 100644 --- a/app/src/dig.c +++ b/app/src/dig.c @@ -4,23 +4,38 @@ int dig(mcu_t *mcu) { if (mcu->state != Dig) { - return 0; + printk("\nGot to Dig but state was %d, returning.", mcu->state); + return 1; } move_dig_motor(mcu); + post_dig_drive(mcu); + mcu->state = Place; + place(mcu); return 0; } int move_dig_motor(mcu_t *mcu) { // Lower/Dig - step_motor(mcu->digStepper, 400, 5000, MOTOR_FORWARD); // If DIP switch is at 400, this is one revolution at 60rpm + set_step_motor(mcu->digStepper, 360, 60, MOTOR_FORWARD); // If DIP switch is at 400, this is one revolution at 60rpm TODO: Change later set_motor_speed(mcu->digActuator, MOTOR_FORWARD, 100); // Wait - k_sleep(K_MSEC(5000)); + k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); // Raise/Stop Digging - step_motor(mcu->digStepper, 400, 5000, MOTOR_BACKWARD); // If DIP switch is at 400, this is one revolution at 60rpm + set_step_motor(mcu->digStepper, 0, 0, MOTOR_STOP); // If DIP switch is at 400, this is one revolution at 60rpm set_motor_speed(mcu->digActuator, MOTOR_BACKWARD, 100); + return 0; +} + +int post_dig_drive(mcu_t *mcu) { + set_motor_speed(mcu->driveLeft, MOTOR_FORWARD, 50); + set_motor_speed(mcu->driveRight, MOTOR_FORWARD, 50); + + k_sleep(K_MSEC(POST_DIG_DRIVE_TIME_MS)); + + set_motor_speed(mcu->driveLeft, MOTOR_STOP, 50); + set_motor_speed(mcu->driveRight, MOTOR_STOP, 50); return 0; } \ No newline at end of file diff --git a/app/src/imu.c b/app/src/imu.c deleted file mode 100644 index 7b3c6cb..0000000 --- a/app/src/imu.c +++ /dev/null @@ -1,100 +0,0 @@ -// imu: magnometer + gyroscope + accelerometer -// LSM6DSO IMU sensor driver using Zephyr's sensor API - -#include "imu.h" -#include -#include -#include -#include - -LOG_MODULE_REGISTER(lsm6dso, LOG_LEVEL_INF); - -#define LSM6DSO_NODE DT_NODELABEL(lsm6dso) - -const struct device *get_lsm6dso_device(void) -{ - const struct device *dev = DEVICE_DT_GET(LSM6DSO_NODE); // ← Changed this! - - if (dev == NULL) { - LOG_ERR("No LSM6DSO device found in device tree!"); - return NULL; - } - - if (!device_is_ready(dev)) { - LOG_ERR("Device %s is not ready", dev->name); - return NULL; - } - - LOG_INF("Found device %s", dev->name); - return dev; -} - -int configure_sensor(const struct device *dev) -{ - struct sensor_value odr; - int ret; - - // Set Output Data Rate (ODR) to 104 Hz - odr.val1 = 104; - odr.val2 = 0; - - // Configure Accelerometer ODR - ret = sensor_attr_set(dev, - SENSOR_CHAN_ACCEL_XYZ, - SENSOR_ATTR_SAMPLING_FREQUENCY, - &odr); - if (ret != 0) { - LOG_ERR("Failed to set accel ODR: %d", ret); - return ret; - } - - // Configure Gyroscope ODR - ret = sensor_attr_set(dev, - SENSOR_CHAN_GYRO_XYZ, - SENSOR_ATTR_SAMPLING_FREQUENCY, - &odr); - if (ret != 0) { - LOG_ERR("Failed to set gyro ODR: %d", ret); - return ret; - } - - LOG_INF("Sensor configured: ODR = %d Hz", odr.val1); - return 0; -} - -int read_imu_data(const struct device *dev, - accel_data_t *accel, - gyro_data_t *gyro) -{ - int ret; - struct sensor_value accel_val[3]; - struct sensor_value gyro_val[3]; - - // Fetch ALL sensor data at once - ret = sensor_sample_fetch(dev); - if (ret != 0) { - LOG_ERR("Failed to fetch IMU data: %d", ret); - return ret; - } - - // Get accelerometer data - sensor_channel_get(dev, SENSOR_CHAN_ACCEL_X, &accel_val[0]); - sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Y, &accel_val[1]); - sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Z, &accel_val[2]); - - // Get gyroscope data - sensor_channel_get(dev, SENSOR_CHAN_GYRO_X, &gyro_val[0]); - sensor_channel_get(dev, SENSOR_CHAN_GYRO_Y, &gyro_val[1]); - sensor_channel_get(dev, SENSOR_CHAN_GYRO_Z, &gyro_val[2]); - - // Convert to float - accel->x = sensor_value_to_float(&accel_val[0]); - accel->y = sensor_value_to_float(&accel_val[1]); - accel->z = sensor_value_to_float(&accel_val[2]); - - gyro->x = sensor_value_to_float(&gyro_val[0]); - gyro->y = sensor_value_to_float(&gyro_val[1]); - gyro->z = sensor_value_to_float(&gyro_val[2]); - - return 0; -} \ No newline at end of file diff --git a/app/src/motor.c b/app/src/motor.c index bb59c5b..24ca856 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -239,6 +239,12 @@ int set_motor_speed(motor_t *motor, motor_direction_t dir, uint8_t speed_pct) return 0; } +int set_step_motor(motor_t *motor, uint8_t degrees, uint8_t rpm, motor_direction_t direction) { + uint8_t pulses = (degrees / 360) * PUL_PER_REV; + uint8_t step_period = 60000000 / (rpm * PUL_PER_REV); + step_motor(motor, pulses, step_period, direction); +} + /* ----------------------------------------------------------------------- * step_motor — blocking step pulse generator for DM542T steppers * steps: number of steps to move @@ -250,6 +256,7 @@ int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_di return -EINVAL; } if (direction == MOTOR_STOP) { + gpio_pin_set_dt(motor->config.pul, 0); return 0; } if (step_period_us < 4) { diff --git a/app/src/place.c b/app/src/place.c new file mode 100644 index 0000000..23b3ac2 --- /dev/null +++ b/app/src/place.c @@ -0,0 +1,27 @@ +#include +#include "place.h" +#include "tamp.h" + +int place(mcu_t *mcu) { + if (mcu->state != Place) { + printk("\nGot to Place but state was %d, returning.", mcu->state); + return 1; + } + place_plant(mcu); + place_dirt(mcu); + mcu->state = Tamp; + tamp(mcu); + return 0; +} + +int place_plant(mcu_t *mcu) { + set_step_motor(mcu->susanStepper, 60, 10, MOTOR_FORWARD); + return 0; +} + +int place_dirt(mcu_t *mcu) { + set_servo_position(mcu->soilDrop, SERVO_OPEN); + k_sleep(K_MSEC(SOIL_TIME_OPEN_MS)); + set_servo_position(mcu->soilDrop, SERVO_CLOSED); + return 0; +} \ No newline at end of file diff --git a/app/src/tamp.c b/app/src/tamp.c new file mode 100644 index 0000000..56ff8d9 --- /dev/null +++ b/app/src/tamp.c @@ -0,0 +1,18 @@ +#include "tamp.h" +#include "motor.h" + +int tamp(mcu_t *mcu) { + if (mcu->state != Tamp) { + printk("\nGot to Tamp but state was %d, returning.", mcu->state); + return 1; + } + tamp_soil(mcu); + return 0; +} + +int tamp_soil(mcu_t *mcu) { + set_step_motor(mcu->tampActuator, 360, 60, MOTOR_FORWARD); + + set_step_motor(mcu->tampActuator, 360, 60, MOTOR_BACKWARD); + return 0; +} \ No newline at end of file From 812bfbe5444090d5dc860799d3167117ba8276df Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Mon, 6 Apr 2026 20:08:50 -0400 Subject: [PATCH 02/13] 1 fix pin --- app/esp32s3_devkitc_procpu.overlay | 45 ++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index 537f91c..ad141d5 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -2,17 +2,17 @@ * ESP32-S3 DevKitC Motor Driver Overlay * * MD20A (PWM) motors: - * driveRight — DIR: GPIO1 PWM: GPIO4 (LEDC ch0) - * driveLeft — DIR: GPIO2 PWM: GPIO5 (LEDC ch1) - * digActuator — DIR: GPIO3 PWM: GPIO6 (LEDC ch2) + * driveRight/NavM2 — DIR: GPIO3 PWM: GPIO9 (LEDC ch0) + * driveLeft/Navm1 — DIR: GPIO38 PWM: GPIO39 (LEDC ch1) + * digActuator/LinAct1 — DIR: GPIO14 PWM: GPIO21 (LEDC ch2) * * DM542T (stepper) motors: - * digStepper — DIR: GPIO14 PUL: GPIO13 - * susanStepper — DIR: GPIO16 PUL: GPIO15 - * tampActuator — DIR: GPIO18 PUL: GPIO17 + * digStepper — DIR: GPIO48 PUL: GPIO47 + * susanStepper — DIR: GPIO11 PUL: GPIO12 + * tampActuator — DIR: GPIO13 PUL: GPIO12 * * Servo motors: - * soilDrop — PWM: GPIO7 + * soilDrop — PWM: GPIO8 */ #include @@ -23,21 +23,21 @@ &pinctrl { ledc0_default: ledc0_default { group1 { - pinmux = , - , - , - ; + pinmux = , + , + , + ; output-enable; }; }; uart1_crsf: uart1_crsf { group1 { - pinmux = ; /* free UART-capable pins */ + pinmux = ; /* free UART-capable pins */ output-enable; }; group2 { - pinmux = ; + pinmux = ; input-enable; }; }; @@ -50,7 +50,20 @@ output-enable; }; }; - /* ← lsm6dso does NOT belong here */ +}; + +/* lsm6dso goes here instead */ +&i2c0 { + status = "okay"; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + clock-frequency = ; + + lsm6dso: lsm6dso@6b { + compatible = "st,lsm6dso"; + reg = <0x6b>; + status = "okay"; + }; }; // CRSF serial, baud rate at 420000 @@ -100,4 +113,8 @@ * ----------------------------------------------------------------------- */ &gpio0 { status = "okay"; +}; + +&gpio1 { + status = "okay"; }; \ No newline at end of file From 23e9903dd415350a3617bbdab194bbffc1eb5aeb Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Mon, 6 Apr 2026 21:27:54 -0400 Subject: [PATCH 03/13] small changes --- app/esp32s3_devkitc_procpu.overlay | 2 +- app/include/motor.h | 1 + app/prj.conf | 2 +- app/src/motor.c | 81 ++++++++++++++++++++++-------- app/src/tamp.c | 1 + 5 files changed, 65 insertions(+), 22 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index ad141d5..a27b7af 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -8,7 +8,7 @@ * * DM542T (stepper) motors: * digStepper — DIR: GPIO48 PUL: GPIO47 - * susanStepper — DIR: GPIO11 PUL: GPIO12 + * susanStepper — DIR: GPIO11 PUL: GPIO10 * tampActuator — DIR: GPIO13 PUL: GPIO12 * * Servo motors: diff --git a/app/include/motor.h b/app/include/motor.h index 5477fe7..6d87314 100644 --- a/app/include/motor.h +++ b/app/include/motor.h @@ -9,6 +9,7 @@ int init_motor(mcu_t *mcu); int move_motor(mcu_t *mcu); int set_motor_speed(motor_t *motor, motor_direction_t dir, uint8_t speed_pct); +int set_step_motor(motor_t *motor, uint8_t degrees, uint8_t rpm, motor_direction_t direction); int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_direction_t direction); #endif \ No newline at end of file diff --git a/app/prj.conf b/app/prj.conf index c92358f..9e01f63 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -1,7 +1,7 @@ CONFIG_GPIO=y CONFIG_SERIAL=y CONFIG_CONSOLE=y -CONFIG_UART_CONSOLE=y +CONFIG_UART_CONSOLE=n CONFIG_PWM=y CONFIG_PRINTK=y CONFIG_STDOUT_CONSOLE=y diff --git a/app/src/motor.c b/app/src/motor.c index 24ca856..6096b5e 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -1,3 +1,40 @@ +// /* ----------------------------------------------------------------------- +// * move_motor — demo sweep: ramps drive-right PWM up and down +// * Call this from a dedicated thread, NOT from init_motor. +// * ----------------------------------------------------------------------- */ +// int move_motor(mcu_t *mcu) +// { +// if (!mcu->driveRight->initialized) { +// printk("driveRight not initialized"); +// return -EINVAL; +// } + +// #define STEP_PCT 5U /* % change per tick */ +// #define TICK_MS 20 /* ms per tick */ + +// /* Set forward direction once */ +// gpio_pin_set_dt(mcu->driveRight->config.dir, 1); + +// bool testing = true; + +// while (1) { +// //set_motor_speed(mcu->driveRight, MOTOR_FORWARD, mcu->rcIn.throttle * 100); +// drive(mcu); + +// step_motor(mcu->digStepper, 400, 500, MOTOR_FORWARD); + +// if (testing) { +// set_servo_position(mcu->soilDrop, SERVO_OPEN); +// } else { +// set_servo_position(mcu->soilDrop, SERVO_CLOSED); +// } +// testing = !testing; +// k_sleep(K_MSEC(TICK_MS)); +// } + +// return 0; +// } + #include #include #include @@ -12,8 +49,9 @@ LOG_MODULE_REGISTER(motor_driver, LOG_LEVEL_INF); /* ----------------------------------------------------------------------- * Device references — resolved at compile time via devicetree * ----------------------------------------------------------------------- */ -static const struct device *gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0)); -static const struct device *pwm_dev = DEVICE_DT_GET(DT_NODELABEL(ledc0)); +static const struct device *gpio_dev0 = DEVICE_DT_GET(DT_NODELABEL(gpio0)); +static const struct device *gpio_dev1 = DEVICE_DT_GET(DT_NODELABEL(gpio1)); +static const struct device *pwm_dev = DEVICE_DT_GET(DT_NODELABEL(ledc0)); /* ----------------------------------------------------------------------- * GPIO dt_specs (dir and pulse pins) @@ -126,10 +164,14 @@ int init_motor(mcu_t *mcu) init_servo(mcu); /* --- Validate devices -------------------------------------------- */ - if (!device_is_ready(gpio_dev)) { + if (!device_is_ready(gpio_dev0)) { printk("GPIO0 device not ready"); return -ENODEV; } + if (!device_is_ready(gpio_dev1)) { + printk("GPIO1 device not ready"); + return -ENODEV; + } if (!device_is_ready(pwm_dev)) { printk("LEDC0 (PWM) device not ready"); return -ENODEV; @@ -137,16 +179,16 @@ int init_motor(mcu_t *mcu) /* --- GPIO dir/pulse specs ---------------------------------------- */ /* MD20A motors — dir only */ - gpio_spec_init(&drive_right_dir_spec, gpio_dev, 1); - gpio_spec_init(&drive_left_dir_spec, gpio_dev, 2); - gpio_spec_init(&dig_actuator_dir_spec, gpio_dev, 3); + gpio_spec_init(&drive_right_dir_spec, gpio_dev0, 3); + gpio_spec_init(&drive_left_dir_spec, gpio_dev1, 6); /* GPIO38 = gpio1 pin 6 */ + gpio_spec_init(&dig_actuator_dir_spec, gpio_dev0, 14); /* DM542T steppers — dir + pulse */ - gpio_spec_init(&dig_stepper_dir_spec, gpio_dev, 14); - gpio_spec_init(&dig_stepper_pul_spec, gpio_dev, 13); - gpio_spec_init(&susan_stepper_dir_spec, gpio_dev, 16); - gpio_spec_init(&susan_stepper_pul_spec, gpio_dev, 15); - gpio_spec_init(&tamp_actuator_dir_spec, gpio_dev, 18); - gpio_spec_init(&tamp_actuator_pul_spec, gpio_dev, 17); + gpio_spec_init(&dig_stepper_dir_spec, gpio_dev1, 16); /* GPIO48 = gpio1 pin 16 */ + gpio_spec_init(&dig_stepper_pul_spec, gpio_dev1, 15); /* GPIO47 = gpio1 pin 15 */ + gpio_spec_init(&susan_stepper_dir_spec, gpio_dev0, 11); + gpio_spec_init(&susan_stepper_pul_spec, gpio_dev0, 10); + gpio_spec_init(&tamp_actuator_dir_spec, gpio_dev0, 13); + gpio_spec_init(&tamp_actuator_pul_spec, gpio_dev0, 12); /* --- PWM specs (MD20A only) --------------------------------------- */ pwm_spec_init(&drive_right_pwm_spec, pwm_dev, 0); @@ -239,12 +281,6 @@ int set_motor_speed(motor_t *motor, motor_direction_t dir, uint8_t speed_pct) return 0; } -int set_step_motor(motor_t *motor, uint8_t degrees, uint8_t rpm, motor_direction_t direction) { - uint8_t pulses = (degrees / 360) * PUL_PER_REV; - uint8_t step_period = 60000000 / (rpm * PUL_PER_REV); - step_motor(motor, pulses, step_period, direction); -} - /* ----------------------------------------------------------------------- * step_motor — blocking step pulse generator for DM542T steppers * steps: number of steps to move @@ -256,7 +292,6 @@ int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_di return -EINVAL; } if (direction == MOTOR_STOP) { - gpio_pin_set_dt(motor->config.pul, 0); return 0; } if (step_period_us < 4) { @@ -279,6 +314,12 @@ int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_di return 0; } +int set_step_motor(motor_t *motor, uint8_t degrees, uint8_t rpm, motor_direction_t direction) { + uint32_t pulses = (degrees / 360) * PUL_PER_REV; + uint32_t step_period = 60000000 / (rpm * PUL_PER_REV); + step_motor(motor, pulses, step_period, direction); +} + /* ----------------------------------------------------------------------- * move_motor — demo sweep: ramps drive-right PWM up and down * Call this from a dedicated thread, NOT from init_motor. @@ -302,7 +343,7 @@ int move_motor(mcu_t *mcu) //set_motor_speed(mcu->driveRight, MOTOR_FORWARD, mcu->rcIn.throttle * 100); drive(mcu); - step_motor(mcu->digStepper, 400, 500, MOTOR_FORWARD); + set_step_motor(mcu->susanStepper, 30, 10, MOTOR_FORWARD); if (testing) { set_servo_position(mcu->soilDrop, SERVO_OPEN); diff --git a/app/src/tamp.c b/app/src/tamp.c index 56ff8d9..9131382 100644 --- a/app/src/tamp.c +++ b/app/src/tamp.c @@ -1,5 +1,6 @@ #include "tamp.h" #include "motor.h" +#include int tamp(mcu_t *mcu) { if (mcu->state != Tamp) { From 68a63f1057f0459f5687d08ede9d2616a9621325 Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Wed, 8 Apr 2026 19:15:56 -0400 Subject: [PATCH 04/13] Changed gpio back to dev0 --- app/esp32s3_devkitc_procpu.overlay | 4 ---- app/prj.conf | 2 +- app/src/main.c | 3 +++ app/src/motor.c | 11 +++-------- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index a27b7af..3ed4b16 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -113,8 +113,4 @@ * ----------------------------------------------------------------------- */ &gpio0 { status = "okay"; -}; - -&gpio1 { - status = "okay"; }; \ No newline at end of file diff --git a/app/prj.conf b/app/prj.conf index 9e01f63..c92358f 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -1,7 +1,7 @@ CONFIG_GPIO=y CONFIG_SERIAL=y CONFIG_CONSOLE=y -CONFIG_UART_CONSOLE=n +CONFIG_UART_CONSOLE=y CONFIG_PWM=y CONFIG_PRINTK=y CONFIG_STDOUT_CONSOLE=y diff --git a/app/src/main.c b/app/src/main.c index 044fed8..cb9b2fd 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -53,6 +53,9 @@ static void motor_thread_entry(void *p1, void *p2, void *p3) int main(void) { printk("Main task started\n"); + const struct device *g=DEVICE_DT_GET(DT_NODELABEL(gpio0)); + gpio_pin_configure(g,1,GPIO_OUTPUT_ACTIVE); + gpio_pin_set(g,1,1); int ret = init_motor(&mcu); if (ret < 0) { diff --git a/app/src/motor.c b/app/src/motor.c index 6096b5e..39da60d 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -50,7 +50,6 @@ LOG_MODULE_REGISTER(motor_driver, LOG_LEVEL_INF); * Device references — resolved at compile time via devicetree * ----------------------------------------------------------------------- */ static const struct device *gpio_dev0 = DEVICE_DT_GET(DT_NODELABEL(gpio0)); -static const struct device *gpio_dev1 = DEVICE_DT_GET(DT_NODELABEL(gpio1)); static const struct device *pwm_dev = DEVICE_DT_GET(DT_NODELABEL(ledc0)); /* ----------------------------------------------------------------------- @@ -168,10 +167,6 @@ int init_motor(mcu_t *mcu) printk("GPIO0 device not ready"); return -ENODEV; } - if (!device_is_ready(gpio_dev1)) { - printk("GPIO1 device not ready"); - return -ENODEV; - } if (!device_is_ready(pwm_dev)) { printk("LEDC0 (PWM) device not ready"); return -ENODEV; @@ -180,11 +175,11 @@ int init_motor(mcu_t *mcu) /* --- GPIO dir/pulse specs ---------------------------------------- */ /* MD20A motors — dir only */ gpio_spec_init(&drive_right_dir_spec, gpio_dev0, 3); - gpio_spec_init(&drive_left_dir_spec, gpio_dev1, 6); /* GPIO38 = gpio1 pin 6 */ + gpio_spec_init(&drive_left_dir_spec, gpio_dev0, 38); /* GPIO38 = gpio1 pin 6 */ gpio_spec_init(&dig_actuator_dir_spec, gpio_dev0, 14); /* DM542T steppers — dir + pulse */ - gpio_spec_init(&dig_stepper_dir_spec, gpio_dev1, 16); /* GPIO48 = gpio1 pin 16 */ - gpio_spec_init(&dig_stepper_pul_spec, gpio_dev1, 15); /* GPIO47 = gpio1 pin 15 */ + gpio_spec_init(&dig_stepper_dir_spec, gpio_dev0, 48); /* GPIO48 = gpio1 pin 16 */ + gpio_spec_init(&dig_stepper_pul_spec, gpio_dev0, 47); /* GPIO47 = gpio1 pin 15 */ gpio_spec_init(&susan_stepper_dir_spec, gpio_dev0, 11); gpio_spec_init(&susan_stepper_pul_spec, gpio_dev0, 10); gpio_spec_init(&tamp_actuator_dir_spec, gpio_dev0, 13); From ae2471583463e7cade4d87cec6a92a590d0a9d3f Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Sat, 11 Apr 2026 23:47:24 -0400 Subject: [PATCH 05/13] It works only if I comment out switch statement --- app/include/main.h | 4 +-- app/include/motor.h | 4 +-- app/include/types.h | 2 ++ app/src/dig.c | 1 - app/src/drive.c | 3 +- app/src/main.c | 87 +++++++++++++++++++++++++++++++++------------ app/src/motor.c | 26 ++++++++------ 7 files changed, 86 insertions(+), 41 deletions(-) diff --git a/app/include/main.h b/app/include/main.h index 61a696b..44cdf7c 100644 --- a/app/include/main.h +++ b/app/include/main.h @@ -5,10 +5,10 @@ #include "types.h" /* Stack size for the motor control thread */ -#define MOTOR_THREAD_STACK_SIZE 2048 +#define MAIN_THREAD_STACK_SIZE 2048 /* Priority for the motor control thread (cooperative, below main) */ -#define MOTOR_THREAD_PRIORITY 5 +#define MAIN_THREAD_PRIORITY 5 void rc_callback(const crsf_channels_t *ch); diff --git a/app/include/motor.h b/app/include/motor.h index 6d87314..fe5ad27 100644 --- a/app/include/motor.h +++ b/app/include/motor.h @@ -3,13 +3,13 @@ #include "types.h" #include "drive.h" -#define PUL_PER_REV 400 +#define PUL_PER_REV 800 /* API */ int init_motor(mcu_t *mcu); int move_motor(mcu_t *mcu); int set_motor_speed(motor_t *motor, motor_direction_t dir, uint8_t speed_pct); -int set_step_motor(motor_t *motor, uint8_t degrees, uint8_t rpm, motor_direction_t direction); +int set_step_motor(motor_t *motor, uint32_t degrees, uint32_t rpm, motor_direction_t direction); int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_direction_t direction); #endif \ No newline at end of file diff --git a/app/include/types.h b/app/include/types.h index 39abf45..c151eee 100644 --- a/app/include/types.h +++ b/app/include/types.h @@ -40,6 +40,7 @@ typedef struct { motor_config_t config; driver_type_t driverType; uint8_t speedPercent; + float gearRatio; bool initialized; } motor_t; @@ -53,6 +54,7 @@ typedef struct { uint8_t pitch; uint8_t roll; uint8_t press; + uint8_t on; } rc_input_t; typedef struct { diff --git a/app/src/dig.c b/app/src/dig.c index 4264b08..1931ec4 100644 --- a/app/src/dig.c +++ b/app/src/dig.c @@ -10,7 +10,6 @@ int dig(mcu_t *mcu) { move_dig_motor(mcu); post_dig_drive(mcu); mcu->state = Place; - place(mcu); return 0; } diff --git a/app/src/drive.c b/app/src/drive.c index 19a708a..52e2960 100644 --- a/app/src/drive.c +++ b/app/src/drive.c @@ -11,7 +11,6 @@ int drive(mcu_t *mcu) { mcu->state = Dig; set_drive_motors(mcu, 50, 50); printk("Button Pressed, switched to Lower Drill."); - dig(mcu); return 0; } @@ -37,7 +36,7 @@ int set_drive_motors(mcu_t *mcu, uint8_t throttle_p, uint8_t turn_p) { float left_speed = ((50 + turn_p_f)) * throttle_p_f; float right_speed = ((50 - turn_p_f)) * throttle_p_f; - printk("\nright speed: %f", right_speed); + //printk("\nSpeed: %f", right_speed); int ret; diff --git a/app/src/main.c b/app/src/main.c index cb9b2fd..a03885e 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -7,10 +7,11 @@ #include "main.h" #include "motor.h" #include "drive.h" +#include "dig.h" +#include "place.h" +#include "tamp.h" #include "crsf.h" -LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); - /* Shared MCU handle — accessible by all threads */ static mcu_t mcu; @@ -20,31 +21,71 @@ void rc_callback(const crsf_channels_t *ch) uint16_t pitch_raw = ch->channels[1]; uint16_t roll_raw = ch->channels[0]; uint16_t press_raw = ch->channels[8]; + uint16_t on_raw = ch->channels[7]; - // printk("\npitch: %d, roll: %deight: %d", pitch_raw, roll_raw, ch->channels[8]); + // printk("\npitch: %d, roll: %deight: %d, 7: %d, 6: %d", pitch_raw, roll_raw, ch->channels[8], ch->channels[7], ch->channels[6]); mcu.rcIn.pitch = crsf_channel_to_float(pitch_raw) * 100; mcu.rcIn.roll = crsf_channel_to_float(roll_raw) * 100; mcu.rcIn.press = crsf_channel_to_float(press_raw) * 100; - + mcu.rcIn.on = crsf_channel_to_float(on_raw) * 100; } /* ----------------------------------------------------------------------- * Motor thread: runs move_motor's infinite sweep loop * ----------------------------------------------------------------------- */ -K_THREAD_STACK_DEFINE(motor_stack, MOTOR_THREAD_STACK_SIZE); -static struct k_thread motor_thread_data; +K_THREAD_STACK_DEFINE(main_stack, MAIN_THREAD_STACK_SIZE); +static struct k_thread main_thread_data; -static void motor_thread_entry(void *p1, void *p2, void *p3) +static void main_thread_entry(void *p1, void *p2, void *p3) { ARG_UNUSED(p2); ARG_UNUSED(p3); - - mcu_t *mcu_ptr = (mcu_t *)p1; - move_motor(mcu_ptr); - /* move_motor loops forever; reaching here means something went wrong */ - printk("motor_thread: move_motor exited unexpectedly\n"); + printk("\nEntered main task."); + mcu_t *mcu = (mcu_t *)p1; + + bool testing = true; + mcu->state = Drive; + + while (1) { + if (mcu->rcIn.on > 50) { + mcu->state = Idle; + } else if (mcu->state == Idle) { + mcu->state = Drive; + } + switch (mcu->state) { + case Drive: + drive(mcu); + break; + case Dig: + dig(mcu); + break; + case Place: + place(mcu); + break; + case Tamp: + tamp(mcu); + break; + default: + break; + } + + continue; + drive(mcu); + + set_step_motor(mcu->susanStepper, 360, 20, MOTOR_FORWARD); + //step_motor(mcu->susanStepper, 400, 4000, MOTOR_FORWARD); + + if (testing) { + set_servo_position(mcu->soilDrop, SERVO_OPEN); + } else { + set_servo_position(mcu->soilDrop, SERVO_CLOSED); + } + testing = !testing; + k_sleep(K_MSEC(2000)); + } + printk("main_thread: exited unexpectedly\n"); } /* ----------------------------------------------------------------------- @@ -53,9 +94,9 @@ static void motor_thread_entry(void *p1, void *p2, void *p3) int main(void) { printk("Main task started\n"); - const struct device *g=DEVICE_DT_GET(DT_NODELABEL(gpio0)); - gpio_pin_configure(g,1,GPIO_OUTPUT_ACTIVE); - gpio_pin_set(g,1,1); + // const struct device *g=DEVICE_DT_GET(DT_NODELABEL(gpio0)); + // gpio_pin_configure(g,1,GPIO_OUTPUT_ACTIVE); + // gpio_pin_set(g,1,1); int ret = init_motor(&mcu); if (ret < 0) { @@ -71,23 +112,23 @@ int main(void) /* Spawn the motor control thread AFTER init succeeds */ k_thread_create( - &motor_thread_data, - motor_stack, - K_THREAD_STACK_SIZEOF(motor_stack), - motor_thread_entry, + &main_thread_data, + main_stack, + K_THREAD_STACK_SIZEOF(main_stack), + main_thread_entry, &mcu, NULL, NULL, - MOTOR_THREAD_PRIORITY, + MAIN_THREAD_PRIORITY, 0, K_NO_WAIT ); - k_thread_name_set(&motor_thread_data, "motor_ctrl"); + k_thread_name_set(&main_thread_data, "main"); - printk("Motor thread spawned\n"); + printk("\nMain thread spawned\n"); /* * main() must not return — the Zephyr kernel keeps running threads, * but returning from main() on some configs halts the scheduler. - * Suspend main indefinitely instead.git push --set-upstream origin motors + * Suspend main indefinitely instead. */ k_thread_suspend(k_current_get()); diff --git a/app/src/motor.c b/app/src/motor.c index 39da60d..7a7adf9 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -106,6 +106,7 @@ static motor_t digStepper = { .driverType = DM542T, .direction = MOTOR_STOP, .speedPercent = 0, + .gearRatio = 20, .initialized = false }; @@ -114,6 +115,7 @@ static motor_t susanStepper = { .driverType = DM542T, .direction = MOTOR_STOP, .speedPercent = 0, + .gearRatio = 5.18, .initialized = false }; @@ -122,6 +124,7 @@ static motor_t tampActuator = { .driverType = DM542T, .direction = MOTOR_STOP, .speedPercent = 0, + .gearRatio = 1, .initialized = false }; @@ -283,14 +286,11 @@ int set_motor_speed(motor_t *motor, motor_direction_t dir, uint8_t speed_pct) * ----------------------------------------------------------------------- */ int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_direction_t direction) { - if (!motor->initialized || motor->driverType != DM542T) { - return -EINVAL; - } if (direction == MOTOR_STOP) { return 0; } - if (step_period_us < 4) { - step_period_us = 4; /* DM542T minimum pulse width */ + if (step_period_us < 5) { + step_period_us = 5; /* DM542T minimum pulse width */ } uint32_t half = step_period_us / 2; @@ -298,6 +298,7 @@ int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_di uint8_t dir = (direction == MOTOR_FORWARD) ? 1 : 0; gpio_pin_set_dt(motor->config.dir, dir); + k_busy_wait(5); /* direction setup time */ for (uint32_t i = 0; i < steps; i++) { gpio_pin_set_dt(motor->config.pul, 1); @@ -309,10 +310,12 @@ int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_di return 0; } -int set_step_motor(motor_t *motor, uint8_t degrees, uint8_t rpm, motor_direction_t direction) { - uint32_t pulses = (degrees / 360) * PUL_PER_REV; - uint32_t step_period = 60000000 / (rpm * PUL_PER_REV); - step_motor(motor, pulses, step_period, direction); +int set_step_motor(motor_t *motor, uint32_t degrees, uint32_t rpm, motor_direction_t direction) { + if (rpm == 0 || !motor->initialized || motor->driverType != DM542T) return -EINVAL; + uint32_t pul_per_rev = PUL_PER_REV * motor->gearRatio; + uint32_t pulses = (degrees * pul_per_rev) / 360; // 360 deg in one rotation + uint32_t step_period = 60000000 / (rpm * pul_per_rev); // 60,000,000 = 1min in us + return step_motor(motor, pulses, step_period, direction); } /* ----------------------------------------------------------------------- @@ -327,7 +330,7 @@ int move_motor(mcu_t *mcu) } #define STEP_PCT 5U /* % change per tick */ -#define TICK_MS 20 /* ms per tick */ +#define TICK_MS 2000 /* ms per tick */ /* Set forward direction once */ gpio_pin_set_dt(mcu->driveRight->config.dir, 1); @@ -338,7 +341,8 @@ int move_motor(mcu_t *mcu) //set_motor_speed(mcu->driveRight, MOTOR_FORWARD, mcu->rcIn.throttle * 100); drive(mcu); - set_step_motor(mcu->susanStepper, 30, 10, MOTOR_FORWARD); + set_step_motor(mcu->susanStepper, 360, 20, MOTOR_FORWARD); + //step_motor(mcu->susanStepper, 400, 4000, MOTOR_FORWARD); if (testing) { set_servo_position(mcu->soilDrop, SERVO_OPEN); From 7471f01536b0119af181e459a1da67b68b7402e1 Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Sun, 12 Apr 2026 00:35:43 -0400 Subject: [PATCH 06/13] Working with state machine --- app/include/main.h | 2 +- app/include/motor.h | 1 + app/src/drive.c | 4 ++-- app/src/main.c | 8 ++++++-- app/src/motor.c | 7 +++++++ app/src/place.c | 2 -- app/src/tamp.c | 1 + 7 files changed, 18 insertions(+), 7 deletions(-) diff --git a/app/include/main.h b/app/include/main.h index 44cdf7c..38e3542 100644 --- a/app/include/main.h +++ b/app/include/main.h @@ -5,7 +5,7 @@ #include "types.h" /* Stack size for the motor control thread */ -#define MAIN_THREAD_STACK_SIZE 2048 +#define MAIN_THREAD_STACK_SIZE 4096 /* Priority for the motor control thread (cooperative, below main) */ #define MAIN_THREAD_PRIORITY 5 diff --git a/app/include/motor.h b/app/include/motor.h index fe5ad27..1e36492 100644 --- a/app/include/motor.h +++ b/app/include/motor.h @@ -11,5 +11,6 @@ int move_motor(mcu_t *mcu); int set_motor_speed(motor_t *motor, motor_direction_t dir, uint8_t speed_pct); int set_step_motor(motor_t *motor, uint32_t degrees, uint32_t rpm, motor_direction_t direction); int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_direction_t direction); +int all_motors_off(mcu_t *mcu); #endif \ No newline at end of file diff --git a/app/src/drive.c b/app/src/drive.c index 52e2960..cba0860 100644 --- a/app/src/drive.c +++ b/app/src/drive.c @@ -22,7 +22,7 @@ int set_drive_motors(mcu_t *mcu, uint8_t throttle_p, uint8_t turn_p) { // Assuming turn is 0 to 100 (0 being full left, 100 being full right) // and throttle is 0 to 100 (0 is full backward, 100 is full forward) - if (throttle_p < 55 && throttle_p > 45) { + if (throttle_p < 55 && throttle_p > 45 && turn_p < 55 && turn_p > 45) { set_motor_speed(mcu->driveLeft, MOTOR_STOP, 0); set_motor_speed(mcu->driveRight, MOTOR_STOP, 0); return 0; @@ -36,7 +36,7 @@ int set_drive_motors(mcu_t *mcu, uint8_t throttle_p, uint8_t turn_p) { float left_speed = ((50 + turn_p_f)) * throttle_p_f; float right_speed = ((50 - turn_p_f)) * throttle_p_f; - //printk("\nSpeed: %f", right_speed); + printk("\nSpeed: %f", right_speed); int ret; diff --git a/app/src/main.c b/app/src/main.c index a03885e..957532e 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -46,12 +46,16 @@ static void main_thread_entry(void *p1, void *p2, void *p3) mcu_t *mcu = (mcu_t *)p1; bool testing = true; - mcu->state = Drive; + mcu->state = Idle; while (1) { - if (mcu->rcIn.on > 50) { + + if (mcu->rcIn.on < 50) { + printk("\nOff"); + all_motors_off(mcu); mcu->state = Idle; } else if (mcu->state == Idle) { + //printk("\nOn"); mcu->state = Drive; } switch (mcu->state) { diff --git a/app/src/motor.c b/app/src/motor.c index 7a7adf9..a594d92 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -353,5 +353,12 @@ int move_motor(mcu_t *mcu) k_sleep(K_MSEC(TICK_MS)); } + return 0; +} + +int all_motors_off(mcu_t *mcu) { + set_motor_speed(mcu->driveLeft, MOTOR_STOP, 0); + set_motor_speed(mcu->driveRight, MOTOR_STOP, 0); + set_motor_speed(mcu->digActuator, MOTOR_STOP, 0); return 0; } \ No newline at end of file diff --git a/app/src/place.c b/app/src/place.c index 23b3ac2..6268b69 100644 --- a/app/src/place.c +++ b/app/src/place.c @@ -1,6 +1,5 @@ #include #include "place.h" -#include "tamp.h" int place(mcu_t *mcu) { if (mcu->state != Place) { @@ -10,7 +9,6 @@ int place(mcu_t *mcu) { place_plant(mcu); place_dirt(mcu); mcu->state = Tamp; - tamp(mcu); return 0; } diff --git a/app/src/tamp.c b/app/src/tamp.c index 9131382..a40b43e 100644 --- a/app/src/tamp.c +++ b/app/src/tamp.c @@ -8,6 +8,7 @@ int tamp(mcu_t *mcu) { return 1; } tamp_soil(mcu); + mcu->state = Drive; return 0; } From e4edd4ab397f1e2a6c22054aec7f01b839f1527a Mon Sep 17 00:00:00 2001 From: fnckingsnowman Date: Tue, 14 Apr 2026 13:56:44 -0400 Subject: [PATCH 07/13] leds: takes planting states from mcu object and updates leds accordingly. havent tested tho at least i think thats what it does rn --- app/include/led_controller.h | 59 ++--- app/src/led_controller.c | 441 ++++++++++++++--------------------- app/src/main.c | 7 + 3 files changed, 198 insertions(+), 309 deletions(-) diff --git a/app/include/led_controller.h b/app/include/led_controller.h index 5ef30ec..7aeaeb9 100644 --- a/app/include/led_controller.h +++ b/app/include/led_controller.h @@ -3,60 +3,39 @@ #include #include +#include "types.h" /** - * Planting step status + * Initialize the LED controller and start the update thread. + * @param mcu pointer to the shared MCU state (reads mcu->state each cycle) */ -enum planting_step_status { - PLANTING_NOT_STARTED, // White (default) - PLANTING_IN_PROGRESS, // Blinking white - PLANTING_COMPLETED, // Solid green - PLANTING_MAINTENANCE // Red -}; +int led_controller_init(mcu_t *mcu); /** - * System state - */ -enum system_state { - SYSTEM_IDLE, // Default state, planting LEDs white - SYSTEM_LOADING, // All planting LEDs breathe white - SYSTEM_PLANTING // In planting cycle -}; - -/** - * Initialize the LED controller - * This starts a background thread that updates LEDs based on state - */ -int led_controller_init(void); - -/** - * Set battery percentage and charging state - * @param percentage: 0-100 - * @param is_charging: true if charging, false otherwise + * Set battery percentage and charging state. + * Call this when BMS data is available. + * @param percentage 0-100 + * @param is_charging true if currently charging */ void led_controller_set_battery(uint8_t percentage, bool is_charging); /** - * Set the status of a specific planting step - * @param step: 1-4 (which planting step) - * @param status: Status of that step - */ -void led_controller_set_planting_step(uint8_t step, enum planting_step_status status); - -/** - * Set system state - * @param state: System state enum + * Mark a planting step as having an error (turns that LED red). + * @param step 1-4 (1=Drive, 2=Dig, 3=Place, 4=Tamp) + * @param error true to set error, false to clear it */ -void led_controller_set_system_state(enum system_state state); +void led_controller_set_planting_error(uint8_t step, bool error); /** - * Complete the planting cycle (reset all to white) + * Signal that the full planting cycle is complete. + * All four planting LEDs will go solid white. */ -void led_controller_complete_cycle(void); +void led_controller_set_planting_complete(void); /** - * Get current states (for debugging) + * Reset planting state (clears complete flag and all errors). + * Call at the start of a new planting cycle. */ -void led_controller_get_status(void); +void led_controller_reset_planting(void); -#endif \ No newline at end of file +#endif diff --git a/app/src/led_controller.c b/app/src/led_controller.c index 9458df9..aa12612 100644 --- a/app/src/led_controller.c +++ b/app/src/led_controller.c @@ -1,365 +1,268 @@ #include "led_controller.h" #include "led_strip.h" -#include "buzzer.h" +#include "types.h" #include #include LOG_MODULE_REGISTER(led_controller, LOG_LEVEL_INF); -// LED positions (only 8 LEDs now, no machine state) -#define LED_BATTERY_25 0 -#define LED_BATTERY_50 1 -#define LED_BATTERY_75 2 -#define LED_BATTERY_100 3 -#define LED_PLANTING_1 4 -#define LED_PLANTING_2 5 -#define LED_PLANTING_3 6 -#define LED_PLANTING_4 7 - -// Timing configuration -#define UPDATE_RATE_MS 50 // How often to update LEDs (50ms = 20 updates/sec) -#define BLINK_PERIOD_MS 300 // Full blink cycle: 300ms ON + 300ms OFF = 600ms total -#define BREATHING_SPEED 10 // How fast breathing changes (higher = faster) - -// Colors -#define COLOR_OFF {.r = 0, .g = 0, .b = 0} -#define COLOR_WHITE {.r = 255, .g = 255, .b = 255} -#define COLOR_GREEN {.r = 0, .g = 255, .b = 0} -#define COLOR_YELLOW {.r = 255, .g = 255, .b = 0} -#define COLOR_RED {.r = 255, .g = 0, .b = 0} - -// State variables +// ── LED index assignments ──────────────────────────────────────────────────── +// pixels 0-3: battery tier indicators +// pixels 4-7: planting step indicators (Drive, Dig, Place, Tamp) +#define LED_BATTERY_1 0 +#define LED_BATTERY_2 1 +#define LED_BATTERY_3 2 +#define LED_BATTERY_4 3 +#define LED_STEP_1 4 // Drive +#define LED_STEP_2 5 // Dig +#define LED_STEP_3 6 // Place +#define LED_STEP_4 7 // Tamp + +// ── Timing ────────────────────────────────────────────────────────────────── +#define UPDATE_RATE_MS 50 +#define BLINK_PERIOD_MS 300 + +// ── Colors ────────────────────────────────────────────────────────────────── +#define COLOR_OFF {.r = 0, .g = 0, .b = 0} +#define COLOR_WHITE {.r = 255, .g = 255, .b = 255} +#define COLOR_GREEN {.r = 0, .g = 255, .b = 0} +#define COLOR_RED {.r = 255, .g = 0, .b = 0} + +// ── Shared LED state (mutex-protected) ────────────────────────────────────── static struct { + // Battery uint8_t battery_percentage; - bool is_charging; - enum planting_step_status planting_steps[4]; - enum system_state system_state; + bool is_charging; + + // Planting + bool planting_complete; // true when all 4 steps done → all solid white + uint8_t error_steps; // bitmask: bit 0=Drive, 1=Dig, 2=Place, 3=Tamp } led_state = { .battery_percentage = 0, - .is_charging = false, - .planting_steps = { - PLANTING_NOT_STARTED, - PLANTING_NOT_STARTED, - PLANTING_NOT_STARTED, - PLANTING_NOT_STARTED - }, - .system_state = SYSTEM_IDLE + .is_charging = false, + .planting_complete = false, + .error_steps = 0, }; static K_MUTEX_DEFINE(state_mutex); -static struct led_rgb pixels[9]; +static struct led_rgb pixels[8]; -// Blink control - uses timer instead of simple toggle +// ── Blink state ────────────────────────────────────────────────────────────── static uint32_t blink_timer_ms = 0; -static bool blink_state = false; +static bool blink_state = false; -// Breathing control - independent from blink -static int16_t breathing_brightness = 0; -static int8_t breathing_direction = 1; - -// Update thread +// ── Thread ────────────────────────────────────────────────────────────────── #define LED_UPDATE_THREAD_STACK_SIZE 2048 -#define LED_UPDATE_THREAD_PRIORITY 7 +#define LED_UPDATE_THREAD_PRIORITY 7 static K_THREAD_STACK_DEFINE(led_update_stack, LED_UPDATE_THREAD_STACK_SIZE); static struct k_thread led_update_thread_data; -void update_battery_leds(void) +// ── Battery LEDs ───────────────────────────────────────────────────────────── +// +// Four LEDs fill up cumulatively based on percentage: +// pixel[0]: pct >= 1 (first quarter, 1-25%) +// pixel[1]: pct >= 25 (second quarter, 25-50%) +// pixel[2]: pct >= 50 (third quarter, 50-75%) +// pixel[3]: pct >= 75 (fourth quarter, 75-100%) +// +// Charging: the highest lit LED blinks to show current charge frontier. +// At 100%, all four are solid (done). +static void update_battery_leds(void) { - bool led_25_on = led_state.battery_percentage >= 0; - bool led_50_on = led_state.battery_percentage >= 25; - bool led_75_on = led_state.battery_percentage >= 50; - bool led_100_on = led_state.battery_percentage >= 75; - - int charging_led = -1; - if (led_state.is_charging) { - if (led_state.battery_percentage < 25) { - charging_led = LED_BATTERY_25; - } else if (led_state.battery_percentage < 50) { - charging_led = LED_BATTERY_50; - } else if (led_state.battery_percentage < 75) { - charging_led = LED_BATTERY_75; - } else if (led_state.battery_percentage < 100) { - charging_led = LED_BATTERY_100; + uint8_t pct = led_state.battery_percentage; + bool charging = led_state.is_charging; + + bool on[4] = { + pct >= 1, + pct >= 25, + pct >= 50, + pct >= 75, + }; + + // Find the frontier LED — the highest tier that is on — for charging blink. + // If pct == 100 or not charging, no blinking. + int frontier = -1; + if (charging && pct < 100) { + for (int i = 3; i >= 0; i--) { + if (on[i]) { + frontier = i; + break; + } + } + // Edge case: battery just connected and reading 0 — blink the first LED + if (frontier == -1) { + frontier = 0; + } + } + + for (int i = 0; i < 4; i++) { + if (i == frontier) { + // Charging frontier blinks + pixels[i] = blink_state ? (struct led_rgb)COLOR_GREEN + : (struct led_rgb)COLOR_OFF; + } else if (on[i]) { + pixels[i] = (struct led_rgb)COLOR_GREEN; + } else { + pixels[i] = (struct led_rgb)COLOR_OFF; } } - - pixels[LED_BATTERY_25] = (led_25_on && (charging_led != LED_BATTERY_25 || blink_state)) ? - (struct led_rgb)COLOR_GREEN : (struct led_rgb)COLOR_OFF; - pixels[LED_BATTERY_50] = (led_50_on && (charging_led != LED_BATTERY_50 || blink_state)) ? - (struct led_rgb)COLOR_GREEN : (struct led_rgb)COLOR_OFF; - pixels[LED_BATTERY_75] = (led_75_on && (charging_led != LED_BATTERY_75 || blink_state)) ? - (struct led_rgb)COLOR_GREEN : (struct led_rgb)COLOR_OFF; - pixels[LED_BATTERY_100] = (led_100_on && (charging_led != LED_BATTERY_100 || blink_state)) ? - (struct led_rgb)COLOR_GREEN : (struct led_rgb)COLOR_OFF; } -void update_planting_leds(void) +// ── Planting step LEDs ──────────────────────────────────────────────────────── +// +// Maps state_t to a step index so we can infer progress: +// Drive=0, Dig=1, Place=2, Tamp=3, anything else=-1 (idle) +// +// Rules (per LED i): +// error set → red (takes priority) +// all complete → solid white +// i < active → solid white (step finished) +// i == active → blinking white (step in progress) +// i > active → off (not yet reached) +// idle (active==-1) → all off +static int state_to_step_index(state_t state) { - if (led_state.system_state == SYSTEM_LOADING) { - // Cast signed brightness to unsigned for LED - uint8_t brightness_value = (uint8_t)breathing_brightness; - - for (int i = 0; i < 4; i++) { - pixels[LED_PLANTING_1 + i].r = brightness_value; - pixels[LED_PLANTING_1 + i].g = brightness_value; - pixels[LED_PLANTING_1 + i].b = brightness_value; - } - return; + switch (state) { + case Drive: return 0; + case Dig: return 1; + case Place: return 2; + case Tamp: return 3; + default: return -1; } +} + +static void update_planting_leds(state_t state) +{ + int active = state_to_step_index(state); + for (int i = 0; i < 4; i++) { - int led_index = LED_PLANTING_1 + i; - - switch (led_state.planting_steps[i]) { - case PLANTING_NOT_STARTED: - pixels[led_index] = (struct led_rgb)COLOR_WHITE; - break; - - case PLANTING_IN_PROGRESS: - pixels[led_index] = blink_state ? (struct led_rgb)COLOR_WHITE : (struct led_rgb)COLOR_OFF; - break; - - case PLANTING_COMPLETED: - pixels[led_index] = (struct led_rgb)COLOR_GREEN; - break; - - case PLANTING_MAINTENANCE: - pixels[led_index] = (struct led_rgb)COLOR_RED; - break; + // Error takes priority over everything else + if (led_state.error_steps & (1 << i)) { + pixels[LED_STEP_1 + i] = (struct led_rgb)COLOR_RED; + continue; + } + + if (led_state.planting_complete) { + // All four steps done — all solid white + pixels[LED_STEP_1 + i] = (struct led_rgb)COLOR_WHITE; + } else if (active < 0) { + // Idle or Bootup — all off + pixels[LED_STEP_1 + i] = (struct led_rgb)COLOR_OFF; + } else if (i < active) { + // This step is already completed — solid white + pixels[LED_STEP_1 + i] = (struct led_rgb)COLOR_WHITE; + } else if (i == active) { + // This step is currently active — blink white + pixels[LED_STEP_1 + i] = blink_state ? (struct led_rgb)COLOR_WHITE + : (struct led_rgb)COLOR_OFF; + } else { + // Not yet reached + pixels[LED_STEP_1 + i] = (struct led_rgb)COLOR_OFF; } } } -void led_update_thread(void *arg1, void *arg2, void *arg3) +// ── LED update thread ──────────────────────────────────────────────────────── +static void led_update_thread(void *arg1, void *arg2, void *arg3) { - ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); - + + mcu_t *mcu = (mcu_t *)arg1; + LOG_INF("LED update thread started"); - LOG_INF("Blink period: %dms, Breathing speed: %d, Update rate: %dms", - BLINK_PERIOD_MS, BREATHING_SPEED, UPDATE_RATE_MS); - + while (1) { - // === Update Blink State === + // Advance blink state blink_timer_ms += UPDATE_RATE_MS; if (blink_timer_ms >= BLINK_PERIOD_MS) { blink_timer_ms = 0; blink_state = !blink_state; } - - // === Update Breathing Effect (FIXED) === - breathing_brightness += breathing_direction * BREATHING_SPEED; - - // Clamp to 0-255 range - if (breathing_brightness >= 255) { - breathing_brightness = 255; - breathing_direction = -1; // Start going down - } else if (breathing_brightness <= 0) { - breathing_brightness = 0; - breathing_direction = 1; // Start going up - } - - // === Update LED Colors === + + // Single word read — same lock-free pattern used for rcIn + state_t current_state = mcu->state; + + // Lock once to read all of led_state and write pixels[] k_mutex_lock(&state_mutex, K_FOREVER); update_battery_leds(); - update_planting_leds(); + update_planting_leds(current_state); k_mutex_unlock(&state_mutex); - - // === Send to LED Strip === + led_strip_set_pixels(pixels, 8); - - // === Sleep Until Next Update === + k_sleep(K_MSEC(UPDATE_RATE_MS)); } } -int led_controller_init(void) +// ── Public API ─────────────────────────────────────────────────────────────── + +int led_controller_init(mcu_t *mcu) { - LOG_INF("Initializing LED controller..."); - int ret = led_strip_init(); if (ret < 0) { - LOG_ERR("Failed to initialize LED strip"); + LOG_ERR("Failed to initialize LED strip: %d", ret); return ret; } - + memset(pixels, 0, sizeof(pixels)); led_strip_set_pixels(pixels, 8); - + k_thread_create(&led_update_thread_data, led_update_stack, K_THREAD_STACK_SIZEOF(led_update_stack), led_update_thread, - NULL, NULL, NULL, + mcu, NULL, NULL, LED_UPDATE_THREAD_PRIORITY, 0, K_NO_WAIT); k_thread_name_set(&led_update_thread_data, "led_update"); - + LOG_INF("LED controller initialized"); return 0; } void led_controller_set_battery(uint8_t percentage, bool is_charging) { - k_mutex_lock(&state_mutex, K_FOREVER); - if (percentage > 100) { percentage = 100; } - + k_mutex_lock(&state_mutex, K_FOREVER); led_state.battery_percentage = percentage; - led_state.is_charging = is_charging; - + led_state.is_charging = is_charging; k_mutex_unlock(&state_mutex); - + LOG_INF("Battery: %d%% %s", percentage, is_charging ? "(charging)" : ""); } -void led_controller_set_planting_step(uint8_t step, enum planting_step_status status) +void led_controller_set_planting_error(uint8_t step, bool error) { if (step < 1 || step > 4) { - LOG_ERR("Invalid step: %d (must be 1-4)", step); + LOG_ERR("Invalid step %d (must be 1-4)", step); return; } - k_mutex_lock(&state_mutex, K_FOREVER); - - // Store old status to detect changes - enum planting_step_status old_status = led_state.planting_steps[step - 1]; - - // Update to new status - led_state.planting_steps[step - 1] = status; - - // Update system state if needed - bool any_in_progress = false; - for (int i = 0; i < 4; i++) { - if (led_state.planting_steps[i] == PLANTING_IN_PROGRESS) { - any_in_progress = true; - break; - } - } - - if (any_in_progress && led_state.system_state == SYSTEM_IDLE) { - led_state.system_state = SYSTEM_PLANTING; + if (error) { + led_state.error_steps |= (1 << (step - 1)); + } else { + led_state.error_steps &= ~(1 << (step - 1)); } - k_mutex_unlock(&state_mutex); - - // === PLAY SOUNDS ON STATE TRANSITIONS === - // Only play if state actually changed - if (old_status != status) { - switch (status) { - case PLANTING_IN_PROGRESS: - // Step started - LOG_INF("Step %d started", step); - // You could play different sounds per step - if (step == 1) { - buzzer_planting_start(); // Rising tone for first step - } - break; - - case PLANTING_COMPLETED: - // Step completed - LOG_INF("Step %d completed", step); - switch (step) { - case 1: buzzer_step_1(); break; - case 2: buzzer_step_2(); break; - case 3: buzzer_step_3(); break; - case 4: buzzer_step_4(); break; - } - break; - - case PLANTING_MAINTENANCE: - // Maintenance required - LOG_INF("Step %d needs maintenance!", step); - buzzer_maintenance(); // ✓ Only plays ONCE! - break; - - case PLANTING_NOT_STARTED: - // Reset to idle (no sound needed) - LOG_INF("Step %d reset", step); - break; - } - } - - const char *status_str[] = {"NOT_STARTED", "IN_PROGRESS", "COMPLETED", "MAINTENANCE"}; - LOG_INF("Planting step %d: %s", step, status_str[status]); } -void led_controller_set_system_state(enum system_state state) +void led_controller_set_planting_complete(void) { k_mutex_lock(&state_mutex, K_FOREVER); - - enum system_state old_state = led_state.system_state; - led_state.system_state = state; - + led_state.planting_complete = true; k_mutex_unlock(&state_mutex); - - // === PLAY SOUNDS ON STATE CHANGES === - if (old_state != state) { - switch (state) { - case SYSTEM_IDLE: - // Return to idle (no sound) - break; - - case SYSTEM_LOADING: - // Started loading - LOG_INF("System loading..."); - buzzer_loadncheck_done(); - break; - - case SYSTEM_PLANTING: - // Started planting cycle - LOG_INF("Planting cycle started"); - buzzer_planting_start(); - break; - } - } - - const char *state_str[] = {"IDLE", "LOADING", "PLANTING"}; - LOG_INF("System state: %s", state_str[state]); -} -void led_controller_complete_cycle(void) -{ - k_mutex_lock(&state_mutex, K_FOREVER); - - for (int i = 0; i < 4; i++) { - led_state.planting_steps[i] = PLANTING_NOT_STARTED; - } - - led_state.system_state = SYSTEM_IDLE; - - k_mutex_unlock(&state_mutex); - - // === PLAY COMPLETION SOUND === - LOG_INF("Cycle complete!"); - buzzer_planting_complete(); // Nokia tune! - - LOG_INF("Cycle complete - reset to idle"); + LOG_INF("Planting cycle complete"); } -void led_controller_get_status(void) +void led_controller_reset_planting(void) { k_mutex_lock(&state_mutex, K_FOREVER); - - printk("\n=== LED Controller Status ===\n"); - printk("Battery: %d%% %s\n", - led_state.battery_percentage, - led_state.is_charging ? "(charging)" : ""); - - printk("System: "); - switch (led_state.system_state) { - case SYSTEM_IDLE: printk("IDLE\n"); break; - case SYSTEM_LOADING: printk("LOADING\n"); break; - case SYSTEM_PLANTING: printk("PLANTING\n"); break; - } - - printk("Planting Steps:\n"); - const char *status_names[] = {"NOT_STARTED", "IN_PROGRESS", "COMPLETED", "MAINTENANCE"}; - for (int i = 0; i < 4; i++) { - printk(" Step %d: %s\n", i + 1, status_names[led_state.planting_steps[i]]); - } - printk("=============================\n\n"); - + led_state.planting_complete = false; + led_state.error_steps = 0; k_mutex_unlock(&state_mutex); -} \ No newline at end of file + + LOG_INF("Planting state reset"); +} diff --git a/app/src/main.c b/app/src/main.c index 957532e..f8679bb 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -11,6 +11,7 @@ #include "place.h" #include "tamp.h" #include "crsf.h" +#include "led_controller.h" /* Shared MCU handle — accessible by all threads */ static mcu_t mcu; @@ -109,6 +110,12 @@ int main(void) } else { mcu.state = Drive; } + + ret = led_controller_init(&mcu); + if (ret < 0) { + printk("LED controller init failed: %d\n", ret); + } + ret = crsf_init(rc_callback, NULL, &mcu); if (ret < 0) { printk("crsf_init failed: %d\n", ret); From 63242b0ab80444d795762e161efafeacfd0f61ba Mon Sep 17 00:00:00 2001 From: fnckingsnowman Date: Tue, 14 Apr 2026 17:22:31 -0400 Subject: [PATCH 08/13] build fix, no test --- app/esp32s3_devkitc_procpu.overlay | 101 +++++++++++------------ app/src/uart_commands.c | 123 ++++++++++------------------- 2 files changed, 91 insertions(+), 133 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index 186d06c..0042100 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -1,26 +1,38 @@ /* - * ESP32-S3 DevKitC Motor Driver Overlay + * ESP32-S3 DevKitC Hardware Overlay * * MD20A (PWM) motors: - * driveRight/NavM2 — DIR: GPIO3 PWM: GPIO9 (LEDC ch0) - * driveLeft/Navm1 — DIR: GPIO38 PWM: GPIO39 (LEDC ch1) - * digActuator/LinAct1 — DIR: GPIO14 PWM: GPIO21 (LEDC ch2) + * driveRight — DIR: GPIO1 PWM: GPIO4 (LEDC ch0) + * driveLeft — DIR: GPIO2 PWM: GPIO5 (LEDC ch1) + * digActuator — DIR: GPIO3 PWM: GPIO6 (LEDC ch2) * * DM542T (stepper) motors: - * digStepper — DIR: GPIO48 PUL: GPIO47 - * susanStepper — DIR: GPIO11 PUL: GPIO10 - * tampActuator — DIR: GPIO13 PUL: GPIO12 + * digStepper — DIR: GPIO14 PUL: GPIO13 + * susanStepper — DIR: GPIO16 PUL: GPIO15 + * tampActuator — DIR: GPIO18 PUL: GPIO17 * * Servo motors: - * soilDrop — PWM: GPIO8 + * soilDrop — PWM: GPIO7 + * + * BQ76930 BMS: + * I2C SDA: GPIO36 SCL: GPIO35 + * ALERT: GPIO2 (active-low, open-drain — pull-up configured in driver) + * + * CRSF RC receiver: + * TX: GPIO18 RX: GPIO17 (UART1, 420000 baud) + * + * WS2812B LED strip: + * MOSI: GPIO5 (SPI2) */ #include /* ----------------------------------------------------------------------- - * Pin control — route LEDC channels to physical GPIO pins + * Pin control — all pinmux groups must live here in &pinctrl * ----------------------------------------------------------------------- */ &pinctrl { + + /* LEDC PWM outputs */ ledc0_default: ledc0_default { group1 { pinmux = , @@ -31,7 +43,7 @@ }; }; - // CRSF serial, could be different pin configs and uart channels on ESP32-S3 + /* CRSF serial (UART1) */ uart1_crsf: uart1_crsf { group1 { pinmux = ; @@ -42,16 +54,8 @@ input-enable; }; }; - /* ← lsm6dso does NOT belong here */ -}; - -/* lsm6dso goes here instead */ -&i2c0 { - status = "okay"; - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - clock-frequency = ; + /* I2C0 — BQ76930 BMS */ i2c0_default: i2c0_default { group1 { pinmux = , @@ -61,7 +65,7 @@ }; }; - // spi for led strip data pin control + /* SPI2 — WS2812B LED strip data line */ spim2_default: spim2_default { group1 { pinmux = ; @@ -70,32 +74,28 @@ }; }; -&i2c0 { +/* ----------------------------------------------------------------------- + * UART1 — CRSF RC receiver at 420 kbaud + * ----------------------------------------------------------------------- */ +&uart1 { status = "okay"; - pinctrl-0 = <&i2c0_default>; + current-speed = <420000>; + pinctrl-0 = <&uart1_crsf>; pinctrl-names = "default"; - clock-frequency = ; - - /* - lsm6dso: lsm6dso@6b { - compatible = "st,lsm6dso"; - reg = <0x6b>; - status = "okay"; - }; - */ }; - -// CRSF serial, baud rate at 420000 -&uart1 { +/* ----------------------------------------------------------------------- + * I2C0 — BQ76930 battery management IC + * ----------------------------------------------------------------------- */ +&i2c0 { status = "okay"; - current-speed = <420000>; - pinctrl-0 = <&uart1_crsf>; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; pinctrl-names = "default"; }; /* ----------------------------------------------------------------------- - * LEDC (PWM) controller — 4 channels, 1 kHz, 10-bit resolution + * LEDC (PWM) — 4 channels * ----------------------------------------------------------------------- */ &ledc0 { status = "okay"; @@ -104,45 +104,42 @@ #address-cells = <1>; #size-cells = <0>; - /* Timer 0 shared by all three channels */ channel0@0 { reg = <0>; timer = <0>; }; - channel1@1 { reg = <1>; timer = <0>; }; - channel2@2 { reg = <2>; timer = <0>; }; - channel3@3 { reg = <3>; timer = <1>; }; }; -// SPI controller for WS2812B LED strip -// hopefully this works, timing is controlled by the one and zero frame parameters, if anything goes wrong it might be that +/* ----------------------------------------------------------------------- + * SPI2 — WS2812B LED strip + * ----------------------------------------------------------------------- */ &spi2 { status = "okay"; pinctrl-0 = <&spim2_default>; pinctrl-names = "default"; - + led_strip: ws2812@0 { compatible = "worldsemi,ws2812-spi"; reg = <0>; - spi-max-frequency = <3200000>; /* 3.2MHz for better timing */ + spi-max-frequency = <3200000>; chain-length = <9>; color-mapping = <2 /* GREEN */ - 1 /* RED */ - 3>; /* BLUE */ - spi-one-frame = <0xFC>; /* 11111100 - longer '1' */ - spi-zero-frame = <0x80>; /* 10000000 - shorter '0' */ + 1 /* RED */ + 3>; /* BLUE */ + spi-one-frame = <0xFC>; + spi-zero-frame = <0x80>; bits-per-symbol = <8>; reset-delay = <280>; label = "WS2812B"; @@ -150,10 +147,8 @@ }; /* ----------------------------------------------------------------------- - * GPIO0 — already defined by the SoC; just ensure it is enabled. - * All dir/pulse pins are driven purely from software (gpio_pin_configure_dt), - * so no additional pinctrl entry is needed for plain GPIO on ESP32-S3. + * GPIO0 — direction/pulse pins driven from software * ----------------------------------------------------------------------- */ &gpio0 { status = "okay"; -}; \ No newline at end of file +}; diff --git a/app/src/uart_commands.c b/app/src/uart_commands.c index 96bfebe..6877f5d 100644 --- a/app/src/uart_commands.c +++ b/app/src/uart_commands.c @@ -7,124 +7,87 @@ LOG_MODULE_REGISTER(uart_commands, LOG_LEVEL_INF); -// Shell command: battery +// Shell command: bat +// Example: bat 75 1 static int cmd_battery(const struct shell *sh, size_t argc, char **argv) { if (argc != 3) { shell_print(sh, "Usage: bat "); shell_print(sh, " percentage: 0-100"); - shell_print(sh, " charging: 0=not charging, 1=charging"); + shell_print(sh, " charging: 0=not charging, 1=charging"); shell_print(sh, "Example: bat 75 1"); return -EINVAL; } - + int percentage = atoi(argv[1]); - int charging = atoi(argv[2]); - + int charging = atoi(argv[2]); + if (percentage < 0 || percentage > 100) { shell_error(sh, "Percentage must be 0-100"); return -EINVAL; } - - led_controller_set_battery(percentage, charging != 0); - shell_print(sh, "Battery set to %d%% %s", percentage, charging ? "(charging)" : ""); - + + led_controller_set_battery((uint8_t)percentage, charging != 0); + shell_print(sh, "Battery: %d%% %s", percentage, charging ? "(charging)" : ""); + return 0; } -// Shell command: planting step -static int cmd_step(const struct shell *sh, size_t argc, char **argv) +// Shell command: err <1|0> +// Set or clear an error on a planting step. +// Example: err 2 1 (mark Dig as error) +// err 2 0 (clear Dig error) +static int cmd_error(const struct shell *sh, size_t argc, char **argv) { if (argc != 3) { - shell_print(sh, "Usage: step <1-4> "); - shell_print(sh, " status: idle|progress|done|maint"); - shell_print(sh, "Example: step 2 progress"); + shell_print(sh, "Usage: err <1|0>"); + shell_print(sh, " step: 1=Drive 2=Dig 3=Place 4=Tamp"); + shell_print(sh, " 1=set error, 0=clear error"); + shell_print(sh, "Example: err 2 1"); return -EINVAL; } - - int step = atoi(argv[1]); - + + int step = atoi(argv[1]); + int error = atoi(argv[2]); + if (step < 1 || step > 4) { shell_error(sh, "Step must be 1-4"); return -EINVAL; } - - enum planting_step_status status; - - if (strcmp(argv[2], "idle") == 0) { - status = PLANTING_NOT_STARTED; - } else if (strcmp(argv[2], "progress") == 0) { - status = PLANTING_IN_PROGRESS; - } else if (strcmp(argv[2], "done") == 0) { - status = PLANTING_COMPLETED; - } else if (strcmp(argv[2], "maint") == 0) { - status = PLANTING_MAINTENANCE; - } else { - shell_error(sh, "Invalid status. Use: idle|progress|done|maint"); - return -EINVAL; - } - - led_controller_set_planting_step(step, status); - shell_print(sh, "Step %d status set", step); - - return 0; -} -// Shell command: system state -static int cmd_system(const struct shell *sh, size_t argc, char **argv) -{ - if (argc != 2) { - shell_print(sh, "Usage: sys "); - shell_print(sh, " state: idle|load|plant"); - shell_print(sh, "Example: sys load"); - return -EINVAL; - } - - enum system_state state; - - if (strcmp(argv[1], "idle") == 0) { - state = SYSTEM_IDLE; - } else if (strcmp(argv[1], "load") == 0) { - state = SYSTEM_LOADING; - } else if (strcmp(argv[1], "plant") == 0) { - state = SYSTEM_PLANTING; - } else { - shell_error(sh, "Invalid state. Use: idle|load|plant"); - return -EINVAL; - } - - led_controller_set_system_state(state); - shell_print(sh, "System state set"); - + led_controller_set_planting_error((uint8_t)step, error != 0); + shell_print(sh, "Step %d error %s", step, error ? "set" : "cleared"); + return 0; } -// Shell command: complete cycle +// Shell command: complete +// Signal that the full planting cycle is done (all LEDs solid white). static int cmd_complete(const struct shell *sh, size_t argc, char **argv) { ARG_UNUSED(argc); ARG_UNUSED(argv); - - led_controller_complete_cycle(); - shell_print(sh, "Cycle complete - all steps reset to idle"); - + + led_controller_set_planting_complete(); + shell_print(sh, "Planting cycle marked complete"); + return 0; } -// Shell command: status -static int cmd_status(const struct shell *sh, size_t argc, char **argv) +// Shell command: resetp +// Reset planting state (clears complete flag and all errors). +static int cmd_reset_planting(const struct shell *sh, size_t argc, char **argv) { ARG_UNUSED(argc); ARG_UNUSED(argv); - - led_controller_get_status(); - + + led_controller_reset_planting(); + shell_print(sh, "Planting state reset"); + return 0; } -// Register shell commands -SHELL_CMD_REGISTER(bat, NULL, "Set battery state", cmd_battery); -SHELL_CMD_REGISTER(step, NULL, "Set planting step status", cmd_step); -SHELL_CMD_REGISTER(sys, NULL, "Set system state", cmd_system); -SHELL_CMD_REGISTER(complete, NULL, "Complete cycle and reset", cmd_complete); -SHELL_CMD_REGISTER(status, NULL, "Show current status", cmd_status); \ No newline at end of file +SHELL_CMD_REGISTER(bat, NULL, "Set battery state: bat ", cmd_battery); +SHELL_CMD_REGISTER(err, NULL, "Set planting step error: err <1-4> <1|0>", cmd_error); +SHELL_CMD_REGISTER(complete, NULL, "Mark planting cycle complete", cmd_complete); +SHELL_CMD_REGISTER(resetp, NULL, "Reset planting state (clears errors/complete)", cmd_reset_planting); From fd5f1be9c0d439033c6f7574388742bf79025f64 Mon Sep 17 00:00:00 2001 From: fnckingsnowman Date: Wed, 15 Apr 2026 15:18:34 -0400 Subject: [PATCH 09/13] buzzer: buzzer noises implemented with ledcontroller --- app/src/buzzer.c | 8 ++++---- app/src/led_controller.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app/src/buzzer.c b/app/src/buzzer.c index 9d9b4f1..2941087 100644 --- a/app/src/buzzer.c +++ b/app/src/buzzer.c @@ -77,19 +77,19 @@ void buzzer_planting_complete(void){ // for each planting state when they complete the step void buzzer_step_1(void){ - buzzer_beep(1500, 200); + buzzer_beep(1500, 400); } void buzzer_step_2(void){ - buzzer_beep(2000, 200); + buzzer_beep(2000, 400); } void buzzer_step_3(void){ - buzzer_beep(2500, 200); + buzzer_beep(2500, 400); } void buzzer_step_4(void){ - buzzer_beep(3000, 200); + buzzer_beep(3000, 400); } void buzzer_maintenance(void){ diff --git a/app/src/led_controller.c b/app/src/led_controller.c index aa12612..e6c3cc1 100644 --- a/app/src/led_controller.c +++ b/app/src/led_controller.c @@ -1,6 +1,7 @@ #include "led_controller.h" #include "led_strip.h" #include "types.h" +#include "buzzer.h" #include #include @@ -183,6 +184,28 @@ static void led_update_thread(void *arg1, void *arg2, void *arg3) // Single word read — same lock-free pattern used for rcIn state_t current_state = mcu->state; + state_t prev_state = mcu->state; + + // Detect state transition and play the matching sound + if (current_state != prev_state) { + switch (current_state) { + case Drive: + buzzer_planting_start(); // system turned on, starting to drive + break; + case Dig: + buzzer_step_1(); // Drive done, entering Dig + break; + case Place: + buzzer_step_2(); // Dig done, entering Place + break; + case Tamp: + buzzer_step_3(); // Place done, entering Tamp + break; + default: + break; + } + prev_state = current_state; + } // Lock once to read all of led_state and write pixels[] k_mutex_lock(&state_mutex, K_FOREVER); @@ -217,6 +240,9 @@ int led_controller_init(mcu_t *mcu) k_thread_name_set(&led_update_thread_data, "led_update"); LOG_INF("LED controller initialized"); + + buzzer_play_startup(); + return 0; } @@ -242,6 +268,7 @@ void led_controller_set_planting_error(uint8_t step, bool error) k_mutex_lock(&state_mutex, K_FOREVER); if (error) { led_state.error_steps |= (1 << (step - 1)); + buzzer_maintenance(); } else { led_state.error_steps &= ~(1 << (step - 1)); } @@ -254,6 +281,8 @@ void led_controller_set_planting_complete(void) led_state.planting_complete = true; k_mutex_unlock(&state_mutex); + buzzer_play_nokia(); + LOG_INF("Planting cycle complete"); } From 26c88ce910cc35dc91e10adc6eccc989a825bc78 Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Wed, 15 Apr 2026 19:28:41 -0400 Subject: [PATCH 10/13] Fix to MVP --- app/esp32s3_devkitc_procpu.overlay | 36 ++++++------------------------ app/include/dig.h | 2 +- app/src/dig.c | 9 +++++--- app/src/main.c | 2 +- app/src/motor.c | 2 +- 5 files changed, 16 insertions(+), 35 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index 3ed4b16..f596c00 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -3,7 +3,7 @@ * * MD20A (PWM) motors: * driveRight/NavM2 — DIR: GPIO3 PWM: GPIO9 (LEDC ch0) - * driveLeft/Navm1 — DIR: GPIO38 PWM: GPIO39 (LEDC ch1) + * driveLeft/Navm1 — DIR: GPIO37 PWM: GPIO38 (LEDC ch1) * digActuator/LinAct1 — DIR: GPIO14 PWM: GPIO21 (LEDC ch2) * * DM542T (stepper) motors: @@ -24,7 +24,7 @@ ledc0_default: ledc0_default { group1 { pinmux = , - , + , , ; output-enable; @@ -32,39 +32,17 @@ }; uart1_crsf: uart1_crsf { - group1 { - pinmux = ; /* free UART-capable pins */ - output-enable; - }; - group2 { - pinmux = ; - input-enable; - }; -}; - - i2c0_default: i2c0_default { group1 { - pinmux = , - ; - drive-open-drain; + pinmux = ; /* free UART-capable pins */ output-enable; }; + group2 { + pinmux = ; + input-enable; + }; }; }; -/* lsm6dso goes here instead */ -&i2c0 { - status = "okay"; - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - clock-frequency = ; - - lsm6dso: lsm6dso@6b { - compatible = "st,lsm6dso"; - reg = <0x6b>; - status = "okay"; - }; -}; // CRSF serial, baud rate at 420000 &uart1 { diff --git a/app/include/dig.h b/app/include/dig.h index 429994d..65b39fd 100644 --- a/app/include/dig.h +++ b/app/include/dig.h @@ -3,7 +3,7 @@ #include "types.h" #include "place.h" -#define DIG_LOWER_TIME_MS 5000 +#define DIG_LOWER_TIME_MS 2000 #define POST_DIG_DRIVE_TIME_MS 5000 int dig(mcu_t *mcu); diff --git a/app/src/dig.c b/app/src/dig.c index 1931ec4..9099496 100644 --- a/app/src/dig.c +++ b/app/src/dig.c @@ -15,15 +15,18 @@ int dig(mcu_t *mcu) { int move_dig_motor(mcu_t *mcu) { // Lower/Dig + set_motor_speed(mcu->digActuator, MOTOR_FORWARD, 50); set_step_motor(mcu->digStepper, 360, 60, MOTOR_FORWARD); // If DIP switch is at 400, this is one revolution at 60rpm TODO: Change later - set_motor_speed(mcu->digActuator, MOTOR_FORWARD, 100); - // Wait + // Wait for k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); // Raise/Stop Digging set_step_motor(mcu->digStepper, 0, 0, MOTOR_STOP); // If DIP switch is at 400, this is one revolution at 60rpm - set_motor_speed(mcu->digActuator, MOTOR_BACKWARD, 100); + set_motor_speed(mcu->digActuator, MOTOR_BACKWARD, 50); + + // Wait for linear actuator to retract + k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); return 0; } diff --git a/app/src/main.c b/app/src/main.c index 957532e..326983f 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -74,7 +74,7 @@ static void main_thread_entry(void *p1, void *p2, void *p3) default: break; } - + k_sleep(K_MSEC(20)); continue; drive(mcu); diff --git a/app/src/motor.c b/app/src/motor.c index a594d92..767c767 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -178,7 +178,7 @@ int init_motor(mcu_t *mcu) /* --- GPIO dir/pulse specs ---------------------------------------- */ /* MD20A motors — dir only */ gpio_spec_init(&drive_right_dir_spec, gpio_dev0, 3); - gpio_spec_init(&drive_left_dir_spec, gpio_dev0, 38); /* GPIO38 = gpio1 pin 6 */ + gpio_spec_init(&drive_left_dir_spec, gpio_dev0, 37); /* GPIO38 = gpio1 pin 6 */ gpio_spec_init(&dig_actuator_dir_spec, gpio_dev0, 14); /* DM542T steppers — dir + pulse */ gpio_spec_init(&dig_stepper_dir_spec, gpio_dev0, 48); /* GPIO48 = gpio1 pin 16 */ From 5a546ff04c8b8bb13d2da561139b2ba400eeff10 Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Thu, 16 Apr 2026 18:44:32 -0400 Subject: [PATCH 11/13] working --- app/esp32s3_devkitc_procpu.overlay | 6 +----- app/src/dig.c | 4 ++-- app/src/led_controller.c | 8 ++++++-- app/src/main.c | 18 +++--------------- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index db0da90..283133e 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -9,7 +9,7 @@ * DM542T (stepper) motors: * digStepper — DIR: GPIO14 PUL: GPIO13 * susanStepper — DIR: GPIO16 PUL: GPIO15 - * tampActuator — DIR: GPIO18 PUL: GPIO17 + * tampActuator — DIR: GPIO13 PUL: GPIO12 * * Servo motors: * soilDrop — PWM: GPIO7 @@ -63,10 +63,6 @@ drive-open-drain; output-enable; }; - group2 { - pinmux = ; - input-enable; - }; }; /* SPI2 — WS2812B LED strip data line */ diff --git a/app/src/dig.c b/app/src/dig.c index 9099496..2273c53 100644 --- a/app/src/dig.c +++ b/app/src/dig.c @@ -16,7 +16,7 @@ int dig(mcu_t *mcu) { int move_dig_motor(mcu_t *mcu) { // Lower/Dig set_motor_speed(mcu->digActuator, MOTOR_FORWARD, 50); - set_step_motor(mcu->digStepper, 360, 60, MOTOR_FORWARD); // If DIP switch is at 400, this is one revolution at 60rpm TODO: Change later + set_step_motor(mcu->digStepper, 360, 20, MOTOR_FORWARD); // If DIP switch is at 400, this is one revolution at 20rpm TODO: Change later // Wait for k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); @@ -26,7 +26,7 @@ int move_dig_motor(mcu_t *mcu) { set_motor_speed(mcu->digActuator, MOTOR_BACKWARD, 50); // Wait for linear actuator to retract - k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); + k_sleep(K_MSEC(DIG_LOWER_TIME_MS + 1000)); return 0; } diff --git a/app/src/led_controller.c b/app/src/led_controller.c index e6c3cc1..0b72a8d 100644 --- a/app/src/led_controller.c +++ b/app/src/led_controller.c @@ -184,7 +184,7 @@ static void led_update_thread(void *arg1, void *arg2, void *arg3) // Single word read — same lock-free pattern used for rcIn state_t current_state = mcu->state; - state_t prev_state = mcu->state; + static state_t prev_state = Bootup; // Detect state transition and play the matching sound if (current_state != prev_state) { @@ -240,7 +240,11 @@ int led_controller_init(mcu_t *mcu) k_thread_name_set(&led_update_thread_data, "led_update"); LOG_INF("LED controller initialized"); - + + ret = buzzer_init(); + if (ret < 0) { + LOG_ERR("Failed to initialize buzzer: %d", ret); + } buzzer_play_startup(); return 0; diff --git a/app/src/main.c b/app/src/main.c index 4df9317..82b0f28 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -44,9 +44,8 @@ static void main_thread_entry(void *p1, void *p2, void *p3) ARG_UNUSED(p2); ARG_UNUSED(p3); printk("\nEntered main task."); + mcu_t *mcu = (mcu_t *)p1; - - bool testing = true; mcu->state = Idle; while (1) { @@ -75,20 +74,9 @@ static void main_thread_entry(void *p1, void *p2, void *p3) default: break; } - k_sleep(K_MSEC(20)); + set_step_motor(mcu->digStepper, 360, 10, MOTOR_FORWARD); + k_sleep(K_MSEC(200)); continue; - drive(mcu); - - set_step_motor(mcu->susanStepper, 360, 20, MOTOR_FORWARD); - //step_motor(mcu->susanStepper, 400, 4000, MOTOR_FORWARD); - - if (testing) { - set_servo_position(mcu->soilDrop, SERVO_OPEN); - } else { - set_servo_position(mcu->soilDrop, SERVO_CLOSED); - } - testing = !testing; - k_sleep(K_MSEC(2000)); } printk("main_thread: exited unexpectedly\n"); } From 13d551f48cbf60bb4e80a48c5aeb9131e2879873 Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Thu, 16 Apr 2026 20:03:42 -0400 Subject: [PATCH 12/13] stepper not working --- app/esp32s3_devkitc_procpu.overlay | 8 ++++---- app/src/led_controller.c | 19 ++++++++----------- app/src/led_strip.c | 6 +++--- app/src/main.c | 5 ++--- app/src/motor.c | 8 ++++---- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index 283133e..ac14c5a 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -7,12 +7,12 @@ * digActuator/LinAct1 — DIR: GPIO14 PWM: GPIO21 (LEDC ch2) * * DM542T (stepper) motors: - * digStepper — DIR: GPIO14 PUL: GPIO13 - * susanStepper — DIR: GPIO16 PUL: GPIO15 + * digStepper — DIR: GPIO48 PUL: GPIO47 + * susanStepper — DIR: GPIO11 PUL: GPIO10 * tampActuator — DIR: GPIO13 PUL: GPIO12 * * Servo motors: - * soilDrop — PWM: GPIO7 + * soilDrop — PWM: GPIO8 * * BQ76930 BMS: * I2C SDA: GPIO36 SCL: GPIO35 @@ -134,7 +134,7 @@ compatible = "worldsemi,ws2812-spi"; reg = <0>; spi-max-frequency = <3200000>; - chain-length = <9>; + chain-length = <8>; color-mapping = <2 /* GREEN */ 1 /* RED */ 3>; /* BLUE */ diff --git a/app/src/led_controller.c b/app/src/led_controller.c index 0b72a8d..3dcc647 100644 --- a/app/src/led_controller.c +++ b/app/src/led_controller.c @@ -4,9 +4,6 @@ #include "buzzer.h" #include -#include - -LOG_MODULE_REGISTER(led_controller, LOG_LEVEL_INF); // ── LED index assignments ──────────────────────────────────────────────────── // pixels 0-3: battery tier indicators @@ -172,7 +169,7 @@ static void led_update_thread(void *arg1, void *arg2, void *arg3) mcu_t *mcu = (mcu_t *)arg1; - LOG_INF("LED update thread started"); + printk("LED update thread started\n"); while (1) { // Advance blink state @@ -225,7 +222,7 @@ int led_controller_init(mcu_t *mcu) { int ret = led_strip_init(); if (ret < 0) { - LOG_ERR("Failed to initialize LED strip: %d", ret); + printk("Failed to initialize LED strip: %d\n", ret); return ret; } @@ -239,11 +236,11 @@ int led_controller_init(mcu_t *mcu) LED_UPDATE_THREAD_PRIORITY, 0, K_NO_WAIT); k_thread_name_set(&led_update_thread_data, "led_update"); - LOG_INF("LED controller initialized"); + printk("LED controller initialized\n"); ret = buzzer_init(); if (ret < 0) { - LOG_ERR("Failed to initialize buzzer: %d", ret); + printk("Failed to initialize buzzer: %d\n", ret); } buzzer_play_startup(); @@ -260,13 +257,13 @@ void led_controller_set_battery(uint8_t percentage, bool is_charging) led_state.is_charging = is_charging; k_mutex_unlock(&state_mutex); - LOG_INF("Battery: %d%% %s", percentage, is_charging ? "(charging)" : ""); + printk("Battery: %d%% %s\n", percentage, is_charging ? "(charging)" : ""); } void led_controller_set_planting_error(uint8_t step, bool error) { if (step < 1 || step > 4) { - LOG_ERR("Invalid step %d (must be 1-4)", step); + printk("Invalid step %d (must be 1-4)\n", step); return; } k_mutex_lock(&state_mutex, K_FOREVER); @@ -287,7 +284,7 @@ void led_controller_set_planting_complete(void) buzzer_play_nokia(); - LOG_INF("Planting cycle complete"); + printk("Planting cycle complete\n"); } void led_controller_reset_planting(void) @@ -297,5 +294,5 @@ void led_controller_reset_planting(void) led_state.error_steps = 0; k_mutex_unlock(&state_mutex); - LOG_INF("Planting state reset"); + printk("Planting state reset\n"); } diff --git a/app/src/led_strip.c b/app/src/led_strip.c index 588354c..0ad1a93 100644 --- a/app/src/led_strip.c +++ b/app/src/led_strip.c @@ -203,10 +203,10 @@ int led_strip_test(void) // Test individual LEDs LOG_INF("Testing individual LEDs..."); - struct led_rgb pixels[9] = {0}; - for (int i = 0; i < 9; i++) { + struct led_rgb pixels[8] = {0}; + for (int i = 0; i < 8; i++) { pixels[i].r = 255; // Red - led_strip_update_rgb(led_strip_dev, pixels, 9); + led_strip_update_rgb(led_strip_dev, pixels, 8); k_sleep(K_MSEC(200)); pixels[i].r = 0; } diff --git a/app/src/main.c b/app/src/main.c index 82b0f28..af2459e 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -44,7 +44,7 @@ static void main_thread_entry(void *p1, void *p2, void *p3) ARG_UNUSED(p2); ARG_UNUSED(p3); printk("\nEntered main task."); - + mcu_t *mcu = (mcu_t *)p1; mcu->state = Idle; @@ -75,8 +75,7 @@ static void main_thread_entry(void *p1, void *p2, void *p3) break; } set_step_motor(mcu->digStepper, 360, 10, MOTOR_FORWARD); - k_sleep(K_MSEC(200)); - continue; + step_motor(mcu->digStepper, 400, 4000, MOTOR_BACKWARD); } printk("main_thread: exited unexpectedly\n"); } diff --git a/app/src/motor.c b/app/src/motor.c index 767c767..28a54da 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -178,11 +178,11 @@ int init_motor(mcu_t *mcu) /* --- GPIO dir/pulse specs ---------------------------------------- */ /* MD20A motors — dir only */ gpio_spec_init(&drive_right_dir_spec, gpio_dev0, 3); - gpio_spec_init(&drive_left_dir_spec, gpio_dev0, 37); /* GPIO38 = gpio1 pin 6 */ + gpio_spec_init(&drive_left_dir_spec, gpio_dev0, 37); gpio_spec_init(&dig_actuator_dir_spec, gpio_dev0, 14); /* DM542T steppers — dir + pulse */ - gpio_spec_init(&dig_stepper_dir_spec, gpio_dev0, 48); /* GPIO48 = gpio1 pin 16 */ - gpio_spec_init(&dig_stepper_pul_spec, gpio_dev0, 47); /* GPIO47 = gpio1 pin 15 */ + gpio_spec_init(&dig_stepper_dir_spec, gpio_dev0, 48); + gpio_spec_init(&dig_stepper_pul_spec, gpio_dev0, 47); gpio_spec_init(&susan_stepper_dir_spec, gpio_dev0, 11); gpio_spec_init(&susan_stepper_pul_spec, gpio_dev0, 10); gpio_spec_init(&tamp_actuator_dir_spec, gpio_dev0, 13); @@ -306,7 +306,7 @@ int step_motor(motor_t *motor, uint32_t steps, uint32_t step_period_us, motor_di gpio_pin_set_dt(motor->config.pul, 0); k_busy_wait(half); } - + printk("\nFinished moving motor: %d", half); return 0; } From 5b5818a97c60961ece05d415a17fbb1539a9475d Mon Sep 17 00:00:00 2001 From: Jake-Hensley Date: Thu, 16 Apr 2026 21:19:15 -0400 Subject: [PATCH 13/13] Tweaked digging params --- app/esp32s3_devkitc_procpu.overlay | 4 ++++ app/src/dig.c | 10 ++++++---- app/src/main.c | 14 +------------- app/src/motor.c | 9 +++++++-- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/app/esp32s3_devkitc_procpu.overlay b/app/esp32s3_devkitc_procpu.overlay index f596c00..3eec53a 100644 --- a/app/esp32s3_devkitc_procpu.overlay +++ b/app/esp32s3_devkitc_procpu.overlay @@ -91,4 +91,8 @@ * ----------------------------------------------------------------------- */ &gpio0 { status = "okay"; +}; + +&gpio1 { + status = "okay"; }; \ No newline at end of file diff --git a/app/src/dig.c b/app/src/dig.c index 9099496..cf65d19 100644 --- a/app/src/dig.c +++ b/app/src/dig.c @@ -16,14 +16,16 @@ int dig(mcu_t *mcu) { int move_dig_motor(mcu_t *mcu) { // Lower/Dig set_motor_speed(mcu->digActuator, MOTOR_FORWARD, 50); - set_step_motor(mcu->digStepper, 360, 60, MOTOR_FORWARD); // If DIP switch is at 400, this is one revolution at 60rpm TODO: Change later + set_step_motor(mcu->digStepper, 720, 15, MOTOR_FORWARD); + //step_motor(mcu->digStepper, 1500, 750, MOTOR_FORWARD); // Wait for - k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); + // k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); + set_motor_speed(mcu->digActuator, MOTOR_STOP, 0); + set_step_motor(mcu->digStepper, 360, 15, MOTOR_FORWARD); // Raise/Stop Digging - set_step_motor(mcu->digStepper, 0, 0, MOTOR_STOP); // If DIP switch is at 400, this is one revolution at 60rpm - set_motor_speed(mcu->digActuator, MOTOR_BACKWARD, 50); + set_motor_speed(mcu->digActuator, MOTOR_BACKWARD, 75); // Wait for linear actuator to retract k_sleep(K_MSEC(DIG_LOWER_TIME_MS)); diff --git a/app/src/main.c b/app/src/main.c index 326983f..de6bb58 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -76,18 +76,6 @@ static void main_thread_entry(void *p1, void *p2, void *p3) } k_sleep(K_MSEC(20)); continue; - drive(mcu); - - set_step_motor(mcu->susanStepper, 360, 20, MOTOR_FORWARD); - //step_motor(mcu->susanStepper, 400, 4000, MOTOR_FORWARD); - - if (testing) { - set_servo_position(mcu->soilDrop, SERVO_OPEN); - } else { - set_servo_position(mcu->soilDrop, SERVO_CLOSED); - } - testing = !testing; - k_sleep(K_MSEC(2000)); } printk("main_thread: exited unexpectedly\n"); } @@ -122,7 +110,7 @@ int main(void) main_thread_entry, &mcu, NULL, NULL, MAIN_THREAD_PRIORITY, - 0, + K_FP_REGS, K_NO_WAIT ); k_thread_name_set(&main_thread_data, "main"); diff --git a/app/src/motor.c b/app/src/motor.c index 767c767..abbb135 100644 --- a/app/src/motor.c +++ b/app/src/motor.c @@ -50,6 +50,7 @@ LOG_MODULE_REGISTER(motor_driver, LOG_LEVEL_INF); * Device references — resolved at compile time via devicetree * ----------------------------------------------------------------------- */ static const struct device *gpio_dev0 = DEVICE_DT_GET(DT_NODELABEL(gpio0)); +static const struct device *gpio_dev1 = DEVICE_DT_GET(DT_NODELABEL(gpio1)); static const struct device *pwm_dev = DEVICE_DT_GET(DT_NODELABEL(ledc0)); /* ----------------------------------------------------------------------- @@ -170,6 +171,10 @@ int init_motor(mcu_t *mcu) printk("GPIO0 device not ready"); return -ENODEV; } + if (!device_is_ready(gpio_dev1)) { + printk("GPIO1 device not ready"); + return -ENODEV; + } if (!device_is_ready(pwm_dev)) { printk("LEDC0 (PWM) device not ready"); return -ENODEV; @@ -181,8 +186,8 @@ int init_motor(mcu_t *mcu) gpio_spec_init(&drive_left_dir_spec, gpio_dev0, 37); /* GPIO38 = gpio1 pin 6 */ gpio_spec_init(&dig_actuator_dir_spec, gpio_dev0, 14); /* DM542T steppers — dir + pulse */ - gpio_spec_init(&dig_stepper_dir_spec, gpio_dev0, 48); /* GPIO48 = gpio1 pin 16 */ - gpio_spec_init(&dig_stepper_pul_spec, gpio_dev0, 47); /* GPIO47 = gpio1 pin 15 */ + gpio_spec_init(&dig_stepper_dir_spec, gpio_dev1, 16); /* GPIO48 = gpio1 pin 16 */ + gpio_spec_init(&dig_stepper_pul_spec, gpio_dev1, 15); /* GPIO47 = gpio1 pin 15 */ gpio_spec_init(&susan_stepper_dir_spec, gpio_dev0, 11); gpio_spec_init(&susan_stepper_pul_spec, gpio_dev0, 10); gpio_spec_init(&tamp_actuator_dir_spec, gpio_dev0, 13);