• L'Assemblée Générale du Prius Touring Club aura lieu le 7 décembre 2024 du côté de Rennes. Si vous êtes adhérent renseignez-vous ici.

elm327 BT / Android

  • Initiateur de la discussion Initiateur de la discussion priusfan
  • Date de début Date de début
@planetaire:
après 7EA 10, quel est le groupe suivant (c'est le nb d'octets de la réponse)?





PS attention, je suis en train de réorganiser les séquences pour le système hybride (7e2)
de façon à avoir 2 groupes homogènes:
1 à interroger aussi vite que possible:
21 61 62 67 68 74 8A
l'autre contenant des variables à variation lente (SoC et températures pour lequel une fréquence de 1 fois par minute devrait suffire):
21 01 70 71 87 98
 
Dernière édition:
Deux exemples de réponses:

Au démarrage première trame
7EA 10 27 61 C3 3F FF 0F A0

En roulant première trame
7EA 10 27 61 C3 3F FE 12 54

D'après la doc de berkeley on a sur les 4 octets de droite : les tr/mn puis les Nm de MG2.
(Tr/mn avec un ofset de 16383, Nm ofset de 500)

Le 27 en rouge doit être le nbre d'octets de la réponse = 39 en décimal

Octets utiles = 4 + 5*7 = 39 (Mais 4 utilisés dans la dernière trame)
 
distinction auto P2 / P3

en réponse à
AT SH 7E2
21 C3

réponse P2
7EA 10 27 61 C3 etc.....

7EA réponse à 7E2 (=7E2 + 8 )
10 1ère trame d' un message multitrame
27 nb octets de la réponse effectivement 39
61 reponse à un 21 (=21 + 40)
C3 réponse à C3

la p3 répond très différemment

7EA 03 xx xx xx

7EA réponse à 7E2 (=7E2 + 8 )
03 nb octets de la réponse

les 6 premiers caractères (dont l'espace) suffisent donc à caractériser une P2 ou une P3.

CQFD
 
séquence de commandes et décodage

J'ai modifié la séquence de commandes et mis au clair les règles d' extraction des variables.

il y a 5 demandes
2 en rapide
2 en fréquence moyenne (1 minute ?)
1 en fréquence lente (5 minutes ?)

le tableau excel ci-joint résume l'ensemble.
je pense qu'il peut servir de modèle pour la P2.

@guinness:
petit pb de fermeture de l'appli,
elle ne ferme pas la liaison BT avec le dongle (le voyant vert reste allumé).
elle semble rester active: processmonitor la montre encore active aprés fermeture.
impossible de la relancer sans tout débrancher et rebrancher.

@suivre....
 

Pièces jointes

Dernière édition:
pb fermeture

Ouais, j'avais constaté ça effectivement; malheureusement la règle sur android est qu'on ne peut normalement pas fermer une appli, on ne fait qu'arrêter une (ou plusieurs) activités; je vais quand même tenter de corriger le fait que quand on fait Exit ça termine bien proprement la liaison BT et qu'on puisse redémarrer sans problème.

J'ai pas eu le temps de coder depuis ce week-end pour l'instant... :sad:

Edit: Merci pour le fichier précis, c'est exactement le genre de specs que j'attendais, on verra si j'ai des questions au moment de l'implem...

Pour la fréquence, étant donné qu'on est limité par la vitesse de transmission BT, je pensais demander en permanence des requêtes et jouer sur la périodicité de certaines requêtes (plus facile à implémenter que d'essayer de respecter une certaine fréquence, un genre de "best effort", quoi) .
Quelqu'un voit-il une objection à ce style d'implem (ça ne pose pas de pb aux ECUs d'être sollicitées en permanence?)?
Le problème que je vois avec cette implem c'est que les demandes moins fréquentes seront demandées deux fois moins souvent en fonction du dongle BT que les gens auront achetés (mais il y a deux solutions à ça: la première est de changer la périodicité à la main dans le fichier xml, la deuxième est d'adapter la périodicité dans notre code, en fonction des vitesses de réponse constatées).
D'ailleurs petite question sur la température des Inverters, ça suffit de la surveiller une fois par minute?
 
