Bad file number - Synaser

Antworten
Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Bad file number - Synaser

Beitrag von Maik81SE »

Moin ihr lieben,

zZ habe ich leider sehr viel Freizeit zu hause und nutzte die Zeit an meinen Programmen zu Arbeiten.

Die Grundroutinen, welche die UART auf meinem Atmega16 steuern laufen und somit habe ich nun auch meinen Grundbefehlssatz aufgebau.
Dies läuft auch mit dem Abstrich der Übertragungsrate (115200) zuriedenstellend.
Feinschliff kommt 3 rev. vor dem Final-Board.

Bei der Portionierung der Ersten Routine habe ich jedoch nach dem 4tem Durchlauf folgenden Softwarefehler.

USB.LastErrorDesc = Bad file number

Initialisiert wird meine Schnittstelle wie folgt

Code: Alles auswählen

procedure TTray_Form.Find_MS;
var MS_Load: String;
begin
  if FileExists('/dev/ttyUSB0') then begin
    if (     _USB.Connect  and (Not _USB.Error)) then begin
      {$ifdef CPUARM}
        MS_load                   :='$0#M>';     // <--- ARM Masteranvorderung zum Atmega16 /128
      {$endif}
      {$ifdef CPUi386}
        MS_load                   :='$1#M>';     // <--- PC Masteranvorderung zum Atmega16 /128 (Dominant, auch wenn ARM schon Master ist
      {$endf}
      USB.SendString(MS_Load);
      _USB.RXD                    := USB.RecvTerminated(1000, '>')+'>';
      StatusBar1.Panels[0].Text   := _USB.RXD;
      StatusBar1.Panels[0].Width  := Canvas.TextWidth(_USB.RXD) + 50;;

      end;
    end;
end;

procedure TTray_Form.FormCreate(Sender: TObject);
begin
  USB                             := TBlockSerial.Create;
  try
    USB.Connect(Port);
//    USB.Config(115200, 8, 'N', 1, false, false);			
    USB.Config(9600, 8, 'N', 1, false, false);
    Sleep(1000);
  finally
    if USB.LastError = 0 then begin						<--- Auswertung muß noch erweitert werden
      _USB.Connect                := True;
      _USB.Error                  := False;
    end;
  end;
  Statusbar1.Panels[1].Text       := USB.LastErrorDesc;
end;

procedure TTray_Form.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  USB.Free;
end;
Auf dem ersten Blick sehe ich daran nicht, was den einen LastError = -9 auslösen könnte, damit ich dies als vorzeitige Fehlerbehandlung ausräumen kann.

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Bad file number - Synaser

Beitrag von Winni »

Hi!

Da gab es vor Jahren schon mal eine Debatte.
Mit Beiträgen von Theo.
er ist hier ja noch immer unterwegs:

viewtopic.php?t=2082


Winni

Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Re: Bad file number - Synaser

Beitrag von Maik81SE »

Winni hat geschrieben:
Di 8. Dez 2020, 22:32
Hi!

Da gab es vor Jahren schon mal eine Debatte.
Mit Beiträgen von Theo.
er ist hier ja noch immer unterwegs:

viewtopic.php?t=2082


Winni
Danke, ähnliche Debatte hab ich gesucht.

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Bad file number - Synaser

Beitrag von sstvmaster »

Wenn du unter Linux bist, probiere mal bitte folgendes nach dem Create:

Code: Alles auswählen

USB.LinuxLock := False;
Bei einigen hat es auch geholfen die config(...) vor dem connect() zu setzten.

Nachtrag: Nach dem Connect würde ich auch noch einen Sleep() einbauen.
Ich hatte mal das Problem, speziell bei USB->Seriell Adaptern, das der USB-Port nicht schnell genug geöffnet
war und gleich danach die Parametrisierung in die Hose ging.
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Re: Bad file number - Synaser

Beitrag von Maik81SE »

sstvmaster hat geschrieben:
Mi 9. Dez 2020, 15:03
Wenn du unter Linux bist, probiere mal bitte folgendes nach dem Create:

Code: Alles auswählen

