π
<-

News 2025
January (14)

News 2024
October (12)
August (9)
July (10)
June (20)
May (14)
April (16)
March (7)
January (20)

News 2023
October (19)
August (14)
July (13)
June (21)
May (29)
April (24)
March (24)
January (24)

News 2022
October (23)
August (14)
July (15)
June (17)
May (31)
April (27)
March (28)
January (34)

News 2021
October (24)
August (37)
July (50)
June (32)
May (48)
April (61)
March (35)
January (34)

News 2020
October (17)
August (43)
July (43)
June (45)
May (60)
April (78)
March (36)
January (39)

News 2019
October (13)
August (18)
July (23)
June (28)
May (31)
April (26)
March (38)
January (37)

News 2018
October (13)
August (32)
July (23)
June (64)
May (63)
April (45)
March (43)
January (45)

News 2017
October (26)
August (39)
July (52)
June (88)
May (51)
April (43)
March (37)
January (33)

News 2016
October (25)
August (42)
July (34)
June (109)
May (55)
April (34)
March (37)
January (24)

News 2015
October (22)
August (56)
July (22)
June (94)
May (56)
April (32)
March (40)
January (21)

News 2014
October (26)
August (18)
July (23)
June (101)
May (57)
April (59)
March (54)
January (31)

News 2013
October (67)
August (50)
July (43)
June (193)
May (93)
April (102)
March (45)
January (50)

News 2012
October (64)
August (63)
July (53)
June (132)
May (88)
April (73)
March (57)
January (58)

News 2011
October (56)
August (31)
July (27)
June (71)
May (61)
April (32)
March (36)
January (24)

News 2010
October (11)
August (8)
July (14)
June (10)
May (3)
April (3)
March (1)

News 2009
August (3)
July (1)
June (2)
May (1)
April (2)
March (1)

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

KhiCAS NumWorks Nspire CX: Python-turtle encore plus parfait

New postby critor » 19 Apr 2022, 11:25

15120Pour accompagner en douceur la transition du Scratch au Python en Seconde, la plupart des solutions Python sur calculatrices graphiques offrent turtle, une bibliothèque permettant du tracé relatif comme en Scratch. On peut citer :
  • la NumWorks dont l'application Python intègre directement turtle
  • les Casio Graph 35+E II et Graph 90+E dont l'application Python intègre directement turtle
  • les TI-Nspire CX II sur lesquelles on peut rajouter la bibliothèque officielle turtle (anciennement ce_turtl) à l'environnement Python
  • les TI-83 Premium CE Edition Python (France), TI-84 Plus CE-T Python Edition (Europe) et TI-84 Plus CE Python (Amérique du Nord), sur lesquelles on peut rajouter une bibliothèque turtle officielle
  • et KhiCAS

11302Aujourd'hui penchons-nous à nouveau sur le turtle de KhiCAS. Conçu par Bernard Parisse, enseignant-chercheur à l'Université de Grenoble, KhiCAS est la déclinaison sur calculatrices du logiciel de Mathématiques intégré Xcas. Disponible pour calculatrices NumWorks N0110, TI-Nspire CX, Casio Graph 35+E II et Graph 90+E, KhiCAS te donne donc accès à une interface unifiée ainsi qu'à des fonctionnalités haut de gamme peu importe la marque ou le modèle de ta calculatrice ! :bj:

12024Ce formidable environnement de Mathématiques et de sciences t'apporte bien des choses. Nous pouvons citer dans tous les cas :
  • la reprise du moteur de calcul formel GIAC développé pour Xcas par le même auteur.
  • la possibilité de programmer dans 2 langages :
    • le langage Xcas historique
    • le langage Xcas avec une couche de compatibilité syntaxique Python

Dans ses éditions pour TI-Nspire CX et NumWorks N0110, KhiCAS apporte pas mal de compléments :
  • possibilité de composer et convertir ses unités
  • une bibliothèque de constantes physiques
  • plusieurs applications elles-même intégrées, dont entre autres :
    • tableur / feuille de calcul
    • tableau périodique des éléments
    • calcul financier
  • 2 langages de programmation supplémentaires :
    • Python via un interpréteur Micropython
    • Javascript via un interpréteur QuickJS

L'environnement Python sur ces modèles est extrêmement riche, bien davantage que les solutions Python intégrées par les constructeurs. On peut citer nombre de bibliothèques :
  • cas et xcas pour appeler le moteur de calcul formel GIAC directement depuis tes scripts Python
  • cmath pour traiter directement tes calculs sur les nombres complexes en Python
  • linalg pour l'algèbre linéaire
  • arit pour l'arithmétique
  • ulab.scipy pour le calcul scientifique
  • ulab.numpy pour le calcul matriciel et vectoriel
  • plusieurs bibliothèque de tracés :
    • turtle pour les tracés relatifs à la Scratch
    • matplotlib pour les tracés dans un repère
    • graphic pour les tracés par pixels, accompagnée de casioplot pour la compatibilité avec les scripts graphiques Casio et kandinsky pour la compatibilité avec les scripts graphiques NumWorks
  • et bien d'autres : gc, math, micropython, nsp, pylab, random, sys, time, ubinascii, ucollections, uctypes, uerrno, uhashlib, uheapq, uio, ujson, ure, ustruct, uzlib

Un fantastique avantage du turtle KhiCAS, exclusif à ce jour, c'est qu'une fois que ton script Python-turtle a terminé de s'exécuter, il t'est possible d'en faire défiler l'affichage avec les flèches du clavier ! :bj:

La dernière mise à jour alpha de KhiCAS améliore encore plus la fiabilité de la bibliothèque turtle. Elle est disponible à ce jour :
  • uniquement en version alpha pour TI-Nspire CX
  • uniquement en version alpha pour NumWorks N0110
Découvrons ensemble les nouveautés.








A) Tests de conformité comparatifs (toutes solutions turtle)

Go to top

Tentons pour le moment un autodiagnostic plus général des différences entres les ancienne et nouvelle bibliothèques turtle de KhiCAS, c'est-à-dire la vérification de tout ce qui peut différer du standard.

Voici des scripts en ce sens, une amélioration majeure de ceux développés dans le code de notre test de rentrée QCC 2021 :
Code: Select all
_turtle_errors = 0

def _turtle_error(k):
  global _turtle_errors
  _turtle_errors |= 1 << k

# import turtle
try:
  import turtle
  if not "forward" in dir(turtle):
    turtle = turtle.Turtle()
except ImportError: #TI-83 Premium CE
  from ce_turtl import turtle
  _turtle_error(0)
try:
  turtle.clear()
except:
  turtle.reset()

# can turtle be patched ?
_fix_turtle = True
try:
  def _fixcolor(c): return c
  turtle._fixcolor = _fixcolor
except:
  _fix_turtle = False

# test color() + pencolor() + fillcolor()
if not "pencolor" in dir(turtle):
  pencolor = turtle.color
  _turtle_error(1)
else:
  pencolor = turtle.pencolor
if not "color" in dir(turtle):
  _turtle_error(2)
if not "fillcolor" in dir(turtle):
  _turtle_error(12)

if not "clear" in dir(turtle):
  _turtle_error(13)
if not "reset" in dir(turtle):
  _turtle_error(14)
if not "heading" in dir(turtle):
  _turtle_error(11)

# test color argument types
_color_types = 0
try:
  pencolor([0, 0, 0])
  _color_types |= 1 << 0
except: _turtle_error(4)
try:
  pencolor((0, 0, 0))
  _color_types |= 1 << 1
except: _turtle_error(5)
try:
  pencolor(0, 0, 0)
  _color_types |= 1 << 2
except: _turtle_error(6)
try:
  pencolor("black")
  _color_types |= 1 << 3
except: _turtle_error(7)

# test colormode()
if not "colormode" in dir(turtle):
  _turtle_error(3)

# test color strings
_colors_fix={
  "blue":(0,0,1),
  "green":(0,1,0),
  "red":(1,0,0),
  "cyan":(0,1,1),
  "yellow":(1,1,0),
  "magenta":(1,0,1),
  "white":(1,1,1),
  "orange":(1,0.65,0),
  "purple":(0.66,0,0.66),
  "brown":(0.75,0.25,0.25),
  "pink":(1,0.75,0.8),
  "grey":(0.66,0.66,0.66),
  "black":(0,0,0),
}
for c in tuple(_colors_fix.keys()):
  try:
    pencolor(c)
    _colors_fix.pop(c)
  except: pass
if len(_colors_fix):
  if _color_types & 1 << 3:
    _turtle_error(8)

# test circle(,)
try: turtle.circle(0,0)
except:
  _turtle_error(9)

#test towards
try: turtle.towards
except:
  _turtle_error(15)

# test for unfixable missing functions
_missing_fct=["write","pensize","dot"]
for f in tuple(_missing_fct):
  try:
    eval("turtle."+f)
    _missing_fct.remove(f)
  except: pass
if len(_missing_fct):
    _turtle_error(16)

_missing_alias=[
  ["backward","back","bk"],
  ["forward","fd"],
  ["right","rt"],
  ["left","lt"],
  ["position","pos"],
  ["goto","setpos","setposition"],
  ["setheading","seth"],
  ["pendown","pd","down"],
  ["penup","pu","up"],
  ["pensize","width"],
  ["showturtle","st"],
  ["hideturtle","ht"],
]
for aliases in tuple(_missing_alias):
  validf = None
  for f in tuple(aliases):
    try:
      eval("turtle."+f)
      validf = f
      aliases.remove(f)
      break
    except: pass
  for f in tuple(aliases):
    try:
      eval("turtle."+f)
      aliases.remove(f)
    except: pass
  if not len(aliases):
    _missing_alias.remove(aliases)
  else:
    aliases.insert(0, validf)
if len(_missing_alias):
    _turtle_error(17)

try:
  turtle.position()
except:
  try:
    turtle.pos()
  except:
    _turtle_error(10)
Code: Select all
from ttl_chk import *
from ttl_chk import _fix_turtle, _turtle_errors, _colors_fix, _missing_fct, _missing_alias

def turtle_diags():
  print("Type: " + str(type(turtle)))
  print("Patchable: " + (_fix_turtle and "yes" or "no"))
  errors_msg = (
    "No <import turtle>",
    "No pencolor()",
    "No color()",
    "No colormode()",
    "No color as list",
    "No color as tuple",
    "No color as args",
    "No color as string",
    "Missing colors strings: ",
    "No circle(,angle)",
    "Can't get position()",
    "No heading()",
    "No fill",
    "No clear()",
    "No reset()",
    "No towards()",
    "Other missing: ",
    "Missing aliases: ",
  )
  errors = 0
  for k in range(len(errors_msg)):
    if _turtle_errors & 1 << k:
      errors += 1
      msg = "Err " + str(k) + ": " + errors_msg[k]
      if k == 8:
        msg += str(len(_colors_fix)) + " " + str(tuple(_colors_fix.keys()))
      if k == 16:
        msg += str(len(_missing_fct)) + " " + " ".join(_missing_fct)
      if k == 17:
        l = []
        for v in _missing_alias:
          l.extend(v[1:])
        msg += str(len(l)) + " " + " ".join(l)
      print(msg)
  print(str(errors) + " error" + ((errors > 1) and "s" or ""))

turtle_diags()


Voici ce que nous racontent les scripts sur les différentes solutions turtle :

TI-83PCE/84+CE
turtle


TI-Nspire CX II
turtle

Casio
Graph 90E


KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl


NumWorks
Casio
Graph 35+E II



