PCM pour MBED

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Bien, bien, bien

CA MAAAARCHE

Pour pcm, j'ai besoin de pas mal de pid.
En enlevant les octets inutiles, j'arrive à faire passer 800 trames par seconde. Je pourrais même monter à 1200 trames. Après buffer overflow assuré.

Le MBED lit ces trames à la vitesse de 1 toutes les 8 microsecondes, mais pour la traiter et la renvoyer il lui faut, avec la meilleure version de mon calcul, 703 micro secondes.

J'avais un problème avec ta routine d'économie d'électricité (wait 0.5), car attendre 500000 microsecondes faisait remplir le buffer. Cela faisait 400 trames si je n'avais pas de chance. Bon il est vrai que mon premier calcul était aussi responsable, il prenait 2200 microsecondes par trames, et ne permettait de passer que 450 trames par secondes pour 800 qui arrivait. Buffer overflow assuré.

J'ai souffert. Mais je suis content.
 

planétaire

Participant hyperactif
Inscrit
4 Fév. 2008
messages
8,846
Score de réaction
4,967
Localisation
Caldera d'Ecouves
Véhicule
Prius 2 lithium et d autres VE
...
Le MBED lit ces trames à la vitesse de 1 toutes les 8 microsecondes, mais pour la traiter et la renvoyer il lui faut, avec la meilleure version de mon calcul, 703 micro secondes.
... J'ai souffert. Mais je suis content.

Super. :youpi: 8 microsecondes c'est hyper-super-méga rapide. S'il ne faisait que cela il passerait son temps à attendre, on n'a "que" 1600 trames passives par seconde !

Pour accélérer les calculs on trouve toujours des astuces. Cela peut par exemple aller jusqu'à dupliquer des instructions plutôt que de boucler.
On augmente la taille du programme au profit de la vitesse d'exécution.
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Super. :youpi: 8 microsecondes c'est hyper-super-méga rapide. S'il ne faisait que cela il passerait son temps à attendre, on n'a "que" 1600 trames passives par seconde !

cela ne servirait surtout à rien. Car si c'est pour les jeter ensuite, car le buffer ne tiendrait meme pas 0,3 seconde.

Mais effectivement, heureusement qu'il passe peu de temps là, car il m'en reste suffisamment pour les renvoyer en bluetooth.
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Nouvelle version: je stocke quelques données en local. Pour l instant, une ligne par démarrage/arrêt : distance, litre, température. Je vais ajouter d autres données sous peu comme la 12v au démarrage, le Soc au démarrage, ...
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
ajouter n'importe quelle trame semble créer le problème.
mais je vais vérifier

j'ai un autre problème, difficile à détecter, mais le pid 230 le permet. J'ai des trames qui s'inversent (ce pid ne devrait qu'augmenter)

Line 26612: 2303E7402000000ED
Line 26629: 2303E7602000000EF
Line 26644: 2303E8202000000FB<---
Line 26647: 2303E7702000000F0<---
Line 26665: 2303E8302000000FC
Line 26684: 2303E8402000000FD
Line 26702: 2303E8602000000FF
Line 26720: 2303E870200000000
Line 26738: 2303E890200000002
Line 26757: 2303E8B0200000004
Line 26775: 2303E8C0200000005

cela m'arrive très fréquemment
est-ce du à ma lecture par PCM du MBED, ou à ce que moi j'envoie du MBED, ou aux données que je récupère dans le MBED pour les envoyer ? il me reste à investiguer.
il faudrait que je regarde si j'en ai en log = 1

