Dual com ports over single PICO USB for debugging messageport - easy !

Support for Arduino in combination with Air Manager and Air Player

Moderators: russ, Ralph

Post Reply
Message
Author
User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Dual com ports over single PICO USB for debugging messageport - easy !

#1 Post by jph »

One real pain in the %$$ with messageport (or any com port based system) is debugging at the Arduino IDE end. You can send limited debug message to AM, but that is not the best way at all.
What is needed, ideally, is another com port so you can use the serial terminal built into the IDE.
I have, in the past, used an Arduino Mega with an added FTDI Serial USB converter for a second com port - 1 to Air Manager messageport and the other to the debug terminal. - 2 com ports, 2 usb leads, 2 usb ports used etc. :( Ok,it works, but it is a pain.
It looked like this. :o
frankenmega.jpg

Using the PICO I thought there has to be a better way. It uses virtual com ports - so surely there must be a way to add more as we are hardly taxing the USB port with one little com port.

Well, long story short, it IS possible. After a bit of digging I found it is possible to add the native USB (USBSer1) as well as the standard 'Serial' that messageport uses.
From the Arduino IDE using Earle Philhowers core for rp2040, you select, from the 'tools' menu, the Adafruit tinyusb stack for USB. You will need to edit the tusb_config_rp2040.h file to assign more potential CDC class devices by changing this line in the file -

Code: Select all

#define CFG_TUD_CDC 2 // was 1 - edited by Joe for dual VCP on pico 
Then you can try the following code for the PICO - which is just a VERY basic built in led on off via messageport using just message_id and no data.

Code: Select all

// Joe Hanley (JPH) 9 2022
// test of two virtual com ports over a single usb on PICO with AM Messageport

#include <Adafruit_TinyUSB.h>
#include <si_message_port.hpp>
// Create extra USB Serial Ports.  "Serial" is already created.
Adafruit_USBD_CDC USBSer1;


SiMessagePort* messagePort;      

void setup() {                         // setup: run once
  //messagePort = new SiMessagePort(SI_MESSAGE_PORT_DEVICE_ARDUINO_UNO, SI_MESSAGE_PORT_CHANNEL_A, new_message_callback);
  messagePort = new SiMessagePort(SI_MESSAGE_PORT_DEVICE_RPI_PICO, SI_MESSAGE_PORT_CHANNEL_A, new_message_callback);
  pinMode(LED_BUILTIN, OUTPUT);
  //Serial.begin(115200);              // dont need to 'begin' here as messageport does it already
  USBSer1.begin(115200);               // start our second virtual com port
}                                      // setup end

void loop() {                          // main program loop
  messagePort->Tick(); // make sure to call frequently
}                                      //    loop end

static void new_message_callback(uint16_t message_id, struct SiMessagePortPayload* payload) {

  if (message_id == 100) {
    digitalWrite(LED_BUILTIN, HIGH);
    // send data to our debug terminal on USBSer1
    USBSer1.print("We received message_id ");
    USBSer1.println(message_id);
  }

  if (message_id == 101) {
    digitalWrite(LED_BUILTIN, LOW);
    USBSer1.print("We received message_id ");
    USBSer1.println(message_id);
  }

}
in AM use this simple code and comment / uncomment the line to set or reset the led.

Code: Select all

pico_test_led = hw_message_port_add("PICO_1", new_message_received) 


function new_message_received(pico_test_led, payload)
--  
end

if hw_connected("RPI_PICO_A") then
  print("We have the right hardware hooked up !")
end

hw_message_port_send(pico_test_led,100) -- pico built in led on
--hw_message_port_send(pico_test_led,101) -- pico built in led off
Now, on my pico, I have 2 com ports, com 4 and com 30.
the lower number is the 'serial' port for messageport so start AM and add device COM4 and you should see -
Dual CDC VCP PICO1.jpg
Pico is connected,
You can select com 30 in the arduino IDE and open the serial monitor and you can have full debug messages and outputs via USBSer1.
You use it just like any other print in Arduino - as in USBSer1.print or USBSer1.println etc.

All over a single USB cable.
Neat ! :)

left window is IDE Serial Terminal on com 30 and right is AM messageport on com 4
Dual CDC VCP PICO2.jpg
You can always use the
#ifdef DEBUG
USBSer1.print(xyz); // print some useful stuff on the serial terminal on the second virtual com port ...
#endif
and add all the debug areas through your code for debugging and control it with a single #define DEBUG - or just comment uncomment
Very useful.

2 com ports via one USB cable.!

Next we need multiple instances of messageport so we can run one instance on each core of the pico with it's own vcp and still only use 1 usb cable. ;)
That's for later though lol :)
Joe

ps - and, no, it's not limited to two com ports ! - you can have more if you wanted ! - all over the same single USB cable. You could run one device as a master to collect data from other devices and send it all over 1 nice neat single USB from a complete cockpit if you wanted to. How neat is that ? - figuratively and literally !.
Some of the STM32 dev boards have 6 hardware serial ports built in. These can be linked to other boards. Endless possibilities.
Joe. CISSP, MSc.

wendy
Posts: 46
Joined: Sun Aug 26, 2018 7:48 am
Contact:

Re: Dual com ports over single PICO USB for debugging messageport - easy !

#2 Post by wendy »

