Motor Diver issue with the nRF5340

Hi,

I have written a code for the motor driver and that is going to be flashed onto nRF5340. There are two communication buses that I am using in the code: UART and GPIO. Attachin code for the references: 

Main.c:

#include <zephyr/zephyr.h>
#include <sys/printk.h>
#include <drivers/uart.h>
#include <drivers/gpio.h>
#include <cJSON.h>

#define SLEEP_TIME_MS   1000
#define RECEIVE_BUFF_SIZE 10
#define MSG_SIZE 1024

cJSON *root;
#define RECEIVE_TIMEOUT 100

/* queue to store up to 10 messages (aligned to 16-byte boundary) */
K_MSGQ_DEFINE(uart_msgq, MSG_SIZE, 10, 16);

static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios);
static const struct gpio_dt_spec led2 = GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios);
static const struct gpio_dt_spec led3 = GPIO_DT_SPEC_GET(DT_ALIAS(led3), gpios);

const struct device *uart= DEVICE_DT_GET(DT_NODELABEL(uart0));
/**
 * @brief Start/stop motor.
 *
 * Motor would be running in the desired direction based on the provided values
 *
 *     gpio_pin_configure(spec->port, spec->pin, spec->dt_flags | extra_flags);
 *
 * @param is_Enable 
 * @return 
 */

static struct gpio_callback gpio_cb;
int motor_pos = 0;      /*Reference position of the motor*/
unsigned int input_steps = 0;
int num = 0; 						
int motor_direction = 0; /* 0 : Motor stopped, Motor Direction CW: +1, Motor Direction CCW: -1 */

static void motor_controller(bool enable, bool direction, const struct gpio_dt_spec *pin1, const struct gpio_dt_spec *pin2)
{
	if(!enable) 
	{
		gpio_pin_configure_dt(pin1, GPIO_OUTPUT_INACTIVE);
        gpio_pin_configure_dt(pin2, GPIO_OUTPUT_INACTIVE);
		motor_direction = 0;
	}
	else
	{
		motor_pos = 0;
		gpio_pin_configure_dt(pin1, GPIO_OUTPUT_INACTIVE);
        gpio_pin_configure_dt(pin2, GPIO_OUTPUT_INACTIVE);
	
        if(direction)
		{
			motor_direction = -1;
			/* Counter Clockewise direction Movement */
			gpio_pin_configure_dt(pin1, GPIO_OUTPUT_ACTIVE);
		}
		else
		{
			motor_direction = 1;
			/* Clockwise direction Movement */
			gpio_pin_configure_dt(pin2, GPIO_OUTPUT_ACTIVE);
		}
	}
}

static void motor_counter(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
	(void) dev;
	(void) cb;
	(void) pins;
    
		motor_pos++;
		
		if(motor_pos >= input_steps && motor_direction != 0)
		{
			printk("Stopping motor from the callback function\n");
			motor_controller(false, false, &led0, &led1);
		}
		printk("Rotation:%d , Motor Pos:%d\n",motor_direction, motor_pos);
}

/* receive buffer used in UART ISR callback */
static char rx_buf[MSG_SIZE];
static int rx_buf_pos;
/*
 * Read characters from UART until line end is detected. Afterwards push the
 * data to the message queue.
 */
void serial_cb(const struct device *dev, void *user_data)
{
	uint8_t c;

	if (!uart_irq_update(uart)) {
		return;
	}

	while (uart_irq_rx_ready(uart)) {

		uart_fifo_read(uart, &c, 1);

		if ((c == '\n' || c == '\r') && rx_buf_pos > 0) {
			/* terminate string */
			rx_buf[rx_buf_pos] = '\0';

			/* if queue is full, message is silently dropped */
			k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);

			/* reset the buffer (it was copied to the msgq) */
			rx_buf_pos = 0;
		} else if (rx_buf_pos < (sizeof(rx_buf) - 1)) {
			rx_buf[rx_buf_pos++] = c;
		}
		/* else: characters beyond buffer size are dropped */
	}
}

