π
<-

News 2024
June (4)
May (4)
April (2)

News 2023
August (2)
July (3)
June (3)
May (7)
April (2)
March (3)

News 2022
August (3)
July (1)
June (4)
May (1)
April (6)
March (4)
January (12)

News 2021
August (8)
July (28)
June (20)
May (19)
April (25)
March (15)

News 2020
August (16)
July (13)
June (17)
May (38)
April (21)
March (17)

News 2019
August (10)
July (3)
June (4)
May (11)
April (8)
March (18)
January (14)

News 2018
August (5)
July (1)
June (9)
May (10)
April (2)
March (14)
January (12)

News 2017
August (10)
July (14)
June (14)
May (11)
April (9)
March (12)
January (11)

News 2016
October (10)
August (8)
July (4)
June (8)
May (14)
April (9)
March (13)
January (11)

News 2015
October (15)
August (11)
July (4)
June (7)
May (12)
April (6)
March (11)

News 2014
August (2)
July (4)
June (2)
May (5)
April (4)
March (5)

News 2013
August (6)
July (6)
June (8)
May (14)
April (24)
March (16)
January (10)

News 2012
October (11)
August (6)
July (7)
June (8)
May (16)
April (16)
March (6)

News 2011
August (4)
July (4)
June (11)
May (5)
April (2)
March (6)

News 2010
July (1)
June (1)
May (2)
April (1)

News 2009
August (2)
April (1)

Zero, clone amélioré de TI-84 Plus CE (100 MHz + USB-C)

Postby critor » 01 Apr 2022, 15:03

1415914165Pour les calculatrices scientifiques, nos magasins sont inondés de clones de calculatrices Casio.

Avec l'accord du constructeur ou pas, les fabricants reprennent ce qui leur plaît dans les éléments matériels, logiciels et de design de Casio.

On peut citer aussi bien des marques poubelles comme Lexibook, Auchan, des constructeurs qui perdent de leur superbe en s'abaissant à cela comme HP, des contrefaçons de Citizen en Gtttzen, ...

Lorsque conçus sans son accord, parfois Casio arrive même à faire condamner le constructeur concerné, comme avec la EATES fc-991CN+.
4095413414337


Ces clones pouvaient parfois se révéler intéressants, car utilisant souvent des matériel et même processeur différents de ceux de Casio.

Toutefois jusqu'à présent si l'on s'en tient aux modèles récents, ce phénomène de clonage ne concernait que les calculatrices scientifiques.

Dans le cadre des calculatrices graphiques on ne trouvait jusqu'à présent essentiellement que des clones plus ou moins bien réussis de très vieilles calculatrices Casio du siècle dernier. Aux capacités nullissimes dans le contexte actuel, elles concernaient davantage l'Asie et l'Afrique. La non conformité aux modes examen français ou européens terminait de plus d'expliquer leur quasi inexistence chez nous.

Mais les choses sont peut-être sur le point de changer sur la scène des Etats-Unis. Pour le contexte rappelons que la TI-84 Plus CE (version internationale de notre TI-83 Premium CE française) y est la référence, et que NumWorks est actuellement en train de tenter de pénétrer le marché nord-américain pour la rentrée 2022, avec son nouveau modèle N0120.

Or un tout nouveau clone de calculatrice graphique est actuellement en préparation pour la rentrée 2022, la Zero, et pourrait bien venir contrecarrer ses plans.

En effet comme tu devrais le remarquer malgré l'évolution du design dans le temps, la Zero ne s'inspire pas d'une antiquité mais de la TI-84 Plus CE au succès planétaire !
Tu y retrouves ainsi entre autres exactement le même clavier et n'auras donc rien à apprendre de spécifique pour utiliser la Zero.

La toute dernière version du design a certes un peu évolué depuis, et la ressemblance est moins flagrante en dehors du clavier.

Chose remarquable ici, nous avons une protection antichoc sous la forme d'une bande de caoutchouc d'un bleu très esthétique faisant le tour du boîtier ; un excellent choix dans le contexte du cadre scolaire que l'on sait être très hostile pour les appareils électroniques.

Sur le matériel par contre, la Zero s'affranchit totalement de son modèle, et pour le meilleur comme nous allons voir.
Outre l'écran couleur 2,8", on nous annonce plusieurs bonnes nouvelles :
  • non plus un processeur 8 bits eZ80 à 48 MHz, mais un 32 bits à 100 MHz ! :bj:
  • une connectivité USB enfin contemporaine et facile avec un port USB-C, première calculatrice graphique au monde à nous proposer cette évolution tant attendue ! :bj:
  • 20% de stockage supplémentaire, ce qui par rapport aux 4 Mio de Flash des TI-84 Plus CE nous amène donc à supposer 5 Mio (sans doute répartis sur 2 puces de capacités respectives 4 Mio et 1 Mio, règle binaire des puissances de 2 oblige)

Imagine ce que pourraient donner tes programmes TI-Basic et assembleur favoris à 100 MHz... :favorite:

Nous mourrons d'envie de pouvoir te la tester, mais pour te faire patienter en attendant voici un petit unboxing de la part d'un des testeurs et par Zero eux-même en vidéo :



Notons le clin d'œil sur la boîte, "this box contains Zero calculators". ;)

Cassant complètement les codes et habitudes des cloneurs de calculatrices, la Zero pourrait bien venir jouer les trouble-fêtes à la rentrée 2022 et damer le pion à NumWorks sur le marché américain. Surtout que de plus se baser sur la TI-84 Plus CE, le modèle local largement plébiscité par les petits américains, est sans doute un énorme avantage.

À très bientôt on espère...

Liens :
Crédits images Zero :

Découverte du processeur non-z80 des TI-80 de 1995, enfin !

New postby critor » 03 Apr 2022, 10:18

Aujourd'hui nous allons parler TI-80, la calculatrice graphique Texas Instruments la plus mystérieuse jamais produite.

13446Mais plantons dabord le décor. En 1990 Texas Instruments rentrait dans la formidable aventure des calculatrices graphiques avec son tout premier modèle, la TI-81, équipé d'un processeur 8 bits z80 cadencé à 5 MHz.

Dans un premier temps jusqu'en 1992, différentes versions du logiciel gravé en ROM ont défilé et sont consultables via la combinaison de touches
2nd
MATH
ALPHA
LN
: 1.0, 1.1, 1.1K, 1.5K, 1.6K et 1.8K.

Avec la sortie des TI-85 et TI-82 en 1992 puis 1993, la TI-81 devint l'entrée de la gamme graphique Texas Instruments.

178Justement les TI-81 assemblées à compter de 1993 ont subi une révision matérielle majeure. Pour mutualiser les éléments de production et ainsi économiser, Texas Instruments leur a fait utiliser les mêmes cartes électroniques que les TI-82 qui venaient de sortir . Quelques petites différences toutefois :
  • les composants relatifs au circuit de communication étaient absents sur les cartes destinées à équiper des TI-81, puisque ce modèle était dépourvu de tout port de communication
  • la puce ROM soudée sur les cartes destinées aux TI-81 conservait la capacité de 64K suffisante pour le logiciel, au lieu des 128K des TI-82
  • le processeur par contre passait à 6 MHz comme sur les TI-82, et permettait donc à ces dernières TI-81 d'être un peu plus rapides
Pour gérer correctement ce matériel sensiblement différent, le logiciel TI-81 a lui-même dû subir des adaptations majeures, distribuées sous les numéros de version V2.00 et V2.0V.

Et voilà nous y sommes déjà. En 1995 Texas Instruments arrête la production des TI-81 et les remplace par un tout nouveau modèle d'entrée de gamme, la TI-80.

Fort logiquement les versions du logiciel ici consultables via la combinaison via la combinaison de touches
MODE
ALPHA
LN
poursuivent la numérotation : 3.0 et 4.0.
Comme pour la TI-81 pas de port de communication, à l'exception des très rares modèles enseigants dits TI-80 ViewScreen munis d'un port mini-Jack 2.5mm dédié aux captures d'écran.

La TI-80 avait la particularité d'être nettement plus légère et petite que la TI-81. Sans couvercle, on passait :
  • d'un poids de 206g à seulement 110g, à peine plus de la moitié !
  • d'une épaisseur de 2,22cm à seulement 1,60cm
  • d'une hauteur de 17,36cm à seulement 16,18cm
  • d'une largeur de 8,09cm à seulement 7,25cm

Mais tout ceci impliquait également des sacrifices :
  • au lieu de 4 piles AAA, la TI-80 s'alimentait avec 2 piles boutons CR2032 nettement plus chères
  • d'une définition de 96×64 pixels sur les TI-81, l'écran ne faisait plus que 64×48 pixels sur les TI-80
  • en taille également, l'écran se réduisait de 2,48" à seulement 1,85"

Un modèle extrêmement mystérieux qui continue à nous résister à ce jour depuis plus de 25 ans. Nombre d'étapes clé ont pris beaucoup plus de temps que sur les autres modèles TI de l'époque :
  • 2010 : dumping partiel de 32K du logiciel en version 3.0 et 4.0, à partir de la puce ROM externe
  • 2010 : dumping du logiciel en version 4.0 complété avec les 16K manquant sur une ROM interne à la puce du processeur
  • 2011 : premier émulateur
  • 2012 : support des TI-80 ViewScreen par le logiciel de connectivité TiLP
  • 2021 : récupération enfin du logiciel de connectivité dédié officiel TI-Graph Link 80
Et toujours aucune possibilité d'exécuter des programmes assembleur à ce jour.