...Pour la fréquence, étant donné qu'on est limité par la vitesse de transmission BT, je pensais demander en permanence des requêtes et jouer sur la périodicité de certaines requêtes (plus facile à implémenter que d'essayer de respecter une certaine fréquence, un genre de "best effort", quoi) .

Qu'est ce que tu entends par en permanence ?
Tu as forcément une limitation qui est: pas de demande tant que la précédente n'a pas eu sa réponse complète.
Quand j'utilisais Tactrix, c'est ce que je demandais aux Ecu: dès la fin d'une réponse, hop question suivante. Résultat 2050 pid reçus (sollicités+passifs) par seconde au lieu de 1166 sans les sollicités. Les Ecu ont répondu pendant des milliers de km sans problème, sur ma P2.
D'ailleurs petite question sur la température des Inverters, ça suffit de la surveiller une fois par minute?
C'est hélas trop lent. La température des inverter monte en quelques secondes ! Par exemple en une dizaine lors d'un dépassement musclé.

A+ ;-)
 
saturation ECU ?

réponse de Rodin (alias mr hybride toyfrance).

j'avais le même type d'inquiétude et lui avais posé la question de vive voix lors de mon essai de la p3 plugin.
je lui avais demandé si nos pcm et autres manips génaient toy france d'une part et si l'on risquait de saturer les ECUs.
il m'avait répondu : a) vos manips c'est marrant b) qu'est ce que vous croyez que l'on fait lorsque il y a un pb sur une voiture???
cela ne vaut pas une bénédiction et évidemment est sans garanties.

fréquence de collecte de ma zone orange: pas grave on change la fréquence...
 
youhou !

Dongle reçu ce matin ! Merci ! :jap:

J'ai maintenant de quoi tester un peu plus sérieusement en attendant le renouvellement du stock. :ovation:😉

Edit: Pour les noms servant à distinguer les différents modèles, il vaut mieux que j'utilise les numéros de moteur (2ZR-FXE et 1NZ-FXE) plutôt que ceux du chassis (ZVW30 et XW20), non?
Bon y aura des commentaires pour ceux qui ne connaissent par les modèles par coeur, hein!
 
Dernière édition:
weekly report ;-)

Bonsoir à tous,

