Forum: Mikrocontroller und Digitale Elektronik Atmega32U4-Board: USB-Ausgabe in Betrieb nehmen


von Matthias W. (matt007)


Angehängte Dateien:

Lesenswert?

es geht um die Nutzung der USB-Schnittstelle eines 
Atmega32u4-ProMicro-Boards unter Win7 64bit.

auf das Board lässt sich mit AVRDUDE Code aufspielen wenn man Reset 
drückt und sich so der Bootloader meldet.

als Code nutze ich das Beispiel "USB Serial, Version 1.7" für Teensy 2 
von der Seite www.pjrc.com/teensy/usb_serial.html.

zum Ansprechen von USB werden die Dateien usb_serial.c und usb_serial.h 
verwendet. Die Ausgabe über USB erfolgt mittels 
usb_serial_putchar(data). Probiert habe ich auch 
usb_serial_putchar_nowait(data).

Leider kommen keine Daten raus. Wie bekomme ich das in Betrieb?

von Thomas W. (diddl)


Lesenswert?

Hast du das INF File verwendet?

Wird die USB Hardware im device manager angezeigt?
Wenn ja, als was?

von Stefan F. (Gast)


Lesenswert?

Du bist ja ein Spaßvogel, postest hier die USB implementierung aber 
nicht dein Anwendungsprogramm. Hoffst du darauf, dass jemand einen 
Fehler in der USB implementierung findet?

Ohne main() Funktion gucke ich da gar nicht erst rein, denn ich bin kein 
Wahrsager.

von Matthias W. (matt007)


Lesenswert?

Thomas W. schrieb:
> Hast du das INF File verwendet?

ich habe den zu diesem Beispiel vorgesehenen Treiber von PJRC verwendet. 
Das gelbe Warnzeichen im Gerätemanager verschwand.

> Wird die USB Hardware im device manager angezeigt? Wenn ja, als was?

ja Thomas. Es wird angezeigt als "Teensy USB Serial (COM5)".

von Matthias W. (matt007)


Lesenswert?

Stefanus F. schrieb:
> Ohne main() Funktion gucke ich da gar nicht erst rein

in der main-Funktion ist jede Menge anderer Kram den ich erstmal 
ausblenden müsste weil er schlicht den Rahmen hier sprengt und ich nicht 
alles posten möchte.

95% des Code im main lief schon mal fehlerfrei auf einem atmega2560. Ich 
habe das nur leicht umgeschrieben. Ein kleiner USB-Teil kam auch dort 
hinzu.

Das kann ich gerne posten. Sorry daß ich es vergessen habe. Muss den 
Code erst suchen. Bitte etwas Geduld !

von Thomas W. (diddl)


Lesenswert?

Ist normal absolut einfach und sicher in der Funktion, und sehr robust.


Hast du den PC mal neu gestartet?

Ich hatte schon den Fall, dass es direkt nach der Installation des 
Drivers nicht funktionieren wollte. Erst nach einem Reboot.

von Stefan F. (Gast)


Lesenswert?

Matthias W. schrieb:
> in der main-Funktion ist jede Menge anderer Kram den ich erstmal
> ausblenden müsste weil er schlicht den Rahmen hier sprengt und ich nicht
> alles posten möchte.

Dann mach das. Im Rahmen der Fehlersuche müsstest du das auch für dich 
selbst tun. Wenn ein komplexes Programm an unbekannter Stelle versagt, 
reduziert man es, bis der Fehler verschwindet. Lass dich nicht zu der 
bequemen Idee verleiten, dass der alte Code mit dem Problem nichts zu 
tun haben kann, weil er ja mal woanders funktionierte. Oft ist das so, 
aber wenn nicht, blockiert diese Haltung den Weg zum Erfolg.

Ich würde Dir empfehlen, ein ganz minimlaistisches Programm zu 
schreiben, dass in regelmäßigen Abständen "Hallo\n" Sendet und außerdem 
ein Echo von allen empfangenden Zeichen zurück schickt.

von Matthias W. (matt007)


Lesenswert?

Stefanus F. schrieb:
> Ich würde Dir empfehlen, ein ganz minimlaistisches Programm zu
> schreiben, dass in regelmäßigen Abständen "Hallo\n" Sendet