177En fait comme vu plus haut, il semble qu'un des objectifs de Texas Instruments lors de la conception de la TI-80 ait été de minimiser le plus possible les coûts de production. Et dans ce cadre il y a juste quelque chose que nous ne t'avons pas encore dit, le processeur enfermé dans la puce Toshiba T6M53A n'est pas même pas un z80.

Impensable de nos jours, sans doute qu'à l'époque le code encore relativement modeste du logiciel graphique Texas Instruments permettait encore un portage pas trop coûteux pour un tout autre processeur.

Cette puce Toshiba n'a hélas pas de datasheet public. Une ancienne page du site Texas Instruments donnait toutefois des informations sur les processeurs des calculatrices. À la place de z80 pour les autres modèles elle indiquait ici qu'il s'agissait d'un processeur propriétaire, et précisait qu'il était cadencé à 980 KHz, soit beaucoup moins que la TI-81 précédente.

Une hypothèse à partir des images récupérées de la ROM en version 4.0, basée sur l'alignement des instructions, était qu'il s'agissait d'un processeur 16 bits. Mais ce n'était absolument pas une preuve, et pouvait être une conséquence de bien d'autres contraintes lors de la conception.

Le processeur de la TI-80 nous restent donc encore fort mystérieux...

1542015419Une méthode populaire permettant d'identifier les calculatrices utilisant des processeurs similaires, est le test dit de la signature trigonométrique. Il suffit de calculer en mode décimal et degrés
$mathjax$Arcsin\left(Arccos\left(Arctan\left(tan\left(cos\left(sin\left(9\right)\right)\right)\right)\right)\right)$mathjax$
.

Le résultat mathématique est de 9, mais le moteur de calcul flottant de nos calculatrices répond normalement une valeur approchante.

Plus précisément, le résultat dépend du cœur de calcul utilisé, qu'il soit logiciel ou matériel. Nos calculatrices récentes permettent parfois d'accueillir plusieurs logiciels de calcul, mais généralement plus une calculatrice est simple, plus les algorithmes de calcul reposeront sur les capacités précâblées dans le processeur, ce qui est notamment le cas des calculatrices scientifiques entre autres.

Et justement, la TI-80 répond 8.999999007884, alors que les TI-81 trouvent 8.999999616566.

Or le logiciel TI-80 en version 3.0 étant une évolution directe du logiciel TI-81 en version 2.0, il semble donc ici que la différence soit due au matériel.

Et justement, la TI-80 n'est pas la seule calculatrice à répondre 8.999999007884 au test.

C'est également le cas des TI-68 de 1989 et TI Galaxy 67 de 1992.

Or selon le musée Datamath, le processeur de la TI Galaxy 67 nous est connu. Sa puce Toshiba TMP0620F utilise un cœur Toshiba TMC17C, une architecture 4 bits.

Réutiliser un cœur 4 bits de calculatrice scientifique dans le contexte des économies drastiques qui semblent avoir été au cahier des charges de la TI-80, avec comme conséquence entre autres un écran matriciel de définition bien plus modeste, cela nous paraît en effet très plausible a posteriori.

En conclusion voici donc enfin la réponse à l'énigme après près de 27 ans de mystères ; le processeur de la TI-80 serait un 4 bits TMC17C de chez Toshiba, cadencé à 980 KHz.

Référence : Comparaison TI-80 et TI-81

Elimination, immense RPG pour TI-83 Premium CE

New postby critor » 13 Apr 2022, 14:38

15445Elimination est un jeu de type RPG, une création originale par Hot_Dog initialement sortie en novembre 2021 pour calculatriaces TI-82 Plus, TI-83 Plus et TI-84 Plus monochromes, prenant la forme d'une application.

Le gameplay est comparable à ce que tu as peut-être connu avec Final Fantasy, Pokemon, Earthbound ou encore Super Mario RPG. Tu enchaînes des phases d'exploration et de combat au tour par tour.

En 2050, les terriens sont en guerre avec une étrange race extraterreste insectiforme venue de la galaxie Whirlpool (tourbillon). Mais toute ressemblance avec d'autres histoires de science fiction s'arrête là, car les terriens avaient l'avantage.

Notre aventure démarre avec quatre enfants : Ryan, Jamie, Collin et Megan, qui par curiosité s'amusent à monter à bord d'une soucoupe volante écrasée. Malheureusement pendant qu'ils sont encore à bord, la soucoupe est récupérée et ramenée dans la galaxie Whirlpool. Bien évidemment, aucun d'eux ne sachant piloter une soucoupe volante alien, ce moyen de retour est a priori inenvisageable. Sauf qu'une autre race extraterrestre, les Tosonians et leur leader Jaslin, sont prêts à aider nos quatre explorateurs à retrouver le chemin de la voie lactée.

C'est le début d'une formidable aventure sur calculatrices. Pour aider à la construction du vaisseau spatial Tosonian, ton équipe va devoir explorer des planètes, progresser en expérience et niveau, et accumuler des ressources (or, cuivre, lithium, ...).

15446Aujourd'hui Hot_Dog nous fait l'immense plaisir d'une version couleur d'Elimination pour TI-83 Premium CE et TI-84 Plus CE ! :bj:

11 niveaux t'attendent sur 8 planètes peuplées de plus de 70 ennemis dont des boss ; mais qu'attends-tu ? ;)
Attention, Elimination rentre dans la catégorie des programmes en langage machine dits ASM.

Or, suite à un acte hautement maladroit d'un enseignant de Mathématiques français avec ses gesticulations certes compréhensibles mais aveugles dans le contexte de la réforme du lycée, Texas Instruments a réagi en supprimant la gestion de tels programmes depuis la mise à jour 5.5.1.

