French AStream_NewData et données non régulières

fgh3966

Active Member
Licensed User
En, français une recherche internet a propos de la persistance rétinienne donnera des résultats.
Dans les années 1800 (avant les ordinosaures (lol)) on s'éclairait avec lampes a filaments alimentées par des dynamos actionées par de la mécanique (fioul, charbon, etc ...)
Les scientifiques ont fait des mesures et en on déduit que faire tourner les dynamo a 50hz ou 60hz iraient bien. Pas la peine d'aller plus vite et de gaspiller de l'énergie.
Avec une fréquence inférieure a 50/60hz les gens seraient gêné par du scintillement.

( Excusez les erreurs de frappes )
 
Last edited:

emexes

Expert
Licensed User
En supposant (1) que les morceaux de série contiennent la plupart du temps au moins un paquet complet, et (2) que nous sommes d'accord sur le fait qu'il est acceptable de mettre à jour avec les données les plus récentes reçues (c'est-à-dire en sautant les paquets périmés) :

Je l'ai hacké au strict minimum, ce qui devrait être tout à fait utilisable, faites-en l'essai 🍻 :

B4X:
 Sub Astreams1_NewData (Buffer() As Byte) ' bytes received

    Dim ExpectedPacketLength As Int = 19
    Dim ExpectedFirstByte As Byte = 0x85
    Dim ExpectedLastByte As Byte = 0xF9
 
    If Buffer.Length < ExpectedPacketLength Then
        Log(DateTime.Now & "short packet" & Buffer.Length & "bytes")
    Else
        Dim FoundPacketAt As Int = -1
        For LastByteAt = Buffer.Length - 1 To ExpectedPacketLength - 1 Step -1    'search for last complete packet
            If Buffer(LastByteAt) = ExpectedLastByte Then    'if last byte is ok
                Dim FirstByteAt As Int = LastByteAt - ExpectedPacketLength + 1
                If Buffer(FirstByteAt) = ExpectedFirstByte Then    'and first byte is ok
                    FoundPacketAt = FirstByteAt    'then we'll call that a win!
                    Exit
                End If
            End If
        Next
 
        If FoundPacketAt < 0 Then
            Log(DateTime.Now & " no packet found in " & Buffer.Length & " bytes")
        Else
            Dim TidyPacket(ExpectedPacketLength) As Byte
            For I = 0 To ExpectedPacketLength - 1
                TidyPacket(I) = Buffer(FoundPacketAt + I)
            Next
            HandleNixiePacket(TidyPacket)
        End If
    End If
End Sub

Sub HandleNixiePacket(B() As Byte)
    Dim bc As ByteConverter
Log(DateTime.Now & TAB & bc. HexFromBytes(B))
End Sub
B4J Log output::
 Waiting for debugger to connect...
Program started.
1709620898015    857F00AA0869B4AEAA2271493A04F470F3FBF9
1709620898034    857F00AA08F74EE8462602AC495843038719F9
1709620898034    857F00AA08832B23847D11B3AF968FB464CDF9
1709620898040    857F00AA088C36DFC40893DD57F54497CE9CF9
1709620898044    857F00AA081B89C462E479B3605CEA62DC3FF9
1709620898050    857F00AA080F81C5E3E2BFA55D8733683A6BF9
1709620898051    857F00AA088E3E63249136FF3DFF1CCB0732F9
1709620898052    857F00AA08F42001EE06A8146D760E0C8082F9
 
Last edited:

emexes

Expert
Licensed User
Si vous n'obtenez aucun résultat du programme de test, essayez de contourner la vérification ExpectedLastByte (et peut-être aussi la vérification ExpectedFirstByte), soit en commentant les lignes If Then et End If, soit en ajoutant "True Or" au Si les lignes par exemple :

B4X:
        For LastByteAt = Buffer.Length - 1 To ExpectedPacketLength - 1 Step -1    'search for last complete packet
            If True Or Buffer(LastByteAt) = ExpectedLastByte Then    'if last byte is ok
                Dim FirstByteAt As Int = LastByteAt - ExpectedPacketLength + 1
                If True Or Buffer(FirstByteAt) = ExpectedFirstByte Then    'and first byte is ok
                    FoundPacketAt = FirstByteAt    'then we'll call that a win!
                    Exit
                End If
            End If
        Next
 

OliverA

Expert
Licensed User
Longtime User
HandleNixiePacket(TidyPacket)
Si vous remplacez ce paramètre par
B4X:
CallSubDelayed2(Me, "HandleNixiePacket", TidyPacket)
vous placez l’appel HandleNixiePacket dans la file d’attente et libérez votre application pour gérer le prochain événement _NewData dès que possible. Vous n’avez pas à vous soucier de l’exécution dans le désordre, car la file d’attente est traitée de manière linéaire.

If you change this to
B4X:
CallSubDelayed2(Me, "HandleNixiePacket", TidyPacket)
you place the HandleNixiePacket call onto the queue and free up your app to handle the next _NewData event as soon as possible. You don't have to worry about out of order execution, since the queue is processed in a linear fashion.
 

fgh3966

Active Member
Licensed User
Merci j'ai essayé ce que vous m'avez écris, je vais refaire des essais et je vous tiens au courant.

Aussi avec felusbserial on peut façilement modifier la taille des buffers, est-ce génant d'utiliser felusbserial ?
Aussi malgrès la modification de la taille des buffers le smartphone ne freeze plus hélàs les données ne sont pas fluides comme sur un ordinateur


calsub = appel a sous-routines ? C'est bien ça ?


B4X:
Private Sub serial_DataAvailable (Buffer() As Byte)

    Dim ExpectedFirstByte As Byte = resdeci     
        If Buffer.Length < 16 Then
        Log(DateTime.Now & "short packet" & Buffer.Length & "bytes")
      
    Else
        Dim FoundPacketAt As Int = -1
        For LastByteAt = Buffer.Length - 1 To 16 - 1 Step -1    'search for last complete packet
            If Buffer(LastByteAt) = 251 Then    'if last byte is ok
                Dim FirstByteAt As Byte = Bit.And(0xFF,Buffer(0)) + Bit.shiftright(Buffer(2),4)
                If Buffer(FirstByteAt) = ExpectedFirstByte Then    'and first byte is ok
                    FoundPacketAt = FirstByteAt    'then we'll call that a win!
                    Exit
                End If
            End If
        Next
      
        If FoundPacketAt < 0 Then
            Log(DateTime.Now & " no packet found in " & Buffer.Length & " bytes")
        Else
            Dim TidyPacket(16) As Byte
            For I = 0 To 16 - 1
                TidyPacket(I) = Buffer(FoundPacketAt + I)
            Next
            CallSubDelayed2(Me, "HandleNixiePacket", TidyPacket)'    HandleNixiePacket(TidyPacket)
        End If
    End If
  
End Sub
      
Sub HandleNixiePacket(B() As Byte)
    Dim bc As ByteConverter
    Log(DateTime.Now & TAB & bc. HexFromBytes(B))
End Sub
 
Last edited:

fgh3966

Active Member
Licensed User
hi, voici un log du programme que vous m'avez envoyé
Ne serait il pas possible de caputrer les données entrantes dans un buffer de mémoire dans un processus rapide et aussi en même temps dans un autre processus séparé et plus lent filtrer, afficher les denières données valides ?

Merci
 

Attachments

  • log-080324.zip
    3 KB · Views: 42

emexes

Expert
Licensed User
Lol ok I was probably a little optimistic that this wouldn't happen:

Log output:
1709908803235 no packet found in 19 bytes
1709908803411 no packet found in 19 bytes
1709908803610 no packet found in 19 bytes
1709908803807 no packet found in 19 bytes
1709908803974 no packet found in 19 bytes
1709908804173 no packet found in 19 bytes

So please try again with these two highlighted lines added:

B4X:
Sub Astreams1_NewData (Buffer() As Byte) ' bytes received
    Dim ExpectedPacketLength As Int = 19
    Dim ExpectedFirstByte As Byte = 0x85
    Dim ExpectedLastByte As Byte = 0xF9
 
    If Buffer.Length < ExpectedPacketLength Then
        Log(DateTime.Now & "short packet" & Buffer.Length & "bytes")
    Else
        Dim FoundPacketAt As Int = -1
        For LastByteAt = Buffer.Length - 1 To ExpectedPacketLength - 1 Step -1    'search for last complete packet
            If Buffer(LastByteAt) = ExpectedLastByte Then    'if last byte is ok
                Dim FirstByteAt As Int = LastByteAt - ExpectedPacketLength + 1
                If Buffer(FirstByteAt) = ExpectedFirstByte Then    'and first byte is ok
                    FoundPacketAt = FirstByteAt    'then we'll call that a win!
                    Exit
                End If
            End If
        Next
 
        If FoundPacketAt < 0 Then
            Dim bc As ByteConverter
            Log(bc.HexFromBytes(Buffer))
            Log(DateTime.Now & " no packet found in " & Buffer.Length & " bytes")
        Else
            Dim TidyPacket(ExpectedPacketLength) As Byte
            For I = 0 To ExpectedPacketLength - 1
                TidyPacket(I) = Buffer(FoundPacketAt + I)
            Next
            HandleNixiePacket(TidyPacket)
        End If
    End If
End Sub

Sub HandleNixiePacket(B() As Byte)
    Dim bc As ByteConverter
    Log(DateTime.Now & TAB & bc.HexFromBytes(B))
End Sub
 

fgh3966

Active Member
Licensed User
Pourquoi le buffer sature ?

Voici le code et un log


code avec 251 et buffer read 64, buffer write 64:
Sub btnConnect_Click
    If manager.GetDevices.Length = 0 Then
        Label1.Text = "No USB devices."
    Else
        Dim device As UsbDevice = manager.GetDevices(0) 'the device
        If manager.HasPermission(device) = False Then
            manager.RequestPermission(device)
        Else
            usbserial.BUFFER_READ_SIZE = 64
            usbserial.BUFFER_WRITE_SIZE = 64
            usbserial.Initialize("serial", device, -1)
            usbserial.BaudRate = 460800
'            usbserial.bitStart = usbserial
            usbserial.DataBits = usbserial.DATA_BITS_8
            usbserial.StopBits = usbserial.Stop_bits_1
           
            usbserial.Parity = usbserial.PARITY_NONE
            usbserial.FlowControl = usbserial.FLOW_CONTROL_OFF
            usbserial.StartReading
            Label1.Text = "Connected"
        End If
    End If
End Sub

Private Sub serial_DataAvailable (Buffer() As Byte)
'    Dim lenghth, fb0, fb1, fb2, fb3, fb4, fb5, fb6, fb7, fb8, fb9 As Int 'Log("L-E-N-G-T-H-") 'lenghth = Buffer.length 'Log (Bit.And(0xff,lenghth))
    Dim ExpectedFirstByte As Byte = resdeci
'    If Buffer.Length > 16 Then
       
        If Buffer.Length < 16 Then
        Log(DateTime.Now & "short packet" & Buffer.Length & "bytes")
       
    Else
        Dim FoundPacketAt As Int = -1
        For LastByteAt = Buffer.Length - 1 To 16 - 1 Step -1    'search for last complete packet
            If Buffer(LastByteAt) = 251 Then    'if last byte is ok
                Dim FirstByteAt As Byte = Bit.And(0xFF,Buffer(0)) + Bit.shiftright(Buffer(2),4)
                If Buffer(FirstByteAt) = ExpectedFirstByte Then    'and first byte is ok
                    FoundPacketAt = FirstByteAt    'then we'll call that a win!
                    Exit
                End If
            End If
        Next
       
        If FoundPacketAt < 0 Then
            Dim bc As ByteConverter
            Log(bc.HexFromBytes(Buffer))
            Log(DateTime.Now & " no packet found in " & Buffer.Length & " bytes")
        Else
            Dim TidyPacket(16) As Byte
            For I = 0 To 16 - 1
                TidyPacket(I) = Buffer(FoundPacketAt + I)
            Next
            CallSubDelayed2(Me, "HandleNixiePacket", TidyPacket)'    HandleNixiePacket(TidyPacket)
        End If
    End If
   
End Sub
       
Sub HandleNixiePacket(B() As Byte)
    Dim bc As ByteConverter
    Log(DateTime.Now & TAB & bc. HexFromBytes(B))
End Sub
 

Attachments

  • log-090324.zip
    3.7 KB · Views: 32

emexes

Expert
Licensed User
Log output:
1709187211650    19    857F00AA08000F0000122400D2410000F807F9
1709187211682    19    857F00AA0800000000157E00D24100005C00F9
1709187211698    19    857F00AA08000F000018D800D2410000B900F9
1709187211714    19    857F00AA08000000001C3200D34100001800F9
1709187211746    19    857F00AA08000F00001F8C00D34100007500F9
1709187211762    19    857F00AA08000F000022E600D3410000D200F9
1709187211794    19    857F00AA0800000000274000D44100003200F9
1709187211810    19    857F00AA08000F0000299A00D44100008E00F9
1709187211842    19    857F00AA08000F00002CF400D4410000EB00F9

Log output:
422A002A45000100006FF300F4000031FBFBFB
422A002A45000000008AC300F700001FFBFBFB
422A002A4500000000A59300F800200DFBFBFB
422A002A4500000000BD6300F80050F8FBFBFB
422A002A4500000000D63300000000E4FBFBFB
422A002A4500000000F10300030000D2FBFBFB
422A002A45000000000DD400050000C1FBFBFB
422A002A450000000028A400080000AFFBFBFB
422A002A45000100003F74000B000099FBFBFB

Précédemment, nous avons reçu des paquets qui commençaient tous par les valeurs d'octet 0x85 0x7F et se terminaient par la valeur d'octet 0xF9.

Maintenant, nous recevons des paquets qui commencent tous par la valeur d'octet 0x42 0x2A et se terminent par la valeur d'octet 0xF8.

Peut-être que certaines de ces valeurs représentent l'heure du jour ou le jour du mois ou une autre valeur qui évolue lentement, et c'est pourquoi elles sont toutes identiques pendant l'exécution d'un programme, mais toutes identiques mais différentes pendant l'exécution d'un programme ultérieur.

Un protocole de données par paquets en série devrait prévoir un moyen de synchroniser l'émetteur et le récepteur afin qu'ils s'accordent sur le point de départ de chaque paquet, dans le flux (flot ?!) d'octets entrant.

En général, cela se fait au moyen d'un octet de départ à valeur constante et, parfois, d'un octet de fin à valeur constante.

Quelle documentation avez-vous sur le format de ces paquets de 19 octets ? Êtes-vous en mesure d'en discuter avec la personne ou la société qui met en œuvre l'extrémité de transmission du flux de données USB ? Vous avez mentionné que les paquets ont une valeur de contrôle (checksum ? CRC ?) - si vous pouviez trouver la position de l'octet dans les paquets de 19 octets, cela pourrait nous aider à comprendre le format du paquet.
 

emexes

Expert
Licensed User
En regardant le bon côté des choses, la valeur changeante du dernier octet correspond à ce que vous avez dit plus tôt sur le fait qu'il avait encore une autre valeur différente, à savoir 252 (= 0xFC) 🍻
 
Last edited:

fgh3966

Active Member
Licensed User
les valeurs ne sont pas importantes et il est façilement possible de les changer. Nous avons définitivement défini que la valeur ( 251 > au format décimal) comme octet de repère arrivant en 17 ième position.

Donc 17 octets sont envoyés et le dernier est de 251

Les 16 autres octets peuvent contenir n'importe quelle valeur sauf 251, on peut y mettre un compteur ou décompteur, etc ...
Ce qui ne fonctionne pas avec b4a c'est que nous n'arrivons pas a recevoir les 17 octets de données séparés de 0,5 ms voire 0,3 ms.
Pourquoi ?
Pourtant sur un PC ça fonctionne bien.
Et dans un smartphones il y a tout ce qu'il faut car avec un appareil de niveau moyen on arrive à compresser des vidéos, etc ...
>>> Donc pas de problème de puissance de calcul ni de rapidité.
 

fgh3966

Active Member
Licensed User
re re.
Je viens de discutter avec le fournisseur de la carte et si ça peut vous arranger vous pouvez vous même définir les données sur les 16 octet de données.
Le seur octet fixe est le N°16 fixé à 251.
Actuellement c'est établi comme ce qui suit :
Les deux premiers octet : octet N°0 et N°1 constituent un identifiant.
Les 10 octets suivants sont des valeurs aléatoires.
L'octet N°16 , car il y a 17 octets , vaut 251 ( au format décimal )

Ce qui ne fonctionne pas c'est que nous n'arrivons pas a recevoir les 17 octets de données séparés de 0,5 ms voire 0,3 ms.
 

emexes

Expert
Licensed User
Oui les paquet ont toujours une longueur de 19 octets et la valeur 252 est au 19e octet.
L'octet N°16 , car il y a 17 octets , vaut 251

J'ai l'impression d'être dans le jeu télévisé "Qui veut être millionnaire ?" 🤣

Est-ce que "17 octets se terminant par la valeur d'octet 251" est la réponse finale ?

Ou bien le système est-il encore en cours de développement et susceptible de changer à nouveau ?

Pas d'inquiétude si c'est le cas, mais ce serait merveilleux de savoir que je suis confus pour une raison, et que je ne deviens pas fou. 🍻
 

emexes

Expert
Licensed User
Essayez ceci. C'est la méthode d'analyse de paquets la plus folle plus flexible que j'ai jamais écrite. 🤣

Ajoutez ces trois variables globales:

B4X:
Sub Process_Globals
    ...
    Dim ExpectedPacketLength As Int = 19    'probably wrong but will be updated when valid-looking packet is received
    Dim ExpectedFirstByte As Byte = 0x85    'ditto
    Dim ExpectedLastByte As Byte = 0xF9    'ditto
End Sub

et copiez-collez ces deux sous-routines mises à jour:

B4X:
Sub Astreams1_NewData (Buffer() As Byte)        ' bytes received
    Log(DateTime.Now & TAB & "Buffer(" & Buffer.Length & ")")    'to help debugging; comment out when working
 
    If Buffer.Length >= 9 And Buffer.Length <= 27 Then    '18 +/- 50% (18 =approximate usual packet length = average of observed lengths 17 and 19)
        Dim LastByte As Byte = Buffer(Buffer.Length - 1)
        If Bit.And(LastByte, 0xF0) = 0xF0 Then    'terminal byte has value 240 or higher eg 251, 252
            Dim LastByteIsUniqueFlag As Boolean = True
            For I = 0 To Buffer.Length - 2
                If Buffer(I) = LastByte Then
                    LastByteIsUniqueFlag = False
                    Exit
                End If
            Next
   
            If LastByteIsUniqueFlag Then    'terminal byte not contained within packet data
                ExpectedPacketLength = Buffer.Length
                ExpectedFirstByte = Buffer(0)
                ExpectedLastByte = LastByte
            End If
        End If
    End If
 
    If Buffer.Length < ExpectedPacketLength Then
        Log(DateTime.Now & " short packet " & Buffer.Length & " bytes")    'feel free to replace with proper error handler
    Else
        Dim FoundPacketAt As Int = -1
        For LastByteAt = Buffer.Length - 1 To ExpectedPacketLength - 1 Step -1    'search for last complete packet
            If Buffer(LastByteAt) = ExpectedLastByte Then    'if last byte is ok
                Dim FirstByteAt As Int = LastByteAt - ExpectedPacketLength + 1
                If Buffer(FirstByteAt) = ExpectedFirstByte Then    'and first byte is ok
                    FoundPacketAt = FirstByteAt    'then we'll call that a win!
                    Exit
                End If
            End If
        Next
 
        If FoundPacketAt < 0 Then
            Log(DateTime.Now & " no packet found in " & Buffer.Length & " bytes")    'feel free to replace with proper error handler
        Else
            Dim TidyPacket(ExpectedPacketLength) As Byte
            For I = 0 To ExpectedPacketLength - 1
                TidyPacket(I) = Buffer(FoundPacketAt + I)
            Next
            HandleNixiePacket(TidyPacket)
        End If
    End If
End Sub

Sub HandleNixiePacket(B() As Byte)
    Dim bc As ByteConverter
    Log(DateTime.Now & TAB & bc.HexFromBytes(B))
End Sub
 
Last edited:

OliverA

Expert
Licensed User
Longtime User
Ce qui ne fonctionne pas c'est que nous n'arrivons pas a recevoir les 17 octets de données séparés de 0,5 ms voire 0,3 ms.
Je ne comprends toujours pas. Oui, les communications série doivent être suffisamment rapides pour capturer toutes les données à capturer. Mais les données doivent-elles être traitées aussi vite qu’elles arrivent (toutes les 0,5 ms) ? Sinon, pourquoi capturer des paquets à ce rythme ? Augmentez simplement le tampon série entrant à la quantité de données que vous souhaitez traiter à un moment donné (disons 8 ms ?). Ensuite, l'événement _newData ne sera lancé que toutes les 8 ms sans aucune perte de données (s'il se produit, il n'a aucun rapport avec B4X, mais une limite du système sous-jacent lui-même). Tout traitement immédiat peut être effectué à ce moment-là et tout traitement supplémentaire peut ensuite être repoussé via un CallSubDelayed stratégique (comme l'affichage des données, le stockage des données, etc.).

