TPE 2002/2003 Voiture télécommandée
|
|
|
- Roger Bénard
- il y a 10 ans
- Total affichages :
Transcription
1 TPE 00/003 Voiture télécommandée Sebastien Chapenoire Nicolas Viennot
2 ::Le sommaire Le TPE Dans le cadre des Travaux Personnels Encadrés 00/003, qui ont débuté au début du mois d octobre 00 et ce sont achevés à la fin du mois de janvier 003, nous avons réalisé une voiture télécommandée par ordinateur. Cette idée nous est venu au départ car nous sommes passionnés par la robotique, l électronique, l informatique et tous les domaines se rattachant autour de cela. Nous avons au cours de ces quatre mois conçu et créé en totalité un engin piloté par ordinateur. Nous avons essayé le mieux possible de réaliser un véhicule voué à l exploration, c est pourquoi la voiture est équipée d une transmission radio AM afin de pouvoir disposer d un rayon de manœuvre suffisant. Elle est aussi dotée d une vitesse relativement importante de 30 km/h, de suspensions dans l optique d explorer de multiples terrains et d une bonne autonomie de fonctionnement. Un gros travail de recherche a été obligatoire afin d acquérir les divers connaissances que...:: Introduction ::......:: Le sommaire ::... nous avons utilisé pour mener le projet à son terme avant même de commencer la conception des différentes parties de la voiture. Cette dernière s est étalée sur environ trois mois et il fut difficile de s organiser afin d optimiser le mieux possible le temps qui nous a été imparti. Nous avons perdu de précieuses heures dans beaucoup de domaines concernant la conception car il est difficile de cerner rapidement le travail à réaliser et les solutions techniques que nous avons utilisé, tant elles sont divers. La conception s est scindée en trois partie : la partie mécanique, la partie électronique et enfin la programmation. Une fois cela suffisamment entamé, nous avons pu commencer la réalisation de la voiture. Cette partie comprend l usinage des pièces mécaniques, la création des cartes électroniques et celle des programmes informatiques. La dernière étape fut l imposante partie de tests afin de coordonner la mécanique, la transmission radio, l électronique et la programmation. La Mécanique...:: L approche théorique ::... 4 Principe 4 Calculs du rapport de reduction 4...:: La conception et la réalisation ::... 5 Le chassis 5 La partie avant du chassis 5 La partie arriere du chassis 5 La partie moteur 6 Piece 6 Piece 7 Les axes 7 La plaque arriere 8 La partie avant 8 Le pivot 9 Le plateau 9 Attache d amortisseur 9 Le guide en translation 0 La plaque avant 0 L Electronique...:: Introduction ::......:: Le microcontrôleur ::... La base du montage Le choix du microcontroleur Le PIC6F876...:: Le programmateur ::... 3 Le programmateur standard 3 Le programmateur alternatif 3 Explications du schema 4...:: La télécommande ::... 5 Description de la transmission 5 Description des composants 5...:: La voiture ::... 6 Description de l environnement 6 Etude de la partie puissance 6 Etude de la partie logique 7...:: Les circuits électroniques ::... 9 Fonctionnement de Protel 9 Les modules Aurel sur un PCB 9 Le routage 9 Les nappes d interconnection La programmation...:: Introduction :: :: Le PIC6F876 ::... 3 Les ports 3 L horloge 3 Les registres fondamentaux 3 Presentation des projets 3 Les instructions 4 La RAM 5 La pile d appels 7 Les interruptions 7 Les modules 7...:: Le programmateur de PIC ::... 3 Introduction 3 La programmation des PICs 3 Les protocoles 3 Le logiciel PC 3 Le code source (PIC) 33 Le code source (PC) 43 Main.cpp 43 Hex.h 46 Hex.cpp 47 Com.h 49 Com.cpp 49 Pic.h 5 Pic.cpp 53...:: La voiture :: Introduction 57 L alimentation des moteurs 57 Les capteurs de vitesse 57 Les freins 57 La transmission 58 CRC.h 58 main.c 58 Le logiciel PC 63 Main.cpp 64 Perf.h 70 Perf.ccp 70 Module.h 7 Module.cpp 73 Com.h 75 Com.cpp 75 Engine.h 78 Engine.cpp 78 Fps.h 79 Fps.cpp 79 Graph.h 80 Graph.cpp 8 Input.h 84 Input.cpp 84 Recorder.h 85 Recorder.cpp 86 Speed.h 89 Speed.cpp 89 Stats.h 90 Stats.cpp 90 TPE 00/003 - Voiture Télécommandée
3 La mécanique Sebastien Chapenoire
4 La Mécanique ::L approche théorique...:: L approche théorique ::... Principe Le premier travail auquel nous nous sommes attachés a été d établir les différentes fonctions que devait remplir la voiture au niveau mécanique, dont voici la description. Nous avons prévu au départ que la voiture ait une vitesse maximale de 30 km/h. Nous avons donc essayé de nous en rapprocher le plus possible aux moyens des éléments déjà existant dans le commerce, c est à dire les moteurs, les pignons et les roues dentées. Cette vitesse est à notre avis relativement acceptable car elle permet de nombreuses performances très correctes étant données les solutions techniques retenues. Nous pensons en effet qu il est déjà compliqué de faire avancer très précisément un tel engin, c est pourquoi nous avons trouvé ce compromis. Certes il existe beaucoup de voitures électriques modèle-réduit ayant des vitesses bien UN moteur GZ-600 BB supérieures, mais il s agit pour notre projet d un prototype et nous préférons créer entièrement la voiture, plutôt que de récupérer des éléments tels qu une plate-forme de modélisme, un châssis déjà fabriqué, et ainsi ne faire que modifier un engin déjà existant. Rentrons maintenant plus en détails dans les solutions techniques du projet. Nous avons opté pour une propulsion de la voiture et pour un contrôle de la direction par différentiel, c est à dire par modification du rapport cyclique des deux moteurs à courant continu, ou plus simplement en faisant varier la vitesse d une des roues par rapport à l autre, forçant ainsi le véhicule à tourner. C est le principe que l on peut retrouver sur de nombreux engins de chantier à chenilles. Ainsi la voiture pourra pivoter sur elle-même autant en marche avant qu en marche arrière en faisant tourner les roues arrières en sens contraire l une par rapport à l autre. Cette solution technique a été préférée au banal système de direction que l on retrouve sur toutes les voitures, c est à dire une crémaillère ainsi qu un système de tringlerie, qui réduit le champ des manœuvres en raison du rayon de braquage. De plus ce type de direction une crémaillière requiert l ajout d un servo moteur, élément assez onéreux pour l utilisation qui en est faite dans notre projet. Ayant choisit ce type de motorisation, il était donc obligatoire de penser à créer un système destiné à permettre la rotation des roues avant sans difficulté, puisqu elles ne sont pas motorisées, ce qui sera décrit ultérieurement dans le dossier. Autre élément important à prendre en compte, le véhicule est entièrement suspendu au moyen de quatre amortisseurs à pression d huile équipant chacun une roue de la voiture, et relié au châssis grâce à une pièce usinée, détaillée plus tard dans la partie mécanique. Cependant la partie moteur est dite non suspendue, c est à dire qu elle décrit les mêmes trajectoires que les amortisseurs, ce qui peut paraître contraire aux principes mécaniques qui conseillent d avoir le moins possible de masse non suspendue dans un ouvrage tel que le nôtre. Nous aurions pu suivre ces conseils, mais il aurait fallu pour cela utiliser une transmission à cardan ce qui impose une conception un peu plus complexe et des pertes énergétiques par frottements supplémentaires. On peut considérer que dans notre cas, compte un amortisseur tenu du poids de la batterie, la masse non suspendue de la partie motrice est faible, donc relativement négligeable. Nous voulons aussi disposer d une bonne autonomie de fonctionnement, c est pourquoi la voiture est équipée d une batterie au plomb gélifié d un poids de,8 kg, ce qui représente une masse importante pour la taille du véhicule. C est l élément le plus volumineux, il a donc été préférable de la placer judicieusement, ce qui sera précisé plus loin dans le dossier. Les parties Sealant Negative Plate Electrolyte Retentive Separator Positive Plate Terminals Relief Valve Top Cover Cover Container l impostante batterie usinées de la voiture sont quasiment toutes réalisées en aluminium, mise à part la carrosserie qui sera faite en résine transparente et les axes qui sont en acier pour une meilleure solidité. Calculs du rapport de reduction Les roues montées sur la partie moteur de la voiture ont un rayon de 37,5mm. On dispose de moteurs à courant continu les roues à denture droite ayant une vitesse maximale de rotation nominale de 3000 tr/min et un couple moteur de 4,5N.cm. La vitesse maximale à atteindre est de 30 km/h ( = 8,33 m/s). Le périmètre de la roue est P = 35,6 mm. Donc sans réducteur, la vitesse maximale est V = 3000 x 35,6 / 60 = 5,04 m/s. Cette vitesse est bien évi- La courbe de charge du GZ-600 BB 4 TPE 00/003 - Voiture Télécommandée
5 ::L approche théorique La Mécanique demment trop grande et le couple développé par les moteurs est bien trop faible, c est la raison pour laquelle il faut un réducteur afin tout d abord de réduire la vitesse et d augmenter le couple. On peut calculer le rapport de réduction dont on a besoin : r = 5,04 / 8,33 = 6,. Il faut donc un système réduisant la vitesse d environ six fois. Pour cela, nous avons sélectionné deux roues dentées afin de réaliser ce réducteur : une roue de dents et une roue de 7 dents. On peut vérifier la conformité de ce choix avec la formule : R = - x /7 = -/6. Ce résultat signifie que la fréquence de rotation est divisée par six et que le sens de rotation à la sortie du réducteur est inversé par rapport à celui de l axe du moteur. Au niveau de l augmentation du couple, la raison (rapport de réduction) étant de -/6, le couple devrait en théorie être multiplié par six. Cependant, en raison des pertes dues aux divers frottements, l augmentation est en moyenne multipliée par 0,75. Donc k = 0,75 x 6 = 4,5. Le couple moteur nominal est de 4,5 N.cm, donc théoriquement, le couple exercé sur la roue est C = 4,5 x 4,5 = 9,N.cm. Puis on peut calculer le couple afin de savoir si ce rapport correspond bien à notre demande. On fixe le temps d accélération pour atteindre les 30 km/h en 5 secondes. Donc l accélération est de ф = 8,33 / 5 =,66m/s². Grâce au théorème du centre d inertie, on peut déterminer la force appliquée à la roue. Ainsi F = m x ф, m étant la masse du véhicule. Nous l avons évalué à 3,5kg. Ainsi, F = 3,5 x,66 = 5,8N. Grâce à cette valeur, on peut désormais déterminer le couple exercé. C est en réalité le moment de la force F, c est pourquoi il faut utiliser le rayon de la roue. C = F x R = 5,8 x 0,0375 = N.cm, ce calcul est valable pour une roue, donc avec les deux roues, on obtient un couple de 40N.cm. Ainsi, on assure la possibilité de monter des pentes sans problèmes. De toutes les manières, les valeurs utilisées dans calculs précédents ne sont pas définitives car il va s en suivre une grosse partie de tests qui fixera ces résultats définitivement. Sur la courbe caractéristique du moteur, on voit que le couple maximal fournit peut dépasser la valeur nominale donc les tests nous promettent de bien belles surprises....:: La conception et la réalisation ::... Toutes les pièces usinées du véhicule ont été au préalable conçues sur papier, puis elles ont été dessinées sur le logiciel SolidWorks 00. Tous les dessins et les vues en perspective inclus dans ce dossier proviennent de ce logiciel. Le chassis Nous avons choisi après plusieurs semaines de réflexions de réaliser un châssis ressemblant à celui d un véhicule deux roues, c est à dire basé sur une forme triangulaire, pour plus de solidité. Les fixations qui engendrent des problèmes de solidité sont ainsi réduites ainsi que le nombre de pièces, contrairement à la solution envisagée ci-après, dans laquelle nous avions conçu un châssis très simple basé sur une plate-forme où venait se greffer une armature permettant la fixation d autres éléments. Le châssis est réalisé entièrement en aluminium à partie de plaques de 3 mm d épaisseur. Il se compose de différentes parties fixées entre elles au moyen d un système vis/ écrou indesserrables, dans l optique de résister aux vibrations lors du déplacement de la voiture. Les écrous sont équipés pour cela d un anneau de Nylon (Nylstop) qui permet d empêcher le desserrage des pièces. On a préféré cette solution à la place de rivet pop car on aura certainement besoin de changer ou de modifier certaines pièces en vue de futures améliorations et donc de démonter le châssis. Les plaques ont été découpées, évidées à des endroits précis pour créer les logements de certains composants, puis pliées. Des perçages ont été réalisés afin de permettre la fixation des différents éléments qui viendront composer la voiture. La partie avant du châssis La partie avant du chassis Elle est donc entièrement réalisée en aluminium, matériau léger, facile à travailler et relativement solide. Elle est fabriquée en plusieurs étapes. D abord vient le découpage à la forme voulue, puis viennent les évidements pour la batterie et le pliage. Il y a trois traits de pliages. Les trous réalisés ont un diamètre de 3 mm. La batterie est soutenue dans son logement grâce à deux barres d aluminium de 3 mm d épaisseur et de 0 mm de largeur, coudées à 90, et pliées à une des extrémités afin de permettre la fixation par deux plans parallèles. On peut remarquer que le logement de la batterie est situé le plus au centre et le plus bas possible afin d abaisser au maximum le centre de gravité du véhicule dans l optique de réduire le déséquilibre et l inertie de la voiture lors de changements de direction. La partie arriere du chassis Cette partie vient se rattacher à la partie avant du châssis par l intermédiaire de deux pattes de fixation situées à l arrière de la partie avant. Un évidement est placé au centre de la pièce afin de permettre le positionnement des moteurs ainsi que leur déplacement dû au débattement des amortisseurs. La pièce a été ensuite pliée à une des extrémités et sur toute sa largeur afin de pouvoir positionner et fixer les attaches d amortisseurs. La partie arrière du châssis TPE 00/003 - Voiture Télécommandée 5
6 La Mécanique ::La conception La partie moteur La partie moteur est composée de deux entités identiques. Elles sont chacune composées d un moteur fonctionnant par différentiel l un par rapport à l autre fixé à des pièces entièrement similaires. Toutes les pièces de la partie moteur sont donc en double exemplaires dans la voiture. Il faut de plus accorder une précision plus particulière à tous ces éléments afin de respecter une parfaite symétrie au niveau de la partie motrice. En raison des performances que doit posséder la voiture, nous avons dû réduire la vitesse et augmenter le couple, et donc dû créer un réducteur (voir plus haut dans la partie calcul), ainsi qu un renvoi d angle afin de gagner de la place. C est pourquoi il a fallu concevoir une première pièce pouvant permettre la fixation du moteur ainsi que celle du pignon de dents et de la roue dentée de 7 dents l arrière de la voiture 3 Piece Cette pièce est au départ un parallélépipède en aluminium, puis nous avons usiné la pièce afin de créer une forme en L, tout d abord pour alléger la pièce, et ensuite pour permettre la mise en position du moteur grâce à un premier alésage ne demandant pas une grande précision contrairement au second destiné à contenir un roulement à billes. Voici donc quelques calculs permettant de concevoir B la pièce. Nous disposons de roues dentées de module 0,8. Afin de déterminer l entre-axe des deux engrenages, il faut donc calculer leur diamètre primitif respectif, car deux roues à denture droite utilisées dans n importe quel système B-B B ont en permanence un point de contact qui est La pièce le point de tangence de 0 les dimentions de La pièce leur diamètre primitif. On peut déterminer cela grâce à la formule suivante : d = m x Z, m étant le module et Z le nombre de dents. On obtient donc d() = 0,8 x = 9,6 mm et d(7) = 0,8 x 7 = 57,6 mm. Pour connaître l entre-axe, il suffit maintenant de faire l opération suivante : D= [d() + d(7)] / = [9,6 + 57,6] / = 33,6 mm. Ayant ainsi déterminé l entre-axe, il a fallut créer les deux alésages de 3 mm de diamètre ayant un entre-axe de 33,6 mm. En réalité l alésage devant contenir le roulement, a un diamètre inférieur TPE 00/003 - Voiture Télécommandée
7 ::La conception La Mécanique à celui du roulement qui est précisément de,98 mm. Cette opération fut réalisée en quatre étapes : un alésage avec un foret de mm de diamètre. Un second avec un foret de 6 mm. Un troisième avec un foret de,8 mm. La finition a été réalisée à la main à l aide d une lime. Au final, l alésage approche les,93 mm. La précision pour ce genre de manœuvre n est pas rigoureuse car nous travaillons avec des éléments de petites tailles de l ordre de 0 ou 0 mm et un outil tel qu un foret a toujours une certaine flexibilité, cela créé donc une imprécision lors de l usinage. L opération suivante consiste en l insertion du roulement à billes de diamètre extérieur de 3 mm en serrage. Le serrage le plus approprié pour ce type de roulement se situe entre 5 et 0 centièmes de millimètres. Le roulement est monté serré dans la pièce pour plus de facilité de montage des pièces entre elles. On aurait pu les laisser libre dans la pièce et réaliser le serrage grâce à de la colle araldite, dite colle des roulements à billes Loctite, mais cette solution est moins dans l esprit mécanique, c est en quelque sorte une solution de secours. On a rajouté à la pièce quatre alésages de 3 mm de diamètre lui permettant d être fixée plus tard sur un support d assemblage réunissant toutes les pièces de la partie motrice. un pignon à denture droite Piece La seconde pièce qu il a fallu réaliser devait contenir les pignons coniques du renvoi d angle. Elle est aussi réalisée en double exemplaires. Les deux pièces sont équipées de roulements à billes afin de réduire les pertes mécaniques créées par les frottements des différents éléments de transmission. Le matériau utilisé pour la fabrication de la pièce est l aluminium. Différentes opérations y ont été effectuées. Elle a tout d abord été usinée en forme de U, puis elle a été alésée afin d y intégrer trois roulements à billes identiques à celui inséré dans la pièce précédente. Nous avions, avant d adopter ce schéma de pièce, fixé notre attention sur le même système mais composé de trois pièces identiques en forme de L, assemblées sur une plaque d aluminium percée de plusieurs trous de fixation. Mais cette méthode s est avérée moins performante car il fallait fixer les trois pièces très précisément et le nombre d entités fabriquées passait à six alors que deux suffissent pour la solution définitive. Les roulements sont au nombre de trois : le premier est utilisé pour soutenir d un coté, l arbre provenant de la pièce contenant les deux roues à denture droite et de l autre, le premier pignon conique du renvoi l interieur d un roulement l engrenage conique d angle. Quant aux deux autres roulements, ils sont utilisés pour soutenir le second pignon conique de part et d autre de la pièce par l intermédiaire de l axe relié à la roue arrière. Nous aurions pu réaliser ce système à l aide d un unique roulement, mais il aurait le pignon conique fallu pour cela un roulement à double rangées de billes pour un meilleur maintien dans l axe de la roue. Mais le coût de cet élément et sa rareté car il est de petite A taille, nous ont forcé à choisir une solution technique à deux roulements. La technique utilisée pour les différents alésages est la même que pour la pièce précédente, c est à dire que nous nous sommes servi d un foret de,8 mm. Cependant, il a fallu respecter avec grand soin les spécifications techniques de ces pignons. Elles sont décrites dans le document ci-joint où la principale grandeur à respecter est E = mm, qui est la distance entre la base du pignon et le point de concours des droites confondues avec le diamètre primitif décrivant l inclinaison de la pièce en perspective l engrenage. Cette pièce a été usinée avec deux congés situés à la base de l usinage intérieur et nous avons gardé une épaisseur de 7 mm sur deux des côtés afin de rigidifier cette partie, car elle subit de nombreux efforts en raison de la proximité de la roue et de la suspension. Les axes Deux autres éléments viennent compléter les deux pièces décrites précédemment, ce sont deux arbres de 6 mm de diamètre. Le premier est destiné à relier la pièce supportant le moteur et les roues à denture droite, à l autre pièce contenant les deux pignons coniques. Cet axe fait 37 mm de longueur. Il 7 48 A-A A R5 5 la pièce l axe de la roue arrière TPE 00/003 - Voiture Télécommandée 7
8 La Mécanique ::La conception traverse l engrenage de 7 dents, ainsi que deux roulements appartenant chacun à une pièce, puis il vient enfin s emmancher sur le premier pignon conique. La mise en position des engrenages se fait grâce aux surfaces cylindriques et le maintien en position est réalisé au moyen de goupilles fendues traversant l engrenage et l axe. Un outil spécial a été fabriqué pour cette opération. Il permet d aléser en même temps l élément de transmission et l axe ce qui améliore considérablement la précision de ce perçage. Quant à la roue dentée de dents est maintenu en position en serrage car le diamètre de son alésage intérieur est de 3 mm et celui de l arbre moteur est de 3,7 mm. Il y a donc 7 centièmes de serrage. Le second arbre est destiné à transmettre le mouvement de rotation du second pignon conique à la roue arrière. L arbre traverse deux roulement à billes situés sur une même pièce ainsi que le deuxième pignon. Il fait 9 mm de longueur. Les moyens utilisés pour le maintien en position des éléments sont les mêmes que précédemment, c est à dire la goupille fendue. La fixation de la roue sur l axe est faite au moyen un ecrou nylstop d une tête de vis en H. En effet la jante dispose d un logement hexagonal sur sa face intérieure, c est pourquoi nous avons transformé une simple vis M8. Nous l avons alésé d un trou de 6 mm de diamètre puis nous avons surfacé les deux faces afin qu il puisse se loger dans la jante sans difficultés. La pièce a été ensuite emmanchée en force sur l arbre. En réalité le diamètre de l arbre est légèrement inférieur à 6 mm, il fait précisément 5,98 mm, il a donc fallu réaliser un alésage s approchant de 5,93mm pour la tête de vis M8. La dernière opération consista à fileter une extrémité de cet arbre sur 9 mm de longueur afin que la jante puisse être immobilisée entre la pièce hexagonale et l écrou venant sur le filetage. L écrou de serrage est un écrou indesserrable Nylstop de dimension M4. La plaque arriere Dans le but d assembler tous ces éléments, nous avons conçu autre une pièce très simple. Il s agit d une tôle de 3 mm d épaisseur pliée à une extrémité et percée à plusieurs endroits. La raison du pliage sera détaillée plus tard lorsque l assemblage du châssis et de la partie moteur sera détaillée. La plaque est dotée de six trous de 3 mm de diamètre. Quatre d entre eux sont réservés pour la fixation du support de moteur et des engrenages à denture droite, et les deux autres servent au placement de la fixation des amortisseurs. Un évidement a une roue La plaque arrière en perspective été réalisé dans la pièce pour créer un logement à la roue de 7 dents afin d éviter une collision avec la plaque compte tenu de sa grande taille. Cet élément étant la base de la partie motrice, la plaque est reliée au châssis, d un coté par la suspension, et de l autre par deux pattes jouant le rôle d une liaison pivot. Ces deux dernières sont faites en acier ressort, matériau similaire aux lames de scie à métaux. Il est suffisamment solide et flexible pour supporter une trajectoire comme celle des suspensions. Une fois ces pièces conçues, il s agit de les assembler les unes aux autres. La fixation est réalisée avec des vis M3 et des écrous Nylstop. Le couple moteur est donc transmis de pièce en pièce : en voici l énumération. L arbre moteur, la roue de dents, la roue de 7 dents, la goupille, l arbre de 37 mm de longueur, la goupille, le premier pignon conique, le second pignon conique, la goupille 3, l axe de 9 mm de longueur, la tête de vis H, la jante et le pneu. 6 3 la plaque arrière assemblage partie moteur La partie avant La partie avant du véhicule est composée des roues et des suspensions. Le système que nous avons conçu permet aux roues avant de pivoter sur elles-mêmes comme des roues de chariot. Cette solution est de rigueur dans le projet car la direction est réalisée par différentiel, et si on ne laissait aucune liberté de mouvement aux roues avant, nous serions confrontés à des frottements et, à plus long terme, à des problèmes mécaniques tels que la détérioration de certaines pièces à cause d axes faussés. Dans ce but, nous avons 8 TPE 00/003 - Voiture Télécommandée
9 ::La conception La Mécanique 34, La chape de la roue avant du créer une pièce contenant la roue et pouvant pivoter. C est une sorte de chape qui contient la roue avant et son axe. Elle est aussi en aluminium et nous l avons usiné en forme de U afin de créer un logement pour la roue et pour un capteur de vitesse. Nous avons ensuite enlevé une partie de la pièce afin de la rendre plus esthétique, puis nous avons créé trois alésages : deux d entre eux sont destinés à contenir des roulements pour l axe de la roue, ils ont un diamètre de 9,98 mm. Le dernier alésage sert à faire pivoter la roue. La pièce est en effet assemblé avec un autre élément décrit ciaprès. Le trou fait 9,95 mm de diamètre. Le pivot La chape en perspective L élément destiné à être assemblé à la pièce précédente est un pion cylindrique. Il est muni d un épaulement dans l optique de le renforcer car c est lui qui assurera la rotation est qui encaissera tous les chocs pour les A-A ( : ) A A Pour compléter ces deux pièces et terminer le système de rota- le plateau tion, nous avons créer un plateau pouvant contenir un roulement à bille de 5,98 mm de diamètre. C est un parallélépipède de 8 mm d épaisseur alésé d un trou de 5,94 mm de diamètre. Cette opération est assez compliqué et fastidieuse car il est difficile de trouver un outil tel qu un foret ou un fraise de 5,9 mm de diamètre. Il faut pour cela usiner la pièce sur un tour en la montant au préalable sur un plateau, ce qui est très long car il faut centrer parfaitement la pièce afin de respecter les bonnes dimensions. Ainsi insérer dans le plateau, le pion cylindrique et donc la chape sont rentrer en serrage dans le roulement. Le plateau est aussi percer de trois trous, deux de 3 mm de diamètre dans l optique de fixer une attache d amortisseur, et un de 8 mm de diamètre pour permettre l emmanche d un cylindre de guidage. le plateau en perspective Attache d amortisseur Un autre élément a été spécialement conçu pour rattacher les suspensions au châssis et au reste de la voiture. C est une fixation en aluminium réalisée à partir d une barre que l on a usiné puis tronçonnée pour créer huit pièces similaires. Elle est 8 le pivot avant transmettre ensuite aux suspensions. Une extrémité de la pièce est emmanchée dans la chape de la roue, tandis que l autre est montée en force dans un roulement à bille d un diamètre intérieur de 0 mm. Ce pion est creux car il doit laisser passer les fils de connexion des différents capteurs. La roue est fixée à la chape au moyen d un arbre de 3 mm de diamètre traversant la roue ainsi qu un petit disque muni de fente régulièrement espacées jouant le rôle, avec une fourche optoélectronique, de capteur de vitesse. le pivot en perspective Le plateau l attache d amortisseur 5 TPE 00/003 - Voiture Télécommandée 9
10 La Mécanique ::La conception principalement composée d une gorge destiné à la tête de l amortisseur et d un alésage de 5 mm de diamètre. Deux trous de 3 mm de diamètre ont été percés pour permettre la fixation. Le maintien en position de la suspension et de la fixation est réalisé au moyen d un petit axe. Le blocage en translation de l axe est effectué d un coté grâce à la l attache en perspective tête de l axe et de l autre grâce à une goupille épingle fabriquée avec de la corde à piano. Cette pièce joue le rôle de liaison pivot car le débattement de l amortisseur créé une légère rotation. Le guide en translation La suspension ne jouant que le rôle d une liaison pivot glissant, il a fallu supprimer un degrés de liberté : la rotation autour de la fourche de l amortisseur. Pour cela nous avons créé un guide composer d un cylindre d aluminium de 8 mm de diamètre et d un tube en cuivre de 0 mm de diamètre extérieur et de 8 mm de diamètre intérieur. Le but étant aussi de ren- le guide forcer cette partie du mon- tage. Le cylindre peut donc coulisser librement à l intérieur du tube. Nous avons choisis du cuivre car d après une règle simple, deux métaux de couleurs différentes sont moins exposées aux frottements que deux métaux en contact de même aspect. La plaque avant Le guide est d un coté assemblé au plateau contenant le roulement et de l autre à une plaque en aluminium de 5 mm la plaque avant d épaisseur accueillant l autre partie du guide ainsi qu une autre attache d amortisseur. Les trous de la fixation de la suspension et celui du tube sont en double sur cette pièce car elle permet d assembler la roue avant droite et la roue avant gauche. Cette plaque est ensuite assembler à la partie avant du châssis. 0 TPE 00/003 - Voiture Télécommandée
11 L électronique Nicolas Viennot
12 L Electronique ::Introduction...:: Introduction ::... La base du montage Nous avons tout d abord fait fausse route en essayant de traiter le problème de la commande des moteurs, de la transmission radio, analogiquement. Puis nous avons découvert la puissance de l électronique numérique (autre que de quelques portes NAND en série). En effet, l utilisation de microcontrôleurs est une obligation pour les projets de robotiques, domotiques etc... Le circuit électronique devient simple, et ainsi, la facture s allège. On arrive à une miniaturisation très poussée. Le circuit est beaucoup plus fiable car les caracéristiques des composants analogiques changent au cours du temps et de la température. En bref, l électronique numérique commence véritablement à remplacer tous les circuits analogiques (chaine, radio, etc...). Ainsi nous avons du faire face au choix des microcontrôleurs, à leur programmation, à la réalisation des schémas et à la réalisation des circuits imprimés....:: Le microcontrôleur ::... ORGANISATION FONCTIONNELLE D'UN SYSTEME A MICROCONTROLEUR" Unité de traitement électronique ACTIONNEUR CAPTEURS Interfaçage d'entrée Unité centrale de traitement Interfaçage de sortie OPERATEUR Signaux analogique, numérique et/ou logique Signaux numériques à traiter Signaux numériques traités Signaux analogique, numérique et/ou logique Le choix du microcontroleur On distingue familles de microcontôleurs : Les CISC (Complex Instruction Set Computer), le CPU (Central Processing Unit) possède un grand nombre d instructions, chacune d elles s exécute en plusieurs périodes d horloges. Et les RISC (Reduced Instruction Set Computer), le CPU possède un nombre réduit d instructions ainsi la vitesse d exécution est bien plus rapide qu un CISC, en effet le décodage d une instruction se fait plus rapidement puisque cette dernière est codée sur un faible nombre de bits. On peut choisir entre les DSPs, les classiques 68HC, et les PICs. Les DSP sont des microcontrôleurs très spécifiques dans le traitement du signal. Ce n est pas un choix adapté à notre projet. Les 68HC de Motorola appartiennent à la famille CISC, ils sont puissants mais lents. Ce microcontrôleur n est pas adapté puisque nous n avons pas réellement besoin de sa capacité de calcul. Les PIC de Microchip (Programmable Intelligent Controller) appartiennent à la famille RISC, ils sont très performants. Le PIC est donc un microcontôleur adapté à notre projet. MCLR/VPP RA0/AN0 RA/AN RA/AN/VREF- RA3/AN3/VREF+ RA4/T0CKI RA5/AN4/SS VSS OSC/CLKIN OSC/CLKOUT RC0/TOSO/TCKI RC/TOSI/CCP RC/CCP RC3/SCK/SCL PIC6F876/ RB7/PGD RB6/PGC RB5 RB4 RB3/PGM RB RB RB0/INT VDD VSS RC7/RX/DT RC6/TX/CK RC5/SDO RC4/SDI/SDA Le Brochage du PIC6F876 Le rôle du microcontrôleur Le PIC6F876 On utilisera le PIC6F876 de la gamme Mid-Range (8 bits). Il comporte un jeu de 35 instructions, et possède une vitesse d exécution de 00ns par instruction pour une horloge fonctionnant à 0MHz. Les autres fonctionnalitées seront traitées dans la partie programmation. Ce microcontrôleur est flashable, c est à dire qu on peut le programmer autant de fois que l on veut, et non comme les OTP (One Time Programmable) que l on utilise uniquement dans la fabrication de masse, ce qui sera très utile lors du prototypage. Il possède 8Ko de ROM (le programme ne pourra donc pas éxeder 89 instructions), 368 octets de RAM et 56 octets de EEPROM (non utilisés pour notre application). Autres avantages des PICs : ils sont peu onéreux, très robustes, et bien sûr très fiables, en bref c est un outil très performant dans l électronique numérique et les systèmes embarqués. Le PIC6F876-04/SP coûte 7.90 à l unité chez Farnell ( Il est disponible en boitier. On le choisit en Le Boitier DIP-8 boitier DIP-8 et on prend la version 4MHz même si on l utilise à 0MHz (les PICs sont overclockables même si la documentation technique en prétend le contraire c est à dire que l on peut booster la vitesse d exécution du microcontrôleur). Cette version supporte des températures allant de 0 à 75, si on préfère avoir une plus grande marge, on choisira la version I (Industrial) voir E (Extended) mais nous choisirons la version commerciale. Leur environement de travail pour la programmation est gratuit et convivial. Ce type de microcontrôleur est extremement utilisé dans toute sortes d applications. TPE 00/003 - Voiture Télécommandée
13 ::Le Microcontrôleur L Electronique FLASH Program Memory 3 Data Bus Program Counter 8 Level Stack (3-bit) RAM File Registers 8 PORTA RA0/AN0 RA/AN RA/AN/VREF- RA3/AN3/VREF+ RA4/T0CKI RA5/AN4/SS Program 4 Bus Instruction reg OSC/CLKIN OSC/CLKOUT Instruction Decode & Control Timing Generation 8 Direct Addr 7 Power-up Timer Oscillator Start-up Timer Power-on Reset Watchdog Timer Brown-out Reset In-Circuit Debugger Low Voltage Programming RAM Addr () Addr MUX Indirect 8 Addr FSR reg STATUS reg ALU W reg MUX PORTB PORTC RB0/INT RB RB RB3/PGM RB4 RB5 RB6/PGC RB7/PGD RC0/TOSO/TCKI RC/TOSI/CCP RC/CCP RC3/SCK/SCL RC4/SDI/SDA RC5/SDO RC6/TX/CK RC7/RX/DT MCLR VDD, VSS Timer0 Timer Timer 0-bit A/D Data EEPROM CCP, Synchronous Serial Port USART Le schéma interne du PIC6F876 et son equivalant en silicium...:: Le programmateur ::... Le programmateur standard Pour implanter un programme dans la mémoire flash, il faut un programmateur, le transfère des données se fait de manière serielle synchrone sur les pins RB6 (Horloge) et RB7 (Donnée) du microcontrôleur. Le programmateur proposé par électronique pratique (magazine nº70) fonctionne sur un port série classique. Pour piloter le programmateur de PIC, on utlise IC- Prog ( qui est un logiciel gratuit de très bonne qualitée. Il faut le configurer en programmateur JDM, sur un port série classique, la programmation s effectue sans Le programmateur alternatif Pour utiliser les pins Rx et Tx, il faut intercaler un microcontrôleur qui va se charger de convertir les données du PC pour les envoyer au PIC à programmer. On va utiliser pour cela un autre PIC6F876 même si un PIC6F84A moins cher aurait suffit. PC PIC servant d interface PIC à programmer Normes RS3 Normes TTL Le port série du PC obéit aux normes RS3, le niveau logique 0 correspond à une tension comprise entre +3V et +5V (habituellement V) et le niveau logique correspond à une tension comprise entre -3V et -5V. Pour convertir le RS3 en TTL (logique 0V 5V) on utilise le MAX3. +5V INPUT C3 l interface conviviale de icprog problèmes. Or mon ordinateur portable ne possède pas de port série, donc j ai du faire l achat d un convertisseur USB/Série. Avec ce nouveau port, la programmation ne marche pas (il s agit en fait d un bug du microcontrôleur), en effet la vitesse de commutation des pins RTS et DTS étant trop lente, le microcontrôleur décroche. C est ainsi que l utilisation d un programmateur de PICs utilisant les pins Tx et Rx du port série s avère être obligatoire. En effet, les pins Rx et Tx sont spécifiques pour l émission de donnée. DEVICE MAX0 MAX3 MAX3A MAX0 MAX3 MAX3A DIP/SO CAPACITANCE (µf) C C C V CC 5 GND 4 T OUT 3 R IN R OUT T IN 0 T IN 9 R OUT C C C C TTL/CMOS INPUTS TTL/CMOS OUTPUTS C+ V+ C- 3 C+ 4 C- 5 V- 6 T OUT 7 R IN 8 C5 6 V C+ CC V+ +0V +5V TO +0V 3 C- VOLTAGE DOUBLER 4 C+ +0V TO -0V 6-0V V- 5 C- VOLTAGE INVERTER C4 T IN 400k 0 T IN R OUT 9 R OUT +5V 400k +5V GND 5 T OUT 4 T OUT 5k 5k 7 RIN 3 R IN 8 RS-3 OUTPUTS RS-3 INPUTS Brochage et schema du MAX3 TPE 00/003 - Voiture Télécommandée 3
14 L Electronique ::Le Programmateur Pour programmer les PICs, il faut également une tension de 3V sur la pin MCLR, or on veut que l alimentation se fasse du port USB (5V - 500mA) pour une portabilité maximale. Donc il faut créer la tension de programmation artificiellement, j utilise pour cela un TL497A. En prenant les désignations du schéma de Texas Instrument, V I = 5V, R CL = 0Ω, L = 00µH, C T = 00pF, C O = 47µF, R est une résistance variable de 00K. Il faut régler R pour obtenir V O = 3.3V. Explications du schema Le programmateur peut programmer des PICs à 8, 6, 8, 40 broches, ainsi que des EEPROMs 4LCxx. JP3 est un connecteur pour une éventuelle carte fille (si on veut programmer des smartcard, etc...). JP4 est un connecteur pour le port série en support 3 broches, ce qui est très pratique lors du prototypage puisque je branche alternativement le port série au VI RCL 3 L TL497A CT R =. kω BASIC CONFIGURATION (Peak Switching Current = I(PK) < 500 ma) R CO VO Schéma de montage du TL497A programmateur et à la platine d expérimentation. JP est le connecteur pour l alimentation (USB). Y est le quartz qui va cadanser le PIC à 0MHz avec ses condensateurs de 8pF (il faut en choisir entre 5pF et 30pF), on aurait pu utiliser un résonateur qui inclue les 3 en. Q sert à piloter le 3V par une fonction inverseuse: si RB0 = 0V, Q est bloqué, donc VPP = 3V (R8 consomme un peu, c est pour cela que l on règle le TL497A à 3.3V) ; si RB0 = 5V, Q est passant, donc V CE = 0V et donc VPP = 0V. D, D, D3, D4 sont les leds de visualisation d état, leur résistances séries sont de 330Ω, c est suffisant pour la luminosité. De plus chaque pin du PIC ne doit pas débiter plus de 0mA, la règle est respectée Attention tout de même avec la résistance de reglage du 3V, je dis ceci en connaissance de causes : par inadvertance, le PIC a reçu 60V par la pin MCLR, ce qui l a immédiatement détruit. 0 JP J JP C3 6 u C4 u C5 0u U VCC V+ V- MAX3 R R C7 8pF C8 Y 0Mhz +5 PIC6F876-0/P +5 0 R8 VPP MCLR/Vpp Vdd OSC/CLKIN OSC/CLKOUT K R9 RA0/AN0 RB0/INT 3 RA/AN RB K 4 3 RA/AN/Vref- RB 5 4 R0 RA3/AN3/Vref+ RB3/PGM 6 5 RA4/T0CKI RB RA5/AN4/SS RB5 7 RB6/PGC D 8 D3 RB7/PGD R RC0/TOSO/TCKI 330 RC/TOSI/CPP 3 RC/CPP 4 CLK RC3/SCK/SCL 5 DATA R RC4/SDI/SDA 6 RC5/SDO D4 Vss RC6/TX/CK 9 8 Vss RC7/RX/DT C+ C- C+ C- T T GND R3 330 D C u C u Q +5 R5 0K R7 k +3 C6 47u 3 C93 00p L 00uH R4 U 0 I LIM SEN VCC F CON INH COL OUT CMPR IN SUB EMIT OUT K A NC BASE GND BASE DRV TL497AIJ JP DATA CLK VPP +5 U4 +5 DATA 7 GP0 VDD CLK 6 8 GP VSS 5 GP/T0CKI VPP 4 GP3/MCLR/VPP 3 GP4/OSC/CLKOUT GP5/OSC/CLKIN PICC5XX U OSC/CLKI VDD VPP 4 MCLR 5 OSC/CLKO 7 6 RA0 RB0/INT 8 7 RA RB 8 RA RB 9 RA3 RB3 3 0 RA4/T0CKI RB4 RB5 CLK RB6 5 3 DATA VSS RB7 PIC6C84A-0I/P 9 VPP U A0/WP VCC 7 A Test 3 6 CLK A SCL 4 5 DATA VSS SDA 4LC6 U6 OSC/CLKI VDD MCLR/VPP OSC/CLKO RC0/TOSO/TCKI RA0 RC/TOSO RA RC/CCP RA RC3/SCK/SCL RA3 RC4/SDI/SDA RA4/T0CLK RC5/SDO RA5/SS RC6/TX RC7/RX RB0/INT RB RB RB3 RB4 RB5 VSS RB6 VSS RB7 PIC6C6-0/SP CLK 8 DATA 3 VPP CLK 39 DATA 40 3 U7 OSC/CLKI MCLR/VPP RA0/AN0 RA/AN RA/AN RA3/AN3/VREF RA4/T0CKI RA5/SS/AN4 RB0/INT RB RB RB3 RB4 RB5 RB6 RB7 VSS VSS PIC6C74AI/JW VDD VDD OSC/CLKO RC0/TOSI/TCKI RC/TOSI/CCP RC/CCP RC3/SCK/SCL RC4/SDI/SDA RC5/SDO RC6/TX/CK RC7/RX/DT RD0/PSP0 RD/PSP RD/PSP RD3/PSP3 RD4/PSP4 RD5/PSP5 RD6/PSP6 RD7/PSP7 RE0/RD/AN5 RE/WR/AN6 RE/CS/AN Schema du programmateur 4 TPE 00/003 - Voiture Télécommandée
15 ::La Télécommande L Electronique...:: LA Télécommande ::... Description de la transmission Pour acheminer les données vers la voiture, on utilise les modules radio hybrides Aurel (l émetteur: TX-SAW 433/s-Z et le récepteur: RF 90 A-5S). La transmission doit se faire dans les sens, pour permettre des retours d informations tels que la vitesse. Ce sont des modules radio qui fonctionnent en AM (Amplitude Modulation) à la fréquence de 433.9MHz, on les utilise à 4800bps (ce qui est beaucoup pour ces modules mais presque trop faible pour notre application que L émetteur TX-SAW 433/s-z nous verrons en détails dans la partie programmation). On LE récepeteur RF 90 a-5s pourra utiliser le transceiver (module d emission et réception) XTR-869 fonctionnant en FM (Frequence Modulation) à MHz (bande moins polluée que la 433 puisqu elle n a été ouverte que récement en Europe), on pourra l utiliser à 500bps ce qui donne de plus grandes possibilités pour la gestion en temps-réel de la voiture. La portée de la transmission n a pas encore été mesurée (elle depend énormement de l accordage de l antenne, etc...) mais elle devrait être comprise à priori entre 50m et 00m. Puisque l émeteur et le récepteur fonctionnent sur la même fréquence, on ne peut les utiliser en même temps car sinon il se brouilleraient entre eux. On parle alors de transmission half-duplex, c est à dire que les interlocuteurs peuvent parler mais pas en même temps. L utilisation de antennes séparées est obligatoire si l on ne veut pas utiliser de relais spécifique Le transeiver xtr-869 (ensuite il faut piloter le relais par le port série etc...) sinon la puissance serait diffusée et donc la portée serait réduite. Description des composants Pour convertir les signaux du port série, on va utiliser le classique MAX3, les modules radios Aurel TX- SAW 433/s-Z et RF 90 A-5S. L émetteur est RF alimenté par une tension comprise entre +5V et +V, on va donc utiliser le TL497A AM puisque la télécommande tirera son alimentation à partir du port USB pour une portabilité maximale. Le schéma fonctionne très similairement au programmateur de PIC, le réglage de la tension de sortie du TL497A doit par contre se faire à V (pas plus!). On aurait pu mettre des condensateurs de découplage sur les modules radios (très sensibles) de l ordre de 00nF pour absorber les pics d intensité des circuits integrés mais la version finalisée de la télécommande sera avec le transeiver XTR-869, qui nécessite énormement de précaution comme l électricité statique de l antenne qui doit être évacuée par une bobine vers la masse au lieu de pénetrer dans le module. Il y a encore bien d autres astuces que je ne vérrais que expérimentalement avec un analyseur de spectres et autres. Le débuggage des circuit HF est très difficile puisque les facteurs de fonctionnement sont très variés comme la proximité des composants, ou encore les masses environnantes (la batterie au plomb va perturber énormement la transmission voire la bloquer totalement). TUNING DETECTOR 0 J R5 0K 3 JP3 R7 k RF AMP LF AMP COMP. JP Le schéma interne du RF 90 A-5S GND Antenna 3 GND 4 NC 5 NC 6 NC 7 NC 8 NC 9 GND RX-TX switch Preamp BPF Saw Filter +5 C6 47u +5 C3 6 u C4 3 C93 00p C5 0u R4 U 0 I LIM SEN F CON INH COL OUT CMPR IN SUB EMIT OUT NC GND TL497AIJ U VCC V+ V- R R C+ C- C+ C- T T GND u MAX3 RF Aurel RF 90 Vcc 0 Vcc Antenna 5 Vcc Test Point GND 7 GND Output GND Ampl. O.L. PLL Controlled Mixer Vcc GND GND GND K R3 330 L TX 433 Aurel TX-SAW 433 VCC A D 00uH BASE BASE DRV Input Mod Input Mod Output P Antenna P C u C u Antenna Le schéma de la télécommande SAW OSCILLATOR MATCHING NETWORK Le schéma interne du TX-SAW 433 PLL Controlled Oscillator 50 KHz IF limiter PLL Demod. Vcc Tx-Rx Tx Enable Buffer Power Supply RX-TX RX-TX Enable switch Rx Enable Slicer 8 GND 7 Vcc 6 Rx EN 5 Tx EN 4 Mod. in 3 Analog ou Data out C.D. 0 GND Le schéma interne du XTR-869 TPE 00/003 - Voiture Télécommandée 5
16 L Electronique ::La Voiture...:: LA VOITURE ::... UN moteur GZ-600 BB Description de l environnement La partie électronique de la voiture se compose de deux parties, une logique et une puissance. Ces deux parties sont distinctes, c est à dire que l on sépare les deux cartes électroniques, chacune d elles possède sa propre alimentation pour éviter les éventuelles perturbations des moteurs. La partie logique s alimente avec deux piles de 9 volts et la partie puissance avec la batterie au plomb de V. La voiture est équipée de moteurs GZ-600 BB à courant continu de tension nominale 9.7V. Les capteurs de vitesse sont des fourches HoneyWell (optocoupeur avec un disque à fentes entre l émetteur infra-rouge et le phototransistor). Etude de la partie puissance La courbe de charge des moteurs est établie sur une tension de 9.6V donc n est pas vraiment adapté à notre application puisqu on les sur-alimente à V. La courbe indique que si on désir un couple important, l intensité absorbée peut aller jusqu à 40A par moteur, donc 80A maximum pour les (ce que la batterie peut fournir) mais à priori, le point de fonctionnement d un moteur devrait se situer au rendement maximal, et donc la consommation nominale est en dessous de 0A. L étude de la consommation est déterminante pour le choix de nos composants. L inversion du sens de rotation des moteurs se fait traditionnellement avec un pont en H (montage à 4 transistors) mais nous allons la faire avec des relais RT (relais à contacts inverseurs). On a choisi les relais Finder 44.6 qui supportent 0A sans problèmes, pour les piloter il faut mettre un transistor qui pilote la bobine car elle consomme 00mA et le PIC ne peut en délivrer que 0. La variation de vitesse pour un moteur à courant continu se fait par modulation de largeur d impultions (PMW) un FInder 44.6 que l on verra plus en détails dans la partie programmation. Le PIC6F876 possède modules PWM et donc on ne se servira pas de contrôleurs externes. Au debut, Le pilotage des moteurs se faisait par des transistors de puissance darlington NPN, mais avec leur Vce qui avoisinent.5v, la perte est V ce * I n =.5 * 8 = W ce qui est la puissance de mon fer à souder. Ces transistors ont été évidement détruits lors de l experimentation de la carte puissance. C est pourquoi on utilise des transistors MOS qui génerent moins de pertes que les bi-polaires. On a choisit les IRL004L de International Rectifier à canal N. Ils sont de la 5ème génération de transistors HEXFETs avec une résistance R ds(on) = Ω et une intensité maximale en charge de 0A, ce qui donne une dissipation nominale en charge de R ds(on) * I n = * 64 = 0.5W (c est bien mieux). Ces transistors sont vendus dans un boitier TO-6. Pour piloter ces transistors, on utilisera une tension de V au lieu de 5V (tension délivrée par le PIC) Le boitier TO-6 car d après la courbe ci-dessous le courant passe mieux avec une tension V GS élevée donc il y aura moins de pertes. Il faut donc utiliser un driver MOS, j ai choisis le IR447 dans son boitier DIP-8, il peut piloter transisors MOS. Pour freiner, on utilisera des résistances de 0.5Ω, mais on testera si l utilisation Le boitier DIP-8 d un simple fil fera l affaire, en effet, le freinage s effectue en cours-circuitant le moteur, celui-ci fonctionnera comme une géneratrice et convertira toute l énergie d inertie en chaleur. Pour piloter le freinage, on utilisera également un relais sans oublier les diodes de roue libres qui protègent les transistors. INA INB I D, Drain-to-Source Current (A) VGS TOP 5V V 0V 8.0V 6.0V 4.0V 3.0V BOTTOM.0V PREDRV PREDRV La courbe de charge du GZ-600 BB.0V Le schéma interne du IR447 0µs PULSE W IDTH 0.0 T J = 75 C A DRV DRV V DS, Drain-to-Source Voltage (V) Vs Vs OUTA OUTB GND Une courbe du IRL004 6 TPE 00/003 - Voiture Télécommandée
17 ::La Voiture L Electronique U3 NC VDD +_ 6 +_ BAT_ V 4 3 A B GND NC MAX447CPA Q4 IRF04 Q5 IRF04 +_ D5 +_ +_ D4 +_ D K D K JP Q7 Q8 +_ D3 K3 Q9 JP8 Moteur Gauche JP9 Moteur Droit JP0 JP Resistances freinage R esponse time -µs P hotodarlington Phototrans istor Le schéma de Puissance de la voiture Etude de la partie logique L alimentation de la partie logique se fait en 8V, donc il 000 faut employer des étages de régulation pour obtenir le V pour les modules Aurel, et le 5V 00 pour le PIC. On utilise les régulateurs 78 et 7805 avec des condensateurs de 0µF pour 0 stabiliser la tension. On aurait pu mettre des condensateurs de découplagessur les modules Aurel et sur le PIC de 00nF mais le schéma n est pas une version finalisée (il manque le chargeur de batterie). Pour charger une batterie, il faut l alimenter avec un courant continu de 0% de sa capacitée, notre batterie faisant 7Ah, il faut lui injecter 700mA pendant une ène d heures, mais attention à ne pas trop depasser la durée, sinon la batterie risquerait d exploser. Pour faire un génerateur d intensité constante, on utilise un transistor NPN en régime d amplification, en lui fixant Load resistance - Ohms La fourche phototransistor un courant dans sa base et en utilisant une diode (une LED par exemple) avec une résistance variable en série, et donc le courant du collecteur sera constant (et réglable avec la résistance). Puisqu il fonctionne en amplificateur, la puissance dissipée est alors importante donc il faut munir le transistor d un radiateur. On pourra également utiliser un circuit intégré qui s occupera intégralement de la charge. Les ré- TPE 00/003 - Voiture Télécommandée 7
18 L Electronique ::La Voiture cepteurs infra-rouge ont un temps de réponse qui dépend de leur résistances de tirage. On a choisi des KΩ pour obtenir un temps de réaction avoisinant les 0µs, ce qui semble suffisant. La vitesse de la voiture sera fonction de la fréquence du signal reçu par le PIC (nous aborderons les calculs relatifs aux capteurs de vitesses dans la partie programmation). Le PIC intègre un convertisseur analogique/numérique, on s en servira pour réaliser un testeur de batterie. Sur le schéma, R9 et R0 consituent un diviseur de tension de rapport /4 basé sur la tension de la batterie. R et R sont des résistances variables pour régler les tensions de réference à partir du 5V fixe. Si la mesure se trouve erronée, on ajoutera une faible résistance pour forcer la PIC6F876-0/P 0 MCLR/Vpp Vdd 9 0 OSC/CLKIN OSC/CLKOUT RA0/AN0 RA/AN RA/AN/Vref- RA3/AN3/Vref+ RA4/T0CKI RA5/AN4/SS Vss Vss RB0/INT RB RB RB3/PGM RB4 RB5 RB6/PGC RB7/PGD RC0/TOSO/TCKI RC/TOSI/CPP RC/CPP RC3/SCK/SCL RC4/SDI/SDA RC5/SDO RC6/TX/CK RC7/RX/DT BAT_9 8V U +5 IN OUT GND JP JP4 JP5 JP6 JP Carte Puissance Voyants E=D= ; +(E) = +(D) = 3 +5 Moteur gauche R5 3 Moteur droit 3 Roue arriere 3 Direction R8 K Capteurs de vitesse RC RC RC3 RC4 RC5 RB RB RB3 RB4 RB5 RB6 RA4 RC0 RB0 RA5 RA0 RA RA RA3 RA4 RA5 Y C 8pF 0Mhz C 8pF RB0 RB RB RB3 RB4 RB5 RB6 RB7 RC0 RC RC RC3 RC4 RC5 RC6 RC7 Cerveau RF 90 Aurel RF 90 Vcc Vcc Vcc GND GND GND Antenna Test Point Output P Antenna RC7 +R TX 433 Aurel TX-SAW 433 Vcc GND GND GND Input Mod Input Mod Output 3 Emission/Reception Radio RC RA3 00K R R9 00 RA0 RA 00K R R0 6 RA R3 K Q Indicateur batterie C3 0uF U +R IN OUT GND 78 C4 0uF Alimentation Chargeur de battrie a integrer C5 0uF 3 JP3 R3 R4 R R6 R7 R8 R9 R0 Q K R 330 R K R6 330 R3 K R7 330 R4 K +5 P Antenna + BAT_ V Le schema de la carte logique dela voiture 8 TPE 00/003 - Voiture Télécommandée
19 ::Les PCBs.5 =.4 L Electronique...:: Les circuits électroniques ::... Fonctionnement de Protel Pour concevoir les PCBs (Printed Circuit Board), on utilise Protel de la companie Altium (même logiciel que pour la capture des schémas). Il intègre un système très pratique de synchronisation des PCBs et des schémas. Il intègre de complexes modules de simulation pour les circuits hautefréquence mais on ne s en servira pas dans notre application. Il faut préciser que Protel est un logiciel pouvant router des circuit bien plus compliqués que le notre, en effet il peut router des cartes mères, gérer un circuit comportant plus de 3 couches, et en faire l auto-routage intelligent, qui nous le verrons, est totalement inefficace pour notre circuit simple couche. Son environnement de travail est très convivial, l interface est soignée. Le seul défaut de ce logiciel est le prix (8000$). Les modules Aurel sur un PCB Le PCB supportant un module radio doit être très soigné. En effet, d après la documentation de Aurel, il faut établir des 38. Component Side Les dimensions du récepteur plans de masse sous l ensemble du module. Si le circuit était double face, il aurai fallut mettre un plan de masse sur la deuxième couche. Il faut également les garder à quelques centimètres des autres composants et le plus loin de tout circuit haute fréquence comme quartz et autres. Le pas des broches est de.54mm (00mil). Les = Protel ingègre des modules de simulation de PCBs la conception d un pcb avec un module aurel étamée pour avoir une hauteur de mm afin d apporter une résistance minimale pour ne pas échauffer le circuit lors de passage important d intensité. L espacement des pistes est de 0.3mm. Les PCBs ci-dessous sont à l échelle :. Pour le routage du programmateur de PIC, j ai été forcé de faire deux petits straps (en rouge) la conception d un pcb avec un module aurel dimensions des modules ont été pris en compte lors de la réalisation des librairies, de même pour les relais Finder. Le routage L auto-routeur de Protel (nommé Situs) utilise des algorythmes très complexes mais surtout utile dans un PCB multi-couche comme le lissage de pistes, la gestion des vias (trou intercouche), et bien d autres encore. Pour un circuit comme le notre, il n arrive même pas a router les 70% des pistes. Il a donc fallut faire un routage manuel sur feuille pour ensuite le porter dans le logiciel. Pour la partie logique des PCBs, on utilise une largeur de piste de 0.7mm et pour la partie puissance, on utilise une largeur de mm. Les pistes de la partie puissance seront La simulation 3D du programmateur de pic Le pcb de la télécommande à l echelle : L implantation de la télécommande TPE 00/003 - Voiture Télécommandée 9
20 L Electronique 0 ::Les PCBs Le pcb du programmateur de pic L implantation du programmateur de pic Le pcb de la carte puissance L implantation de la carte puissance Le pcb de la carte logique L implantation de la carte logique TPE 00/003 - Voiture Télécommandée
21 ::Les PCBs L Electronique La realisation Pour réaliser un circuit imprimé, on passe généralement par 8 étapes. Tout d abord, on imprime le typon sur un transparent (faire attention à l échelle), puis on insole la plaquette cuivrée présensibilisée positive avec une insoleuse (on peut aussi le faire avec des lampes UV qui sont bien moins chères. On peut également transformer un vieux scanner en insoleuse avec des néon UV) et attention au sens du typon. Après l insolation, il faut enlever le présensibilisé qui a été exposé aux UVs, pour cela on utilise du revelateur qui n est rien d autre que de la soude. On peut également utiliser du DESTOP (déboucheur pour les canalisations) qui une fois mélangé avec l eau chauffera. Une fois le cuivre à enlever mis à nu, on procède à la gravue, traditionnellement fait avec du très salissant perchlorure de fer chaud. Ce procédé dure environ 5 minutes. On peut également utiliser de l acide chloridrique et de l eau oxygénée à 30 volumes. Les proportions sont : /3 d eau, /3 d acide et /3 d eau oxygénée (à la louche). Une fois le mélange fait, il faut vite mettre la plaquette dans le bain, des bulles s en échappent et environ 5 secondes plus tard, la gravure est terminée et c est propre. Le mélange n est plus utilisable et doit être jetté contrairement au perchlorure de fer qui peut Une graveuse à bulles servir pour plusieurs gravures. Bien sûr, il faut prendre un maximum de précautions avec ce genre de produits. Ensuite, il faut enlever le présensibilisé, pour cela on utilise de l acétone ou de l alcool à bruler. Ensuite, vient le perçage. Lorsque l on pèrce avec des forêts HSS sur de l époxy, ceux-ci s usent très vite (environ 50 trous) et finissent par provoquer des cratères. Les forêts en carbure de tungstène sont adaptés et quasiment inusables mais ils sont très cassants (rien qu en les faisant tomber par terre, ils cassent) et nécéssitent une vitesse de rotation de tr/min. Il faut également faire des les CMS sont très petits un scanner relooké en insoleuse Une graveuse à jets pastilles pleines (sans trous de centrage). Ensuite, pour avoir un circuit protégé contre les oxydations et facile à souder, on étame le circuit. Pour cela on passe du flux (ou du mirror fait l affaire) puis on plonge le circuit dans un bain d étain à froid. On peut d ailleurs faire cela en appliquant de la pâte d étain avec un pinceau en cuivre très chaud. Ou encore avec un fer (méthode employée avec la carte puissance : on a déposé très soigneusement une épaisseur de à mm d étain sur les pistes ainsi la section est d au moins mm ). Ensuite on vérifie le circuit à l ohmmètre à la recherche de court-circuit et de micro coupures. Puis on soude les composants. Un petit fer à souder est obligatoire pour les composants CMS (Composants Une insoleuse la constitution de la plaquette cuivrée Montés en Surface). Pour une propreté optimal, on peut enlever la résine déposée lors de la soudure avec une brosse à dent et de l acétone. Ensuite vient la phase du test (moment critique de l opération)... Les nappes d interconnection Pour relier les cartes entre elles, il faut utiliser des nappes. Dans notre application, vu que nous n avons pas beaucoup d interconnections, on fait une nappe avec du fil et des connecteurs tulipes (avec un pas classique de.54mm). On mettra des gaines thermo-réctractables pour proteger les soudures. Pour les cables de puissances, on prendra des cables de.5mm de section, ce qui est légerement sur-dimentioné, mais il vaut mieux être le plus prudent possible avec les circuits de puissance. Une perçeuse et ses forêts TPE 00/003 - Voiture Télécommandée
22 La Programmation Nicolas Viennot
23 ::Introduction La Programmation...:: Introduction ::... Presentation des projets Nous avons 4 projets de programmation pour notre application. Deux pour le programmateur de PIC et deux pour la voiture. Pour le programmateur de PIC, il faut programmer le PIC qui va interfaçer les données (vu dans la partie électronique) et bien sûr le logiciel qui va envoyer les données vers ce PIC. Pour la voiture, il va falloir coder le PIC de la voiture et le logiciel qui va servir de télécommande. Les programmes vont être réalisé en assembleur et en C pour les PICs, et en C++ pour les logiciels. Nous verrons rapidement le fonctionnement du PIC6F876 qui est un microcontrôleur 8 bits....:: Le PIC6F876 ::... Les ports On dispose de 0 entrées/sorties décomposées en 3 ports distincts : le port A, B et C. Le port A possède 5 I/O, ce port peut être utilisé en port numérique ou analogique (convertion analogique/numérique) ou les. Les entrées sont du type TTL. Attention à la pin RA4 puisqu elle est à collecteur ouvert, donc il faut en prendre compte si on l utilise comme sortie. Le port B est classique avec 7 I/O et des sources d interruptions que nous verrons ultérieurement. Les entrées sont du type TTL, on peut également les paramétrer avec des résistances de tirage en interne. Le port C possède 7 I/ O, il est principalement utilisé pour les différents modules que nous verrons ultérieurement. Les entrées sont du type trigger de schmitt. L horloge Comme nous l avons vu dans la partie électronique, le temps d éxecution d une instruction est de 00ns pour une horloge fonction- C () OSC FLASH Program Memory Program 4 Bus Instruction reg OSC/CLKIN OSC/CLKOUT Instruction Decode & Control Timing Generation 3 Data Bus Program Counter 8 8 Level Stack (3-bit) Direct Addr 7 Power-up Timer Oscillator Start-up Timer Power-on Reset Watchdog Timer Brown-out Reset In-Circuit Debugger Low Voltage Programming RAM File Registers RAM Addr () Addr MUX Indirect 8 Addr FSR reg STATUS reg ALU W reg MUX PORTA PORTB PORTC RA0/AN0 RA/AN RA/AN/VREF- RA3/AN3/VREF+ RA4/T0CKI RA5/AN4/SS RB0/INT RB RB RB3/PGM RB4 RB5 RB6/PGC RB7/PGD RC0/TOSO/TCKI RC/TOSI/CCP RC/CCP RC3/SCK/SCL RC4/SDI/SDA RC5/SDO RC6/TX/CK RC7/RX/DT C () XTAL OSC R s () RF (3) SLEEP To Internal Logic PIC6F87X l horloge est basée sur le quartz MCLR VDD, VSS Timer0 Timer Timer Data EEPROM CCP, Synchronous Serial Port 0-bit A/D USART OSC CLKOUT I/O Pin (Input) I/O Pin (Output) Old Value Q4 Q Q Q3 0, Note: Refer to Figure 5-5 for load conditions. PCH PCL PC PC PCLATH<4:0> PCLATH PCH PCLATH<4:3> PCLATH le timing des I/o avec l horloge le PC. PCL 8 Instruction with PCL as Destination ALU GOTO,CALL Opcode <0:0> le registre PC 6 New Value nant à 0MHz tout simplement parceque l éxecution d une instruction se fait en 4 étapes. Généralement : en premier temps le décodage de l instruction, ensuite la lecture de l argument, puis le traitement des données, et enfin l écriture des données. Ainsi cycle d instruction = 4 cycle d horloge. Les seule instructions qui consomment cycles d instruction sont celles qui écrivent dans Les registres fondamentaux Le PIC ne possède qu un seul registre accumulateur de 8 bits (un pentium en possède quatres de 3bits chacun), c est le registre qui va nous permettre de réaliser toute sortes de calculs. C est un registre tampon, il s appelle W. Le PC (Program Counter) est un ensemble de registres qui stoque l addresse de la prochaine instruction à éxecuter. En effet, le processeur possède un sequenceur qui va executer une liste d instructions organisées qui forment le programme. Le PC est de 3 bits car la ROM fait 8Ko. Il est composé du PCL (PC Low RBPU () Data Bus WR Port WR TRIS RD TRIS RD Port Set RBIF Le schéma interne du PIC6F876 From other RB7:RB4 pins Data Latch D Q CK TRIS Latch D Q CK RB7:RB6 In Serial Programming Mode Latch Q D Q EN D EN TTL Input Buffer VDD Weak P Pull-up I/O pin () ST Buffer Q RD Port Note : I/O pins have diode protection to VDD and VSS. : To enable weak pull-ups, set the appropriate TRIS bit(s) and clear the RBPU bit (OPTION_REG<7>). Q3 les pins 4 à 7 du port B TPE 00/003 - Voiture Télécommandée 3
24 La Programmation ::Le PIC6F876-8bits) et du PCLATH (PC LATch High) car la ROM est composée de 8Ko d instructions. Le registre STATUS est un registre qui rassemble des bits d état du PIC. Il indique l état d une opération (débordement dans le bit de CARRY par exemple) ou encore compose les bits de sélection de banque de RAM. Les registres FSR et INDR forment un pointeur pour accéder à la mémoire indirectement. On charge l addresse que l on veut dans FSR et l accède par INDR. Les instructions Il y a 35 instructions en tout. Il y a les opérations logiques : les OU, ET, XOR, NOT, IOR. Ainsi que les opérations arithmétiques comme l addition et la soustraction mais de multiplication ni de division. Une routine multiplicative de deux nombres de 8 bits donnant un résultat sur 6 bits prend environ 70 instructions (avec des rotations de bits, C C Register f Register f les rotations de bits addition, saut conditionnel, etc...). Il existe bien sûr des processeur éxecutant une multiplication en une seule instruction MAC (Multiply and ACcumulate). Il y a également les rotations de bit vers la gauche et vers la droite Bank Select Direct Addressing Location Select Data Memory () Indirect Addressing RP:RP0 6 From Opcode 0 IRP 7 FSR register 0 00h 7Fh h FFh 00h 7Fh 80h FFh Bank Select Location Select Bank 0 Bank Bank Bank 3 l accès direct et indirect à la RAM à travers le bit de retenue (CARRY du registre STATUS), ainsi que les opérations d incrémentation et de décrémentation avec ou sans test de remise à 0. Les instructions de branchement (toutes celles qui modifient le PC) qui consomment cycles d instructions sont celles comme goto, return, call, jump. Il y a aussi les instructions pour positionner les bits comme bsf, les tests logiques etc... De nombreuses instructions prennent opérandes, ce sont souvent un octet (addresse, nombre quelconque) et une destination (W, f). Mnemonic, Operands Description Cycles MSb 4-Bit Opcode LSb Status Affected Notes ADDWF ANDWF CLRF CLRW COMF DECF DECFSZ INCF INCFSZ IORWF MOVF MOVWF NOP RLF RRF SUBWF SWAPF XORWF BCF BSF BTFSC BTFSS ADDLW ANDLW CALL CLRWDT GOTO IORLW MOVLW RETFIE RETLW RETURN SLEEP SUBLW XORLW f, d f, d f - f, d f, d f, d f, d f, d f, d f, d f - f, d f, d f, d f, d f, d f, b f, b f, b f, b k k k - k k k - k - - k k Add W and f AND W with f Clear f Clear W Complement f Decrement f Decrement f, Skip if 0 Increment f Increment f, Skip if 0 Inclusive OR W with f Move f Move W to f No Operation Rotate Left f through Carry Rotate Right f through Carry Subtract W from f Swap nibbles in f Exclusive OR W with f Bit Clear f Bit Set f Bit Test f, Skip if Clear Bit Test f, Skip if Set Add literal and W AND literal with W Call subroutine Clear Watchdog Timer Go to address Inclusive OR literal with W Move literal to W Return from interrupt Return with literal in W Return from Subroutine Go into standby mode Subtract W from literal Exclusive OR literal with W BYTE-ORIENTED FILE REGISTER OPERATIONS () () BIT-ORIENTED FILE REGISTER OPERATIONS () () LITERAL AND CONTROL OPERATIONS bb 0bb 0bb bb x 00 0kkk 0000 kkk xx xx x 00 dfff dfff lfff 0xxx dfff dfff dfff dfff dfff dfff dfff lfff 0xx0 dfff dfff dfff dfff dfff bfff bfff bfff bfff kkkk kkkk kkkk 00 kkkk kkkk kkkk 0000 kkkk kkkk kkkk ffff ffff ffff xxxx ffff ffff ffff ffff ffff ffff ffff ffff 0000 ffff ffff ffff ffff ffff ffff ffff ffff ffff kkkk kkkk kkkk 000 kkkk kkkk kkkk 00 kkkk kkkk kkkk C,DC,Z Z Z Z Z Z Z Z Z C C C,DC,Z Z C,DC,Z Z TO,PD Z TO,PD C,DC,Z Z Note : When an I/O register is modified as a function of itself ( e.g., MOVF PORTB, ), the value used will be that value present on the pins themselves. For example, if the data latch is for a pin configured as input and is driven low by an external device, the data will be written back with a 0. : If this instruction is executed on the TMR0 register (and, where applicable, d = ), the prescaler will be cleared if assigned to the Timer0 module. 3: If Program Counter (PC) is modified, or a conditional test is true, the instruction requires two cycles. The second cycle is executed as a NOP. la liste des 35 instructions,,,,,,3,,,3,,,,,,,,, TPE 00/003 - Voiture Télécommandée
25 ::Le PIC6F876 La Programmation La RAM Abréviation pour Random Access Memory, c est tout simplement une zone de mémoire que le programme va accéder pour stocker et lire des données relative à son fonctionnement. Cette mémoire est rapide d accès. Au démarrage du PIC, elle contient des données aléatoires, ces données sont altérées si la tension d alimentation baisse en dessous des.5v. Le PIC contient 368 octets de RAM et vu qu il fonctionne en 8 bits, on va devoir y accéder par 3 différentes zones, dites banques. On va choisir une banque RP:RP0 Bank par les bits RP:RP0. Il y a 00 0 une zone commune aux 0 3 banques, c est de 0x70 à àx7h. Cette zone de 6 octets est nécéssaire pour 0 3 l acces aux banques les interruptions que nous verrons ultérieurement, et elle est utile pour stocker les données très fréquement utilisées comme les états du programme. Indirect addr. (*) TMR0 PCL STATUS FSR PORTA PORTB PORTC PORTD () 00h 0h 0h 03h 04h 05h 06h 07h 08h Indirect addr. (*) OPTION_REG PCL STATUS FSR TRISA TRISB TRISC TRISD () Indirect addr. (*) TMR0 PCL STATUS FSR PORTB PORTE () 09h TRISE () PCLATH INTCON PIR PCLATH INTCON PIE PCLATH INTCON PIR TMRL TMRH TCON TMR TCON SSPBUF SSPCON CCPRL CCPRH CCPCON RCSTA TXREG RCREG CCPRL CCPRH CCPCON ADRESH ADCON0 File Address 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh 0h h h 3h 4h 5h 6h 7h 8h 9h Ah Bh Ch Dh Eh Fh 0h PIE PCON SSPCON PR SSPADD SSPSTAT TXSTA SPBRG ADRESL ADCON File Address 80h 8h 8h 83h 84h 85h 86h 87h 88h 89h 8Ah 8Bh 8Ch 8Dh 8Eh 8Fh 90h 9h 9h 93h 94h 95h 96h 97h 98h 99h 9Ah 9Bh 9Ch 9Dh 9Eh 9Fh A0h EEDATA EEADR EEDATH EEADRH General Purpose Register File Address 00h 0h 0h 03h 04h 05h 06h 07h 08h 09h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh 0h h h 3h 4h 5h 6h 7h 8h 9h Ah Bh Ch Dh Eh Fh 0h Indirect addr. (*) OPTION_REG PCL STATUS FSR TRISB PCLATH INTCON EECON EECON Reserved () Reserved () General Purpose Register 6 Bytes 6 Bytes File Address 80h 8h 8h 83h 84h 85h 86h 87h 88h 89h 8Ah 8Bh 8Ch 8Dh 8Eh 8Fh 90h 9h 9h 93h 94h 95h 96h 97h 98h 99h 9Ah 9Bh 9Ch 9Dh 9Eh 9Fh A0h General Purpose Register 96 Bytes General Purpose Register accesses 70h-7Fh 7Fh Bank 0 Bank FFh General Purpose Register General Purpose Register 80 Bytes EFh 80 Bytes 80 Bytes F0h 6Fh accesses 70h accesses 70h-7Fh 70h - 7Fh 7Fh Bank Bank 3 EFh F0h FFh Unimplemented data memory locations, read as 0. * Not a physical register. Note : These registers are not implemented on the PIC6F876. : These registers are reserved, maintain these registers clear. la RAM et les registres spécifiaues TPE 00/003 - Voiture Télécommandée 5
26 La Programmation ::Le PIC6F876 Address Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit Bit Bit 0 Bank 0 Value on: POR, BOR 00h (3) INDF Addressing this location uses contents of FSR to address data memory (not a physical register) h TMR0 Timer0 Module Register xxxx xxxx 0h (3) PCL Program Counter (PC) Least Significant Byte h (3) STATUS IRP RP RP0 TO PD Z DC C 000 xxx 04h (3) FSR Indirect Data Memory Address Pointer xxxx xxxx 05h PORTA PORTA Data Latch when written: PORTA pins when read --0x h PORTB PORTB Data Latch when written: PORTB pins when read xxxx xxxx 07h PORTC PORTC Data Latch when written: PORTC pins when read xxxx xxxx 08h (4) PORTD PORTD Data Latch when written: PORTD pins when read xxxx xxxx 09h (4) PORTE RE RE RE xxx 0Ah (,3) PCLATH Write Buffer for the upper 5 bits of the Program Counter Bh (3) INTCON GIE P EIE T0IE INTE RBIE T0IF INTF RBIF x 0Ch PIR PSPIF (3) ADIF RCIF TXIF SSPIF CCPIF TMRIF TMRIF Dh PIR (5) EEIF BCLIF CCPIF -r Eh TMRL Holding register for the Least Significant Byte of the 6-bit TMR Register xxxx xxxx 0Fh TMRH Holding register for the Most Significant Byte of the 6-bit TMR Register xxxx xxxx 0h TCON TCKPS TCKPS0 TOSCEN TSYNC TMRCS TMRON h TMR Timer Module Register h TCON TOUTPS3 TOUTPS TOUTPS TOUTPS0 TMRON TCKPS TCKPS h SSPBUF Synchronous Serial Port Receive Buffer/Transmit Register xxxx xxxx 4h SSPCON WCOL SSPOV SSPEN CKP SSPM3 SSPM SSPM SSPM h CCPRL Capture/Compare/PWM Register (LSB) xxxx xxxx 6h CCPRH Capture/Compare/PWM Register (MSB) xxxx xxxx 7h CCPCON CCPX CCPY CCPM3 CCPM CCPM CCPM h RCSTA SPEN RX9 SREN CREN ADDEN FERR OERR RX9D x 9h TXREG USART Transmit Data Register Ah RCREG USART Receive Data Register Bh CCPRL Capture/Compare/PWM Register (LSB) xxxx xxxx Ch CCPRH Capture/Compare/PWM Register (MSB) xxxx xxxx Dh CCPCON CCPX CCPY CCPM3 CCPM CCPM CCPM Eh ADRESH A/D Result Register High Byte xxxx xxxx Fh ADCON0 ADCS ADCS0 CHS CHS CHS0 GO/DONE ADON Bank 80h (3) INDF Addressing this location uses contents of FSR to address data memory (not a physical register) h OPTION_REG RBPU INTEDG T0CS T0SE PSA PS PS PS0 8h (3) PCL Program Counter (PC) Least Significant Byte h (3) STATUS IRP RP RP0 TO PD Z DC C 000 xxx 84h (3) FSR Indirect Data Memory Address Pointer xxxx xxxx 85h TRISA PORTA Data Direction Register -- 86h TRISB PORTB Data Direction Register 87h TRISC PORTC Data Direction Register 88h (4) TRISD PORTD Data Direction Register 89h (4) TRISE IBF OBF IBOV PSPMODE PORTE Data Direction Bits Ah (,3) PCLATH Write Buffer for the upper 5 bits of the Program Counter Bh (3) INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF x 8Ch PIE PSPIE () ADIE RCIE TXIE SSPIE CCPIE TMRIE TMRIE Dh PIE (5) EEIE BCLIE CCPIE -r Eh PCON POR BOR qq 8Fh Unimplemented 90h Unimplemented 9h SSPCON GCEN ACKSTAT ACKDT ACKEN RCEN PEN RSEN SEN h PR Timer Period Register 93h SSPADD Synchronous Serial Port (I C mode) Address Register h SSPSTAT SMP CKE D/A P S R/W UA BF h Unimplemented 96h Unimplemented 97h Unimplemented 98h TXSTA CSRC TX9 TXEN SYNC BRGH TRMT TX9D h SPBRG Baud Rate Generator Register Ah Unimplemented 9Bh Unimplemented 9Ch Unimplemented 9Dh Unimplemented 9Eh ADRESL A/D Result Register Low Byte xxxx xxxx 9Fh ADCON ADFM PCFG3 PCFG PCFG PCFG Les registres spécifiques 6 TPE 00/003 - Voiture Télécommandée
27 ::Le PIC6F876 La Programmation Address Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit Bit Bit 0 Bank 00h (3) INDF Addressing this location uses contents of FSR to address data memory (not a physical register) h TMR0 Timer0 Module Register xxxx xxxx 0h (3) PCL Program Counter s (PC) Least Significant Byte h (3) STATUS IRP RP RP0 TO PD Z DC C 000 xxx 04h (3) FSR Indirect Data Memory Address Pointer xxxx xxxx 05h Unimplemented 06h PORTB PORTB Data Latch when written: PORTB pins when read xxxx xxxx 07h Unimplemented 08h Unimplemented 09h Unimplemented 0Ah (,3) PCLATH Write Buffer for the upper 5 bits of the Program Counter Bh (3) INTCON GIE P EIE T0IE INTE RBIE T0IF INTF RBIF x 0Ch EEDATA EEPROM Data Register Low Byte xxxx xxxx 0Dh EEADR EEPROM Address Register Low Byte xxxx xxxx 0Eh EEDATH EEPROM Data Register High Byte xxxx xxxx 0Fh EEADRH EEPROM Address Register High Byte xxxx xxxx Bank 3 80h (3) INDF Addressing this location uses contents of FSR to address data memory (not a physical register) h OPTION_REG RBPU INTEDG T0CS T0SE PSA PS PS PS0 8h (3) PCL Program Counter (PC) Least Significant Byte h (3) STATUS IRP RP RP0 TO PD Z DC C 000 xxx 84h (3) FSR Indirect Data Memory Address Pointer xxxx xxxx 85h Unimplemented 86h TRISB PORTB Data Direction Register 87h Unimplemented 88h Unimplemented 89h Unimplemented 8Ah (,3) PCLATH Write Buffer for the upper 5 bits of the Program Counter Bh (3) INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF x 8Ch EECON EEPGD WRERR WREN WR RD x--- x000 8Dh EECON EEPROM Control Register (not a physical register) Eh Reserved maintain clear Fh Reserved maintain clear Legend: x = unknown, u = unchanged, q = value depends on condition, - = unimplemented, read as '0', r = reserved. Shaded locations are unimplemented, read as 0. Note : The upper byte of the program counter is not directly accessible. PCLATH is a holding register for the PC<:8> whose contents are transferred to the upper byte of the program counter. : Bits PSPIE and PSPIF are reserved on PIC6F873/876 devices; always maintain these bits clear. 3: These registers can be addressed from any bank. 4: PORTD, PORTE, TRISD, and TRISE are not physically implemented on PIC6F873/876 devices; read as 0. 5: PIR<6> and PIE<6> are reserved on these devices; always maintain these bits clear. La pile d appels Lorsque le programme veut faire appel à une routine, il doit éxecuter un call, On peut décomposer un call en quatres temps : l addresse du PC est enregistrée dans la pile, puis on éxecute la routine, et ensuite par un return, on sort l addresse de la pile pour la mettre dans le PC, et ainsi revenir dans le programme. On l appelle pile car contrairement à un FIFO (que l on verra plus tard), lorsque l on ajoute des objets sur la pile, ces derniers se dépilent exactement comme une pile de livres. Le dernier livre empilé sera le premier livre dépilé. La pile du PIC comporte 8 emplacements, c est à dire que l on peut faire 8 appels de routines successives (une routine qui appelle une sous-routine etc...). Les interruptions Ce sont des évenements qui interronpent directement le programme principal pour éxecuter des routines spécifiques. C est une rupture de séquence asynchrone. En fait, c est un appel et donc consomme une addresse dans la pile, ainsi on arrive à une limite de 7 call dans la routine d interruption. Dès On-Chip Program Memory CALL, RETURN RETFIE, RETLW PC<:0> Stack Level Stack Level Stack Level 8 RESET Vector Interrupt Vector Page 0 Page Page Value on: POR, BOR Les registres spécifiques (suite) qu une interruption survient, le PC est positionné au vecteur d interruption (0x4) et le flag GIE est effacé pour etre repositioné par un retfie. Il y a 4 sources d interruptions differentes. Celles que nous utiliserons seront INT 3 (changement d état sur RB0, uniquement sur front montant ou descendant), les trois timers (cas d un débordement), les deux évenements des modules USART (pour la transmission sérielle asynchrone), la conversion analogique/numérique. Chaque interruption peut être activée/désactivée à tout 0000h moment. 0004h 0005h 07FFh 0800h 0FFFh 000h 7FFh 800h Page 3 FFFh La pile d appels Les modules Le PIC comporte trois timers. Le Timer0 (8 bits), le Timer(6bits) et le Timer (8bits). Le timer0 et le timer peuvent faire office de compteur hardware pour compter des fronts montant ou descendants de la pin RA4 et RC0. La fréquence maximale de ces signaux ne doit pas excéder 0MHz (ce qui présente une marge certaine). Le Timer et sont utilisés pour les modules CPPs, l interruption du Timer est déclanchée quand ce dernier est égal à PR +. Les D TPE 00/003 - Voiture Télécommandée 7
28 La Programmation ::Le PIC6F876 EEIF EEIE PSPIF PSPIE CCPIF CCPIE BCLIF BCLIE ADIF ADIE RCIF RCIE TXIF TXIE SSPIF SSPIE CCPIF CCPIE TMRIF TMRIE TMRIF TMRIE T0IF T0IE INTF INTE RBIF RBIE PEIE GIE Wake-up (If in SLEEP mode) Interrupt to CPU timers utilisés en mode timers sont incrémenté à chaque cycle d instruction. On peut assigner aux timer des prédiviseurs, ce CLKOUT (= FOSC/4) qui revient à augmanter leur base de temps. Si le Timer 0 à un prédiviseur de 8 alors tout les 8 cycles 0 d instruction, il sera incrémenté. Seul le Timer est RA4/T0CKI équipé d un postdiviseur. Dans le PIC, il y a un système d anti-plantage : le watchdog (ou chien de pin garde), le programme ne peut que le remettre à T0SE zero mais ne peut pas le lire. Dans le programme principal, on va éxecuter clrwdt (clear watchdog) comme dans les longues boucles ou encore au début d une routine, pour être sûr que 0 M le watchdog ne débordera pas, sinon le PIC va U reseter (presque comme une remise sous tension). Watchdog X Timer Si le PIC se promenne n importe où dans la ROM et n execute plus les clrwdt alors il reset automatiquement, et attention à ne pas en mettre PSA dans la routine d interruption, sinon le watchdog WDT Enable bit est quand même remis à zero même en cas de plantage. Sans assigner de prédiviseur, il déborde au bout de 8ms (environ puisque ce dernier varie en fonction de la température du PIC). On peut lui assigner un prédiviseur (partagé avec celui du timer0) pour lui faire atteindre un temps maximum de 800ms environ. Le PIC comporte également Set Flag bit TMRIF on Overflow RC0/TOSO/TCKI RC/TOSI/CCP () TMR TMRH TMRL TOSC TOSCEN FOSC/4 Enable Oscillator () Internal Clock TMRON On/Off TMRCS TSYNC Prescaler,, 4, 8 TCKPS:TCKPS0 Note : When the TOSCEN bit is cleared, the inverter is turned off. This eliminates power drain. Synchronize det Q Clock 0 0 Synchronized Clock Input Le timer M U X 0 T0CS 8-bit Prescaler to - MUX 0 M U X WDT Time-out Note: T0CS, T0SE, PSA, PS:PS0 are (OPTION_REG<5:0>). Sets Flag bit TMRIF M U X PSA PRESCALER Postscaler : to :6 4 TOUTPS3: TOUTPS0 PSA TMR Output () RESET EQ SYNC Cycles PS:PS0 TMR Reg Comparator PR Reg La pile d appels Data Bus TMR0 Reg Set Flag Bit T0IF on Overflow Le timer 0 et le watchdog des modules de communication sériel. On utilisera le module de communication USART en asynchrone (addressable Universal Synchronous Asynchronous Receiver Transmitter). Une liaison asynchrone est une communication où les interlocuteurs se sont mis d accord sur la vitesse de transmission et donc ne nécéssite pas de ligne d horloge. Tandis qu une communication synchrone nécéssite une ligne d horloge, ainsi à chaque frond déscendant ou montant, une lecture ou une écriture sur les lignes de données va opérer. On en verra en détails pour la transmission radio ou lors de la programmation de PIC. La vitesse de transmission minimal est de 0bps et la vitesse maxi- Le timer male est de.5mbps pour un quartz fonctionnant à 0MHz. Pour ne pas que l un des interlocuteurs désynchronise, la tolérence maximale est de 5%, il vaut mieux rester en dessous des 3% voire. Avec un quartz à 0MHz, on a une erreur d environ % avec les vitesse de communication classique (4800, 9600, etc...). Pour avoir une erreur nulle (à la précision du quartz) il faut utiliser des quartzs multiples de MHz, ce qui peut être nécessaire dans certaines applications. 8 Prescaler :, :4, :6 TCKPS: TCKPS0 FOSC/4 Note : TMR register output can be software selected by the SSP module as a baud clock. 8 TPE 00/003 - Voiture Télécommandée
29 ::Le PIC6F876 La Programmation RX (pin) Rcv Shift Reg Rcv Buffer Reg Read Rcv Buffer Reg RCREG START bit START bit0 bit bit7/8 STOP bit bit0 bit Word RCREG bit7/8 Word RCREG STOP bit START bit bit7/8 STOP bit RCIF (Interrupt Flag) OERR bit CREN Note: This timing diagram shows three words appearing on the RX input. The RCREG (receive buffer) is read after the third word, causing the OERR (overrun) bit to be set. chronogramme de réception Write to TXREG BRG Output (Shift Clock) RC6/TX/CK (pin) TXIF bit (Interrupt Reg. Flag) TRMT bit (Transmit Shift Reg. Empty Flag) Word Word START Bit Bit 0 Bit Bit 7/8 STOP Bit START Bit Bit 0 Word Word Word Word Transmit Shift Reg. Transmit Shift Reg. Note: This timing diagram shows two consecutive transmissions. Ces modules fonctionne suivant la norme NRZ (non return to zero), c est à dire un bit de start, 8 ou 9 bits de données, et un bit de start. On peut émuler le bit de paritée par le bit d addressage (bit 9) logicielement (non supporté en hardware). La lecture d un bit se fait en fesant trois lectures et en prennant la valeur la plus significative. Le module de réception intègre un FIFO (First In, First Out) de deux emlacements. Elle fonctionne comme une file d attente dans un magazin : le premier arrivé est le premier traité, et le dernier attend jusqu à ce qu on le traite (d où le fonctionement inverse de la pile). Ainsi le PIC peut avoir reçu deux octets et être en train de réceptionner un troisième avant qu on les traite. Si le FIFO est plein et qu un nouvel octet vient d être reçu, alors le module passe en état d overflow (bit OERR) et là, il faut couper la réception et la rélancer. Le module gère également les erreurs de frames (si le bit de stop = 0). On pilote les modules à travers RCSTA, TXSTA, SPBRG. Nous verrons ces modules en détails lors des communications dans notre application. Le PIC intègre également deux modules CPPs qui peut être utilisé en trois modes distincts : Capture, Compare, PWM. Nous allons utiliser le mode PWM (Pulse Width Modulation) qui signifie modulation de largeur d impulsion. On peut paramétrer le PWM par sa fréquence et son FOSC RC7/RX/DT TXIE Interrupt x64 Baud Rate CLK TXIF TXEN SPBRG Baud Rate Generator Pin Buffer and Control SPEN Baud Rate CLK SPBRG Baud Rate Generator Data Recovery Data Bus TXREG Register 8 MSb LSb (8) 0 TSR Register TX9D 64 or 6 Interrupt TX9 CREN RCIF MSb RX9 RCIE STOP RX9D TRMT OERR chronogramme d émission RSR Register Pin Buffer and Control SPEN FERR (8) 7 0 RCREG Register 8 Data Bus LSb START FIFO le schéma interne du récepteur RC6/TX/CK pin le schéma interne de l émetteur TPE 00/003 - Voiture Télécommandée 9
30 La Programmation ::Le PIC6F876 7 Period Duty Cycle TMR = PR ADRESH ADFM = 0 7 Right Justified TMR = Duty Cycle ADRESL 0-bit Result TMR = PR 0 0-bit Result Le PWM rapport cyclique. On arrive à atteindre une résolution maximale de 0bits (04 valeurs possible) pour une fréquence de 0kHz et une résolution de 5.5bits (45 valeurs possibles) pour une fréquence de 00kHz. le PWM utilise le Timer et son registre PR. Le postscaler du Timer n influe en rien sur le PWM. Le PIC intègre également un convertisseur A/D (Analog to Digital) qui permet de lire une donnée analogique. Cette conversion s effetue sur ADFM = 0 une seule pin du port A à la fois. On peut spécifier des tensions ADRESH 0-bit Result ADRESL Left Justified la justification du convertiseur A/D Duty Cycle Registers CCPRL CCPRH (Slave) Comparator TMR Comparator PR (Note ) de référence autres que la tension d alimentation. Le temps CCPCON<5:4> d acquisition dépend de la tension d alimentation du PIC, de sa température, et de la précision voulue. Dans le pire des cas, l acquisition dure 0µs pour une précision optimale de 0bit. Le résultat peut être justifié à gauche ou à droite.le PIC comporte d autre modules : un module Compare, Capture, MSSP (Master Synchronous Serial Port) qui sert surtout pour le bus I C. R S Clear Timer, CCP pin and latch D.C. Q TRISC<> RC/CCP CHS:CHS0 VAIN (Input Voltage) RE/AN7 () RE/AN6 () RE0/AN5 () RA5/AN4 RA3/AN3/VREF+ A/D Converter RA/AN VDD 000 RA0/AN0 VREF+ (Reference Voltage) PCFG3:PCFG0 Note : The 8-bit timer is concatenated with -bit internal Q clock, or bits of the prescaler, to create 0-bit timebase. le schéma du module PwM RA/AN/VREF- VREF- (Reference Voltage) PCFG3:PCFG0 VSS Note : Not available on PIC6F873/876 devices. le schéma du sélecteur de cannal du module A/d 30 TPE 00/003 - Voiture Télécommandée
31 ::Le programmateur de PIC La Programmation...:: Le programmateur de PIC ::... Introduction Notre programmateur de PIC doit fonctionner avec les pins Tx et Rx de port série qui est une transmission asynchrone et retransmettre un signal synchrone vers le PIC à programmer. On aurai pu utiliser un PIC moins performants que le 6F876 mais on va l utiliser pour ses modules USART. La programmation du côté PIC va se faire en assembleur, ainsi on pourra se familiariser avec le PIC. Le logiciel côté PC va être en C++, langage orienté object très performent, nous aborderont rapidement la synchronisation entre les threads (définies ultiérieurement). TABLE -: COMMAND MAPPING FOR PIC6F87X La programmation des PICs Pour programmer un PIC, on doit lui fournir les données de façon sérielle synchrone. c est à dire avec une ligne de donnée et une ligne d horloge (correspondant aux pins RB7 et RB6). La transmission se fait en half-duplex (les deux interlocuteurs ne parlent pas en même temps). On peut envoyer 0 commandes différentes pour le PIC6F876. On n abordera pas du tout la programmation de l EEPROM (donnée équivalente a la RAM sauf qu elle est statique, elle ne s efface pas). La programmation de la ROM (mémoire du programme) s effectue Command Mapping (MSB LSB) Data Voltage Range Load Configuration X X , data (4), 0.V - 5.5V Load Data for Program Memory X X , data (4), 0.V - 5.5V Read Data from Program Memory X X , data (4), 0.V - 5.5V Increment Address X X 0 0.V - 5.5V Begin Erase Programming Cycle V - 5.5V Begin Programming Only Cycle V - 5.5V Load Data for Data Memory X X 0 0 0, data (4), 0.V - 5.5V Read Data from Data Memory X X 0 0 0, data (4), 0.V - 5.5V Bulk Erase Setup V - 5.5V Bulk Erase Setup V - 5.5V La liste des commandes MCLR RB6 (Clock) VIHH tdly µs min. Next Command RB7 (Data) 0 0 X X tset tdly X 0 thld µs min. 00 ns min. RESET Program/Verify Test Mode L envoie de la commande increment address MCLR tset0 RB6 (Clock) VIHH thld0 µs min. tdly RB7 (Data) RESET X X 00 ns min. tset thld tdly µs min. strt_bit Program/Verify Test Mode tset thld 00 ns min. stp_bit L envoie d une donnée vers le PIC à programmer TPE 00/003 - Voiture Télécommandée 3
32 La Programmation ::Le programmateur de PIC START Load Configuration Data START Bulk Erase Sequence No Program ID Location? Yes Program Cycle Read Data Command Set VDD = VDDP Increment Address Command Report Programming Failure No Data Correct? No Address = 0x004? Yes Load Data Command PROGRAM CYCLE Yes Increment Address Command Begin Programming Only Command Load Data Command Increment Address Command Wait tprog Begin Program Only Command* Wait tprog Increment Address Command Report Program Configuration Word Error No Data Correct? Yes Program Cycle (Config. Word) Read Data Command Increment Address Command No All Locations Done? Verify all Locations DONE * Assumes that a bulk erase was issued before programming configuration word. If not, use the program flow from Figure -4. en chargeant un mot de 4 bits (taille d une instruction) puis en effectuant la commande de programmation, etc... Pour programmer la configuration du PIC (type de quartz, protection de la ROM, etc...) il faut aller à l addresse 0x007. Il y a d autre information à l addresse 0x000 telles que la version, la révision et l identification du PIC. Les protocoles Le PC envoit des informations au PIC d interface telle que les commandes à envoyer au PIC à programmer ou encore les données à programmer. La transmission s effectue à 8000bps full-duplex (ligne de d emission et réception séparée). Pour envoyer une commande au PIC, il faut l envoyer de la manière 0bxxxxxx où les x sont le code binaire de la commande. Pour piloter manuelement les lignes de la tension de programmation, des données, et de l horloge, on envoie 0b0xxxxxx (liste des commandes définie dans l entête du programme cicontre). Pour envoyer des données à programmer, on envoie 0b0xxxxxx + 0bxxxxxxxx (4 x en tout). Le PIC va répondre qu il a en effet traité l information par RX_OK (0x) et RX_ERROR (0x). RX_OK signifie que la commande ou l envoie de donnée a été traitée et RX_ERROR indique que la donnée n a pas été reçu et donc, que le PC doit la renvoyer. L envoie des données du PIC au PIC à programmer se fait par des rotations de bits (voir les marcos SENDBIT et GETBIT). La temporisation tprog(le temps que la programmation s effectue) se gère avec le timer. Elle est de 4ms sans effacement et de 8ms avec effacement. Le logiciel PC Le programme est composé de deux threads et parfois trois. L utilisation du multi-thread est pour simuler l exécution simultanée de plusieur programme. En effet, la thread principale traite l organigramme de la programmation de la configuration Report Verify Error Data Correct? tout les messages de windows, comme les DONE actions de l utilisateur sur l interface. La La programmation de la rom thread de réception (initialisée quand l objet lpcom est créé) traite tout les octets qui arrive depuis le port série. Et parfois la thread de programmation ou de lecture (sinon la thread principale serait bloquée et le logiciel aurai l air planté) va, en suivant les organigrammes, L interface de test répondrent à la demande de l utilisateur. L interface du programmateur intègre une barre de progression et une barre d état (Status). Le bouton Skip sert à stopper l action en cours, HW Test sert à entrer dans le mode de test manuel des I/O du PIC. Le logiciel accepte les fichier du format HEX6 de intel, format que les compilateurs génerent. No L interface du programmateur 3 TPE 00/003 - Voiture Télécommandée
33 ::Le programmateur de PIC La Programmation Le code source (PIC) ;*******************************************************************************; ; Projet: Programmateur de PIC ; Date: //0 ; Version:.0 ;*******************************************************************************; ; Pins Configs: ; ============= ; ; RB0: commande de VPP (inverse) ; RC3: CLK ; RC4: DATA ; RC6: TX (PC) ; RC7: RX (PC) ; ; Protocole: ( bit start, 8 bit, 0 bit de parite, bit de stop ; ========= ; ; PC -> Pic: ; - emission de la commande ; - si besoin de donnee, envoie de octets de donnes ; - xxxxxx: commande a envoyer au pic ; - 0xxxxxx: HW test ; * : VDD ON ; * : VDD OFF ; * : DATA ON ; * : DATA OFF ; * : CLOCK ON ; * : CLOCK OFF ; * : DATA IN EVENT ON ; * : DATA IN EVENT OFF ; - 0xxxxxx + xxxxxxxx: Data ;*******************************************************************************; LIST p=6f876 ; Définition de processeur #include <p6f876.inc> ; fichier include ; Configuration generale ; CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_ON & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_ON & _HS_OSC ; _CP_OFF Pas de protection du code ; _DEBUG_OFF RB6 et RB7 en utilisation normale (pas de debug) ; _WRT_ENABLE_OFF Le programme ne peut pas écrire dans la flash ; _CPD_ON Memoire EEprom protegee ; _LVP_OFF RB3 en utilisation normale (programmation) ; _BODEN_OFF Reset tension hors service (<4V) ; _PWRTE_ON Demarrage temporise ; _WDT_ON Watchdog on ; _HS_OSC Oscillateur haute vitesse (4Mhz<F<0Mhz) ; REGISTRE OPTION_REG (configuration) ; OPTIONVAL EQU B 0000 ; RBPU b7 : = Résistance rappel +5V hors service ; INTEDG b6 : = Interrupt sur flanc montant de RB0 ; 0= Interrupt sur flanc descend. de RB0 ; TOCS b5 : = source clock = transition sur RA4 ; 0= horloge interne ; TOSE b4 : = Sélection flanc montant RA4(si B5=) ; 0= Sélection flanc descendant RA4 ; PSA b3 : = Assignation prédiviseur sur Watchdog ; 0= Assignation prédiviseur sur Tmr0 ; PS/PS0 b/b0 valeur du prédiviseur ; 000 = / (watchdog) ou / (tmr0) ; 00 = / /4 ; 00 = /4 /8 ; 0 = /8 /6 ; 00 = /6 /3 ; 0 = /3 /64 ; 0 = /64 /8 ; = /8 /56 ; REGISTRE INTCON (contrôle interruptions standard) ; INTCONVAL EQU B ; GIE b7 : masque autorisation générale interrupt ; ne pas mettre ce bit à ici ; sera mis en temps utile TPE 00/003 - Voiture Télécommandée 33
34 La Programmation ::Le programmateur de PIC ; PEIE b6 : masque autorisation générale périphériques ; T0IE b5 : masque interruption tmr0 ; INTE b4 : masque interuption RB0/Int ; RBIE b3 : masque interruption RB4/RB7 ; T0IF b : flag tmr0 ; INTF b : flag RB0/Int ; RBIF b0 : flag interruption RB4/RB7 ; REGISTRE PIE (contrôle interruptions périphériques) ; PIEVAL EQU B ; PSPIE b7 : Toujours 0 sur PIC 6F786 ; ADIE b6 : masque interrupt convertisseur A/D ; RCIE b5 : masque interrupt réception USART ; TXIE b4 : masque interrupt transmission USART ; SSPIE b3 : masque interrupt port série synchrone ; CCPIE b : masque interrupt CCP ; TMRIE b : masque interrupt TMR = PR ; TMRIE b0 : masque interrupt débordement tmr ; REGISTRE PIE (contrôle interruptions particulières) ; PIEVAL EQU B ; UNUSED b7 : inutilisé, laisser à 0 ; RESERVED b6 : réservé, laisser à 0 ; UNUSED b5 : inutilisé, laisser à 0 ; EEIE b4 : masque interrupt écriture EEPROM ; BCLIE b3 : masque interrupt collision bus ; UNUSED b : inutilisé, laisser à 0 ; UNUSED b : inutilisé, laisser à 0 ; CCPIE b0 : masque interrupt CCP ; REGISTRE ADCON (ANALOGIQUE/DIGITAL) ; ADCONVAL EQU B ; PORTA en mode digital ; DIRECTION DES PORTS I/O ; DIRPORTA EQU B ; Direction PORTA (=entrée) DIRPORTB EQU B 0 ; Direction PORTB DIRPORTC EQU B 000 ; Direction PORTC ;***************************************************************************** ; DEFINES * ;***************************************************************************** #DEFINE NEW_CMD Flags,0 #DEFINE READ Flags, #DEFINE SEND Flags, #DEFINE CMD_ONLY Flags,3 #DEFINE WAIT_4MS Flags,4 #DEFINE WAIT_8MS Flags,5 #DEFINE VPP PORTB,0 #DEFINE CLK PORTC,3 #DEFINE DATA PORTC,4 #DEFINE LOAD_CONFIG 0x0 #DEFINE LOAD_DATA_FOR_PROG 0x #DEFINE READ_DATA_FROM_PROG 0x4 #DEFINE INC_ADDR 0x6 #DEFINE BEGIN_ERASE_PROG 0x8 #DEFINE BEGIN_PROG_ONLY 0x8 #DEFINE LOAD_DATA_FOR_DATA 0x3 #DEFINE READ_DATA_FROM_DATA 0x5 #DEFINE BULK_ERASE_SETUP 0x #DEFINE BULK_ERASE_SETUP 0x7 #DEFINE RX_OK 0x #DEFINE ERROR_RX 0x ;***************************************************************************** ; MACRO * ;***************************************************************************** ; Changement de banques ; TPE 00/003 - Voiture Télécommandée
35 ::Le programmateur de PIC La Programmation BANK0 macro ; passer en banque0 bcf STATUS,RP0 bcf STATUS,RP endm BANK macro ; passer en banque bsf STATUS,RP0 bcf STATUS,RP endm SENDBIT macro ; send bit du carry bsf CLK ; on monte l horloge bcf DATA ; on met DATA off btfsc STATUS,C ; Carry == 0? bsf DATA ; si non, on le met on goto $+ ; on attends histoire de... goto $+ goto $+ goto $+ goto $+ ; CUT -- DEBUG ; movlw D 30 ; movwf Loop_wait ; call wait4ms ; decfsz Loop_wait ; goto $- ; CUT -- DEBUG bcf CLK ; on descend l horloge goto $+ goto $+ goto $+ goto $+ goto $+ ; CUT -- DEBUG ; movlw D 30 ; movwf Loop_wait ; call wait4ms ; decfsz Loop_wait ; goto $- ; CUT -- DEBUG endm GETBIT macro ; receptioner dans le carry bsf CLK ; on monte l horloge bcf STATUS,C ; clear carry goto $+ ; on attends histoire de... goto $+ goto $+ goto $+ goto $+ ; CUT -- DEBUG ; movlw D 30 ; movwf Loop_wait ; call wait4ms ; decfsz Loop_wait ; goto $- ; CUT -- DEBUG btfsc DATA ; Data == 0? bsf STATUS,C ; non, on met le carry bcf CLK ; on descend l horloge goto $+ goto $+ goto $+ goto $+ goto $+ ; CUT ; movlw D 30 ; movwf Loop_wait TPE 00/003 - Voiture Télécommandée 35
36 La Programmation ::Le programmateur de PIC ; call wait4ms ; decfsz Loop_wait ; goto $- ; CUT endm ;***************************************************************************** ; VARIABLES BANQUE 0 * ;***************************************************************************** ; Zone de 80 bytes ; CBLOCK 0x0 ; Début de la zone (0x0 à 0x6F) TXBuffer : ; Buffer d emission TXPtr : ; Pointeur d emission RXBuffer : 3 ; Buffer de reception RXPtr : ; Pointeur de reception PicCmd : ; commande a envoyer PicData : ; data Loop : ; compteur Loop_wait : ; compteur de tempo ENDC ; Fin de la zone ;***************************************************************************** ; VARIABLES ZONE COMMUNE * ;***************************************************************************** ; Zone de 6 bytes ; CBLOCK 0x70 ; Début de la zone (0x70 à 0x7F) Flags : ; Flags w_temp : ; Sauvegarde registre W status_temp : ; sauvegarde registre STATUS FSR_temp : ; sauvegarde FSR (si indirect en interrupt) PCLATH_temp : ; sauvegarde PCLATH (si prog>k) ENDC ;***************************************************************************** ; DEMARRAGE SUR RESET * ;***************************************************************************** org 0x000 ; Adresse de départ après reset goto init ; Initialiser ; //////////////////////////////////////////////////////////////////////////// ; I N T E R R U P T I O N S ; //////////////////////////////////////////////////////////////////////////// ;***************************************************************************** ; ROUTINE INTERRUPTION * ;***************************************************************************** ;sauvegarder registres ; org 0x004 ; adresse d interruption movwf w_temp ; sauver registre W swapf STATUS,w ; swap status avec résultat dans w movwf status_temp ; sauver status swappé movf FSR, w ; charger FSR movwf FSR_temp ; sauvegarder FSR movf PCLATH, w ; charger PCLATH movwf PCLATH_temp ; le sauver clrf PCLATH ; on est en page 0 BANK0 ; passer en banque0 36 TPE 00/003 - Voiture Télécommandée
37 ::Le programmateur de PIC La Programmation ; Interruption TMR0 ; btfsc INTCON,T0IE ; tester si interrupt timer autorisée btfss INTCON,T0IF ; oui, tester si interrupt timer en cours goto intsw ; non test suivant call inttmr0 ; oui, traiter interrupt tmr0 bcf INTCON,T0IF ; effacer flag interrupt tmr0 goto restorereg ; et fin d interruption ; Interruption transmission USART ; intsw: bsf STATUS,RP0 ; sélectionner banque btfss PIE,TXIE ; tester si interrupt autorisée goto intsw ; non sauter bcf STATUS,RP0 ; oui, sélectionner banque0 btfss PIR,TXIF ; oui, tester si interrupt en cours goto intsw ; non sauter call inttx ; oui, traiter interrupt ; LE FLAG NE DOIT PAS ETRE REMIS A 0 ; C EST L ECRITURE DE TXREG QUI LE PROVOQUE ; Interruption réception USART ; intsw: bsf STATUS,RP0 ; sélectionner banque btfss PIE,RCIE ; tester si interrupt autorisée goto restorereg ; non sauter bcf STATUS,RP0 ; oui, sélectionner banque0 btfss PIR,RCIF ; oui, tester si interrupt en cours goto restorereg ; non sauter call intrc ; oui, traiter interrupt ; LE FLAG NE DOIT PAS ETRE REMIS A 0 ; C EST LA LECTURE DE RCREG QUI LE PROVOQUE restorereg: movf ;restaurer registres ; PCLATH_temp,w ; recharger ancien PCLATH movwf PCLATH ; le restaurer movf FSR_temp,w ; charger FSR sauvé movwf FSR ; restaurer FSR swapf status_temp,w ; swap ancien status, résultat dans w movwf STATUS ; restaurer status swapf w_temp,f ; Inversion L et H de l ancien W ; sans modifier Z swapf w_temp,w ; Réinversion de L et H dans W ; W restauré sans modifier status retfie ; return from interrupt ;***************************************************************************** ; INTERRUPTION TIMER 0 * ;***************************************************************************** inttmr0: movf RXPtr,f ; test du pointeur de reception btfsc STATUS,Z ; == 0? goto tmr0end ; oui on ne declare pas d erreur clrf RXPtr ; raz du pointeur RX movlw ERROR_RX ; erreur de reception call sendack ; on l envoie tmr0end: return ; fin d interruption timer ;***************************************************************************** ; INTERRUPTION RECEPTION USART * ;***************************************************************************** intrc: clrf TMR0 TPE 00/003 - Voiture Télécommandée 37
38 La Programmation ::Le programmateur de PIC movlw RXBuffer ; pointer le buffer de reception addwf RXPtr,w ; indexer avec le pointeur movwf FSR ; charger dans TSR movf RCREG,w ; charger la donnee lue movwf INDF ; et la sauver dans le buffer indexe ; Detection du type de donnee recu ; movf RXPtr,f ; test == 0? btfsc STATUS,Z ;? goto ptr0 ; oui, on gere la commande ; Reception du eme octet de donnee ; bcf STATUS,C rlf RXBuffer+,f ; rotation d un bit vers la gauche rlf RXBuffer,f ; (bit start + bit stop) movf RXBuffer+,w ; on charge le tout dans les donnees movwf PicData+ movf RXBuffer,w movwf PicData clrf RXPtr ; raz du pointeur de reception movlw RX_OK ; reception ok call sendack ; l envoyer return ; et on sort ptr0: btfsc RXBuffer,7 ; b7 ==? btfss RXBuffer,6 ; b6 ==? goto rcnext ; non, on verifie les autres possibilitees goto rccmd ; oui, on traite une commande rcnext: btfss RXBuffer,7 ; b7 == 0? btfss RXBuffer,6 ; b6 ==? goto rcdata ; non, on recoie des donnees ; oui, on traite le HW test ; Gestion manuelle des sorties ; movlw RX_OK ; reception ok call sendack ; l envoyer hwon: btfsc RXBuffer,5 ; b5 == 0 goto hwon ; non, sortie on ; oui, sortie off btfsc RXBuffer,0 ; VDD? bsf VPP ; = 0 btfsc RXBuffer, ; DATA? bcf DATA ; = 0 btfsc RXBuffer, ; CLOCK? bcf CLK ; = 0 return ; on sort btfsc RXBuffer,0 ; VDD? bcf VPP ; = btfsc RXBuffer, ; DATA? bsf DATA ; = btfsc RXBuffer, ; CLOCK? bsf CLK ; = return ; Gestion des donnees ; rcdata: bcf RXBuffer,6 ; clr du bit 6 (bit de stop) incf RXPtr,f ; incrementation du pointeur de reception return ; on sort ; Gestion de la commande pour le PIC ; rccmd: movwf PicCmd ; on sauve la commande en memoire bsf NEW_CMD ; on valide l envoie de commande return ; fin d interruption 38 TPE 00/003 - Voiture Télécommandée
39 ::Le programmateur de PIC La Programmation ;***************************************************************************** ; INTERRUPTION TRANSMISSION USART * ;***************************************************************************** inttx: movf TXBuffer,w ; Charger le buffer movwf TXREG ; dans TXREG btfss TXBuffer,7 ; Data? goto txend movf TXBuffer+,w ; Charger le buffer (eme octet) movwf TXREG ; dans TXREG txend: BANK ; on arrte la transmission bcf PIE,TXIE BANK0 return ; on sort ; //////////////////////////////////////////////////////////////////////////// ; P R O G R A M M E ; //////////////////////////////////////////////////////////////////////////// ;***************************************************************************** ; INITIALISATIONS * ;***************************************************************************** init: ; initialisation PORTS (banque 0 et ) ; BANK0 ; sélectionner banque0 bsf STATUS,RP0 ; passer en banque movlw ADCONVAL ; PORTA en mode digital/analogique movwf ADCON ; écriture dans contrôle A/D movlw DIRPORTA ; Direction PORTA movwf TRISA ; écriture dans registre direction movlw DIRPORTB ; Direction PORTB movwf TRISB ; écriture dans registre direction movlw DIRPORTC ; Direction PORTC movwf TRISC ; écriture dans registre direction BANK0 clrf PORTA ; Sorties PORTA à 0 clrf PORTB ; sorties PORTB à 0 clrf PORTC ; sorties PORTC à 0 bsf VPP ; VPP = 0 BANK ; Registre d options (banque ) ; movlw OPTIONVAL ; charger masque movwf OPTION_REG ; initialiser registre option ; registres interruptions (banque ) ; movlw INTCONVAL ; charger valeur registre interruption movwf INTCON ; initialiser interruptions movlw PIEVAL ; Initialiser registre movwf PIE ; interruptions périphériques movlw PIEVAL ; initialiser registre movwf PIE ; interruptions périphériques init: ; Effacer RAM banque 0 ; bcf STATUS,RP0 ; sélectionner banque 0 movlw 0x0 ; initialisation pointeur movwf FSR ; d adressage indirect clrf INDF ; effacer ram incf FSR,f ; pointer sur suivant btfss FSR,7 ; tester si fin zone atteinte (>7F) goto init ; non, boucler TPE 00/003 - Voiture Télécommandée 39
40 La Programmation ::Le programmateur de PIC ; USART config ; BANK movlw B ; charger TX config movwf TXSTA ; dans TXSTA movlw D 9 ; 0e6/(6*(9+)) = 5000bps (.3% d erreur) ; movlw D 86 ; 0e6/(6*(86+)) = 4368bps (.% d erreur) ; movlw D 9 ; 0e6/(6*(9+)) = 965bps (0.% d erreur) movwf SPBRG ; configurer le baud rate BANK0 movlw B ; charger RX config movwf RCSTA ; dans RCSTA ; Timer config ; movlw B ; charger config movwf TCON ; dans TCON ; autoriser interruptions (banque 0) ; clrf PIR ; effacer flags clrf PIR ; effacer flags bsf RCSTA,SPEN ; on lance la reception clrf RXPtr ; raz du pointeur de reception bsf INTCON,GIE ; valider interruptions clrf Flags ; clr flags goto start ; programme principal ;***************************************************************************** ; PROGRAMME PRINCIPAL * ;***************************************************************************** ; attente des 4ms ; wait4ms: movlw 0xB ; charger (4e-3/0.e-6 = 0000) movwf TMRH movlw 0xE4 movwf TMRL bsf TCON,TMRON ; et lancer le timer... waitl: btfsc PIR,TMRIF ; debordement? goto waitend ; oui, on sort clrwdt ; effacer watch dog goto waitl ; on boucle waitend: bcf PIR,TMRIF ; on efface le flag d interruption bcf TCON,TMRON ; on arrete le timer return waittx: BANK clrwdt ; effacer watch dog btfsc PIE,TXIE ; reste des caractères à envoyer? goto $- ; oui, attendre btfss TXSTA,TRMT ; buffer de sortie vide? goto $-4 ; non, attendre BANK0 return ; envoie d un retour ; sendack: call waittx ; on attends l emmission precedente movwf TXBuffer ; on charge le message BANK bsf PIE,TXIE ; et on l envoie BANK0 return ; Start ; start: movlw RX_OK ; on a recu la commande call sendack movlw 0x ; on reset Flags (tout en gardant NEW_CMD) 40 TPE 00/003 - Voiture Télécommandée
41 ::Le programmateur de PIC La Programmation andwf Flags,f ; avec un simple et logique waitdata: clrwdt ; effacer watch dog btfss NEW_CMD ; nouvelles donnees? goto waitdata ; non on boucle ; Set Flags ; bcf NEW_CMD ; on valide set: btfss PicCmd,3 ; Prog? goto set ; non bsf WAIT_4MS ; wait 4ms pour la prog btfss PicCmd,4 ; Erase? bsf WAIT_8MS ; wait 4ms de plus pour erase goto cmd ; on envoie la commande btfsc PicCmd,5 ; Send Data? bsf SEND ; oui btfsc PicCmd,4 ; Read Data? bsf READ ; oui bcf PicCmd,4 ; on clr bcf PicCmd,5 ; on clr cmd: cmdl: ; Send Command ; movlw D 6 ; 6 bits a envoyer movwf Loop ; a mettre dans le compteur rrf PicCmd,f ; placer les bits dans le Carry SENDBIT ; on envoie decfsz Loop,f ; on decremente le compteur et si == 0, on sort goto cmdl ; on envoie tous les bits bcf DATA ; on clr data bcf CLK ; et clk clrwdt ; effacer watch dog ; Branchement ; btfsc SEND ; on envoie des donnes? goto send ; oui, on va dans la routine d envoi btfsc READ ; on recois des donnes? goto read ; oui, on va dans la routine de reception ; on a recu une simple commande btfss WAIT_4MS ; on attends 4ms? goto start ; non, on boucle call wait4ms ; oui, on attends btfss WAIT_8MS ; on attends 4ms de plus? goto start ; non, on boucle call wait4ms ; oui, on attends goto start ; et revient au depart send: sendl: read: ; Send Data ; movlw D 6 ; 6 bits a envoyer movwf Loop ; a mettre dans le compteur rrf PicData,f ; rotation de bit de PicData rrf PicData+,f ; le bit qui sort va etre envoye SENDBIT ; on envoie le bit decfsz Loop,f ; on decremente le compteur et si == 0, on sort goto sendl ; on envoie tous les bits bcf DATA ; on clr data bcf CLK ; et clk goto start ; et revenir au depart ; Read Data ; BANK bsf DATA ; passer DATA en entree BANK0 TPE 00/003 - Voiture Télécommandée 4
42 La Programmation ::Le programmateur de PIC readl: movlw D 6 ; 6 bits a lire movwf Loop ; a mettre dans le compteur GETBIT ; on lit le bit de data (dans le carry) rrf PicData,f ; on l enregistre rrf PicData+,f decfsz Loop,f ; on decremente le compteur et si == 0, on sort goto readl ; on boucle BANK bcf DATA ; passer DATA en sortie BANK0 bcf DATA ; on clr data bcf CLK ; et clk ; on verifie les donnees bsf STATUS,C ; on met le carry bcf PicData,7 ; on enleve le stop bit rrf PicData,f ; on enleve le start bit rrf PicData+,f ; par rotations call waittx movf PicData,w ; on charge PicData movwf TXBuffer ; dans le buffer d emission movf PicData+,w movwf TXBuffer+ BANK bsf PIE,TXIE ; on lance l emission BANK0 goto start ; on revient au depart END ; directive fin de programme 4 TPE 00/003 - Voiture Télécommandée
43 ::PICprog - Main.cpp La Programmation Le code source (PC) Main.cpp #define WIN3_LEAN_AND_MEAN #include windows.h #include resource.h #include shlobj.h #include Com.h #include Pic.h #include Hex.h #include SHELLAPI.H #define READ_LEN #define BUFFER_LEN 0x008 0xFFFF #define HW_VDDON 0x6 #define HW_VDDOFF 0x4 #define HW_DATAOUTON 0x6 #define HW_DATAOUTOFF 0x4 #define HW_CLOCKON 0x64 #define HW_CLOCKOFF 0x44 #define HW_ON 0x68 #define HW_OFF 0x48 #define MAXPATH 5 CCom* CPic* CHex* HINSTANCE HBRUSH HWND RECT short* char char char HBRUSH HKEY hkey; lpcom=0; lppic=0; lphex=0; hins; hbr; hwnddlg; rcmain; buffer; temp; sbuf[5]; szfile[56]; brmain,brhw; void Error(char* error) { MessageBox(0,error,0,MB_ICONERROR); delete lpcom; exit(0); void Status(char* status) { SetDlgItemText(hWndDlg,IDC_STATUS,status); BOOL CALLBACK DialogProcHW(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) { RECT rpos; static POINT move,prev; switch(umsg) { case WM_LBUTTONDOWN: GetCursorPos(&prev); SetCapture(hWnd); case WM_LBUTTONUP: ReleaseCapture(); case WM_MOUSEMOVE: if ((wparam == MK_LBUTTON) && (GetCapture() == hwnd)) { GetWindowRect(hWnd,&rPos); GetCursorPos(&move); SetWindowPos(hWnd,0,rPos.left+move.x-prev.x,rPos.top+move.y-prev.y,0,0, SWP_NOSIZE SWP_NOZORDER); prev=move; case WM_INITDIALOG: // lppic->sethwtest(); SetWindowPos(hWnd,HWND_TOPMOST,rcMain.right,rcMain.top,0,0,SWP_NOSIZE); case WM_CLOSE: // lppic->sethwtest(0); EndDialog(hWnd,0); case WM_COMMAND: switch(loword(wparam)) { case IDC_VDD: lppic->setvdd(isdlgbuttonchecked(hwnd,idc_vdd) & 0x); case IDC_DATAOUT: lppic->setdataout(isdlgbuttonchecked(hwnd,idc_dataout) & 0x); TPE 00/003 - Voiture Télécommandée 43
44 La Programmation ::PICprog - Main.cpp case IDC_CLOCK: lppic->setclock(isdlgbuttonchecked(hwnd,idc_clock) & 0x); case IDC_EXIT: // lppic->sethwtest(0); EndDialog(hWnd,0); case WM_CTLCOLOREDIT: case WM_CTLCOLORDLG: case WM_CTLCOLORBTN: case WM_CTLCOLORSTATIC: case WM_CTLCOLORSCROLLBAR: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORMSGBOX: HDC edc=(hdc)wparam; SetTextColor(edc,RGB(55,55,55)); SetBkMode(edc,TRANSPARENT); return (int)brhw; return 0; void AddPath(char* szpath) { char temp[56]; char line[]; line[]=0; DWORD data; for(int i=;i<=maxpath;i++) { data = 56; line[0] = i+0x30; if(regqueryvalueex(hkey,line,0,0,(unsigned char*)temp,&data)!= ERROR_SUCCESS) if(!strcmp(szpath,temp)) { if(i>maxpath) i = MAXPATH; for(;i>;i--) { data = 56; line[0] = i+0x30-; if(regqueryvalueex(hkey,line,0,0,(unsigned char*)temp,&data)!= ERROR_SUCCESS) continue; line[0] = i+0x30; RegSetValueEx(hKey,line,0,REG_SZ,(unsigned char*)temp,strlen(temp)); RegSetValueEx(hKey,,0,REG_SZ,(unsigned char*)szpath,strlen(szpath)); BOOL CALLBACK DialogProcMain(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) { HDROP hdrop; RECT rpos; HDC edc; DWORD data; static POINT move,prev; char sztemp[56]; switch(umsg) { case WM_LBUTTONDOWN: GetCursorPos(&prev); SetCapture(hWnd); case WM_LBUTTONUP: ReleaseCapture(); case WM_MOUSEMOVE: if ((wparam == MK_LBUTTON) && (GetCapture() == hwnd)) { GetWindowRect(hWnd,&rPos); GetCursorPos(&move); SetWindowPos(hWnd,0,rPos.left+move.x-prev.x,rPos.top+move.y-prev.y,0,0,SWP_NOSIZE SWP_NO- ZORDER); prev=move; case WM_INITDIALOG: hwnddlg=hwnd; lppic = new CPic(lpCom,GetDlgItem(hWnd,IDC_PROGRESS)); if(szfile[0]) lphex->readhexfile(szfile); else RegQueryValueEx(hKey,,0,0,(unsigned char*)szfile,&data); SetDlgItemText(hWnd,IDC_COMBO,szFile); SetFocus(GetDlgItem(hWnd,IDC_OPEN)); lppic->brun=0; SetEvent(lpPic->hIdle); SetEvent(lpPic->hNewData); case WM_CLOSE: // delete lppic; // delete lpcom; 44 TPE 00/003 - Voiture Télécommandée
45 ::PICprog - Main.cpp La Programmation // delete lphex; exit(0); case WM_DROPFILES: hdrop = (HDROP) wparam; DragQueryFile(hDrop,0,szTemp,56); DragFinish(hDrop); SetDlgItemText(hWnd,IDC_COMBO,szTemp); case WM_COMMAND: switch(loword(wparam)) { case IDC_EXIT: TerminateThread(lpPic->hThread,0); lppic->brun=0; SetEvent(lpPic->hIdle); lppic->setvdd(0); exit(0); case IDC_HW: GetWindowRect(hWnd,&rcMain); DialogBox(hIns,MAKEINTRESOURCE(IDD_HW),0,DialogProcHW); case IDC_ERASE_PROG: lppic->eraseprog(); case IDC_ERASE_CONFIG: lppic->eraseconfig(); case IDC_READ_PROG: lphex->clearbuffer(); lppic->readall(buffer,read_len); case IDC_READ_CONFIG: lppic->readconfig(); case IDC_PROG: lppic->writeprog(buffer); case IDC_COMBO: if(hiword(wparam)==cbn_dropdown) { SendDlgItemMessage(hWnd,IDC_COMBO,CB_RESETCONTENT,0,0); char temp[56]; char line[]; line[]=0; DWORD data; for(int i=;i<=maxpath;i++) { data = 56; line[0] = i+0x30; if(regqueryvalueex(hkey,line,0,0,(unsigned char*)temp,&data)!= ERROR_SUCCESS) SendDlgItemMessage(hWnd,IDC_COMBO,CB_ADDSTRING,0,(long)temp); else GetDlgItemText(hWnd,IDC_COMBO,szFile,56); case IDC_OPEN: GetDlgItemText(hWnd,IDC_COMBO,szFile,56); AddPath(szFile); lphex->readhexfile(szfile); case IDC_PROG_E: lppic->writeprog_e(buffer); case IDC_PROG_CONFIG: lppic->progconfig(buffer); case IDC_SKIP: TerminateThread(lpPic->hThread,0); lppic->brun=0; SetEvent(lpPic->hIdle); lppic->setvdd(0); SetEvent(lpPic->hIdle); SetEvent(lpPic->hNewData); case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: edc=(hdc)wparam; SetTextColor(edc,RGB(55,55,55)); SetBkColor(edc,RGB(0x3,0,0x3)); return (int)(hbr); case WM_CTLCOLORDLG: case WM_CTLCOLORBTN: case WM_CTLCOLORSTATIC: case WM_CTLCOLORSCROLLBAR: case WM_CTLCOLORMSGBOX: edc=(hdc)wparam; SetTextColor(edc,RGB(55,55,55)); TPE 00/003 - Voiture Télécommandée 45
46 La Programmation ::PICprog - Main.cpp SetBkMode(edc,TRANSPARENT); return (int)brmain; return 0; int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { hbr=createsolidbrush(rgb(0x3,0,0x3)); HBITMAP bmain,bhw; bmain=loadbitmap(hinstance,makeintresource(idb_main)); bhw=loadbitmap(hinstance,makeintresource(idb_hw)); brmain=createpatternbrush(bmain); brhw=createpatternbrush(bhw); hins=hinstance; buffer = new short[read_len]; lphex = new CHex(); buffer = (short*)lphex->buffer; lpcom = new CCom( COM: baud=8000 parity=n data=8 stop= ); InitCommonControls(); int len=strlen(lpcmdline); if(len>3) { strcpy(szfile,lpcmdline+); szfile[len-]=0; else szfile[0]=0; DWORD coucou; RegCreateKeyEx(HKEY_LOCAL_MACHINE, SOFTWARE\\PicProg,0,0,REG_OPTION_NON_VOLATILE,KEY_ALL_ ACCESS,0,&hKey,&coucou); DialogBox(hInstance,MAKEINTRESOURCE(IDD_MAIN),0,DialogProcMain); delete lpcom; delete lppic; delete lphex; return 0; Hex.h // Hex.h: interface for the CHex class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_hex_h 909CDF37_0539_4D7_80E7_34FD7AEB94 INCLUDED_) #define AFX_HEX_H 909CDF37_0539_4D7_80E7_34FD7AEB94 INCLUDED_ #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 #include windows.h class CHex { public: ClearBuffer(); Error(char* error); unsigned char ReadNextByte(); unsigned char ReadByte(DWORD pos=-); char* ReadHexFile(char* file); void BuildHexFile(char* file, char* buffer,int* len); CHex(); virtual ~CHex(); HANDLE hfile; char* Buffer; DWORD Index; unsigned char Checksum; ; #endif //!defined(afx_hex_h 909CDF37_0539_4D7_80E7_34FD7AEB94 INCLUDED_) 46 TPE 00/003 - Voiture Télécommandée
47 ::PICprog - Hex.cpp La Programmation Hex.cpp // Hex.cpp: implementation of the CHex class. // ////////////////////////////////////////////////////////////////////// #include Hex.h #include windows.h ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// #define SAFE_CLOSE(a) if(a!=invalid_handle_value) {CloseHandle(a),a=INVALID_HANDLE_VALUE; #define BUFFER_LEN 0xFFFF void Status(char* status); CHex::CHex() { hfile = INVALID_HANDLE_VALUE; Buffer=new char[buffer_len]; CHex::~CHex() { if(buffer) delete Buffer; SAFE_CLOSE(hFile); void CHex::BuildHexFile(char *file, char *buffer, int *len) { char* CHex::ReadHexFile(char* file) { SAFE_CLOSE(hFile); hfile = CreateFile(file, GENERIC_READ,FILE_SHARE_READ FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL FILE_FLAG_SEQUENTIAL_SCAN, 0); if(hfile == INVALID_HANDLE_VALUE) { char error[56]; strcpy(error, Can t open ); strcat(error,file); Error(error); SAFE_CLOSE(hFile); return 0; DWORD size = GetFileSize(hFile,0); DWORD num; char temp; ClearBuffer(); unsigned char strlen=0; unsigned int addr; unsigned int bufsize=0; Index=0; while(index<size) { Checksum=0; temp=0; //Check the : SetFilePointer(hFile,Index,0,FILE_BEGIN); ReadFile(hFile,&temp,,&num,0); Index++; if(temp!= : ) //Get line lenght strlen = ReadNextByte(); //Get Address addr = ReadNextByte() << 8; addr += ReadNextByte(); //Get line type int i; char type = ReadNextByte(); switch(type) { case : //EOF reached SAFE_CLOSE(hFile); char status[64]; wsprintf(status, Hex file succefully loaded (%u words),bufsize/); Status(status); return Buffer; case 0: //Data //Save bytes into Buffer for(i=0;i<strlen;i++) { if(index>=size) { Error( Invalid Hex File ); TPE 00/003 - Voiture Télécommandée 47
48 La Programmation ::PICprog - Hex.cpp SAFE_CLOSE(hFile); return 0; *(Buffer+addr) = ReadNextByte(); addr++; bufsize++; default: // dont care for(i=0;i<strlen;i++) { ReadNextByte(); //Get the checksum and compare Checksum=~--Checksum; if(readbyte(-)!= Checksum) Index+=4; Error( Invalid Hex File ); SAFE_CLOSE(hFile); return 0; unsigned char CHex::ReadByte(DWORD pos) { static DWORD CurrentIndex=0; if(hfile == INVALID_HANDLE_VALUE) return 0; if(pos==-) pos=index; if(currentindex!=pos) { SetFilePointer(hFile,pos,0,FILE_BEGIN); CurrentIndex=pos; char buf[]; DWORD num; ReadFile(hFile,buf,,&num,0); CurrentIndex+=; buf[0] -= buf[0] > 0x39? 0x37 : 0x30; buf[] -= buf[] > 0x39? 0x37 : 0x30; return ( ( buf[0] << 4 ) buf[]); CHex::Error(char *error) { Status(error); MessageBox(0,error,0,MB_ICONERROR); unsigned char CHex::ReadNextByte() { char ret = ReadByte(); Checksum += ret; Index+=; return ret; CHex::ClearBuffer() { memset(buffer,-,buffer_len); 48 TPE 00/003 - Voiture Télécommandée
49 ::PICprog - Com.h La Programmation Com.h // Com.h: interface for the CCom class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_com_h 73CA363_BFB5_4CE4_9C4D_8CDEFDEB5ECD INCLUDED_) #define AFX_COM_H 73CA363_BFB5_4CE4_9C4D_8CDEFDEB5ECD INCLUDED_ #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 #include windows.h typedef bool (CALLBACK* RXPROC)(unsigned char*,int); class CCom { public: void RXBytePerByte(bool bpb); void InitRXProc(RXPROC proc); void SendByte(unsigned char* buffer,dword len); bool GetBit(); SendBit(bool bit); static unsigned long stdcall CTSloop(void* ptr); static unsigned long stdcall RXThread(void* ptr); bool GetCTS() { return CTS; SetTD(bool state); SetRTS(bool state); SetDTR(bool state); CCom(char* config); virtual ~CCom(); ; HANDLE bool bool HANDLE RXPROC bool hcom; CTS; quit; thread; RXCallBack; byteperbyte; #endif //!defined(afx_com_h 73CA363_BFB5_4CE4_9C4D_8CDEFDEB5ECD INCLUDED_) Com.cpp // Com.cpp: implementation of the CCom class. // ////////////////////////////////////////////////////////////////////// #include Com.h #include windows.h ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// void Error(char* error); void Status(char* status); CCom::CCom(char* conf) { char config[50]; byteperbyte=0; strcpy(config,conf); DCB DCB; hcom = 0; quit = 0; RXCallBack=0; ZeroMemory(&DCB,sizeof(DCB)); DCB.DCBlength=sizeof(DCB); BuildCommDCB(config,&DCB); DCB.StopBits=; DCB.fBinary=; for(unsigned char i=0;i<00;i++) { if(*(config+i)==0) if(*(config+i)== : ) { *(config+i) = 0; hcom=createfile(config, TPE 00/003 - Voiture Télécommandée 49
50 La Programmation ::PICprog - Com.cpp GENERIC_READ GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if(hcom == INVALID_HANDLE_VALUE) { char error[50]; strcpy(error, Can t open ); strcat(error,config); // Error(error); SetCommState(hCom,&DCB); SetupComm(hCom,0x000,0x000); SetCommMask(hCom,EV_CTS); COMMTIMEOUTS cto; cto.readintervaltimeout=maxdword; cto.readtotaltimeoutconstant=55555; cto.readtotaltimeoutmultiplier=maxdword; cto.writetotaltimeoutconstant=5000; cto.writetotaltimeoutmultiplier=0; SetCommTimeouts(hCom,&cto); GetCommState(hCom,&DCB); DWORD Id; CTS=0; // thread=createthread(0,0,ctsloop,this,0,&id); thread=createthread(0,0,rxthread,this,0,&id); CCom::~CCom() { quit=; SetTD(0); SetDTR(0); SetRTS(0); DWORD exit; do { GetExitCodeThread(thread,&exit); while(exit==still_active); CloseHandle(hCom); CCom::SetDTR(bool state) { if(state) EscapeCommFunction(hCom,SETDTR); else EscapeCommFunction(hCom,CLRDTR); CCom::SetRTS(bool state) { if(state) EscapeCommFunction(hCom,SETRTS); else EscapeCommFunction(hCom,CLRRTS); CCom::SetTD(bool state) { if(state) SetCommBreak(hCom); else ClearCommBreak(hCom); unsigned long stdcall CCom::RXThread(void* ptr) { CCom* lpcom=(ccom*)ptr; unsigned char RXBuffer[00]; OVERLAPPED ov; DWORD readen; ZeroMemory(&ov,sizeof(ov)); ov.hevent=createevent(0,0,0,0); while() { ReadFile(lpCom->hCom,RXBuffer,00,0,&ov); WaitForSingleObject(ov.hEvent,INFINITE); GetOverlappedResult(lpCom->hCom,&ov,&readen,0); if(!readen) continue; RXBuffer[readen]=0; if(lpcom->byteperbyte) { for(unsigned int i=0;i<readen;i++) { if(lpcom->rxcallback) lpcom->rxcallback(rxbuffer+i,); else { if(lpcom->rxcallback) lpcom->rxcallback(rxbuffer,readen); CloseHandle(ov.hEvent); return 0; 50 TPE 00/003 - Voiture Télécommandée
51 ::PICprog - Com.cpp La Programmation unsigned long stdcall CCom::CTSloop(void* ptr) { CCom* lpcom=(ccom*)ptr; DWORD mask; OVERLAPPED ov; ZeroMemory(&ov,sizeof(ov)); ov.hevent=createevent(0,0,0,0); SetThreadPriority(lpCom->thread,THREAD_PRIORITY_HIGHEST); while() { WaitCommEvent(lpCom->hCom,&mask,&ov); WaitForSingleObject(ov.hEvent,INFINITE); if(lpcom->quit) return 0; if(mask==ev_cts) { lpcom->cts^=; mask=0; CloseHandle(ov.hEvent); return 0; CCom::SendBit(bool bit) { SetRTS(); SetDTR(bit); SetRTS(0); bool CCom::GetBit() { SetRTS(); Sleep(); bool bit = GetCTS(); SetRTS(0); return bit; void CCom::SendByte(unsigned char *buffer,dword len) { static OVERLAPPED ov = {0,0,0,0,0; static bool init=0; if(!init) { init=; ov.hevent = CreateEvent(0,0,0,0); WriteFile(hCom,buffer,len,0,&ov); WaitForSingleObject(ov.hEvent,INFINITE); void CCom::InitRXProc(RXPROC proc) { RXCallBack=proc; void CCom::RXBytePerByte(bool bpb) { byteperbyte = bpb; TPE 00/003 - Voiture Télécommandée 5
52 La Programmation ::PICprog - Pic.h Pic.h // Pic.h: interface for the CPic class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_pic_h 83D3C7DE_0095_4A09_BE0_5D3FAFE80DC INCLUDED_) #define AFX_PIC_H 83D3C7DE_0095_4A09_BE0_5D3FAFE80DC INCLUDED_ #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 #include com.h #define CMD 0xC0 #define DATA 0x80 #define LOAD_CONFIG 0x0 CMD #define LOAD_DATA_FOR_PROG 0x CMD #define READ_DATA_FROM_PROG 0x4 CMD #define INC_ADDR 0x06 CMD #define BEGIN_ERASE_PROG 0x08 CMD #define BEGIN_PROG_ONLY 0x8 CMD #define LOAD_DATA_FOR_DATA 0x3 CMD #define READ_DATA_FROM_DATA 0x5 CMD #define BULK_ERASE_SETUP 0x0 CMD #define BULK_ERASE_SETUP 0x07 CMD #define HW_VDDON 0x6 #define HW_VDDOFF 0x4 #define HW_DATAOUTON 0x6 #define HW_DATAOUTOFF 0x4 #define HW_CLOCKON 0x64 #define HW_CLOCKOFF 0x44 #define HW_ON 0x68 #define HW_OFF 0x48 #define RX_OK 0x #define ERROR_RX 0x #define ERROR_READ 0x3 class CPic { public: ReadConfig(); EraseProg(); EraseConfig(); WriteProg_E(short *buffer); void HandleData(unsigned char byte); void SetHWTest(bool state); void SetDataOut(bool state); void SetVDD(bool state); void SetClock(bool state); void HandleData(unsigned char* buffer, int len); static bool stdcall RXProc(unsigned char* RX,int len); ProgConfig(short* buffer); static unsigned long stdcall ReadALLThread(void* ptr); static unsigned long stdcall WriteProgThread(void* ptr); ReadALL(short* buffer,int len); WriteProg(short* buffer); CPic(CCom* com,hwnd hwndbar); virtual ~CPic(); CCom* lpcom; static CPic* lppic; short* Buffer; int Len; volatile bool brun; int TXLen; unsigned char TXBuffer[00]; unsigned char InPtr; unsigned char DataInBuf[]; volatile short DataIn; volatile HANDLE hidle; volatile HANDLE hnewdata; ; DWORD HANDLE HWND bool Id; hthread; hbar; Prog_E; #endif //!defined(afx_pic_h 83D3C7DE_0095_4A09_BE0_5D3FAFE80DC INCLUDED_) 5 TPE 00/003 - Voiture Télécommandée
53 ::PICprog - Pic.cpp La Programmation Pic.cpp // Pic.cpp: implementation of the CPic class. // ////////////////////////////////////////////////////////////////////// #include Pic.h #include windows.h #include commctrl.h ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// void Status(char* status); CPic::CPic(CCom* com,hwnd hwndbar) { hbar=hwndbar; lpcom=com; brun=0; lppic=this; InPtr=0; Buffer=0; lpcom->rxbyteperbyte(); lpcom->initrxproc(rxproc); /* hidle = CreateEvent(0,0,,0); hnewdata = CreateEvent(0,0,0,0); lppic->setdataout(0); lppic->setclock(0); lppic->setvdd(0); */ CPic::~CPic() { CloseHandle(hIdle); CloseHandle(hNewData); unsigned long stdcall CPic::ReadALLThread(void* ptr) { CPic* lppic=(cpic*)ptr; lppic->brun=; lppic->datain=0; lppic->setvdd(0); Sleep(); lppic->setdataout(0); lppic->setclock(0); Sleep(); lppic->setvdd(); SendMessage(lpPic->hBar,PBM_SETRANGE,0,MAKELPARAM(0,lpPic->Len)); SendMessage(lpPic->hBar,PBM_SETPOS,0,0); for(int i=0;lppic->brun && i<lppic->len;i++) { ResetEvent(lpPic->hNewData); SendMessage(lpPic->hBar,PBM_SETPOS,i,0); char status[3]; lppic->handledata(read_data_from_prog); WaitForSingleObject(lpPic->hNewData,INFINITE); if(!lppic->brun) { lppic->setvdd(0); return 0; *(lppic->buffer + i) = lppic->datain; wsprintf(status, bytes read: %i (0x%04X),i,lpPic->DataIn); Status(status); lppic->handledata(inc_addr); lppic->setvdd(0); lppic->brun=0; return 0; #define BUF_LEN 0x000 unsigned long stdcall CPic::WriteProgThread(void* ptr) { CPic* lppic=(cpic*)ptr; lppic->brun=; lppic->len=0; for(int i=buf_len;i>=0;i--) { if(*(lppic->buffer+i)!= -) { lppic->len=i; TPE 00/003 - Voiture Télécommandée 53
54 La Programmation ::PICprog - Pic.cpp lppic->setdataout(0); lppic->setclock(0); lppic->setvdd(); SendMessage(lpPic->hBar,PBM_SETRANGE,0,MAKELPARAM(0,lpPic->Len)); int char short bwritten=0; status[8]; temp; for(i=0;lppic->brun && i<=lppic->len;i++) { SendMessage(lpPic->hBar,PBM_SETPOS,i,0); temp=*(lppic->buffer+i); if(temp!= -) { temp= temp << 8 temp >> 8 DATA; lppic->handledata((unsigned char*)&temp,); lppic->handledata(load_data_for_prog); lppic->handledata(lppic->prog_e ==? BEGIN_ERASE_PROG : BEGIN_PROG_ONLY); bwritten++; wsprintf(status, bytes written: %i (0x%04X),bwritten,*(lpPic->Buffer+i)); Status(status); lppic->handledata(inc_addr); lppic->brun=0; lppic->buffer=0; lppic->setvdd(0); Status( Idle. ); return 0; CPic::ReadALL(short *buffer,int len) { if(!buffer brun) return 0; Buffer=buffer; Len=len; hthread=createthread(0,0,readallthread,this,0,&id); return 0; CPic::WriteProg(short *buffer) { if(!buffer brun) return 0; Buffer=buffer; Prog_E=0; hthread=createthread(0,0,writeprogthread,this,0,&id); return 0; CPic::WriteProg_E(short *buffer) { if(!buffer brun) return 0; Buffer=buffer; Prog_E=; hthread=createthread(0,0,writeprogthread,this,0,&id); return 0; CPic::EraseConfig() { if(brun) return 0; brun = ; SendMessage(lpPic->hBar,PBM_SETRANGE,0,MAKELPARAM(0,7)); SendMessage(lpPic->hBar,PBM_SETPOS,0,0); SetVDD(0); SetDataOut(0); SetClock(0); Sleep(); SetVDD(); Sleep(); SendMessage(lpPic->hBar,PBM_SETPOS,,0); short temp=0x3fff; temp = temp << 8 temp >> 8 DATA; lppic->handledata((unsigned char*)&temp,); SendMessage(lpPic->hBar,PBM_SETPOS,,0); HandleData(LOAD_CONFIG); for(int i=0;i<7;i++) { HandleData(INC_ADDR); SendMessage(lpPic->hBar,PBM_SETPOS,3,0); lppic->handledata(bulk_erase_setup); 54 TPE 00/003 - Voiture Télécommandée
55 ::PICprog - Pic.cpp La Programmation SendMessage(lpPic->hBar,PBM_SETPOS,4,0); lppic->handledata(bulk_erase_setup); SendMessage(lpPic->hBar,PBM_SETPOS,5,0); lppic->handledata(begin_erase_prog); SendMessage(lpPic->hBar,PBM_SETPOS,6,0); lppic->handledata(bulk_erase_setup); SendMessage(lpPic->hBar,PBM_SETPOS,7,0); lppic->handledata(bulk_erase_setup); Status( Config Erased ); SetVDD(0); brun = 0; return 0; CPic::EraseProg() { if(brun) return 0; brun = ; SendMessage(lpPic->hBar,PBM_SETRANGE,0,MAKELPARAM(0,8)); SendMessage(lpPic->hBar,PBM_SETPOS,0,0); SetVDD(0); SetDataOut(0); SetClock(0); Sleep(); SetVDD(); Sleep(); SendMessage(lpPic->hBar,PBM_SETPOS,,0); short temp=0x3fff; temp = temp << 8 temp >> 8 DATA; lppic->handledata((unsigned char*)&temp,); SendMessage(lpPic->hBar,PBM_SETPOS,,0); lppic->handledata(load_data_for_prog); SendMessage(lpPic->hBar,PBM_SETPOS,3,0); lppic->handledata(bulk_erase_setup); SendMessage(lpPic->hBar,PBM_SETPOS,4,0); lppic->handledata(bulk_erase_setup); SendMessage(lpPic->hBar,PBM_SETPOS,5,0); lppic->handledata(begin_erase_prog); SendMessage(lpPic->hBar,PBM_SETPOS,6,0); lppic->handledata(bulk_erase_setup); SendMessage(lpPic->hBar,PBM_SETPOS,7,0); lppic->handledata(bulk_erase_setup); SetVDD(0); SendMessage(lpPic->hBar,PBM_SETPOS,8,0); Status( Program Erased ); brun = 0; return 0; CPic::ProgConfig(short *buffer) { Buffer=buffer; brun=; SetDataOut(0); SetClock(0); SetVDD(); HandleData(LOAD_CONFIG); for(int i=0;i<7;i++) { HandleData(INC_ADDR); short temp=*(buffer + 0x007); char status[8]; wsprintf(status, PIC Configured: 0x%X,temp); temp = temp << 8 temp >> 8 DATA; HandleData((unsigned char*)&temp,); HandleData(LOAD_DATA_FOR_PROG); HandleData(BEGIN_ERASE_PROG); Status(status); SetVDD(0); brun=0; return 0; CPic::ReadConfig() { brun=; SetDataOut(0); SetClock(0); SetVDD(); TPE 00/003 - Voiture Télécommandée 55
56 La Programmation ::PICprog - Pic.cpp HandleData(LOAD_CONFIG); for(int i=0;i<7;i++) { HandleData(INC_ADDR); DataIn=0; ResetEvent(hNewData); HandleData(READ_DATA_FROM_PROG); WaitForSingleObject(lpPic->hNewData,INFINITE); if(!brun) { SetVDD(0); return 0; char status[8]; wsprintf(status, Configuration: 0x%X,DataIn); Status(status); brun = 0; SetVDD(0); return 0; CPic* CPic::lpPic; bool stdcall CPic::RXProc(unsigned char *RX,int len) { if(lppic->inptr == ) { lppic->inptr=0; *lppic->datainbuf = *RX; memcpy((void*)&lppic->datain,lppic->datainbuf,); SetEvent(lpPic->hNewData); else if(*rx & DATA) { *(lppic->datainbuf+) = *RX & ~DATA; lppic->inptr=; else { if(*rx == RX_OK) SetEvent(lpPic->hIdle); else if(*rx == ERROR_RX) lppic->lpcom->sendbyte(lppic->txbuffer,lppic->txlen); return 0; void CPic::HandleData(unsigned char *buffer, int len) { if(waitforsingleobject(hidle,00) == WAIT_TIMEOUT) { lppic->brun=0; SetEvent(lpPic->hIdle); SetEvent(lpPic->hNewData); TerminateThread(lpPic->hThread,0); Status( Timed Out... ); memcpy(txbuffer,buffer,len); TXLen=len; ResetEvent(hIdle); lpcom->sendbyte(txbuffer,txlen); void CPic::SetClock(bool state) { HandleData(state ==? HW_CLOCKON:HW_CLOCKOFF); void CPic::SetVDD(bool state) { HandleData(state ==? HW_VDDON:HW_VDDOFF); void CPic::SetDataOut(bool state) { HandleData(state ==? HW_DATAOUTON:HW_DATAOUTOFF); void CPic::SetHWTest(bool state) { HandleData(state ==? HW_ON:HW_OFF); void CPic::HandleData(unsigned char byte) { HandleData(&byte,); 56 TPE 00/003 - Voiture Télécommandée
57 ::La voiture La Programmation...:: La voiture ::... Introduction Nous allons traiter cette partie très rapidement, faute de temps, et tout le code source sera sans commentaire... Ces programmes sont loins d être terminés. Comme le programmateur de PIC, nous avons un programme PIC et un programme PC à faire. Le programme PIC est codé en langage C et nous verrons comment utiliser nos modules. Nous verrons rapidement comment gérer la synchronisation du multi-threading de la télécommande. Nous verrons également ce qu est le langage orienté objet avec ses classes. L interface graphique est gérée par DirectX (et donc prenant en compte le blitter materiel, etc...). Puisque nous utilisons une transmission radio, il va falloir vérifier si les transferts de donnés se fond correctement (CRC). Pour gérer les trois capteurs de vitesse, les moteurs, le testeur de batterie, et les transmissions radios, il va falloir définir judicieusement nos prioritées. L alimentation des moteurs Tout d abord pour que la voiture avance tout droit, les moteurs devront tourner rigouresement à la même vitesse. A plus de tr/min, avec les imperfections des moteurs, ils ne pourront pas tourner à la même vitesse si on leur donne la même puissance électrique. Et donc la voiture n ira jamais dans une direction droite. C est pourquoi au lieu de commander une puissance, nous allons commander une vitesse. On a donc recourt à l asservissement en vitesse. Nous choisirons l asservissement PID (Proportionnel, Intégral, Dérivé). Voyons de plus près ce que chaque boucle modifie dans le système. La boucle proportionnelle corrige avec un coefficient Kp l erreur entre la vitesse voulue et la vitesse réelle. Si ce coefficient est trop fort, on dépasse la consigne,,0 Sortie Entrée 0 Position désirée Générateur de trajectoire (n) (n-) Dépassement de position,0+δ,0-δ Tr Montée T p Pic Temps Courant d'erreur de poursuite Erreur de poursuite précédente x Ki Intégrale d'erreur e état stable T s Stabilisation L asservissement proportionnel Courant de position x K d x K p et donc le système oscille jusqu à se stabliliser. On constate qu une erreur dite statique subsiste, ainsi un simple asservissement P n est pas suffisement fiable. On va rajouer une boucle d intégration pour corriger cette erreur statique. Si on ne limite pas la valeur de notre intégrale, lorsque l on impose une consigne que le système n est pas capable d at- il teindre, alors le tèrme intégral va augmenter sans cesse. Puis lorsque l on voudra ralentir, onsera bloqué en vitesse maximale car le terme intégral sera bien trop grand (ce qui est d ailleurs très dangereux vu qu on pert le contrôle du véhicule). C est pou cela qu on limite l intérgale. On constate également que lors d un démarrage par exemple, le système mécanique a un certain temps de réation. Ainsi, lorsque l on va appliquer une consigne l intégrale va augmenter alors que le moteur n a toujours pas réagit. C est la que le phénomène d overshoot, on dépasse violement la valeur limite. Alors ajoute le contrôle dérivé pour améliorer la réponse du système en régime transitoire. Donc on va gérer le PID de façon numérique dans la voiture. L erreur sera la consigne à appliquer moins la vitesse réelle or les vitesses sont des valeurs algébriques, donc il faudra émuler le signe des vitesses des moteurs logicielement avec des algorythmes qui détectent le passage à zero d une vitesse. En effet on ne passe pas de 00tr/min à -00tr/min d un seul coup, on passe par des valeur proche de zero. Les coéfficients se règlent dynamiquement à partir de la télécommande. Les moteurs sont alimentés en PWM. Pour le PID nous utiliserons la résolution maximale qui est 0bits et pour le pilotage manuel des moteurs (donc des puissances) la résolution de 8bit. Les capteurs de vitesse La résolution des capteurs de vitesse des moteurs doit être la meilleure possible pour donner au PID la possiblitée de faire les Amp Kp = Gain proportionnel Kd = Gain dérivé Ki = Gain intégral il = Limite intégrale M= Moteur E= Codeur E M L asservissement PID meilleures corrections sur la puissance à fournir aux moteurs. Pour avoir la meilleur flexibilitée, nous alons utiliser les timer0 et timer en mode compteur pour déterminer la fréquence des signaux reçus, donc il n y a plus que le timer pour gérer tout les timeouts de la transmission radio etc... La fréquence maximale des compteurs est de 0MHz. On utilisera des disques à 00 fentes que l on fixera sur l axe du moteur. On veut savoir quelle est la vitesse du véhicule avant que le PIC décroche pour savoir si on doit changer de méthode. La vitesse de rotation du moteur maximale avant que le PIC sature est: 60 * 0e6 / 00 = tr/min, ce qui est largement assez. Maintenant voyons le temps d echantillonage. On va utiliser les compteurs sur 8 bits (pour simplifier les calculs de multiplication avec les coefficients, etc...). donc 55 est la valeur limite de notre compteur. On va considerer un temps d echantillonage de 5ms, et supposons que la vitesse maximale d un moteur est de 5000 tr/min (en descente, avec de la marge) alors le compteur qui correspond à notre vitesse maximale est de 5e-3 * 5000/60 * 00 = 65. Pour des disques de 36 dents, la valeur maximale est 5. Donc soit on utilise des disques de 36 fentes, doit on utilise des 00 fentes avec une base de temps réglable (qu il faudra émettre vers la télécommande) avec des seuils de vitesses qui fonctionnerai de manière analogue à une entrée trigger de schmitt. Les freins Les freins par résistance sont les freins par défaut, voire de sécurité. On peut inverser le sens de rotation des moteurs pour un freinage optimal. Cependant les roues risquent de ne plus adhérer, alors il faut prévoir un système d ABS qui sera concu lors du test de la voiture puisque pour l instant, il nous est impossible d anticiper les réactions de la voiture. TPE 00/003 - Voiture Télécommandée 57
58 La Programmation ::La voiture La transmission On utilise les modules USART du PIC pour la transmission radio à 4800bps. Le protocol est définit dans l entête du code source. Il faut quand même savoir que la télécommande peut envoyer deux types d informations: la configuration de la voiture, telle que les coefficients, ou encore les phares etc... ou les données relative au déplacement de la voiture comme les consignes du PID ou la puissance des moteurs à fournir (pilotage manuel). L envoie des données se fait en NRZ pour l instant mais devrait se faire en encodage manchaster. En effet, pour que la transmission soit optimale, la moyenne de la valeur des bits envoyés doit être égale à 0.5 (c est à dire qu il y est autant de 0 que de ) car les récepteurs possédent un ajusteur de gain automatique. Pour réaliser cet encodage, on envoie un octet sur deux octets. Il faut savoir que les modules Aurel se mettent en veille au bout d un certain temps, ainsi les premiers bits d un paquet sont erronés. c est pourquoi on envoie l octet àxff avant chaque transmission (0x55 ou 0xAA à tester pour synchroniser les bits de start et stop). Autre point important : il faut définir une chaine qui va servir d accroche pour la transmission. J ai utilisé 0xC9,0x5E mais il semble que c est bien trop léger. Il faudrai minimum 40bits car les pertubations environantes sont énormes. Mais c est ici que la vitesse de 4800bps trouve ses limites, puisque le mieux serait d avoir un aller-retour pour un échantillonage, en effet, en mettant plus de bits d accroche, on augmante le temps à émettre un paquet et avec 6bits d accroche, on depasse presque le temps d un aller-retour sans prendre compte du temps de réaction du convertisseur USB/Série. Seul les tests nous montreront la bonne méthode à emplyer. Pour vérifier l authenticité des données, on aurai pu employer un checksum (somme de tout les octets du paquet modulo 0xFF) mais lorsqu un bit change dans le paquet et qu en même temps, un bit change dans le checksum, il se peut qu il y ai une grave erreur. Alors on utilise un CRC (cyclic redendancy check), si on modifie un seul bit du paquet, le CRC change complétement de valeur. C est ce qui fait sa puissance par rapport au checksum. Pour calculer un CRC on peut soit passer par des polynômes qui nécessitent un temps de calcul, ou alors on peut utiliser des tables qui consomment de la mémoire ROM. Nous allons utiliser les tables. CRC.h const unsigned char CRCTable[56] = { 0x84, 0x0D, 0x3C, 0xB4, 0xBC, 0xD5, 0x6, 0xC7, 0xA7, 0x76, 0xA4, 0xD7, 0xF, 0xEB, 0x9, 0x, 0x7, 0x7A, 0xA9, 0x68, 0x08, 0xBB, 0xD6, 0x7F, 0x05, 0x9C, 0x65, 0x63, 0x9B, 0x8E, 0xCD, 0x0, 0x54, 0xEE, 0x96, 0x47, 0xD9, 0x75, 0x8A, 0xCF, 0x79, 0x8, 0x4A, 0x98, 0xD0, 0x5E, 0xCA, 0xE0, 0x6E, 0x6C, 0x3, 0x86, 0xE, 0xA, 0x8F, 0x7B, 0x64, 0xE9, 0x8, 0x3, 0x9F, 0x6D, 0x56, 0xDC, 0xB3, 0xF7, 0x49, 0x88, 0x4, 0xF0, 0x60, 0x0, 0x8, 0x0, 0x77, 0x80, 0x5C, 0x6F, 0x4D, 0x7, 0x53, 0xA8, 0xB7, 0xF4, 0x07, 0xF9, 0x6, 0xE4, 0xCC, 0xAA, 0xA, 0x6A, 0x90, 0xF, 0xED, 0x66, 0xD8, 0x83, 0x9A, 0xD, 0x30, 0x8B, 0x95, 0xA, 0x0B, 0xB, 0x3F, 0x, 0x4B, 0x3E, 0x4C, 0x44, 0x97, 0x50, 0xE3, 0x7C, 0xC, 0x99, 0x93, 0x46, 0x45, 0xD, 0xB0, 0xBE, 0x89, 0x73, 0x5, 0xBD, 0xBA, 0x9D, 0x0, 0xFD, 0xC5, 0x0C, 0xF, 0xCE, 0xEC, 0x3A, 0x37, 0xA0, 0xF, 0x8C, 0xE6, 0x7, 0xE, 0x03, 0x67, 0xFE, 0x7E, 0x40, 0xE, 0xC9, 0xEA, 0x36, 0x57, 0xDF, 0x0F, 0x39, 0x0E, 0xB, 0xD3, 0xEF, 0x48, 0x6, 0xA5, 0x55, 0x4, 0xDE, 0x43, 0xF5, 0x5B, 0x, 0x00, 0x58, 0x33, 0x09, 0xAD, 0x35, 0xA3, 0x06, 0xFF, 0x5D, 0xB9, 0xAC, 0xC, 0x9, 0x3, 0xA6, 0x, 0xA, 0xBF, 0x94, 0x59, 0x5A, 0xC8, 0x6B, 0xE8, 0x04, 0xDA, 0x9, 0xC, 0x34, 0xC0, 0xB5, 0xD, 0xB, 0x87, 0xB6, 0x0A, 0x78, 0xE, 0xC4, 0xFA, 0xB8, 0x4E, 0x7D, 0x7, 0x4, 0xAF, 0xF3, 0xC, 0xDB, 0x38, 0xDD, 0xFC, 0x3D, 0xCB, 0x6, 0xF8, 0x4, 0x70, 0xC6, 0x9, 0x5, 0xB, 0xD, 0xE7, 0x5F, 0xC3, 0x69, 0xD4, 0x8, 0x8D, 0x74, 0x5, 0xF6, 0x4F, 0xFB, 0xAE, 0xE5, 0x3B, 0xAB, 0x9E, 0x5, 0x3, 0x85, ; main.c /*************************************************************** / / Projet: Voiture telecommandee (partie voiture) / Version: 0. / Notes: PIC Cadence a 0Mhz / Emission/reception a 4800bps / bit start, bit stop, 0 bit parite / un aller-retour = 4ms a 400bps / / Protocol reception: (5-6 bytes) / / Packet par defaut / / - 0xFF (dummy) / - 0xC9 / - 0x5E / - flags / * polarite moteur gauche / * polarite moteur droit / * freins / * packet defaut / - puissance (ou vitesse en PID) moteur gauche / - puissance (ou vitesse en PID) moteur droit / - CRC / / Packet config / / - 0xFF (dummy) / - 0xC9 / - 0x5E / - flags / * lumieres / * phares / * PID / * ABS / * packet config / - coefficient de proportionalite / - coefficient d integration / - coefficient de derivation 58 TPE 00/003 - Voiture Télécommandée
59 ::La voiture - main.c La Programmation / - CRC / / Protocol emission: (7-9 bytes) / / - 0xFF (dummy) / - 0xC9 / - 0x5E / - flags / * direction ( bit) / * indicateur batterie (7 bits) / - vitesse moteur gauche / - vitesse moteur droit / - vitesse roue arriere / - puissance moteur gauche (uniquement en PID) / - puissance moteur droit (uniquement en PID) / - CRC / / Configuration PIN: / / - Entrees: / RA0: Tension du testeur de batterie / RA: Vref- / RA3: Vref+ / RA4: Capteur de vitesse moteur gauche / RC0: Capteur de vitesse moteur droit / RB0: Capteur de vitesse roue arriere / RA5: Capteur de direction / RC7: Recepteur radio / - Sorties: / RA: Commande du testeur de batterie / RB: LED Power / RB: LED reception / RB3: LED emmission / RB4: LED mauvaise reception / RB5: LED freinage / RB6: Phares / RB7: Lumieres / RC5:!Freins par resistances / RC: Puissance du moteur droit / RC: Puissance du moteur gauche / RC3: Polarite du moteur gauche / RC4: Polarite du moteur droit / RC6: Emmeteur radio /***************************************************************/ #include pic.h // PIC 6F876 #include crc.h // CRC-8 tables CONFIG(HS & WDTEN & PWRTEN & BOREN & \ LVPDIS & DPROT & WRTDIS & DEBUGDIS & UNPROTECT); // fuses config #define bitno(adr,bit) ((unsigned)(&adr)*8+(bit)) #define bitset(var,bit) var = << bit #define bitclr(var,bit) var &= ~( << bit) //PINs defines #define LED_POWER RB // LED Power #define LED_RX RB // LED reception #define LED_TX RB3 // LED emmission #define LED_BADPACKET RB4 // LED mauvaise reception #define LED_BRAKES RB5 // LED freinage #define LIGHTS RB6 // Phares #define CAR_LIGHTS RB7 // Phares #define BRAKES RC5 // Freins par resistance #define BAT_TESTER RA // Commande du testeur de batterie #define POL_L RC3 // Polarite du moteur gauche #define POL_R RC4 // Polarite du moteur droit #define DIRECTION RA5 // Capteur de direction roue arriere #define SET_BRAKES { LED_BRAKES = ; BRAKES = 0; #define CLR_BRAKES { LED_BRAKES = 0; BRAKES = ; volatile struct { unsigned IDLE : ; unsigned NEW_SPEED : ; unsigned DIRECTION : ; unsigned OVERSPEEDL : ; unsigned OVERSPEEDR : ; unsigned PID : ; unsigned ABS : ; unsigned : ; Flags; volatile struct { unsigned SENDING : ; unsigned RX_CONFIG : ; unsigned RX_TIMEOUT : ; unsigned TMR50 : ; TPE 00/003 - Voiture Télécommandée 59
60 La Programmation ::La voiture - main.c unsigned : 4; Flags; volatile unsigned char Battery=0; volatile unsigned char SpeedL; // vitesse instantanee volatile unsigned char SpeedR; volatile unsigned char SpeedB; volatile unsigned char ThSpeedL; // vitesse theoriques volatile unsigned char ThSpeedR; volatile unsigned char Kp; volatile unsigned char Ki; volatile unsigned char Kd; // coeff Init() { TRISA = 0b0; TRISB = 0b ; TRISC = 0b000000; PORTA = 0; PORTB = 0; PORTC = 0; // = entree OPTION = 0b00000; // resistances de pull-up off // TMR0 : RA4 // prescale ADCON0 = 0b ; ADCON = 0b000; // Fosc/3 // RA0 en analogique TMRH = 0xFF; TCON = 0b00000; // prescale // Channel RA0 // RA Vref- // RA3 Vref+ // le reste en numerique // not sync // TMR = RC0 PR = 0xFF; TCON = 0b0000; // prescale 4 RCSTA = 0b ; TXSTA = 0b ; SPBRG = 64; // Low Speed // postscale // Transmission enabled // 0e6/(64*(64+)) = 4808bps (0.6% d erreur) main() { CCPCON = 0b000000; CCPCON = 0b000000; PIE = 0b0000; PIE = 0; INTCON = 0b00000; Init(); SPEN = ; GIE = ; LED_POWER = ; Flags.IDLE = ; // PWM mode // ADIE RCIE TMRIE TMRIE // PEIE T0IE INTE while() { asm( clrwdt ); if(flags.idle) { SET_BRAKES; else if(flags.new_speed && Flags.PID) { Flags.NEW_SPEED = 0; interrupt isr() { static unsigned char Timer5; static unsigned char Timer50; static unsigned char Count_SpeedB; static unsigned char Ptr; static unsigned char CRC; static unsigned char RxBuffer[7]; if(txif && TXIE) { if(flags.sending) { unsigned char TX; if(ptr == 0) { CRC = 0; 60 TPE 00/003 - Voiture Télécommandée
61 ::La voiture - main.c La Programmation else { TX = 0xFF; else if(ptr == ) TX = 0xC9; else if(ptr == ) TX = 0x5E; else if(ptr == 3) { bitclr(battery,7); if(flags.direction) bitset(battery,7); TX = Battery; else if(ptr == 4) TX = SpeedL; else if(ptr == 5) TX = SpeedR; else if(ptr == 6) TX = SpeedB; else if(ptr == 7) { if(flags.pid) TX = CCPRH; else { TX = CRC; Ptr = -; Flags.SENDING = 0; else if(ptr == 8) TX = CCPRH; else if(ptr == 9) { TX = CRC; Ptr = -; Flags.SENDING = 0; Ptr++; if(ptr) CRC ^= CRCTable[TX]; TXREG = TX; CREN = ; TXIE = 0; if(rcif) { Flags.RX_TIMEOUT = 0; LED_RX = ; if(ferr) { unsigned char RX; RX = RCREG; CREN = 0; CREN = ; LED_BADPACKET = ; LED_RX = 0; Ptr = 0; else { unsigned char RX = RCREG; RxBuffer[Ptr] = RX; if(ptr == 0) { CRC = 0; LED_RX = 0; if(rx!= 0xC9) Ptr--; else if(ptr == && RX!= 0x5E) { LED_BADPACKET = ; LED_RX = 0; Ptr = -; else if(ptr == ) { Flags.RX_CONFIG = 0; if(bitno(rx,0) == ) Flags.RX_CONFIG = ; else if(ptr == 5 &&!Flags.RX_CONFIG) { Flags.SENDING = ; TXIE = ; LED_RX = 0; Ptr = -; if(rx!= CRC) LED_BADPACKET = ; else { if(bitno(rxbuffer[],)) SET_BRAKES else CLR_BRAKES if(bitno(rxbuffer[],)) POL_R = ; else POL_R = 0; if(bitno(rxbuffer[],3)) POL_L = ; else POL_L = 0; if(flags.pid) { ThSpeedL = RxBuffer[3]; ThSpeedR = RxBuffer[4]; else { CCPRL = RxBuffer[3]; CCPRL = RxBuffer[4]; TPE 00/003 - Voiture Télécommandée 6
62 La Programmation ::La voiture - main.c else if(ptr == 6) { Flags.SENDING = ; TXIE = ; LED_RX = 0; Ptr = -; if(rx!= CRC) LED_BADPACKET = ; else { if(bitno(rxbuffer[],)) Flags.ABS = ; else Flags.ABS = 0; if(bitno(rxbuffer[],)) Flags.PID = ; else Flags.PID = 0; if(bitno(rxbuffer[],3)) LIGHTS = ; else LIGHTS = 0; if(bitno(rxbuffer[],4)) CAR_LIGHTS = ; else CAR_LIGHTS = 0; Kp = RxBuffer[3]; Ki = RxBuffer[4]; Kd = RxBuffer[5]; Ptr++; if(ptr) CRC ^= CRCTable[RX]; if(intf) { INTF = 0; Count_SpeedB++; if(count_speedb == 0) Count_SpeedB--; //overflow handling if(tmr0if) { TMR0IF = 0; Flags.OVERSPEEDL = ; if(tmrif) { TMRIF = 0; TMRH = 0xFF; Flags.OVERSPEEDR = ; if(tmrif) { //.4576ms trigger TMRIF = 0; if(!flags.sending) { if(flags.rx_timeout == ) { if(ptr) { Ptr = 0; CRC = 0; LED_RX = 0; LED_BADPACKET = ; Flags.RX_TIMEOUT = ; Timer5++; Timer50++; if(timer5 == 0) { // Speed trigger Timer5 = 0; SpeedL = TMR0; TMR0 -= SpeedL; SpeedR = TMRL; TMRL -= SpeedR; SpeedB = Count_SpeedB; Count_SpeedB = 0; if(flags.overspeedl) { Flags.OVERSPEEDL = 0; SpeedL = 0xFF; if(flags.overspeedr) { Flags.OVERSPEEDR = 0; SpeedR = 0xFF; if(timer50 == 0) { Flags.TMR50 = ; Timer50 = 0; LED_BADPACKET = 0; if(flags.idle) LED_POWER ^= ; else LED_POWER = ; 6 TPE 00/003 - Voiture Télécommandée
63 ::La voiture - main.c La Programmation Le logiciel PC La télécommande doit être gérée en temps-réel avec les courbes de vitesses, de puissances, et d accéleration en temps-réel. Le programme est composé de plusieurs threads. La thread principale, qui va receptionner les messages de l utilisateur et redessiner constement la fenêtre. La thread qui va s occuper de recevoir des données par le port série (et puisqu on travaille en halt-duplex, on va devoir filtrer la réception parasite qui provient de l emission, en effet le récepteur Aurel va capter ce que l émetteur envoie). La thread qui va s occuper de l envoie des données avec tout les timings nécéssaires pour la détection de paquets perdus, etc... La thread qui va s occuper du timing entre le compteur de FPS, le tracage des graphes (précis à la µs près grâce à certaine routine écrite en assembleur dans perf.cpp), et les statistiques. Et la thread qui va gérer le joystick. Lorsqu on utilise des variables communes entre deux threads, il faut les déclarer volatile sinon la valeur de la variable n est pas rechagée dans les registres (EAX, EBX, etc...). Pour synchroniser les threads entre-elle, on va utiliser des event, des mutex ou encore des semaphores. un event est un évenement. Une thread peut attendre un evenement et reste en veille, dès qu une aure thread va set l event, la thread qui attendait va être de nouveau active. Un mutex est commme un ticket que les thread se passent entre-elles. Un semaphore est comme un lot de tickets, une thread peut prendre un tiket, et le reposer. Si il n y a plus de ticket, on attends qu un se libère. Ceci est très utilisé lors de partages de ressources. Le C++ est un langage orienté objet. Un objet est créé dynamiquement à patir d une classe qui peut être hierachisée. Dans notre programme, la classe CModule est la base de tout les modules de notre interface (graphe, barres des moteurs, etc...). Dans cette classe se trouve tout les objets de notre programme, ainsi ils peuvent s interchanger des informations. Les classes CCom, CEngine, CFps, CGraph, CInput, CRecorder, CSpeed, CStats sont toutes des classes dérivées de CModules. Exemple d objets : nous avons deux moteurs a piloter qui ont les même propriétés donc on utilise deux objects de CEngine : lpenginel et lpenginer. La classe CModule a pour constructeur par défaut l initialiseur de sufraces DirectX. il intègre aussi la gestion de la souris par défaut, ainsi, si une classes dérivé ne veut pas utiliser les messages provenant souris, elle peut tout simplement les ignorer. C est l utilisation du mot-clef virtual. D ailleurs ces messages souris sont traités avant d être dispachés au sein du programme puisque la fenêtre d utilisation peut être resizer sans restrictions, donc il faut éffectuer une sorte de mise à l echelle pour que chaque module puisse s y retrouver. Par ailleurs, il faut que le programme traite quel est le module qui est sous la souris. Autre classe à venir : CBar et CButton, ce qui permettra de rendre la fenêtre plus animée. Par ailleurs, il faudra faire un emplacement pour les transmissions et pour le paramétrage de la voiture tel que les coefficients etc... L interface de la télécommande TPE 00/003 - Voiture Télécommandée 63
64 La Programmation ::CarRemote - main.cpp Main.cpp #define WIN3_LEAN_AND_MEAN #define INITGUID #define WIDTH 04 #define HEIGHT 768 #define LEFT 0 #define RIGHT #include windows.h #include winbase.h #include resource.h #include stdlib.h #include ddraw.h #include engine.h #include graph.h #include stats.h #include speed.h #include recorder.h #include fps.h #include input.h #include com.h #include module.h #define SAFE_DELETE(a) if(a) {delete a,a=0; #define SAFE_RELEASE(a) if(a) {a->release(),a=0; #define CREATE_SURFACE(a,b,c,d) ddsd.dwwidth=c, ddsd.dwheight=d, lpdd->createsurface(&ddsd,&a,0), LoadSurface(&a,&b,0,0); #include perf.h // // Globals Variables // HWND hwnd=0; HINSTANCE hins; HCURSOR harrow,hsize; CModule* lpmodule=0; RECT rcwin; bool bwindowed=,binit=0,brun=0; LPDIRECTDRAW7 lpdd=0; DDSURFACEDESC ddsd; unsigned long ulfpscount=0; float fwinratio=; HANDLE hnexttick=0; // // Surfaces; // LPDIRECTDRAWSURFACE7 lpddsprimary=0; LPDIRECTDRAWSURFACE7 lpddsback=0; LPDIRECTDRAWSURFACE7 lpddsbackground=0; // // divround() : divide, and round // long divround(long num,float num) { _asm { FILD num FLD num FDIV FRNDINT FISTP num WAIT return num; // // mulround() : divide, and round // long mulround(long num,float num) { _asm { FILD DWORD PTR num FLD num FMUL FRNDINT FISTP num WAIT return num; // // Delete() Free memory! // void Delete(void) { binit=0; brun=0; WaitForSingleObject(hNextTick,INFINITE); lpmodule->freememory(); SAFE_DELETE(lpModule); SAFE_RELEASE(lpDDSBackGround); SAFE_RELEASE(lpDDSBack); SAFE_RELEASE(lpDDSPrimary); // TPE 00/003 - Voiture Télécommandée
65 ::CarRemote - main.cpp La Programmation // Fatal Error! // void Error(char* error) { MessageBox(0,error,0,MB_ICONERROR); Delete(); SAFE_RELEASE(lpDD); exit(0); // // LoadSurface(char *szbitmap) : Load a Bitmap in a surface from file // LPDIRECTDRAWSURFACE7 LoadSurface(char* szbitmap) { LPDIRECTDRAWSURFACE7 lpsurf=0; DDSURFACEDESC sdesc; HBITMAP hbitmap=0; BITMAP Bitmap; HDC hdcb=0,hdcs=0; char szbitpath[00]; strcpy(szbitpath, gfx\\ ); strcat(szbitpath,szbitmap); hbitmap=(hbitmap)loadimage(hins, szbitpath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE LR_CREATEDIBSECTION); if(!hbitmap) { wsprintf(szbitpath, Error loading %s,szbitmap); Error(szBitPath); hdcb=createcompatibledc(0); SelectObject(hDCb,hBitmap); GetObject(hBitmap,sizeof(BITMAP),&Bitmap); ZeroMemory(&sDesc,sizeof(sDesc)); sdesc.dwsize = sizeof(sdesc); sdesc.dwflags = DDSD_CAPS DDSD_WIDTH DDSD_HEIGHT; sdesc.dwwidth = Bitmap.bmWidth; sdesc.dwheight = Bitmap.bmHeight; sdesc.ddscaps.dwcaps= DDSCAPS_OFFSCREENPLAIN; if(lpdd->createsurface(&sdesc,&lpsurf,0)!=dd_ok) Error( Can t Create surface ); lpsurf->getdc(&hdcs); BitBlt(hDCs,0,0,sDesc.dwWidth,sDesc.dwHeight,hDCb,0,0,SRCCOPY); DeleteDC(hDCb); if(hdcs) lpsurf->releasedc(hdcs); DeleteObject(hBitmap); return lpsurf; // // LoadSurface(int rsbitmap) : Load a Bitmap in a surface from ressource // LPDIRECTDRAWSURFACE7 LoadSurface(int rsbitmap) { LPDIRECTDRAWSURFACE7 lpsurf=0; DDSURFACEDESC sdesc; HBITMAP hbitmap=0; BITMAP Bitmap; HDC hdcb=0,hdcs=0; hbitmap=loadbitmap(hins,makeintresource(rsbitmap)); hdcb=createcompatibledc(0); SelectObject(hDCb,hBitmap); GetObject(hBitmap,sizeof(BITMAP),&Bitmap); ZeroMemory(&sDesc,sizeof(sDesc)); sdesc.dwsize = sizeof(sdesc); sdesc.dwflags = DDSD_CAPS DDSD_WIDTH DDSD_HEIGHT; sdesc.dwwidth = Bitmap.bmWidth; sdesc.dwheight = Bitmap.bmHeight; sdesc.ddscaps.dwcaps= DDSCAPS_OFFSCREENPLAIN; if(lpdd->createsurface(&sdesc,&lpsurf,0)!=dd_ok) Error( Can t Create surface ); lpsurf->getdc(&hdcs); BitBlt(hDCs,0,0,sDesc.dwWidth,sDesc.dwHeight,hDCb,0,0,SRCCOPY); DeleteDC(hDCb); if(hdcs) lpsurf->releasedc(hdcs); DeleteObject(hBitmap); return lpsurf; // // NextTick() // #define UPDATE 5000 //us... unsigned long stdcall NextTick(void* cool) { HANDLE hthread = GetCurrentThread(); unsigned long time; while(brun) { SetThreadPriority(hThread,THREAD_PRIORITY_TIME_CRITICAL); time = (DWORD)GetTicks(); lpmodule->nexttick(); SetThreadPriority(hThread,THREAD_PRIORITY_NORMAL); TPE 00/003 - Voiture Télécommandée 65
66 La Programmation ::CarRemote - main.cpp DWORD wait = (DWORD)GetTicks()-time; if((dword)getticks()-time<update) { ((CGraph*)lpModule->lpGraph)->sync=; while((dword)getticks()-time<=update) { continue; else ((CGraph*)lpModule->lpGraph)->sync=0; return 0; // // Init() // void Init() { if(!binit) return; lpddsbackground=loadsurface(idb_background); lpddsback->bltfast(0,0,lpddsbackground,0,ddbltfast_wait); if(!bwindowed) lpddsprimary->blt(0,lpddsbackground,0,ddblt_wait,0); lpmodule=new CModule(lpDD,lpDDSBackGround,&fWinRatio); if(!lpmodule) Error( A+ ); lpmodule->lpddsback=lpddsback; lpmodule->setrectenginel(53,43,83-53,655-43); lpmodule->setrectenginer(97,43,7-97,655-43); lpmodule->setrectrecorder(769,455, , ); lpmodule->setrectfps(950,3,65,30); lpmodule->setrectgraph(30,43,969-30,383-43); lpmodule->setrectstats(640,455, , ); lpmodule->setrectspeed(0,0,,); lpmodule->setrectinput(30,455,00,00); lpmodule->setrectcom(0,0,,); lpmodule->lprecorder=new CRecorder(hWnd); lpmodule->lpfps=new CFps(&ulFpsCount); lpmodule->lpenginel=new CEngine(LEFT); lpmodule->lpenginer=new CEngine(RIGHT); lpmodule->lpspeed=new CSpeed(); lpmodule->lpstats=new CStats(739); lpmodule->lpgraph=new CGraph(); lpmodule->lpinput=new CInput(&rcWin); lpmodule->lpcom=new CCom( COM: baud=4800 parity=n data=8 stop= ); brun=; unsigned long Id=0; hnexttick=createthread(0,0,nexttick,0,0,&id); // // InitDD() // void InitDD() { if(bwindowed) { if(lpdd->setcooperativelevel(hwnd,ddscl_normal)!=dd_ok) Error( Can t define Coop Level ); ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwsize = sizeof(ddsd); ddsd.dwflags = DDSD_CAPS; ddsd.ddscaps.dwcaps = DDSCAPS_PRIMARYSURFACE; if(lpdd->createsurface(&ddsd,&lpddsprimary,0)!=dd_ok) Error( Can t Create Primary Surface ); ddsd.dwflags = DDSD_CAPS DDSD_WIDTH DDSD_HEIGHT; ddsd.dwwidth = WIDTH; ddsd.dwheight = HEIGHT; ddsd.ddscaps.dwcaps = DDSCAPS_OFFSCREENPLAIN; if(lpdd->createsurface(&ddsd,&lpddsback,0)!=dd_ok) Error( Can t Create Back Buffer Surface ); LPDIRECTDRAWCLIPPER lpclipper=0; if(lpdd->createclipper(0,&lpclipper,0)!=dd_ok) Error( Can t Create Clipper ); if(lpclipper->sethwnd(0,hwnd)!=dd_ok) Error( Can t Get hwnd ); if(lpddsprimary->setclipper(lpclipper)!=dd_ok) Error( Can t Select Clipper ); SAFE_RELEASE(lpClipper); else { if(lpdd->setcooperativelevel(hwnd,ddscl_exclusive DDSCL_FULLSCREEN DDSCL_ALLOWREBOOT)!=DD_OK) Error( Can t define Coop Level ); if(lpdd->setdisplaymode(width,height,3,0,0)!=dd_ok) { if(lpdd->setdisplaymode(width,height,6,0,0)!=dd_ok) Error( Can t Switch to 04x768 (6,3) ); ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwsize = sizeof(ddsd); ddsd.dwflags = DDSD_CAPS DDSD_BACKBUFFERCOUNT; ddsd.dwbackbuffercount = ; ddsd.ddscaps.dwcaps = DDSCAPS_PRIMARYSURFACE DDSCAPS_FLIP DDSCAPS_COMPLEX; if(lpdd->createsurface(&ddsd,&lpddsprimary,0)!=dd_ok) 66 TPE 00/003 - Voiture Télécommandée
67 ::CarRemote - main.cpp La Programmation Error( Can t Create Primary Surface ); DDSCAPS ddscaps; ZeroMemory(&ddscaps,sizeof(ddscaps)); ddscaps.dwcaps=ddscaps_backbuffer; if(lpddsprimary->getattachedsurface(&ddscaps,&lpddsback)!=dd_ok) Error( Can t Create Back Buffer Surface ); ZeroMemory(&rcWin,sizeof(RECT)); fwinratio=; binit=; return; // // SwitchMode() // void SwitchMode() { binit=0; DestroyWindow(hWnd); Delete(); bwindowed^=; if(bwindowed) hwnd = CreateWindow( CarRemote, Car Remote Control, WS_VISIBLE WS_POPUP, (GetSystemMetrics(SM_CXSCREEN)-WIDTH)/, (GetSystemMetrics(SM_CYSCREEN)-HEIGHT)/, WIDTH,HEIGHT, 0, 0, hins, 0); else hwnd = CreateWindow( CarRemote, Car Remote Control, WS_VISIBLE WS_POPUP, (GetSystemMetrics(SM_CXSCREEN)-WIDTH)/, (GetSystemMetrics(SM_CYSCREEN)-HEIGHT)/, WIDTH, HEIGHT, 0, 0, hins, 0); InitDD(); Init(); if(bwindowed) SetWindowPos(hWnd, 0, (GetSystemMetrics(SM_CXSCREEN)-WIDTH)/, (GetSystemMetrics(SM_CYSCREEN)-HEIGHT)/, WIDTH, HEIGHT, SWP_NOZORDER); // // RefreshScreen! // #define MAXFPS 000/00 void Refresh() { static long last; if(!binit) return; HRESULT hr; //Starting to blt every surfaces... lpmodule->refreshscreen(); last=maxfps-gettickcount()+last; if(last>maxfps) last=maxfps; else if(last<0) last=0; Sleep(last); while(true) { if(bwindowed) hr=lpddsprimary->blt(&rcwin,lpddsback,0,ddblt_wait,0); else hr=lpddsprimary->flip(0,ddflip_wait DDFLIP_NOVSYNC); //else hr=lpddsprimary->blt(0,lpddsback,0,ddblt_wait,0); if(hr==dderr_surfacelost) { lpddsprimary->restore(); lpddsback->restore(); continue; if(hr!=dderr_wasstilldrawing) continue; ulfpscount++; last=gettickcount(); // // Clip(); // bool Clip(int x,int y,rect *rc,point *pt) { if(x >= rc->left && x <= rc->right && y>=rc->top && y<=rc->bottom) { TPE 00/003 - Voiture Télécommandée 67
68 La Programmation ::CarRemote - main.cpp pt->x=x-rc->left; pt->y=y-rc->top; return ; return 0; // // ProcessMouse(); // void ProcessMouse(int x,int y,bool LButton,bool RButton,bool moving) { x=mulround(x,fwinratio); y=mulround(y,fwinratio); POINT pt; if(clip(x,y,&lpmodule->rcenginel,&pt)) ((CEngine*)lpModule->lpEngineL)->ProcessMouse(pt.x,pt.y,LButton,RButto n,moving); else if(clip(x,y,&lpmodule->rcenginer,&pt)) ((CEngine*)lpModule->lpEngineR)->ProcessMouse(pt.x,pt.y,LButton,R Button,moving); else if(clip(x,y,&lpmodule->rcgraph,&pt)) ((CGraph*)lpModule->lpGraph)->ProcessMouse(pt.x,pt.y,LButton,RButto n,moving); else if(clip(x,y,&lpmodule->rcfps,&pt)) ((CFps*)lpModule->lpFps)->ProcessMouse(pt.x,pt.y,LButton,RButton,movi ng); else if(clip(x,y,&lpmodule->rcinput,&pt)) ((CInput*)lpModule->lpInput)->ProcessMouse(pt.x,pt.y,LButton,RButto n,moving); else if(clip(x,y,&lpmodule->rcrecorder,&pt)) ((CRecorder*)lpModule->lpRecorder)->ProcessMouse(pt.x,pt.y,LButt on,rbutton,moving); else if(clip(x,y,&lpmodule->rcstats,&pt)) ((CStats*)lpModule->lpStats)->ProcessMouse(pt.x,pt.y,LButton,RButto n,moving); // // WindowProc // LRESULT CALLBACK WindowProc(HWND hwnd, unsigned umsg, WPARAM wparam, LPARAM lparam) { static RECT rcpos,rpos; static bool bresizing=0; static POINT move,prev,pt; switch (umsg) { case WM_COMMAND: if(loword(wparam)==idm_switchmode) { SwitchMode(); case WM_LBUTTONDOWN: if (rpos.right-move.x<=0 && rpos.bottom-move.y<=0) { bresizing=; SetCursor(hSize); SetCapture(hWnd); GetCursorPos(&prev); if(bwindowed && HIWORD(lParam)<=30) SetCapture(hWnd); ProcessMouse(LOWORD(lParam),HIWORD(lParam),,(wParam & MK_RBUTTON)? :0,0); case WM_LBUTTONUP: if(bwindowed) { ReleaseCapture(); bresizing=0; prev.x=loword(lparam); prev.y=hiword(lparam); if(prev.x>=973 && prev.x<=997 && prev.y>=3 && prev.y<=7) { Delete(); PostMessage(hWnd,WM_QUIT,0,0); else if(prev.x>=94 && prev.x<=966 && prev.y>=3 && prev.y<=7) { ShowWindow(hWnd,SW_MINIMIZE); ProcessMouse(LOWORD(lParam),HIWORD(lParam),0,(wParam & MK_RBUTTON)? :0,0); case WM_RBUTTONDOWN: ProcessMouse(LOWORD(lParam),HIWORD(lParam),wParam & MK_LBUTTON,,0); case WM_RBUTTONUP: ProcessMouse(LOWORD(lParam),HIWORD(lParam),wParam & MK_LBUTTON,0,0); case WM_MOUSEMOVE: pt.x=loword(lparam); pt.y=hiword(lparam); GetCursorPos(&move); GetWindowRect(hWnd,&rPos); if(bwindowed) { if (rpos.right-move.x<=00 && rpos.bottom-move.y<=00 bresizing) { SetCursor(hSize); if (wparam == MK_LBUTTON) { if(!bresizing) SetCapture(hWnd); int xr,yr; if((move.x-rpos.left)*3/4 >= move.y-rpos.top) { xr = move.x-rpos.left; 68 TPE 00/003 - Voiture Télécommandée
69 ::CarRemote - main.cpp La Programmation yr = (move.x-rpos.left)*3/4; else { xr = (move.y-rpos.top)*4/3; yr = move.y-rpos.top; if(xr <= 5) xr = 5; if(yr <= 5) yr = 5; SetWindowPos(hWnd, 0, 0, 0, xr,yr, SWP_NOZORDER SWP_NOMOVE); GetWindowRect(hWnd,&rcWin); fwinratio=(float)width/(float)(rpos.right-rpos.left); Refresh(); bresizing=; else if ((wparam == MK_LBUTTON) && (GetCapture() == hwnd)) { SetWindowPos(hWnd, 0, rpos.left+move.x-prev.x, rpos.top+move.y-prev.y, 0, 0, SWP_NOSIZE SWP_NOZORDER); prev=move; ProcessMouse(pt.x, pt.y, (bool)(wparam & MK_LBUTTON), (wparam & MK_RBUTTON)? :0, ); case WM_MOVE: GetWindowRect(hWnd,&rcWin); case WM_CREATE: if(bwindowed) { rcpos.left=(getsystemmetrics(sm_cxscreen)-width)/; rcpos.top=(getsystemmetrics(sm_cyscreen)-height)/; rcpos.right=rcpos.left+width-5; rcpos.bottom=rcpos.top+height-5; case WM_CLOSE: Delete(); PostMessage(hWnd,WM_QUIT,0,0); default: return DefWindowProc(hWnd, umsg, wparam, lparam); return ; // // WinMain // int WINAPI WinMain(HINSTANCE hinstance,hinstance hprevinstance,lpstr lpszcmdline,int ncmdshow) { hins=hinstance; harrow=loadcursor(0,idc_arrow); hsize=loadcursor(0,idc_sizenwse); WNDCLASS wc; wc.style=cs_hredraw CS_VREDRAW CS_DBLCLKS; //wc.style=cs_hredraw CS_VREDRAW; wc.lpfnwndproc=windowproc; wc.cbclsextra=0; wc.cbwndextra=sizeof(dword); wc.hinstance=hinstance; wc.hicon=0; wc.hcursor=harrow; wc.hbrbackground=0; wc.lpszmenuname=0; wc.lpszclassname= CarRemote ; if(!registerclass(&wc)) Error( Can t Reg Class ); hwnd = CreateWindow( CarRemote, Car Remote Control, WS_VISIBLE WS_POPUP, (GetSystemMetrics(SM_CXSCREEN)-WIDTH)/, (GetSystemMetrics(SM_CYSCREEN)-HEIGHT)/, WIDTH, HEIGHT, 0, 0, hinstance, TPE 00/003 - Voiture Télécommandée 69
70 La Programmation ::CarRemote - main.cpp 0); if(!hwnd) Error( Can t Create Window ); HACCEL haccel=loadaccelerators(hinstance,makeintresource(idr_key)); if(directdrawcreateex(0,(void**)&lpdd, IID_IDirectDraw7,0)!=DD_OK) Error( Can t init DDraw ); //if(directdrawcreateex((guid*)ddcreate_emulationonly,(void**)&lpdd, IID_IDirectDraw7,0)!=DD_OK) Error( Can t init DDraw ); InitPerf(); InitDD(); Init(); MSG msg; ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); SetForegroundWindow(hWnd); while(true) { if(peekmessage(&msg,0,0,0,pm_noremove)) { if(!(getmessage(&msg,0,0,0))) if(!(translateaccelerator(hwnd,haccel,&msg))) { TranslateMessage(&msg); DispatchMessage(&msg); else { Refresh(); Delete(); SAFE_RELEASE(lpDD); DeleteObject(hArrow); DeleteObject(hSize); return 0; #include windows.h #ifndef PERF_INC #define PERF_INC LONGLONG GetTicks(); void StartBench(); void StopBench(); void InitPerf(); #endif Perf.h Perf.ccp #include windows.h #define BENCH #ifdef BENCH DWORD countertsc=; LONGLONG bench=0; DWORD bench=0; DWORD ulbench=0; DWORD starteip=0; bool bbenchinit=0; #ifdef _DEBUG LONGLONG GetTicks() { //slow version, safe static LONGLONG tsc; _asm { RDTSC //read time stamp counter mov DWORD PTR tsc,eax mov DWORD PTR tsc+4,edx return (LONGLONG)((ULONGLONG)tsc/(ULONGLONG)countertsc); //using ualldiv() #else LONGLONG GetTicks() { //faster version, unsafe? _asm { RDTSC push eax mov eax,edx xor edx,edx div dword ptr countertsc //div edx:eax with ecx mov ecx,eax pop eax div dword ptr countertsc mov edx,ecx ret return 0; //dummy #endif void StartBench() { if(starteip) return; //already running _asm { mov eax,[ebp+4] //get EIP mov dword ptr starteip,eax bench=gettickcount(); //store date bench=getticks(); 70 TPE 00/003 - Voiture Télécommandée
71 ::CarRemote - Perf.cpp La Programmation void StopBench() { static LONGLONG benchbis=0; if(!starteip) return; //not running benchbis=getticks(); bench=gettickcount()-bench; //calculate delta static DWORD endeip=0; if(!bbenchinit) { //used to calibrate starteip=0; return; _asm { mov eax,[ebp+4] //Get EIP sub eax,5 mov dword ptr endeip,eax benchbis-=ulbench; // if(benchbis>=bench) bench=benchbis-bench; else bench=0; static char szbench[80]; //not unsing stack wsprintf(szbench, Start EIP: %08X\nEnd EIP: %08X\n\n%uµs\n%ums, starteip, endeip, (unsigned long)bench, (unsigned long)bench); starteip=0; //not running anymore MessageBox(0,szBench, BenchMark,0); //dispay bench result #define BENCHPASS 5000 void CalibrateBench() { //get execution time for startbench() and stopbench() LONGLONG pass,pass; GetCurrentProcessId(); pass=getticks(); for(unsigned int i=benchpass;i>0;i--) { _asm nop pass=getticks()-pass; pass=getticks(); for(i=benchpass;i>0;i--) { StartBench(); StopBench(); pass=getticks()-pass; ulbench=((dword)pass-(dword)pass)/benchpass; bbenchinit=; void CalibrateTicks() { LONGLONG freq,count,count; LONGLONG tsc,tsc; QueryPerformanceFrequency((LARGE_INTEGER*)&freq); //get a precise timer QueryPerformanceCounter((LARGE_INTEGER*)&count); _asm { RDTSC mov DWORD PTR tsc,eax mov DWORD PTR tsc+4,edx Sleep(500); //wait a little while... QueryPerformanceCounter((LARGE_INTEGER*)&count); _asm { RDTSC mov DWORD PTR tsc,eax mov DWORD PTR tsc+4,edx count-=count; tsc-=tsc; double tsc=((double)tsc*(double)freq)/(double)count; //calculate CPU clock tsc*= ; //µs presision double show=0; _asm { fld qword ptr tsc fst show FRNDINT //round result fistp dword ptr countertsc wait //safe // char szcpu[50]= Found CPU Frequency: ; // gcvt(show,0,szcpu+); // MessageBox(0,szCPU, CPU frequency,0); #endif #ifdef BENCH void InitPerf() { CalibrateTicks(); CalibrateBench(); #endif TPE 00/003 - Voiture Télécommandée 7
72 La Programmation ::CarRemote - Module.h Module.h // Module.h: interface for the CModule class. // ////////////////////////////////////////////////////////////////////// #include ddraw.h #include windows.h #if!defined(afx_module_h 6A5A6B9_6FB_474_9647_74CD3B0B0747 INCLUDED_) #define AFX_MODULE_H 6A5A6B9_6FB_474_9647_74CD3B0B0747 INCLUDED_ #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 class CModule { public: void FreeMemory(); CModule(LPDIRECTDRAW7 lpdd_,lpdirectdrawsurface7 lpsappback_,float* ratio); SetRectRecorder(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectFps(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectEngineL(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectEngineR(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectSpeed(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectStats(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectGraph(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectInput(unsigned int x,unsigned int y,unsigned int width,unsigned int height); SetRectCom(unsigned int x,unsigned int y,unsigned int width,unsigned int height); void RefreshScreen(); virtual void ProcessMouse(int x,int y,bool LButton,bool RButton,bool moving) { ; virtual void NextTick(); static Init(CModule* ptr); CModule() { virtual ~CModule(); LPDIRECTDRAWSURFACE7 LPDIRECTDRAWSURFACE7 RECT bool lpsback; lpsurf; rc; bupdate; static LPDIRECTDRAWSURFACE7 lpddsback; static LPDIRECTDRAWSURFACE7 lpsappback; static LPDIRECTDRAW7 lpdd; static RECT static RECT static RECT static RECT static RECT static RECT static RECT static RECT static RECT static CModule* static CModule* static CModule* static CModule* static CModule* static CModule* static CModule* static CModule* static CModule* static float* rcrecorder; rcfps; rcenginel; rcenginer; rcspeed; rcstats; rcgraph; rcinput; rccom; lpenginel; lpfps; lpenginer; lpgraph; lpstats; lpspeed; lprecorder; lpinput; lpcom; fwinratio; private: SetRect(RECT* rc,unsigned int x,unsigned int y,unsigned int width,unsigned int height); ; #endif //!defined(afx_module_h 6A5A6B9_6FB_474_9647_74CD3B0B0747 INCLUDED_) 7 TPE 00/003 - Voiture Télécommandée
73 ::CarRemote - Module.cpp La Programmation Module.cpp // Module.cpp: implementation of the CModule class. // ////////////////////////////////////////////////////////////////////// #include Module.h #include windows.h #define SAFE_DELETE(a) if(a) {delete a,a=0; #define SAFE_RELEASE(a) if(a) {a->release(),a=0; LPDIRECTDRAWSURFACE7 LoadSurface(char* szbitmap); void Error(char* error); //Static definitions LPDIRECTDRAW7 LPDIRECTDRAWSURFACE7 LPDIRECTDRAWSURFACE7 RECT RECT RECT RECT RECT RECT RECT RECT RECT CModule* CModule* CModule* CModule* CModule* CModule* CModule* CModule* CModule* float* CModule::lpDD; CModule::lpDDSBack; CModule::lpSAppBack; CModule::rcRecorder; CModule::rcFps; CModule::rcEngineL; CModule::rcEngineR; CModule::rcSpeed; CModule::rcStats; CModule::rcGraph; CModule::rcInput; CModule::rcCom; CModule::lpEngineL; CModule::lpFps; CModule::lpEngineR; CModule::lpGraph; CModule::lpStats; CModule::lpSpeed; CModule::lpRecorder; CModule::lpInput; CModule::lpCom; CModule::fWinRatio; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CModule::CModule(LPDIRECTDRAW7 lpdd_,lpdirectdrawsurface7 lpsappback_,float* ratio) { fwinratio=ratio; lpdd=lpdd_; lpsappback=lpsappback_; CModule::~CModule() { CModule::SetRect(RECT* rc,unsigned int x,unsigned int y,unsigned int width,unsigned int height) { rc->left=x; rc->top=y; rc->right=x+width; rc->bottom=y+height; CModule::SetRectRecorder(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcRecorder,x,y,width,height); CModule::SetRectFps(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcFps,x,y,width,height); CModule::SetRectEngineL(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcEngineL,x,y,width,height); CModule::SetRectEngineR(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcEngineR,x,y,width,height); CModule::SetRectSpeed(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcSpeed,x,y,width,height); CModule::SetRectStats(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcStats,x,y,width,height); CModule::SetRectGraph(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcGraph,x,y,width,height); CModule::SetRectInput(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcInput,x,y,width,height); CModule::SetRectCom(unsigned int x,unsigned int y,unsigned int width,unsigned int height) { SetRect(&rcCom,x,y,width,height); TPE 00/003 - Voiture Télécommandée 73
74 La Programmation ::CarRemote - Module.cpp CModule::Init(CModule* ptr) { RECT* rc; if(ptr==lpfps) rc=&rcfps; else if(ptr==lprecorder) rc=&rcrecorder; else if(ptr==lpstats) rc=&rcstats; else if(ptr==lpspeed) rc=&rcspeed; else if(ptr==lpgraph) rc=&rcgraph; else if(ptr==lpenginel) rc=&rcenginel; else if(ptr==lpenginer) rc=&rcenginer; else if(ptr==lpinput) rc=&rcinput; else if(ptr==lpcom) rc=&rccom; else return 0; DDSURFACEDESC ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwsize = sizeof(ddsd); ddsd.dwflags = DDSD_CAPS DDSD_WIDTH DDSD_HEIGHT; ddsd.dwwidth = rc->right-rc->left; ddsd.dwheight = rc->bottom-rc->top; ddsd.ddscaps.dwcaps = DDSCAPS_OFFSCREENPLAIN; if(lpdd->createsurface(&ddsd,&ptr->lpsback,0)!=dd_ok) Error( Can t Create surface ); if(lpdd->createsurface(&ddsd,&ptr->lpsurf,0)!=dd_ok) Error( Can t Create surface ); ptr->lpsback->blt(0,lpsappback,rc,ddblt_wait,0); ptr->lpsurf->blt(0,lpsappback,rc,ddblt_wait,0); return 0; void CModule::RefreshScreen() { if(lpfps && lpfps->bupdate) lpddsback->bltfast(rcfps.left,rcfps.top,lpfps->lpsurf,0,ddbltfast_wait); lpfps->bupdate = 0 ; if(lpenginel && lpenginel->bupdate) lpddsback->bltfast(rcenginel.left,rcenginel.top,lpenginel- >lpsurf,0,ddbltfast_wait); lpenginel->bupdate = 0 ; if(lpenginer && lpenginer->bupdate) lpddsback->bltfast(rcenginer.left,rcenginer.top,lpenginer- >lpsurf,0,ddbltfast_wait); lpenginer->bupdate = 0 ; if(lpgraph && lpgraph->bupdate) lpddsback->bltfast(rcgraph.left,rcgraph.top,lpgraph->lpsurf,0,ddbltfast_ WAIT); lpgraph->bupdate = 0 ; if(lpstats && lpstats->bupdate) lpddsback->bltfast(rcstats.left,rcstats.top,lpstats->lpsurf,0,ddbltfast_ WAIT); lpstats->bupdate = 0 ; if(lpspeed && lpspeed->bupdate) lpddsback->bltfast(rcspeed.left,rcspeed.top,lpspeed->lpsurf,0,ddbltfast_ WAIT); lpspeed->bupdate = 0 ; if(lprecorder && lprecorder->bupdate) lpddsback->bltfast(rcrecorder.left,rcrecorder.top,lprecorder- >lpsurf,0,ddbltfast_wait); lprecorder->bupdate = 0 ; if(lpinput && lpinput->bupdate) lpddsback->bltfast(rcinput.left,rcinput.top,lpinput->lpsurf,0,ddbltfast_ WAIT); lpinput->bupdate = 0 ; if(lpcom && lpcom->bupdate) lpddsback->bltfast(rccom.left,rccom.top,lpcom->lpsurf,0,ddbltfast_wait); lpcom->bupdate = 0 ; void CModule::FreeMemory() { SAFE_DELETE(lpFps); SAFE_DELETE(lpRecorder); SAFE_DELETE(lpStats); SAFE_DELETE(lpSpeed); SAFE_DELETE(lpGraph); SAFE_DELETE(lpEngineL); SAFE_DELETE(lpEngineR); SAFE_DELETE(lpInput); SAFE_DELETE(lpCom); void CModule::NextTick() { lpfps->nexttick(); lpstats->nexttick(); lpgraph->nexttick(); 74 TPE 00/003 - Voiture Télécommandée
75 ::CarRemote - Com.h La Programmation Com.h // Com.h: interface for the CCom class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_com_h 73CA363_BFB5_4CE4_9C4D_8CDEFDEB5ECD INCLUDED_) #define AFX_COM_H 73CA363_BFB5_4CE4_9C4D_8CDEFDEB5ECD INCLUDED_ #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 #include windows.h #include ddraw.h #include module.h typedef bool (CALLBACK* RXPROC)(unsigned char*,int); class CCom : public CModule { public: bool SendConfig; void SendByte(char* buffer,dword len); static unsigned long stdcall RXThread(void* ptr); static unsigned long stdcall LoopThread(void* ptr); SetTD(bool state); SetRTS(bool state); SetDTR(bool state); CCom(char* config); virtual ~CCom(); HANDLE HANDLE HANDLE HANDLE HANDLE hcom; hrxthread; hloopthread; hrx; hrxack; ; unsigned char RXBuffer[56]; volatile DWORD readen; #endif //!defined(afx_com_h 73CA363_BFB5_4CE4_9C4D_8CDEFDEB5ECD INCLUDED_) Com.cpp // Com.cpp: implementation of the CCom class. // ////////////////////////////////////////////////////////////////////// #include Com.h #include crc.h #include windows.h #include engine.h #include speed.h #include perf.h ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// void Error(char* error); void Status(char* status); CCom::CCom(char* conf) { lpcom=this; Init(this); char config[50]; strcpy(config,conf); DCB DCB; hcom = 0; SendConfig = ; ZeroMemory(&DCB,sizeof(DCB)); DCB.DCBlength=sizeof(DCB); BuildCommDCB(config,&DCB); for(unsigned char i=0;i<00;i++) { if(*(config+i)==0) TPE 00/003 - Voiture Télécommandée 75
76 La Programmation ::CarRemote - Com.cpp if(*(config+i)== : ) { *(config+i) = 0; hcom=createfile(config, GENERIC_READ GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if(hcom == INVALID_HANDLE_VALUE) { char error[50]; strcpy(error, Can t open ); strcat(error,config); //Error(error); SetupComm(hCom,0x000,0x000); SetCommState(hCom,&DCB); SetCommMask(hCom,EV_CTS); COMMTIMEOUTS cto; cto.readintervaltimeout=maxdword; cto.readtotaltimeoutconstant=55555; cto.readtotaltimeoutmultiplier=maxdword; cto.writetotaltimeoutconstant=5000; cto.writetotaltimeoutmultiplier=0; SetCommTimeouts(hCom,&cto); DWORD Id; hrx = CreateEvent(0,0,0,0); hrxack = CreateEvent(0,0,0,0); hrxthread=createthread(0,0,rxthread,this,0,&id); hloopthread=createthread(0,0,loopthread,this,0,&id); CCom::~CCom() { SetTD(0); SetDTR(0); SetRTS(0); TerminateThread(hRXThread,0); TerminateThread(hLoopThread,0); WaitForSingleObject(hRXThread,INFINITE); WaitForSingleObject(hLoopThread,INFINITE); CloseHandle(hCom); CCom::SetDTR(bool state) { if(state) EscapeCommFunction(hCom,SETDTR); else EscapeCommFunction(hCom,CLRDTR); CCom::SetRTS(bool state) { if(state) EscapeCommFunction(hCom,SETRTS); else EscapeCommFunction(hCom,CLRRTS); CCom::SetTD(bool state) { if(state) SetCommBreak(hCom); else ClearCommBreak(hCom); unsigned long stdcall CCom::RXThread(void* ptr) { CCom* lpcom=(ccom*)ptr; lpcom->readen=0; ZeroMemory(&lpCom->RXBuffer,sizeof(lpCom->RXBuffer)); OVERLAPPED ov; DWORD readen; ZeroMemory(&ov,sizeof(ov)); ov.hevent=createevent(0,0,0,0); SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL); while() { ReadFile(lpCom->hCom,lpCom->RXBuffer,56,0,&ov); WaitForSingleObject(ov.hEvent,INFINITE); GetOverlappedResult(lpCom->hCom,&ov,&readen,0); if(!readen) continue; lpcom->readen=readen; SetEvent(lpCom->hRX); WaitForSingleObject(lpCom->hRXAck,INFINITE); 76 TPE 00/003 - Voiture Télécommandée
77 ::CarRemote - Com.cpp La Programmation unsigned long stdcall CCom::LoopThread(void* ptr) { CCom* lpcom=(ccom*)ptr; char TxBuffer[6]; ZeroMemory(TxBuffer,sizeof(TxBuffer)); while() { if(lpcom->sendconfig) { else { //WARNING!!!! REMOVE lpcom->sendconfig = 0; //WARNING!!!! REMOVE TxBuffer[0] = 0x; //flags TxBuffer[] = 0; //Kp TxBuffer[] = 0; //Ki TxBuffer[3] = 0; //Kd lpcom->sendbyte(txbuffer,4); int ThrottleL,ThrottleR; if(lpcom->lpenginel) ThrottleL = ((CEngine*)lpCom->lpEngineL)->GetThrottle(); if(lpcom->lpenginer) ThrottleR = ((CEngine*)lpCom->lpEngineR)->GetThrottle(); TxBuffer[0] = (ThrottleL >= 0? 0x8:0) (ThrottleR >= 0? 0x4:0); TxBuffer[] = (unsigned char) abs(throttlel); TxBuffer[] = (unsigned char) abs(throttler); //StartBench(); lpcom->sendbyte(txbuffer,3); //StopBench(); if(waitforsingleobject(lpcom->hrx,00) == WAIT_TIMEOUT) { bool tim = 0; continue; SetEvent(lpCom->hRXAck); return 0; #define HEADER_LEN 3 void CCom::SendByte(char *buffer,dword len) { static OVERLAPPED ovw = {0,0,0,0,0; static OVERLAPPED ovr = {0,0,0,0,0; static bool init=0; static unsigned char Buffer[56] = { 0xFF, 0xC9, 0xE5 ; if(!init) { init=; ovw.hevent = CreateEvent(0,0,0,0); ovr.hevent = CreateEvent(0,0,0,0); unsigned char CRC = CRCTable[0xC9] ^ CRCTable[0xE5]; for(unsigned int i=0;i<len;i++) { Buffer[HEADER_LEN + i] = *(buffer+i); CRC ^= CRCTable[*(buffer+len)]; Buffer[HEADER_LEN + i] = CRC; len += HEADER_LEN+; WriteFile(hCom,Buffer,len,0,&ovw); WaitForSingleObject(ovw.hEvent,INFINITE); Buffer[0]=0; // Flush RX Buffer DWORD readeni=0; while(readeni<len) { if(waitforsingleobject(hrx,50) == WAIT_TIMEOUT) { readeni+=readen; SetEvent(hRXAck); TPE 00/003 - Voiture Télécommandée 77
78 La Programmation ::CarRemote - Engine.h Engine.h #if!defined(afx_engine_h 3BD_4FE9_44F_B4EB_4BC6849EDFD7 INCLUDED_) #define AFX_ENGINE_H 3BD_4FE9_44F_B4EB_4BC6849EDFD7 INCLUDED_ #include windows.h #include ddraw.h #include module.h #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 class CEngine : public CModule { public: CEngine(char Left_Right); virtual ~CEngine(); int GetThrottle() { return Throttle; void SetThrottle(int throttle); virtual void ProcessMouse(int x,int y,bool LButton,bool RButton,bool moving); bool draw; private: LPDIRECTDRAWSURFACE7 lpsfullbar; int Throttle; ; #endif //!defined(afx_engine_h 3BD_4FE9_44F_B4EB_4BC6849EDFD7 INCLUDED_) #include Engine.h #include resource.h #ifndef LEFT #define LEFT 0 #endif #ifndef RIGHT #define RIGHT #endif #define RELEASE(a) if(a) {a->release(),a=0; Engine.cpp LPDIRECTDRAWSURFACE7 LoadSurface(int rsbitmap); void Error(char* error); CEngine::CEngine(char Left_Right) { lpsback=0; LPDIRECTDRAWSURFACE7 lpsbar; //lpsbar=loadsurface( engine_pattern.bmp ); lpsbar=loadsurface(idb_engine_pattern); draw=; if(left_right) lpenginer=this; else lpenginel=this; Init(this); DDSURFACEDESC ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwsize = sizeof(ddsd); ddsd.dwflags = DDSD_CAPS DDSD_WIDTH DDSD_HEIGHT; ddsd.dwwidth = 30; ddsd.dwheight = 56; ddsd.ddscaps.dwcaps = DDSCAPS_OFFSCREENPLAIN; if(lpdd->createsurface(&ddsd,&lpsfullbar,0)!=dd_ok) Error( Can t Create surface ); Throttle=; SetThrottle(0); for(int i=0;i<5;i++) lpsfullbar->bltfast(0,i,lpsbar,0,ddbltfast_wait); RELEASE(lpSBar); CEngine::~CEngine() { RELEASE(lpSFullBar); RELEASE(lpSurf); RELEASE(lpSBack); void CEngine::SetThrottle(int throttle) { if(throttle==throttle) return; if(throttle>56) throttle=56; else if(throttle<-56) throttle=-56; Throttle=throttle; lpsurf->blt(0,lpsback,0,ddblt_wait,0); if(throttle!=0) { static RECT rc = {0,0,30,0; rc.bottom=abs(throttle); if(throttle>0) lpsurf->bltfast(0,56-throttle,lpsfullbar,&rc,ddbltfast_wait); else lpsurf->bltfast(0,56,lpsfullbar,&rc,ddbltfast_wait); bupdate = ; return; void CEngine::ProcessMouse(int x,int y,bool LButton,bool RButton,bool moving) { if (LButton &&!moving) draw^=; 78 TPE 00/003 - Voiture Télécommandée
79 ::CarRemote - Fps.h La Programmation Fps.h // Fps.h: interface for the CFps class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_fps_h 337B0_3D_D9_8D_D8EF4B6B7 INCLUDED_) #define AFX_FPS_H 337B0_3D_D9_8D_D8EF4B6B7 INCLUDED_ #include windows.h #include ddraw.h #include module.h #define COUNT 0 #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 class CFps : public CModule { public: CFps(unsigned long* counter); virtual ~CFps(); virtual void NextTick(); ; unsigned long* HFONT unsigned long ulfpscount; hfont; ulcount[count+][]; #endif //!defined(afx_fps_h 337B0_3D_D9_8D_D8EF4B6B7 INCLUDED_) Fps.cpp // Fps.cpp: implementation of the CFps class. // ////////////////////////////////////////////////////////////////////// #include Fps.h #define RELEASE(a) if(a) {a->release(),a=0; void Error(char* error); #define FPS_X 950 #define FPS_Y 34 ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CFps::CFps(unsigned long* counter) { lpfps=this; ulfpscount=counter; Init(this); hfont = CreateFont(3,0,0,0,0,0,0,0,0, OUT_TT_PRECIS, CLIP_TT_ALWAYS, ANTIALIASED_QUALITY, FF_DONTCARE, Palatino Linotype ); ulcount[count][0]=0; CFps::~CFps() { RELEASE(lpSurf); RELEASE(lpSBack); DeleteObject(hFont); void CFps::NextTick() { float ffps; char szfps[0]; unsigned char len; static unsigned int index=count; index++; if(index>count) index=0; ulcount[index][0]=gettickcount(); ulcount[index][]=*ulfpscount; *ulfpscount=0; lpsurf->blt(0,lpsback,0,0,0); if(ulcount[count][0]==0) return; unsigned long Fps=0; unsigned long time=0; for(int i=0;i<count;i++) Fps+=ulCount[i][]; Fps*=000; TPE 00/003 - Voiture Télécommandée 79
80 La Programmation ::CarRemote - Fps.cpp if(index==count) ffps=(float)fps/(float)(ulcount[count][0]-ulcount[0][0]); else ffps=(float)fps/(float)(ulcount[index][0]-ulcount[index+][0]); if(ffps>=00) gcvt(ffps,4,szfps); else if(ffps>=0) gcvt(ffps,3,szfps); else gcvt(ffps,,szfps); len=strlen(szfps); if(*(szfps+len-)==. ) *(szfps+len-)=0; HDC hdcfps=0; lpsurf->getdc(&hdcfps); if(hdcfps) { SelectObject(hDCFps,hFont); SetBkMode(hDCFps,TRANSPARENT); SetTextColor(hDCFps,RGB(0,0,0)); TextOut(hDCFps,,,szFps,strlen(szFps)); SetTextColor(hDCFps,RGB(55,55,55)); TextOut(hDCFps,0,0,szFps,strlen(szFps)); lpsurf->releasedc(hdcfps); bupdate = ; Graph.h // Graph.h: interface for the CGraph class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_graph_h 6DAE7046_C66_46C_A0B_F6B75DA9837 INCLUDED_) #define AFX_GRAPH_H 6DAE7046_C66_46C_A0B_F6B75DA9837 INCLUDED_ #include windows.h #include ddraw.h #include Engine.h #include stats.h #include module.h #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 class CGraph : public CModule { public: CGraph(); virtual void NextTick(); virtual ~CGraph(); int LPDIRECTDRAWSURFACE7 LPDIRECTDRAWSURFACE7 LPDIRECTDRAWSURFACE7 LPDIRECTDRAWSURFACE7 bool HPEN HPEN HPEN HPEN Width; lps; lps; lpspattern; lpswarning; sync; Pen; Pen; Pen3; Pen4; ; #endif //!defined(afx_graph_h 6DAE7046_C66_46C_A0B_F6B75DA9837 INCLUDED_) 80 TPE 00/003 - Voiture Télécommandée
81 ::CarRemote - Graph.cpp La Programmation Graph.cpp // Graph.cpp: implementation of the CGraph class. // ////////////////////////////////////////////////////////////////////// #include Graph.h #include ddraw.h #include stats.h #include resource.h //#include Engine.h #define RELEASE(a) if(a) {a->release(),a=0; #define UPDATE 0 ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// LPDIRECTDRAWSURFACE7 LoadSurface(int rsbitmap); void Error(char* error); unsigned long stdcall Graphing(void* graph); CGraph::CGraph() { lpgraph=this; sync=; Width = rcgraph.right-rcgraph.left; lpspattern=0; lps=0; lps=0; lpswarning=0; //lpspattern=loadsurface( graph_pattern.bmp ); lpspattern=loadsurface(idb_graph_pattern); Init(this); DDSURFACEDESC ddsd; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwsize = sizeof(ddsd); ddsd.dwflags = DDSD_CAPS DDSD_WIDTH DDSD_HEIGHT; ddsd.dwwidth = Width; ddsd.dwheight = 40; ddsd.ddscaps.dwcaps = DDSCAPS_OFFSCREENPLAIN; if(lpdd->createsurface(&ddsd,&lps,0)!=dd_ok) Error( Can t Create surface ); if(lpdd->createsurface(&ddsd,&lps,0)!=dd_ok) Error( Can t Create surface ); ddsd.dwheight = 60; if(lpdd->createsurface(&ddsd,&lpswarning,0)!=dd_ok) Error( Can t Create surface ); DDBLTFX fx; ZeroMemory(&fx,sizeof(fx)); fx.dwsize=sizeof(fx); fx.dwfillcolor=rgb(55,0,55); lps->blt(0,0,0,ddblt_wait DDBLT_COLORFILL,&fx); lps->blt(0,0,0,ddblt_wait DDBLT_COLORFILL,&fx); HFONT hfont = CreateFont(57,0,0,0,0,0,0,0,0, OUT_TT_PRECIS, CLIP_TT_ALWAYS, ANTIALIASED_QUALITY, FF_DONTCARE, Palatino Linotype ); HDC dc; RECT rect={0,0,width,60; lpswarning->blt(0,lpsback,&rect,ddblt_wait,0); lpswarning->getdc(&dc); SelectObject(dc,hFont); SetBkMode(dc,TRANSPARENT); SetTextColor(dc,RGB(0,0,0)); TextOut(dc,,, WARNING: Synchonisation lost,8); SetTextColor(dc,RGB(55,55,55)); TextOut(dc,0,0, WARNING: Synchonisation lost,8); lpswarning->releasedc(dc); DeleteObject(hFont); DDPIXELFORMAT format; ZeroMemory(&format,sizeof(format)); format.dwsize=sizeof(format); lps->getpixelformat(&format); DDCOLORKEY ck; ck.dwcolorspacehighvalue=format.dwrbitmask format.dwbbitmask; ck.dwcolorspacelowvalue=format.dwrbitmask format.dwbbitmask; lps->setcolorkey(ddckey_srcblt,&ck); lps->setcolorkey(ddckey_srcblt,&ck); Pen=CreatePen(PS_SOLID,,RGB(30,93,08)); Pen=CreatePen(PS_SOLID,,RGB(94,95,40)); Pen3=CreatePen(PS_SOLID,,RGB(03,55,9)); Pen4=CreatePen(PS_SOLID,,RGB(3,40,59)); TPE 00/003 - Voiture Télécommandée 8
82 La Programmation ::CarRemote - Graph.cpp RECT rc = {0,0,5,5; RECT rcd = {0,0,5,5; lpsurf->blt(0,lpsback,0,ddblt_wait,0); while(rc.top<=40) { if(rc.bottom>40) rc.bottom=40; rcd.bottom =40-rc.top; if(rcd.bottom >5) rcd.bottom=5; while(rc.left<=width) { rcd.right=width-rc.left; if(rcd.right>5) rcd.right=5; if(rc.right>width) rc.right=width; lps->blt(&rc,lpspattern,&rcd,ddblt_wait,0); rc.left+=5; rc.right+=5; rc.top+=5; rc.bottom+=5; rc.left=0; rc.right=5; lps->bltfast(0,0,lps,0,ddbltfast_wait); rc.left=width-; CGraph::~CGraph() { RELEASE(lpSBack); RELEASE(lpS); RELEASE(lpS); RELEASE(lpSurf); RELEASE(lpSPattern); RELEASE(lpSWarning); DeleteObject(Pen); DeleteObject(Pen); DeleteObject(Pen3); DeleteObject(Pen4); void CGraph::NextTick() { static RECT rcd = {0,0,5,5; static unsigned char cycle = 4; static unsigned char cyclep = 0; static long Temp = 0; static HDC dc = 0; static int PrevL[5]; static int PrevR[5]; static RECT rc = {39,0,30,5; static RECT rc = {,0,30,40; static RECT rc = {0,0,39,40; static POINT prev = {38,0; static POINT prev = {38,0; static POINT prev3 = {38,0; static POINT prev4 = {38,0; static bool init = 0; if (!init) { rc.left=width-; rc.right=width; rc.right=width; rc.right=width-; prev.x=width-; prev.x=width-; prev3.x=width-; prev4.x=width-; init = ; lps->blt(&rc,lps,&rc,ddblt_wait,0); rc.top=0; rc.bottom=5; while(rc.top<=40) { if(rc.bottom>40) rc.bottom=40; rcd.bottom =40-rc.top; if(rcd.bottom >5) rcd.bottom=5; rcd.left=cycle; rcd.right=cycle+; lps->blt(&rc,lpspattern,&rcd,ddblt_wait,0); rc.top+=5; rc.bottom+=5; //Get Device Context lps->getdc(&dc); // Draw L Throttle if(((cengine*)lpenginel)->draw) { SelectObject(dc,Pen); Temp=0; PrevL[cycleP]=((CEngine*)lpEngineL)->GetThrottle(); for(unsigned int i=0;i<5;i++) Temp+=PrevL[i]; Temp/=5L; Temp=0-(Temp*0)/56; 8 TPE 00/003 - Voiture Télécommandée
83 ::CarRemote - Graph.cpp La Programmation if(temp==40) Temp=39; else if(temp==0) Temp=; MoveToEx(dc,prev.x,prev.y,0); LineTo(dc,Width,Temp); prev.y=temp; //Draw R Throttle if(((cengine*)lpenginer)->draw) { SelectObject(dc,Pen); Temp=0; PrevR[cycleP]=((CEngine*)lpEngineR)->GetThrottle(); for(int i=0;i<5;i++) Temp+=PrevR[i]; Temp/=5L; Temp=0-(Temp*0)/56; if(temp==40) Temp=39; else if(temp==0) Temp=; MoveToEx(dc,prev.x,prev.y,0); LineTo(dc,Width,Temp); prev.y=temp; //Draw Speed; SelectObject(dc,Pen3); Temp=((CStats*)lpStats)->ISpeed; Temp=0-(Temp*0)/590; if(temp==40) Temp=39; else if(temp==0) Temp=; MoveToEx(dc,prev3.x,prev3.y,0); LineTo(dc,Width,Temp); prev3.y=temp; //Draw Acceleration SelectObject(dc,Pen4); Temp=((CStats*)lpStats)->IAccel; Temp=0-(Temp*40)/0; if(temp==40) Temp=39; else if(temp==0) Temp=; MoveToEx(dc,prev4.x,prev4.y,0); LineTo(dc,Width,Temp); prev4.y=temp; //Desync? if(!sync) SetPixel(dc,Width-,0,RGB(55,0,0)); //Done lps->releasedc(dc); dc=0; lpsurf->bltfast(0,0,lpsback,0,ddbltfast_wait); //if(!sync) lpsurf->bltfast(0,0,lpswarning,0,ddbltfast_wait); lpsurf->bltfast(0,0,lps,0,ddbltfast_wait DDBLTFAST_SRCCOLORKEY); cycle++; cyclep++; if(cycle==5) cycle=0; if(cyclep==5)cyclep=0; LPDIRECTDRAWSURFACE7 lpstemp; lpstemp=lps; lps=lps; lps=lpstemp; bupdate = ; return; TPE 00/003 - Voiture Télécommandée 83
84 La Programmation ::CarRemote - Input.h Input.h // Input.h: interface for the CInput class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_input_h 33706F5_5AA_4F74_9AFF_CBB50C53347 INCLUDED_) #define AFX_INPUT_H 33706F5_5AA_4F74_9AFF_CBB50C53347 INCLUDED_ #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 #include windows.h #include ddraw.h #include Engine.h #include stats.h #include module.h class CInput : public CModule { public: virtual void ProcessMouse(int x,int y,bool LButton,bool RButton,bool moving); void ProcessControl(int x,int y,bool FastTurn); CInput(RECT* rc); virtual ~CInput(); ; RECT* lprcwin; #endif //!defined(afx_input_h 33706F5_5AA_4F74_9AFF_CBB50C53347 INCLUDED_) Input.cpp // Input.cpp: implementation of the CInput class. // ////////////////////////////////////////////////////////////////////// #include Input.h #include engine.h ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CInput::CInput(RECT* rc) { lprcwin=rc; lpinput=this; Init(this); CInput::~CInput() { long divround(long num,float num); void CInput::ProcessMouse(int x,int y,bool LButton,bool RButton,bool moving) { RECT rc; HDC dc; if(lbutton) { rc.left=lprcwin->left+divround(rcinput.left,*fwinratio)+; rc.top=lprcwin->top+divround(rcinput.top,*fwinratio)+; rc.right=lprcwin->left+divround(rcinput.right,*fwinratio); rc.bottom=lprcwin->top+divround(rcinput.bottom,*fwinratio); ClipCursor(&rc); lpsurf->bltfast(0,0,lpsback,0,ddbltfast_wait); lpsurf->getdc(&dc); SetPixel(dc,x-,y-,RGB(55,0,0)); SetPixel(dc,x,y-,RGB(55,0,0)); SetPixel(dc,x+,y-,RGB(55,0,0)); SetPixel(dc,x-,y,RGB(55,0,0)); SetPixel(dc,x,y,RGB(55,0,0)); SetPixel(dc,x+,y,RGB(55,0,0)); SetPixel(dc,x-,y+,RGB(55,0,0)); SetPixel(dc,x,y+,RGB(55,0,0)); SetPixel(dc,x+,y+,RGB(55,0,0)); lpsurf->releasedc(dc); bupdate = ; x=x - ( rcinput.right - rcinput.left ) /; y=( rcinput.bottom - rcinput.top ) / - y; x=(x*54)/00; y=(y*70)/00; if(x>45) x=56; if(x<-45) x=-56; if(y>50) y=56; if(y<-50) y=-56; if(x>-0 && x<0) x=0; 84 TPE 00/003 - Voiture Télécommandée
85 ::CarRemote - Input.cpp La Programmation if(y>-0 && y<0) y=0; ProcessControl(x,y,RButton); else ClipCursor(0); void CInput::ProcessControl(int x,int y,bool FastTurn) { int L=y,R=y; if(x!=0) { if(x<0) { if(fastturn) L=L*(x)/56; else L=(L*(56+x))/56; else { if(fastturn) R=-R*(x)/56; else R=(R*(56-x))/56; ((CEngine*)lpEngineL)->SetThrottle(L); ((CEngine*)lpEngineR)->SetThrottle(R); Recorder.h // Recorder.h: interface for the CRecorder class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_recorder_h C3DD596_877_4960_B93B_3B40A08CF97 INCLUDED_) #define AFX_RECORDER_H C3DD596_877_4960_B93B_3B40A08CF97 INCLUDED_ #include windows.h #include ddraw.h #include commdlg.h #include module.h #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 class CRecorder : public CModule { public: void DrawText(HDC dc,char* sztext,rect* rc); void DecRect(RECT* rc); void IncRect(RECT* rc); bool OpenFile(char* FileName); void RefreshButtons(); void PushPause(); void PushStop(); void PushPlay(); void PushRec(); void Play(char* szfile); CRecorder(HWND hwnd); virtual ~CRecorder(); OPENFILENAME open; LPDIRECTDRAWSURFACE7 lpsbuttondown; HFONT HANDLE char char char char bool bool bool bool hfont; hfile; szfilename[00]; sztime[0]; szsize[0]; szstatus[0]; bfilename; btime; bsize; bstatus; HANDLE HANDLE bool unsigned char hrefresh; hrecord; brun; buttons; ; #endif //!defined(afx_recorder_h C3DD596_877_4960_B93B_3B40A08CF97 INCLUDED_) TPE 00/003 - Voiture Télécommandée 85
86 La Programmation ::CarRemote - Recorder.cpp Recorder.cpp // Recorder.cpp: implementation of the CRecorder class. // ////////////////////////////////////////////////////////////////////// #include Recorder.h #include resource.h #define RELEASE(a) if(a) {a->release(),a=0; void Error(char* error); LPDIRECTDRAWSURFACE7 LoadSurface(int rsbitmap); ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// unsigned long stdcall RefreshRecorder(void* tac); CRecorder::CRecorder(HWND hwnd) { lprecorder=this; lpsbuttondown=0; buttons=0; hrecord=0; hrefresh=0; hfile=0; btime=; bsize=; bfilename=; bstatus=; open.lstructsize=sizeof(open); open.hinstance=(hinstance)getwindowlong(hwnd,gwl_hinstance); open.lpstrfilter= Car PlayBack Files (*.car)\0*.car\0 ; open.lpstrcustomfilter=0; open.nmaxcustfilter=0; open.nfilterindex=; open.nmaxfile=300; open.lpstrfiletitle=0; open.nmaxfiletitle=0; open.lpstrinitialdir=0; open.lpstrtitle=0; open.flags=ofn_explorer OFN_OVERWRITEPROMPT; open.nfileoffset=0; open.nfileextension=0; open.lpstrdefext= car ; open.lcustdata=0; open.lpfnhook=0; open.lptemplatename=0; open.hwndowner=hwnd; Init(this); //lpsbuttondown=loadsurface( recorder_buttons.bmp ); lpsbuttondown=loadsurface(idb_recorder_buttons); RefreshButtons(); hfont = CreateFont(3,0,0,0,0,0,0,0,0, OUT_TT_PRECIS, CLIP_TT_ALWAYS, ANTIALIASED_QUALITY, FF_DONTCARE, Palatino Linotype ); brun=; strcpy(sztime, 00:00 ); strcpy(szstatus, Waiting... ); strcpy(szsize, 0 Ko ); strcpy(szfilename, ---- ); unsigned long Id=0; hrefresh=createthread(0,0,&refreshrecorder,this,0,&id); CRecorder::~CRecorder() { brun=0; unsigned long ex=still_active; while(ex==still_active) { GetExitCodeThread(hRefresh,&ex); Sleep(); if(hrecord) CloseHandle(hRecord); CloseHandle(hRefresh); RELEASE(lpSButtonDown); RELEASE(lpSBack); RELEASE(lpSurf); if(hfile) CloseHandle(hFile); DeleteObject(hFont); unsigned long stdcall RefreshRecorder(void* tac) { CRecorder* rec=0; 86 TPE 00/003 - Voiture Télécommandée
87 ::CarRemote - Recorder.cpp La Programmation HDC dc=0; RECT rcsurf = {0,0,00,47; RECT rcstatus = {,5,98,40; RECT rcfilename = {,40,98,75; RECT rcsize = {,75,98,0; RECT rctime = {,0,98,45; rec=(crecorder*)tac; rec->lpsurf->bltfast(0,0,rec->lpsback,&rcsurf,ddbltfast_wait); while(rec->brun==) { rec->lpsurf->getdc(&dc); SelectObject(dc,rec->hFont); SetBkMode(dc,TRANSPARENT); if(rec->bstatus) { rec->drawtext(dc,rec->szstatus,&rcstatus); rec->bstatus=0; if(rec->bfilename) { rec->drawtext(dc,rec->szfilename,&rcfilename); rec->bfilename=0; if(rec->bsize) { rec->drawtext(dc,rec->szsize,&rcsize); rec->bsize=0; if(rec->btime) { rec->drawtext(dc,rec->sztime,&rctime); rec->btime=0; rec->lpsurf->releasedc(dc); dc=0; Sleep(00); return 0; BOOL CALLBACK DialogProca(HWND hwnddlg,uint umsg,wparam wparam,lparam lparam) { switch (umsg) { case WM_INITDIALOG: // return ; case WM_LBUTTONDOWN: EndDialog(hwndDlg,0); return 0; unsigned long stdcall Record(void* tac) { //return 0; CRecorder* rec=0; rec=(crecorder*)tac; rec->open.lpstrtitle= Choose the file to record to ; rec->open.lpstrfile=0; if(!getsavefilename(&rec->open)) { return 0; //int hop=dialogbox(rec->open.hinstance,makeintresource(0),rec->open.hwndowner,dialogproca); HWND hop=createdialog(rec->open.hinstance,makeintresource(0),rec->open.hwndowner,dialogproca); ShowWindow(hop,SW_SHOWNORMAL); MSG msg; while(getmessage(&msg,hop,0,0)) { if(msg.message==wm_lbuttondown) TranslateMessage(&msg); DispatchMessage(&msg); return 0; void CRecorder::Play(char* szfile) { if(openfile(szfile)) { void CRecorder::PushRec() { char vlan[56]; OpenFile(vlan); if(buttons==) { if(hrecord) TerminateThread(hRecord,0); if(hrecord) CloseHandle(hRecord); hrecord=0; unsigned long Id=0; hrefresh=createthread(0,0,&record,this,0,&id); buttons=0; RefreshButtons(); void CRecorder::PushPlay() { if(buttons==) { TPE 00/003 - Voiture Télécommandée 87
88 La Programmation ::CarRemote - Recorder.cpp buttons=0; void CRecorder::PushStop() { if(buttons==3) { buttons=0; void CRecorder::PushPause() { if(buttons==4) { buttons=0; void CRecorder::RefreshButtons() { RECT rc; RECT rcsurf={0,47,00,00; lpsurf->bltfast(0,47,lpsback,&rcsurf,ddbltfast_wait); rc.top=0; rc.bottom=39; switch(buttons) { case : rc.left=0; rc.right=39; lpsurf->bltfast(0,48,lpsbuttondown,&rc,ddbltfast_wait); case : rc.left=47; rc.right=86; lpsurf->bltfast(57,48,lpsbuttondown,&rc,ddbltfast_wait); case 3: rc.left=94; rc.right=33; lpsurf->bltfast(04,48,lpsbuttondown,&rc,ddbltfast_wait); case 4: rc.left=4; rc.right=80; lpsurf->bltfast(5,48,lpsbuttondown,&rc,ddbltfast_wait); bool CRecorder::OpenFile(char* FileName) { if(hfile) CloseHandle(hFile); hfile=0; strcpy(szfilename,filename); hfile=createfile(szfilename, GENERIC_READ GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL FILE_FLAG_SEQUENTIAL_SCAN, 0); if(hfile==invalid_handle_value) { strcpy(szfilename, Cant t open file ); return 0; return ; void CRecorder::IncRect(RECT *rc) { rc->left+=; rc->top+=; rc->right+=; rc->bottom+=; void CRecorder::DecRect(RECT *rc) { rc->left-=; rc->top-=; rc->right-=; rc->bottom-=; void CRecorder::DrawText(HDC dc,char *sztext, RECT *rc) { SetTextColor(dc,RGB(0,0,0)); IncRect(rc); lpsurf->bltfast(rc->left,rc->top,lpsback,rc,ddbltfast_wait); ::DrawText(dc,szText,strlen(szText),rc,DT_CENTER); DecRect(rc); SetTextColor(dc,RGB(55,55,55)); ::DrawText(dc,szText,strlen(szText),rc,DT_CENTER); 88 TPE 00/003 - Voiture Télécommandée
89 ::CarRemote - Speed.h La Programmation Speed.h // Speed.h: interface for the CSpeed class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_speed_h 36079A0_3ED_4DDE_9D5_FE9B9998 INCLUDED_) #define AFX_SPEED_H 36079A0_3ED_4DDE_9D5_FE9B9998 INCLUDED_ #include module.h #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 class CSpeed : public CModule { public: CSpeed(); virtual ~CSpeed(); SetSpeed(int speed); void ResetMaxSpeed() { MaxSpeed=Speed; int GetSpeed() { return Speed; int GetMaxSpeed() { return MaxSpeed; private: int int Speed; MaxSpeed; ; #endif //!defined(afx_speed_h 36079A0_3ED_4DDE_9D5_FE9B9998 INCLUDED_) Speed.cpp // Speed.cpp: implementation of the CSpeed class. // ////////////////////////////////////////////////////////////////////// #include Speed.h ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSpeed::CSpeed() { lpspeed=this; Init(this); Speed=0; MaxSpeed=0; CSpeed::~CSpeed() { CSpeed::SetSpeed(int speed) { Speed=speed; if(speed>maxspeed) MaxSpeed=Speed; TPE 00/003 - Voiture Télécommandée 89
90 La Programmation ::CarRemote - Stats.h Stats.h // Stats.h: interface for the CStats class. // ////////////////////////////////////////////////////////////////////// #if!defined(afx_stats_h BE575F69_04F0_4F00_8FE5_DABABA50D INCLUDED_) #define AFX_STATS_H BE575F69_04F0_4F00_8FE5_DABABA50D INCLUDED_ #include windows.h #include ddraw.h #include Engine.h #include Speed.h #include module.h #if _MSC_VER > 000 #pragma once #endif // _MSC_VER > 000 class CStats : public CModule { public: CStats(unsigned int len); virtual void NextTick(); virtual ~CStats(); ; HFONT int* int* int* unsigned int long long Lenght; hfont; Speed; Accel; Power; ISpeed; IAccel; #endif //!defined(afx_stats_h BE575F69_04F0_4F00_8FE5_DABABA50D INCLUDED_) Stats.cpp // Stats.cpp: implementation of the CStats class. // ////////////////////////////////////////////////////////////////////// #define BENCH #include Stats.h #include Engine.h #include Speed.h #include perf.h ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// void Error(char* error); unsigned long stdcall Stating(void* tac); #define RELEASE(a) if(a) {a->release(),a=0; #define UPDATE 0 //#define LENGHT 30 CStats::CStats(unsigned int len) { lpstats=this; Lenght=len; Speed=new int[lenght]; Accel=new int[lenght]; Power=new int[lenght]; ISpeed=0; IAccel=0; ZeroMemory(Speed,Lenght*sizeof(int)); ZeroMemory(Accel,Lenght*sizeof(int)); ZeroMemory(Power,Lenght*sizeof(int)); hfont=0; Init(this); hfont = CreateFont(4,0,0,0,500,0,0,0,0, OUT_TT_PRECIS, CLIP_TT_ALWAYS, ANTIALIASED_QUALITY, FF_DONTCARE, Palatino Linotype ); CStats::~CStats() { RELEASE(lpSBack); RELEASE(lpSurf); DeleteObject(hFont); delete Speed; 90 TPE 00/003 - Voiture Télécommandée
91 ::CarRemote - Stats.cpp La Programmation delete Accel; delete Power; #define AccelSmooth 0 void CStats::NextTick() { static bool sync=; static unsigned long Time = 0; static long Temp = 0; static unsigned int cycle = 0; static unsigned int cyclea = Lenght-; static RECT rc = {,4,58,96; static RECT rc = {0,,60,98; static HDC dc = 0; static char sztemp[00]; static DDBLTFX fx; static long MSpeed=0; static long ASpeed=0; static long AAccel=0; static long IPower=0; static long APower=0; static long AccelS[AccelSmooth]; static char szlights[4]; int L=0; int R=0; strcpy(szlights, Off ); ZeroMemory(&fx,sizeof(fx)); fx.dwsize=sizeof(fx); fx.dwfillcolor=rgb(55,0,55); { Time=GetTickCount(); L=((CEngine*)lpEngineL)->GetThrottle(); R=((CEngine*)lpEngineR)->GetThrottle(); //IPower=abs(L)+abs(R); IPower=L+R; //Used for fake speed IPower=IPower*00/5; *(Power+cycle)=IPower; Temp=0; for(unsigned int i=50,j=cycle;i>0;i--) { Temp+=*(Power+j); if(j==0) j=lenght; j--; Temp=Temp*3/50; ((CSpeed*)lpSpeed)->SetSpeed(Temp); ISpeed=((CSpeed*)lpSpeed)->GetSpeed(); *(Speed+cycle)=ISpeed; MSpeed=((CSpeed*)lpSpeed)->GetMaxSpeed(); APower=0; for(i=0;i<lenght;i++) APower+=*(Power+i); APower/=(long)Lenght; ASpeed=0; for(i=0;i<lenght;i++) ASpeed+=*(Speed+i); ASpeed/=(long)Lenght; *(Accel+cycle)=(ISpeed-*(Speed+cyclea)); long accel=0; for(i=5,j=cycle;i>0;i--) { accel+=*(accel+j); if(j==0) j=lenght; j--; AccelS[cycle%AccelSmooth]=accel/5L; accel=0; for(i=0;i<accelsmooth;i++) { accel+=accels[i]; accel/=(long)accelsmooth+5; IAccel=accel; AAccel=0; for(i=0;i<lenght;i++) AAccel+= *(Accel+i); AAccel/=(long)Lenght; wsprintf(sztemp, TPE 00/003 - Voiture Télécommandée 9
92 La Programmation ::CarRemote - Stats.cpp %li\n%li\n%li\n%li\n%li\n%li%%\n%li%%\n%s, MSpeed, ISpeed, ASpeed, IAccel, AAccel, IPower, APower, szlights); lpsurf->bltfast(0,0,lpsback,0,0); lpsurf->getdc(&dc); SelectObject(dc,hFont); SetBkMode(dc,TRANSPARENT); SetBkColor(dc,RGB(55,0,55)); SetTextColor(dc,RGB(0,0,0)); DrawText(dc,szTemp,strlen(szTemp),&rc,DT_LEFT); SetTextColor(dc,RGB(55,55,55)); DrawText(dc,szTemp,strlen(szTemp),&rc,DT_LEFT); lpsurf->releasedc(dc); Temp=UPDATE-(GetTickCount()-Time); if(temp<=0) { //Handle Desync Temp=0; sync=0; else sync=; if(temp>=update) Temp=UPDATE; //Protection cycle++; cyclea++; if(cycle==lenght) cycle=0; if(cyclea==lenght) cyclea=0; if(temp!=0) Sleep(Temp); //Sync bupdate = ; return;...:: conclusion ::... Le Bilan Grâce aux TPE, nous avons élargi notre connaissance en mécanique et en électronique numérique. A present, nous nous ouvrons vers des projets de domotique, robotiques, etc... En résumé, ce fut une éxperience en temps limitée qui nous a fait apprendre énormement de chose. Remerciements : Fabrice Delauré - Mr Grialou et sa secrétaire - Mr Duviau - Mr Lechevrel - et tout ceux qui nous ont aidé. 9 TPE 00/003 - Voiture Télécommandée
CIRCUITS DE PUISSANCE PNEUMATIQUES
V ACTIONNEURS PNEUMATIQUES : 51 Généralités : Ils peuvent soulever, pousser, tirer, serrer, tourner, bloquer, percuter, abloquer, etc. Leur classification tient compte de la nature du fluide (pneumatique
1 Le module «train avant»
Face au constat des années précédentes, il est difficile de faire de grosses interventions dans le délai intercourse; c est pourquoi nous proposons une voiture constituée de cinq modules interchangeables
2105-2110 mm 1695 mm. 990 mm Porte-à-faux avant. Modèle de cabine / équipage Small, simple / 3. Codage 46804211 46804311 46804511
CANTER 3S13 2105-2110 mm 1695 mm 990 mm Porte-à-faux avant 3500 3995 4985 Longueur max. de carrosserie** 2500 2800 3400 Empattement 4635 4985 5785 Longueur hors tout Masses/dimensions Modèle 3S13 Modèle
ENREGISTREUR DE TEMPERATURE
ENREGISTREUR DE TEMPERATURE Jean-Pierre MANDON 2005 www.pictec.org Cet enregistreur de température a été réalisé dans le cadre de la construction d'un chauffe eau solaire. Il me permet d'enregistrer les
1. PRESENTATION DU PROJET
Bac STI2D Formation des enseignants Jean-François LIEBAUT Denis PENARD SIN 63 : Prototypage d un traitement de l information analogique et numérique (PSoC) 1. PRESENTATION DU PROJET Les systèmes d éclairage
ARDUINO DOSSIER RESSOURCE POUR LA CLASSE
ARDUINO DOSSIER RESSOURCE POUR LA CLASSE Sommaire 1. Présentation 2. Exemple d apprentissage 3. Lexique de termes anglais 4. Reconnaître les composants 5. Rendre Arduino autonome 6. Les signaux d entrée
Manuel d'utilisation de la maquette
Manuel d'utilisation de la maquette PANNEAU SOLAIRE AUTO-PILOTE Enseignement au lycée Article Code Panneau solaire auto-piloté 14740 Document non contractuel L'énergie solaire L'énergie solaire est l'énergie
Conférence sur les microcontroleurs.
Conférence sur les microcontroleurs. Le microcontrôleur Les besoins et le développement. Vers 1970, pour des calculs (calculatrice). Le premier est le 4004 de Intel, 90K. La technologie. Les 2 principales
DISQUE DUR. Figure 1 Disque dur ouvert
DISQUE DUR Le sujet est composé de 8 pages et d une feuille format A3 de dessins de détails, la réponse à toutes les questions sera rédigée sur les feuilles de réponses jointes au sujet. Toutes les questions
COMMENT RESOUDRE LES PROBLEMES DE VIBRATION DE L ESSIEU AVANT SUR LES TOYOTA MODELE HZJ
COMMENT RESOUDRE LES PROBLEMES DE VIBRATION DE L ESSIEU AVANT SUR LES TOYOTA MODELE HZJ 75? (valable également pour le modèle Hi-Lux équipé de lames de ressort à l avant) Christophe Humbert * Octobre 2002
MOTO ELECTRIQUE. CPGE / Sciences Industrielles pour l Ingénieur TD06_08 Moto électrique DIAGRAMME DES INTER-ACTEURS UTILISATEUR ENVIRONNEMENT HUMAIN
MOTO ELECTRIQUE MISE EN SITUATION La moto électrique STRADA EVO 1 est fabriquée par une société SUISSE, située à LUGANO. Moyen de transport alternatif, peut-être la solution pour concilier contraintes
SUIVEUR SOLAIRE : Informations complémentaires
SUIVEUR SOLAIRE : Informations complémentaires IMPORTANT : L objectif de la présente note technique n est pas de se substituer à l ouvrage «Alimentation électrique de sites isolés» mais de fournir des
Recopieur de position Type 4748
Recopieur de position Type 4748 Fig. 1 Type 4748 1. Conception et fonctionnement Le recopieur de position type 4748 détermine un signal de sortie analogique 4 à 20 ma correspondant à la position de vanne
Objet : Alimentation pour ordinateur portable et autre. Alimentation Schéma 1
Objet : Alimentation pour ordinateur portable et autre. Question posée par les membres du club d astronomie de Lavardac 47230. Est-il possible d augmenter l autonomie des ordinateurs portables (qui tout
SYSTEME DE PALPAGE A TRANSMISSION RADIO ETUDE DU RECEPTEUR (MI16) DOSSIER DE PRESENTATION. Contenu du dossier :
SYSTEME DE PALPAGE A TRANSMISSION RADIO ETUDE DU RECEPTEUR (MI16) DOSSIER DE PRESENTATION Contenu du dossier : 1. PRESENTATION DU SYSTEME DE PALPAGE A TRANSMISSION RADIO....1 1.1. DESCRIPTION DU FABRICANT....1
Dossier de sponsoring
Dossier de sponsoring Sommaire Le mot de l équipe Objectifs Organisation La Formula Student Descriptif technique Nous soutenir Budget Contact Le mot de l équipe «EstaCars est un projet pédagogique, sur
FAG Detector II le collecteur et l analyseur de données portatif. Information Technique Produit
FAG II le collecteur et l analyseur de données portatif Information Technique Produit Application La maintenance conditionnelle Principe de fonctionnement Application Le FAG II est, à la fois, un appareil
DPM 100/50 NOTICE D UTILISATION
DPM 100/50 NOTICE D UTILISATION Contenu Mortaiser les portes en bois Mortaiser les portes en bois Pages 3-5 Procédure recommandée Percer des trous droits dans les portes Page 5 Mortaiser les portes en
0.8 U N /0.5 U N 0.8 U N /0.5 U N 0.8 U N /0.5 U N 0.2 U N /0.1 U N 0.2 U N /0.1 U N 0.2 U N /0.1 U N
Série 55 - Relais industriels 7-10 A Caractéristiques 55.12 55.13 55.14 Relais pour usage général avec 2, 3 ou 4 contacts Montage sur circuit imprimé 55.12-2 contacts 10 A 55.13-3 contacts 10 A 55.14-4
Casisa Anthony DOSSIER PERSONNEL
Casisa Anthony TSSI DOSSIER PERSONNEL Année scolaire 2012-2013 La voiture solaire I) Planification 1) Introduction Dans le cadre du Projet Pluridisciplinaire Encadré en classe de Terminale SSI, nous avons
Introduction : Les modes de fonctionnement du transistor bipolaire. Dans tous les cas, le transistor bipolaire est commandé par le courant I B.
Introduction : Les modes de fonctionnement du transistor bipolaire. Dans tous les cas, le transistor bipolaire est commandé par le courant. - Le régime linéaire. Le courant collecteur est proportionnel
ENCASTREZ UN EVIER ET POSEZ UN MITIGEUR A DOUCHETTE
ENCASTREZ UN EVIER ET POSEZ UN MITIGEUR A DOUCHETTE ETAPE 1 LE PLAN DE TRAVAIL 1.a Repères Repères Mettez en place provisoirement le plan de travail et tracez au crayon effaçable deux repères qui correspondent
500 W sur 13cm avec les modules PowerWave
500 W sur 13cm avec les modules PowerWave Philippe Borghini / F5jwf [email protected] Janvier 2012 Introduction Tout le monde a déjà vu au moins une fois, sur les puces, ces fameuses platines PowerWave
AUTOPORTE III Notice de pose
AUTOPORTE III Notice de pose Vous avez acquis le système AUTOPORTE, nous vous en remercions. Veuillez lire attentivement cette notice, vous serez à même de faire fonctionner correctement ce système. FONCTIONNEMENT
Baccalauréat Professionnel. Microtechniques. Session 2012 DOSSIER TECHNIQUE (DT)
Baccalauréat Professionnel Microtechniques Session 2012 E2 - EPREUVE DE TECHNOLOGIE Préparation d une intervention microtechnique DOSSIER TECHNIQUE (DT) Session : 2012 Dossier Technique Page 1 sur 8 A
Leçon 1 : Les principaux composants d un ordinateur
Chapitre 2 Architecture d un ordinateur Leçon 1 : Les principaux composants d un ordinateur Les objectifs : o Identifier les principaux composants d un micro-ordinateur. o Connaître les caractéristiques
Projet de synthèse de l'électronique analogique : réalisation d'une balance à jauges de contrainte
J3eA, Journal sur l enseignement des sciences et technologies de l information et des systèmes, Volume 4, HorsSérie 2, 20 (2005) DOI : http://dx.doi.org/10.1051/bibj3ea:2005720 EDP Sciences, 2005 Projet
Zoom sur La Poursuite Solaire
Zoom sur La Poursuite Solaire www.solar-tracking.com Optimiser le rendement énergétique Le réchauffement climatique mondial et la volonté commune de réduire les émissions de gaz à effet de serre ont relancé
SÉRIE RM Découpeuses-Cambreuses RM 40K / RM 40KS / RM 40P
SÉRIE RM Découpeuses-Cambreuses RM 40K / RM 40KS / RM 40P Fabrication de grandes séries avec une efficacité accrue Augmentez la qualité de vos pièces de précision, réduisez vos coûts unitaires et fabriquez
Centre de tournage. et de fraisage CNC TNX65/42
Centre de tournage et de fraisage CNC TNX65/42 Le tour TRAUB TNX65/42 pose de nouveaux jalons dans l'usinage à haute performance. Le concept de machine futuriste avec l'incomparable nouvelle unité de fraisage
LES LOIS PHYSIQUES APPLIQUÉES AUX DEUX-ROUES : 1. LA FORCE DE GUIDAGE
LES LOIS PHYSIQUES APPLIQUÉES AUX DEUX-ROUES : 1. LA FORCE DE GUIDAGE 2. L EFFET GYROSCOPIQUE Les lois physiques qui régissent le mouvement des véhicules terrestres sont des lois universelles qui s appliquent
Références pour la commande
avec fonction de détection de défaillance G3PC Détecte les dysfonctionnements des relais statiques utilisés pour la régulation de température des éléments chauffants et émet simultanément des signaux d'alarme.
Notice technique. Système de surveillance MAS 711
Notice technique Système de surveillance MAS 711 Informations d ordre général Le MAS 711 Flygt est un système de surveillance de pompes destiné aux grosses pompes Flygt, c est à dire aux pompes équipées
Informations produits scalamobil S35 scalacombi S36
Informations produits Sommaire scalamobil S35 scalacombi S36 Aperçu 40 Avantages du produit 41 Visuel du produit 42 Descriptif 43 Accessoires 44 scalacombi S36 46 scalasiège X3 47 Accessoires scalasiège
Les liaisons SPI et I2C
DAMÉCOURT BENJAMIN AVRIL 28 Liaisons synchrones Les liaisons SPI et I2C Face arrière d un imac : trois ports USB, un port Firewire 4 et un port Firewire 8 CHRONOLOGIE ANNÉES 7 La liaison SPI et la création
RELAIS STATIQUE. Tension commutée
RELAIS STATIQUE Nouveau Relais Statique Monophasé de forme compacte et économique Coût réduit pour une construction modulaire Modèles disponibles de 15 à 45 A Modèles de faible encombrement, avec une épaisseur
Information. BASES LITTERAIRES Etre capable de répondre à une question du type «la valeur trouvée respecte t-elle le cahier des charges?
Compétences générales Avoir des piles neuves, ou récentes dans sa machine à calculer. Etre capable de retrouver instantanément une info dans sa machine. Prendre une bouteille d eau. Prendre CNI + convocation.
Carte Relais GSM (Manuel Utilisateur)
Carte Relais GSM (Manuel Utilisateur) Carte Relais GSM Introduction Cette carte est une véritable centrale de télécommande et d alarme par GSM. Elle se connecte par un port série à un modem GSM compatible
BACCALAURÉAT TECHNOLOGIQUE Sciences et Technologies de l Industrie et du Développement Durable ENSEIGNEMENTS TECHNOLOGIQUES TRANSVERSAUX
BACCALAURÉAT TECHNOLOGIQUE Sciences et Technologies de l Industrie et du Développement Durable ENSEIGNEMENTS TECHNOLOGIQUES TRANSVERSAUX Coefficient 8 Durée 4 heures Aucun document autorisé Calculatrice
uc : Cas d utilisation Top-Chair [Utilisation normale] Fauteuil Top-Chair Déplacer le fauteuil sur tous chemins «include» «include» «extend»
TopChair S c Première partie Présentation du système Plus d autonomie pour plus de liberté! TopChair S c offre aux personnes à mobilité réduite une nouvelle possibilité de se déplacer sans assistance à
(Exemple ici de calcul pour une Ducati 748 biposto, et également pour un S2R1000, équipé d un disque acier en fond de cloche, et ressorts d origine)
Analyse de la charge transmise aux roulements de la roue dentée, notamment en rajoutant les efforts axiaux dus aux ressorts de l embrayage (via la cloche) (Exemple ici de calcul pour une Ducati 748 biposto,
Contribution à la conception par la simulation en électronique de puissance : application à l onduleur basse tension
Contribution à la conception par la simulation en électronique de puissance : application à l onduleur basse tension Cyril BUTTAY CEGELY VALEO 30 novembre 2004 Cyril BUTTAY Contribution à la conception
Centrale d alarme DA996
Centrale d alarme DA996 Référence : 7827 La DA-996 est une centrale d alarme pour 6 circuits indépendants les uns des autres, avec ou sans temporisation, fonctions 24 heures, sirène, alerte et incendie.
CENTRAL MEDIA VÉHICULE SOLAIRE PROJET. Réf. KCM 2088. Dossier de MONTAGE. et d'aide à la REALISATION. Version 2.00
CENTRAL MEDIA PROJET Réf. Dossier de MONTAGE et d'aide à la REALISATION VÉHICULE SOLAIRE Version 2.00 AVANT PROPOS Central Média développe le thème du transport pour les cours de technologie au collège.
Dimensionnement d une roue autonome pour une implantation sur un fauteuil roulant
Dimensionnement d une roue autonome pour une implantation sur un fauteuil roulant I Présentation I.1 La roue autonome Ez-Wheel SAS est une entreprise française de technologie innovante fondée en 2009.
NOTICE D UTILISATION ET D INSTALLATION. de la CARTE MONITORING DE RELAIS «IO-MONITOR»
NOTICE D UTILISATION ET D INSTALLATION de la CARTE MONITORING DE RELAIS «IO-MONITOR» Z.A.C. de la Plaine 1 rue Brindejonc des moulinais B.P. 45804 31505 TOULOUSE CX 5 Tél. : 05.61.36.03.03 Fax : 05.61.36.03.00
Le multiplexage. Sommaire
Sommaire Table des matières 1- GENERALITES... 2 1-1 Introduction... 2 1-2 Multiplexage... 4 1-3 Transmission numérique... 5 2- LA NUMERATION HEXADECIMALE Base 16... 8 3- ARCHITECTURE ET PROTOCOLE DES RESEAUX...
GROUPE HOLDIM Leader mondial de l optimisation moteur. DYNORACE 2WD /DF2 Banc 2 roues motrices. Banc de puissance Disponible en 3 versions :
BANCS DE PUISSANCE Banc de puissance Disponible en 3 versions : Inertiel /DF2is Inertiel /DF2i Freiné /DF2fs Avec un frein à courant de Foucault 3 GROUPE HOLDIM Leader mondial de l optimisation moteur
Désaccouplement et accouplement de la face avant aile et de son support
Désaccouplement et accouplement de la face avant aile et de son support DÉPOSE 1 : Déposer : - le capot-moteur et suivant le côté où le travail est à effectuer, - le cric de l intérieur de roue droit -
Comment créer votre propre lampes LED
Comment créer votre propre lampes LED Intro Un tutorial pour faire fabriqué des ampoules LED comme à l usine. Après de nombreuses tentatives pour faire toutes sortes de conversions LED, j ai enfin trouvé
KASTOspeed: Scies automatiques de production à lame circulaire pour le débit économique de très grandes séries dans l acier et les non-ferreux.
KASTOspeed: Scies automatiques de production à lame circulaire pour le débit économique de très grandes séries dans l acier et les non-ferreux. Très grandes performances en un temps record: Scies automatiques
Notice de montage, d utilisation et de maintenance
SmartTouch confort d accès NB506N avec technique de transpondeur à longue portée Notice de montage, d utilisation et de maintenance Notice de montage et d utilisation pour le client final MBW26-FR/07.15-6
GUIDE TECHNIQUE. Février 2012 P O R T A R O L PORTAROL FGDT-007-K 1
GUIDE TECHNIQUE Février 2012 P O R T A R O L FGDT-007-K 1 Sommaire PORTAROL 3 - PORTAROL 4 - TABLIER LAMES ALUMINIUM 5 - LAME FINALE 6 - COULISSES 7-8 - DIAMETRE D ENROULEMENT 9 - FIXATION EXTERIEURE COFFRE
Système à enseigner : Robot M.I.M.I. MultipodeIntelligent à Mobilité Interactive. Version 1.0
Système à enseigner : Robot M.I.M.I. MultipodeIntelligent à Mobilité Interactive Sommaire - Le Robot M.I.M.I. (Multipode Intelligent à Mobilité Interactive) - Présentation du Système à Enseigner. - Composition
Les connexions. Multifonctions. Avantage. Forme ronde et non carrée :
Les connexions Multifonctions Avantage Forme ronde et non carrée : En plus d une esthétique agréable et assortie à la forme ronde des tubes et joints LeanTek, la forme arrondie des F-M Trilogiq permet
Aperçu. S35 Franchir les escaliers en toute sécurité.
Aperçu S35 Franchir les escaliers en toute sécurité. 34 Avantages du produit Informations produits Avantages du produit Le scalamobil demeure le produit de référence pour représenter la gamme Alber. Le
WWW.ELCON.SE Multichronomètre SA10 Présentation générale
WWW.ELCON.SE Multichronomètre SA10 Présentation générale Le SA10 est un appareil portable destiné au test des disjoncteurs moyenne tension et haute tension. Quoiqu il soit conçu pour fonctionner couplé
Catalogue Produits. 2011 v1
Catalogue Produits 2011 v1 A propos d Actisense INTRODUCTION Interfaces et Sondes intelligentes Actisense. Depuis plusieurs années Actisense est synonyme d excellence dans le domaine des sondes intelligentes,
1 Définition. 2 Systèmes matériels et solides. 3 Les actions mécaniques. Le système matériel : Il peut être un ensemble.un sous-ensemble..
1 Définition GÉNÉRALITÉS Statique 1 2 Systèmes matériels et solides Le système matériel : Il peut être un ensemble.un sous-ensemble..une pièce mais aussi un liquide ou un gaz Le solide : Il est supposé
Electrotechnique: Electricité Avion,
Electrotechnique: Electricité Avion, La machine à Courant Continu Dr Franck Cazaurang, Maître de conférences, Denis Michaud, Agrégé génie Electrique, Institut de Maintenance Aéronautique UFR de Physique,
Transmissions série et parallèle
1. Introduction : Un signal numérique transmet généralement plusieurs digits binaires. Exemple : 01000001 ( huit bits). Dans une transmission numérique on peut envisager deux modes : les envoyer tous en
Traffic engineering MODE. ou FIXE. électrique, le réseau MODE. d enregistrement. LED s avec. par des
2008 ISIS 120 Analyse Trafic SIRIEN SA 11/03/2008 1. INTRODUCTION Le radar préventif ISIS 120 peut s utiliser selon deux modes : MODE RADAR PRÉVENTIF : Il fonctionne simplement comme radar préventif MOBILE
Relais statiques SOLITRON MIDI, Commutation analogique, Multi Fonctions RJ1P
Relais statiques SOLITRON MIDI, Commutation analogique, Multi Fonctions RJ1P Relais statique CA Multi fonctions - 5 sélections de modes de fonctionnement: angle de phase, trains d ondes distribuées et
Boîtier de contrôle et de commande avec EV 3/2 voies intégrée
A B C Boîtier de contrôle et de commande avec EV 3/2 voies intégrée Conception Le boîtier de contrôle / commande type GEMÜ avec électrovanne pilote 3/2 voies intégrée pour les actionneurs pneumatiques
INFUSIONS MC Marquises contrastantes en polycarbonate Mode d assemblage et d installation
INFUSIONS MC Marquises contrastantes en polycarbonate Mode d assemblage et d installation 1. DÉFINITION Les marquises contrastantes Infusions offrent un choix de 16 finis de métal ou de plastique transparent
Robots CNC. WITTMANN nommé «Meilleur achat» pour les robots. Technology working for you.
Robots CNC WITTMANN nommé «Meilleur achat» pour les robots Technology working for you. Le concept robot novateur Des dizaines d années d expériences, de développements et d innovations ont fait des robots
W 12-2 : haute performance et savoir-faire compact
Barrières W - Détecteurs réflex, élimination de premier plan EPP Détecteurs réflex, élimination d arrière-plan EAP W - : haute performance et savoir-faire compact Détecteurs réflex énergétiques fibres
INSTRUCTIONS DE POSE
5/2013 FR INSTRUCTIONS DE POSE Etant donné la plus longue durée de vie de la porte en bois composite Duofuse par rapport à une porte en bois classique, il est important de la placer correctement afin de
Synoptique. Instructions de service et de montage
Montage- und Bedienungsanleitung Mounting and Operating Instructions Instructions de service et de montage Istruzioni di montaggio ed uso Instrucciones de montaje y de servicio p p p p Terminale porta
LE NOUVEAU SYSTEME DE BRAS PORTEUR
LE NOUVEAU SYSTEME DE BRAS PORTEUR 28 Même conception Charges admissibles de 600 à 1 800 N Un ensemble complet et cohérent Même design Association possible de versions différentes horizontalement et verticalement
BACCALAURÉAT GÉNÉRAL SÉRIE SCIENTIFIQUE
BACCALAURÉAT GÉNÉRAL SÉRIE SCIENTIFIQUE ÉPREUVE DE SCIENCES DE L INGÉNIEUR ÉPREUVE DU VENDREDI 20 JUIN 2014 Session 2014 Durée de l épreuve : 4 heures Coefficient 4,5 pour les candidats ayant choisi un
Vis à billes de précision à filets rectifiés
sommaire Calculs : - Capacités de charges / Durée de vie - Vitesse et charges moyennes 26 - Rendement / Puissance motrice - Vitesse critique / Flambage 27 - Précharge / Rigidité 28 Exemples de calcul 29
Actions de réduction de bruit sur un moteur poids lourd
10 Actions de réduction de bruit sur un moteur poids lourd Laurent Moulin, Renault VI, 99, route de Lyon, 69802 Saint Priest, e-mail : [email protected] D epuis 1974 à aujourd hui, la réglementation
KIT SOLAIRE EVOLUTIF DE BASE
PARALLELE ENERGIE KIT SOLAIRE EVOLUTIF DE BASE Ce kit solaire est un système solaire facile à utiliser. Il s agit d un «générateur solaire» qui convertit la lumière du soleil en électricité, et qui peut
Neu. Technique d installation / de surveillance. VARIMETER RCM Contrôleur différentiel type B IP 5883
Technique d installation / de surveillance VARIMETER RCM Contrôleur différentiel type IP 5883 0249636 X1 A1 X1 i2 11 Alarm 12 Neu IP 5583 N 5018/035 N 5018/030 escription du produit Le contrôleur différentiel
MetROCab VÉHICULe ÉLeCtRIQUe À RaYON D action ÉteNDU et DIFFÉReNtIeL ÉLeCtRONIQUe
MetROCab VÉHICULE ÉLECTRIQUE À RAYON D ACTION ÉTENDU ET DIFFÉRENTIEL ÉLECTRONIQUE GRACE A SON GROUPE MOTOPROPULSEUR DE POINTE A FAIBLES EMISSIONS (LOW EMISSION ADVANCED POWERTRAIN, OU LEAP) DEVELOPPE PAR
MOTORISATION DIRECTDRIVE POUR NOS TELESCOPES. Par C.CAVADORE ALCOR-SYSTEM WETAL 2013 10 Nov
1 MOTORISATION DIRECTDRIVE POUR NOS TELESCOPES Par C.CAVADORE ALCOR-SYSTEM WETAL 2013 10 Nov Pourquoi motoriser un télescope? 2 Pour compenser le mouvement de la terre (15 /h) Observation visuelle Les
Vue 2D / 3D / Dessin / Cotation Utilise : Logiciel edrawings Fichier.EPRT Dossier Tp-eDrawings
Vue 2D / 3D / Dessin / Cotation Utilise : Logiciel edrawings.eprt Dossier Tp-eDrawings TP EDRAWINGS INITIATION A LA CONCEPTION ASSISTÉE PAR ORDINATEUR (CAO) Les icônes Zoom au mieux pour obtenir un affichage
RAPPORT DE CLASSEMENT. RAPPORT DE CLASSEMENT n EFR-14-002348
Voie Romaine F-57280 Maizières-lès-Metz Tél : +33 (0)3 87 51 11 11 Fax : +33 (0 3 87 51 10 58 n EFR-14-002348 Selon les normes EN 15650 : 2010 et EN 13501-3 : 2007 Concernant Une gamme de clapets type
TP 7 : oscillateur de torsion
TP 7 : oscillateur de torsion Objectif : étude des oscillations libres et forcées d un pendule de torsion 1 Principe général 1.1 Définition Un pendule de torsion est constitué par un fil large (métallique)
DimNet Gradateurs Numériques Evolués Compulite. CompuDim 2000
DimNet Gradateurs Numériques Evolués Compulite La gamme des gradateurs Compulite est conçue autour des technologies les plus récentes et les plus évoluées que ces 20 dernières années ont vu apparaître.
véhicule hybride (première
La motorisation d un véhicule hybride (première HERVÉ DISCOURS [1] La cherté et la raréfaction du pétrole ainsi que la sensibilisation du public à l impact de son exploitation sur l environnement conduisent
Sommaire Table des matières
Notice de montage 1 Sommaire Table des matières I. Mise en garde... 3 II. Avant de commencer... 4 1. Préparer vos outils... 4 2. Pièces nécessaires pour le montage de votre porte Keritek... 5 III. Étape
Série D65/D75/D72 Afficheurs digitaux modulaires
Série D65/D75/D72 Afficheurs digitaux modulaires Afficheurs digitaux modulaires Afficheurs digitaux individuels La série D65/D75/D72 représente une vaste gamme de modules d affichage numériques, hexadécimaux
Catalogue de machines. CNC-Carolo. Edition de juillet 2011
Catalogue de machines 1/6 La Basic 30x20 : L'accès à la CNC pour débuter Idéale pour la gravure, la découpe de multiplis jusqu'à 5 mm d'épaisseur, la réalisation de circuits imprimés Description : Modèle
SECURIT GSM Version 2
EOLE informatique SECURIT GSM Version 2 Notice d installation & Guide utilisateur Eole informatique 42 rue Claude Decaen -75012 Paris Tél. 01.43.43.00.97 www.eole-informatique.com 15/03/2006 SOMMAIRE Notice
fullprotect inside EOLE SPEie RS E-SPEie 0.5-12-5V-0.6A-RS 1.0 revision Protection environnement Datasheet édition française
Protection environnement Datasheet édition française 1.0 revision R-D-CO-D-27112011-1.0-C fullprotect inside SPEi Protection environnement interne SPEe Protection environnement externe SPEc Contrôle de
Système d alarme sans fil GSM / SMS / RFID. www.camshop.fr
Système d alarme sans fil GSM / SMS / RFID Caractéristiques Panneau de contrôle Reconnait jusqu à 10 télécommandes Peut être connectée jusqu à 50 capteurs sans fil (contacts porte / fenêtre, radars ) Peut
Atelier B : Maintivannes
Atelier B : Maintivannes BMA03 : Procédure de réglage de la vanne de régulation CAMFLEX BMA03 : Procédure de réglage de la vanne CAMFLEX Page 1 Buts de l exercice : - Réaliser la manutention d un élément
III Capteurs et actuateurs
III Capteurs et actuateurs Tous les systèmes électroniques ont en commun qu ils fonctionnent selon le principe ETS (Entrée, Traitement, Sortie) du traitement de l information. ENTRÉE TRAITEMENT SORTIE
BACCALAURÉAT TECHNOLOGIQUE SESSION 2008 POSITIONNEUR DE PANNEAU SOLAIRE POUR CAMPING-CAR
BACCALAURÉAT TECHNOLOGIQUE SÉRIE SCIENCES ET TECHNIQUES INDUSTRIELLES GÉNIE ÉLECTROTECHNIQUE SESSION 2008 ÉPREUVE: ÉTUDE DES CONSTRUCTIONS Durée: 4 heures Coefficient : 6 POSITIONNEUR DE PANNEAU SOLAIRE
SIMPLIFIEZ-VOUS L OUVERTURE
SIMPLIFIEZ-VOUS L OUVERTURE 1] LES AUTOMATISMES DE PORTE - DWPS10 AUTOMATISME POUR PORTE SIMPLE... P. 170 - DWPD10 AUTOMATISME POUR PORTES DOUBLES... P. 170 2] PRODUITS COMPLÉMENTAIRES ADAPTÉS AUX PERSONNES
Voyez la réponse à cette question dans ce chapitre. www.hometownroofingcontractors.com/blog/9-reasons-diy-rednecks-should-never-fix-their-own-roof
Une échelle est appuyée sur un mur. S il n y a que la friction statique avec le sol, quel est l angle minimum possible entre le sol et l échelle pour que l échelle ne glisse pas et tombe au sol? www.hometownroofingcontractors.com/blog/9-reasons-diy-rednecks-should-never-fix-their-own-roof
Elaboration de Fer à Béton
Elaboration de Fer à Béton Cisailles électriques Combinées (cisailles-cintreuses) Cintreuses électriques Cintreuses à étriers électriques Cisailles électro-hydrauliques manuelles et lieuse de barres d
CYLINDRE ET BÉQUILLE ÉLECTRONIQUES À BADGE Aperio E100 & C100
SYSTÈMES D IDENTIFICATION CYLINDRE ET BÉQUILLE ÉLECTRONIQUES À BADGE Aperio E100 & C100 CONTRÔLE D ACCÈS SANS FIL RFID Contrôle des portes en temps réel. Fonctionnalités Aperio : le chaînon manquant grâce
Système de surveillance vidéo
Conrad sur INTERNET www.conrad.fr N O T I C E Version 12/01 Entretien Pour un fonctionnement correct de votre système de surveillance vidéo, prenez note des conseils suivants : 1/ Tenez la caméra et le
Sommaire buses. Buses
Sommaire buses Buses Pour tous types de machines hautes pression Pour des canalisations jusqu au Ø 600 mm Efficacité maximale Pour toutes sortes d obstruction Radiales ou rotatives Avec ou sans jet avant
PASSAGE A NIVEAU HO/N
PASSAGE A NIVEAU HO/N Description Ce passage à niveau en laiton est composé de deux demi-barrières, ainsi que de deux feux lumineux rouges. Vous pouvez utiliser ce PN sur un nombre quelconque de voie y
Eléments constitutifs et synthèse des convertisseurs statiques. Convertisseur statique CVS. K à séquences convenables. Source d'entrée S1
1 Introduction Un convertisseur statique est un montage utilisant des interrupteurs à semiconducteurs permettant par une commande convenable de ces derniers de régler un transfert d énergie entre une source
MODE OPÉRATOIRE. VI) Le projet mené dans le cadre de la technologie. Le projet porte sur la réalisation d une horloge CD.
VI) Le projet mené dans le cadre de la technologie. Le projet porte sur la réalisation d une horloge CD. 1 La réalisation se déroule en plusieurs phases : - analyse préalable du besoin : étude de l appel