Si tu es sur une des versions ainsi bridées, tu peux quand même jouer sans trop d'efforts. Il te faut :
  1. installer arTIfiCE pour remettre la possibilité de lancer des programmes ASM
  2. ensuite de préférence installer Cesium pour pouvoir lancer les programmes ASM plus facilement, ou même AsmHook pour pouvoir les lancer comme avant
  3. installer les bibliothèques C nécessaires au fonctionnement de certains jeux dont celui-ci (mais rien de compliqué, juste à transférer le fichier et c'est tout)

Téléchargements :
Link to topic: Elimination, immense RPG pour TI-83 Premium CE (Comments: 6)

Tableau périodique alternatif thème sombre TI-83 Premium CE

New postby critor » 14 Apr 2022, 10:51

Ta calculatrice TI-83 Premium CE ou TI-84 Plus CE dispose d'une application de tableau périodique des éléments appelée Periodic.

Periodic est normalement préinstallé en usine, et est ensuite mis à jour ou réinstallé avec les fichiers de packs de mises à jour diffusés par Texas Instruments chaque année. L'application est alors accessible via la combinaison
2nde
résol
sur TI-83 Premium CE ou via la touche
apps
sur TI-84 Plus CE. Sur TI-83 Premium CE, cette application a même le gros avantage de rester disponible en mode examen, contrairement aux modèles concurrents de chez Casio.

La dernière version de Periodic est la 5.5.0.0038 compilée le 12 mai 2020, et accompagne donc les packs de mises à jour depuis la mise à jour système 5.5 de rentrée 2020.

C'est une très belle application, disposant d'une superbe interface justement en forme de tableau périodique et tirant profit de l'écran couleur pour distinguer différentes familles d'éléments. :favorite:

Mais c'est loin d'être tout. Pour accéder à un élément ciblé, tu as le choix entre parcourir le tableau périodique évoqué ou bien une liste d'éléments. Pour te faciliter les choses cette liste peut justement être triée aussi bien par numéro atomique que nom ou symbole. :D

Rajoutons la possibilité d'exporter les valeurs numériques de propriétés d'élément pour les réutiliser hors de l'application, ainsi que celle de construire des diagrammes qui pourront entre autres mettre en évidence le caractère périodique des propriétés chimiques ! :bj:


Nous en sommes donc à bientôt 2 ans sans mise à jour de l'application Periodic.

Et Texas Instruments ferait peut-être mieux de se méfier car le concurrent français NumWorks a annoncé fin 2021 être en train de travailler sur une application de tableau péridodique pour une future mise à jour, un des plus gros manques de sa calculatrice, et a l'habitude pour chaque nouveauté d'innover grandement sur l'interface...

Frédéric Desautels alias mr womp womp vient donc de sauter sur l'occasion et de te programmer en langage C sa propre vision d'un tableau périodique amélioré pour TI-83 Premium CE et compatibles.

Son programme est bien évidemment loin d'égaler l'application officielle. On peut déplorer :
  • l'impossibilité d'accéder aux éléments par liste
  • l'impossibilité d'exporter ou représenter graphiquement les propriétés numériques
  • la précision décimale inférieure à l'affichage des propriétés numériques
  • la non prise en compte de la langue de la calculatrice, l'affichage étant ici toujours en Anglais
  • un tout petit peu moins de propriétés que Texas Instruments, 13 au lieu de 15

Mais ce qui nous intéresse aujourd'hui ce ne sont pas les manques, mais les différences. Frédéric nous offre en effet quelques évolutions sur l'interface qu'il a tout particulièrement soignée, avec :
  • les symboles des éléments directement affichés sur le tableau périodique et facilitant donc d'une part au plus grand nombre la recherche sur cette interface, et permettant de plus de lister rapidement les éléments appartenant à une même famille ou période :bj:
  • un thème sombre moins agressif pour les yeux :bj:
  • un affichage des propriétés en petite police permettant de tout faire rentrer sur un même écran, au lieu d'avoir à faire défiler sur 3 écrans comme avec Texas Instruments :bj:
  • sur l'affichage des propriétés, possibilité de passer directement à l'élément suivante/précédent avec les touches fléchées sans avoir à repasser par la vue en tableau :bj:

Mais bien sûr à la différence de l'application officielle, ce programme ne restera malheureusement pas disponible en mode examen, les réglementation et spécifications associées semblant avoir été conçues de façon trop complaisante avec les constructeurs ; ce genre de programme parfaitement légitime en France n'aurait jamais dû être bloqué par le mode examen en France. :'(
Donc pour t'en servir en évaluation, pas d'autre choix qu'attendre que Texas Instruments accepte de faire quelque chose de similaire, ou à défaut un de ses concurrents.

Attention, ce programme rentre dans la catégorie des programmes en langage machine dits ASM.

Or, suite à un acte hautement maladroit d'un enseignant de Mathématiques français avec ses gesticulations certes compréhensibles mais maladroites et à courte vue dans le contexte de la réforme du lycée, Texas Instruments a réagi en supprimant la gestion de tels programmes depuis la mise à jour 5.5.1.

Si tu es sur une des versions ainsi bridées, tu peux quand même jouer sans trop d'efforts. Il te faut :
  1. installer arTIfiCE pour remettre la possibilité de lancer des programmes ASM
  2. ensuite de préférence installer Cesium pour pouvoir lancer les programmes ASM plus facilement, ou même AsmHook pour pouvoir les lancer comme avant
  3. installer les bibliothèques C nécessaires au fonctionnement de certains jeux dont celui-ci (mais rien de compliqué, juste à transférer le fichier et c'est tout)

Téléchargements :

Bêta-test micro:bit v2.5.1 pour 83 Premium CE + drone Tello

New postby critor » 18 Apr 2022, 17:10

12212Depuis des années maintenant, Texas Instruments réalise de gros efforts pour rendre la programmation de ses calculatrices accessible à tous et toutes. Le constructeur a prêté une attention toute particulière aux plus jeunes et non initiés, souhaitant leur permettre de créer tous les projets imaginables sans avoir à se concentrer sur des difficultés annexes. :)

Nous pouvions déjà citer l'interface TI-Innovator Hub, le robot pilotable TI-Innovator Rover, la grille programmable TI-RGB Array ou encore l'adaptateur TI-SensorLink pour capteurs analogiques Vernier.
Tous ces éléments ont de plus l'avantage d'être utilisables directement avec le langage Python des calculatrices concernées, faisant de l'écosystème Texas Instruments le seul Python connecté ! :bj:

Un superbe support pour les enseignements scientifiques au lycée surtout maintenant que tous partagent le même langage de programmation, notamment en SNT, spécialité NSI, SI et Physique-Chimie, avec le gros avantage de la mobilité. En effet, les programmes produits et données collectées restent présents dans la calculatrice apportée par chaque élève à chaque cours, ce qui allège la charge logistique de l'enseignant. Données et algorithmes pourront donc être traités / travaillés à la prochaine séance, en devoir à la maison ou même de façon transdisciplinaire en collaboration avec un autre enseignant ! :D

129591295812957Et depuis la rentrée 2020 dernière grande révolution en date, plus besoin de t'équiper en TI-Innovator pour bénéficier de ces formidables avantages. En effet, la TI-83 Premium CE Edition Python française s'est vu rajouter la gestion du nanoordinateur BBC micro:bit programmable en Python dont tu étais peut-être déjà équipé·e ! :bj:

La carte micro:bit est initialement un projet lancé par la BBC (British Broadcasting Corporation), le groupe audiovisuel public britannique, accompagné de nombre de partenaires dont ARM, Microsoft et Samsung. Elle fut distribuée gratuitement à un million d'élèves britanniques de 11 et 12 ans.

Le nom rend hommage au précédent succès du groupe dans ce domaine, le microordinateur à vocation pédagogique BBC Micro des années 1980, l'équivalent britannique de par son adoption à nos microordinateurs Thomson MO5 et TO7 inondant écoles, collèges et lycées à la fin de cette décennie dans le cadre du plan IPT (Informatique Pour Tous).
12277Les cartes micro:bit utilisent un connecteur micro-USB et ta calculatrice un mini-USB.

Pour relier les deux une solution est d'adjoindre un adaptateur mini-USB.

1296512964Pour moins d'encombrement, tu as aussi la solution d'utiliser un câble direct, au choix :
  • USB micro-B mâle ↔ USB mini-A mâle
  • USB micro-B mâle ↔ USB mini-B OTG mâle

1296212961La carte micro:bit dans ses versions 1 est programmable en Python et présentait initialement les caractéristiques et capacités suivantes :
  • processeur 32 bits ARM Cortex-M0 cadencé à 16 MHz
  • mémoire de stockage Flash d'une capacité de 256 Kio
  • mémoire de travail RAM d'une capacité de 16 Kio permettant un heap (tas) Python de 10,048 Ko
  • un afficheur, grille programmable de 5×5= 25 diodes rouges adressables, bien adapté pour l'affichage de motifs éventuellement animés ou encore de texte défilant
  • nombre de capteurs intégrés :
    • capteur de luminosité (lié aux diodes)
    • capteur de température (sur le processeur)
    • 2 boutons poussoirs
      A
      et
      B
      programmables de part et d'autre, comme sur les premières manettes et consoles de jeux portables de chez Nintendo
    • accéléromètre 3D, permettant de détecter les variations d'accélération et par conséquence diverses actions : secouer, pencher, chute libre, ...
    • boussole magnétique 3D, pour détecter cette fois-ci les champs magnétiques
  • connectivité Bluetooth 4.0 basse énergie 2,4 GHz maître/esclave

134501296113451Depuis début 2021 est disponible la nouvelle carte micro:bit v2.

Elle utilise un tout nouveau microcontrôleur, le nRF52833, toujours de chez Nordic Semiconductor. Cette fois-ci nous avons des spécifications qui devraient nous permettre de respirer :
  • processeur 32 bits ARM Cortex-M0 cadencé à 64 MHz au lieu de 16 MHz soit 4 fois plus rapide ! :bj:
  • mémoire de stockage Flash d'une capacité de 512 Kio au lieu de 256 Kio soit 2 fois plus grande ! :bj:
  • mémoire de travail RAM d'une capacité de 128 Kio au lieu de 16 Kio soit 8 fois plus grande, permettant un heap (tas) Python de 64,512 Ko ! :bj:

Elle apporte sur cette même face plusieurs nouveautés ou changements :
  • ajout d'un haut-parleur
  • ajout d'un microphone MEMs
  • bouton poussoir qui ne sert plus seulement à la réinitialisation (reset), mais permet désormais également d'éteindre la carte (appui long) et de la rallumer (appui court)
  • l'antenne Bluetooth qui devient compatible BLE Bluetooth 5.0, contre seulement 4.0 auparavant
1344912962D'autres nouveautés ou changements sont également présents sur l'autre face :
  • ajout d'une diode DEL indiquant l'état du microphone
  • ajout d'un bouton tactile sur le logo micro:bit, voici pourquoi il perd sa couleur au profit de contacts métalliques

13453Expliquons brièvement la composition de la solution de connectivité BBC micro:bit de Texas Instruments, ainsi que son fonctionnement.

Le solution se compose d'une part d'un fichier TI-Runtime unique à copier sur la carte micro:bit v1 ou v2 et qui lui permet d'être pilotée par la calculatrice. La bonne installation du fichier est aisément vérifiable, puisque faisant afficher à la carte le logo Texas Instruments.

La solution a un principe de fonctionnement très simple, mais non moins ingénieux pour autant. La carte micro:bit étant justement programmable en Python, une fois le TI-Runtime installé elle se met alors à écouter les commandes Python envoyées depuis la calculatrice et à les exécuter.

Depuis ta calculatrice, tu peux envoyer n'importe quelle commande Python à ta carte micro:bit et profiter pleinement de ses capacités grâce à la fonction ti_hub.send(), à condition d'encadrer la commande des bons caractères de contrôle. Voici une fonction mb_run() en ce sens :

14956
Code: Select all
from ti_hub import *

def mb_run(code):
  send('\x05') # enter paste mode (Ctrl-E)
  send(code)
  send('\x04') # exit paste mode (Ctrl-D)

Pour afficher par exemple Pac-Man, il te suffit d'appeler mb_run("display.show(Image.PACMAN)"), conformément à la documentation du Python micro:bit.

Toutefois en pratique dans le contexte scolaire, cette façon de faire n'était pas idéale. Elle rajoutait un niveau d'imbrication : tu devais produire du code Python qui lui-même devait construire le code Python à envoyer et exécuter par la carte micro:bit, une marche sans doute un peu haute pour bien des élèves débutants.


Et bien justement, Texas Instruments est loin de s'être arrêté là. Sa solution de connectivité comporte également des bibliothèques Python additionnelles à charger sur ta calculatrice, au choix en Français ou Anglais, et rajoutant alors des menus permettant de faire appel plus simplement aux éléments correspondants sur la carte micro:bit. 11 bibliothèques étaient disponibles dans la dernière version, facilitant ainsi l'utilisation de certaines bibliothèques du Python micro:bit :
  • microbit (générale, permet d'accéder aux menus des autres bibliothèques)
  • mb_audiomicrobit.audio (effets sonores - accessible via le menu Audio)
  • mb_butnsmicrobit.buttons (boutons A, B et tactile intégrés - accessible via le menu Buttons ou Boutons)
  • mb_dispmicrobit.display (afficheur à 5×5=25 LEDs rouges intégré - accessible via le menu Display ou Affichage)
  • mb_grove (capteurs et actionneurs Grove à rajouter - accessible via le menu Grove Devices)
  • mb_log (enregistrement de données - accessible via le menu Data logging ou Enregistrement de données)
  • mb_mic microbit.microphone (micro intégré - accessible via le menu Microphone)
  • mb_musicmicrobit.music (haut-parleur à rajouter sur micro:bit v1 ou intégré sur micro:bit v2 - accessible via le menu Music ou Musique)
  • mb_neopxmicrobit.neopixel (rubans de LEDs programmables à rajouter - accessible via le menu NeoPixel)
  • mb_notes (notes de musique - accessible via le menu Music ou Musique)
  • mb_pins (contacts programmables intégrés - accessible via le menu Input/output pins ou Broches entrée/sortie)
  • mb_radiomicrobit.radio (communication radio intégrée - accessible via le menu Radio)
  • mb_sensr (capteurs intégrés : boussole, accéléromètre, température - accessible via le menu Sensors and gestures ou Capteurs et gestes)




Texas Instruments et l'espace, c'est une grande histoire qui ne date pas d'hier. Outre les calculatrices qui ont accompagné les missions spatiales, on peut citer une collaboration de longue date avec la Nasa, l'agence spatiale américaine, et nombre de projets et événements ont été conçus dans ce cadre.

Dès le début du siècle Texas Instruments nous faisait rêver de faire débarquer des rovers sur Mars et les piloter à l'aide de nos calculatrices.

Si nous avons enfin le TI-Innovator Rover pilotable par calculatrice aujourd'hui, fallait-il déjà commencer par décoller avant d'espérer pouvoir un jour atteindre Mars.

Or lors de la dernière mise à jour en fouillant le TI-Runtime 2.4.0, nous avions découvert des traces de fonctions destinées à la configuration d'un drone Tello.

Ces fonctions n'étaient toutefois pas exposées et n'étaient donc a priori pas utilisables depuis la calculatrice.


Et bien voici aujourd'hui le grand jour.

Texas Instruments te fait l'honneur de t'inviter à un bêta-test public de la prochaine mise à jour de sa solution micro:bit pour TI-83 Premium CE Edition Python et compatibles, avec support du drone Tello ! :bj:








1) Eléments et versions

Go to top

Le pack d'aujourd'hui nous apporte deux éléments:
  • D'une part, nous avons une mise à jour en version 2.5.1 du TI-Runtime pour les micro:bit v2. Toutefois en pratique, en interrogeant la carte micro:bit avec microbit.runtime_version() après mise à jour cette dernière continue à rétourner l'ancienne version 2.4.0.
  • D'autre nous avons une nouvelle bibliothèques Python tello, en version 2.5.
Nous allons de suite creuser le nouveau TI-Runtime pour vérifier qu'il n'y a pas eu d'erreur, et ensuite te présenter la bibliothèque TELLO.




2) Changements TI-Runtime

