Hello everyone,
I am evaluating wether this Thingy:91x can communicate with an autopilot (CubePilot CubeOrange) or not.
What am I doing right now?
For those who might not know about autopilots, my autopilot CubeOrange has an interface called TELEM1 through which it can receive and send serialized MAVLink messages (this is the protocol that this autopilot's firmware uses for communication). I have already configured this, and set the baudrate to 57600 (among other parameters).
I could see in this graph below that the pins 15 and 16 from the section P9 of Thingy:91x correspond to P0.08 and P0.09 (which are the GPIO pins I am assigning to UART3 Tx and Rx from an overlay (will show later). However, since I lack of some materials and resources, I could not connect the autopilot TELEM1 to these pins 15 and 16, and I connected it to the pins 24 and 25 of the section P5 (I measured with the multimeter and realized it is equivalent, if not please tell me :)).
I wrote an overlay thingy91x_nrf9160.overlay that, among other things, configures the pins 8 and 9 to use UART (UART3 concretly).
/* Pin configuration for UART3 */
&pinctrl {
uart3_default: uart3_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 8)>, <NRF_PSEL(UART_RX, 0, 9)>;
};
};
uart3_sleep: uart3_sleep {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 8)>, <NRF_PSEL(UART_RX, 0, 9)>;
};
};
i2c2_default: i2c2_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 10)>,
<NRF_PSEL(TWIM_SCL, 0, 11)>;
};
};
i2c2_sleep: i2c2_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 10)>,
<NRF_PSEL(TWIM_SCL, 0, 11)>;
low-power-enable;
};
};
};
/* UART3 configuration for AP communication*/
&uart3 {
status = "okay";
current-speed = <57600>;
pinctrl-0 = <&uart3_default>;
pinctrl-1 = <&uart3_sleep>;
pinctrl-names = "default", "sleep";
};
/* UART1 configuration for modem communication */
&uart1 {
status = "okay";
current-speed = < 1000000 >;
hw-flow-control;
};
/* Specify UART1 for modem trace output */
/ {
chosen {
nordic,modem-trace-uart = &uart1;
};
};
/* Disable SPI3 to free up pins for UART3 */
&spi3 {
status = "disabled";
};
&i2c2 {
status = "okay";
pinctrl-0 = <&i2c2_default>;
pinctrl-1 = <&i2c2_sleep>;
pinctrl-names = "default", "sleep";
};
As you can see, I have also set the current-speed for those pins 8 and 9 to 57600, to match the autopilot's TELEM1 port.
This is the pjr.conf I am using in the project:
CONFIG_GPIO=y
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
# Enable UART console output
CONFIG_UART_CONSOLE=y
# Enable printk
CONFIG_PRINTK=y
# Configure logging
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
# Disabling SPI3
CONFIG_SPI_NOR=n
CONFIG_FLASH=n
CONFIG_NET_BUF=y
and this is my main.c code:
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net_buf.h>
#include <zephyr/zbus/zbus.h>
#define DEFAULT_THREAD_STACK_SIZE 2048
#define RX_BUF_LEN 280 /* MAVLink 2.0 max packet size */
#define RECEIVE_TIMEOUT 100
/* Register as a module so Zephyr's logging system is enabled */
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);
/* UART device label defined in overlay file */
#define UART_DEVICE_NODE DEVICE_DT_GET(DT_NODELABEL(uart3))
static const struct device *uart_dev;
/* Double buffers for async RX */
static uint8_t async_rx_buffer[RX_BUF_LEN];
static void uart_callback(const struct device *dev, struct uart_event *evt,
void *user_data) {
LOG_DBG("EVENT: %d", evt->type);
switch (evt->type) {
case UART_TX_DONE:
LOG_INF("UART_TX_DONE");
break;
case UART_RX_BUF_REQUEST:
LOG_INF("UART_RX_BUF_REQUEST");
/* Supply next buffer for RX */
uart_rx_buf_rsp(dev, async_rx_buffer, RX_BUF_LEN);
break;
case UART_RX_BUF_RELEASED:
LOG_DBG("RX buffer released");
break;
case UART_RX_DISABLED:
LOG_ERR("RX disabled, re-enabling");
/* Re-enable RX with fresh buffer */
uart_rx_enable(dev, async_rx_buffer, RX_BUF_LEN, RECEIVE_TIMEOUT);
break;
case UART_RX_RDY:
LOG_INF("UART_RX_RDY");
/* Data ready in previously submitted buffer */
LOG_INF("Received %zu bytes:", evt->data.rx.len);
for (size_t i = 0; i < evt->data.rx.len; i++) {
uint8_t byte = evt->data.rx.buf[evt->data.rx.offset + i];
LOG_INF("Byte[%zu] = 0x%02X", i, byte);
}
break;
default:
LOG_WRN("Unhandled UART event %d", evt->type);
}
}
int main(void) {
int err;
uart_dev = UART_DEVICE_NODE;
if (!device_is_ready(uart_dev)) {
LOG_ERR("UART device is not ready");
return -1;
}
/* Register async callback */
uart_callback_set(uart_dev, uart_callback, NULL);
/* Start RX with initial buffer */
err = uart_rx_enable(uart_dev, async_rx_buffer, RX_BUF_LEN, RECEIVE_TIMEOUT);
if (err) {
LOG_ERR("Failed to enable RX (%d)", err);
return -1;
}
LOG_INF("UART RX enabled");
/* Main loop just sleeps; UART events drive I/O */
while (1) {
k_msleep(10);
}
return 0;
}
Where I intend to print the bytes that the autopilot should be sending.
I do not know what I might be doing wrong, but I am not able to receive any data from the autopilot.
Any help will be really welcome, thanks!![]()