Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot send serial data from raspberry pi pico ( c sdk )

I'm making a remote controlled machine using a pi pico to drive the motors and read some sensors, and a raspberry pi 4 to send commands to the pi pico via serial and host the web interface.

I am currently testing the operation of the serial from the pi pico. To do this I have connected the pi pico with the raspberry in the following way:

connection diagram

Currently, I am using the following files:

1. main.c to receive and send
2. ring_queue.h where the code for the ring queue is located

main.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! %c\n", ch);
      if(ch != 10){
        uCommand[chars_rxed] = ch;
      }
      printf("Should have added it to uCommand: %s\n", uCommand);
      if(uCommand[chars_rxed] == '/'){
        printf("End of the command\n");
        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 something\n");
   char *foo = queue_dequeue((queue*)tx_queue);
   uart_write_blocking(UART_ID, (char*)foo, 32);
   //printf("%s\n", 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 command\n");
          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 '\0';
    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);
}

I'm using the usb for debbugging and when I send a simple command (via the arduino IDE) like $MOVE / I can receive it correctly but not send it back as serial, instead with the usb I can ( the printf under the uart_write_blocking). When I try to send via uart I get random characters on the arduino serial prompt and the pico also seems to receive some of the ones it sent.

like image 844
lasb3tas Avatar asked May 16 '26 14:05

lasb3tas


1 Answers

What are the random characters on the serial prompt? and what characters do you expect?

The third argument (length) of uart_write_blocking is hardcoded to 32, so this function will always try to send 32 bytes back to the raspberry pi -- that could cause some random characters to show up if the string the pico is trying to send is actually less than that. I'd try changing this code snippet to this and see if that stops the random characters.

printf("Trying to send something\n");
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
like image 64
GandhiGandhi Avatar answered May 18 '26 05:05

GandhiGandhi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!