Go to top

Ici pas de menu fouillable depuis la calculatrice pour connaître les fonctions utilisables, mais on peut procéder autrement. On peut en effet ouvrir directement le fichier sur https://python.microbit.org/v/2 pour pouvoir lire son code source :
Code: Select all
from microbit import *
from machine import freq, reset, time_pulse_us
from time import ticks_us, sleep_ms
from utime import sleep_us

# ------------------------------------------- Tello Drone -----------------------------------------------------------

#tello="TELLO-9EF498"
TX_pin = 'pin1' # yellow grove wire
RX_pin = 'pin15' # white grove wire
is_connected = False

def tello_read(cmd,TX=TX_pin,RX=RX_pin):
  try:
    uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
    uart.read()
    udp_len=len(cmd)
    uart.write('AT+CIPSEND=0,' + str(udp_len) + ',"192.168.10.1",8889\r\n')
    sleep (100)
    uart.read()
    udp = bytes(cmd, 'utf-8')
    uart.write(udp+"\r\n")
    sleep(100)
    timeout = 1
    timer = 0
    while not(uart.any()):
        sleep(1)
        timer += .001
        if timer > timeout:
            status = 'Error: timeout'
            break
    msg = str(uart.read())
    start=msg.find(':')
    end = msg.find('\\r\\n',start)
    msg = msg[start+1:end]
    if msg.find('Non')!=-1:
        msg = '0'
    uart.init(baudrate=115200)
    return(msg)
  except:
    uart.init(baudrate=115200)
    return(False)

def tello_control(cmd,TX=TX_pin,RX=RX_pin):
  try:
    timeout = 10
    uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
    uart.read()
    udp_len=len(cmd)
    uart.write('AT+CIPSEND=0,' + str(udp_len) + ',"192.168.10.1",8889\r\n')
    sleep(100)
    uart.read()
    udp = bytes(cmd, 'utf-8')
    uart.write(udp)
    timer = 0
    sleep(100)
    while not(uart.any()):
        sleep(1)
        timer += .001
        if timer > timeout:
            status ='Error: timeout'
            break
    msg = str(uart.read())
    if msg.find('SEND OK')==-1:
      uart.init(baudrate=115200)
      return (False)
    sleep(100)
    uart.read()
    timer = 0
    while not(uart.any()):
        sleep(1)
        timer += .001
        if timer > timeout:
            status = 'Error: timeout'
            break
    sleep(100)
    msg = str(uart.read())
    start=msg.find('\\r\\n+IPD')

    if msg.find('ok',start)!=-1:
        status = "ok"
    uart.init(baudrate=115200)
    #print("ok")
    #sleep(100)
    #print("ok")
    #sleep(100)
    return(status)
  except:
    uart.init(baudrate=115200)
    return(False)

def tello_connect(ssid,pswd="",TX=TX_pin,RX=RX_pin):
  #display.show(ti)
  try:
    timeout = 30
    global TX_pin
    global RX_pin
    TX_pin=locals()[TX]
    RX_pin=locals()[RX]
    uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
    #uart.write('AT+CWQAP\r\n')
    uart.write('AT+RST\r\n')
    #uart.write('AT+RESTORE\r\n')
    uart.write('AT+RFPOWER=30\r\n')
    uart.write('AT+CWMODE=3\r\n')
    uart.read()
    #sleep(100)
    the_ap ='AT+CWJAP=' + '"' + ssid +'"' + "," + '"' + pswd +'"\r\n'
    uart.write(the_ap + '\r\n')
    is_connected = False
    timer = 0
    sleep(100)
    while is_connected == False:
      timer = 0
      while not(uart.any()):
        sleep(1)
        timer += .002
        if timer > timeout:
            tello_AT('AT+RST\r\n')
            reset()
      msg = str(uart.read())
      if msg.find("WIFI GOT IP") !=-1:
        is_connected = True
    uart.write('AT+CIFSR\r\n')
    sleep(100)
    timer = 0
    while not(uart.any()):
      sleep(1)
      timer >.002
      if timer == timeout:
          tello_AT('AT+RST')
          reset()
    msg = str(uart.read())
    if msg.find("192.168.10") !=-1:
        status = 'got IP'
    uart.write('AT+CIPMUX=1\r\n')
    sleep(100)
    msg = uart.read()
    uart.write('AT+CIPSTART=0,"UDP","192.168.10.1",8889,8889,2\r\n')
    sleep(100)
    msg = uart.read()
    sleep(100)
    cmd='command'
    udp_len=len(cmd)
    uart.write('AT+CIPSEND=0,' + str(udp_len) + ',"192.168.10.1",8889\r\n')
    sleep(200)
    uart.read()
    udp = bytes(cmd, 'utf-8')
    uart.write(udp)
    msg = str(uart.read())
    if msg.find('SEND OK')==-1 and status =='got IP':
        status = "Tello Connected"
        display.show(Image.HAPPY)
    else:
        status = "Tello not responding"
        display.show(Image.SAD)
        uart.init(baudrate=115200)
        return (False)
    uart.init(baudrate=115200)
    #print(status)
    return(status)
  except:
    uart.init(baudrate=115200)
    display.show(Image.SAD)
    return(False)

def discover_tello(TX_pin,RX_pin):
  count = 0
  uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
  uart.write('AT+CWLAPOPT=1,2\r\n')
  while count < 15:
    uart.write('AT+CWLAP\r\n')
    while not(uart.any()):
      sleep(10)
    uart.read()     
    sleep(1000)
    msg = str(uart.read())
    start=msg.find('TELLO')
    if start != -1:
      end = msg.find('"',start)
      msg = msg[start:end]
      uart.init(baudrate=115200)
      return(msg)
    else:
      count += 1
  uart.init(baudrate=115200)
  return(False)
 
def write_tello_setup(ssid,tx,rx,number):
  try:
    cfg=open('tello.cfg','w')
    cfg.write(ssid + "@" + tx + "$" + rx + "%" +  number)
    cfg.close()
    return(True)
  except:
    print (False)

def read_tello_setup():
  cfg=open('tello.cfg','r')
  msg = cfg.read()
  d1 = msg.find('@')
  d2 = msg.find('$')
  d3 = msg.find('%')
  ssid = msg[:d1]
  tx = msg[d1+1:d2]
  rx = msg[d2+1:d3]
  number = msg[d3+1:]
  display.show(number)
  return ssid, tx,rx, number
 
# ------------------------------------------- ultrasonic ranger -----------------------------------------------------------