Danke Stefanus. Oben habe ich eine While-Schleife für die USB-Ausgabe 
eingebaut. Da kommt nur leider nichts.

im main.c steht:
initialization();  // fuer UART, Pins, I2C etc.

while (1){
  outs(USART,PSTR("\nTest...")); // Meldung ausgeben in Schleife
  outs(USB,PSTR("\nTest..."));   // Meldung ausgeben in Schleife
}

die Ausgabe auf den USART klappt, die auf USB (Zeile darunter) nicht.

weiter unten - da kommt das Programm aber nun durch die obere 
While-Schleife nicht hin - steht die USB-Eingabe in der Haupt-Schleife:

while(1){

  r = usb_serial_getchar(); // serielles Zeichen von USB einlesen falls 
da
  if (r != -1) {  // nur weiter auswerten wenn aktuelle Eingabe da
    byte=r;      // nur byte anschauen
  }
....
}

von Stefan F. (Gast)


Lesenswert?

Am besten schnürst du mal ein Paket mit dem kompilierbaren Quelltext, 
dem hex File und dem Treiber, damit das jemand ausprobieren kann, der 
den selben Chip vorliegen hat.

von Matthias W. (matt007)


Lesenswert?

die Ausgabefunktion outs steht in out.c und schickt über outc entweder 
auf USB, UART etc.

void outc(unsigned char device, unsigned char data)