USB.LinuxLock := False;
der Tip war schon mal von Vorteil...

habe dahingehend mal die Synaser.pas angepasst
von

Code: Alles auswählen

fLinuxLock := true
zu

Code: Alles auswählen

  {$ifdef Linux}
  fLinuxLock := False;
  {$else}
  fLinuxLock := True;
  {$endif}
Ich gehe stark davon aus, das Viele darüber stolpern könnten.
sstvmaster hat geschrieben:
Mi 9. Dez 2020, 15:03
Bei einigen hat es auch geholfen die config(...) vor dem connect() zu setzten.

Nachtrag: Nach dem Connect würde ich auch noch einen Sleep() einbauen.
Ich hatte mal das Problem, speziell bei USB->Seriell Adaptern, das der USB-Port nicht schnell genug geöffnet
war und gleich danach die Parametrisierung in die Hose ging.
Ich habe sogar ein älteres Programm gefunden, wo ich die Config(...) garnicht geschrieben habe, und dies lief auch ohne Probleme. Warum auch immer :shock:

Weil du mich aber gerade auf die Config hingewiesen hast...

Laut Definition liegt es ja so aus...

Code: Alles auswählen

procedure TBlockSerial.Config(baud, bits: integer; parity: char; stop: integer;
  softflow, hardflow: boolean); 
da ich das aber aus TP zeiten als 16bit auf dem Zettel habe und auch noch heute so verwende, wäre es da nicht gescheiter dies so zu ändern?

Code: Alles auswählen

procedure TBlockSerial.Config(baud: Uint32; bits: integer; parity: char; stop: integer; 
 softflow, hardflow: boolean);
bzw

Code: Alles auswählen

procedure TBlockSerial.Config(baud: int32; bits: integer; parity: char; stop: integer; 
 softflow, hardflow: boolean);
Den Vorteil sehe ich da, das man laut Data Type/de sich nicht noch darum kümmern muß, wie in diesem Artikel beschrieben sich noch mit dem Compilermodus rumschlagen muß, gerade unter dem Aspekt, das viele mit Baud = 115200 setzen werden wollen.

habe auch gleich mal die meine FormCreate umgeschrieben.

Code: Alles auswählen

procedure TTray_Form.FormCreate(Sender: TObject);
begin
  USB                             := TBlockSerial.Create;
  try
    try
//       USB.Config(115200, 8, 'N', 1, false, false);
       USB.Config(9600, 8, 'N', 1, false, false);
       USB.Connect(Port);
       Sleep(1000);
       if USB.LastError = 0 then begin			//			<--- Auswertung muß noch erweitert werden
         _USB.Connect             := True;
         _USB.Error               := False;
         end;
    except
      StatusBar1.Panels[0].Text   := IntToStr(USB.LastError);
      USB.Free;
      end;
  finally
    Statusbar1.Panels[1].Text     := USB.LastErrorDesc;
  end;

procedure TTray_Form.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  {$ifdef Linux}
  {$else}
    USB.LinuxLock                 := False;
  {$endif}
  USB.Free;
end;

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Bad file number - Synaser

Beitrag von sstvmaster »

habe dahingehend mal die Synaser.pas angepasst
von

Code: Alles auswählen

fLinuxLock := true
zu

Code: Alles auswählen

  {$ifdef Linux}
  fLinuxLock := False;
  {$else}
  fLinuxLock := True;
  {$endif}
Eigentlich nicht nötig, da im TBlockSerial.Create, FLinuxLock nur initialsiert wird.
Deshalb danach gleich xxx.LinuxLock := False, weil das dann im TBlockSerial.Connect und TBlockSerial.CloseSocket mit {$IFDEF} angewendet wird.

----

Code: Alles auswählen

procedure TBlockSerial.Config(baud: Uint32; bits: integer; parity: char; stop: integer; 
 softflow, hardflow: boolean);
bzw

Code: Alles auswählen

procedure TBlockSerial.Config(baud: int32; bits: integer; parity: char; stop: integer; 
 softflow, hardflow: boolean);