def ranger(pin=pin0,time = True):
  timeout_us=30000     
  pin.write_digital(0)
  sleep_us(2)
  pin.write_digital(1)
  sleep_us(10)
  pin.write_digital(0)
  pin.read_digital()
  duration = time_pulse_us(pin, 1, timeout_us)/1e6 # t_echo in seconds 
  distance = 343 * duration/2 * 100
  if time:
    return duration
  else:
    return distance

# ------------------------------------------- pulse timer ----------------------------------------------------------------
def time_pulses(pin,pulses):
    try:
        pin.read_digital()
        # wait for one trigger pulse
        while not pin.read_digital():
            pass
        while pin.read_digital():
            pass
        while not pin.read_digital():
            pass
        # begin timing pulses
        t0=ticks_us()
        for n in range(pulses-1):
            while (not pin.read_digital()):
                pass
            while pin.read_digital():
                pass
        tf=ticks_us()
        pulses_time = (tf-t0)/1000000
        return(str(pulses_time))
    except:
        pass

def time_H_to_L(pin):
        pin.read_digital()
        while (pin.read_digital()):
            pass
        t0=ticks_us()
        while not (pin.read_digital()):
            pass
        tf=ticks_us()
        pulse_time = (tf-t0)/1000000
        return(str(pulse_time))

def time_L_to_H(pin):
        pin.read_digital()
        while not (pin0.read_digital()):
            pass
        t0=ticks_us()
        while (pin.read_digital()):
            pass
        tf=ticks_us()
        pulse_time = (tf-t0)/1000000
        return(str(pulse_time))
       

# -------------------------------------------BME280 Barometric Pressure -----------------------------------------------------------
class BME280():
  def __init__(self):
    self.ready = False
    self.IDRegister  = 0xD0         
    self.CTRL_HUM    = 0xF2                 
    self.CTRL_MEAS   = 0xF4         
    self.CONFIG      = 0xF5       
    self.t_fine      = 0
    self.dig_T1      = 0
    self.dig_T2      = 0
    self.dig_T3      = 0
    self.dig_P1      = 0   
    self.dig_P2      = 0   
    self.dig_P3      = 0   
    self.dig_P4      = 0   
    self.dig_P5      = 0 
    self.dig_P6      = 0
    self.dig_P7      = 0 
    self.dig_P8      = 0
    self.dig_P9      = 0
    self.dig_H1      = 0                         
    self.dig_H2      = 0
    self.dig_H3      = 0
    self.dig_H4      = 0
    self.dig_H5      = 0
    self.dig_H6      = 0
    self.TRAW      = 0
    self.PRAW      = 0
    self.HRAW      = 0
    self.ConfigurationData           = bytearray(6)
    self.CalData00_25                = bytearray(25)
    self.CalData00_25BaseAddress     = bytearray(1)
    self.CalData00_25BaseAddress[0]  = 0x88
    self.CalData26_41                = bytearray(7)
    self.CalData26_41BaseAddress     = bytearray(1)
    self.CalData26_41BaseAddress[0]  = 0xE1
    self.RawSensorData               = bytearray(8)
    self.RawSensorDataBaseAddress    = bytearray(1)
    self.RawSensorDataBaseAddress[0] = 0xF7
   
  def init(self):
    try:
      IDAddress     = bytearray(1)
      IDAddress[0]  = self.IDRegister
      i2c.write(0x76, IDAddress, repeat = False)
      id = i2c.read(0x76, 1, repeat = False)
      i2c.write(0x76, self.CalData00_25BaseAddress, repeat = False)   
      self.CalData00_25 = i2c.read(0x76, 25, repeat = False)
      i2c.write(0x76, self.CalData26_41BaseAddress, repeat = False)   
      self.CalData26_41 = i2c.read(0x76, 7, repeat = False)
      self.dig_T1 = self.BuildU16(self.CalData00_25[1], self.CalData00_25[0])     
      self.dig_T2 = self.BuildS16(self.CalData00_25[3], self.CalData00_25[2])     
      self.dig_T3 = self.BuildS16(self.CalData00_25[5], self.CalData00_25[4])     
      self.dig_P1 = self.BuildU16(self.CalData00_25[7], self.CalData00_25[6])     
      self.dig_P2 = self.BuildS16(self.CalData00_25[9], self.CalData00_25[8])     
      self.dig_P3 = self.BuildS16(self.CalData00_25[11], self.CalData00_25[10])   
      self.dig_P4 = self.BuildS16(self.CalData00_25[13], self.CalData00_25[12])   
      self.dig_P5 = self.BuildS16(self.CalData00_25[15], self.CalData00_25[14])   
      self.dig_P6 = self.BuildS16(self.CalData00_25[17], self.CalData00_25[16])   
      self.dig_P7 = self.BuildS16(self.CalData00_25[19], self.CalData00_25[18])   
      self.dig_P8 = self.BuildS16(self.CalData00_25[21], self.CalData00_25[20])
      self.dig_P9 = self.BuildS16(self.CalData00_25[23], self.CalData00_25[22])
      self.dig_H1 = self.CalData00_25[24]                           
      self.dig_H2 = self.BuildS16(self.CalData26_41[1],self.CalData26_41[0])
      self.dig_H3 = self.CalData26_41[2]
      self.dig_H4 = (self.BuildS8(self.CalData26_41[3]) << 4) | (self.CalData26_41[4] & 0x0F)
      self.dig_H5 = (self.BuildS8(self.CalData26_41[5]) << 4) | ((self.CalData26_41[4] >> 4) & 0x0F)
      self.dig_H6 = self.BuildS8(self.CalData26_41[6])
      self.ConfigurationData[0] = self.CTRL_HUM       
      self.ConfigurationData[1] = 0b00000101     
      self.ConfigurationData[2] = self.CTRL_MEAS       
      self.ConfigurationData[3] = 0b10110111
      self.ConfigurationData[4] = self.CONFIG     
      self.ConfigurationData[5] = 0b01000000       
      i2c.write(0x76,self.ConfigurationData, repeat=False)
      sleep(100)
      self.ready = True
    except:
      pass

  def BuildS16(self,msb, lsb):
      sval = ((msb << 8) | lsb)
      if sval > 32767: 
          sval -= 65536
      return sval
         
  def BuildU16(self,msb, lsb):
      return ((msb << 8) |lsb)


  def BuildS8(self,b):
      if b > 127:
          return (b-256)
      else:
          return b
         
  def CalculateTemperature(self):   
      self.t_fine
      Traw = float(self.TRAW)
      v1 = (Traw/ 16384.0 - float(self.dig_T1) / 1024.0) * float(self.dig_T2)
      v2 = ((Traw / 131072.0 - float(self.dig_T1) / 8192.0) * (
      Traw / 131072.0 - float(self.dig_T1) / 8192.0)) * float(self.dig_T3)
      self.t_fine = int(v1 + v2)
      T = (v1 + v2) / 5120.0
      return T

  def CalculatePressure(self):
      Praw = float(self.PRAW)
      v1 = float(self.t_fine) / 2.0 - 64000.0
      v2 = v1 * v1 * float(self.dig_P6) / 32768.0
      v2 = v2 + v1 * float(self.dig_P5) * 2.0
      v2 = v2 / 4.0 + float(self.dig_P4) * 65536.0
      v1 = (float(self.dig_P3) * v1 * v1 / 524288.0 + float(self.dig_P2) * v1) / 524288.0
      v1 = (1.0 + v1 / 32768.0) * float(self.dig_P1)
      if v1 == 0:
          return 0
      p  = 1048576.0 - Praw
      p  = ((p - v2 / 4096.0) * 6250.0) / v1
      v1 = float(self.dig_P9) * p * p / 2147483648.0
      v2 = p * float(self.dig_P8) / 32768.0
      p  = p + (v1 + v2 + float(self.dig_P7)) / 16.0
      return p
     
  def CalculateHumidity(self):
      self.t_fine
      Hraw = float(self.HRAW)
      h = float(self.t_fine) - 76800.0
      h = (Hraw - (float(self.dig_H4) * 64.0 + float(self.dig_H5) / 16384.0 * h)) * (
          float(self.dig_H2) / 65536.0 * (1.0 + float(self.dig_H6) / 67108864.0 * h * (
          1.0 + float(self.dig_H3) / 67108864.0 * h)))
      h = h * (1.0 - float(self.dig_H1) * h / 524288.0)
      if h > 100:
          h = 100
      elif h < 0:
          h = 0
      return h

  def read(self):
    if self.ready:
      try:
        i2c.write(0x76, self.RawSensorDataBaseAddress, repeat = False)
        sleep(100)
        self.RawSensorData = i2c.read(0x76, 8, repeat = False)
        sleep(100)
        self.TRAW = ((self.RawSensorData[3] << 16) | (self.RawSensorData[4] << 8) | self.RawSensorData[5]) >> 4
        self.PRAW = ((self.RawSensorData[0] << 16) | (self.RawSensorData[1] << 8) | self.RawSensorData[2]) >> 4
        self.HRAW = (self.RawSensorData[6] << 8)   | self.RawSensorData[7]
        return self.CalculateTemperature(),self.CalculatePressure(),self.CalculateHumidity()
      except:
        pass
    else:
      self.init()
      if self.ready:
        return (self.read())
      else:
       return None
# -------------------------------------------DHT20 Temperature and Humidity -----------------------------------------------------------
       
