I have a WeAct Studio Black Pill (STM32F411CE).
I am trying to port this Arduino project to run on it: https://github.com/dbloemhard/Arduino-T ... or-ELRS3.x
Arduino only has one Serial port, so i used #defines to switch between debug data sent to Serial Monitor, and serial with the ExpressLRS transmitter module. And now I want to take advantage of there being 3 serial ports on the F411 :
1 Serial port to communicate with the ExpressLRS transmitter module (Serial1 on PB6/PB7)
1 Serial port to receive SBUS data from a head tracking device (Serial2 on PA2/PA3)
1 USB Serial so that debug data is fed to a com port that can be read by my PC (Serial? Or Serial6?)
But i am confused about the hardware serial implementation in the STMDuino core https://github.com/stm32duino/Arduino_C ... wareserial and the
And the Tools/USB Support and Tools U(S)ART Support options in the IDE.
Is it possible to use all 3 UARTs, and feed one of them through the USB port? If so, how would this be implemented?
Using two serial ports + USB Serial on WeAct BlackPill (STM32F411CE)
Using two serial ports + USB Serial on WeAct BlackPill (STM32F411CE)
welcome,
for usb-serial, choose Tools > USB support > CDC Generic 'Serial' supercede U(S)ART
You still have those Serial1, Serial2, Serial3 for your UART
https://github.com/stm32duino/Arduino_C ... wareserial
To bridge data between USB and UART , codes usually looks like
hope it helps
this would 'mix up' the traffic, i.e. 2 uart into/out of 1 usb (virtual) com port, you could optionally comment / remove one block of codes, e.g. that from / to one of the SerialN.
Or you could improve the codes, make your own scheme / protocol etc, to tell one from another.
e.g.
https://www.modbustools.com/modbus.html
this would take programming on the firmware (stm32) and the client s/w
Go to full postfor usb-serial, choose Tools > USB support > CDC Generic 'Serial' supercede U(S)ART
You still have those Serial1, Serial2, Serial3 for your UART
https://github.com/stm32duino/Arduino_C ... wareserial
To bridge data between USB and UART , codes usually looks like
Code: Select all
void setup() {
Serial.begin(); // USB
Serial1.begin(115200);
Serial2.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
// copy usb to uart
if (Serial.available()) {
while(Serial.available()) {
int c = Serial.read();
Serial1.write(c);
Serial2.write(c);
// blink the led for traffic optional
digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN));
}
}
// copy serial1 to usb
if (Serial1.available()) {
while(Serial1.available()) {
int c = Serial1.read();
Serial.write(c);
// blink the led for traffic optional
digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN));
}
}
// copy serial2 to usb
if (Serial2.available()) {
while(Serial2.available()) {
int c = Serial2.read();
Serial.write(c);
// blink the led for traffic optional
digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN));
}
}
// turn off led, check the schematics, this assume led is active low, i.e. the led sink VDD 3.3 into the pin e.g. PC13)
digitalWrite(LED_BUILTIN, HIGH);
}
this would 'mix up' the traffic, i.e. 2 uart into/out of 1 usb (virtual) com port, you could optionally comment / remove one block of codes, e.g. that from / to one of the SerialN.
Or you could improve the codes, make your own scheme / protocol etc, to tell one from another.
e.g.
https://www.modbustools.com/modbus.html
this would take programming on the firmware (stm32) and the client s/w
Re: Using two serial ports + USB Serial on WeAct BlackPill (STM32F411CE)
welcome,
for usb-serial, choose Tools > USB support > CDC Generic 'Serial' supercede U(S)ART
You still have those Serial1, Serial2, Serial3 for your UART
https://github.com/stm32duino/Arduino_C ... wareserial
To bridge data between USB and UART , codes usually looks like
hope it helps
this would 'mix up' the traffic, i.e. 2 uart into/out of 1 usb (virtual) com port, you could optionally comment / remove one block of codes, e.g. that from / to one of the SerialN.
Or you could improve the codes, make your own scheme / protocol etc, to tell one from another.
e.g.
https://www.modbustools.com/modbus.html
this would take programming on the firmware (stm32) and the client s/w
for usb-serial, choose Tools > USB support > CDC Generic 'Serial' supercede U(S)ART
You still have those Serial1, Serial2, Serial3 for your UART
https://github.com/stm32duino/Arduino_C ... wareserial
To bridge data between USB and UART , codes usually looks like
Code: Select all
void setup() {
Serial.begin(); // USB
Serial1.begin(115200);
Serial2.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
// copy usb to uart
if (Serial.available()) {
while(Serial.available()) {
int c = Serial.read();
Serial1.write(c);
Serial2.write(c);
// blink the led for traffic optional
digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN));
}
}
// copy serial1 to usb
if (Serial1.available()) {
while(Serial1.available()) {
int c = Serial1.read();
Serial.write(c);
// blink the led for traffic optional
digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN));
}
}
// copy serial2 to usb
if (Serial2.available()) {
while(Serial2.available()) {
int c = Serial2.read();
Serial.write(c);
// blink the led for traffic optional
digitalWrite(LED_BUILTIN, ! digitalRead(LED_BUILTIN));
}
}
// turn off led, check the schematics, this assume led is active low, i.e. the led sink VDD 3.3 into the pin e.g. PC13)
digitalWrite(LED_BUILTIN, HIGH);
}
this would 'mix up' the traffic, i.e. 2 uart into/out of 1 usb (virtual) com port, you could optionally comment / remove one block of codes, e.g. that from / to one of the SerialN.
Or you could improve the codes, make your own scheme / protocol etc, to tell one from another.
e.g.
https://www.modbustools.com/modbus.html
this would take programming on the firmware (stm32) and the client s/w
Re: Using two serial ports + USB Serial on WeAct BlackPill (STM32F411CE)
Hi! And thanks for the explanation. So I can think of it like this: The "Serial" is the one that goes to USB (virtual), and Serial1/Serial2 are the com ports going to the actual STM UARTs.
Just trying this now, but i am getting a compile error.
If i comment out the Serial1 define
then it compiles, but not actually sure if this works for all three ports, nor why i am commenting out one of the serial ports to get it to compile.
Just trying this now, but i am getting a compile error.
Code: Select all
C:/Users/tokyodom/AppData/Local/Arduino15/packages/STMicroelectronics/tools/xpack-arm-none-eabi-gcc/14.2.1-1.1/bin/../lib/gcc/arm-none-eabi/14.2.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\tokyodom\AppData\Local\arduino\cores\25798f7135ec24e7978629365a7a97a3\core.a(HardwareSerial.cpp.o):(.bss.Serial1+0x0): multiple definition of `Serial1'; C:\Users\tokyodom\AppData\Local\arduino\sketches\D25F0A21588097169B4513AC9DAF3C8D\sketch\STMpleTX.ino.cpp.o:(.bss.Serial1+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1
Compilation error: exit status 1Code: Select all
//HardwareSerial Serial1(PB7, PB6);
HardwareSerial Serial2(PA3, PA2);
void setup() {
...
Serial.begin(115200);
Serial1.begin(SERIAL_BAUDRATE, SERIAL_8N1);
Serial2.begin(100000); // SBUS Input
}Re: Using two serial ports + USB Serial on WeAct BlackPill (STM32F411CE)
Unfortunately i cannot make my own scheme for this since the devices i am interfacing with are fixed in their function.
Actually the ELRS module on Serial1 is already using the modbus protocol (called CRSF after the company that originated it). It would support having multiple devices on the same port, each with their own address. So, i could potentially make a client on the PC to read messages on that port, but i do like the convenience of using serial port monitor
Actually the ELRS module on Serial1 is already using the modbus protocol (called CRSF after the company that originated it). It would support having multiple devices on the same port, each with their own address. So, i could potentially make a client on the PC to read messages on that port, but i do like the convenience of using serial port monitor
Re: Using two serial ports + USB Serial on WeAct BlackPill (STM32F411CE)
the defines are mostly in the variant files
https://github.com/stm32duino/Arduino_C ... L_F411CE.h
https://github.com/stm32duino/Arduino_C ... F411CE.cpp
https://github.com/stm32duino/Arduino_C ... L_F411CE.c
the various HardwareSerial are defined here:
https://github.com/stm32duino/Arduino_C ... ial.h#L200
hence, some of the definitions e.g. Serial, Serial1 are 'default' if the variant defines them.
you could test Serial2, Serial3 though, if using Serial2, Serial3 errors when you don't define them in your sketch, then most likely you need to define/configure it in the sketch.
it is quite possible to 'convert' that by programming your sketch, e.g. if you use the same protocol (modbus?) and kind of connect the same pheripheral to the same port, then when funneling that to the usb port, you could add the headers. But it'd still take some programming on the client / app side to work with that.
messing with usb (driver) is feasible, but normally is 'beyond beginners' and you can kind of make it appear like 3 'virtual com' ports if you bother to go the distance. That is normally not 'basic' arduino style programming, i.e. rework the usb device driver e.g. Serial().
--
note, there are also stuff like such
https://wiki.archlinux.org/title/USB/IP
https://usbip.sourceforge.net/
https://github.com/jtornosm/USBIP-Virtual-USB-Device
https://github.com/lcgamboa/USBIP-Virtual-USB-Device
https://github.com/cezanne/usbip-win
https://github.com/vadimgrn/usbip-win2
but I've not played with it, that'd still (likely) require programming on the client/host side and if it works in e.g. windows / linux etc.
https://github.com/stm32duino/Arduino_C ... L_F411CE.h
https://github.com/stm32duino/Arduino_C ... F411CE.cpp
https://github.com/stm32duino/Arduino_C ... L_F411CE.c
the various HardwareSerial are defined here:
https://github.com/stm32duino/Arduino_C ... ial.h#L200
hence, some of the definitions e.g. Serial, Serial1 are 'default' if the variant defines them.
you could test Serial2, Serial3 though, if using Serial2, Serial3 errors when you don't define them in your sketch, then most likely you need to define/configure it in the sketch.
it is quite possible to 'convert' that by programming your sketch, e.g. if you use the same protocol (modbus?) and kind of connect the same pheripheral to the same port, then when funneling that to the usb port, you could add the headers. But it'd still take some programming on the client / app side to work with that.
messing with usb (driver) is feasible, but normally is 'beyond beginners' and you can kind of make it appear like 3 'virtual com' ports if you bother to go the distance. That is normally not 'basic' arduino style programming, i.e. rework the usb device driver e.g. Serial().
--
note, there are also stuff like such
https://wiki.archlinux.org/title/USB/IP
https://usbip.sourceforge.net/
https://github.com/jtornosm/USBIP-Virtual-USB-Device
https://github.com/lcgamboa/USBIP-Virtual-USB-Device
https://github.com/cezanne/usbip-win
https://github.com/vadimgrn/usbip-win2
but I've not played with it, that'd still (likely) require programming on the client/host side and if it works in e.g. windows / linux etc.
Re: Using two serial ports + USB Serial on WeAct BlackPill (STM32F411CE)
To close the loop here, i have it working now. The only odd thing is that Serial1 is already defined, which means i cannot define it myself (or it will result in a compile error). I did want to do my own definition to keep the code looking clean, but the following code works and outputs to the respective pins, as well as the usb serial port
USB Support is set to CDC (generic 'Serial' supersede U(S)ART)
U(S)ART Support is set to Enabled (generic 'Serial')
Code: Select all
#include <Arduino.h>
//HardwareSerial Serial1(PB7, PB6);
HardwareSerial Serial2(PA3, PA2);
uint32_t lastMicros = micros();
void setup() {
Serial.begin(9600);
Serial1.setRx(PB7);
Serial1.setTx(PB6);
Serial1.begin(9600);
Serial2.setRx(PA3);
Serial2.setTx(PA2);
Serial2.begin(9600);
}
void loop() {
if (lastMicros - micros() > 1000) {
Serial.print("Serial current Micros: ");
Serial.println(micros());
Serial1.print("Serial1 current Micros: ");
Serial1.println(micros());
Serial2.print("Serial2 current Micros: ");
Serial2.println(micros());
lastMicros = micros();
}
}U(S)ART Support is set to Enabled (generic 'Serial')