Before Google Translate:
I still don't understand. Yes, serial communications may need to be fast enough to capture whatever data needs to be captured. But does the data need to be processed as fast as it comes in (every .5ms)? If not, why capture packets at that rate? Just increase the incoming serial buffer to the amount of data you want to process at any given time (let's say 8ms?). Then the _newData event will only be thrown every 8ms without any data loss (if it does occur, it is unrelated to B4X, but a limit of the underlying system itself). Any immediate processing can be done at that time and any additional processing can then be pushed off via a strategic CallSubDelayed (such as displaying the data, storing the data, etc).
 

emexes

Expert
Licensed User
Augmentez simplement le tampon série entrant à la quantité de données que vous souhaitez traiter à un moment donné (disons 8 ms ?).

Si tous les paquets de données doit être traité et que le temps de traitement d'un paquet est plus long que la durée du paquet, la mise en mémoire tampon ne sera d'aucune utilité, si ce n'est qu'elle augmentera le court sentiment de réussite :) avant que la mémoire tampon ne finisse par déborder :oops:
 

emexes

Expert
Licensed User
tout traitement supplémentaire peut ensuite être repoussé via un CallSubDelayed stratégique (comme l'affichage des données, le stockage des données, etc.)

Mais j'ai bien aimé votre idée d'enregistrer la lecture la plus récente dans une mémoire tampon, puis de mettre à jour l'écran à partir de cette lecture une seule fois par rafraîchissement de l'écran.

L'utilisation d'une minuterie comme substitut au rafraîchissement de l'écran pourrait introduire un décalage (en moyenne) d'une demi-période de rafraîchissement de l'écran, mais il s'agit d'environ 10 ms, ce qui, dans le processus de l'œil à la pensée, s'arrondit à zéro. 🙃
 

fgh3966

Active Member
Licensed User
Bonjour
Désolé pour ces changements >>> Est-ce que "17 octets se terminant par la valeur d'octet 251" est la réponse finale ?
Oui, 17 octets se terminant par la valeur d'octet 251 est bien la réponse finale

j'ajuste les variables
Dim ExpectedPacketLength As Int = 19 a 17 'probably wrong but will be updated when valid-looking packet is received
Dim ExpectedLastByte As Byte = 0xF9 a 0XFB 'ditto
 
Top