class DHT20():
  def __init__(self):
    self.ready = False
   
  def init(self):
    try:
      i2c.write(0x38, bytes([0xa8,0x00,0x00]))
      sleep_ms(100)
      i2c.write(0x38, bytes([0xbe,0x08,0x00]))
      sleep(100)
      self.ready = True
    except:
      pass   
   
  def read(self):
    if self.ready:
      try:
        i2c.write(0x38, bytes([0xac,0x33,0x00]))
        sleep(100)
        raw = i2c.read(0x38, 7, True)
        sleep(100)
        data = []
        for i in raw[:]:
          data.append(i)
        temperature = 0
        temperature = (temperature | data[3]) << 8
        temperature = (temperature | data[4]) << 8
        temperature = temperature | data[5]
        temperature = temperature & 0xfffff
        temperature = (temperature * 200 * 10 / 1024 / 1024 - 500)/10
        humidity = 0
        humidity = (humidity | data[1]) << 8
        humidity = (humidity | data[2]) << 8
        humidity = humidity | data[3]
        humidity = humidity >> 4
        humidity = (humidity * 100 * 10 / 1024 / 1024)/10   
        return temperature, humidity
      except:
        pass
    else:
      self.init()
      if self.ready:
        return (self.read())
      else:
       return None


# -------------------------------------------SGP30 VOC and CO2 -----------------------------------------------------------

class SGP30:
  def __init__(self):
    self.ready = False
   
  def init(self):
    try:
      i2c.write(0x58,bytes([0x36, 0x82]))
      self.iaq_init()
      self.ready = True
    except:
      pass 
   
  def TVOC(self):
    return self.iaq_measure()[1]
   
  def baseline_TVOC(self):
    return self.get_iaq_baseline()[1]
   
  def eCO2(self):
    return self.iaq_measure()[0]
   
  def baseline_eCO2(self):
    return self.get_iaq_baseline()[0]
   
  def iaq_init(self):
    self.run(['iaq_init',[0x20,0x03],0,10])
   
  def iaq_measure(self):
    return self.run(['iaq_measure',[0x20,0x08],2,50])
   
  def get_iaq_baseline(self):
    return self.run(['iaq_get_baseline',[0x20,0x15],2,10])
   
  def set_iaq_baseline(self,eCO2,TVOC):
    if eCO2==0 and TVOC==0:raise RuntimeError('Invalid baseline')
    b=[]
    for i in [TVOC,eCO2]:
      a=[i>>8,i&0xFF]
      a.append(self.g_crc(a))
      b+=a
    self.run(['iaq_set_baseline',[0x20,0x1e]+b,0,10])
   
  def set_iaq_humidity(self,PM3):
    b=[]
    for i in [int(PM3*256)]:
      a=[i>>8,i&0xFF]
      a.append(self.g_crc(a))
      b+=a
    self.run(['iaq_set_humidity',[0x20,0x61]+b,0,10])
   
  def run(self,profile):
    n,cmd,s,d=profile
    return self.get(cmd,d,s)
   
  def get(self,cmd,d,rs):
    i2c.write(0x58,bytearray(cmd))
    sleep(d)
    if not rs:return None
    cr=i2c.read(0x58,rs*3)
    o=[]
    for i in range(rs):
      w=[cr[3*i],cr[3*i+1]]
      c=cr[3*i+2]
      if self.g_crc(w)!=c:raise RuntimeError('CRC Error')
      o.append(w[0]<<8|w[1])
    return o
   
  def g_crc(self,data):
    c=0xFF
    for byte in data:
      c^=byte
      for _ in range(8):
        if c&0x80:c=(c<<1)^0x31
        else:c<<=1
    return c&0xFF
 
  def read(self):
    if self.ready:
      try:
        return self.eCO2(), self.TVOC()
      except:
        pass
    else:
      self.init()
      if self.ready:
        return (self.read())
      else:
       return None

# ------------------------------------------- start up -----------------------------------------------------------

def ismb():
  return(True)
 
def get_version():
    print ("TI-Runtime Version 2.4.0")
   
bme280 = BME280()
dht20 = DHT20()
sgp30 = SGP30()
ti = Image("05500:""05595:""55555:""05550:""00500")
display.show(ti)
Code: Select all
from microbit import *
from machine import freq, reset, time_pulse_us
from time import ticks_us, sleep_ms
from utime import sleep_us

tello="TELLO-9EF498"
TX_pin = pin2 # white grove wire
RX_pin = pin1 # yellow grove wire
ssid = "3227 Ridge Road"
pswd="7209909589"

# ------------------------------------------- Tello Drone -----------------------------------------------------------


is_connected = False
 
def tello_read(cmd,TX=TX_pin,RX=RX_pin):
  try:
    uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
    uart.read()
    udp_len=len(cmd)
    uart.write('AT+CIPSEND=0,' + str(udp_len) + ',"192.168.10.1",8889\r\n')
    sleep (100)
    uart.read()
    udp = bytes(cmd, 'utf-8')
    uart.write(udp+"\r\n")
    sleep(100)
    timeout = 1
    timer = 0
    while not(uart.any()):
        sleep(1)
        timer += .001
        if timer > timeout:
            status = 'Error: timeout'
            break
    msg = str(uart.read())
    start=msg.find(':')
    end = msg.find('\\r\\n',start)
    msg = msg[start+1:end]
    if msg.find('Non')!=-1:
        msg = '0'
    uart.init(baudrate=115200)
    return(msg)
  except:
    uart.init(baudrate=115200)
    return(False)

def tello_control(cmd,TX=TX_pin,RX=RX_pin):
  try:
    timeout = 10
    uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
    uart.read()
    udp_len=len(cmd)
    uart.write('AT+CIPSEND=0,' + str(udp_len) + ',"192.168.10.1",8889\r\n')
    sleep(100)
    uart.read()
    udp = bytes(cmd, 'utf-8')
    uart.write(udp)
    timer = 0
    sleep(100)
    while not(uart.any()):
        sleep(1)
        timer += .001
        if timer > timeout:
            status ='Error: timeout'
            break
    msg = str(uart.read())
    if msg.find('SEND OK')==-1:
      uart.init(baudrate=115200)
      return (False)
    sleep(100)
    uart.read()
    timer = 0
    while not(uart.any()):
        sleep(1)
        timer += .001
        if timer > timeout:
            status = 'Error: timeout'
            break
    sleep(100)
    msg = str(uart.read())
    start=msg.find('\\r\\n+IPD')

    if msg.find('ok',start)!=-1:
        status = "ok"
    uart.init(baudrate=115200)
    #print("ok")
    #sleep(100)
    #print("ok")
    #sleep(100)
    return(status)
  except:
    uart.init(baudrate=115200)
    return(False)

def tello_connect(ssid,pswd="",TX=TX_pin,RX=RX_pin):
  #display.show(ti)
  # when the configuration is read, global TX and RX should be updated
  try:
    timeout = 30
    global TX_pin
    global RX_pin
    TX_pin=locals()[TX]
    RX_pin=locals()[RX]
    uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
    #uart.write('AT+CWQAP\r\n')
    uart.write('AT+RST\r\n')
    #uart.write('AT+RESTORE\r\n')
    uart.write('AT+RFPOWER=30\r\n')
    uart.write('AT+CWMODE=3\r\n')
    uart.read()
    #sleep(100)
    the_ap ='AT+CWJAP=' + '"' + ssid +'"' + "," + '"' + pswd +'"\r\n'
    uart.write(the_ap + '\r\n')
    is_connected = False
    timer = 0
    sleep(100)
    while is_connected == False:
      timer = 0
      while not(uart.any()):
        sleep(1)
        timer += .002
        if timer > timeout:
            tello_AT('AT+RST\r\n')
            reset()
      msg = str(uart.read())
      if msg.find("WIFI GOT IP") !=-1:
        is_connected = True
    uart.write('AT+CIFSR\r\n')
    sleep(100)
    timer = 0
    while not(uart.any()):
      sleep(1)
      timer >.002
      if timer == timeout:
          tello_AT('AT+RST')
          reset()
    msg = str(uart.read())
    if msg.find("192.168.10") !=-1:
        status = 'got IP'
    uart.write('AT+CIPMUX=1\r\n')
    sleep(100)
    msg = uart.read()
    uart.write('AT+CIPSTART=0,"UDP","192.168.10.1",8889,8889,2\r\n')
    sleep(100)
    msg = uart.read()
    sleep(100)
    cmd='command'
    udp_len=len(cmd)
    uart.write('AT+CIPSEND=0,' + str(udp_len) + ',"192.168.10.1",8889\r\n')
    sleep(200)
    uart.read()
    udp = bytes(cmd, 'utf-8')
    uart.write(udp)
    msg = str(uart.read())
    if msg.find('SEND OK')==-1 and status =='got IP':
        status = "Tello Connected"
        display.show(Image.YES)
    else:
        status = "Tello not responding"
        display.show(Image.NO)
        uart.init(baudrate=115200)
        return (False)
    uart.init(baudrate=115200)
    #print(status)
    return(status)
  except:
    uart.init(baudrate=115200)
    display.show(Image.NO)
    return(False)

def discover_tello(TX_pin,RX_pin):
  count = 0
  uart.init(baudrate=115200,tx=TX_pin,rx=RX_pin)
  uart.write('AT+CWLAPOPT=1,2\r\n')
  while count < 30:
    uart.write('AT+CWLAP\r\n')
    while not(uart.any()):
      sleep(10)
    uart.read()     
    sleep(1000)
    msg = str(uart.read())
    start=msg.find('TELLO')
    if start != -1:
      end = msg.find('"',start)
      msg = msg[start:end]
      uart.init(baudrate=115200)
      return(msg)
    else:
      count += 1
  uart.init(baudrate=115200)
  return(False)
 
def write_tello_setup(ssid,tx,rx,number):
  try:
    cfg=open('tello.cfg','w')
    cfg.write(ssid + "@" + tx + "$" + rx + "%" +  number)
    cfg.close()
    return(True)
  except:
    print (False)

