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
3 changes: 2 additions & 1 deletion app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.22)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project (growver_firmware)

target_sources(app PRIVATE
target_sources(app PRIVATE
src/main.c
src/motor.c
src/servo.c
Expand All @@ -17,6 +17,7 @@ target_sources(app PRIVATE
src/led_controller.c
src/buzzer.c
src/uart_commands.c
src/fsr.c
)

target_include_directories(app PRIVATE include)
36 changes: 27 additions & 9 deletions app/esp32s3_devkitc_procpu.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include <zephyr/dt-bindings/pinctrl/esp32s3-pinctrl.h>
#include <zephyr/dt-bindings/adc/adc.h>

/* -----------------------------------------------------------------------
* Pin control — route LEDC channels to physical GPIO pins
Expand All @@ -42,16 +43,9 @@
input-enable;
};
};
/* ← lsm6dso does NOT belong here */
};

/* lsm6dso goes here instead */
&i2c0 {
status = "okay";
pinctrl-0 = <&i2c0_default>;
pinctrl-names = "default";
clock-frequency = <I2C_BITRATE_FAST>;

/* Board defines i2c0_default (GPIO1/2) and spim2_default — override them */
/delete-node/ i2c0_default;
i2c0_default: i2c0_default {
group1 {
pinmux = <I2C0_SDA_GPIO36>,
Expand All @@ -62,6 +56,7 @@
};

// spi for led strip data pin control
/delete-node/ spim2_default;
spim2_default: spim2_default {
group1 {
pinmux = <SPIM2_MOSI_GPIO5>;
Expand Down Expand Up @@ -156,4 +151,27 @@
* ----------------------------------------------------------------------- */
&gpio0 {
status = "okay";
};

/* -----------------------------------------------------------------------
* ADC — FSR force sensor on GPIO15 (ADC2 channel 4, Zephyr: adc1 ch4)
* ----------------------------------------------------------------------- */
/ {
zephyr,user {
io-channels = <&adc1 4>;
};
};

&adc1 {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;

channel@4 {
reg = <4>;
zephyr,gain = "ADC_GAIN_1_4"; /* 12 dB atten, ~3.55V full scale */
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <12>;
};
};
20 changes: 20 additions & 0 deletions app/include/fsr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef FSR_H
#define FSR_H

#include <stdint.h>

/**
* @brief Initialize the FSR ADC channel (GPIO15 / ADC2 CH4).
* @return 0 on success, negative errno on failure.
*/
int fsr_init(void);

/**
* @brief Read raw ADC count and converted millivolt value in one shot.
* @param raw_out 12-bit raw ADC value (0–4095).
* @param mv_out Voltage in millivolts.
* @return 0 on success, negative errno on failure.
*/
int fsr_read(uint16_t *raw_out, int32_t *mv_out);

#endif /* FSR_H */
3 changes: 2 additions & 1 deletion app/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ CONFIG_SHELL_ARGC_MAX=12
CONFIG_SHELL_CMD_BUFF_SIZE=256
CONFIG_KERNEL_SHELL=y

CONFIG_I2C=y
CONFIG_I2C=y
CONFIG_ADC=y
54 changes: 54 additions & 0 deletions app/src/fsr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/logging/log.h>
#include "fsr.h"

LOG_MODULE_REGISTER(fsr, LOG_LEVEL_DBG);

/* GPIO15 → ESP32-S3 ADC2 channel 4 → Zephyr node adc1, channel 4 */
static const struct adc_dt_spec fsr_chan =
ADC_DT_SPEC_GET(DT_PATH(zephyr_user));

int fsr_init(void)
{
if (!adc_is_ready_dt(&fsr_chan)) {
LOG_ERR("FSR ADC device not ready");
return -ENODEV;
}
int ret = adc_channel_setup_dt(&fsr_chan);
if (ret < 0) {
LOG_ERR("FSR ADC channel setup failed: %d", ret);
}
return ret;
}

int fsr_read(uint16_t *raw_out, int32_t *mv_out)
{
int16_t buf;
struct adc_sequence seq = {
.buffer = &buf,
.buffer_size = sizeof(buf),
};

int ret = adc_sequence_init_dt(&fsr_chan, &seq);
if (ret < 0) {
return ret;
}

ret = adc_read(fsr_chan.dev, &seq);
if (ret < 0) {
return ret;
}

*raw_out = (uint16_t)buf;

int32_t val = buf;
ret = adc_raw_to_millivolts_dt(&fsr_chan, &val);
if (ret < 0) {
return ret;
}

*mv_out = val;
return 0;
}
66 changes: 66 additions & 0 deletions app/src/main.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor.h>

#include "main.h"
#include "motor.h"
#include "drive.h"
#include "crsf.h"
#include "fsr.h"

/* Shared MCU handle — accessible by all threads */
static mcu_t mcu;
Expand All @@ -28,6 +30,55 @@ void rc_callback(const crsf_channels_t *ch)
}


static void i2c_scan(void)
{
const struct device *i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c0));

if (!device_is_ready(i2c_dev)) {
printk("I2C0 not ready\n");
return;
}

printk("I2C scan:\n");
int found = 0;
for (uint8_t addr = 0x08; addr <= 0x77; addr++) {
uint8_t dummy;
if (i2c_read(i2c_dev, &dummy, 0, addr) == 0) {
printk(" 0x%02x\n", addr);
found++;
}
}
printk(found ? "%d device(s) found.\n\n" : "No devices found.\n\n", found);
}

/* -----------------------------------------------------------------------
* FSR demo thread: logs raw count + millivolts every 500 ms
* ----------------------------------------------------------------------- */
#define FSR_THREAD_STACK_SIZE 1024
#define FSR_THREAD_PRIORITY 6

K_THREAD_STACK_DEFINE(fsr_stack, FSR_THREAD_STACK_SIZE);
static struct k_thread fsr_thread_data;

static void fsr_thread_entry(void *p1, void *p2, void *p3)
{
ARG_UNUSED(p1);
ARG_UNUSED(p2);
ARG_UNUSED(p3);

while (1) {
uint16_t raw;
int32_t mv;

if (fsr_read(&raw, &mv) == 0) {
printk("FSR: raw=%-5u %4d mV\n", raw, mv);
} else {
printk("FSR: read error\n");
}
k_msleep(500);
}
}

/* -----------------------------------------------------------------------
* Motor thread: runs move_motor's infinite sweep loop
* ----------------------------------------------------------------------- */
Expand Down Expand Up @@ -79,6 +130,21 @@ int main(void)

printk("Motor thread spawned\n");

/* FSR demo */
ret = fsr_init();
if (ret < 0) {
printk("FSR init failed: %d\n", ret);
} else {
k_thread_create(&fsr_thread_data, fsr_stack,
K_THREAD_STACK_SIZEOF(fsr_stack),
fsr_thread_entry, NULL, NULL, NULL,
FSR_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_name_set(&fsr_thread_data, "fsr_demo");
printk("FSR demo thread spawned\n");
}

i2c_scan();

/*
* main() must not return — the Zephyr kernel keeps running threads,
* but returning from main() on some configs halts the scheduler.
Expand Down