#c #c #embedded #microcontroller #raspberry-pi-pico
Вопрос:
Я создаю машину с дистанционным управлением, использующую pi pico для управления двигателями и считывания некоторых датчиков, и raspberry pi 4 для отправки команд на pico pi по последовательному каналу и размещения веб-интерфейса.
В настоящее время я тестирую работу серийного устройства от pi pico. Для этого я соединил pi pico с малиной следующим образом:
В настоящее время я использую следующие файлы:
1. main.c to receive and send
2. ring_queue.h where the code for the ring queue is located
главная.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"
#include "ring_queue.h"
#define UART_ID uart0
#define BAUD_RATE 115200
#define DATA_BITS 8
#define STOP_BITS 1
#define PARITY UART_PARITY_NONE
#define UART_TX_PIN 0
#define UART_RX_PIN 1
#define LED_PIN PICO_DEFAULT_LED_PIN
volatile int chars_rxed = 0;
volatile char uCommand[32];
volatile queue *rx_queue;
volatile queue *tx_queue;
void receive_rx(){
while(uart_is_readable(UART_ID)){
char ch = uart_getc(UART_ID);
printf("Got a ch! %cn", ch);
if(ch != 10){
uCommand[chars_rxed] = ch;
}
printf("Should have added it to uCommand: %sn", uCommand);
if(uCommand[chars_rxed] == '/'){
printf("End of the commandn");
queue_enqueue((queue*)rx_queue, (char*)uCommand);
memset((char*)uCommand, 0, sizeof(uCommand));
chars_rxed = 0;
break;
}
if(ch != 10) chars_rxed ;
}
}
void send_tx(){
if(queue_empty((queue*)tx_queue) == 1){
return;
}
else{
printf("Trying to send somethingn");
char *foo = queue_dequeue((queue*)tx_queue);
uart_write_blocking(UART_ID, (char*)foo, 32);
//printf("%sn", queue_dequeue((queue*)tx_queue));
}
}
int main(){
stdio_init_all();
memset((char*)uCommand, 0, sizeof(uCommand));
rx_queue = create_queue(32);
tx_queue = create_queue(32);
uart_init(UART_ID, BAUD_RATE);
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
uart_set_hw_flow(UART_ID, false, false);
uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY);
uart_set_fifo_enabled(UART_ID, true);
int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ;
irq_set_exclusive_handler(UART_IRQ, receive_rx);
irq_set_enabled(UART_IRQ, true);
uart_set_irq_enables(UART_ID, true, false);
while (1){
tight_loop_contents();
if(queue_size((queue*)rx_queue) != 0){
printf("Moving from rx to tx to print the received commandn");
queue_enqueue((queue*)tx_queue, queue_dequeue((queue*)rx_queue));
}
send_tx();
}
}
ring_queue.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
unsigned int tail; // current tail
unsigned int head; // current head
unsigned int size; // current number of items
unsigned int capacity; // Capacity of queue
char** data; // Pointer to array of data
} queue;
queue *create_queue(unsigned int _capacity){
printf("Malloc!n");
queue *myQueue = malloc(sizeof(queue));
printf("Malloc done!n");
if (myQueue == NULL ){
printf("Malloc failed!n");
return NULL;
}
else {
printf("Malloc succeed!n");
myQueue->tail = -1;
myQueue->head = 0;
myQueue->size = 0;
myQueue->capacity = _capacity;
myQueue->data = malloc(_capacity * sizeof(char*));
return myQueue;
}
}
int queue_empty(queue *q) {
if(q == NULL) return -1;
else if(q->size == 0) return 1;
else return 0;
}
int queue_full(queue *q) {
if(q == NULL) return -1;
else if(q->size == q->capacity) return 1;
else return 0;
}
int queue_enqueue(queue *q, const char *item) {
if (q == NULL) return -1;
else if (queue_full(q) == 1) return 0;
else {
q->tail = (q->tail 1) % q->capacity;
q->data[q->tail] = strdup(item);
q->size ;
return 1;
}
}
char *queue_dequeue(queue *q) {
if(q == NULL) return NULL;
else if(queue_empty(q) == 1) return '';
else {
char *item = q->data[q->head];
q->head = (q->head 1) % q->capacity;
q->size--;
return item;
}
}
unsigned int queue_size(queue *q) {
if (q == NULL) return - 1;
else return q->size;
}
void free_queue(queue *q) {
for(int i = 0; i < q->capacity; i ) free(q->data[i]);
free(q->data);
free(q);
}
Я использую usb для отключения, и когда я отправляю простую команду (через IDE arduino), такую как $MOVE/, я могу правильно ее получить, но не отправлять обратно как последовательную, вместо этого с помощью usb я могу ( printf под uart_write_blocking).
Когда я пытаюсь отправить через uart, я получаю случайные символы в приглашении на серийный номер arduino, и pico также, похоже, получает некоторые из отправленных.
Комментарии:
1. Кроме того, мы обычно не используем динамическое управление памятью во встроенных системах, но это является причиной нескольких утечек памяти и ошибок здесь.
strdup()
—> вы никогда не освобождаетесь после >dequeue()
здесь, кроме освобождения всей реализации очереди. возврат из очереди »'
вместоchar*
» а». Отправка 32 байтов вместо длины строки, взятой из очереди, или выполняетсяuart_write_blocking()
проверка''
?
Ответ №1:
Каковы случайные символы в приглашении на серийный номер? и каких персонажей вы ожидаете увидеть?
Третий аргумент (длина) uart_write_blocking
жестко закодирован до 32, поэтому эта функция всегда будет пытаться отправить 32 байта обратно в raspberry pi-это может привести к появлению некоторых случайных символов, если строка, которую пытается отправить pico, на самом деле меньше этой. Я бы попробовал изменить этот фрагмент кода на этот и посмотреть, остановит ли это случайные символы.
printf("Trying to send somethingn");
char *foo = queue_dequeue((queue*)tx_queue);
uart_write_blocking(UART_ID, (char*)foo, strlen(foo)); // only send as many bytes as are in the string