def read_tello_setup():
  try:
    cfg=open('tello.cfg','r')
    msg = cfg.read()
    d1 = msg.find('@')
    d2 = msg.find('$')
    d3 = msg.find('%')
    ssid = msg[:d1]
    tx = msg[d1+1:d2]
    rx = msg[d2+1:d3]
    number = msg[d3+1:]
    display.show(number)
    return ssid, tx,rx, number
  except:
    return False


# ------------------------------------------- ultrasonic ranger -----------------------------------------------------------

def ranger(pin=pin0,time = True):
  timeout_us=30000     
  pin.write_digital(0)
  sleep_us(2)
  pin.write_digital(1)
  sleep_us(10)
  pin.write_digital(0)
  pin.read_digital()
  duration = time_pulse_us(pin, 1, timeout_us)/1e6 # t_echo in seconds 
  distance = 343 * duration/2 * 100
  if time:
    return duration
  else:
    return distance

# ------------------------------------------- pulse timer ----------------------------------------------------------------
def time_pulses(pin,pulses):
    try:
        pin.read_digital()
        # wait for one trigger pulse
        while not pin.read_digital():
            pass
        while pin.read_digital():
            pass
        while not pin.read_digital():
            pass
        # begin timing pulses
        t0=ticks_us()
        for n in range(pulses-1):
            while (not pin.read_digital()):
                pass
            while pin.read_digital():
                pass
        tf=ticks_us()
        pulses_time = (tf-t0)/1000000
        return(str(pulses_time))
    except:
        pass

def time_H_to_L(pin):
        pin.read_digital()
        while (pin.read_digital()):
            pass
        t0=ticks_us()
        while not (pin.read_digital()):
            pass
        tf=ticks_us()
        pulse_time = (tf-t0)/1000000
        return(str(pulse_time))

def time_L_to_H(pin):
        pin.read_digital()
        while not (pin0.read_digital()):
            pass
        t0=ticks_us()
        while (pin.read_digital()):
            pass
        tf=ticks_us()
        pulse_time = (tf-t0)/1000000
        return(str(pulse_time))
       

# -------------------------------------------BME280 Barometric Pressure -----------------------------------------------------------
class BME280():
  def __init__(self):
    self.ready = False
    self.IDRegister  = 0xD0         
    self.CTRL_HUM    = 0xF2                 
    self.CTRL_MEAS   = 0xF4         
    self.CONFIG      = 0xF5       
    self.t_fine      = 0
    self.dig_T1      = 0
    self.dig_T2      = 0
    self.dig_T3      = 0
    self.dig_P1      = 0   
    self.dig_P2      = 0   
    self.dig_P3      = 0   
    self.dig_P4      = 0   
    self.dig_P5      = 0 
    self.dig_P6      = 0
    self.dig_P7      = 0 
    self.dig_P8      = 0
    self.dig_P9      = 0
    self.dig_H1      = 0                         
    self.dig_H2      = 0
    self.dig_H3      = 0
    self.dig_H4      = 0
    self.dig_H5      = 0
    self.dig_H6      = 0
    self.TRAW      = 0
    self.PRAW      = 0
    self.HRAW      = 0
    self.ConfigurationData           = bytearray(6)
    self.CalData00_25                = bytearray(25)
    self.CalData00_25BaseAddress     = bytearray(1)
    self.CalData00_25BaseAddress[0]  = 0x88
    self.CalData26_41                = bytearray(7)
    self.CalData26_41BaseAddress     = bytearray(1)
    self.CalData26_41BaseAddress[0]  = 0xE1
    self.RawSensorData               = bytearray(8)
    self.RawSensorDataBaseAddress    = bytearray(1)
    self.RawSensorDataBaseAddress[0] = 0xF7
   
  def init(self):
    try:
      IDAddress     = bytearray(1)
      IDAddress[0]  = self.IDRegister
      i2c.write(0x76, IDAddress, repeat = False)
      id = i2c.read(0x76, 1, repeat = False)
      i2c.write(0x76, self.CalData00_25BaseAddress, repeat = False)   
      self.CalData00_25 = i2c.read(0x76, 25, repeat = False)
      i2c.write(0x76, self.CalData26_41BaseAddress, repeat = False)   
      self.CalData26_41 = i2c.read(0x76, 7, repeat = False)
      self.dig_T1 = self.BuildU16(self.CalData00_25[1], self.CalData00_25[0])     
      self.dig_T2 = self.BuildS16(self.CalData00_25[3], self.CalData00_25[2])     
      self.dig_T3 = self.BuildS16(self.CalData00_25[5], self.CalData00_25[4])     
      self.dig_P1 = self.BuildU16(self.CalData00_25[7], self.CalData00_25[6])     
      self.dig_P2 = self.BuildS16(self.CalData00_25[9], self.CalData00_25[8])     
      self.dig_P3 = self.BuildS16(self.CalData00_25[11], self.CalData00_25[10])   
      self.dig_P4 = self.BuildS16(self.CalData00_25[13], self.CalData00_25[12])   
      self.dig_P5 = self.BuildS16(self.CalData00_25[15], self.CalData00_25[14])   
      self.dig_P6 = self.BuildS16(self.CalData00_25[17], self.CalData00_25[16])   
      self.dig_P7 = self.BuildS16(self.CalData00_25[19], self.CalData00_25[18])   
      self.dig_P8 = self.BuildS16(self.CalData00_25[21], self.CalData00_25[20])
      self.dig_P9 = self.BuildS16(self.CalData00_25[23], self.CalData00_25[22])
      self.dig_H1 = self.CalData00_25[24]                           
      self.dig_H2 = self.BuildS16(self.CalData26_41[1],self.CalData26_41[0])
      self.dig_H3 = self.CalData26_41[2]
      self.dig_H4 = (self.BuildS8(self.CalData26_41[3]) << 4) | (self.CalData26_41[4] & 0x0F)
      self.dig_H5 = (self.BuildS8(self.CalData26_41[5]) << 4) | ((self.CalData26_41[4] >> 4) & 0x0F)
      self.dig_H6 = self.BuildS8(self.CalData26_41[6])
      self.ConfigurationData[0] = self.CTRL_HUM       
      self.ConfigurationData[1] = 0b00000101     
      self.ConfigurationData[2] = self.CTRL_MEAS       
      self.ConfigurationData[3] = 0b10110111
      self.ConfigurationData[4] = self.CONFIG     
      self.ConfigurationData[5] = 0b01000000       
      i2c.write(0x76,self.ConfigurationData, repeat=False)
      sleep(100)
      self.ready = True
    except:
      pass

  def BuildS16(self,msb, lsb):
      sval = ((msb << 8) | lsb)
      if sval > 32767: 
          sval -= 65536
      return sval
         
  def BuildU16(self,msb, lsb):
      return ((msb << 8) |lsb)


  def BuildS8(self,b):
      if b > 127:
          return (b-256)
      else:
          return b
         
  def CalculateTemperature(self):   
      self.t_fine
      Traw = float(self.TRAW)
      v1 = (Traw/ 16384.0 - float(self.dig_T1) / 1024.0) * float(self.dig_T2)
      v2 = ((Traw / 131072.0 - float(self.dig_T1) / 8192.0) * (
      Traw / 131072.0 - float(self.dig_T1) / 8192.0)) * float(self.dig_T3)
      self.t_fine = int(v1 + v2)
      T = (v1 + v2) / 5120.0
      return T

  def CalculatePressure(self):
      Praw = float(self.PRAW)
      v1 = float(self.t_fine) / 2.0 - 64000.0
      v2 = v1 * v1 * float(self.dig_P6) / 32768.0
      v2 = v2 + v1 * float(self.dig_P5) * 2.0
      v2 = v2 / 4.0 + float(self.dig_P4) * 65536.0
      v1 = (float(self.dig_P3) * v1 * v1 / 524288.0 + float(self.dig_P2) * v1) / 524288.0
      v1 = (1.0 + v1 / 32768.0) * float(self.dig_P1)
      if v1 == 0:
          return 0
      p  = 1048576.0 - Praw
      p  = ((p - v2 / 4096.0) * 6250.0) / v1
      v1 = float(self.dig_P9) * p * p / 2147483648.0
      v2 = p * float(self.dig_P8) / 32768.0
      p  = p + (v1 + v2 + float(self.dig_P7)) / 16.0
      return p
     
  def CalculateHumidity(self):
      self.t_fine
      Hraw = float(self.HRAW)
      h = float(self.t_fine) - 76800.0
      h = (Hraw - (float(self.dig_H4) * 64.0 + float(self.dig_H5) / 16384.0 * h)) * (
          float(self.dig_H2) / 65536.0 * (1.0 + float(self.dig_H6) / 67108864.0 * h * (
          1.0 + float(self.dig_H3) / 67108864.0 * h)))
      h = h * (1.0 - float(self.dig_H1) * h / 524288.0)
      if h > 100:
          h = 100
      elif h < 0:
          h = 0
      return h

  def read(self):
    if self.ready:
      try:
        i2c.write(0x76, self.RawSensorDataBaseAddress, repeat = False)
        sleep(100)
        self.RawSensorData = i2c.read(0x76, 8, repeat = False)
        sleep(100)
        self.TRAW = ((self.RawSensorData[3] << 16) | (self.RawSensorData[4] << 8) | self.RawSensorData[5]) >> 4
        self.PRAW = ((self.RawSensorData[0] << 16) | (self.RawSensorData[1] << 8) | self.RawSensorData[2]) >> 4
        self.HRAW = (self.RawSensorData[6] << 8)   | self.RawSensorData[7]
        return self.CalculateTemperature(),self.CalculatePressure(),self.CalculateHumidity()
      except:
        pass
    else:
      self.init()
      if self.ready:
        return (self.read())
      else:
       return None
