[gelöst] Frage zu unit serial, bzw Raspi Pico aulesen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5783
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: Frage zu unit serial, bzw Raspi Pico aulesen

Beitrag von af0815 »

sstvmaster hat geschrieben:
Di 18. Okt 2022, 21:53
Dumme Zwischenfrage von mir, käme oliver2104 nicht besser er würde die unit Synaser aus dem Paket Laz_Synapse nehmen?
Ich würde sagen, Geschmacksfrage und man holt sich keine fremde Abhängigkeit ins Projekt.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

oliver2104
Beiträge: 20
Registriert: Sa 26. Dez 2020, 13:22

Re: Frage zu unit serial, bzw Raspi Pico aulesen

Beitrag von oliver2104 »

Danke für die Antworten !
Der Vorschlag betreffend unit Synaser ist sicher berechtigt. Aber ich würde wirklich gern zuerst die Grundlagen verstehen,
bevor ich andere units verwende.
Hab das ganze vereinfacht, und den Pico umprogramiert.
Jetzt schickt er alle 1000ms den Integerwert 32000 an die serielle Schnittstelle ( micropython code: print(32000) )
Der Pico ist bei meinem Linux System mit der seriellen Schnittstelle /dev/ttyACM0 verbunden.
dh. in Pascal muss ich schreiben:

Code: Alles auswählen

handle:= SerOpen('/dev/ttyACM0');
in einem Linux Terminal ist es recht einfach, die Ausgabewerte des Pico anzuzeigen.
das sieht das so aus:

Code: Alles auswählen

$ cat /dev/ttyACM0
32000

32000

32000

32000

32000

32000
und so geht das weiter bis ich mit ctrl+c abbreche.
genau diese Werte würde ich gern in Pascal einlesen.
Interessanterweise gibt's nach jedem Wert auch eine Leerzeile.
Wollte mir dann anschauen wieviele Bytes benötigt werden um jede Zeile einzulesen.
und hab in Pascal das laufen lassen:

Code: Alles auswählen

  repeat
    bytes_gelesen:= SerRead(handle, puff, 10);  //zur Sicherheit die Anzahl der Bytes, die eingelesen werden können, auf 10
    if bytes_gelesen > 0 then writeln(bytes_gelesen);  //nur wenn wirklich was eingelesen wurde
  until keypressed; 
Also da geht's nicht um die eigentlichen Werte (sind immer 32000), sondern um die Byte Anzahl die bei jeder Ausgabe eingelesen werden.
Wenn das Pascal Prog ( pico_test) läuft, gibt das folgendes :

Code: Alles auswählen

$ pico_test
3
5
2
5
2
5
2
5
2
das läuft endlos bis eine Taste gedrückt wird.
Die erste Anzahl der gelesenen Bytes ist immer 3.
Dann kommt immer 5 gefolgt von 2.
Hab zuerst gedacht wenn 5 Bytes eingelesen werden, ist das der Wert (32000)
und die 2 Bytes stehen für die Leerzeile.
Also hab ich obigen Pascal Schnipsel umgeschrieben zu:

Code: Alles auswählen

  repeat
    bytes_gelesen:= SerRead(handle, puff, 5);  //  5 ist anscheinden die max. Anzahl der Bytes, 
    if bytes_gelesen = 5 then writeln(puff);  //  nur wenn wirklich 5 Bytes eingelesen wurden
  until keypressed; 
und das kommt dabei raus:

Code: Alles auswählen

$ pico_test
3
808464947
808464947
808464947
808464947
808464947
808464947
808464947
808464947
... usw
frag mich jetzt, was hat 808464947 mit 32000 zu tun und warum kommt noch immer eine 3 als erste Ausgabe ?

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Frage zu unit serial, bzw Raspi Pico aulesen

Beitrag von theo »

Ich vermute, dass du mit print(32000) einen String und keinen Integer schickst.
Diesen sollte man auch als String empfangen.

oliver2104
Beiträge: 20
Registriert: Sa 26. Dez 2020, 13:22

Re: Frage zu unit serial, bzw Raspi Pico aulesen

Beitrag von oliver2104 »

Danke für den Tip !
les das jetzt als string aus:

Code: Alles auswählen

var
  puff: string;
  
  repeat
    bytes_gelesen:= SerRead(handle, puff, 5);   //  5 ist anscheinden die max. Anzahl der Bytes, 
    if bytes_gelesen = 5 then writeln(puff);    //  nur wenn wirklich 5 Bytes eingelesen wurden
  until keypressed; 
zudem sendet der Pico jetzt den Wert 12345 an die serielle Schnittstelle.
das sieht dann so aus:

Code: Alles auswählen

$ pico_test
2345
2345
2345
2345
... usw
Das läuft schon besser, nur die erste Stelle ist abgeschnitten !

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Frage zu unit serial, bzw Raspi Pico aulesen

Beitrag von theo »

Mach so, Strings beginnen bei 1 nicht 0:

Code: Alles auswählen

bytes_gelesen := SerRead(handle, puff[1], 5); 
Anscheinend bist du im ShortString Modus, sonst hätte es direkt gekracht.
https://wiki.freepascal.org/$H

Am Besten du machst das gleich explizit:

Code: Alles auswählen

var
  puff: string[5];     

siro
Beiträge: 650
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 10
CPU-Target: 64Bit
Wohnort: Berlin

Re: Frage zu unit serial, bzw Raspi Pico aulesen

Beitrag von siro »

Ich vermute mal, Du hast keine Synchronisation....

Als Anregung evtl. so:

Code: Alles auswählen

  var value:Byte

  Repeat
    gelesen:=SerRead(SerHandle,value,1);  // nur ein Byte einlesen
  Until value = $0A;                      // oder $0D  ??? je nach Reihenfolge was der Pico als letztes sendet      
Das Carriage Return 0x0D und das Linefeed $0A sollte sicherlich nicht im String landen.
Man muss also erstmal irgendwie "einrasten" synchronisieren.

Dann könntest Du auch solange Zeichen einlesen bis ein Endezeichen erreicht wird und den String zusammenbasteln:

Code: Alles auswählen

  s:='';
  Repeat
    gelesen:=SerRead(SerHandle,value,1);  // nur ein Byte einlesen
    if gelesen >0 then begin
      if (value <> $0A) and (value <> $0D) then s:=s+chr(value);
    end;  
  Until value = $0D;                      // oder $0A  ??? je nach Reihenfolge was der Pico als letztes sendet 
sicher kein schöner Code :wink: aber zum probieren......
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

oliver2104
Beiträge: 20
Registriert: Sa 26. Dez 2020, 13:22

Re: Frage zu unit serial, bzw Raspi Pico aulesen

Beitrag von oliver2104 »

Vielen Dank an @theo und @siro !

Der Pico sendet einen Wert und hängt zuletzt ein newline (LF bzw. $0a) an.
Da im Betrieb theoretisch Werte von 0 bis 65535 möglich sind, können die Stringlängen varieren von 1 bis 5.
Denke der Tip von @siro ist die Lösung.
Hab den Code mit einer weiteren Repeat Schleife eingerahmt und das läuft wie erwünscht.

Code: Alles auswählen

repeat
   s:='';
   repeat
     gelesen:=SerRead(SerHandle,value,1);  // nur ein Byte einlesen
     if gelesen >0 then
       if (value <> $0A) and (value <> $0D) then s:=s+chr(value); 
   until value = $0A;                      // $0A wird vom Pico zuletzt gesendet ( Zeile fertig eingelesen )
   if s <> '' then writeln(s);     // Ausgabe nur dann, wenn es wirklich einen Wert gibt
until keypressed;

Antworten