Nö, Integer wird doch passend zur Bitness und dem Compilermodus angepasst: https://wiki.freepascal.org/Integer

Nachtrag: Das ist gerade der Sinn von den Compilermodi, du kannst Synaser nehmen und zb. eine Konsolenanwendung für DOS, Windows, Linux und Mac OS schreiben ohne darüber nachzudenken, wie Integer interpretiert wird.
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Benutzeravatar
Maik81SE
Beiträge: 308
Registriert: Fr 30. Sep 2011, 14:07
OS, Lazarus, FPC: Debian 12 (L 3.0.0.3 FPC 3.2.2); Windows 10 (L 3.99.0.0 FPC 3.2.0)
CPU-Target: x86-64; arm; avr
Wohnort: Lübeck
Kontaktdaten:

Re: Bad file number - Synaser

Beitrag von Maik81SE »

Gutes Argument, um die Baudrate erst mal nach hinten zu schieben und andere Aspekte in den Fokus zu packen, welche in meinen Programmen von 2015 ohne Probleme liefen, jedoch durch änderungen meiner OS nunmehr Ärger bereiten. :(
  • blockiertes Port; erledigt
  • Automatische USB Erkennung; erledigt
  • TimeOut? Seh den Wald vor lauter bäumen nicht


Um den Fehler zu ermitteln hab ich mir einen Button genommen, der die Schnittstelle mit folgenden Daten füttert.

Code: Alles auswählen

procedure TTray_Form.Button1Click(Sender: TObject);
begin
  _USB.RXD                        := '';
    USB.SendString('$0#M>');     // <--- Masteranvorderung (PC) zum Atmega16 /128 (Dominant, auch wenn ARM schon Master ist
  _USB.RXD                        := USB.RecvTerminated(1000, '>');
  if Length(_USB.RXD) <= 1 then USB.SendString('$0#M>');       // <--- Kontrollabfrage
  _USB.RXD                        := USB.RecvTerminated(1000, '>');
  StatusBar1.Panels[0].Text       := _USB.RXD;
  StatusBar1.Panels[0].Width      := Canvas.TextWidth(_USB.RXD) + 50;
  StatusBar1.Panels[1].Text       := USB.LastErrorDesc;
end;
bin sogar schon am überlegen, den Buffer nach dem Send via Purge zu löschen, auch wenn ich damit gefahr laufe mehr Zeit zuverlieren.

Das das Timeout von meinem µC kommt kann ich zu 99% ausschließen, da via Picocom der zu erwartende Befehl auch so zurückgegeben wird, wie ich es erwarte.

Code: Alles auswählen

int main(void)
{
    uart(false);
   _delay_ms(100);
    while(1)
    if (getch(true) == WakeUp) {
        for (i=0; i<=30; i++) {
            RXD[i] = getch(true);
            if (getch(true) == '>')
                {
                break;
                }
            }
        if ((RXD[0] == '0') && (RXD[1] == 'M'))
//        if ((RXD[0] == '0') && (RXD[1] == '#') && (RXD[2] == 'M'))
        {
            putstring(TXD2_00001);
            _delay_ms(100);
            while(getch(true) == WakeUp)
            {
                for (i=0; i<=30; i++)
                {
                    RXD[i] = getch(true);
                    if (getch(true) == '>')
                    {
                        break;
                        }
                    }
                }
                if (RXD[0] == '2')
                {
                    RPIMaster = false;
                    putstring("PI wird als Slave verwendet");
                    }
                if (RXD[0] == '1')
                {
                    RPIMaster = true;
                    putstring("PI wird als Master verwendet");
                    }
            }
        }
    return 0;
}
Sicherlich werden einige jetzt darauf aufmerksam werden, das ich $0#M> sende aber nur 0M auswerte.

Diese Tatsache betrachte ich in einem anderen anderen Zusammenhang, welche ich unter Code:Blocks erschlagen muß

Code: Alles auswählen

label.caption:= 'gnublin.no-ip.info'
Debian 12 (L 3.0.0.3 FPC 3.2.2);
windows 10 (L 3.99.0.0 FPC 3.2.0)

Antworten