void parse_cmd()
{

}

void create_cmd()
{

}

/*
 * Print a null-terminated string character by character to the UART interface
 */
void print_uart(char *buf)
{
	int msg_len = strlen(buf);

	for (int i = 0; i < msg_len; i++) {
		uart_poll_out(uart, buf[i]);
	}
}

int main(void)
{
	int ret = 0;
	char tx_buf[MSG_SIZE];

    printk("nRF5340: Welcome to the motor controller 1\n");
/*  Verify that the UART device is ready */ 
	if (!device_is_ready(uart)){
		printk("Device is not ready");
		return 1 ;
	}
/*  Verify that the controller devices are ready */
	if (!device_is_ready(led0.port)){
		printk("GPIO device is not ready\r\n");
		return 1;
	}
	input_steps =1500;

	gpio_pin_configure_dt(&led2, GPIO_INPUT);
	gpio_pin_interrupt_configure_dt(&led2, GPIO_INT_EDGE_RISING);
	gpio_init_callback(&gpio_cb, motor_counter, BIT(led2.pin));
	gpio_add_callback(led2.port, &gpio_cb);
    
	/* configure interrupt and callback to receive data */
	uart_irq_callback_user_data_set(uart, serial_cb, NULL);
	uart_irq_rx_enable(uart);
    
	/* indefinitely wait for input from the user */
	while (k_msgq_get(&uart_msgq, &tx_buf, K_FOREVER) == 0 && num) {
		print_uart("nrf5340:\n");
		print_uart(tx_buf);
		print_uart("\r\n");
	}
	motor_controller(true, true, &led0, &led1);	
	
	while (1) {
		k_msleep(SLEEP_TIME_MS);
	}
}

proj.conf file:

CONFIG_MINIMAL_LIBC=n
CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_SCANF=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
CONFIG_CJSON_LIB=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_INTERRUPT_DRIVEN=y

No addition in the overlay file.

I am having a normal DC motor with encoder, encoder is based on the interrupt. After motor runs for x number of ticks I have to stop the motor. The value of x, receiving from another board using UART bus in cJSON format.

If I comment out the code from line number 170 to 174 in main.c file that motor is rotating otherwise not I am not able to debug the issue why it is happening?

Please let me know if some more information is required here.

Also I am not able to get the print statement output on the nRF terminal as well as putty terminal. Earlier it was working but with same code suddenly I am not able get print statement on th nRF terminal and putty application terminal also.

Please help me with this issues.

  • Hi Harsh,

    Thank you for contacting DevZone at NordicSemi.

    I will work on your case and will let you know accordingly.

    Regards,
    Naeem

  • Hi Harsh,

    Thank you for your patience.

    I started with the code, configuration and information you have provided.

    As I see you are facing two problems. One that if you comment code (line 170-174) then your motor is rotating.

    And the other one that you are not able to see output on terminal.


    Firstly, when you build your project and connect DK to the computer, your VS CODE will have the COM port numbers for the DK.

    I connected to both of the COM ports (that VS CODE was detecting) using putty with 115200 baud rate. Please see the attached Image below.

    I think your problem could be connecting to wrong port number or with different baud rate.


    I was able to see the output on both putty terminals. One terminal is printing information (through printk function) and the other one is your serial port.

    Your while loop (line 170-174) will exit once you receive data from the serial port, and then your motor controller would proceed (I guess this is expected behavior).

    Try to provide data from serial terminal (click on second putty terminal and type some data and press enter).

    I hope it works this way as you have intended (as from the comment I can see that the while loop is there to wait for user input).

    However, I do not fully understand your while loop. You can see that you have initialized num with 0, and you are ANDING with variable num in the while loop condition. I can not see the variable num used anywhere else.

    Hope it helps in any possible way. Please note the output I have shown uses a different while loop and does not call for k_msgq_get function. I was just testing the code by providing input from serial terminal.

    Regards,
    Naeem

Related