Aucune erreur n'est détectée automatiquement autmatiquement par nos scripts avec KhiCAS, chose exceptionnelle si l'on compare aux solutions officielles, et signe d'un soin absolument minutieux ! :bj:

Mais ça, c'est pour les problèmes détectables par des vérifications automatisées. Voyons maintenant d'éventuels écarts visuels sur quelques exemples de scripts.

Afin de pouvoir comparer équitablement avec les solutions officielles visiblement parfois bien moins conformes au standard turtle tout en conservant une unique version de chaque script utilisable sur l'ensemble des solutions, voici un script qu'il suffira d'importer à la place de chaque bibliothèque turtle et qui, lorsque celle-ci sera modifiable, corrigera la plupart des erreurs détectées : :bj:
Code: Select all
from ttl_chk import *
from ttl_chk import _color_types, _turtle_errors, _colors_fix, _missing_fct, _missing_alias

_fix_turtle = True

def nop(*argv): return None
idty = lambda c: c

try: # can turtle be patched ?
  turtle._fixcolorlist = idty
  turtle._fixcolorval = idty
  turtle._fixcolorstring = idty
  turtle._fixcolorargs = idty
  turtle._fixcolor = lambda c: turtle._fixcolorlist(turtle._fixcolorval(turtle._fixcolorstring(turtle._fixcolorargs(c))))
except:
  _fix_turtle = False

if _fix_turtle:

  # fix color() + pencolor()
  if _turtle_errors & 0x1000:
    turtle.fillcolor, turtle.begin_fill, turtle.end_fill = idty, nop, nop
  if _turtle_errors & 2:
    def _pencolor_(*argv):
      if len(argv): turtle.color(argv)
      else: return turtle.color()[0]
    turtle.pencolor = _pencolor_
  if _turtle_errors & 4:
    def _color_(*argv):
      if len(argv) == 2:
        turtle.pencolor(argv[0])
        turtle.fillcolor(argv[1])
      elif len(argv):
        turtle.pencolor(argv)
      else:
        return (turtle.pencolor(), turtle.fillcolor())
    turtle.color = _color_

  _fix_color = _color_types & 0b11 != 0b11 or not "colormode" in dir(turtle)

  # fix list/tuple color argument
  if _color_types & 0b11 == 0b10:
    def _fixcolorlist(c): return type(c) is list and tuple(c) or c
    turtle._fixcolorlist = _fixcolorlist
  if _color_types & 0b11 == 0b01:
    def _fixcolorlist(c): return type(c) is list and list(c) or c
    turtle._fixcolorlist = _fixcolorlist
  if not _color_types & 4:
    def _fixcolorargs(*argv):
      return len(argv) != 1 and argv or argv[0]

  if _fix_color:
    turtle._color = turtle.color
    turtle._pencolor = turtle.pencolor
    turtle._fillcolor = turtle.fillcolor
    if _color_types & 0b11:
      def _color(*argv):
        n = len(argv)
        if not(n): return turtle._color()
        elif n==2: turtle._color(argv[0], argv[1])
        else: turtle._color(n > 1 and argv or argv[0])
      def _pencolor(*argv):
        if not(len(argv)): return turtle._pencolor()
        turtle._pencolor(turtle._fixcolor(len(argv) > 1 and argv or argv[0]))
      def _fillcolor(*argv):
        if not(len(argv)): return turtle._fillcolor()
        turtle._fillcolor(turtle._fixcolor(len(argv) > 1 and argv or argv[0]))
    else:
      def _color(*argv):
        n = len(argv)
        if not(n): return turtle._color()
        c = turtle._fixcolor(n == 3 and argv or argv[0])
        turtle._color(c[0], c[1], c[2])
      def _pencolor(*argv):
        if not(len(argv)): return turtle._pencolor()
        c = turtle._fixcolor(len(argv)>1 and argv or argv[0])
        turtle._pencolor(c[0], c[1], c[2])
      def _fillcolor(*argv):
        if not(len(argv)): return turtle._fillcolor()
        c = turtle._fixcolor(len(argv)>1 and argv or argv[0])
        turtle._fillcolor(c[0], c[1], c[2])
    turtle.color = _color
    turtle.pencolor = _pencolor
    turtle.fillcolor = _fillcolor

  # fix colormode()
  if _turtle_errors & 8:
    # test color mode
    try:
      turtle.pencolor([255, 0, 0])
      _color_mode = 255
    except: _color_mode = 1.0
    turtle._color_mode = _color_mode
    def _colormode(*argv):
      if not(len(argv)): return turtle._color_mode
      if int(argv[0]) in (1, 255):
        turtle._color_mode = int(argv[0]) == 255 and 255 or 1.0
    turtle.colormode = _colormode
    if _color_mode == 255:
      turtle._fixcolorval = lambda c: int(turtle._color_mode) == 1 and type(c) in (list, tuple) and [int(c[k] * 255) for k in range(3)] or c
    else:
      turtle._fixcolorval = lambda c: turtle._color_mode == 255 and type(c) in (list, tuple) and [c[k] / 255 for k in range(3)] or c

  # fix color strings
  if len(_colors_fix):
    def _fixcolorstring(c):
      if type(c) is str and c in _colors_fix:
        c = _colors_fix[c]
        if turtle.colormode() == 255:
          c = [int(c[k] * 255) for k in range(3)]
      return c
    turtle._fixcolorstring = _fixcolorstring

  # fix circle(,)
  if _turtle_errors & 0x200:
    turtle._circle = turtle.circle
    def _circle(r, a=360): turtle._circle(r)
    turtle.circle = _circle

  if len(_missing_fct):
    for f in _missing_fct:
      exec("turtle."+f+"=nop")

  if len(_missing_alias):
    for aliases in _missing_alias:
      validf = aliases[0]
      for f in aliases[1:]:
        exec(validf and "turtle."+f+"=turtle."+validf or "turtle."+f+"=nop")

  # fix clear()
  if _turtle_errors & 0x2000:
    turtle.clear = turtle.reset

  # fix reset()
  if _turtle_errors & 0x4000:
    turtle.reset = turtle.clear

  # fix towards()
  if _turtle_errors & 0x8000:
    from math import atan2, pi
    def _towards(x, y):
      x0, y0 = turtle.pos()
      return atan2(y - y0, x - x0) * 180 / pi
    turtle.towards = _towards




B) 4 exemples comparatifs améliorés

Go to top

Maintenant que nous avons de quoi faire tourner une unique version de chaque script sur l'ensemble des machines, poursuivons donc l'exploration de l'ensemble des solutions turtle avec quelques exemples de script.

Nous allons en profiter pour nous en donner à cœur joie avec les formidables fonctions de remplissage rajoutées dans l'avant-dernière version de KhiCAS, sur le thème de #LesMathématiquesSontBelles.

C'est donc l'occasion de voir si il y avait d'autres problèmes qui n'ont pas pu être détectés automatiquement, et si ils sont toujours présents dans la dernière version.

Plusieurs des exemples qui vont suivre sont inspirés de publications de Bert Wikkerink pour TI-Nspire CX II et très librement et fortement adaptés pour être fonctionnels dans le contexte du heap Python bien plus restreint des TI-83 Premium CE et compatibles.

Commençons par quelques exemples sur lesquels la dernière version de KhiCAS progresse :

Exemple B1 : Le défilé automobile

Go to top

Nous t'emmenons maintenant au défilé avec les logos de plusieurs grands constructeurs... automobiles :
Code: Select all
from ttl_fix import *

def rpoly(c, n):
  for k in range(n):
    turtle.forward(c)
    turtle.left(360 / n)