J'avais évoqué ici des trames inversées, il me semble que j'ai aussi des trames en double et des trames manquantes. Ceci pourrait expliquer la bizarrerie concernant la consommation évoqué dans une autre thread (celle sur l'arrondi de la conso). Est-ce comme l'évoque Priusfan un pb de buffer en lecture coté Windows PCM ou est-ce un bug ou une limitation coté MBED CAN ? Ou encore un bug que j'aurais créé dans le ring buffer coté mbed en voulant contrôler le buffer overflow ? à suivre

Voici des traces du pid3C8 modifié, où j'ai entre autre mis à la fin les 6 derniers octets du timestamp en microseconde enregistré coté MBED au moment de la lecture du CAN.

3C8000000000000A049
3C8000000000001A052
3C8000000000002A12B
3C8000000000008A098
3C8000000000004A070
3C8000000000005A07A
3C8000000000006A085
3C800000000000CA323
3C8000000000008A098
3C8000000000009A0A4
3C800000000000BA0B9
3C8000000000012A296
3C800000000000DA0CC
3C800000000000EA0D7
3C8000000000015A11E
3C8000000000010A0EA

le désordre est évident
on voit qu'il manque une entre celle à 2A12B et à 4A070, celle à 3AXXX, car ces trames arrivent toutes les 64 ms (0x10000)
cette trame semble être remplacée par une arrivant plus tard, la 8AXXX, qui du coup serait en double.
mais par contre la AAXXX, est manquante, et pas remplacée.

maintenant que je peux écrire sur la sdcard, je vais logguer un peu coté MBED ou faire au moins des tests.
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Avec ma trame 520 modifiée, j'ai une partie de la réponse.
Après le 520, les 4 octets suivant représentent le volume consommé, les 8 octets suivants la somme (faite coté MBED) des volumes consommés, les 6 octets suivants le time stamp en microseconde au moment de la lecture du CAN par le MBED.

On peut voir que la somme est juste, trame après trame, donc ce n'est pas le Pc qui duplique les trames, mais elles sont comme dupliquées dans le buffer, pour qu'au moment où on lit le buffer pour envoyer au Pc elles sont en double (par exemple la stampée 11b066).

On peut aussi voir que quand il y en a une en double, parfois elle remplace une trame manquante en se basant sur le temps entre deux trames, qui est de l'ordre de 0,8 à 1 seconde, temps entre 20 tours de moteur, à environ 1200 tours minute. Ainsi la 11b066 est en double, mais elle est en trop et ne remplace aucune manquante, car il y a le "bon" temps entre 050711, 11b066 et 1ebfe0. Par contre, la 2c24fe est en double et semble remplacer une trame manquante. Et sans qu'il y ait doublon, il manque une trame avant la 71b2a6.

Bref des trames en plus, d'autres en moins, d'autres remplacées, pas étonnant que mon volume consommé soit faux par rapport à l'odb. Mais le plus remarquable, c'est que ces problèmes semblent peu affecter le calcul du volume par la méthode PCM (intégration en utilisant le pid 520 et le pid3C8 lui aussi chahuté).

520 04a2 000004a2 e050e6
520 036a 0000080c ec7964
520 03b6 00000bc2 f8b678
520 0381 00000f43 050711
520 0308 0000124b 11b066
520 0308 00001553 11b066
520 0320 00001873 1ebfe0
520 035d 00001bd0 2c24fe
520 035d 00001f2d 2c24fe
520 03c3 000022f0 479d07
520 03bf 000026af 559d99
520 03d4 00002a83 71b2a6
520 03f1 00002e74 7fb74a
520 01ef 00003063 8f38ad
520 01ef 00003252 8f38ad
520 0189 000033db 9fcd2e
520 0195 00003570 afe83c
520 0196 00003706 bf59ca
520 018f 00003895 ce5e5e
520 01be 00003a53 dccfa2
520 025a 00003cad ea6b7f
520 02aa 00003f57 f7fc09
520 02cb 00004222 05b88e
520 02e2 00004504 138525
520 02e8 000047ec 2179a6
520 02f6 00004ae2 2f8a36
520 02c7 00004da9 3daac7
520 0139 00004ee2 4de600
520 0139 0000501b 4de600
520 0000 0000501b 6f9fc1

Autre fait remarquable, ce cahot semble s'arrêter au bout de quelques minutes (2-3 ) pour un trajet d'une vingtaine de minute. C'est d'ailleurs ce que j'avais constaté concernant la conso odb qui ne continuait pas à diverger comme elle le faisait au début du trajet, mais semblait devenir conforme.

Je vais regarder si le cahot s'arrête aussi coté pid3C8
 

priusfan

darwiniste
Prius Touring Club
Inscrit
22 Oct. 2005
messages
6,545
Score de réaction
9,446
Localisation
conflans ste honorine
Véhicule
Ioniq5
communique moi ton projet mbed, je jetterai un oeil neuf sur la gestion du ringbuffer.
pour info, gary utilise un RB de 2048 entrées, mais en stockant de manière particulière la partie data[] dans une "memorybank" secondaire, cf son appli...
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Effectivement, j'observe bien la même chose.
J'affiche la différence entre les time stamps de 2 trames qui se suivent, pour chaque trame.
cahot.PNG

(j'ai tronqué à 300000 le graphe en y)
On peut voir que jusqu'au point 4800 environ (x 64 ms = 307 s = 5 min), c'est complètement cahotique. Des trames inversées, des trames dupliquées, des trames manquantes, à la pelle.
Et après cette période, jusque la fin du trajet (environ 33 min), par ci par là, une trame manquante (c'est le petit pic).
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Je suis inquiet avec ce bout de code
Code:
void can_check(void) {
    led3 = 1 ;
    tct = timer.read_us();
    
    while ( can2.read(can_MsgRx) ) {  <=====  cette ligne

        rb_write_pointer++ ;                //  increase write_pointer
        rb_write_pointer &= BUFFER_MASK;    //  loop if at end of array
en en particulier la ligne que j'ai marqué
en effet je boucle tant que je peux lire

mais ailleurs, j'ai
Code:
can2.attach(&can_check);
qui lance cette boucle quand il y a aussi quelque chose à lire

n'a-t-on pas le risque qu'il fasse les deux en parallèle ? et mette en buffer 2 fois la même ligne.
 

kinetik

Participant hyperactif
Inscrit
29 Mai 2011
messages
1,446
Score de réaction
797
Localisation
proche banlieue de Paris
Véhicule
Prius 2
J'avais évoqué ici des trames inversées, il me semble que j'ai aussi des trames en double et des trames manquantes. Ceci pourrait expliquer la bizarrerie concernant la consommation évoqué dans une autre thread (celle sur l'arrondi de la conso). Est-ce comme l'évoque Priusfan un pb de buffer en lecture coté Windows PCM ou est-ce un bug ou une limitation coté MBED CAN ? Ou encore un bug que j'aurais créé dans le ring buffer coté mbed en voulant contrôler le buffer overflow ? à suivre

Je n'ai jamais vu d'inversion sur le pid 230. Tu as un timestamp associé ?
Un bug dans un buffer me semble une bonne hypothèse.
As-tu essayé de mettre une seconde capture en paralllèle ?
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
C'est en cours.
 

guinness

Participant hyperactif
Inscrit
23 Juil. 2009
messages
510
Score de réaction
126
Localisation
Ile de France
Véhicule
Prius3 et Nissan Leaf
Je suis inquiet avec ce bout de code [..]

Pour se prémunir du risque évoqué, il suffit d'utiliser en variable globale un booléen, e.g. :
Code:
volatile bool inside_can_check = false;
qui est testé en début de fonction, si vrai on sort de suite, si faux on le met à vrai puis on exécute la fonction et on le met à false en sortie du while; ça coûte pas cher à tester en tout cas.
 

priusfan

darwiniste
Prius Touring Club
Inscrit
22 Oct. 2005
messages
6,545
Score de réaction
9,446
Localisation
conflans ste honorine
Véhicule
Ioniq5
can2.attach(&can_check) est utilisé une fois seulement à la fin de la routine init() et permet d'associer une routine à un "interrupt"; il n' y a donc aucun risque de ce coté là.

par contre, après analyse de ton appli, je constate que tu fais énormément de manipulations de strings pour générer des logs.

en effet, tu relaies toutes les trames reçues vers la log et je pense que cela pourrait bien saturer de ce coté...

combien de trames/sec balances tu vers la log??
envoies ton appli @guinness, il a l'oeil du pro pour cela (tout se passe dans main.cpp)
 

guinness

Participant hyperactif
Inscrit
23 Juil. 2009
messages
510
Score de réaction
126
Localisation
Ile de France
Véhicule
Prius3 et Nissan Leaf
C'est justement l'association avec l'interrupt qui l'inquiète: si l'interrupt se produit alors que l'on est déjà dans la fonction (par exemple en train de tester la fin du while et on voit que can2.read nous donne qqchose), alors l'interrupt lance a nouveau la fonction (mais dans ce cas can2.read devra retourner la suite de ce qui a été lu dans le premier appel) et on peut avoir une lecture hors séquence car ce n'est qu'en sortant de l'interrupt que le premier appel de fonction continuera à être exécuté.
Pas forcément très probable mais il faut toujours se méfier des choses non probables quand on programme, tester avec le booleen devrait éliminer cette hypothèse facilement...
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Et si pendant que je suis dans la boucle une nouvelle trame arrive et fait un interrupt ?

Mais comment le programme gère-t-il à la fois d'appeler can_check par interrupt, quand des données proviennent du bus Can, et d'un autre coté boucler tant qu'il y a des le données sur le bus Can ?

Intéressante ton idée de mettre un booléen pour simuler un singleton pour être sur de ne pas rentrer dans la boucle sans en être sorti.
 

guinness

Participant hyperactif
Inscrit
23 Juil. 2009
messages
510
Score de réaction
126
Localisation
Ile de France
Véhicule
Prius3 et Nissan Leaf
Mais comment le programme gère-t-il à la fois d'appeler can_check par interrupt, quand des données proviennent du bus Can, et d'un autre coté boucler tant qu'il y a des le données sur le bus Can ?

ça dépend de l'OS et/ou des options de compilations: soit on est en multi-thread soit on est en mode interrupt "pur" comme au temps de MS-DOS.
Dans le premier cas les deux vont s'exécuter en parallèle (éventuellement simulé si un seul processeur, c'est-à-dire que n instructions vont s'exécuter pour l'une des taches, puis k instructions pour l'autres, etc.); dans le deuxième cas la routine en interrupt interrompt la première qui ne reprendra que lorsque l'interrupt aura fini sa boucle (et si elle avit déjà fait le read alors elle travaillera sur des données en retard par rapport à tout ce qu'aura traité la partie interrupt.
Reste la question de deux appels simultanés à can2.read, est-ce que cette fonction est ré-entrante?
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
J'ai commencé des essais avec la boucle protégée par la variable volatile, et sans boucle mais aussi sans protection. Je pense qu'il faudra peut-être aussi essayer sans boucle et avec protection.

Voici du code pour comprendre :
(pour info je n'ai pas la led4 qui clignote, ni même s'allume, donc pas de buffer overflow)

Code:
volatile bool inside_can_check = false ;
volatile unsigned int rb_write_pointer = 0; // ring buffer write pointer
volatile unsigned int rb_read_pointer = 0;  // ring buffer read pointer
volatile unsigned int rb_data_size = 0;     // ring buffer number of entries

void can_check(void) { // called by interrupt

    if (!inside_can_check) {
      inside_can_check = true ;
      while ( can2.read(can_MsgRx) ) {

        rb_write_pointer++ ;                //  increase write_pointer
        rb_write_pointer &= BUFFER_MASK;    //  loop if at end of array
        rb_data_size++ ;                    //  ring buffer number of entries

        if ( rb_write_pointer == rb_read_pointer && rb_data_size == BUFFER_SIZE) {  // buffer overflow
            fprintf(stderr, "buffer overflow\r\n");
            led4=!led4;
            bufferoverflow=true;
            rb_data_size = 1;
            rb_write_pointer = 1;
            rb_read_pointer = 0;
        }       // error

 
        // add entries in the ring buffer
        second[rb_write_pointer] = timer.read_us();
        can_id[rb_write_pointer] = can_MsgRx.id & 0xFFF;
        msg_length[rb_write_pointer] = can_MsgRx.len;
        for (char i=0; i<can_MsgRx.len; i++) {
            data[rb_write_pointer][i] = can_MsgRx.data[i];
        } // for

      } // while
      inside_can_check = false ;
    }
} // can_check

int main() {
    init();  //  executes:     can2.attach(&can_check);
       
    while (1) {
        // read CAN messages from the buffer       
        if ( rb_data_size > 0 ) {               // new message is available
            rb_read_pointer++;                      // position to next
            rb_read_pointer &= BUFFER_MASK;         // loop if at end of array
            rb_data_size--;                         // update nbr of entries in the ring buffer

            // we store in w_vars the results : it is not funny to manage all these [][]
            w_id=can_id[rb_read_pointer];
            w_len=msg_length[rb_read_pointer];
            w_sec=second[rb_read_pointer];
            w_num=rb_read_pointer;
            for (int i=0; i<w_len; i++) {
                w_data[i]=data[rb_read_pointer][i];
            } // for

            wrkmsg();               //  decide what to do with the message  (w_vars)
            
        } //        end // if ( rb_data_size > 0 )
    } // while
} // main

Normalement je devrais avec ça protéger la lecture mais aussi le stockage des données dans le buffer.
Normalement si je rejette malencontreusement un accès à can_check la fois d'après il devrait lire ce qui a été raté, car il n'a pas fait de can2.read.
 

priusfan

darwiniste
Prius Touring Club
Inscrit
22 Oct. 2005
messages
6,545
Score de réaction
9,446
Localisation
conflans ste honorine
Véhicule
Ioniq5
cela me parait bien verrouillé :jap:

de mon coté, pour une simple question de consommation, je procèderai à des tests en rajoutant le délai initial dans le cas du "sleeping", càd quand le nb de trames est faible, car il parait qu'une boucle sans délai fait consommer + que lorsqu'il y a un délai... je vais donc insérer un ampèremètre dans l'alim pour chiffrer cela.
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
Bien, la conclusion c'est que ce n'est pas à la lecture du bus Can, ni au stockage (au moment du stockage) dans le ring buffer, que le cahot se produit. Par contre je perds une trame sur 300 environ en me basant sur l'écart prévisible entre 2 trames. Il faudra que je regarde plus tard à quoi c'est du. Mais ce n'est pas le plus grave. C'est le cahot le plus grave.

Je vais donc mettre plus de traces coté lecture du ring buffer. Mais le plus probable maintenant est coté communication bluetooth.
 

thierryb

Participant hyperactif
Inscrit
20 Janv. 2011
messages
1,968
Score de réaction
1,032
Localisation
Yvelines
Véhicule
Prius 2 sol pack ipa 2008 verte
de mon coté, pour une simple question de consommation, je procèderai à des tests en rajoutant le délai initial dans le cas du "sleeping"

T'inquiète. J'ai laissé le sleeping. Mais pour la démo c'était plus simple.

je vais donc insérer un ampèremètre dans l'alim pour chiffrer cela.

Ça m'intéresse. Regarde en le faisant dormir moins longtemps : 0,5 0,3 0,2 0,1 0,05 0,03 0,02 0,01 secondes
 
Pages vues depuis le 20 Oct 2005: 284,383,848
Haut Bas