Hallo zusammen,
für ein Hobbyprojekt versuche ich seit einigen Tagen, eine
ESP32S3-DevkitC-1 Plattine über ihre Native-USB mit einem Navspark
NS-RAW GPS Empfänger zu verbinden.
ESP32S3:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1-v1.0.html
NS-RAW:
https://navspark.mybigcommerce.com/ns-raw-carrier-phase-raw-measurement-output-gps-receiver/
Mit dem uC der GPS-Platine kann man theoretisch über einen seriellen
Port kommunizieren, leider ist nur TX und nicht RX über die Pins de
Platine erreichbar. Will man dem GPS (z.B. Konfigurations-) Befehle
schicken, muss man dies über den micro-USB Stecker und einen PL2303 der
Platine tun.
Die GPS-Platine kann man per USB mit einem PC verbinden und mit einer SW
des Herstellers steuern. Alles, was mir der Hersteller sagen konnte,
ist, dass ich mit einem ESP32 die Funktion des PCs nachbilden musste, um
ihre GPS-Platine mit dem ESP32 bedienen zu können.
Soweit ich zu verstehen glaube, muss man dafür mit den ESP32 über seinen
nativen USB als Host arbeiten lassen, womit ich bisher noch keine
Erfahrung gemacht hatte.
Für Testzwecken habe ich (unten anderen) den Setup im Bild benutzt. OTG
Kabel zwischen dem USB des ESP32 und dem der GPS-Platine. Dazu 5v und
GND (graues und gelbes Kabel, die Platine akzeptiert 3,6-10v) und eine
serielle Verbindung mit TX des GPS (der RX, wie gesagt, ist nicht über
die Pins zu erreichen.) Dieses Signal kann ich alternativ mit einem
Oszilloskop überprüfen.
Die ESP32 verbinde ich über den UART Port mit einem PC. Ich weiß nicht,
ob diese Darstellung alles besser schildert oder das Ganze noch
komplizierter macht :)
[PC] <- Kabel -> [(CP2102)<->(ESP32S3 native USB)] <- Kabel ->
[(PL2303) <-> (GPS-uC)]
Im ESP32 lasse ich dieses Program laufen (mit der Arduino IDE
kompiliert, mit der Konfiguration die auf dem dritten Bild im Anhang zu
sehen ist):
1 | #if ARDUINO_USB_MODE
|
2 | #warning This sketch should be used when USB is in OTG mode
|
3 | void setup(){}
|
4 | void loop(){}
|
5 | #else
|
6 | #include "USB.h"
|
7 |
|
8 | #if ARDUINO_USB_CDC_ON_BOOT
|
9 | #define HWSerial Serial0
|
10 | #define USBSerial Serial
|
11 | #else
|
12 | #define HWSerial Serial
|
13 | USBCDC USBSerial;
|
14 | #endif
|
15 |
|
16 | static void usbEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
|
17 | if(event_base == ARDUINO_USB_EVENTS){
|
18 | arduino_usb_event_data_t * data = (arduino_usb_event_data_t*)event_data;
|
19 | switch (event_id){
|
20 | case ARDUINO_USB_STARTED_EVENT:
|
21 | HWSerial.println("USB PLUGGED");
|
22 | break;
|
23 | case ARDUINO_USB_STOPPED_EVENT:
|
24 | HWSerial.println("USB UNPLUGGED");
|
25 | break;
|
26 | case ARDUINO_USB_SUSPEND_EVENT:
|
27 | HWSerial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en);
|
28 | break;
|
29 | case ARDUINO_USB_RESUME_EVENT:
|
30 | HWSerial.println("USB RESUMED");
|
31 | break;
|
32 |
|
33 | default:
|
34 | break;
|
35 | }
|
36 | } else if(event_base == ARDUINO_USB_CDC_EVENTS){
|
37 | arduino_usb_cdc_event_data_t * data = (arduino_usb_cdc_event_data_t*)event_data;
|
38 | switch (event_id){
|
39 | case ARDUINO_USB_CDC_CONNECTED_EVENT:
|
40 | HWSerial.println("CDC CONNECTED");
|
41 | break;
|
42 | case ARDUINO_USB_CDC_DISCONNECTED_EVENT:
|
43 | HWSerial.println("CDC DISCONNECTED");
|
44 | break;
|
45 | case ARDUINO_USB_CDC_LINE_STATE_EVENT:
|
46 | HWSerial.printf("CDC LINE STATE: dtr: %u, rts: %u\n", data->line_state.dtr, data->line_state.rts);
|
47 | break;
|
48 | case ARDUINO_USB_CDC_LINE_CODING_EVENT:
|
49 | HWSerial.printf("CDC LINE CODING: bit_rate: %u, data_bits: %u, stop_bits: %u, parity: %u\n", data->line_coding.bit_rate, data->line_coding.data_bits, data->line_coding.stop_bits, data->line_coding.parity);
|
50 | break;
|
51 | case ARDUINO_USB_CDC_RX_EVENT:
|
52 | HWSerial.printf("CDC RX [%u]:", data->rx.len);
|
53 | {
|
54 | uint8_t buf[data->rx.len];
|
55 | size_t len = USBSerial.read(buf, data->rx.len);
|
56 | HWSerial.write(buf, len);
|
57 | }
|
58 | HWSerial.println();
|
59 | break;
|
60 | case ARDUINO_USB_CDC_RX_OVERFLOW_EVENT:
|
61 | HWSerial.printf("CDC RX Overflow of %d bytes", data->rx_overflow.dropped_bytes);
|
62 | break;
|
63 |
|
64 | default:
|
65 | break;
|
66 | }
|
67 | }
|
68 | }
|
69 |
|
70 | void setup() {
|
71 | HWSerial.begin(115200);
|
72 | HWSerial.setDebugOutput(true);
|
73 |
|
74 | USB.onEvent(usbEventCallback);
|
75 | USBSerial.onEvent(usbEventCallback);
|
76 |
|
77 | USBSerial.begin();
|
78 | USB.begin();
|
79 | }
|
80 |
|
81 | void loop() {
|
82 | while(HWSerial.available()){
|
83 | size_t l = HWSerial.available();
|
84 | uint8_t b[l];
|
85 | l = HWSerial.read(b, l);
|
86 | USBSerial.write(b, l);
|
87 | }
|
88 | }
|
89 | #endif /* ARDUINO_USB_MODE */
|
Dieses Program sollte seitens des ESP32, alles was über den UART kommt,
auf den nativen USB weiterleiten. Damit kann ich am PC z.B. mit Realterm
Konfigurationsbefehle an die ESP32 schicken, die dann die GPS Platine
auch empfangen sollte - tut sie aber nicht, denn sie reagiert nicht auf
sie. Die Befehle sollten nicht das Problem sein: Mit dem Protokol habe
ich schon mit einem anderen GPS Empfänger desselben Herstellers ziemlich
viel rumgespielt, und die NS-RAW reagiert auf diese Befehle, wenn ich
die Platine direkt am PC per USB anschließe.
Als weiterer Hinweis: Von den mehreren Meldungen, die das Program zeigen
kann, sehe ich nur "USB Unplugged" wenn ich die GPS-Platine trenne. Ich
sehe keine, wenn ich die wieder anschließe, doch auch gar nichts zu
einer CDC Verbindung.
Also die Frage, wenn das Problem halbwegs zu verstehen ist: Kann jemand
sehen, warum die GPS-Platine angeblich nichts vom nativen USB des ESP32
empfängt? Habe ich einfach ein grunsätzliches Verständnisproblem über
die Funktionsweise des ESP32 als USB Host? Jeder Vorschlag ist
willkommen!
Vielen Dank im Voraus