Alors le week-end a été moins fructueux que prévu, mais j'ai quand même committé quelques changements:
  • Normalement on doit pouvoir faire Exit puis relancer l'appli et se connecter (même si en fait l'appli ne se ferme vraiment qu'à la discrétion du système),
  • J'ai commencé à jouer avec les menus mais je n'ai encore rien implémenté.
  • J'ai essayé de faire en sorte de minimiser la quantité de nourriture qu'on donne au garbage collector (même s'il reste encore du boulot!), mais il faut être prudent car en multithread on a vite fait des bêtises (d'ailleurs j'ai des soucis avec mon code pour debugguer sans voiture, heureusement que priusfan me prête son dongle bleu)
  • Je n'ai pas eu le temps de faire le parsing XML des fichiers de commande ni la détection du type de HSD, par contre j'ai quand même créé la structure de classes dynamiques pour interpréter les réponses (PIII only pour l'instant).
  • Et enfin, j'ai implémenté la récupération des bytes utils pour les réponses dans un tableau à une dimension.

C'est tout pour cette fois. Celui qui veut s'amuser peut commencer à jouer dans Decoder_2ZR_FXE.decodeResponse() pour commencer à interpréter les réponses...
A suivre... :coolman:
 
weekend studieux et prolifique :jap:.

je viens de commencer à regarder et j'ai une chtite question dans CommandResponseObject et plus précisément dans getResponsePayload.
je n'ai pas compris comment tu arrives à sauter systématiquement les 2 premiers groupes de chaque trame (ligne) ; je vois dans le code un trt spécifique uniquement pour le "10" de la première ligne.
en fait, toutes les lignes doivent subir exactement le même régime, (cf posts 193 &194 )
càd ignorer les 2 premiers groupes (ou commencer à analyser depuis position 8)
à la limite récupérer systématiquement avec offset démarrant à 2 dans cette partie:
Code:
    // Convert each two-digit string into the corresponding byte:
                    for (int k=offset; k<hexaStr.length; k++) {

maintenant, j'ai peut-être loupé qqc; pour moi, le juge de paix sera de consulter le contenu de res après trt de plusieurs type de trames...

demain , il fera jour
 
brainfart

Bien vu: le coup de fatigue était pour moi 😳 j'ai codé ça ce matin très tôt ou hier soir très tard, ça dépend comment on regarde.
En fait dans ma tête je voulais lire la longueur (byte suivant 10) et ne pas mettre la longueur dans le résultat; puis j'ai relu ton post et j'ai vu que tu voulais simplement tous les bytes après les 7Ex xx, et j'ai oublié d'enlever mon début de dev (où offset aurait du être à 2 au départ).
Du coup j'ai simplifié le code après effacement de mes noeuds au cerveau insomniaque...

PS: Il y a sans doute d'autres bugs, j'ai pas eu beaucoup de temps pour tester (d'ailleurs j'étais à Osny ce matin chez Block-Out, j'aurais presque pu passer te rendre ton dongle car le mien est à la poste, mais j'avais pas encore testé)
 
optimisation débit / moins de boulot pour le GC....

maintenant que l'on sait que la partie interro / réponse est de trés bonne qualité, je propose de passer à l'optimisation pour améliorer le débit en ne demandant plus la transmission des espaces intercalaires ni du \r dans les réponses.
concrètement dans l' Init

AT S0 au lieu de AT S1 (valeur par défaut).
AT L0 au lieu de AT L1

conséquences au niveau du décodage:

  • inutile de procéder à:
Code:
// First, remove parasitic '\r':
                String temp = getResponseString().replaceAll("\\r", "");
autant de boulot en moins pour le GC

  • là où cela devient un peu plus velu,(mais une fois au point, on n'y touche plus): le décodage de la réponse complète sera effectué en "crawling" en jouant à saute mouton dans la réponse complète, sans passer par un "split"; autant de boulot en moins pour le GC
je vais tester qqc dans ce sens.


 
Woow ! Ça avance vite 😎. Je suis encore dans la gestion des aiguilles avec un dev à part. Dès que j'ai fini, on en discute pour que je puisse fournir ce qu'il faut pour la partie graphique.
 
propal version alpha de crawler:
Code:
            try {
                // each frame should contain exactly 20 car: 3+ 8*2 + "\n"
                int nf=getResponseString().length()/ 20;     // nf = number of frames
                for (int nl=0; nl<nf; nl++) {                // nl= frame number
                    int start=nl*20+5;                        // start with the 6th car
                    for(int bb=0;bb<7;bb++){                // bb est le couple à traiter
                        int pos = start + bb*2;                // pos est la position dans la chaine du couple à traiter
                        _formattedBytesResponse.put((byte) ((Character.digit(getResponseString().charAt(pos), 16) << 4)
                                + Character.digit(getResponseString().charAt(pos+1), 16)));
                    }
                }
à affiner certainement.....
 
Dernière édition:
Pas trop le temps là tout de suite, mais remarque rapide, si on veut enlever la nourriture de la bouche du GC alors il vaut mieux éviter d'appeler getResponseString() et travailler directement sur le Buffer (je ferai ça après coup si vous voulez).
Par ailleurs, pour éviter les bugs liés au multi-thread tout en diminuant les objets créés, je vais changer la méthode pour que le ByteBuffer soit fourni par l'instance qui appelle plutôt que stockée dans la classe (comme on ré-utilise les instances de Command, c'est une source de bug).

Je me limiterai ensuite sur les changements pour la perf tant qu'on n'aura pas benchmarké un peu (car comme il y a du JIT compiling, on n'est pas forcément maitre des meilleures optim comme on peut l'être en C++, il vaut donc mieux benchmarker pour voir ce qu'il faut vraiment optimiser).

Pour la partie graphique, effectivement on s'approche du fait d'être capable de communiquer des infos de mesures à l'UI (je compte utiliser l'API native android sendMessage pour chaque ensemble de résultats qu'on collecte - car plusieurs résultats par commande), donc c'est pour bientôt ! 8)
Dans un premier temps je ferais une page avec juste des champs texte mis à jour, et on pourra migrer vers de beaux graphiques dès qu'ils seront prêt.

On verra au final si on est moins gourmand que Torque qui me bouffe 40% de la batterie de mon Nexus S pour l'instant.

PS: FX, est-ce que tu sais lire les infos de voltage de chaque groupe de module de la batterie HT? c'est possible depuis ce bus ou bien il faut un autre protocole pour ça?
 
PS: FX, est-ce que tu sais lire les infos de voltage de chaque groupe de module de la batterie HT? c'est possible depuis ce bus ou bien il faut un autre protocole pour ça?
bonne question...
réponse 1: avec un interface tactrix et le logiciel officiel techstream OUI.
réponse 2:
je pense que c'est jouable depuis l'interface actuelle, en changeant de protocole, càd en passant en KWP2000 à 9600bps.
par défaut ce protocole suppose une vitesse de 10.4 kbps, amha, c'est pourquoi ce protocole n'est pas retenu automatiquement.

le sniffer que j'ai développé et utilisé, il y a un an, ne supervisait que le can, et il n'y avait rien à voir lorsque l'on interrogeait la batterie.

@suivre

je serais de moins en moins dispo jusqu' à fin mars...
 
Il n'y a pas urgence, c'est pour surveiller le vieillissement de ma batterie sur le long terme, donc on pourra regarder ça (bien) plus tard; le fait d'être à 9600 bauds sur un autre protocole ne me gêne pas car ça sortirait du cadre des devs actuels (on pourrait avoir un autre écran (ou des logs dans un fichier) dont on se servirait pour ne surveiller que certains paramètres de temps en temps).

Edit: Bon j'ai committé cette nuit quelques modifs dont le code de PriusFan (sans le getResponseString()). Ca a l'air de marcher correctement.
J'ai corrigé le bug du chargement de la classe dynamique pour décoder (a marchait pas 😳).
En tout cas j'ai pu comparer en mode debug (avec simu des réponses) que le fait d'utiliser des CharBuffer/ByteBuffer accélère notablement le code, donc ça paye bien.
Dans le code actuel on peut avoir des soucis si les commandes se déroulent plus vite que ce qu'on arrive à décoder (car on ré-utilise un seul objet par commande), mais c'est peu probable en BT à mon avis!

PS: J'ai reçu mon OBDLink BT, effectivement c'est bcp plus encombrant que le dongle bleu (qui lui était vraiment le top en terme d'encombrement), mais c'est aussi bcp plus évolué (on peut mettre à jour le firmware, ça va bien à 115200 baud, backup en USB si besoin et LEDs pour voir ce qui se passe).
FX, Je te renvois ton dongle cette semaine, merci pour l'interim :jap:
 
Dernière édition:
youhou!

Alors c'est pas encore committé et il reste plein de trucs à faire, mais ce matin j'ai fait le trajet domicile travail en utilisant mon "BT HSD Monitor" sur un Nexus S et il m'affichait correctement en temps réel les infos suivantes: ICE RPM, ICE TEMP et Batt Amps 😎 😀

D'ailleurs pour les ampères c'est vraiment bizarre les données quand on glide en N (ça oscille pas mal sous les 10 Amp)...

Pour l'instant je n'ai que des infos sous forme de texte, j'attends de l'aide pour améliorer le graphisme, mais pour valider en live les moulinettes de récupération d'info c'est déjà pas mal.
Si quelqu'un sait comment faire les changement d'écran en faisant glisser le doigt (à la torque), ça serait pas mal.

J'ai pas encore committé (ce soir ou demain), j'éditerai ce post quand ce sera fait.
PS: Il y a encore pas mal de bugs et de décodage à finir, et j'ai toujours pas fait la config en xml...
 
bravo,
je pense que si tu arrives à superviser correctement les Amp, techniquement le + dur est fait;
pour info, l'oscillation me semble normale,
vérifie l'excursion:
tu dois aller d'une conso max de 150 A à - 100 A en regen (ordre de grandeur).
 
Je confirme les ordres de grandeur.

Ca ne devrait pas être trop dur de faire la même chose pour la PII dans une classe dédiée, par contre j'ai pas encore implémenté la détection du type de HSD, donc il faudra changer le nom de la classe à charger (pour l'instant dans une string en dur) dans ResponseHandler.java

Je vais essayer de coder le torque et la vitesse de MG1 (j'ai un glide en N dans les 80 km/h sur mon trajet de retour 8)) pour le retour de ce soir.
Je vous préviens quand c'est committé (je créerai la classe pour la PII, y aura plus qu'à modifier le code).

PS: FX, j'ai toujours ton dongle, pas eu le temps de m'arrêter à la poste, je te le renvoie la semaine prochaine.
 
@guinness:
je ne connais quasiment pas java, mais il y quand même un truc qui me semble louche ici:
Code:
            try {
                // Reset the buffer:
                response.rewind();
                // First, remove parasitic '\r':
                //String temp = getResponseString().replaceAll("\\r", ""); // No longer needed thanks to ATL0

                // split("\n") would be easier to read but feeds the GC...
                // each frame should contain exactly 20 char: 3+ 8*2 + "\n"
                int nf=_rawStringResponse.length()/ 20; // nf = number of frames
                for (int nl=0; nl<nf; nl++) {           // nl= frame number
                    int start=nl*20+5;                  // start with the 6th char
                    for(int bb=0;bb<7;bb++){            // bb est le couple à traiter
                        int pos = start + bb*2;         // pos est la position dans la chaine du couple à traiter
                        response.put((byte) ((Character.digit([B]_rawStringResponse[/B].charAt(pos), 16) << 4)
                                            + Character.digit([B][COLOR=Red]getResponseString()[/COLOR][/B].charAt(pos+1), 16)));
                    }
                }
à la place du machin en rouge, j'aurais bien vu _rawStringResponse (ou inversement)...

ps: le machin bleu attendra une rencontre IRL...:-x
 
Ooops (y en aura surement d'autres car j'ai codé un peu vite)

Effectivement, bien vu, le but était de se débarrasser de getResponseString() et j'en ai oublié un (mais ça marche quand même car on récupère bien le bon byte).

J'ai pas encore testé le profiling sous eclipse donc il reste sans doute du boulot pour l'optim, mais en tout cas les perfs sont là pour une visu en live...

Mon code n'est pas encore committé, donc encore un peu de patience...
 
Excellentissisme !
Ben j'attends le commit pour commencer le boulot en P2 et vérifier si je peux aider au niveau du graph. Ce ne sera pas simple le graph néanmoins !
 
une petite remarque:
il me semble fort utile de continuer à logger (éventuellement paramétrable) l'intégralité des demandes/réponses sur sdcard; en effet il reste pas mal de "zones blanches" dans les réponses, et avec le recul, il sera peut-être possible de leur trouver un sens, je pense en particulier à l'injection (qui sert au calcul de conso) qui poserait pb en cas de frein moteur.
d'après certains gusses de priuschat, l'injection serait parfois présente à tort...
 
Pages vues depuis le 20 Oct 2005: 316,285,603
Retour
Haut Bas