1.Project Planning
The use of IOT technology makes our lives more convenient, Matter as the mainstream IOT open protocol, Matter solves two key problems, device interconnection and message subscription and distribution mechanism between devices under multi-protocol conditions, although the implementation is more complex, but the adaptation effect should be the best at present. In response to the needs of remote pet feeding, the Matter protocol was used to interconnect sensors and actuators, and a prototype application was designed to realize the function of feeding pets remotely and checking the feeding effect.
2.Part Sourcing
To achieve the project goals, we applied for the nRF 7002DK development board and the nRF 52840 dongle, as well as a servo motor, a weight sensor, and a Zephyr-based nRF development SDK for the development platform:
1) Nordic7002DK
2) Motor
3) Sensor
4) Nordic 52840 Donge
3. Building
The Nordic7002DK acts as a controller to connect the sensor and the motor, which is connected via the GPIO port on the board.
The 52840Donge acts as a switch and connects to the Nordic7002DK via the Matter protocol (using wifi) to enable sensor data reading and control. The entire circuit is shown in the figure.
4.Coding and distance algorithm
Drawing on the matter examples in the nRF Development SDK, light bulb, light switch, and thermostat, you need to program the sensor, motor, and controller separately.
1) Sensors
The sensor is responsible for acquiring and transmitting the weight information through. We can use I2C to communicate with sensor. First config it in hardware overlap file, then write communicated code in source.
#if defined(CONFIG_APP_TRIGGER)
const struct sensor_trigger trig = {
.chan = SENSOR_CHAN_ALL,
.type = SENSOR_TRIG_TIMER,
};
static void trigger_handler(const struct device *dev,
const struct sensor_trigger *trig)
{
struct sensor_value temp, press, humidity, iaq;
sensor_sample_fetch(dev);
sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);
LOG_INF(" press: %d.%06d",
press.val1, press.val2,
);
};
#endif /* defined(CONFIG_APP_TRIGGER) */
int main(void)
{
const struct device *const dev = DEVICE_DT_GET_ANY(bosch_bme680);
LOG_INF("App started");
k_sleep(K_SECONDS(5));
if (dev == NULL) {
LOG_ERR("no device found");
return 0;
}
if (!device_is_ready(dev)) {
LOG_ERR("device is not ready");
return 0;
}
#if defined(CONFIG_APP_TRIGGER)
int ret = sensor_trigger_set(dev, &trig, trigger_handler);
if (ret) {
LOG_ERR("couldn't set trigger");
return 0;
}
#else
while (1) {
struct sensor_value temp, press, humidity, iaq;
sensor_sample_fetch(dev);
sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);
LOG_INF(" press: %d.%06d",
press.val1, press.val2,
);
k_sleep(K_MSEC(1000));
}
#endif /* defined(CONFIG_APP_TRIGGER) */
return 0;
}
2) Motor
The motor is responsible for opening the valve, releasing a certain amount of food, closing the valve.We can use PMW to driver with motor. First config it in hardware overlap file, then write communicated code in source.
/ {
servo: servo {
compatible = "pwm-servo";
pwms = <&flexpwm2_pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; /* FMU_CH1 */
/* <&flexpwm2_pwm1 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>, */ /* FMU_CH2 */
/* <&flexpwm2_pwm2 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>, */ /* FMU_CH3 */
/* <&flexpwm2_pwm3 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>, */ /* FMU_CH4 */
/* <&flexpwm3_pwm2 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>,*/ /* FMU_CH5 */
/* <&flexpwm3_pwm0 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; */ /* FMU_CH6 */
/* <&flexpwm4_pwm2 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; */ /* FMU_CH7 */
/* <&flexpwm4_pwm0 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; */ /* FMU_CH8 */
min-pulse = <PWM_USEC(700)>;
max-pulse = <PWM_USEC(2500)>;
};
};
static const struct pwm_dt_spec servo = PWM_DT_SPEC_GET(DT_NODELABEL(servo));
static const uint32_t min_pulse = DT_PROP(DT_NODELABEL(servo), min_pulse);
static const uint32_t max_pulse = DT_PROP(DT_NODELABEL(servo), max_pulse);
#define STEP PWM_USEC(100)
enum direction {
DOWN,
UP,
};
int main(void)
{
uint32_t pulse_width = min_pulse;
enum direction dir = UP;
int ret;
printk("Servomotor control\n");
if (!pwm_is_ready_dt(&servo)) {
printk("Error: PWM device %s is not ready\n", servo.dev->name);
return 0;
}
while (1) {
ret = pwm_set_pulse_dt(&servo, pulse_width);
if (ret < 0) {
printk("Error %d: failed to set pulse width\n", ret);
return 0;
}
if (dir == DOWN) {
if (pulse_width <= min_pulse) {
dir = UP;
pulse_width = min_pulse;
} else {
pulse_width -= STEP;
}
} else {
pulse_width += STEP;
if (pulse_width >= max_pulse) {
dir = DOWN;
pulse_width = max_pulse;
}
}
k_sleep(K_SECONDS(1));
}
return 0;
}
3) Controller
Connect to remote devices via the Matter protocol and send control signals. use button in dongle to send signal.
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios,
{0});
static struct gpio_callback button_cb_data;
/*
* The led0 devicetree alias is optional. If present, we'll use it
* to turn on the LED whenever the button is pressed.
*/
static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios,
{0});
void button_pressed(const struct device *dev, struct gpio_callback *cb,
uint32_t pins)
{
printk("Button pressed at %" PRIu32 "\n", k_cycle_get_32());
}
int main(void)
{
int ret;
if (!gpio_is_ready_dt(&button)) {
printk("Error: button device %s is not ready\n",
button.port->name);
return 0;
}
ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
if (ret != 0) {
printk("Error %d: failed to configure %s pin %d\n",
ret, button.port->name, button.pin);
return 0;
}
ret = gpio_pin_interrupt_configure_dt(&button,
GPIO_INT_EDGE_TO_ACTIVE);
if (ret != 0) {
printk("Error %d: failed to configure interrupt on %s pin %d\n",
ret, button.port->name, button.pin);
return 0;
}
gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
gpio_add_callback(button.port, &button_cb_data);
printk("Set up button at %s pin %d\n", button.port->name, button.pin);
if (led.port && !gpio_is_ready_dt(&led)) {
printk("Error %d: LED device %s is not ready; ignoring it\n",
ret, led.port->name);
led.port = NULL;
}
if (led.port) {
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
if (ret != 0) {
printk("Error %d: failed to configure LED device %s pin %d\n",
ret, led.port->name, led.pin);
led.port = NULL;
} else {
printk("Set up LED at %s pin %d\n", led.port->name, led.pin);
}
}
printk("Press the button\n");
if (led.port) {
while (1) {
/* If we have an LED, match its state to the button's. */
int val = gpio_pin_get_dt(&button);
if (val >= 0) {
gpio_pin_set_dt(&led, val);
}
k_msleep(SLEEP_TIME_MS);
}
}
return 0;
}
Comments