nRF52 Zephyr VSCode DeviceTree

Hello everyone. I've started coding with Zephyr on my nRF52 device. I'm relatively new to this. I'm trying to drive a DC motor with L298N. However, I have no idea how to configure the pin settings in the device tree. I have defined the motor pins in the device tree, but when I try to use them in main.c, I get an error saying they are not defined. Can someone help me understand how to use the device tree? Thank you.

  • I am using the nRF52832 microcontroller and the SDK version 2.3.0.

  • Ok, I found a few extra issues.

    Try this overlay instead:

    / {
        aliases {
            motor-pwm = &motor_pwm0;
            motor-en = &motor_en;
            motor-in1 = &motor_in1;
            motor-in2 = &motor_in2;
        };
        
        motor_pwm {
            compatible = "pwm-leds";
            motor_pwm0: motor_pwm0 {
        		pwms = <&pwm0 0 PWM_MSEC(10) 0>;
        		status = "okay";
        	};
        };
    	
    	motor_gpios {
    	    compatible = "gpio-keys";
        	motor_en: motor_en {
        		gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
        		
        	};
        	
        	motor_in1: motor_in1 {
        		gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
        		
        	};
        	
        	motor_in2: motor_in2 {
        		gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
        	
        	};
        };
    };
    
    &pwm_led0 {
    	status = "disabled";
    };

    It also seems that you are using some outdated functions in your code. Read this section of the version 2.x.x migration guide:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.3.0/nrf/migration/migration_guide_1.x_to_2.x.html#changes-in-pwm-api

    You may also want to take a look at the samples at:

    zephyr/samples/basic/blinky_pwm
    zephyr/samples/basic/button

    to see examples of code for pwm-leds and gpio-keys.

  • Thank you. I made some changes to the code.But now I'm getting a different error. What could be the cause of this error?

    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/pwm.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/devicetree/gpio.h>
    #include <zephyr/devicetree/pwms.h>
    
    #define PWM_PERIOD_USEC 2000
    
    #define ENA_PIN DEVICE_DT_GET(motor_en)
    #define IN1_PIN DEVICE_DT_GET(motor_in1)
    #define IN2_PIN DEVICE_DT_GET(motor_in2)
    
    #define PWM_DEV PWM_DT_SPEC_GET(motor_pwm0)
    #define PWM_CHANNEL DEVICE_DT_GET(motor_pwm0)
    
    #define MOTOR_SPEED_MIN -100
    #define MOTOR_SPEED_MAX 100
    
    void main(void)
    {
        struct device *pwm_dev , *ena_dev, *in1_dev, *in2_dev;
        int motor_speed = 0;
    
        pwm_dev = device_get_binding DEVICE_DT_GET(motor_pwm0);
        if (!pwm_dev) {
            printk("Failed to open PWM device\n");
            return;
        }
    
    
        ena_dev = device_get_binding DEVICE_DT_GET	(motor_en);
        in1_dev = device_get_binding DEVICE_DT_GET	(motor_in1);
        in2_dev = device_get_binding DEVICE_DT_GET	(motor_in2);
        if (!ena_dev || !in1_dev || !in2_dev) {
            printk("Failed to open GPIO devices\n");
            return;
        }
    
        
        if (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL, PWM_PERIOD_USEC, 0) < 0) {
            printk("Failed to configure PWM period\n");
            return;
        }
    
        if (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL, PWM_PERIOD_USEC, 0) < 0) {
            printk("Failed to configure PWM duty cycle\n");
            return;
        }
    
        if (gpio_pin_configure(ena_dev, ENA_PIN, GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT) < 0) {
            printk("Failed to configure ENA pin\n");
            return;
        }
        if (gpio_pin_configure(in1_dev, IN1_PIN, GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT) < 0) {
            printk("Failed to configure IN1 pin\n");
            return;
        }
        if (gpio_pin_configure(in2_dev, IN2_PIN, GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT) < 0) {
            printk("Failed to configure IN2 pin\n");
            return;
        }
    
        while (1) {
    
            motor_speed = clamp(motor_speed, MOTOR_SPEED_MIN, MOTOR_SPEED_MAX);
    
            uint32_t pwm_duty = map(motor_speed, MOTOR_SPEED_MIN, MOTOR_SPEED_MAX, 0, PWM_PERIOD_USEC);
            if (pwm_pin_set_usec(pwm_dev, PWM_CHANNEL, PWM_PERIOD_USEC, pwm_duty) < 0) {
                printk("Failed to set PWM duty cycle\n");
                return;
            }
    
            if (motor_speed > 0) {
                gpio_pin_set(ena_dev, ENA_PIN, 1);
                gpio_pin_set(in1_dev, IN1_PIN, 1);
                gpio_pin_set(in2_dev, IN2_PIN, 0);
            } else if (motor_speed < 0) {
                gpio_pin_set(ena_dev, ENA_PIN, 1);
                gpio_pin_set(in1_dev, IN1_PIN, 0);
                gpio_pin_set(in2_dev, IN2_PIN, 1);
            } else {
                gpio_pin_set(ena_dev, ENA_PIN, 0);
                gpio_pin_set(in1_dev, IN1_PIN, 0);
                gpio_pin_set(in2_dev, IN2_PIN, 0);
            }
    
            k_sleep(K_MSEC(100));
        }
    }

  • Try this:

    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/pwm.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/devicetree/gpio.h>
    #include <zephyr/devicetree/pwms.h>
    
    #define PWM_PERIOD_USEC 2000
    
    static const struct gpio_dt_spec ena_dev = GPIO_DT_SPEC_GET_OR(DT_ALIAS(motor_en), gpios, {0});
    static const struct gpio_dt_spec in1_dev = GPIO_DT_SPEC_GET_OR(DT_ALIAS(motor_in1), gpios, {0});
    static const struct gpio_dt_spec in2_dev = GPIO_DT_SPEC_GET_OR(DT_ALIAS(motor_in2), gpios, {0});
    
    static const struct pwm_dt_spec pwm_dev = PWM_DT_SPEC_GET(DT_ALIAS(motor_pwm0));
    
    //#define ENA_PIN DEVICE_DT_GET(motor_en)
    //#define IN1_PIN DEVICE_DT_GET(motor_in1)
    //#define IN2_PIN DEVICE_DT_GET(motor_in2)
    
    //#define PWM_DEV PWM_DT_SPEC_GET(motor_pwm0)
    //#define PWM_CHANNEL DEVICE_DT_GET(motor_pwm0)
    
    #define MOTOR_SPEED_MIN -100
    #define MOTOR_SPEED_MAX 100
    
    void main(void)
    {
        //struct device *pwm_dev , *ena_dev, *in1_dev, *in2_dev;
        int motor_speed = 0;
    
    	if (!device_is_ready(pwm_dev.dev)) {
    		printk("Error: PWM device %s is not ready\n",
    		       pwm_dev.dev->name);
    		return;
    	}
    
    	if (!device_is_ready(ena_dev.port) || !device_is_ready(in1_dev.port) 
    		|| !device_is_ready(in2_dev.port)) {
    		printk("Error: gpio device %s is not ready\n",
    		       ena_dev.port->name);
    		return;
    	}
    
        //pwm_dev = device_get_binding DEVICE_DT_GET(motor_pwm0);
        //if (!pwm_dev) {
        //    printk("Failed to open PWM device\n");
        //    return;
        //}
    
    
        //ena_dev = device_get_binding DEVICE_DT_GET	(motor_en);
        //in1_dev = device_get_binding DEVICE_DT_GET	(motor_in1);
        //in2_dev = device_get_binding DEVICE_DT_GET	(motor_in2);
        //if (!ena_dev || !in1_dev || !in2_dev) {
        //    printk("Failed to open GPIO devices\n");
        //    return;
        //}
    
        
        if (pwm_set_dt(&pwm_dev, PWM_PERIOD_USEC, 0) < 0) {
            printk("Failed to configure PWM period\n");
            return;
        }
    
        if (gpio_pin_configure_dt(&ena_dev, (GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT)) < 0) {
            printk("Failed to configure ENA pin\n");
            return;
        }
        if (gpio_pin_configure_dt(&in1_dev, (GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT)) < 0) {
            printk("Failed to configure IN1 pin\n");
            return;
        }
        if (gpio_pin_configure_dt(&in2_dev, (GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT)) < 0) {
            printk("Failed to configure IN2 pin\n");
            return;
        }
    
        while (1) {
    
            motor_speed = clamp(motor_speed, MOTOR_SPEED_MIN, MOTOR_SPEED_MAX);
    
            uint32_t pwm_duty = map(motor_speed, MOTOR_SPEED_MIN, MOTOR_SPEED_MAX, 0, PWM_PERIOD_USEC);
            if (pwm_set_dt(&pwm_dev, PWM_PERIOD_USEC, pwm_duty) < 0) {
                printk("Failed to set PWM duty cycle\n");
                return;
            }
    
            if (motor_speed > 0) {
                gpio_pin_set_dt(ena_dev, 1);
                gpio_pin_set_dt(in1_dev, 1);
                gpio_pin_set_dt(in2_dev, 0);
            } else if (motor_speed < 0) {
                gpio_pin_set_dt(ena_dev, 1);
                gpio_pin_set_dt(in1_dev, 0);
                gpio_pin_set_dt(in2_dev, 1);
            } else {
                gpio_pin_set_dt(ena_dev, 0);
                gpio_pin_set_dt(in1_dev, 0);
                gpio_pin_set_dt(in2_dev, 0);
            }
    
            k_sleep(K_MSEC(100));
        }
    }

    You can remove the commented out code and rename things as you see fit.

  • I changed the code and now the motors are working. Thanks for your help.


    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/pwm.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/devicetree/gpio.h>
    #include <zephyr/devicetree/pwms.h>
    #include <zephyr/drivers/led.h>
    
    
    
    static const struct pwm_dt_spec pwm_led0 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0));
    static const struct gpio_dt_spec in1_dev = GPIO_DT_SPEC_GET_OR(DT_ALIAS(motor1), gpios, {0});
    static const struct gpio_dt_spec in2_dev = GPIO_DT_SPEC_GET_OR(DT_ALIAS(motor2), gpios, {0});
    static const struct gpio_dt_spec ena_dev = GPIO_DT_SPEC_GET_OR(DT_ALIAS(motor0), gpios, {0});
    
    
    #define MIN_PERIOD PWM_SEC(1U) / 128U
    #define MAX_PERIOD PWM_SEC(1U)
    
    void main(void)
    {
    	uint32_t max_period;
    	uint32_t period;
    	uint8_t dir = 0U;
    	int ret;
    	int ret1;
    
      
    
    	printk("PWM-based blinky\n");
    
    
    	if (gpio_pin_configure_dt(&ena_dev, (GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT)) < 0) {
            printk("Failed to configure ENA pin\n");
            return;
        }
        if (gpio_pin_configure_dt(&in1_dev, (GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT)) < 0) {
            printk("Failed to configure IN1 pin\n");
            return;
        }
        if (gpio_pin_configure_dt(&in2_dev, (GPIO_OUTPUT_ACTIVE | GPIO_OUTPUT)) < 0) {
            printk("Failed to configure IN2 pin\n");
            return;
        }
    
    	if (!device_is_ready(pwm_led0.dev)) {
    		printk("Error: PWM device %s is not ready\n",
    		       pwm_led0.dev->name);
    		return;
    	}
    
    	gpio_pin_set_dt(&ena_dev, 1);
        gpio_pin_set_dt(&in1_dev, 1);
        gpio_pin_set_dt(&in2_dev, 0);
    	pwm_set_dt(&pwm_led0, MIN_PERIOD, MIN_PERIOD / 2U);
    	
    
    }	

Related