def audi(r):
  ir = 2 * r // 13
  turtle.penup()
  turtle.left(90)
  turtle.forward(r//2 - 2*ir)
  turtle.right(90)
  turtle.forward(-ir)
  turtle.pendown()
  turtle.pensize(3)
  for i in range(4):
    turtle.penup()
    turtle.forward(3 * ir)
    turtle.pendown()
    turtle.circle(2 * ir)

def mercedez_benz(r):
  ir = r // 2
  turtle.penup()
  turtle.forward(ir)
  turtle.left(90)
  turtle.forward(ir)
  turtle.pendown()
  turtle.pensize(2)
  x, y = turtle.pos()
  turtle.setheading(210)
  for i in range(3):
    turtle.goto(x,y)
    turtle.forward(ir)
    turtle.left(120)
  turtle.setheading(0)
  turtle.circle(-ir)

def citroen(r):
  x,y=turtle.pos()
  turtle.setheading(0)
  turtle.color((255,0,0), (255,0,0))
  turtle.begin_fill()
  rpoly(r, 4)
  turtle.end_fill()
  turtle.fillcolor((255,255,255))
  for i in range(2):
    turtle.setheading(45)
    turtle.begin_fill()
    for k in range(2):
      turtle.forward(.71 * r)
      turtle.left(k and 172 or -90)
    for k in range(2):
      turtle.forward(5 * r / 6)
      turtle.left(106)
    turtle.end_fill()
    y += r / 3
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()

def mitsubichi(r):
  ir = r // 3
  turtle.penup()
  turtle.left(90)
  turtle.forward(ir)
  turtle.right(90)
  turtle.forward(r // 2)
  turtle.pendown()
  for i in range(3):
    turtle.setheading(60 + 120*i)
    turtle.color((255,0,0), (255,0,0))
    turtle.begin_fill()
    for k in range(4):
      turtle.forward(ir)
      turtle.left((k%2) and 120 or 60)
    turtle.end_fill()

def jeep(r):
  a=54
  ir = r/0.47552825814758/4 #sin(radians(a))/cos(radians(a))
  a=ir/0.85
  d=0.93*ir
  turtle.penup()
  turtle.forward(r//2)
  turtle.right(90)
  turtle.forward(ir - r)
  turtle.pendown()
  x, y = turtle.pos()
  turtle.setheading(234)
  turtle.forward(ir)
  turtle.left(126)
  turtle.fillcolor((180,180,180))
  turtle.begin_fill()
  rpoly(a, 5)
  turtle.end_fill()
  for i in range(5):
    col = i < 3 and (0,0,0) or (255,255,255)
    for j in range(2):
      turn =  j and turtle.left or turtle.right
      turtle.goto(x,y)
      turtle.setheading(90 + 72*i)
      turtle.fillcolor(col)
      turtle.begin_fill()
      turtle.forward(d)
      turn(172)
      turtle.forward(0.85*d)
      turn(44)
      turtle.forward(0.2*d)
      turtle.end_fill()
      col = [255 - col[k] for k in range(3)]

turtle.speed(0)
turtle.colormode(255)

r = 92
for iy in range(2):
  for ix in range(3):
    i = iy*3+ix
    if i < 5:
      y, x = (2*iy - 1) * r//2 - 48, (ix - 1)*r - 50
      turtle.penup()
      turtle.goto(x, y)
      turtle.setheading(0)
      turtle.pensize(1)
      turtle.pencolor((0,0,0))
      turtle.pendown()
      (mercedez_benz,jeep,mitsubichi,citroen,audi)[i](r)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Amélioration fantastique, KhiCAS rattrape le gros retard qu'il avait ici par rapport à la concurrence, et trace maintenant correctement les différents logos des constructeurs ! :bj:

Exemple B2 : Les flocons de Koch

Go to top

Encore une fois si tu es dans le Sud de la France, tu n'a pas dû voir de neige depuis des années... Faison donc neiger dans ta calculatrice maintenant, faisons neiger des flocons de Koch :
Code: Select all
from ttl_fix import *

def rotate_list(l):
  l[1:],l[0] = l[0:-1],l[-1]

def koch(n, l):
  if n<=0:
    turtle.forward(l)
  else:
    koch(n - 1, l / 3)
    turtle.left(60)
    koch(n - 1, l / 3)
    turtle.right(120)
    koch(n - 1, l / 3)
    turtle.left(60)
    koch(n - 1, l / 3)

def flock(n, l):
  koch(n, l)
  turtle.right(120)
  koch(n, l)
  turtle.right(120)
  koch(n, l)

turtle.speed(0)
turtle.colormode(255)

c = [127, 255, 0]
l = 80
for j in range(2):
  for i in range(3):
    n = j and 3 + i or 2 - i
    s = 5 - n
    turtle.penup()
    turtle.goto(i*117-157, j*95-25)
    turtle.pencolor(tuple(c))
    turtle.pensize(s)
    turtle.setheading(0)
    turtle.pendown()
    flock(n, l)
    n += 1
    rotate_list(c)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Beau progrès ici aussi, le flocon en haut à droite est enfin tracé de la bonne couleur comme chez la concurrence.

Exemple B3 : La linea

Go to top

Code: Select all
try: #TI-83 Premium CE
  from ti_system import disp_clr
  disp_clr()
except: pass
from ttl_fix import *

def spiral(k,a,l):
  x0, y0 = turtle.pos()
  h0 = turtle.heading()
  while True:
    for s in l:
      turtle.forward(s*k)
      turtle.left(180-a)
    x, y = turtle.pos()
    if abs(x - x0) + abs(y - y0) + abs(turtle.heading() - h0) <= 1:
      break

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(255)
turtle.color((0,0,0),(255,255,0))

try:
  for i in range(-1, 2, 2):
    turtle.penup()
    turtle.goto(80*i - ((i > 0) and 40 or 50), 0)
    turtle.pendown()
    try: turtle.begin_fill()
    except: pass
    spiral((i > 0) and 9 or 30, (i > 0) and 90 or 36, (i > 0) and (1,2,3,4,5,6,7,8,9) or (1,2,3))
    try: turtle.end_fill()
    except: pass
except MemoryError as e: print(e)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Belle amélioration ici aussi, KhiCAS remplit enfin correctement la forme de droite magré sa complexité !

Exemple B4 : Pavage d'une lagogne

Go to top

Partons maintenant à la pêche avec un script très hautement impressionnant par rapport aux contraintes de heap des TI-83 Premium CE et compatibles ; ici nous sommes vraiment sur le fil de la limite des possibilités concernant ces modèles.

Voici donc une lagogne littéralement pavée de poissons :
Code: Select all
from math import sqrt
from ttl_fix import *

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(255)
turtle.pencolor((0,0,0))

a=16

try:
  j = 0
  while -5 < j < 4:
    col = ((0,0,255),(255,0,0),(255,180,0))[j%3]
    i = 0
    while -2 + (j % 2) < i < 2:
      for c in range(3):
        turtle.penup()
        turtle.goto(sqrt(3)*3*a*(i*2-(j%2)), 3*a*j)
        turtle.setheading(-30 + 120*c)
        turtle.pendown()
        turtle.fillcolor(col)
        turtle.begin_fill()
        for k in range(-17, 18):
          l = a*sqrt(7)
          tf = ((1,141.787), (0,l), (1,-100.893), (0,a), (1,120), (0,a/2), [1,-120], [0,-a], [0,a], [1,120], (0,a/2), (1,60), (0,a), (1,-120), (0,a), (1,100.893), (0,l), [1,-40.893])[abs(k)]
          if k==6 or k==9 or k==17: tf[1] -= 180
          elif k==7 or k==8: tf[1] *= -1
          (turtle.forward, turtle.left)[tf[0]](tf[1])
        turtle.end_fill()
        turtle.forward(6*a)
        turtle.backward(5*a)
        turtle.penup()
        turtle.right(90)
        l = a*sqrt(3)/6
        for k in range(2):
          turtle.forward(l)
          turtle.pencolor((255,255,255))
          turtle.dot(a//4)
          turtle.pencolor((0,0,0))
          turtle.dot(a//8)
          turtle.backward(l)
          turtle.left(180)
      i = -i + (i <= 0)
    j = -j - (j >= 0)
except Exception as e: print(e)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Formidable ici aussi, les poissons se comportent enfin correctement sous KhiCAS pour réaliser la pavage !
Petits détails toutefois non spécifiques à cet exemple, lorsque l'on fait défiler le tracé obtenu :
  • les affichages effectués sur la barre de titre/état en haut d'écran (18 premières lignes de pixels) ne sont pas nettoyés correctement lors des rafraichissements
  • les formes ne sont bizarrement pas remplies correctement dans une bande correspondant aux 42 premières lignes de pixels

Exemple B4 : ♫ Le tournesol, le tournesol, ... ♫

Go to top

15452Terminons enfin avec un exemple absolument bluffant de réalisme pour du turtle, nous allons faire pousser un tournesol devant toi :
Code: Select all
from math import pi, sin, cos, sqrt
from ttl_fix import *

def spiral():
  phi = (1+sqrt(5))/2
  a  =0
  r = 0
  dr = 0.15
  turtle.penup()
  for i in range(300):
    turtle.forward(r)
    turtle.pencolor((0,0,0))
    try: turtle.dot(3)
    except: pass
    turtle.pencolor((205,133,63))
    try: turtle.dot(2)
    except: pass
    turtle.goto(0,0)
    turtle.setheading(0)
    a+=360/phi
    turtle.right(a)
    if a>=360:
      r+=dr
      a-=360   

def feuille(core,a):
    try: turtle.begin_fill()
    except: pass
    turtle.right(a/2)
    turtle.forward(core)
    turtle.left(a)
    turtle.forward(core)
    turtle.left(180-a)
    turtle.forward(core)
    turtle.left(a)
    turtle.forward(core)
    try: turtle.end_fill()
    except: pass

turtle.speed(0)
turtle.colormode(255)
turtle.pencolor((30,144,255))
try: turtle.dot(320)
except: pass

d=25
core=40
turtle.pencolor((160,82,45))
try: turtle.dot(40)
except: pass

c=((255,215,0),(255,255,0))

for i in range(2):
  turtle.color(c[0], c[i])
  for h in range(10*i,370,20):
    r=h * pi / 180
    x=d*cos(r)
    y=d*sin(r)
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    turtle.setheading(h)
    feuille(core,32)

spiral()

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Excellent, les graines dans le cœur sont enfin délimitées correctement sous KhiCAS ! :bj:





C) 13 autres exemples comparatifs

Go to top




Exemple C1 : La dalle aux ammonites

Go to top

C'est donc parti pour quelques exemples afin d'approfondir les améliorations de la nouvelle bibliothèque turtle pour TI-83 Premium CE Edition Python et compatibles, ainsi que les points forts et faibles par rapport aux autres modèles de calculatrices.

Précisons que les problèmes récurrents ne seront pas systématiquement réévoqués sur chaque exemple.

Un petit peu au Nord de Digne-les-bains en rive droite de la Bléone se trouve la dalle aux ammonites. Comme il est strictement interdit d'en prélever, voici de quoi en reproduire une sur ta calculatrice :
Code: Select all
from ttl_fix import *
from math import pi

turtle.speed(0)
turtle.pencolor((0,0,0))
turtle.pendown()
turtle.pensize(1)

turtle.goto(0,-8)
x,y = turtle.pos()
turtle.left(115)
for i in range(132):
  turtle.forward(10)
  try:
    h = turtle.towards(x,y)
    turtle.setheading(h)
  except: pass
  d=10*pi
  turtle.forward(d)
  turtle.backward(d)
  turtle.right(90)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C2 : L'escargot de lumière

Go to top

Si tu es dans le Sud de la France tu sais qu'il ne pleut pas souvent (par contre, quand il pleut... il pleut !). Alors voici pour toi un escargot bariolé :
Code: Select all
from math import exp
from ttl_fix import *

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(1.0)

turtle.penup()
turtle.goto(0, -20)
turtle.pendown()
turtle.right(90)
for i in range(20):
  c = [exp(-.5 * ((i - k) / 12)**2) for k in (6, 18, 30)]
  cb = [v/2 for v in c]
  turtle.color(cb, c)
  try: turtle.begin_fill()
  except: pass
  turtle.circle(27 + i)
  try: turtle.end_fill()
  except: pass
  turtle.right(10)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C3 : Le triangle de Penrose

Go to top

Tu n'as jamais touché à un triangle de Penrose ? Et bien voici de quoi en afficher le plan dans ta calculatrice, tu n'auras plus qu'à l'imprimer en 3D, si tu arrives à comprendre où est le devant et l'arrière : ;)
Code: Select all
from math import sqrt
from ttl_fix import *

def hook(a, c):
  turtle.penup()
  turtle.goto(0,-15)
  turtle.setheading(a)
  turtle.forward((l - 4*b) / sqrt(3))
  turtle.right(150)
  turtle.pendown()
  lf = ((turtle.left, 60),[turtle.forward,b],(turtle.left,120),(turtle.forward,l-b),[turtle.right,120],[turtle.forward,l-3*b])
  try:
    turtle.fillcolor(c)
    turtle.begin_fill()
  except: pass
  for k in range(-len(lf) + 1, len(lf)):
    tf = lf[abs(k)]
    if k == 1: tf[1] = l
    elif k == 4: tf[0] = turtle.left
    elif k == 5: tf[1] = b
    tf[0](tf[1])
  try: turtle.end_fill()
  except: pass
 
turtle.speed(0)
turtle.pensize(2)
turtle.colormode(255)

l=180
b=23

for i in range(112):
  turtle.pencolor(232 - int(i * 23 / 11), 249 - int(i * 29 / 55), 255)
  turtle.penup()
  turtle.goto(-192, 111 - 2*i)
  turtle.pendown()
  turtle.forward(384)

turtle.pencolor((0,0,0))
turtle.pensize(1)

hook(330, (255,255,0))
hook(90, (0,0,255))
hook(210, (255,0,0))

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C4 : La courtepointe de Mamie

Go to top

Voici maintenant la courtepointe brodée avec amour et soin par Mamie :
Code: Select all
from ttl_fix import *

def rotate_list(l):
  l[1:],l[0] = l[0:-1],l[-1]

def poly_reg_a(l, a):
  h0 = turtle.heading()
  while True:
    turtle.forward(l)
    turtle.left(a)
    if abs(h0 - turtle.heading()) < .1:
      break

turtle.hideturtle()
turtle.speed(0)
turtle.pensize(1)
turtle.colormode(255)

c = [191, 127, 0]
cf = [127, 255, 0]
i = 0
while i > -3:
  j = 0
  while j > -2:
    turtle.penup()
    turtle.goto((i - 1)*88, (j - 1)*85 + 28)
    turtle.pendown()
    turtle.color(c, cf)
    try: turtle.begin_fill()
    except: pass
    poly_reg_a(80, 140)
    try: turtle.end_fill()
    except: pass
    rotate_list(c)
    rotate_list(cf)
    j = -j + (j <= 0)
  i = -i + (i <= 0)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C5 : Les vitraux rhombiques

Go to top

Voici maintenant une belle rosace rhombique pour décorer le bâtiment de ton choix.

Nous utilisons ici la méthode .dot() permettant de remplir un disque de diamètre donné, afin de générer de quoi avoir une couleur de fond d'écran sur nos calculatrices, suffit-il juste de lui spécifier un diamètre suffisamment grand :
Code: Select all
from ttl_fix import *

turtle.speed(0)
turtle.colormode(255)
turtle.pencolor((0,0,255))
turtle.dot(320)
turtle.pencolor((0,0,0))
turtle.pensize(2)
col = ((255,0,0),(255,255,0),(0,255,0),(255,255,255),(255,0,255))
a=60

for i in range(10):
  c = col[i%5]
  turtle.color(c, c)
  turtle.begin_fill()
  for j in range(5):
    turtle.forward(a)
    turtle.right(72)
  turtle.end_fill()
  turtle.right(36)

for i in range(10):
  c = [v//3 for v in col[i%5]]
  turtle.pencolor(c)
  for j in range(5):
    turtle.forward(a)
    turtle.right(72)
  turtle.right(36)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Par rapport au fond bleu, notons que c'est bel et bien KhiCAS qui adopte le comportement correct. Selon le standard turtle, la méthode .dot() attend en paramètre le diamètre du disque à tracer. Ce sont les modèles Texas Instruments qui le considèrent à tort comme un rayon et remplissent alors tout l'écran.

Exemple C6 : Les roses par 12

Go to top

Voici maintenant une rose, cette fois-ci sur un fond d'écran en dégradé radial. Nous utiliserons pour cela cette fois-ci une boucle de .dot() :
Code: Select all
from math import pi, sin, cos, sqrt
from ttl_fix import *

def rpoly(c, n):
  a=360/n
  for k in range(n):
    turtle.forward(c)
    turtle.left(a)
def carre(c): rpoly(c, 4)

turtle.speed(0)
turtle.colormode(255)
turtle.penup()

r=80
alpha=(15 * pi / 180)

for i in range(320):
  c=int(255/320*i)
  turtle.pencolor(c,c,c)
  try: turtle.dot(320-i)
  except: pass

turtle.goto(20,-76)
turtle.color((255,255,255),(0,0,0))

for i in range(4):
  a=r*sin(alpha)*2
  d=a/sqrt(2)
  turtle.pendown()
  for i in range(12):
    turtle.right(15)
    try: turtle.begin_fill()
    except: pass
    carre(d)
    try: turtle.end_fill()
    except: pass
    turtle.left(45)
    turtle.penup()
    turtle.forward(a)
    turtle.pendown()
  turtle.penup()
  turtle.left(75)
  turtle.forward(d)
  turtle.right(60)
  r=r*cos(alpha)-a/2

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Sur la taille du disque de fond d'écran et comme déjà dit, c'est ici encore KhiCAS qui fait comme il faut.

Exemple C7 : Les triangles de Sierpiński

Go to top

Revenons aux fractales et à la récursivité avec les triangles de Sierpiński. As-tu déjà réussi à les compter ? Et bien voici de quoi commencer sur ta calculatrice :
Code: Select all
from ttl_fix import *

def sierp(n, l):
  if n == 0:
    for i in range (0, 3):
      turtle.forward(l)
      turtle.left(120)
  if n > 0:
    sierp(n - 1, l / 2)
    turtle.forward(l / 2)
    sierp(n - 1, l / 2)
    turtle.backward(l / 2)
    turtle.left(60)
    turtle.forward(l / 2)
    turtle.right(60)
    sierp(n - 1, l / 2)
    turtle.left(60)
    turtle.backward(l / 2)
    turtle.right(60)

turtle.colormode(255)
turtle.speed(0)
turtle.pensize(1)

turtle.penup()
turtle.goto(-110, -95)
turtle.pendown()
turtle.pencolor((255,0,0))
sierp(6, 220)
turtle.penup()
turtle.forward(400)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C8 : Sous le soleil exactement

Go to top

Plaçons-nous maintenant sous le soleil exactement, profitant ainsi de toutes les couleurs de la lumière blanche :
Code: Select all
from math import exp
from ttl_fix import *

def rpoly(c, n):
  a=360/n
  for k in range(n):
    turtle.forward(c)
    turtle.left(a)
def carre(c): rpoly(c, 4)

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(1.0)

n = 36
for i in range(n):
  k=.4 + 4*i/255
  cp = [.7*exp(-.5 * ((n - i - k) / (n / 3))**2) for k in (6, 18, 30)]
  turtle.pencolor(cp)
  try:
    turtle.fillcolor((k,k,0))
    turtle.begin_fill()
  except: pass
  carre(60)
  try: turtle.end_fill()
  except: pass
  turtle.right(360 / n)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C9 : Le labyrinthe du Minotaure

Go to top

Explorons maintenant dans la labyrinthe du Minotaure :
Code: Select all
from ttl_fix import *

turtle.speed(0)
turtle.colormode(255)
turtle.pendown()

turtle.right(48)
turtle.pencolor((0,0,0))
for i in range(98):
  turtle.forward(2*i)
  turtle.left(90.5)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C10 : Le carreau de carreaux

Go to top

Code: Select all
from math import sqrt
from ttl_fix import *

def rotate_list(l):
  l[1:],l[0] = l[0:-1],l[-1]

def reg_poly(l, n):
  for i in range(n):
    turtle.forward(l)
    turtle.left(360/n)

def square(l):
  reg_poly(l, 4)

turtle.colormode(255)
turtle.pencolor(0,0,0)
turtle.speed(0)

turtle.pensize(3)
d=190
c=[0,255,127]
turtle.penup()
turtle.goto(-d/2,-d/2)
turtle.setheading(0)
turtle.pendown()
for i in range(8):
  try:
    turtle.fillcolor(tuple(c))
    turtle.begin_fill()
  except: pass
  square(d)
  try:
    turtle.end_fill()
  except: pass
  turtle.penup()
  turtle.forward(d/2)
  turtle.left(45)
  turtle.pendown()
  d/=sqrt(2)
  rotate_list(c)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C11 : Les étoiles jumelles

Go to top

Code: Select all
try: # TI-83 Premium CE
  from ti_system import disp_clr
  disp_clr()
except: pass
from ttl_fix import *

def rpoly(c, n):
  a=360/n
  for k in range(n):
    turtle.forward(c)
    turtle.left(a)

def rosace(c, n1, a, n2):
  try: turtle.begin_fill()
  except: pass
  for i in range(n2):
    turtle.left(a)
    rpoly(c, n1)
  try: turtle.end_fill()
  except: pass

turtle.colormode(255)
turtle.pencolor((0,0,0))

try: turtle.dot(320)
except: pass
turtle.color((255,255,255),(255,255,0))
turtle.speed(0)
turtle.pensize(1)
try:
  for i in range(-1, 2, 2):
    turtle.penup()
    turtle.goto(80*i, 0)
    turtle.pendown()
    rosace((i > 0) and 21 or 30, (i > 0) and 12 or 8, 30, 12)
    turtle.pensize(2)
    turtle.pencolor((0,0,255))
except MemoryError as e: print(e)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Sur la taille du disque de fond d'écran, c'est à nouveau ici KhiCAS qui a raison et pas TI.

Exemple C12 : La toile de l'araignée

Go to top

Suivons maintenant le fil de l'araignée :
Code: Select all
from ttl_fix import *

def spiral(a,b):
  turtle.pencolor((0,0,0))
  try: turtle.dot(320)
  except: pass
  turtle.pencolor((255,255,0))
  for i in range(189):
    for j in range(6):
      turtle.forward(i/a)
      turtle.left(23)
    turtle.left(b)
    try: turtle.dot(2)
    except: pass
   
turtle.speed(0)
turtle.colormode(255)
turtle.pensize(1)

a=17
b=194

spiral(a,b)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II





Conclusion

Go to top

Selon notre outil de tests, KhiCAS pour TI-Nspire CX et NumWorks N0110 est bien mieux conforme au standard Python-turtle que l'ensemble des solutions turtle officielles, et semble en conséquence bien mieux se comporter en pratique sur une majorité de nos exemples. nous semble offrir à ce jour la meilleure bibliothèque Python turtle toutes solutions confondues.

Les méthodes de remplissage, absentes des implémentations officielles de Casio et NumWorks t'ouvrent la porte à de formidables progrès.

Les progrès témoignent d'un soin minutieux apporté par Bernard Parisse, et vu que tout semble parfait maintenant il va nous falloir tenter d'inventer de nouveaux exemples piégeux... :P




Téléchargements

Go to top


KhiCAS NumWorks Nspire CX: Python-turtle encore plus parfait

New postby critor » 19 Apr 2022, 11:25

15120Pour accompagner en douceur la transition du Scratch au Python en Seconde, la plupart des solutions Python sur calculatrices graphiques offrent turtle, une bibliothèque permettant du tracé relatif comme en Scratch. On peut citer :
  • la NumWorks dont l'application Python intègre directement turtle
  • les Casio Graph 35+E II et Graph 90+E dont l'application Python intègre directement turtle
  • les TI-Nspire CX II sur lesquelles on peut rajouter la bibliothèque officielle turtle (anciennement ce_turtl) à l'environnement Python
  • les TI-83 Premium CE Edition Python (France), TI-84 Plus CE-T Python Edition (Europe) et TI-84 Plus CE Python (Amérique du Nord), sur lesquelles on peut rajouter une bibliothèque turtle officielle
  • et KhiCAS

11302Aujourd'hui penchons-nous à nouveau sur le turtle de KhiCAS. Conçu par Bernard Parisse, enseignant-chercheur à l'Université de Grenoble, KhiCAS est la déclinaison sur calculatrices du logiciel de Mathématiques intégré Xcas. Disponible pour calculatrices NumWorks N0110, TI-Nspire CX, Casio Graph 35+E II et Graph 90+E, KhiCAS te donne donc accès à une interface unifiée ainsi qu'à des fonctionnalités haut de gamme peu importe la marque ou le modèle de ta calculatrice ! :bj:

12024Ce formidable environnement de Mathématiques et de sciences t'apporte bien des choses. Nous pouvons citer dans tous les cas :
  • la reprise du moteur de calcul formel GIAC développé pour Xcas par le même auteur.
  • la possibilité de programmer dans 2 langages :
    • le langage Xcas historique
    • le langage Xcas avec une couche de compatibilité syntaxique Python

Dans ses éditions pour TI-Nspire CX et NumWorks N0110, KhiCAS apporte pas mal de compléments :
  • possibilité de composer et convertir ses unités
  • une bibliothèque de constantes physiques
  • plusieurs applications elles-même intégrées, dont entre autres :
    • tableur / feuille de calcul
    • tableau périodique des éléments
    • calcul financier
  • 2 langages de programmation supplémentaires :
    • Python via un interpréteur Micropython
    • Javascript via un interpréteur QuickJS

L'environnement Python sur ces modèles est extrêmement riche, bien davantage que les solutions Python intégrées par les constructeurs. On peut citer nombre de bibliothèques :
  • cas et xcas pour appeler le moteur de calcul formel GIAC directement depuis tes scripts Python
  • cmath pour traiter directement tes calculs sur les nombres complexes en Python
  • linalg pour l'algèbre linéaire
  • arit pour l'arithmétique
  • ulab.scipy pour le calcul scientifique
  • ulab.numpy pour le calcul matriciel et vectoriel
  • plusieurs bibliothèque de tracés :
    • turtle pour les tracés relatifs à la Scratch
    • matplotlib pour les tracés dans un repère
    • graphic pour les tracés par pixels, accompagnée de casioplot pour la compatibilité avec les scripts graphiques Casio et kandinsky pour la compatibilité avec les scripts graphiques NumWorks
  • et bien d'autres : gc, math, micropython, nsp, pylab, random, sys, time, ubinascii, ucollections, uctypes, uerrno, uhashlib, uheapq, uio, ujson, ure, ustruct, uzlib

Un fantastique avantage du turtle KhiCAS, exclusif à ce jour, c'est qu'une fois que ton script Python-turtle a terminé de s'exécuter, il t'est possible d'en faire défiler l'affichage avec les flèches du clavier ! :bj:

La dernière mise à jour alpha de KhiCAS améliore encore plus la fiabilité de la bibliothèque turtle. Elle est disponible à ce jour :
  • uniquement en version alpha pour TI-Nspire CX
  • uniquement en version alpha pour NumWorks N0110
Découvrons ensemble les nouveautés.








A) Tests de conformité comparatifs (toutes solutions turtle)

Go to top

Tentons pour le moment un autodiagnostic plus général des différences entres les ancienne et nouvelle bibliothèques turtle de KhiCAS, c'est-à-dire la vérification de tout ce qui peut différer du standard.

Voici des scripts en ce sens, une amélioration majeure de ceux développés dans le code de notre test de rentrée QCC 2021 :
Code: Select all
_turtle_errors = 0

def _turtle_error(k):
  global _turtle_errors
  _turtle_errors |= 1 << k

# import turtle
try:
  import turtle
  if not "forward" in dir(turtle):
    turtle = turtle.Turtle()
except ImportError: #TI-83 Premium CE
  from ce_turtl import turtle
  _turtle_error(0)
try:
  turtle.clear()
except:
  turtle.reset()

# can turtle be patched ?
_fix_turtle = True
try:
  def _fixcolor(c): return c
  turtle._fixcolor = _fixcolor
except:
  _fix_turtle = False

# test color() + pencolor() + fillcolor()
if not "pencolor" in dir(turtle):
  pencolor = turtle.color
  _turtle_error(1)
else:
  pencolor = turtle.pencolor
if not "color" in dir(turtle):
  _turtle_error(2)
if not "fillcolor" in dir(turtle):
  _turtle_error(12)

if not "clear" in dir(turtle):
  _turtle_error(13)
if not "reset" in dir(turtle):
  _turtle_error(14)
if not "heading" in dir(turtle):
  _turtle_error(11)

# test color argument types
_color_types = 0
try:
  pencolor([0, 0, 0])
  _color_types |= 1 << 0
except: _turtle_error(4)
try:
  pencolor((0, 0, 0))
  _color_types |= 1 << 1
except: _turtle_error(5)
try:
  pencolor(0, 0, 0)
  _color_types |= 1 << 2
except: _turtle_error(6)
try:
  pencolor("black")
  _color_types |= 1 << 3
except: _turtle_error(7)

# test colormode()
if not "colormode" in dir(turtle):
  _turtle_error(3)

# test color strings
_colors_fix={
  "blue":(0,0,1),
  "green":(0,1,0),
  "red":(1,0,0),
  "cyan":(0,1,1),
  "yellow":(1,1,0),
  "magenta":(1,0,1),
  "white":(1,1,1),
  "orange":(1,0.65,0),
  "purple":(0.66,0,0.66),
  "brown":(0.75,0.25,0.25),
  "pink":(1,0.75,0.8),
  "grey":(0.66,0.66,0.66),
  "black":(0,0,0),
}
for c in tuple(_colors_fix.keys()):
  try:
    pencolor(c)
    _colors_fix.pop(c)
  except: pass
if len(_colors_fix):
  if _color_types & 1 << 3:
    _turtle_error(8)

# test circle(,)
try: turtle.circle(0,0)
except:
  _turtle_error(9)

#test towards
try: turtle.towards
except:
  _turtle_error(15)

# test for unfixable missing functions
_missing_fct=["write","pensize","dot"]
for f in tuple(_missing_fct):
  try:
    eval("turtle."+f)
    _missing_fct.remove(f)
  except: pass
if len(_missing_fct):
    _turtle_error(16)

_missing_alias=[
  ["backward","back","bk"],
  ["forward","fd"],
  ["right","rt"],
  ["left","lt"],
  ["position","pos"],
  ["goto","setpos","setposition"],
  ["setheading","seth"],
  ["pendown","pd","down"],
  ["penup","pu","up"],
  ["pensize","width"],
  ["showturtle","st"],
  ["hideturtle","ht"],
]
for aliases in tuple(_missing_alias):
  validf = None
  for f in tuple(aliases):
    try:
      eval("turtle."+f)
      validf = f
      aliases.remove(f)
      break
    except: pass
  for f in tuple(aliases):
    try:
      eval("turtle."+f)
      aliases.remove(f)
    except: pass
  if not len(aliases):
    _missing_alias.remove(aliases)
  else:
    aliases.insert(0, validf)
if len(_missing_alias):
    _turtle_error(17)

try:
  turtle.position()
except:
  try:
    turtle.pos()
  except:
    _turtle_error(10)
Code: Select all
from ttl_chk import *
from ttl_chk import _fix_turtle, _turtle_errors, _colors_fix, _missing_fct, _missing_alias

def turtle_diags():
  print("Type: " + str(type(turtle)))
  print("Patchable: " + (_fix_turtle and "yes" or "no"))
  errors_msg = (
    "No <import turtle>",
    "No pencolor()",
    "No color()",
    "No colormode()",
    "No color as list",
    "No color as tuple",
    "No color as args",
    "No color as string",
    "Missing colors strings: ",
    "No circle(,angle)",
    "Can't get position()",
    "No heading()",
    "No fill",
    "No clear()",
    "No reset()",
    "No towards()",
    "Other missing: ",
    "Missing aliases: ",
  )
  errors = 0
  for k in range(len(errors_msg)):
    if _turtle_errors & 1 << k:
      errors += 1
      msg = "Err " + str(k) + ": " + errors_msg[k]
      if k == 8:
        msg += str(len(_colors_fix)) + " " + str(tuple(_colors_fix.keys()))
      if k == 16:
        msg += str(len(_missing_fct)) + " " + " ".join(_missing_fct)
      if k == 17:
        l = []
        for v in _missing_alias:
          l.extend(v[1:])
        msg += str(len(l)) + " " + " ".join(l)
      print(msg)
  print(str(errors) + " error" + ((errors > 1) and "s" or ""))

turtle_diags()


Voici ce que nous racontent les scripts sur les différentes solutions turtle :

TI-83PCE/84+CE
turtle


TI-Nspire CX II
turtle

Casio
Graph 90E


KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl


NumWorks
Casio
Graph 35+E II



Aucune erreur n'est détectée automatiquement autmatiquement par nos scripts avec KhiCAS, chose exceptionnelle si l'on compare aux solutions officielles, et signe d'un soin absolument minutieux ! :bj:

Mais ça, c'est pour les problèmes détectables par des vérifications automatisées. Voyons maintenant d'éventuels écarts visuels sur quelques exemples de scripts.

Afin de pouvoir comparer équitablement avec les solutions officielles visiblement parfois bien moins conformes au standard turtle tout en conservant une unique version de chaque script utilisable sur l'ensemble des solutions, voici un script qu'il suffira d'importer à la place de chaque bibliothèque turtle et qui, lorsque celle-ci sera modifiable, corrigera la plupart des erreurs détectées : :bj:
Code: Select all
from ttl_chk import *
from ttl_chk import _color_types, _turtle_errors, _colors_fix, _missing_fct, _missing_alias

_fix_turtle = True

def nop(*argv): return None
idty = lambda c: c

try: # can turtle be patched ?
  turtle._fixcolorlist = idty
  turtle._fixcolorval = idty
  turtle._fixcolorstring = idty
  turtle._fixcolorargs = idty
  turtle._fixcolor = lambda c: turtle._fixcolorlist(turtle._fixcolorval(turtle._fixcolorstring(turtle._fixcolorargs(c))))
except:
  _fix_turtle = False

if _fix_turtle:

  # fix color() + pencolor()
  if _turtle_errors & 0x1000:
    turtle.fillcolor, turtle.begin_fill, turtle.end_fill = idty, nop, nop
  if _turtle_errors & 2:
    def _pencolor_(*argv):
      if len(argv): turtle.color(argv)
      else: return turtle.color()[0]
    turtle.pencolor = _pencolor_
  if _turtle_errors & 4:
    def _color_(*argv):
      if len(argv) == 2:
        turtle.pencolor(argv[0])
        turtle.fillcolor(argv[1])
      elif len(argv):
        turtle.pencolor(argv)
      else:
        return (turtle.pencolor(), turtle.fillcolor())
    turtle.color = _color_

  _fix_color = _color_types & 0b11 != 0b11 or not "colormode" in dir(turtle)

  # fix list/tuple color argument
  if _color_types & 0b11 == 0b10:
    def _fixcolorlist(c): return type(c) is list and tuple(c) or c
    turtle._fixcolorlist = _fixcolorlist
  if _color_types & 0b11 == 0b01:
    def _fixcolorlist(c): return type(c) is list and list(c) or c
    turtle._fixcolorlist = _fixcolorlist
  if not _color_types & 4:
    def _fixcolorargs(*argv):
      return len(argv) != 1 and argv or argv[0]

  if _fix_color:
    turtle._color = turtle.color
    turtle._pencolor = turtle.pencolor
    turtle._fillcolor = turtle.fillcolor
    if _color_types & 0b11:
      def _color(*argv):
        n = len(argv)
        if not(n): return turtle._color()
        elif n==2: turtle._color(argv[0], argv[1])
        else: turtle._color(n > 1 and argv or argv[0])
      def _pencolor(*argv):
        if not(len(argv)): return turtle._pencolor()
        turtle._pencolor(turtle._fixcolor(len(argv) > 1 and argv or argv[0]))
      def _fillcolor(*argv):
        if not(len(argv)): return turtle._fillcolor()
        turtle._fillcolor(turtle._fixcolor(len(argv) > 1 and argv or argv[0]))
    else:
      def _color(*argv):
        n = len(argv)
        if not(n): return turtle._color()
        c = turtle._fixcolor(n == 3 and argv or argv[0])
        turtle._color(c[0], c[1], c[2])
      def _pencolor(*argv):
        if not(len(argv)): return turtle._pencolor()
        c = turtle._fixcolor(len(argv)>1 and argv or argv[0])
        turtle._pencolor(c[0], c[1], c[2])
      def _fillcolor(*argv):
        if not(len(argv)): return turtle._fillcolor()
        c = turtle._fixcolor(len(argv)>1 and argv or argv[0])
        turtle._fillcolor(c[0], c[1], c[2])
    turtle.color = _color
    turtle.pencolor = _pencolor
    turtle.fillcolor = _fillcolor

  # fix colormode()
  if _turtle_errors & 8:
    # test color mode
    try:
      turtle.pencolor([255, 0, 0])
      _color_mode = 255
    except: _color_mode = 1.0
    turtle._color_mode = _color_mode
    def _colormode(*argv):
      if not(len(argv)): return turtle._color_mode
      if int(argv[0]) in (1, 255):
        turtle._color_mode = int(argv[0]) == 255 and 255 or 1.0
    turtle.colormode = _colormode
    if _color_mode == 255:
      turtle._fixcolorval = lambda c: int(turtle._color_mode) == 1 and type(c) in (list, tuple) and [int(c[k] * 255) for k in range(3)] or c
    else:
      turtle._fixcolorval = lambda c: turtle._color_mode == 255 and type(c) in (list, tuple) and [c[k] / 255 for k in range(3)] or c

  # fix color strings
  if len(_colors_fix):
    def _fixcolorstring(c):
      if type(c) is str and c in _colors_fix:
        c = _colors_fix[c]
        if turtle.colormode() == 255:
          c = [int(c[k] * 255) for k in range(3)]
      return c
    turtle._fixcolorstring = _fixcolorstring

  # fix circle(,)
  if _turtle_errors & 0x200:
    turtle._circle = turtle.circle
    def _circle(r, a=360): turtle._circle(r)
    turtle.circle = _circle

  if len(_missing_fct):
    for f in _missing_fct:
      exec("turtle."+f+"=nop")

  if len(_missing_alias):
    for aliases in _missing_alias:
      validf = aliases[0]
      for f in aliases[1:]:
        exec(validf and "turtle."+f+"=turtle."+validf or "turtle."+f+"=nop")

  # fix clear()
  if _turtle_errors & 0x2000:
    turtle.clear = turtle.reset

  # fix reset()
  if _turtle_errors & 0x4000:
    turtle.reset = turtle.clear

  # fix towards()
  if _turtle_errors & 0x8000:
    from math import atan2, pi
    def _towards(x, y):
      x0, y0 = turtle.pos()
      return atan2(y - y0, x - x0) * 180 / pi
    turtle.towards = _towards




B) 4 exemples comparatifs améliorés

Go to top

Maintenant que nous avons de quoi faire tourner une unique version de chaque script sur l'ensemble des machines, poursuivons donc l'exploration de l'ensemble des solutions turtle avec quelques exemples de script.

Nous allons en profiter pour nous en donner à cœur joie avec les formidables fonctions de remplissage rajoutées dans l'avant-dernière version de KhiCAS, sur le thème de #LesMathématiquesSontBelles.

C'est donc l'occasion de voir si il y avait d'autres problèmes qui n'ont pas pu être détectés automatiquement, et si ils sont toujours présents dans la dernière version.

Plusieurs des exemples qui vont suivre sont inspirés de publications de Bert Wikkerink pour TI-Nspire CX II et très librement et fortement adaptés pour être fonctionnels dans le contexte du heap Python bien plus restreint des TI-83 Premium CE et compatibles.

Commençons par quelques exemples sur lesquels la dernière version de KhiCAS progresse :

Exemple B1 : Le défilé automobile

Go to top

Nous t'emmenons maintenant au défilé avec les logos de plusieurs grands constructeurs... automobiles :
Code: Select all
from ttl_fix import *

def rpoly(c, n):
  for k in range(n):
    turtle.forward(c)
    turtle.left(360 / n)

def audi(r):
  ir = 2 * r // 13
  turtle.penup()
  turtle.left(90)
  turtle.forward(r//2 - 2*ir)
  turtle.right(90)
  turtle.forward(-ir)
  turtle.pendown()
  turtle.pensize(3)
  for i in range(4):
    turtle.penup()
    turtle.forward(3 * ir)
    turtle.pendown()
    turtle.circle(2 * ir)

def mercedez_benz(r):
  ir = r // 2
  turtle.penup()
  turtle.forward(ir)
  turtle.left(90)
  turtle.forward(ir)
  turtle.pendown()
  turtle.pensize(2)
  x, y = turtle.pos()
  turtle.setheading(210)
  for i in range(3):
    turtle.goto(x,y)
    turtle.forward(ir)
    turtle.left(120)
  turtle.setheading(0)
  turtle.circle(-ir)

def citroen(r):
  x,y=turtle.pos()
  turtle.setheading(0)
  turtle.color((255,0,0), (255,0,0))
  turtle.begin_fill()
  rpoly(r, 4)
  turtle.end_fill()
  turtle.fillcolor((255,255,255))
  for i in range(2):
    turtle.setheading(45)
    turtle.begin_fill()
    for k in range(2):
      turtle.forward(.71 * r)
      turtle.left(k and 172 or -90)
    for k in range(2):
      turtle.forward(5 * r / 6)
      turtle.left(106)
    turtle.end_fill()
    y += r / 3
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()

def mitsubichi(r):
  ir = r // 3
  turtle.penup()
  turtle.left(90)
  turtle.forward(ir)
  turtle.right(90)
  turtle.forward(r // 2)
  turtle.pendown()
  for i in range(3):
    turtle.setheading(60 + 120*i)
    turtle.color((255,0,0), (255,0,0))
    turtle.begin_fill()
    for k in range(4):
      turtle.forward(ir)
      turtle.left((k%2) and 120 or 60)
    turtle.end_fill()

def jeep(r):
  a=54
  ir = r/0.47552825814758/4 #sin(radians(a))/cos(radians(a))
  a=ir/0.85
  d=0.93*ir
  turtle.penup()
  turtle.forward(r//2)
  turtle.right(90)
  turtle.forward(ir - r)
  turtle.pendown()
  x, y = turtle.pos()
  turtle.setheading(234)
  turtle.forward(ir)
  turtle.left(126)
  turtle.fillcolor((180,180,180))
  turtle.begin_fill()
  rpoly(a, 5)
  turtle.end_fill()
  for i in range(5):
    col = i < 3 and (0,0,0) or (255,255,255)
    for j in range(2):
      turn =  j and turtle.left or turtle.right
      turtle.goto(x,y)
      turtle.setheading(90 + 72*i)
      turtle.fillcolor(col)
      turtle.begin_fill()
      turtle.forward(d)
      turn(172)
      turtle.forward(0.85*d)
      turn(44)
      turtle.forward(0.2*d)
      turtle.end_fill()
      col = [255 - col[k] for k in range(3)]

turtle.speed(0)
turtle.colormode(255)

r = 92
for iy in range(2):
  for ix in range(3):
    i = iy*3+ix
    if i < 5:
      y, x = (2*iy - 1) * r//2 - 48, (ix - 1)*r - 50
      turtle.penup()
      turtle.goto(x, y)
      turtle.setheading(0)
      turtle.pensize(1)
      turtle.pencolor((0,0,0))
      turtle.pendown()
      (mercedez_benz,jeep,mitsubichi,citroen,audi)[i](r)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Amélioration fantastique, KhiCAS rattrape le gros retard qu'il avait ici par rapport à la concurrence, et trace maintenant correctement les différents logos des constructeurs ! :bj:

Exemple B2 : Les flocons de Koch

Go to top

Encore une fois si tu es dans le Sud de la France, tu n'a pas dû voir de neige depuis des années... Faison donc neiger dans ta calculatrice maintenant, faisons neiger des flocons de Koch :
Code: Select all
from ttl_fix import *

def rotate_list(l):
  l[1:],l[0] = l[0:-1],l[-1]

def koch(n, l):
  if n<=0:
    turtle.forward(l)
  else:
    koch(n - 1, l / 3)
    turtle.left(60)
    koch(n - 1, l / 3)
    turtle.right(120)
    koch(n - 1, l / 3)
    turtle.left(60)
    koch(n - 1, l / 3)

def flock(n, l):
  koch(n, l)
  turtle.right(120)
  koch(n, l)
  turtle.right(120)
  koch(n, l)

turtle.speed(0)
turtle.colormode(255)

c = [127, 255, 0]
l = 80
for j in range(2):
  for i in range(3):
    n = j and 3 + i or 2 - i
    s = 5 - n
    turtle.penup()
    turtle.goto(i*117-157, j*95-25)
    turtle.pencolor(tuple(c))
    turtle.pensize(s)
    turtle.setheading(0)
    turtle.pendown()
    flock(n, l)
    n += 1
    rotate_list(c)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Beau progrès ici aussi, le flocon en haut à droite est enfin tracé de la bonne couleur comme chez la concurrence.

Exemple B3 : La linea

Go to top

Code: Select all
try: #TI-83 Premium CE
  from ti_system import disp_clr
  disp_clr()
except: pass
from ttl_fix import *

def spiral(k,a,l):
  x0, y0 = turtle.pos()
  h0 = turtle.heading()
  while True:
    for s in l:
      turtle.forward(s*k)
      turtle.left(180-a)
    x, y = turtle.pos()
    if abs(x - x0) + abs(y - y0) + abs(turtle.heading() - h0) <= 1:
      break

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(255)
turtle.color((0,0,0),(255,255,0))

try:
  for i in range(-1, 2, 2):
    turtle.penup()
    turtle.goto(80*i - ((i > 0) and 40 or 50), 0)
    turtle.pendown()
    try: turtle.begin_fill()
    except: pass
    spiral((i > 0) and 9 or 30, (i > 0) and 90 or 36, (i > 0) and (1,2,3,4,5,6,7,8,9) or (1,2,3))
    try: turtle.end_fill()
    except: pass
except MemoryError as e: print(e)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Belle amélioration ici aussi, KhiCAS remplit enfin correctement la forme de droite magré sa complexité !

Exemple B4 : Pavage d'une lagogne

Go to top

Partons maintenant à la pêche avec un script très hautement impressionnant par rapport aux contraintes de heap des TI-83 Premium CE et compatibles ; ici nous sommes vraiment sur le fil de la limite des possibilités concernant ces modèles.

Voici donc une lagogne littéralement pavée de poissons :
Code: Select all
from math import sqrt
from ttl_fix import *

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(255)
turtle.pencolor((0,0,0))

a=16

try:
  j = 0
  while -5 < j < 4:
    col = ((0,0,255),(255,0,0),(255,180,0))[j%3]
    i = 0
    while -2 + (j % 2) < i < 2:
      for c in range(3):
        turtle.penup()
        turtle.goto(sqrt(3)*3*a*(i*2-(j%2)), 3*a*j)
        turtle.setheading(-30 + 120*c)
        turtle.pendown()
        turtle.fillcolor(col)
        turtle.begin_fill()
        for k in range(-17, 18):
          l = a*sqrt(7)
          tf = ((1,141.787), (0,l), (1,-100.893), (0,a), (1,120), (0,a/2), [1,-120], [0,-a], [0,a], [1,120], (0,a/2), (1,60), (0,a), (1,-120), (0,a), (1,100.893), (0,l), [1,-40.893])[abs(k)]
          if k==6 or k==9 or k==17: tf[1] -= 180
          elif k==7 or k==8: tf[1] *= -1
          (turtle.forward, turtle.left)[tf[0]](tf[1])
        turtle.end_fill()
        turtle.forward(6*a)
        turtle.backward(5*a)
        turtle.penup()
        turtle.right(90)
        l = a*sqrt(3)/6
        for k in range(2):
          turtle.forward(l)
          turtle.pencolor((255,255,255))
          turtle.dot(a//4)
          turtle.pencolor((0,0,0))
          turtle.dot(a//8)
          turtle.backward(l)
          turtle.left(180)
      i = -i + (i <= 0)
    j = -j - (j >= 0)
except Exception as e: print(e)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Formidable ici aussi, les poissons se comportent enfin correctement sous KhiCAS pour réaliser la pavage !
Petits détails toutefois non spécifiques à cet exemple, lorsque l'on fait défiler le tracé obtenu :
  • les affichages effectués sur la barre de titre/état en haut d'écran (18 premières lignes de pixels) ne sont pas nettoyés correctement lors des rafraichissements
  • les formes ne sont bizarrement pas remplies correctement dans une bande correspondant aux 42 premières lignes de pixels

Exemple B4 : ♫ Le tournesol, le tournesol, ... ♫

Go to top

15452Terminons enfin avec un exemple absolument bluffant de réalisme pour du turtle, nous allons faire pousser un tournesol devant toi :
Code: Select all
from math import pi, sin, cos, sqrt
from ttl_fix import *

def spiral():
  phi = (1+sqrt(5))/2
  a  =0
  r = 0
  dr = 0.15
  turtle.penup()
  for i in range(300):
    turtle.forward(r)
    turtle.pencolor((0,0,0))
    try: turtle.dot(3)
    except: pass
    turtle.pencolor((205,133,63))
    try: turtle.dot(2)
    except: pass
    turtle.goto(0,0)
    turtle.setheading(0)
    a+=360/phi
    turtle.right(a)
    if a>=360:
      r+=dr
      a-=360   

def feuille(core,a):
    try: turtle.begin_fill()
    except: pass
    turtle.right(a/2)
    turtle.forward(core)
    turtle.left(a)
    turtle.forward(core)
    turtle.left(180-a)
    turtle.forward(core)
    turtle.left(a)
    turtle.forward(core)
    try: turtle.end_fill()
    except: pass

turtle.speed(0)
turtle.colormode(255)
turtle.pencolor((30,144,255))
try: turtle.dot(320)
except: pass

d=25
core=40
turtle.pencolor((160,82,45))
try: turtle.dot(40)
except: pass

c=((255,215,0),(255,255,0))

for i in range(2):
  turtle.color(c[0], c[i])
  for h in range(10*i,370,20):
    r=h * pi / 180
    x=d*cos(r)
    y=d*sin(r)
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    turtle.setheading(h)
    feuille(core,32)

spiral()

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

nouveau
KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II

ancien
KhiCAS
NumWorks
TI-Nspire CX II CX


Excellent, les graines dans le cœur sont enfin délimitées correctement sous KhiCAS ! :bj:





C) 13 autres exemples comparatifs

Go to top




Exemple C1 : La dalle aux ammonites

Go to top

C'est donc parti pour quelques exemples afin d'approfondir les améliorations de la nouvelle bibliothèque turtle pour TI-83 Premium CE Edition Python et compatibles, ainsi que les points forts et faibles par rapport aux autres modèles de calculatrices.

Précisons que les problèmes récurrents ne seront pas systématiquement réévoqués sur chaque exemple.

Un petit peu au Nord de Digne-les-bains en rive droite de la Bléone se trouve la dalle aux ammonites. Comme il est strictement interdit d'en prélever, voici de quoi en reproduire une sur ta calculatrice :
Code: Select all
from ttl_fix import *
from math import pi

turtle.speed(0)
turtle.pencolor((0,0,0))
turtle.pendown()
turtle.pensize(1)

turtle.goto(0,-8)
x,y = turtle.pos()
turtle.left(115)
for i in range(132):
  turtle.forward(10)
  try:
    h = turtle.towards(x,y)
    turtle.setheading(h)
  except: pass
  d=10*pi
  turtle.forward(d)
  turtle.backward(d)
  turtle.right(90)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C2 : L'escargot de lumière

Go to top

Si tu es dans le Sud de la France tu sais qu'il ne pleut pas souvent (par contre, quand il pleut... il pleut !). Alors voici pour toi un escargot bariolé :
Code: Select all
from math import exp
from ttl_fix import *

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(1.0)

turtle.penup()
turtle.goto(0, -20)
turtle.pendown()
turtle.right(90)
for i in range(20):
  c = [exp(-.5 * ((i - k) / 12)**2) for k in (6, 18, 30)]
  cb = [v/2 for v in c]
  turtle.color(cb, c)
  try: turtle.begin_fill()
  except: pass
  turtle.circle(27 + i)
  try: turtle.end_fill()
  except: pass
  turtle.right(10)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C3 : Le triangle de Penrose

Go to top

Tu n'as jamais touché à un triangle de Penrose ? Et bien voici de quoi en afficher le plan dans ta calculatrice, tu n'auras plus qu'à l'imprimer en 3D, si tu arrives à comprendre où est le devant et l'arrière : ;)
Code: Select all
from math import sqrt
from ttl_fix import *

def hook(a, c):
  turtle.penup()
  turtle.goto(0,-15)
  turtle.setheading(a)
  turtle.forward((l - 4*b) / sqrt(3))
  turtle.right(150)
  turtle.pendown()
  lf = ((turtle.left, 60),[turtle.forward,b],(turtle.left,120),(turtle.forward,l-b),[turtle.right,120],[turtle.forward,l-3*b])
  try:
    turtle.fillcolor(c)
    turtle.begin_fill()
  except: pass
  for k in range(-len(lf) + 1, len(lf)):
    tf = lf[abs(k)]
    if k == 1: tf[1] = l
    elif k == 4: tf[0] = turtle.left
    elif k == 5: tf[1] = b
    tf[0](tf[1])
  try: turtle.end_fill()
  except: pass
 
turtle.speed(0)
turtle.pensize(2)
turtle.colormode(255)

l=180
b=23

for i in range(112):
  turtle.pencolor(232 - int(i * 23 / 11), 249 - int(i * 29 / 55), 255)
  turtle.penup()
  turtle.goto(-192, 111 - 2*i)
  turtle.pendown()
  turtle.forward(384)

turtle.pencolor((0,0,0))
turtle.pensize(1)

hook(330, (255,255,0))
hook(90, (0,0,255))
hook(210, (255,0,0))

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C4 : La courtepointe de Mamie

Go to top

Voici maintenant la courtepointe brodée avec amour et soin par Mamie :
Code: Select all
from ttl_fix import *

def rotate_list(l):
  l[1:],l[0] = l[0:-1],l[-1]

def poly_reg_a(l, a):
  h0 = turtle.heading()
  while True:
    turtle.forward(l)
    turtle.left(a)
    if abs(h0 - turtle.heading()) < .1:
      break

turtle.hideturtle()
turtle.speed(0)
turtle.pensize(1)
turtle.colormode(255)

c = [191, 127, 0]
cf = [127, 255, 0]
i = 0
while i > -3:
  j = 0
  while j > -2:
    turtle.penup()
    turtle.goto((i - 1)*88, (j - 1)*85 + 28)
    turtle.pendown()
    turtle.color(c, cf)
    try: turtle.begin_fill()
    except: pass
    poly_reg_a(80, 140)
    try: turtle.end_fill()
    except: pass
    rotate_list(c)
    rotate_list(cf)
    j = -j + (j <= 0)
  i = -i + (i <= 0)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C5 : Les vitraux rhombiques

Go to top

Voici maintenant une belle rosace rhombique pour décorer le bâtiment de ton choix.

Nous utilisons ici la méthode .dot() permettant de remplir un disque de diamètre donné, afin de générer de quoi avoir une couleur de fond d'écran sur nos calculatrices, suffit-il juste de lui spécifier un diamètre suffisamment grand :
Code: Select all
from ttl_fix import *

turtle.speed(0)
turtle.colormode(255)
turtle.pencolor((0,0,255))
turtle.dot(320)
turtle.pencolor((0,0,0))
turtle.pensize(2)
col = ((255,0,0),(255,255,0),(0,255,0),(255,255,255),(255,0,255))
a=60

for i in range(10):
  c = col[i%5]
  turtle.color(c, c)
  turtle.begin_fill()
  for j in range(5):
    turtle.forward(a)
    turtle.right(72)
  turtle.end_fill()
  turtle.right(36)

for i in range(10):
  c = [v//3 for v in col[i%5]]
  turtle.pencolor(c)
  for j in range(5):
    turtle.forward(a)
    turtle.right(72)
  turtle.right(36)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Par rapport au fond bleu, notons que c'est bel et bien KhiCAS qui adopte le comportement correct. Selon le standard turtle, la méthode .dot() attend en paramètre le diamètre du disque à tracer. Ce sont les modèles Texas Instruments qui le considèrent à tort comme un rayon et remplissent alors tout l'écran.

Exemple C6 : Les roses par 12

Go to top

Voici maintenant une rose, cette fois-ci sur un fond d'écran en dégradé radial. Nous utiliserons pour cela cette fois-ci une boucle de .dot() :
Code: Select all
from math import pi, sin, cos, sqrt
from ttl_fix import *

def rpoly(c, n):
  a=360/n
  for k in range(n):
    turtle.forward(c)
    turtle.left(a)
def carre(c): rpoly(c, 4)

turtle.speed(0)
turtle.colormode(255)
turtle.penup()

r=80
alpha=(15 * pi / 180)

for i in range(320):
  c=int(255/320*i)
  turtle.pencolor(c,c,c)
  try: turtle.dot(320-i)
  except: pass

turtle.goto(20,-76)
turtle.color((255,255,255),(0,0,0))

for i in range(4):
  a=r*sin(alpha)*2
  d=a/sqrt(2)
  turtle.pendown()
  for i in range(12):
    turtle.right(15)
    try: turtle.begin_fill()
    except: pass
    carre(d)
    try: turtle.end_fill()
    except: pass
    turtle.left(45)
    turtle.penup()
    turtle.forward(a)
    turtle.pendown()
  turtle.penup()
  turtle.left(75)
  turtle.forward(d)
  turtle.right(60)
  r=r*cos(alpha)-a/2

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Sur la taille du disque de fond d'écran et comme déjà dit, c'est ici encore KhiCAS qui fait comme il faut.

Exemple C7 : Les triangles de Sierpiński

Go to top

Revenons aux fractales et à la récursivité avec les triangles de Sierpiński. As-tu déjà réussi à les compter ? Et bien voici de quoi commencer sur ta calculatrice :
Code: Select all
from ttl_fix import *

def sierp(n, l):
  if n == 0:
    for i in range (0, 3):
      turtle.forward(l)
      turtle.left(120)
  if n > 0:
    sierp(n - 1, l / 2)
    turtle.forward(l / 2)
    sierp(n - 1, l / 2)
    turtle.backward(l / 2)
    turtle.left(60)
    turtle.forward(l / 2)
    turtle.right(60)
    sierp(n - 1, l / 2)
    turtle.left(60)
    turtle.backward(l / 2)
    turtle.right(60)

turtle.colormode(255)
turtle.speed(0)
turtle.pensize(1)

turtle.penup()
turtle.goto(-110, -95)
turtle.pendown()
turtle.pencolor((255,0,0))
sierp(6, 220)
turtle.penup()
turtle.forward(400)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C8 : Sous le soleil exactement

Go to top

Plaçons-nous maintenant sous le soleil exactement, profitant ainsi de toutes les couleurs de la lumière blanche :
Code: Select all
from math import exp
from ttl_fix import *

def rpoly(c, n):
  a=360/n
  for k in range(n):
    turtle.forward(c)
    turtle.left(a)
def carre(c): rpoly(c, 4)

turtle.speed(0)
turtle.pensize(1)
turtle.colormode(1.0)

n = 36
for i in range(n):
  k=.4 + 4*i/255
  cp = [.7*exp(-.5 * ((n - i - k) / (n / 3))**2) for k in (6, 18, 30)]
  turtle.pencolor(cp)
  try:
    turtle.fillcolor((k,k,0))
    turtle.begin_fill()
  except: pass
  carre(60)
  try: turtle.end_fill()
  except: pass
  turtle.right(360 / n)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C9 : Le labyrinthe du Minotaure

Go to top

Explorons maintenant dans la labyrinthe du Minotaure :
Code: Select all
from ttl_fix import *

turtle.speed(0)
turtle.colormode(255)
turtle.pendown()

turtle.right(48)
turtle.pencolor((0,0,0))
for i in range(98):
  turtle.forward(2*i)
  turtle.left(90.5)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C10 : Le carreau de carreaux

Go to top

Code: Select all
from math import sqrt
from ttl_fix import *

def rotate_list(l):
  l[1:],l[0] = l[0:-1],l[-1]

def reg_poly(l, n):
  for i in range(n):
    turtle.forward(l)
    turtle.left(360/n)

def square(l):
  reg_poly(l, 4)

turtle.colormode(255)
turtle.pencolor(0,0,0)
turtle.speed(0)

turtle.pensize(3)
d=190
c=[0,255,127]
turtle.penup()
turtle.goto(-d/2,-d/2)
turtle.setheading(0)
turtle.pendown()
for i in range(8):
  try:
    turtle.fillcolor(tuple(c))
    turtle.begin_fill()
  except: pass
  square(d)
  try:
    turtle.end_fill()
  except: pass
  turtle.penup()
  turtle.forward(d/2)
  turtle.left(45)
  turtle.pendown()
  d/=sqrt(2)
  rotate_list(c)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Exemple C11 : Les étoiles jumelles

Go to top

Code: Select all
try: # TI-83 Premium CE
  from ti_system import disp_clr
  disp_clr()
except: pass
from ttl_fix import *

def rpoly(c, n):
  a=360/n
  for k in range(n):
    turtle.forward(c)
    turtle.left(a)

def rosace(c, n1, a, n2):
  try: turtle.begin_fill()
  except: pass
  for i in range(n2):
    turtle.left(a)
    rpoly(c, n1)
  try: turtle.end_fill()
  except: pass

turtle.colormode(255)
turtle.pencolor((0,0,0))

try: turtle.dot(320)
except: pass
turtle.color((255,255,255),(255,255,0))
turtle.speed(0)
turtle.pensize(1)
try:
  for i in range(-1, 2, 2):
    turtle.penup()
    turtle.goto(80*i, 0)
    turtle.pendown()
    rosace((i > 0) and 21 or 30, (i > 0) and 12 or 8, 30, 12)
    turtle.pensize(2)
    turtle.pencolor((0,0,255))
except MemoryError as e: print(e)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II


Sur la taille du disque de fond d'écran, c'est à nouveau ici KhiCAS qui a raison et pas TI.

Exemple C12 : La toile de l'araignée

Go to top

Suivons maintenant le fil de l'araignée :
Code: Select all
from ttl_fix import *

def spiral(a,b):
  turtle.pencolor((0,0,0))
  try: turtle.dot(320)
  except: pass
  turtle.pencolor((255,255,0))
  for i in range(189):
    for j in range(6):
      turtle.forward(i/a)
      turtle.left(23)
    turtle.left(b)
    try: turtle.dot(2)
    except: pass
   
turtle.speed(0)
turtle.colormode(255)
turtle.pensize(1)

a=17
b=194

spiral(a,b)

try: turtle.show() #TI-83 Premium CE
except: pass


TI-83PCE/84+CE
turtle

TI-Nspire CX II
turtle

Casio
Graph 90+E

KhiCAS
NumWorks
TI-Nspire CX II CX

TI-83PCE/84+CE
ce_turtl

NumWorks
Casio
Graph 35+E II





Conclusion

Go to top

Selon notre outil de tests, KhiCAS pour TI-Nspire CX et NumWorks N0110 est bien mieux conforme au standard Python-turtle que l'ensemble des solutions turtle officielles, et semble en conséquence bien mieux se comporter en pratique sur une majorité de nos exemples. nous semble offrir à ce jour la meilleure bibliothèque Python turtle toutes solutions confondues.

Les méthodes de remplissage, absentes des implémentations officielles de Casio et NumWorks t'ouvrent la porte à de formidables progrès.

Les progrès témoignent d'un soin minutieux apporté par Bernard Parisse, et vu que tout semble parfait maintenant il va nous falloir tenter d'inventer de nouveaux exemples piégeux... :P




Téléchargements

Go to top


nQuake 1.03 accéléré + gérant dernières TI-Nspire CX

New postby critor » 20 Apr 2022, 09:19

Nous te parlons régulièrement sur nos calculatrices de jeux Doom-like, du nom du mythique jeu fps de 1993 par id Software avec affichage 3D (technique du raycasting étendu).

Si sur calculatrices il s'est souvent agi de créations de fans dans loin d'égaler l'original, signalons les TI-Nspire avec leur formidable processeur 32 bits ARM9 (architecture ARMv5) qui sont les premières calculatrices à avoir bénéficié d'un véritable portage, nDoom par Mrakoplatz pour les TI-Nspire monochromes dès 2011, puis moi-même dès 2012 pour les TI-Nspire CX. C'est-à-dire qu'il s'agit d'une recompilation intégrale à partir du code source du jeu. Tu pouvais donc ici retrouver l'intégralité du jeu original ainsi que de ses extensions et évolutions compatibles (Ultimate Doom, Final Doom, Plutonia Experiment, TNT Evilution, Doom II, ...)
Le code source de nDoom vient tout juste d'être repris cette année pour créer CGDoom, un portage compatible Casio Graph 90+E et fx-CG10/20/50.

Rappelons que sur les TI-Nspire la couche logicielle très lourde de l'environnement écrase littéralement les performances des programmes en langage interprété (Basic ou Python), que pour ce genre de projet il faut pouvoir exécuter du code machine et donc disposer du jailbreak Ndless, que malheureusement Texas Instruments a toujours farouchement combatte le jailbreak Ndless et que l'équipe de développement de ce dernier semble avoir baissé les bras, Ndless n'est plus adapté pour les dernières mises à jour de rentrée 2021 (TI-Nspire CX 4.5.5 et TI-Nspire CX II 5.3.1) qui bien évidemment interdisent le retour à une version inférieure. :'(

5937Mais id Software n'a pas sorti que Doom dans ce style. Avant Doom il y a eu Wolfenstein 3D en 1992, et après Doom il y a eu Quake en 1996.

Quake a lui aussi bénéficié d'un portage pour TI-Nspire par Ralf Willenbacher alias rwill en 2015.

Par rapport à Doom, Quake apporte plusieurs évolutions significatives au moteur :
  • D'une part le moteur permet d'afficher l'ensemble des éléments en 3D. C'est-à-dire que les ennemis et items ne sont plus de simples sprites te présentant toujours la même face pour les items, ou un nombre limité de faces pour les ennemis.
  • D'autre part, tu peux désormais sauter et même dans certaines conditions voler. c'est-à-dire que la 3ème dimension passe d'une décoration à un véritable élément de jeu.

rwill nous ayant hélas quitté pour un temps, dans le cadre des dernières mises à jour de Ndless Vogtinator s'était chargé de patcher nQuake pour le rendre compatible avec les révisions majeures du matériel TI-Nspire CX sorties depuis :
  • les TI-Nspire CX CR4+ (assemblées à partir d'octobre 2015) qui retournaient la géométrie du buffer l'écran, ce dernier passant de 320×240 pixels à 240×320 pixels
  • les TI-Nspire CX II (assemblées depuis novembre 2018)
Toutefois, il s'agissait d'un patch très rapide s'appuyant sur le mode de compatibilité alors introduit dans Ndless, un mode qui interceptait et corrigeait les affichages. L'activation de ce mode t'était indiquée par une fenêtre popup au lancement de nQuake, et dans ce cas les performances n'étaient pas au rendez-vous.

15453Et bien bonne nouvelle, rwill est de retour cette année ! :D

Il vient de prendre le temps de nous signer une mise à jour nQuake de qualité, la version 1.03 :
  • gérant désormais directement les dernières révisions matérielles TI-Nspire, et n'utilisant donc plus le mode de compatibilité Ndless :bj:
  • et en prime nettement plus performante :bj:

Regarde un peu ces performances que nous avons mesurées, sans aucun overclocking :
modèle
fréquence
processeur
ancien nQuake
par Vogtinator
nouveau nQuake
par rwill
TI-Nspire CX
132 MHz
7.8 fps
10 fps (+28,21%)
TI-Nspire CX CR4+
156 MHz
9.8 fps
10 fps (+2,04%)
TI-Nspire CX II
396 MHz
20.8 fps
26 fps (+25%)


Avec des performances aussi fantastiques, sur les dernières TI-Nspire CX II nous sommes désormais à vitesse réelle, zyeute un peu ça : :#tritop#:

Téléchargements :

Source : viewtopic.php?f=20&t=25548

Mise à jour 1.0.10 applis Classpad fx-CP400 pour Android/iOS

New postby critor » 21 Apr 2022, 09:05

Classpad est le haut de gamme des calculatrices graphiques Casio. Lancée pour la rentrée 2003, cette gamme se caractérise par des modèles munis d'un écran tactile à stylet de 160×240 pixels ainsi que d'un moteur de calcul formel.

Se sont succédées les :
  • Classpad 300 (rentrée 2003)
  • Classpad 300+ (rentrée 2005) qui rajoutait une connexion USB standard
  • Classpad 330 (rentrée 2007)
  • Classpad 330+ (rentrée 2012) qui remplaçait le processeur Renesas SH3 historique par un SH4, mais également hélas fermait l'écosystème en retirant la possibilité d'installer et lancer des applications tierces, limitation qui persiste à ce jour et nuit grandement à la popularité de cette gamme au sein de nos communautés de passionnés et développeurs

2714Depuis la gamme est passée à une nouvelle génération matérielle dite Classpad II, accélérant le processeur SH4 à 117,96 MHz tout en passant à un écran couleur en 320×528 pixels. Cette fois-ci, les modèles sont distints selon la zone de distribution :
  • la fx-CP400, modèle international sorti à la rentrée 2013
  • la fx-CP400+E qui remplace la fx-CP400 en France à la rentrée 2016, lui rajoutant une diode examen conformément à la nouvelle réglementation
  • la fx-CG500 pour l'Amérique du Nord à la rentrée 2017, déclinaison conçue pour être autorisée aux examens en retirant diverses choses interdites : dispositions non alphabétiques du clavier virtuel (Qwerty, Qwertz, Azerty), mentions de la gamme Classpad car nommément interdite à cause de cela dans plusieurs réglementations d'examens

Mais Casio te permet également de retrouver l'intégralité des capacités de son logiciel de Mathématiques intégré Classpad sur ton smartphone ou ta tablette, aussi bien sous Android qu'iOS, grâce à 2 applications d'émulation dédiées :
  • Classpad qui reproduit le fonctionnement des fx-CP400 et fx-CP400+E
  • fx-CG500 pour l'Amérique du Nord
Les dernières versions étaient les 1.0.9 du 30 octobre 2020, qui intégraient elles-mêmes les dernières nouveautés apportées au logiciel Classpad avec les mises à jour pour calculatrices en version 2.01.7000 du 11 juin 2020.

Suprise Casio nous sort aujourd'hui pour la rentrée 2022 une mise à jour de l'ensemble de ces applications, la version 1.0.10.

Datée du 20 avril 2022, elle continue apparemment à utiliser le même logiciel de Mathématiques intégré Classpad en version 2.01.7000, ce qui suggère donc déjà qu'il n'y a aucune nouveauté niveau capacités après pourtant près de 2 ans, et peut-être même qu'il n'y en aurait pas davantage pour calculatrices d'ici la rentrée 2022.

Les pages des applications indiquent la correction d'un bug mineur sans plus de précisions, que l'on peut par élimination supposer être spécifique à la gestion de l'appareil hôte ou de son système d'exploitation.

Téléchargements :

-
Search
-
Social TI-Planet
-
Featured topics
Grand Concours 2024-2025 - Programmation Python
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 !
12345
-
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.
702 utilisateurs:
>691 invités
>4 membres
>7 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)