if (device==USB){
      usb_serial_putchar(data);
      //usb_serial_putchar_nowait(data);
#endif // USB

Ausgabe über device=UART geht, über device=USB kommt nichts und 
blockiert.

es ist dabei scheinbar egal ob ich zur Ausgabe usb_serial_putchar(data) 
oder usb_serial_putchar_nowait(data) verwende.

von Matthias W. (matt007)


Lesenswert?

Thomas W. schrieb:
> Ist normal absolut einfach und sicher in der Funktion, und sehr robust.

dann sollte es ja bald laufen.

> Hast du den PC mal neu gestartet?

noch nicht. Es sind so viele andere Fenster noch offen.

> Ich hatte schon den Fall, dass es direkt nach der Installation des
> Drivers nicht funktionieren wollte. Erst nach einem Reboot.

ok. Ich probier es mal. Dauert ein wenig ! Bitte Geduld !

von Matthias W. (matt007)


Lesenswert?

einen Durchbruch sehe ich durch neu Booten nicht. Seltsamerweise werden 
zwar im Gerätemanager nun
- Teensy USB Serial (COM5) und
- USB Serial Port (COM6) angezeigt.

nur nach Öffnen hterm sehe ich nur COM1 und COM6. COM5 fehlt da nun. 
Vorhin war er noch da. Schließen/Öffnen hterm bessert nicht. Refresh 
Component List bessert auch nicht.

nach Reset am Board sind alle 3 wieder da. Lästig.

wenn ich COM5 verbinde (mit welcher Baudrate denn?) und dann Reset 
drücke kommen keine Zeichen im hterm an. Dies erst mal zur Info.

von Matthias W. (matt007)


Lesenswert?

Stefanus F. schrieb:
> Am besten schnürst du mal ein Paket mit dem kompilierbaren Quelltext,
> dem hex File und dem Treiber, damit das jemand ausprobieren kann, der
> den selben Chip vorliegen hat.

das dauert eine Weile. Melde mich dann.

von Stefan F. (Gast)


Lesenswert?

Wenn ich unter Windows Treiberprobleme vermute, probiere ich Linux (und 
umgekehrt). Linux kann man sehr bequem von einem USB Stick starten und 
ausprobieren.

Linux hat hier den Vorteil, detailliertere Fehlermeldungen zu liefern 
und für sehr viele Bastelsachen (insbesondere serielle USB Verbindungen) 
keine speziellen Treiber zu benötigen.

Downloade Dir Ubuntu, übertrage es auch einen Stick, starte, AVR 
anstecken und dann gibst du im Terminalfenster "dmesg" ein, um zu sehen, 
was der Linux Kernel/Treiber dazu zu sagen hat.

von Matthias W. (matt007)


Lesenswert?

Stefanus F. schrieb:
> Downloade Dir Ubuntu, übertrage es auch einen Stick, starte, AVR
> anstecken und dann gibst du im Terminalfenster "dmesg" ein, um zu sehen,
> was der Linux Kernel/Treiber dazu zu sagen hat.

Danke für den Hinweis Stefanus. Bisher lief das ja immer noch alles 
brauchbar unter Win7. Was 2020 wird - das wird sich zeigen.

von Stefan F. (Gast)


Lesenswert?

Was soll das heissen? Ist Dir dieser Test zu aufwändig? Ich bräuchte 
dafür weniger als eine Stunde inclusive download. Das ist doch 
letztendlich sinnvoller, als weitere Tage am Treiber herum zu basteln 
ohne zu wissen, ob es daran liegt.

Wenn du mit Linux noch nicht vertraut bist, brauchst du vielleicht etwas 
länger. Aber dabei helfen wir Dir ggf. gerne.

von Matthias W. (matt007)


Angehängte Dateien:

Lesenswert?

Stefanus F. schrieb:
> Am besten schnürst du mal ein Paket mit dem kompilierbaren Quelltext,
> dem hex File und dem Treiber, damit das jemand ausprobieren kann, der
> den selben Chip vorliegen hat.

hier ist das abgemagerte Paket. Unter WinAVR mit aktuellem AVRDUDE wurde 
es anstandslos in der Eingabeaufforderung mittels "make program" 
übersetzt, sollte also eigentlich laufen.

von Matthias W. (matt007)


Angehängte Dateien:

Lesenswert?

im Verzeichnis usb_treiber liegt der USB-Treiber von PJRC den ich unter 
Win7 64bit genutzt habe.

hier das hex-file.

von Stefan F. (Gast)


Lesenswert?

Nach der Initialisierung hängt dein Programm in dieser Endlosschleife:
1
   while (1){ 
2
     outs(USART,PSTR("\nTest...")); // Meldung ausgeben in Schleife 
3
     outs(USB,PSTR("\nTest..."));   // Meldung ausgeben in Schleife 
4
   }

Ich wollte prüfen, wie diese outs() Funktion reagiert, wenn der 
Ausgabepuffer überflutet wird, was hier offenbar der Fall ist, das 
fortlaufende Ausgabe ohne Bremse:
1
// schreibt String (Text) zur Ausgabe USART/LCD/SRAM
2
void outs(unsigned char device, const char *str)
3
{
4
   char c;
5
6
   if (device==USART){
7
      while ((c=pgm_read_byte(str++)) ){  // get next char, bis /0
8
         //usart_putc(c);     //send char
9
         outc(USART,c);       //send char
10
      }
11
   }
12
   else if (device==LCD){ 
13
#if LCD // LCD-Ausgabe ggf. ausblenden 
14
      //while ((c=pgm_read_byte(str++)) ){  // get next char, bis /0
15
      while (*str) {          // get next char, bis /0
16
         //lcd_putc(*str++);  //send char
17
         outc(LCD,*str++);    //send char
18
      }
19
#endif // LCD
20
   }
21
      else { // SRAM-Ausgabe
22
#if SRAM // SRAM-Ausgabe ggf. ausblenden 
23
      //while ((c=pgm_read_byte(str++)) ){  // get next char, bis /0
24
      while (*str) {          // get next char, bis /0
25
         outc(SRAM,*str++);   //send char
26
      }
27
#endif // SRAM
28
   }
29
}

Von USB steht da nichts. Kein Wunder, dass so am USB Port keine Ausgaben 
stattfinden.

von Matthias W. (matt007)


Lesenswert?

Stefanus F. schrieb:
> Ich bräuchte dafür weniger als eine Stunde inclusive download.

das ist prima. Aus Erfahrung weiß ich leider daß vieles leider nicht 
immer so einfach ist. Ich hatte anfangs auch gehofft daß dieses einfache 
Beispiel rasch laufen könnte. Die Praxis zeigt daß da oft Hürden sind . 
. .

von Matthias W. (matt007)


Lesenswert?

Stefanus F. schrieb:
> on USB steht da nichts.

Danke für den Hinweis !

da sieht man wie betriebsblind man oft ist. Oben baut man den Schalter 
für USB ein und unten habe ich ihn wohl vergessen.

von Matthias W. (matt007)


Lesenswert?

Stefanus F. schrieb:
> Aber dabei helfen wir Dir ggf. gerne.

Danke Stefanus.

wenn Du meinst daß das - trotz der vermutlichen Ursache die Du ja 
dankenswerter Weise sofort gefunden hast - Sinn macht - so können wir es 
versuchen. Es wird halt ggf. eine Weile dauern und Geduld erfordern.

von Matthias W. (matt007)


Angehängte Dateien:

Lesenswert?

Stefanus F. schrieb:
> Von USB steht da nichts. Kein Wunder, dass so am USB Port keine Ausgaben
> stattfinden.

mit diesem out.c sollte es besser gehen.

bei meinem größeren Programm sehe ich nun immerhin Ausgaben mit hterm 
auf COM5. Obwohl ich alle Baudraten der Liste durchprobiert habe sind 
nur Rechtecke zu sehen - irgendwelche Sonderzeichen.

keine Ahnung wo/ob man die Baudrate zum Senden einstellen kann.

es gibt usb_serial_get_baud(void) zum Auslesen von Einstellungen.
es steht da: "These aren't actually used by USB at all (communication is 
always at full USB speed), but they are set by the host..)