# -------------------------------------------DHT20 Temperature and Humidity -----------------------------------------------------------
       
class DHT20():
  def __init__(self):
    self.ready = False
   
  def init(self):
    try:
      i2c.write(0x38, bytes([0xa8,0x00,0x00]))
      sleep_ms(100)
      i2c.write(0x38, bytes([0xbe,0x08,0x00]))
      sleep(100)
      self.ready = True
    except:
      pass   
   
  def read(self):
    if self.ready:
      try:
        i2c.write(0x38, bytes([0xac,0x33,0x00]))
        sleep(100)
        raw = i2c.read(0x38, 7, True)
        sleep(100)
        data = []
        for i in raw[:]:
          data.append(i)
        temperature = 0
        temperature = (temperature | data[3]) << 8
        temperature = (temperature | data[4]) << 8
        temperature = temperature | data[5]
        temperature = temperature & 0xfffff
        temperature = (temperature * 200 * 10 / 1024 / 1024 - 500)/10
        humidity = 0
        humidity = (humidity | data[1]) << 8
        humidity = (humidity | data[2]) << 8
        humidity = humidity | data[3]
        humidity = humidity >> 4
        humidity = (humidity * 100 * 10 / 1024 / 1024)/10   
        return temperature, humidity
      except:
        pass
    else:
      self.init()
      if self.ready:
        return (self.read())
      else:
       return None


# -------------------------------------------SGP30 VOC and CO2 -----------------------------------------------------------

class SGP30:
  def __init__(self):
    self.ready = False
   
  def init(self):
    try:
      i2c.write(0x58,bytes([0x36, 0x82]))
      self.iaq_init()
      self.ready = True
    except:
      pass 
   
  def TVOC(self):
    return self.iaq_measure()[1]
   
  def eCO2(self):
    return self.iaq_measure()[0]   

  def iaq_init(self):
    self.run(['iaq_init',[0x20,0x03],0,10])

  def iaq_measure(self):
    return self.run(['iaq_measure',[0x20,0x08],2,50])
     
  def baseline_TVOC(self):
    return self.get_iaq_baseline()[1]
       
  def baseline_eCO2(self):
    return self.get_iaq_baseline()[0]
   
  def get_iaq_baseline(self):
    return self.run(['iaq_get_baseline',[0x20,0x15],2,10])
   
  def set_iaq_baseline(self,eCO2,TVOC):
    if eCO2==0 and TVOC==0:raise RuntimeError('Invalid baseline')
    b=[]
    for i in [TVOC,eCO2]:
      a=[i>>8,i&0xFF]
      a.append(self.g_crc(a))
      b+=a
    self.run(['iaq_set_baseline',[0x20,0x1e]+b,0,10])
   
  def set_iaq_humidity(self,PM3):
    b=[]
    for i in [int(PM3*256)]:
      a=[i>>8,i&0xFF]
      a.append(self.g_crc(a))
      b+=a
    self.run(['iaq_set_humidity',[0x20,0x61]+b,0,10])

   
  def run(self,profile):
    n,cmd,s,d=profile
    return self.get(cmd,d,s)

 
  def get(self,cmd,d,rs):
    i2c.write(0x58,bytearray(cmd))
    sleep(d)
    if not rs:return None
    cr=i2c.read(0x58,rs*3)
    o=[]
    for i in range(rs):
      w=[cr[3*i],cr[3*i+1]]
      c=cr[3*i+2]
      if self.g_crc(w)!=c:raise RuntimeError('CRC Error')
      o.append(w[0]<<8|w[1])
    return o
   
  def g_crc(self,data):
    c=0xFF
    for byte in data:
      c^=byte
      for _ in range(8):
        if c&0x80:c=(c<<1)^0x31
        else:c<<=1
    return c&0xFF

 
  def read(self):
    if self.ready:
      try:
        return self.eCO2(), self.TVOC()
      except:
        pass
    else:
      self.init()
      if self.ready:
        return (self.read())
      else:
       return None


# ------------------------------------------- start up -----------------------------------------------------------

def ismb():
  return(True)
 
def get_version():
    print ("TI-Runtime Version 2.4.0")
   
bme280 = BME280()
dht20 = DHT20()
sgp30 = SGP30()
ti = Image("05500:""05595:""55555:""05550:""00500")
display.show(ti)

L'on constate en effet que la quasi totalité des changements concernent le support du drone Tello.




3) Nouvelle bibliothèque TELLO et premier script

Go to top

La bibliothèque TELLO une fois chargée sur ta calculatrice, est importable dans des scripts Python en passant par le menu des modules complémentaires. Cela t'active alors un nouveau menu tello drone.

Nous y retrouvons alors plusieurs onglets :
  • Fly pour tout ce qui concerne les contrôles dans le cadre d'un vol
  • Data pour interroger les capteurs intégrés au drone Tello
  • Maneuver pour quelques figures acrobatiques
  • EDU pour les plans de vol
  • Settings pour les réglages


Cela a l'air super simple non, enfantin même ? Voici donc déjà un premier script : :D
Code: Select all
from tello import *
tello.takeoff()
tello.forward(50)
d=tello.altitude()
tello.turn_left(180)
tello.forward(50)
tello.land()




4) Matériel nécessaire et premiers branchements

Go to top

Bref outre la calculatrice, que te faut-il maintenant niveau matériel pour piloter un drone Tello ?

  1. nanoordinateur BBC micro:bit v2
  2. câble mini/micro-USB direct pour BBC micro:bit v2 et calculatrice
  3. carte d'extension Grove ou bitmaker
  4. module Grove WiFi + cable Grove
  5. batterie externe USB + câble micro-USB
  6. drone Tello

Tu as tout le matériel entre les mains ? C'est parti pour les manipulations :

Commençons par enregistrer ton drone Tello si c'est sa première utilisation, étape qui ne peut se faire avec la calculatrice :
  1. Télécharge l'application de vol Tello sur ton téléphone.
  2. Allume ton drone Tello.
  3. Sur ton téléphone, recherche les points d'accès WiFi.
  4. Connecte-toi au point d'accès Tello qui devrait apparaître.
  5. Ouvre l'application et accepte l'enregistrement.
  6. Ferme l'application et déconnecte ton téléphone du point d'accès Tello.
    (attention à ce que ton téléphone n'y reste pas connecté ou ne s'y reconnecte pas tout seul, ce qui risque de perturber la communication avec la calculatrice)

Voici maintenant pour les connexions :
  1. Insère le nanoordinateur micro:bit v2 dans la carte d'extension, en faisant attention au sens.
  2. Connecte la batterie USB à la carte d'extension.
  3. Connecte le module Grove WiFi au port P1 de la carte d'extension.
  4. Assure-toi que la batterie USB est chargée et allumée si disposant d'un bouton.
  5. Allume la carte d'extension si disposant d'un bouton.
    (les DELs sur les micro:bit, carte d'extension et module WiFi doivent s'allumer)
  6. Connecte enfin la micro:bit à la calculatrice, puis allume cette dernière si nécessaire.
  7. Assure-toi que le drone Tello est chargé et allumé. Il va clignoter sous différentes couleurs puis se fixer sur du jaune clignotant lorsque prêt.

Et voilà, paré à décoller, tu peux enfin écrire et lancer ton premier script.




5) Lancement et tutoriel de décollage

Go to top

Dernière chose avant de te laisser voler de tes propres ailes, quand tu lances un script important le module tello, la calculatrice n'est pas capable de détecter la carte d'extension utilisée (Grove ou bitmaker) et va donc te demander de préciser.

Si tu préfères bricoler tes propres branchements, tu disposes également si tu préfères d'un écran de configuration avancé.

Si nécessaire, voici pour résumer tout cela un tuto-vidéo officiel en Anglais:




Téléchargements

Go to top

Décidément Texas Instruments, déjà leader incontesté des projets scientifiques sur calculatrices graphiques, se permet d'innover de façon encore plus formidable. En conséquence pour toi une toute nouvelle dimension à explorer pour des projets encore plus fantastiques ! :bj:

Merci TI ! :favorite:

  • TI-Runtime 2.5.1 pour BBC microbit v2
  • bibliothèque Python complémentaire TELLO

Source : https://resources.t3europe.eu/t3europe- ... 50b9bcfffa

-
Search
-
Social TI-Planet
-
Featured topics
Comparaisons des meilleurs prix pour acheter sa calculatrice !
"1 calculatrice pour tous", le programme solidaire de Texas Instruments. Reçois gratuitement et sans aucune obligation d'achat, 5 calculatrices couleur programmables en Python à donner aux élèves les plus nécessiteux de ton lycée. Tu peux recevoir au choix 5 TI-82 Advanced Edition Python ou bien 5 TI-83 Premium CE Edition Python.
Enseignant(e), reçois gratuitement 1 exemplaire de test de la TI-82 Advanced Edition Python. À demander d'ici le 31 décembre 2024.
Aidez la communauté à documenter les révisions matérielles en listant vos calculatrices graphiques !
1234
-
Donations / Premium
For more contests, prizes, reviews, helping us pay the server and domains...
Donate
Discover the the advantages of a donor account !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partner and ad
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
639 utilisateurs:
>621 invités
>9 membres
>9 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Other interesting websites
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)