Very nice work Joe.

Debugging and testing messageport applications is really not easy because you cannot use serial monitor in Arduino when AM is running with messageport. What I did until now is use a LCD I2c pack to debug.

I will certainly try your method to see what it is all about.

thanks for sharing,
Regards, Wendy

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Dual com ports over single PICO USB for debugging messageport - easy !

#3 Post by jph »

Thanks Wendy,
One 'gothca' to watch out for is when you change USB Stack: from the tools menu from PICO SDK to Adafruit TinyUSB that the port enumeration will change as the new stack has it's own UID VID.
I found that where I originally had com 14 on the pico sdk, when running for the first time with adafruit tinyusb stack that the new ports - com 4 and com 30, were shown as well as the 'old' com 14. This is the IDE not clearing old data. Once flashed restart the IDE and the old 'now non existent' com 14 will have gone from the ide list.
It baffled me for a time :?
It was never shown in device manager as it didnt exist, as said, just the IDE not removing the old instance.
You can swap USB stacks as required.
I actually found there is a limit of 3 'virtual' ports at the moment. The main 'serial', then you can assign USBSer1 and USBSer2 as well, which is still fun :D
Very useful ! Only available on boards that support the adafruit stack though, which is fine.
I also use the STM32 Nucleo-144 boards which are utterly incredible. These do have dual com ports - physical - on them so can be used with a terminal ok, but don't support the adafruit stack. Still fine though as they come with the dual ports as standard.
Joe
Joe. CISSP, MSc.

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Dual com ports over single PICO USB for debugging messageport - easy !

#4 Post by jph »

An update to the dual virtual com ports on the PICO,
The way I did it at first was to have the normal 'Serial' assigned to the Messageport lib and and the USBSer1 assigned to the Serial Terminal for debug.
This is a a total pain as you need to constantly swap com ports as the main 'Serial' is the port that the PICO is programmed via.

To get around this (sorry @Corjan - please forgive my butchering of your lovely code - it will probably hurt your eyes to look at and don't laugh too much :( )

I made a quick edit of the si_message_port_driver.cpp file in src dir of the messageport lib so that MP uses USBSer1 with the Adafruit tinyUSB stack.

I honestly tried (FOR DAYS!!) to pass the 'Stream' Serial object (not even sure if I am using the terms correctly) but my head nearly exploded - I learnt a hell of a lot more about the MP lib and a hell of a lot about how little I understand in certain areas. :lol:
I have always had huge respect for Corjan but it went up even more than I though it could. A code guru indeed.

Anyway, you can make the following change when using the pico - remember to put it back to normal though if using not Adafruit tinyUSB supported processors.
MP will use USBSer1 and work as normal, the 2 com ports that appear will always have the highest number assigned to the USBSer1 port.
That leaves you completely free to use normal Serial for debug on the Arduino serial monitor or your IDE serial monitor and not have to change the com port over for programming.

Code: Select all

// Joe's botch of the si_message_port_driver.cpp file in messageport/src lib dir for using the USBSer1 port 
// for messageport leaving normal 'Serial' free for debug and programming
// forgive me Corjan :)

#include "si_message_port_driver.h"
#include "Arduino.h"
#include <Adafruit_TinyUSB.h> // Needed for multiple virtual com ports on Pico and supported processors (I believe ESP32/S3/ESP8266 etc supports Adafruit tiny USB also ?
Adafruit_USBD_CDC USBSer1;    // for second vcp on pico - need to declare here as passing Stream class references is WAY WAY beyond my abilities
                              // I tried it, (passing the Stream &xyz etc) .. yikes !
			      // All I can say is that Corjan is a total god to understand all that stuff. It baffles me completely :) :)

void si_message_port_driver_init() {
	//Serial.begin(115200);
	USBSer1.begin(115200);    // Joe 
}



// remember to comment out when not using pico ;) - Joe
void si_message_port_driver_sync(struct SiCircularData* input_buffer, struct SiCircularData* output_buffer) {
	uint8_t byte;
	if (si_circular_poll(output_buffer, 0, &byte) == SI_OK) {
		USBSer1.write(byte);
	}

	while ( (USBSer1.available() > 0) && (si_circular_data_free(input_buffer) > 0) ) {
		si_circular_push(input_buffer, USBSer1.read());
	}
}

/* void si_message_port_driver_sync(struct SiCircularData* input_buffer, struct SiCircularData* output_buffer) {
	uint8_t byte;
	if (si_circular_poll(output_buffer, 0, &byte) == SI_OK) {
		Serial.write(byte);
	}

	while ( (Serial.available() > 0) && (si_circular_data_free(input_buffer) > 0) ) {
		si_circular_push(input_buffer, Serial.read());
	}
} */
Also, don't forget that you need to enable the multi serial as in the first post - copied here
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
From the Arduino IDE using Earle Philhowers core for rp2040, you select, from the 'tools' menu, the Adafruit tinyusb stack for USB. You will need to edit the tusb_config_rp2040.h file to assign more potential CDC class devices by permanently changing this line in that file.

Code: Select all

#define CFG_TUD_CDC 2 // was 1 - edited by Joe for dual VCP on pico 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
It is definitely easier than swapping things over all the time in the IDE.
Joe
Joe. CISSP, MSc.

Post Reply