das soll also immer maximal schnell sein. Hterm kann ich bis 256000 baud 
einstellen.

zum Interrupt-Handlung USB-Interrupt habe ich selbst nichts gemacht.

von Εrnst B. (ernst)


Lesenswert?

Matthias W. schrieb:
> mit diesem out.c sollte es besser gehen.

Nächste Fehlerquelle:

für USART liest die Funktion aus dem Flash (pgm_read)

die anderen aus dem RAM.

von Matthias W. (matt007)


Lesenswert?

Εrnst B. schrieb:
> für USART liest die Funktion aus dem Flash (pgm_read)

Danke Ernst !
das war meines Wissens so gewollt. Bisher lief das jedenfalls wie 
gewünscht.

von Matthias W. (matt007)


Lesenswert?

Εrnst B. schrieb:
> die anderen aus dem RAM.

ja. Bisher lief das so brauchbar. Ich weiß nicht mehr genau warum ich 
das so gemacht hatte.

von Stefan F. (Gast)


Lesenswert?

> outs(USB,PSTR("\nTest..."));

Der String liegt im Flash, wegen PSTR.
1
      while (*str) {          // get next char, bis /0
2
         outc(USB,*str++);    //send char
3
      }

Hier liest du Zeichen aus dem RAM. Das passt nicht zusammen.

von Εrnst B. (ernst)


Lesenswert?

Matthias W. schrieb:
> ja. Bisher lief das so brauchbar.

ist zumindest unerwartet, wenn die Funktion in Abhängigkeit des 
Ausgabe-Kanals den Eingabeparameter unterschiedlich verarbeitet.
-> Wenn das so gewollt ist, würde mir dazu der deutliche Warnhinweis in 
den Kommentaren fehlen.

Warum nicht (grob skizziert)
1
void outs(unsigned char device, const char *str)
2
{
3
      while (*str) {          // get next char, bis /0
4
         outc(device,*str++);    //send char over variable device
5
      } 
6
}
7
8
void outs_P(unsigned char device, const char *str) {
9
      char c;
10
      while ((c=pgm_read_byte(str++)) ){  // get next char, bis /0
11
         outc(device,c);       //send char
12
      }
13
}


Dann ist die Unterscheidung nach device nur an einer einzelnen Stelle 
(im outc), und du kannst je nach "Datenquelle" das passende "outs" 
verwenden.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Εrnst B. schrieb:
> Warum nicht outs() und outs_P() ?

Nachmachen kann jeder, das wäre doch zu einfach.

Spaß beiseite: So macht man das. Punkt.

von Matthias W. (matt007)


Lesenswert?

Εrnst B. schrieb:
> Dann ist die Unterscheidung nach device nur an einer einzelnen Stelle
> (im outc), und du kannst je nach "Datenquelle" das passende "outs"
> verwenden.

vielen Dank Ernst für den guten Hinweis. Du hast schon recht. Das kann 
Sinn machen.

von Thomas Z. (usbman)


Lesenswert?

Matthias W. schrieb:
> mit diesem out.c sollte es besser gehen.

aber nur wenn USB definiert ist.... #if USB....
Das ist doch sicher nicht das was du erreichen willst.

Thomas

: Bearbeitet durch User
von Matthias W. (matt007)


Angehängte Dateien:

Lesenswert?

Εrnst B. schrieb:
> Warum nicht (grob skizziert)
> void outs(unsigned char device, const char *str)
> void outs_P(unsigned char device, const char *str)

das habe ich gemacht Ernst. Anbei ein neues main.c, out.c, out.h. Die 
nicht abgemagerte Version übersetzt ohne Fehler.

von Matthias W. (matt007)


Lesenswert?

Thomas Z. schrieb:
> aber nur wenn USB definiert ist.... #if USB....

ja Thomas. In out.h steht #define USB 4. Über die defines blende ich 
unnötige Codeteile ggf. aus.

von Matthias W. (matt007)


Angehängte Dateien:

Lesenswert?

ich bin ein Stück weitergekommen. Die Zeichen kamen vermutlich zu 
schnell hintereinander über USB und so kam hterm wohl durcheinander und 
zeigte konstant Rechtecke (01) an statt der erwarteten Zeichenfolge.

durch Einfügen von delays kann ich die korrekte Ausgabe und auch Eingabe 
nun sehen. Nur leider klappt das korrekte Verbinden mit dem 
Terminalprogramm nicht immer.

manchmal erkennt hterm kein COM5, obwohl im Gerätemanager USB als COM5 
angezeigt wird. Drücken auf "R" hilft ggf. nicht und auch Neustart von 
hterm hilft nicht immer.

mit dem alten Bray-Terminalprogramm klappt das Verbinden schlicht gar 
nicht. Obwohl COM5 im Gerätemanager da ist erscheint beim Versuch damit 
zu verbinden die Meldung "Error: port is not available". Bei COM1 jedoch 
(COM-Port des Laptops) klappt es sofort.

Kennt jemand diese Probleme? Wie werde ich das los?
Ist das ein Treiberproblem?

von Karl M. (Gast)


Lesenswert?

Unter LunaAVR läuft das, nimm mal Putty als Terminal Programm.

von Matthias W. (matt007)


Lesenswert?

Karl M. schrieb:
> Unter LunaAVR läuft das

Danke Karl für den Hinweis. Das läuft unter LunaAVR?
https://www.mikrocontroller.net/articles/LunaAVR
"Basic/Pascal-ähnliche Programmiersprache"

Du hast also nicht mein Programm übersetzt oder das main.hex genommen?
Mit Luna habe ich bisher nicht gearbeitet.

> nimm mal Putty als Terminal Programm.

Danke, ich probier es aus.

von Matthias W. (matt007)


Lesenswert?

Putty zeigt bei mir dasselbe Problem wie ich es von hterm kenne.

obwohl im Gerätemanager COM5 angezeigt wird ist ggf. keine Verbindung 
möglich. Es erscheint dann die Meldung:
Putty: Unable to open connection to COM5. Unable to configure serial 
port.

mit Hilfe von hterm habe ich das Problem näher eingegrenzt:
wenn ich das Board per USB am Laptop anstecke so meldet sich bald COM5 
im Gerätemanager. Wenn ich dann bei Hterm auf R gehe - so findet hterm 
COM5. Mit COM5 kann ich dann auch verbinden.

wenn ich dann den USB-Stecker abziehe verschwindet COM5 im 
Gerätemanager. Beim Neuanstecken erscheint es wieder. Nur ist dann die 
Verbindung gestört. Hterm zeigt die Ausgaben nicht mehr an und eine 
Verbindung mit Hterm klappt auch nicht mehr, obwohl COM5 noch angezeigt 
wird.

ähnliche Probleme zeigt das Video "Windows USB Serial COM port driver 
bug" https://www.youtube.com/watch?v=DRmvUsa2xuU

man sieht wie Verbindungsprobleme auftreten bei einem Arduino-Board mit 
Nicht-FTDI-chip. Man sieht auch wie keine Probleme auftreten bei einem 
Arduino-Board mit FTDI-Chip.

muss man sich nun damit abfinden, daß es diese Probleme gibt - oder gibt 
es eine Lösung? Wer hat eine Idee? Was soll ich wo im Code ändern? 
Welchen anderen Treiber soll ich probieren? das Terminalprogramm alleine 
ändern scheint keine Lösung.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.