Microbit y Python


Objetivos y contenidos

Objetivos
Contenidos

Introducción

Introducción

Microbit v2 vs v1

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

La microbit fué lanzada en el 2015  con la versión 1 que tiene los siguientes sensores y actuadores

hardware_1_0.png

Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

En el 2020 se lanzó la versión 2 que tiene además incorporó estas características

hardware_2 (1).png
Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

Además de estas que no se ven:

La alimentación es a través de los 5V del puerto USB o 3V a través del conector JST. También es posible alimentar a la micro:bit desde los anillos 3V/GND en el conector de borde.

Pinout

Hay 25 pistas/patillas que incluyen 5 agujeros para usar con clavijas tipo banana de 4 mm o pinzas de cocodrilo. Tres de estos anillos son para entrada y salida de propósito general (GPIO) y también sirven para detección analógica, PWM y táctil, y dos están conectados a la alimentación de la micro:bit.

Solamente tienen conexión las pistas frontales, las posteriores están sin conexión y los anillos posteriores están conectados a los delanteros. Las pistas mas finas están separadas 1,27 mm, algunas son utilizadas por micro:bit y otras están disponibles para su uso mediante cualquiera de los conectores externos existentes, lo que permite un amplio mercado de accesorios externos. En en enlace tenemos una guia de accesorios para micro:bit

En la imagen siguiente tenemos la descripción de pines de la micro:bit v2 a la izquierda y de la v1 a la derecha para poder comparar y establecer las diferencias de una forma sencilla.

pinout.png
Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

En microbit.pinout.xyz tenemos un fantástico recurso para obtener más información sobre los pines de la micro:bit y de cómo los utilizan algunos accesorios.

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Introducción

Ventajas y desventajas Python

Ventajas

Python es un lenguaje de desarrollo y curva de aprendizaje rápido. Tiene una comunidad amplia con muchas librerías, ejemplos, tutoriales... que para casi todos los problemas, seguro que encuentras una solución escrita en Python

Es un lenguaje de alto nivel, es decir, que se programa igual que los programadores, pero interpretable para los humanos !. Comparándolo con otros lenguajes (Java, C++, etc..) es el más "humanizado".

También gestiona la memoria, por ejemplo, si programas en C++, tú eres el responsable de limpiar la memoria de datos que ya no usas, o corres el peligro de quedarte sin memoria. En Python ya lo hace por ti.

Desventajas

La gestión de memoria que antes se mencionaba tiene un precio; bajada de velocidad y paradójicamente coste de memoria. 

En otros programas, el compilador esta en tu PC, pero en Python está en el dispositivo (por eso se llama lenguaje Interpretado), esto hace que ocupa memoria, y en microbit por ejemplo esto hace que no puedes usar Python y código Bluetooh pues no hay suficiente memoria RAM.

2024-07-04 18_44_27-(1) Exploring the Arduino Nano ESP32 _ MicroPython & IoT Cloud - YouTube.png
Fuente  vídeo Exploring the Arduino Nano ESP32 | MicroPython & IoT

También hay que tener en cuenta que si Python es un lenguaje interpretado, siempre será más lento que un lenguaje compilado por ejemplo el C++, pues para ejecutarlo el dispositivo, lo ejecuta, pues lo tiene en binario y en paz, pero en Python cada instrucción necesita ser interpretado, decodificado, en binario antes de ejecutarse.

Introducción

Editores

Tienes dos opciones, online o local :

Programar online con Microbit.org

Entramos en https://python.microbit.org/ y el editor online nos permite trabajar ;

  1. Una biblioteca de códigos que nos permitirá seleccionar y usar para programar de forma guiada
  2. Un simulador para ver cómo se ejecutaría nuestro código
  3. Un botón para enviar a la microbit real
  4. Botones para guardar nuestro código de forma local y abrir los existentes.

2024-09-18 22_40_17-micro_bit Python Editor.png

En este tutorial utilizaremos este editor online.

Programar en local con MU

Es un editor muy sencillo, se descarga en https://codewith.mu/ y permite su instalación en Windows, Linux y Apple.2024-07-04 18_44_27-(1) Exploring the Arduino Nano ESP32 _ MicroPython & IoT Cloud - YouTube.png
Fuente https://codewith.mu/ CC-BY-NC-SA

La primera vez que lo ejecutamos (tarda algo la primera vez) nos pide el modo que se puede cambiar en cualquier momento:

2024-09-18 22_28_05-Configuración.png

  1. Escribimos el código
  2. Lo comprobamos
  3. Flasheamos, es decir enviamos el código al Microbit (conectarlo previamente)
  4. Cuando sale el mensaje Código copiado al microbit procedemos a resetearlo (si quieres desconectar y volver a conectar) para que la placa ejecute el programa.

2024-09-18 22_34_58-Configuración.png

OTROS EDITORES DE PYTHON QUE NO SON COMPATIBLES CON PYTHON MICROBIT

Vamos a ver este programa escribo en https://python.microbit.org/

# Imports go at the top
from microbit import *
while True:
    if pin0.is_touched():
        display.show(Image.HEART)
    else:
        display.show(Image.NO)

Lo que hace es :


EL MISMO CÓDIGO EN MAKECODE-PYTHON
Makecode a pesar de que esta orientado a programar con bloques, tiene su sección de Python

2024-09-23 10_37_07-Microsoft MakeCode for micro_bit.png

Al darle en Python (arriba a la derecha), muestra este código

def on_forever():
    if pins.digital_read_pin(DigitalPin.P0) == 1:
        basic.show_icon(IconNames.HEART)
    else:
        basic.show_icon(IconNames.NO)
basic.forever(on_forever)

Como se puede ver makecode python no es comp0atiuble con https://python.microbit.org/ ya lo dice en su tutorial https://microbit-micropython.readthedocs.io/en/v2-docs/

2024-09-23 10_46_05-BBC micro_bit MicroPython documentation — BBC micro_bit MicroPython 2 documentat.png

EL MISMO CÓDIGO CON PYTHON DE TINKERCAD

Tinkercad https://www.tinkercad.com/ es una herramienta estupenda de simulación pues es muy realístico, igual que Maquecode, este muy orientado a la programación en bloques pero también tiene su sección de código python

2024-09-23 10_51_49-Circuit design PIN0-CORE-CREW - Tinkercad.png

Si le das la opción de bloque+código intenta muestra los bloques traducidos a código, pero si le das la opción sólo código pierdes la programación en bloques, Esto ya lo vimos en https://libros.catedu.es/books/programa-arduino-mediante-codigo/page/software en los párrafos escritos en naranja.

El código generado vemos que no es compatible con Python microbit

# Python code
#

def on_pulsed_p0_high():
  basic.show_icon(IconNames.Heart)
pins.on_pulsed(DigitalPin.P0, PulseValue.HIGH, on_pulsed_p0_high)

def on_pulsed_p0_low():
  basic.show_icon(IconNames.No)
pins.on_pulsed(DigitalPin.P0, PulseValue.LOW, on_pulsed_p0_low)

Introducción

Introducción al Python

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Palabras reservadas

Son palabras reservadas que tienen un significado especial para el compilador y que no podemos usar para poner nombres a variables o funciones. Todas las palabras, excepto True, False y None se escriben en minúsculas. A continuación se da un listado de todas las palabras reservadas o keywords:

False, None, True, and, as, assert, async, await, break, class, continue, def, del, elif, else, except, finally, for, from, global, if, import, in, is, lambda, nonlocal, not, or, pass, raise, return, try, while, with, yield

El listado al principio nos puede resultar abrumador, pero imaginemos un lenguaje con tan solo esas palabras y entenderemos que no resultará tan complejo familiarizarse, al menos con las mas usuales.

Identificadores

Los identificadores son los nombres que se dan a variables, clases, métodos, etc. No podemos usar palabras reservadas para estos nombres.

Algunas reglas que nos pueden resultar útiles para nombrar identificadores son:

Nos va a resultar muy útil recordar lo siguiente:

Variables, constantes y literales

Variables

En programación, una variable es un nombre que se utiliza para referirse a una posición de memoria donde se almacena un valor. De forma más abstracta, puede considerarse como una caja que almacena un valor. El nombre de la caja es el nombre de la variable y el contenido su valor. Todas las variables constan de tres partes: un nombre, un tipo de dato y un valor. En la figura siguiente vemos tres variables de distintos tipos:

boxes.pngLicencia CC-BY-SA fuente

La variable name contiene la cadena Bob, la variable winner es cierta y la variable score contiene el valor 35.

Python no dispone de ningún comando para declarar variables. Una variable se crea cuando se le asigna valor por primera vez. La técnica de declarar variables es poner un nombre seguido del signo de asignación (=) y el valor asignado a la variable. En la declaración es importante tener claro que se distinguen mayúsculas de minúsculas y que no están permitidos los caracteres especiales.

En Python no se declara de forma explicita el tipo de la variable pues se trata de un lenguaje inferido. Las variables incluso pueden cambiar de tipo desde el que se establece al asignarle valor la primera vez. Es decir, si declaro valor = 5 inicialmente la variable será de tipo entero (int), pero si en el programa se realizan operaciones que al final hacen que valor = 1.33 ahora valor es de tipo float. Automáticamente sabe que valor es un número entero y declara la variable valor como un int.

Aunque no es necesario si es posible especificar el tipo de dato de una variable, haciendo:

x = str(22) # x será la cadena '22'
y = int(22) # y será el entero 22
z = float(22) # z será el número de coma flotante 22.0

Algunas reglas para nombrar variables que podemos tener en cuenta son:

Constantes

Una constante no es mas que un tipo especial de variable cuyo valor no puede modificarse.

En Python, las constantes suelen declararse y asignarse en un módulo (un nuevo archivo que contiene variables, funciones, etc y que se importa al archivo principal).

Veamos cómo declaramos constantes en un archivo separado y lo usamos en el archivo principal,

Creamos un archivo que nombramos constantes.py y que contendrá:

PI = 3.141592
FUERZA_GRAVEDAD = 9.82

Creamos el archivo principal main.py, que contendrá:

import constantes

print(constantes.PI)
print(constantes.FUERZA_GRAVEDAD)

En el ejemplo creamos el archivo de módulo constantes.py y asignamos el valor constante a PI y FUERZA_GRAVEDAD.

Después, creamos el archivo main.py e importamos el módulo constantes. Finalmente, imprimimos el valor de cada constante.

La convención es nombrarlas en mayúsculas para distinguirlas de las variables.

Literales

Numéricos

Los literales son representaciones de valores fijos en un programa. Pueden ser números, caracteres, cadenas, etc. Por ejemplo, "¡Hola, mundo!", 12, 23.0, "C", etc.

Los literales numéricos son inmutables (no pueden cambiar) y pueden pertenecer a uno de los tres tipos de datos numéricos posibles: Entero, Coma flotante y Complejo. Los tipos son:

Solamente hay dos literales booleanos True y False

Cadenas de caracteres

Los literales de caracteres son caracteres unicode encerrados entre comillas, por ejemplo S. Los literales cadenas de caracteres son cadenas de csaracteres encerradas entre comillas, por ejemplo Python es divertido.

Especiales

En Python existe un literal especial, None. Podemos usarlo, por ejemplo, para especificar una variable nula, por ejemplo:

var = None
print(var)
# El resultado será: None

Tipos de datos en Python

En Python, al igual que en programación en general, los tipos de datos especifican el tipo de datos que puede almacenarse en una variable.

Numéricos

Contienen valores numéricos y sabemos que:

Los tipos básicos de datos son:

Podemos realizar conversión de tipos así:

Cadenas

Contienen secuencias de caracteres. Una cadena es una secuencia de caracteres representada entre comillas simples o dobles.

Las cadenas pueden estar encerradas entre comillas simples ('...') o dobles ("...") con el mismo resultado. Podemos usar para incluir comillas en una cadena.

La función print() devuelve la cadena que encierra entre los paréntesis, omitiendo las comillas que la encierran.

En la imagen siguiente se ven varios ejemplos con cadenas utilizando como editor el IDLE que por defecto se instala con Python y que se abre desde una terminal simplemente invocando a Python.

cad1.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Una cadena raw (cruda) se interpreta tal como se escribe, es decir, se omiten los caracteres especiales expresados con . Las cadenas raw se escriben entrecomilladas y van precedidas del carácter 'r'. En la imagen vemos un ejemplo.

cad2.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Es posible aplicar la operación de multiplicar a textos haciendo que estos se repitan. En la imagen siguientes vemos ejemplos de concatenación y multiplicación, así como un error cometido.

cad3.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Secuencias

Contienen colecciones de datos, como las listas, las tuplas, las colecciones de datos (set) o los diccionarios.

Una lista es una colección ordenada de elementos similares o de distinto tipo separados por comas y encerrados entre corchetes [ ].

Tupla es una secuencia ordenada de elementos, igual que una lista. La única diferencia es que las tuplas son inmutables. Una vez creadas, las tuplas no pueden modificarse. En Python, se utilizan los paréntesis () para almacenar los elementos de una tupla.

Las colecciones de datos son un conjunto desordenada de elementos únicos. Una colección de datos se define por valores separados por comas dentro de llaves { }.

Un diccionario es una colección ordenada de elementos. Almacena los elementos como pares clave/valor. Siendo las claves identificadores únicos que se asocian a cada valor.

Estudiaremos estos últimos tipos mas extensamente cuando los necesitemos.

Los datos de tipo booleano solamente pueden contener True o False.

Dado que en programación Python todo es un objeto, los tipos de datos son en realidad clases y las variables son instancias(objeto) de estas clases.

Comentarios en Python

En los comentarios, pueden incluirse palabras que nos ayuden a identificar además, el subtipo de comentario:

# TODO esto es algo por hacer
# FIXME (arreglarme) esto es algo que debe corregirse
# XXX esto también, es algo que debe corregirse

Identation o sangría en Python

La sangría se refiere a los espacios al comienzo de una línea de código.

Mientras que en otros lenguajes de programación la sangría en el código es solo para facilitar la lectura, la sangría en Python es muy importante ya que se usa para indicar un bloque de código.

if 5 > 2:
    print("Cinco es mayor que 2")

Lo siguiente sería un error de sintaxis.

if 5 > 2:
print("Cinco es mayor que 2")

El número de espacios de la identation puede ser cualquiera siempre que al menos sea un espacio. Siempre hay que usar el mismo número de espacios en el mismo bloque de código.

Operadores en Python

Los operadores son símbolos especiales que realizan operaciones con variables y valores.

A continuación tenemos una lista de los diferentes tipos de operadores de Python:

Operadores aritméticos

Los operadores aritméticos se utilizan para realizar operaciones matemáticas como sumas, restas, multiplicaciones, etc.

Operador Descripción Ejemplo
+ Suma o concatenación en textos 5+3=8"Hola" + "Mundo" = "Hola Mundo
- Diferencia 6-3=3
* Multiplicación 3*3=9
/ División 6/2=3
// Parte entera de un cociente 10//3=3
% Resto de un cociente 10%3=1
** Potenciación 5**2=25
Operadores de asignación

Los operadores de asignación se utilizan para asignar valores a variables.

Operador Descripción Ejemplo
= Asignación x=4a = a + 1
+= Suma y asignación x+=1 equivale a x = x + 1
-= Diferencia y asignación x-=1 equivale a x = x - 1
*= Multiplicación y asignación x*=3 equivale a x = x * 3
/= División y asignación x/=3 equivale a x = x / 3
%= Asignación de restos x%=3 equivale a x = x % 3
**= Asignación de exponentes x**=3 equivale a x = x ** 3

Operadores de Comparación

Los operadores de comparación comparan dos valores/variables y devuelven un resultado booleano: Verdadero o Falso True o False.

Operador Descripción Ejemplo
== Igual a 2==3 retorna False
!= Distinto de 2!=3 retorna True
< Menor que 2<3 retorna True
> Mayor que 2>3 retorna False
<= Menor o igual que 2<=3 retorna True
>= Mayor o igual que 2>=3 retorna False

Operadores Lógicos

Los operadores lógicos se utilizan para comprobar si una expresión es Verdadera o Falsa. Se utilizan en la toma de decisiones.

Operador Descripción Ejemplo
and AND lógica a and b #True si a y b son ciertos
or OR lógica a or b #True si a o b son ciertos
not NOT lógica not a #True si el operador a es falso

En la figura siguiente vemos un ejemplo con lo que devuelve en cada caso.

logicos.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Operadores Bitwise

Los operadores bit a bit o bitwise actúan sobre los operandos como si fueran cadenas de dígitos binarios. Operan bit a bit, de ahí su nombre.

 

 

Operador Descripción Ejemplo
& AND bit a bit 5&6 # 101 & 110 = 110 = 4
| OR bit a bit 5 \| 6 # 101 \| 110 = 111 = 7
~ NOT bit a bit ~3 # ~011 = 100 = -4
^ XOR bit a bit 5^3 # 101^011 = 110 = 6
<< Desplazamiento izquierda 4<<1 # 100 << 1 = 1000 = 8
>> Desplazamiento derecha 4 >> 1 # 100 >> 1 = 010 = 2
Operadores especiales

El lenguaje Python ofrece algunos tipos especiales de operadores como el operador de identidad (identity) y el operador de pertenencia (membership).

En Python, is e is not se utilizan para comprobar si dos valores se encuentran en la misma parte de la memoria. Dos variables que son iguales no implica que sean idénticas. Algunos ejemplos aclaran mejor lo dicho.

x1 = 5
y1 = 5
x2 = 'Hello'
y2 = 'Hello'

print(x1 is not y1)  # False

print(x2 is y2)  # True

Vemos que x1 e y1 son enteros con los mismos valores, por lo que son iguales e idénticos. Lo mismo ocurre con x2 e y2 (cadenas).

En Python, in y not in son los operadores de pertenencia. Se utilizan para comprobar si un valor o variable se encuentra en una secuencia (cadena, lista, tupla, conjunto y diccionario).

En un diccionario sólo podemos comprobar la presencia de la clave, no del valor.

Introducción

Micropython de microbit

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

API: El módulo microbit

Todo lo necesario para interactuar con el hardware de la micro:bit está en el módulo microbit y se recomienda su uso escribiendo al principio del programa:

from microbit import *

Las funciones disponibles directamente son:

sleep(ms) #1
running_time() #2
temperature() #3
scale(valor_a_convertir, from_=(min, max), to=(min, max)) #4
panic(error_code) #5
reset() #6
set_volume(valor) #7 (V2)
'''
1 Esperar el número de milisegundos indicado
2 Devuelve el tiempo en ms desde la última vez que se encendió la micro:bit
3 Devuelve la temperatura en Celcius
4 Convierte un número de una escala de valores a otra
5 La micro:bit entra en modo pánico por falta de memoria y se dibuja una
cara triste en la pantalla. El valor de error_code puede ser cualquier entero.
6 Resetea la micro:bit
7 Estable el volumen de salida con un *valor* entre 0 y 255
'''

Estructuras de datos en Python

Las listas (list)

Se trata de un tipo de dato que permite almacenar series de datos de cualquier tipo bajo su estructura. Se suelen asociar a las matrices o arrays de otros lenguajes de programación.

En Python las listas son muy versatiles permitiendo almacenar un conjunto arbitrario de datos. Es decir, podemos guardar en ellas lo que sea.

Una lista se crea con [] y sus elementos se separan por comas. Una gran ventaja es que pueden tener datos de diferentes tipos.

lista = [1, "Hola", 3.141592, [1 , 2, 3], Image.HAPPY]

Las de principales propiedades de las listas:

Hay dos métodos aplicables:

En el ejemplo vemos el funcionamiento.

ejem_listas.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Con estos conocimientos tendremos suficiente para hacer lo que pretendemos, que no es otra cosa que animar imágenes.

Las tuplas (tuple)

Son muy similares a las listas con una diferencia principal con las mismas y es que las tuplas no pueden ser modificadas directamente, lo que implica que no dispone de los métodos vistos para listas. Una tupla permite tener agrupados un número inmutable de elementos.

Una tupla se crea con () y sus elementos se separan por comas.

tupla = (1, 2, 3)

Principales propiedades:

A continuación vemos un ejemplo.

ejem_tuplas.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Diccionarios (dict)

Estas estructuras contienen la colección de elementos con la forma clave:valor separados por comas y encerrados entre {}. Las claves son objetos inmutables y los valores pueden ser de cualquier tipo. Sus principales características son:

A continuación vemos un ejemplo

ejem_dicc.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Bucles

Los Bucles son un tipo de estructura de control muy útil cuando queremos repetir un bloque de código varias veces. En Python existen dos tipos de bloques, el bucle for para contar la cantidad de veces que se ejecuta un bloque de código, y el bucle while que realiza la acción hasta que la condición especificada no sea cierta.

While 
La sintaxis de while es la siguiente:
while condicion:
    bloque de codigo

donde "condicion", que se evalúa en cada iteración, puede ser cualquier expresión realizado con operadores condicionales que devuelva como resultado un valor True o False. Mientra que "bloque de codigo" es el conjunto de instrucciones que se estarán ejecutando mientras la condición sea verdadera (True o '1'). Es lo mismo poner while true: que poner while 1:.

Para recorrer los bucles se utilizan variables que forman parte de la condición, estableciendose en esta lo que deben cumplir.

Un ejemplo sencillo podría ser el siguiente, controlar el riego de una planta en función del valor de la humedad de la tierra en la que está.

from microbit import *

while (humedad() < 45):
    display.scroll(Image.SAD)
    sleep(1000)

display.show(Image.HAPPY)

que hará que si la humedad baja por debajo de 45 se muestre una carita triste indicando que hay que regar y si es mayor mostrará una carita feliz. Evidentemente hay que resolver el tema de como obtener la humedad, pero esa es una historia que veremos mas adelante.

El bucle while puede tener de manera opcional un bloque else cuyas sentencias se ejecutan cuando se han realizado todas las iteraciones del bucle. Un ejemplo lo vemos a continuación:

cuenta = 0
while cuenta < 5:
    print("Iteración del bucle")
    cuenta = cuenta + 1
else:
    print("bucle finalizado")
for

Son también bucles pero su acción está dirigida a contar el número de veces que ocurre algo o realizar una acción un determinado número de veces. Es especialmente útil para recorrer los datos de una lista, tupla o diccionario.

La sintaxis de este tipo de bucles en Python es:

for variable in secuencia:
    declaracion

Siendo "variable" la variable que se va a recorrer en el bucle de forma que cuando se alcance el valor establecido se sale del bucle.

La variable puede ser una cadena, un rango de valores que se expresa con range(n), siendo n el número de valores del rango que se inicia en 0 y que pueden ser iterados con una variable. Mas ampliamente, la sintaxis de range() es range(start, stop, step) siendo start y stop opcionales.

Veamos un primer ejemplo en el que vamos a utilizar un bucle para encender uno a uno por filas los LEDs de la primera y última columna.

from microbit import *
for var in range(5): # var puede tomar 5 valores, del 0 al 4
    display.set_pixel(0, var, 9) # Se ilumina el LED de la fila 0 y el valor de var para columna
    sleep(300)
    display.set_pixel(4, var, 9) # Se ilumina el LED de la fila 4 y el valor de var para columna
    sleep(300)

Los bucles se pueden anidar, es decir se puede crear un bucle dentro de otro del mismo o diferente tipo, de forma que por cada iteración del bucle mas externo se tienen que producir todas las iteraciones del bucle mas interno. Veamos como ejemplo el de encender todos los LEDs de uno en uno, de izquierda a derecha, utilizando el valor de sus coordenadas x,y. El programa sería:

from microbit import *

display.clear()
for y in range(0, 5): # Valor de columna
    for x in range(0, 5): # Valor de fila
        display.set_pixel(x, y, 9) # Encender LED x,y
        sleep(100)

En la animación siguiente vemos el programa en funcionamiento.

ejem_dicc.png

Federico Coca Guia de Trabajo de Microbit CC-BY-SA

El bucle for puede tener de manera opcional un bloque else cuyas sentencias se ejecutan cuando se han realizado todas las iteraciones del bucle. Un ejemplo lo vemos a continuación:

for var in range(5):
    print(var)
else:
    print("bucle finalizado")
Bucle for decontando

Se trata del mismo bucle for pero ahora la cuenta la realizamos hacia atrás. Hay dos formas sencillas de hacerlo:

for i in range(20, 0, -2): #imprimere 20, 18, 16, ... 0
for i in reversed(range(0,21,2)): #imprimere 20, 18, 16, ... 0
Sentencias break y continue

La sentencia break se utiliza para terminar un bucle de forma inmediata al ser encontrada. En la imagen vemos la sintaxis de la sentencia break y su funcionamiento.

break.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

La sentencia continue se utiliza para saltar la iteración actual del bucle y el flujo de control del programa pasa a la siguiente iteración. En la imagen vemos la sintaxis de la sentencia continue y su funcionamiento.

continue.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

En la figura siguiente vemos dos ejemplos de esta sentencia

ejem_continue.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Sentencia condicional if...else

En Python hay tres formas de declaración de if...else

  1. Declaración if
  2. Declaración if...else
  3. Declaración if...elif...else
  1. Declaración if. La sintaxix de esta declaración en Python tiene la forma siguiente:
if condicion:
    # Cuerpo de la sentencia if

# Código después del if

Si el resultado de evaluar la condición es cierto (True o 1), el código en "Cuerpo de la sentencia if" y lo estará haciendo mientras se cumpla la condición.

En el momento que la condición sea evaluada como falsa (False o 0) el código en "Cuerpo de la sentencia if" se omite y continua la ejecución del programa por "Código después del if". En la figura siguiente vemos la explicación de forma gráfica.

f_if.png
Funcionamiento de la sentencia if
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

1. Declaración if...else. Una sentencia if puede tener de manera opcional una clausula else. La sintaxix de esta declaración en Python tiene la forma siguiente:

if condicion:
    # Bloque de sentencias si condicion es True

    else:
    # Bloque de sentencias si condicion es False

La sentencia se evalúa de la siguiente forma: Si condición es True se ejecuta el código dentro del if y el código dentro del else se omite. Si condición es False se ejecuta el código dentro del else y el código dentro del if se omite. Cuando finaliza bien la parte del if o bien la del else el programa continua con la siguiente sentencia.

En la figura siguiente vemos la explicación de forma gráfica.

f_ifelse.png
Funcionamiento de la sentencia if...else Federico Coca Guia de Trabajo de Microbit CC-BY-SA

  1. Declaración if...elif...else. La sentencia if...else se utiliza para ejecutar un bloque de código entre dos alternativas posibles. Sin embargo, si necesitamos elegir entre más de dos alternativas, entonces utilizamos la sentencia if...elif...else. La sintaxis de la sentencia if...elif...else es:
if condicion_1:
    # Bloque 1
elif condicion_2:
    #Bloque 2

    else:
    # Bloque 3

Se evalúa así: Si condicion_1 es True, se ejecuta Bloque 1. Si condicion_1 es False, se evalúa condicion_2. Si condicion_2 es True, se ejecuta Bloque 2. Si condicion_2 es False, se ejecuta Bloque 3.

En la figura siguiente vemos la explicación de forma gráfica.

f_ifelifelse.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Funciones en Python

En esta sección vamos a dar solamente una breve introducción a lo que son las funciones y los módulos en Python para estudiar dos funciones concretas definidas en MicroPhyton para micro:bit.

Una función es un bloque de código que realiza una tarea específica.

Supongamos que necesitas crear un programa para crear un círculo y colorearlo. Puedes crear dos funciones para resolver este problema:

Dividir un problema complejo en trozos más pequeños hace que nuestro programa sea fácil de entender y reutilizar.

Existen dos tipos de funciones en Python:

La sintaxis de una función es la siguiente:

def nombre_funcion(argumentos):
    #Cuerpo de la función

    return

Donde,

Veamos un ejemplo sencillo que no manda parametros ni retorna nada.

def saludo():
    print("Hola Mundo!")

saludo() #Llama a la función
print("Programa")
saludo()
print("Otra vez programa")

Va a generar como salida la cadena "Hola Mundo!" seguida de la cadena "Programa" seguida otra vez de "Hola Mundo!" y finaliza con "Otra vez programa".

Cuando se llama a la función, el control del programa pasa a la definición de la función, se ejecuta todo el código dentro de la función y despés el control del programa salta a la siguiente sentencia después de la llamada a la función.

Como ya se ha mencionado, una función también puede tener argumentos. Un argumento es un valor aceptado por una función. Cuando creamos una función con argumentos necesitamos pasar los correspondientes valores cuando la llamamos.

De forma genérica una función con argumentos tiene la siguiente sintaxis:

def funcion(arg1, arg2, ar3,...):
    #Código

#Llamada a la función
funcion(valor1, valor2, valor3, ...)
#Código

Cuando llamamos a la función le pasamos los valores correspondiendo valor1 a arg1, valor2 a arg2 y así sucesivamente.

La llamada a la función se puede hacer mencionando el nombre del argumento, que es lo que se conoce como 'argumentos con nombre', siendo el código totalmente equivalente al anterior.

funcion(arg1=valor1, arg2=valor2, arg3=valor3, ...)

Una función Python puede o no devolver un valor. Si queremos que nuestra función devuelva algún valor a una llamada realizada a función, utilizamos la sentencia return.

En el ejemplo siguiente se llama a la función cuatro veces con valores diferentes.

def cal_potencia(base, exponente):
    resultado = base ** exponente
    return resultado

#Llamadas a la función
print('Potencia =', cal_potencia(2,8))
print('Potencia =', cal_potencia(3,3))
print('Potencia =', cal_potencia(4,5))
print('Potencia =', cal_potencia(9,6))

El resultado es:

Potencia = 256
Potencia = 27
Potencia = 1024
Potencia = 531441

En Python, las funciones de la biblioteca estándar son las funciones incorporadas que se pueden utilizar directamente en nuestro programa. Por ejemplo,

Estas funciones están definidas dentro de un módulo. Y, para utilizarlas debemos incluir dicho módulo en nuestro programa. Por ejemplo, sqrt() y pow() están definidos en el módulo math. Para usar las funciones podemos hacer como en el ejemplo siguiente:

import math #Carga el módulo math

raiz = math.sqrt(25)
print("La raiz cuadrada de 25 es ", raiz)

potencia = pow(2, 8)
print("2^8 =", potencia)

En el ejemplo la variable raiz contendrá el cálculo de la raiz cuadrada y se define por defecto como variable real o decimal y potencia contendrá el resultado de elevar a 8 el número 2. Los resultados obtenidos son:

La raiz cuadrada de 25 es 5.0
2^8 = 256

Las principales ventajas de utilizar funciones son:

Módulos en Python

A medida que nuestro programa crece, puede contener muchas líneas de código. En lugar de poner todo en un solo archivo, podemos utilizar módulos para separar por funcionalidad los códigos en varios archivos. Esto hace que nuestro código quede organizado y sea más fácil de mantener.

Un módulo es un archivo que contiene código para realizar una tarea específica. Un módulo puede contener variables, funciones, clases, etc. Veamos un ejemplo, vamos a crear un módulo escribiendo algo como lo siguiente:

#Definición del módulo suma

def sumar(a, b):

    resultado = a + b
    return resultado

Guardamos este programa en un archivo, por ejemplo modulo_sumar.py y tendremos definida una función de nombre sumar en ese módulo. La función recibe dos valores y devuelve la suma.

Cuando, en un programa diferente, queramos sumar dos números podemos importar la definición creada utilizando la palabra reservada import. Para acceder a la función definida en el módulo tenemos que utilizar el operador . (punto). Se parece mucho a que el módulo es una clase y la función una instancia de esa clase.

# Programa de sumas
import modulo_sumar

modulo_sumar.sumar(4, 5) #devolverá 9

Python tiene mas de 200 módulos estándar que pueden ser importados de la misma manera que importamos los módulos definidos por nosotros. En la documentación de Python en español encontramos la referencia a La biblioteca estándar de Python.

Números aleatorios

Este módulo está basado en el módulo random de la librería estándar de Python. Contiene funciones para generar comportamientos aleatorios.

Para acceder a este módulo es necesario:

import random

Vamos a ver sus funciones a continuación.

random.getrandbits(n)

.seed(n). Inicializa el generador de números aleatorios con un número entero conocido "n". Esto le proporcionará una aleatoriedad determinista reproducible a partir de un estado inicial dado (n).

random.seed(n)
random.randint(a, b)
random.randrange(stop)
random.randrange(start, stop)
random.randrange(start, stop, step)
random.choice(secuencia)
random.random()
random.uniform(a, b)

En la imagen vemos ejemplos ejecutados en la shell.

func_random.png

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

 

Introducción

Para saber más Python

Curso completo de Python 222pag pdf Descargar
Curso completo de Python 422pag Descargar
Curso completo de Python desde 0  Ver
Curso de Python desde 0 Ver
Manual de referencia Python Ver
Programación en Python Ver
Trabajando con ficheros en Python Ver
Programación orientada a objeto en Python Ver
un manual para aquellos usuarios con previos conocimientos de Python, como la programación modular y orientada a objetos.
También algunos conocimientos de las librerías tkinter  (Para crear interfaces gráficos y SQlite3 (para gestionar bases de datos).
Descargar

Agradecimientos a Pere Manel http://peremanelv.com

Empezando

Empezando

Hola Mundo

No hay mejor manera para empezar que este sencillo programa

  1. Entramos en https://python.microbit.org/
  2. Nos vamos a la pestaña de Reference - Loops y arrastramos el código de While loops infinite
  3. Cambiamos el texto por "Hola Mundo" y lo simulamos en el microbit virtual de la izquierda
  4. ¿Lo ha hecho bien? pues conecta tu microbit a tu ordenador, y Sent to Microbit te saldrá un diálogo pidiendo vincular tu microbit, acepta y ya esta !!!!

2024-09-14 13_48_48-Configuración.png

El código Pytho que ha subido a Microbit es el siguiente, la primera línea importa las librerías para manejar microbit, la segunda es el bucle While y al poner la condición true, se ejecutará siempre, y la instrucción que ejecuta es display.scroll donde visualiza en forma de marquesina el texto que pongamos, también puede ser un número.

from microbit import *


while True:
    display.scroll('Hola Mundo')

Empezando

Imágenes

Extraído de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

API: Display

Control de la matriz de 5x5 LEDs que en micro:bit se conoce como pantalla. Los métodos de la clase son:

display.get_pixel(x, y) #1
display.set_pixel(x, y, val) #2
display.clear() #3
display.show(image, delay=0, wait=True, loop=False, clear=False) #4
display.scroll(string, delay=400) #5
'''
1 Obtiene el brillo [0 (apagado) a 9 (máx))] del pixel (x,y)
2 Establece el brillo [0 (apagado) a 9 (máx))] del pixel (x,y)
3 Borra (apaga) la pantalla
4 Muestra la imagen
5 Desplaza una cadena por la pantalla a la velocidad en ms del *delay*
'''

En ambos casos de la API existen otras muchas opciones no incluidas. La funcionalidad de autocompletar nos ayudará para no tener que recordar la sintaxis y conocer las que no aparece aquí. En la animación siguiente vemos un ejemplo de ambos casos.

logicos.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Imágenes

MicroPython nos ofrece muchas imágenes integradas para mostrar por pantalla y podemos crear efectos interesantes. Mediante la característica de autocompletar se nos van a mostrar todas las definidas que están listadas en la documentación oficial. Ya hemos visto como cargar una imagen, lo que puedo aconsejar en este momento es realizar el ejercicio de mostrar cada una de las disponibles para familiarizarnos con ellas.

Es perfectamente posible crar nuestras propias imágenes configurando cada Pixel o LED de la pantalla. También es posible crear animaciones con imágenes.

Imágenes DIY

Crear nuestras propias imágenes va a resultar una tarea sencilla cuando conozcamos la información para hacerlo. Cada pixel (LED) de la pantalla se puede configurar con diez valores que pueden tomar un valor entre 0 (cero) y 9 (nueve). Cuando le damos valor 0 (cero) es decirle literalmente que el brillo es nulo y sin embargo cuando le damos el valor 9 (nueve) lo ponemos al máximo de brillo posible. Podemos jugar con todos los valores intermedios para crear niveles de brillo.

La forma mas sencilla de definir una imagen consiste en utilizar la clase microbit.Image para crearla a partir de una cadena o string que devuelva el pictograma. Es decir utilizando el comando Image(string) teniendo que constar de dígitos con los valores 0 a 9 indicados. Para verlo rápidamente hacemos el ejemplos de dibujar una X en relieve asignándola a una variable.

mi_imagen_X = Image("90009:"
                    "06060:"
                    "00300:"
                    "06060:"
                    "90009")

Los dos puntos indican un salto de línea por lo que se puede usar el ASCII no imprimible "\n" que es precisamente eso, un salto de línea.

mi_imagen_X = Image("90009\n"
                    "06060\n"
                    "00300\n"
                    "06060\n"
                    "90009")

Los valores de brillo dan la sensación de relieve de profundidas a la X.

En cualquier caso esto no se escribe normalmente así, salvo para hacer mas o menos un gráfico del pixelado, sino en una sola línea.

mi_imagen_X = Image("90009\n06060\n00300\n06060\n90009")

Ahora parece mas elegante utilizar los dos puntos como indicador de salto de línea.

mi_imagen_X = Image("90009:06060:00300:06060:90009")

En la imagen vemos el resultado de lo explicado.

mi_X_relieve.png
Imagen de una X en relieve
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Este es el código creado:

from microbit import * 
"""mi_imagen_X = Image("90009\n"
                       "06060\n"
                       "00300\n"
                       "06060\n"
                       "90009")"""
#mi_imagen_X = Image("90009\n06060\n00300\n06060\n90009")
mi_imagen_X = Image("90009:06060:00300:06060:90009")
display.show(mi_imagen_X)
Animar imágenes

En micro:bit Python ya disponemos de un par de listas de imágenes incorporadas que se llaman

Image.ALL_Clocks
Image.ALL_ARROWS

Estas dos ordenes hacen que MicroPython entienda que necesita mostrar cada imagen de la lista, una tras otra.

Cuando queremos mostrar en la pantalla una imagen se nos muestra la siguiente ayuda contextual:

ayuda_disp_show.png
Ayuda contextual para display.show()
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

donde nos indica claramente que image puede ser una cadena, un número, una imagen o una lista de imágenes. Además aparecen las opciones que podemos configurar.

Con esta información crear un "reloj" que esté continuamente marcando cada hora es bastante sencillo, basta con poner el siguiente código y darle a simular.

# Imports go at the top
from microbit import *
display.show(Image.ALL_CLOCKS, delay=400, loop=True)

En la animación vemos el funcionamiento de este "reloj".

ayuda_disp_show.png

Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Si cambiamos el reloj por las flechas veremos como van rotando flechas en ángulos de 45 grados.

ayuda_disp_show.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Para animar nuestras propias imágenes tendremos que crear cada una sobre un lienzo de 5x5 pixeles y establecer las diferencias para crear la animación. Podemos crear tantas imágenes como creamos oportuno. Creamos una lista con todas las imágenes en el orden que se tienen que reproducir y ya podemos mostrar nuestra lista en la pantalla.

En la animación siguiente vemos un efecto creado de esta forma.

ayuda_disp_show.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Este es el código para crear la animación.

# Imports go at the top
from microbit import *
display.clear()
cor1=Image("90000:90000:90000:90000:90000")
cor2=Image("79000:79000:79000:79000:79000")
cor3=Image("57900:57900:57900:57900:57900")
cor4=Image("35790:35790:35790:35790:35790")
cor5=Image("13579:13579:13579:13579:13579")
cor6=Image("01357:01357:01357:01357:01357")
cor7=Image("00135:00135:00135:00135:00135")
cor8=Image("00013:00013:00013:00013:00013")
cor9=Image("00001:00001:00001:00001:00001")
cor10=Image("00000:00000:00000:00000:00000")
todas_las_cortinas=[cor1,cor2,cor3,cor4,cor5,cor6,cor7,cor8,cor9,cor10]
display.show(todas_las_cortinas, delay=100, loop=True)

Funciones para la pantalla

Si wait es True, esta función se bloqueará hasta que la animación termine, de lo contrario la animación ocurrirá en segundo plano.

Si loop es True, la animación se repetirá para siempre.

Si clear es True, la pantalla se borrará después de que las iteraciones hayan terminado.

Los argumentos waitloop y clear deben especificarse utilizando su palabra clave.

Si wait es True, esta función se bloqueará hasta que la animación termine, de lo contrario la animación ocurrirá en segundo plano.

Si loop es True, la animación se repetirá para siempre.

Si monospace es True, todos los caracteres ocuparán 5 columnas de píxeles de ancho, de lo contrario habrá exactamente 1 columna de píxeles en blanco entre cada carácter mientras se desplazan.

Los argumentos waitloop y monospace deben especificarse utilizando su palabra clave.

Extraído de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Empezando

Imágenes estáticas y animadas

Imágenes estáticas

Sin tocar el código anterior, vamos ahora a Display y arrastramos el código de sonrisa

2024-09-15 09_34_49-micro_bit Python Editor.png

Vamos a tocar el código para que quede de esta forma, de esta manera practicamos la edición de código

# Imports go at the top
from microbit import *


# Code in a 'while True:' loop repeats forever
while True:
    display.show(Image.SMILE)
    sleep(1000)
    display.scroll('Hola mundo')    

La sonrisa se ve un segundo = 1.000 mseg y luego ejecuta el scroll

¿¿ Qué esperas para experimentar otras imágenes ?

Imágenes animadas

Podemos poner las imágenes prediseñadas en la variable Image pero también podemos crearlas fácilmente. En el siguiente programa se define qué led de la matriz 5x5 se enciende a la máxima intensidad (0-9)

Avanzando en la programación, se definen 5 variables catedux tipo imagen, y se define una variable all_catedus que es tipo array que contienen todas.

from microbit import *

catedu1 =  Image("00900:"
                 "09000:"
                 "90000:"
                 "09000:"
                 "00900")

catedu2 =  Image("09000:"
                 "90000:"
                 "09000:"
                 "00900:"
                 "00090")

catedu3 =  Image("90000:"
                 "09000:"
                 "00900:"
                 "00090:"
                 "00009")

catedu4 =  Image("00009:"
                 "00090:"
                 "00900:"
                 "09000:"
                 "90000")

catedu5 =  Image("00090:"
                 "00900:"
                 "09000:"
                 "90000:"
                 "09000")

all_catedus = [catedu1,catedu2,catedu3,catedu2,catedu1,catedu5,catedu4]
while(True):
    display.show(all_catedus, delay=200)

O jugar con las intensidades: En este juego de luces del coche fantástico se utiliza la intensidad media 5 :

Este ejemplo de regular la intensidad del led es imposible de realizar en programación por bloques.

from microbit import *


catedu1 =  Image("00005:"
                 "00000:"
                 "00000:"
                 "00000:"
                 "00000")

catedu2 =  Image("00009:"
                 "00050:"
                 "00000:"
                 "00000:"
                 "00000")

catedu3 =  Image("00005:"
                 "00090:"
                 "00500:"
                 "00000:"
                 "00000")

catedu4 =  Image("00000:"
                 "00050:"
                 "00900:"
                 "05000:"
                 "00000")

catedu5 =  Image("00000:"
                 "00000:"
                 "00500:"
                 "09000:"
                 "50000")

catedu6 =  Image("00000:"
                 "00000:"
                 "00000:"
                 "05000:"
                 "90000")

catedu7 =  Image("00000:"
                 "00000:"
                 "00000:"
                 "00000:"
                 "50000")

all_catedus = [catedu1,catedu2,catedu3,catedu4,catedu5,catedu6,catedu7,catedu6,catedu5,catedu4,catedu3,catedu2]
while(True):
    display.show(all_catedus, delay=100)


¿No sabes lo que es el coche fantástico? eso es que no tienes la edad adecuada para la robótica 😁

También podemos hacerlo pixel a pixel y no utilizar variables tipo array

from microbit import *

display.clear()
while(True):
    for n in range(0, 5): 
        display.set_pixel(n, 3, 9)
        if (n<4):
            display.set_pixel(n+1, 3, 5)
        if (1<n):
            display.set_pixel(n-1, 3, 5)
        if (1<n):
            display.set_pixel(n-2, 3, 0)    
        sleep(200)
    for n in reversed(range(0, 5)): 
        display.set_pixel(n, 3, 9)
        if (n<4):
            display.set_pixel(n+1, 3, 5)
        if (1<n):
            display.set_pixel(n-1, 3, 5)
        if (n<3):
            display.set_pixel(n+2, 3, 0)    
        sleep(200)

Empezando

Eventos para los botones

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Si trabajamos con versiones anteriores a V2 solamente disponemos de los botones A, B y A+B, pero si tenemos una versión V2 también disponemos del botón táctil incorporado en el logo, aunque a todos los efectos este se considera un pin de entrada.

El logo no es tratado exactamente como un botón, sino como un pin de nombre logo. En el borde existen otros tres pines, los 0, 1 y 2. Por ello la forma de trabajar con el logo va a ser un poco diferente, como veremos en la actividad A04.

La diferencia fundamental, ademas de la forma, es que el logo es un sensor capacitivo y los pines son sensores resistivos. En la práctica esto significa que el logo funciona simplemente tocandolo y los pines necesitan cerrar el circuito con GND, por lo que para que funcionen como pulsador debemos tocar tanto el pinto como GND.

Si queremos que MicroPython reaccione a los eventos de pulsación de los botones, debemos ponerlo en un bucle infinito y comprobar si el botón is_pressed.

Para trabajar con los botones de la micro:bit tenemos disponibles funciones que se han cargado al importar el módulo microbit. Estas funciones están basadas en la función genérica is_pressed() pensada para saber que tecla de un teclado se ha pulsado. Sin embargo, en el caso de MicroPython a para micro:bit a estos botones se les ha asignado un nombre a cada uno, button_a para el A y button_b para el B, de manera que para usarlos se llama al botón y con el operador . a la función is_pressed(). Por ejemplo, button_a.is_pressed() es el código encargado de saber si estamos pulsando el botón A y button_b.is_pressed() si lo es el B.

Esta función retorna el total acumulado de pulsaciones de botones y restablece este total a cero antes de volver. Es decir, podemos capturar el número de veces que hemos pulsado un botón. El valor de retorno es un número, por lo que, para mostrarlo en la pantalla de LEDs hay que convertirlo en cadena con la función str().

Devuelve True o False para indicar si se ha presionado el botón desde la última vez que se inicio el dispositivo o se llamó a este método. Llamar a este método borra el estado de que ha sido pulsado, de modo que el botón debe pulsarse de nuevo antes de que este método vuelva a retornar True.

Vamos a hacer un ejemplo que aclarará mejor lo explicado. Se trata de crear un programa (le podremos de nombre Caritas_X) en el que mientras mantegamos pulsado el botón A se muestra una cara sonriente, si no se pulsa ningún botón se muestra una cara triste y si se pulsa el botón B la cara desaparece (se apagan todos los LEDs) y tras 2 segundos aparece una X que se va haciendo cada vez mas grande partiendo del punto central. Finalmente pasados otros 2 segundos el programa vuelve a empezar. El código es:

from microbit import *
while True:
    while True:
        if button_a.is_pressed():
            display.show(Image.HAPPY)
        elif button_b.is_pressed():
            break
        else:
            display.show(Image.SAD)

    display.clear()
    sleep(2000)
    mi_X_peque = Image("00000:00000:00900:00000:0000")
    display.show(mi_X_peque)
    sleep(200)
    mi_X_media = Image("00000:09090:00900:09090:0000")
    display.show(mi_X_media)
    sleep(200)
    mi_X_grande = Image("90009:09090:00900:09090:90009")
    display.show(mi_X_grande)
    sleep(2000)

En la animación siguiente vemos como funciona

f_ifelifelse.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Si observamos con cuidado apreciaremos que en algún momento se accionan los botones A y B pero los que aparecen en la parte inferior, debajo de la pantalla de simulación. Están al lado de un logotipo que indica que se pulsen con una flechita. Justo debajo de estos aparecen los citados del borde de placa y el logo junto a ellos, pues es tratado asi, como un pin, y además a su izquierda hay un candado cerrado indicativo de que no se está usando ninguno de ellos. En la imagen siguiente se ve mejor lo indicado.

control_simu.png

Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Vamos a crear otro ejemplo en el que se cuenten las veces que pulsamos el botón A o el botón B durante un tiempo de 3 segundo. El programa es el siguiente:

from microbit import *

sleep(3000) #Espera de 3 segundos

#Convertimos número a cadena con str()
pulsado = str(button_b.get_presses())

display.show(pulsado)

# Por si hemos pulsado mas de 9 veces
display.scroll(pulsado)

En la 'Referencia' del compilador, dentro de Botones tenemos un ejemplo que nos indica el botón que hemos pulsado con cuatro opciones posibles, el A, el B, A o B y finalmente A y B. Animamos a cargarlos y probarlos para familiarizarnos todo lo posible con ellos.

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Empezando

Botones

Los botones pueden dar juego, combinándolos con la instrucción if --- else

from microbit import *

while True:
    if button_a.is_pressed():
        display.show(Image.HAPPY)
    elif button_b.is_pressed():
        break
    else:
        display.show(Image.SAD)

display.clear()

Extraido de tutorial https://microbit-micropython.readthedocs.io/en/v2-docs/tutorials/buttons.html

¿Qué pasa si pulsamos el botón B ?

En el apartado Reference podemos ir a Buttons tenemos diferentes muestras de código :

2024-09-18 22_52_55-micro_bit Python Editor.png

La diferencia entre este código 

while True:
    if button_a.was_pressed():
        display.scroll('A')

y este otro código

while True:
    if button_a.is_pressed():
        display.scroll('A')

es muy sutil, no hay diferencia si apretamos el botón A  excepto si lo mantenemos pulsado

El siguiente código, visualiza el número de veces que pulsas el botón A durante 3 segundos :

from microbit import *
display.scroll('Press A')
sleep(3000)
display.scroll(button_a.get_presses())

Jugando

Jugando

Nivel de luz

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Vamos a ver como utilizar la micro:bit como detector de luz, cosa que es bastante sencilla por la pantalla de LEDs que puede actuar como sensor.

El programa es:

from microbit import *

while True:
    nivel_luz = display.read_light_level()
    uart.write(str(nivel_luz) + "\r\n")
    sleep(1000)

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Si quieres realizarlo con la microbit real, tendrás que visualizar el puerto seria, para ello necesitas instalar el programa Putty ver https://libros.catedu.es/books/microbit-y-python/page/putty


Jugando

Temperatura

La función en micropython para leer la temperatura de la placa en ºC interna y devuelve un valor entero es la siguiente

microbit.temperature()

Un programa ejemplo sería :

from microbit import *

while True:
    Temperatura = temperature()
    Frase = "T= "+str(Temperatura)+"*C "
    display.scroll(Frase)
    sleep(1000)

Jugando

Magnetómetro

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Este módulo permite acceder a la brújula electrónica incorporada. Antes de utilizarla, la brújula debe estar calibrada; de lo contrario, las lecturas pueden ser erróneas.


Advertencia. Calibrar la brújula hará que su programa se detenga hasta que se complete la calibración. La calibración consiste en un pequeño juego para dibujar un círculo en la pantalla LED girando el dispositivo.


Las funciones son:

Ejemplos de actividades con la brújula

 Antes de nada debemos calibrar la brújula para después mostrar la posición de la micro:bit utilizando las flechas predefinidas.

Brújula indicando el norte
from microbit import *

# Antes de nada calibtrar
compass.calibrate()

# Mantener la aguja apuntando aproximadamente en la dirección correcta.
while True:
    sleep(100)
    aguja = ((15 - compass.heading()) // 30) % 12
    display.show(Image.ALL_CLOCKS[aguja])
Brújula N,S,E,O

El programa, de muy poca precisión es el siguiente:

from microbit import *

compass.calibrate()
while True:
    angulo = compass.heading()
    if angulo < 45:
        display.show("N")
    elif angulo < 135:
        display.show("E")
    elif angulo < 225:
        display.show("S")
    elif angulo < 315:
        display.show("O")
    else:
        display.show("N")
Brújula a 45º

Lo que vamos a hacer ahora es localizar las siguientes ocho direcciones, separadas entre si un ángulo de 45º: noroeste (NE), oeste (O), suroeste (SO), sur (S), sureste (SE), este (E), noreste (NE), norte (N). El margen o ángulo que va a englobar cada dirección estará ajustado dentro de otro ángulo de 45º dividido en dos iguales de 22.5º respecto a la dirección principal. Un gráfico nos aclara mejor la idea

A11_brujula_MC.png

En el editor Mu también son válidas las definiciones predefinidas para las flechas.

El programa es:

from microbit import *

compass.calibrate()
while True:
    angulo = compass.heading()
    if angulo > 22.5 and angulo <= 67.5:
        display.show(Image.ARROW_NE)
    elif angulo > 67.5 and angulo <= 112.5:
        display.show(Image.ARROW_E)
    elif angulo > 112.5 and angulo <= 157.5:
        display.show(Image.ARROW_SE)
    elif angulo > 157.5 and angulo <= 202.5:
        display.show(Image.ARROW_S)
    elif angulo > 202.5 and angulo <= 247.5:
        display.show(Image.ARROW_SW)
    elif angulo > 247.5 and angulo <= 292.5:
        display.show(Image.ARROW_W)
    elif angulo > 292.5 and angulo <= 337.5:
        display.show(Image.ARROW_NW)
    elif angulo > 337.5 and angulo <= 22.5:
        display.show(Image.ARROW_N)
Brújula indicando el norte

En este se intenta simplemente visualizar una aguja que apunte al norte

from microbit import *

# Antes de nada calibtrar
compass.calibrate()

# Mantener la aguja apuntando aproximadamente en la dirección correcta.
while True:
    sleep(100)
    aguja = ((15 - compass.heading()) // 30) % 12
    display.show(Image.ALL_CLOCKS[aguja])

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Jugando

Acelerómetro

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Este objeto permite acceder al acelerómetro de la placa.

Por defecto MicroPython establece el rango del acelerómetro en ± 2000 mg (siendo g una unidad de aceleración basada en la gravedad estándar), que configura los valores máximo y mínimo devueltos por las funciones del acelerómetro. El rango puede cambiarse mediante microbit.accelerometer.set_range().

El acelerómetro también proporciona funciones de conveniencia para detectar gestos. Los gestos reconocidos se representan como cadenas: arriba (up), abajo (down), izquierda (left), derecha (right), boca arriba (face up), boca abajo (face down), caída libre (freefall), 3g, 6g, 8g, sacudida (shake).


Nota: Los gestos no se actualizan en segundo plano por lo que es necesario realizar llamadas constantes a algún método del acelerómetro para realizar la detección de gestos. Normalmente los gestos pueden ser detectados usando un bucle con un pequeño retardo microbit.sleep().


Sus funciones son:

A continuación vamos a ver los ejemplos que aparecen en la documentación oficial traducidos.

Trazador gráfico de aceleraciones

El programa lo vamos a hacer en el editor Mu para aprovechar su trazador gráfico.

from microbit import *

while True:
    uart.write(str(accelerometer.get_values()) + "\r\n")
    sleep(1000)

Ponemos en marcha el trazador, y la comunicación serie REPL después de flashear el programa. Hacemos reset de la micro:bit y podemos ver la evolución de las lecturas con los movimientos de la placa.

A11_brujula_MC.png

Gradiometro

En este programa se ve como si la luz pesara:

El programa es:

from microbit import *
# El brillo estara entre 0 y 9
brillo = 9 
# La funcion mapear ajusta los valores 
# leidos y los lleva al rango 0-4.
def mapear(valor):   
    if valor < -500:
        valor=-500
    elif valor > 500:
        valor=500
    valor=(valor+500)/250
    return int(valor)

while True:
    # Lee la aceleración en x e y con un
    #rango que va de -2000 a 2000.
    roll_x = accelerometer.get_x()
    pitch_y = accelerometer.get_y()
    # No necesitamos un rango tan amplio por
    # eso lo bajamos de -500 a 500
    x=mapear(roll_x)
    y=mapear(pitch_y)
    display.clear()
    display.set_pixel(x, y, brillo)
    sleep(500)
Bola mágica

Una bola 8 mágica que adivina el futuro. Haz una pregunta y agita el dispositivo para obtener una respuesta.

# Magic 8 ball by Nicholas Tollervey. February 2016.
# Bola mágica 8 por Nicholas Tollervey. Febrero 2016.
# Ask a question then shake.
# Haz una pregunta y agita la micro:bit
# This program has been placed into the public domain.
# Este programa es de dominio público.

from microbit import *
import random

respuestas = [
    "Es cierto",
    "Es decididamente así",
    "Sin duda alguna",
    "Sí, definitivamente.",
    "Puedes confiar en ello",
    "Como yo lo veo, sí",
    "Lo más probable",
    "Buenas perspectivas",
    "Si",
    "Los indicios apuntan a que sí",
    "Respuesta dudosa inténtalo de nuevo",
    "Vuelve a preguntar más tarde",
    "Mejor no te lo digo ahora",
    "No se puede predecir ahora",
    "Concéntrate y vuelve a preguntar",
    "No cuentes con ello",
    "Mi respuesta es no",
    "Mis fuentes dicen que no",
    "Perspectivas no tan buenas",
    "Muy dudoso",
]

while True:
    display.show('8')
    if accelerometer.was_gesture('shake'):
        display.clear()
        sleep(1000)
        display.scroll(random.choice(respuestas))
    sleep(10)
Juego evita obstáculos

 Un juego consistentente en evitar obstáculos moviendo la micro:bit.

# Simple Slalom by Larry Hastings, September 2015
# Eslalon simple de Larry Hastings, septiembre de 2015.
# This program has been placed into the public domain.
# Este programa es de dominio público.
import microbit as m
import random

p = m.display.show
min_x = -1024
max_x = 1024
range_x = max_x - min_x
wall_min_speed = 400
player_min_speed = 200
wall_max_speed = 100
player_max_speed = 50
speed_max = 12

while True:

    i = m.Image('00000:'*5)
    s = i.set_pixel
    player_x = 2
    wall_y = -1
    hole = 0
    score = 0
    handled_this_wall = False
    wall_speed = wall_min_speed
    player_speed = player_min_speed
    wall_next = 0
    player_next = 0

    while True:
        t = m.running_time()
        player_update = t >= player_next
        wall_update = t >= wall_next
        if not (player_update or wall_update):
            next_event = min(wall_next, player_next)
            delta = next_event - t
            m.sleep(delta)
            continue

        if wall_update:
            # calculate new speeds
            speed = min(score, speed_max)
            wall_speed = wall_min_speed + int((wall_max_speed - wall_min_speed) * speed / speed_max)
            player_speed = player_min_speed + int((player_max_speed - player_min_speed) * speed / speed_max)
            wall_next = t + wall_speed
            if wall_y < 5:
                # erase old wall
                use_wall_y = max(wall_y, 0)
                for wall_x in range(5):
                    if wall_x != hole:
                        s(wall_x, use_wall_y, 0)
        wall_reached_player = (wall_y == 4)
        if player_update:
            player_next = t + player_speed
            # find new x coord
            x = m.accelerometer.get_x()
            x = min(max(min_x, x), max_x)
            # print("x accel", x)
            s(player_x, 4, 0) # turn off old pixel
            x = ((x - min_x) / range_x) * 5
            x = min(max(0, x), 4)
            x = int(x + 0.5)
            # print("have", position, "want", x)
            if not handled_this_wall:
                if player_x < x:
                    player_x += 1
                elif player_x > x:
                    player_x -= 1
            # print("new", position)
            # print()
        if wall_update:
            # update wall position
            wall_y += 1
            if wall_y == 7:
                wall_y = -1
                hole = random.randrange(5)
                handled_this_wall = False
            if wall_y < 5:
                # draw new wall
                use_wall_y = max(wall_y, 0)
                for wall_x in range(5):
                    if wall_x != hole:
                        s(wall_x, use_wall_y, 6)
        if wall_reached_player and not handled_this_wall:
            handled_this_wall = True
            if (player_x != hole):
                # collision! game over!
                break
            score += 1
        if player_update:
            s(player_x, 4, 9) # turn on new pixel
        p(i)
    p(i.SAD)
    m.sleep(1000)
    m.display.scroll("Score:" + str(score))
    while True:
        if (m.button_a.is_pressed() and m.button_a.is_pressed()):
            break
        m.sleep(100)

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA


 

Jugando

Micrófono

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

ATENCIÓN SÓLO VÁLIDO PARA PLACAS V2

Este objeto permite acceder al micrófono integrado disponible en micro:bit V2. Se puede utilizar para responder al sonido. La entrada del micrófono se encuentra en la parte frontal de la placa junto a un LED de actividad del micrófono, que se ilumina cuando el micrófono está en uso.

microfono.png
Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

El micrófono puede responder a un conjunto predefinido de eventos sonoros que se basan en la amplitud y la longitud de onda del sonido. Están representados por instancias de la clase SoundEvent, accesibles a través de variables en microbit.SoundEvent:

Las funciones disponibles son:

Sonómetro

No estaría nada mal poner esto en clase, comedores...

from microbit import *

# definicion funcion mapea para cambiar un rango de valores a otro
def mapea(valor, deMin, deMax, aMin, aMax):
    deRango = deMax - deMin
    aRango = aMax - aMin
    valorEsc_de = float(valor - deMin)/float(deRango)
    valorEsc_a = aMin + (valorEsc_de * aRango)
    return valorEsc_a

# Creamos los imagenes para el grafico de barras
grafico5 = Image("99999:"
                 "99999:"
                 "99999:"
                 "99999:"
                 "99999")

grafico4 = Image("00000:"
                 "99999:"
                 "99999:"
                 "99999:"
                 "99999")

grafico3 = Image("00000:"
                 "00000:"
                 "99999:"
                 "99999:"
                 "99999")

grafico2 = Image("00000:"
                 "00000:"
                 "00000:"
                 "99999:"
                 "99999")

grafico1 = Image("00000:"
                 "00000:"
                 "00000:"
                 "00000:"
                 "99999")

grafico0 = Image("00000:"
                 "00000:"
                 "00000:"
                 "00000:"
                 "00000")

graficos = [grafico0, grafico1, grafico2, grafico3, grafico4, grafico5]

# ignora el primer nivel de sonido leido
nivelSonido = microphone.sound_level()
sleep(200)
# establece un umbral para el nivel de sonido
umbral = microphone.set_threshold(SoundEvent.LOUD, 125)
while True:
    # si el umbral es superado se muestra una carita triste
    if microphone.sound_level() >= 125:
        display.show(Image.SAD)
        sleep(1000)
    else:
        # mapear nivel de sonido de 0-255 a 0-5 para escoger gráfico
        nivelSonido = int(mapea(microphone.sound_level(), 0, 255, 0, 5))
        display.show(graficos[nivelSonido])

Uso de las API

Un ejemplo que utiliza algunas de las funciones de la API del micrófono es:

'''Prueba básica del micrófono.  
Boton A: actualizar pantalla cuando se escucha un sonido alto o bajo. 
Botón B: actualizar la pantalla cuando se escucho un sonido alto o bajo. 
Al agitarla: se muestran los últimos sonidos escuchados, para intentar esta prueba 
se hace un sonido fuerte y uno silencioso antes de agitar.'''

from microbit import *

display.clear()
sound = microphone.current_event()

while True:
    if button_a.is_pressed():
        if microphone.current_event() == SoundEvent.LOUD:
            display.show(Image.SQUARE)
            uart.write('Es Fuerte\n')
        elif microphone.current_event() == SoundEvent.QUIET:
            display.show(Image.SQUARE_SMALL)
            uart.write('Es Silencio\n')
        sleep(500)
    display.clear()
    if button_b.is_pressed():
        if microphone.was_event(SoundEvent.LOUD):
            display.show(Image.SQUARE)
            uart.write('Fue Fuerte\n')
        elif microphone.was_event(SoundEvent.QUIET):
            display.show(Image.SQUARE_SMALL)
            uart.write('Fue silencioso\n')
        else:
            display.clear()
        sleep(500)
    display.clear()
    if accelerometer.was_gesture('shake'):
        sounds = microphone.get_events()
        soundLevel = microphone.sound_level()
        print(soundLevel)
        for sound in sounds:
            if sound == SoundEvent.LOUD:
                display.show(Image.SQUARE)
            elif sound == SoundEvent.QUIET:
                display.show(Image.SQUARE_SMALL)
            else:
                display.clear()
            print(sound)
            sleep(500)

En la consola serie vemos algunos resultados:

consola_ejem_micr.png
Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

Se ve mejor con un vídeo, pero con el simulador que nos muestra la cantidad de sonido:

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Jugando

Radio

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

El módulo de radio permite que los dispositivos trabajen juntos a través de redes inalámbricas sencillas.

El módulo de radio es conceptualmente muy sencillo:

Para acceder a este módulo se necesita:

Las constantes son:

Las funciones disponibles son:


Nota Una velocidad de datos menor de 250 kbit/seg es compatible con micro:bit V1, y puede ser posible con micro:bit V2, pero no se garantiza que funcione en todos los dispositivos. Para acceder a esta característica oculta para la compatibilidad con V1 ponemos 2 en el argumento data_rate.


Si no se llama a config se asumen los valores por defecto descritos anteriormente.

Los tres valores de la tupla representan:

Envío de la temperatura

Vamos a enviar la temperatura medida por la placa y en el valor recibido vamos a calcular la diferencia entre la temperatura de la placa que recibe y la que envía, estableciendo así la diferencia de temperaturas entre, por ejemplo, una zona al sol y otra a la sombra.

El código es el siguiente

El código del programa es el siguiente:

from microbit import *
import radio
radio.on()
radio.config(channel=50, group=90)

while True:
    if button_a.is_pressed():
       radio.send(str(temperature()))
    recibido = radio.receive()
    if recibido is not None:
        display.show(recibido)
        sleep(50)
    display.clear()

El resultado (se visualiza en Makecode que permite una simulación en dos placas que https://python.microbit.org/ no permite)


A11_brujula_MC.png
Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

Enviar "Agitar" cuando se agita

vamos a realizar una especie de juego en el que se envía el mensaje "agitar (shake)" a un grupo de micro:bits (podemos poner otras en un grupo diferente) cuando se realiza justamente ese gesto. Usaremos uno de los botones para salir del programa.

El código del programa es el siguiente:

from microbit import *
import radio
radio.on()
radio.config(channel=50, group=90)

while True:
    if accelerometer.is_gesture('shake'):
        radio.send("Agitar")
    recibido = radio.receive()
    if recibido is not None:
        display.show(recibido)
        sleep(50)
    display.clear()

El resultado (se visualiza en Makecode que permite una simulación en dos placas que https://python.microbit.org/ no permite)

A11_brujula_MC.png
Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Hackeando

Hackeando

Pines de Entrada/salida

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

En MicroPython, cada pin en la BBC micro:bit está representado por un objeto llamado pinN, donde N es el número del pin.

Por ejemplo, para usar el pin etiquetado 0 (cero), puedes usar el objeto llamado pin0 en tu script. El pin del logo V2 utiliza pin_logo.

Estos objetos tienen varios métodos asociados dependiendo de lo que el pin específico es capaz de hacer, por ejemplo, leer, escribir o tocar.

Quizá lo mas sencillo que podemos hacer es comprobar que los pines 0, 1 y 2 del borde de placa son táctiles. Haremos como ejemplo que al tocar cualquiera de ellos la micro:bit sonria y si no se toca ningúno que esté triste. Le hacemos cosquillas a la micro:bit. El programa es:

from microbit import *
"""
pin0.set_touch_mode(pin0.CAPACITIVE)
pin1.set_touch_mode(pin0.CAPACITIVE)
pin2.set_touch_mode(pin0.CAPACITIVE)
"""
while True:
    if (pin0.is_touched() or pin1.is_touched() or pin2.is_touched()):
        display.show(Image.HAPPY)
    else:
        display.show(Image.SAD)

En la animación vemos el funcionamiento del programa.

pinout.png
Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

Si descargamos firmware en una placa para probar el programa debemos saber que no basta con tocar alguno de los pines con una mano, hay que tocarlo simultaneamente con la otra mano en GND para cerrar el circuito eléctrico.

En la última versión de micro:bit V2 es posible cambiar el comportamiento predeterminado de la patilla, de modo que no sea necesario tocar GND. En los programas siguientes el código que hace esto está comentado por lo que si queremos probarlo debemos eliminar esos comentarios. Recordemos que por defecto los pines del conector de borde son sensores táctiles resistivos mientras que el pin logo V2 es capacitivo.

Pines digitales

Podemos utilizar los pines 0, 1 y 2 del borde de placa en modo digital tanto para leer su valor como para escribir o establecer su valor. Esto se representa con un "1" lógico (sin las comillas) si están activados o los queremos activar y un "0" lógico si están desactivados o los queremos desactivar.

Si queremos escribir en ellos los pines estarán actuando como salidas y tenemos que invocar al método write para hacerlo. Las sentencias, para un pin genérico "N" son:

pinN.write_digital(1) #Salida en estado alto
pinN.write_digital(0) #Salida en estado bajo

También podemos conectar, por ejemplo un interruptor o botón pulsador al pin (veremos como hacerlo en la siguiente actividad) y comprobar si el interruptor está abierto (0) o cerrado (1). En este caso los pines estarán configurados como entradas y la lectura de su estado se obtiene invocando el método read. Las sentencias, para un pin genérico "N" son:

pinN.read_digital() #Devuelve el estado 0 o 1 del pin N

Nunca se conecta nada a los pines con un voltaje superior a 3v porque se puede dañar la micro:bit.

Pines analógicos

Podemos utilizar los pines 0, 1 y 2 del borde de placa en modo analógico tanto para leer su valor como para escribir o establecer su valor. Esto significa que en lugar de estar activos o inactivos (0 o 1), varían su valor entre 0 y 1023.

Si queremos escribir en ellos los pines estarán actuando como salidas y tenemos que invocar al método write para hacerlo. La sentencia, para un pin genérico "N" es:

pinN.write_analog(valor) #valor puede estar entre 0 y 1023

Si conectamos sensores o actuadores analógicos a los pines podemos leer su valor invocando a read. La sentencia, para un pin genérico "N" es:

pinN.read_analog(valor) #valor puede estar entre 0 y 1023

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Hackeando

Input output

Una manera rápida de probar las entradas y salidas de microbit es utilizar el código predefinido que hay en reference

Si entramos en simulación, al pulsar sobre el PIN0 se visualiza 0 en el display

2024-09-22 14_25_04-micro_bit Python Editor.png

Podemos ahora usar bloques lógicos para tener otras posibilidades:

# Imports go at the top
from microbit import *
while True:
    if pin0.is_touched():
        display.show(Image.HEART)
    else:
        display.show(Image.NO)

Hackeando

Música predefinida o crea tu música

SALIDAS DE AUDIO

La placa Microbit v2 tiene un altavoz incorporado que se puede anular o activar con la instrucción speaker.on() o speaker.off() 

La salida de audio también sale por el pin0, de tal manera que si conectamos un altavoz o headphone, y tenemos speaker.on() se oirá por los sitios, si lo tienes en off sólo por el buzzer/headphones exterior:

435692553_1.png
headphones_1.png
Fuente https://www.teachwithict.com/microbit-music-python.html

BBC micro:bit "Magic 8-Ball" lesson is licenced under a Creative Commons Attribution 4.0 International License.

Ojo, hay que conectar un buzzer pasivo, es decir, que reproduce la señan analógica en sonido (o sea un altavoz normal y corriente)

si quieres conectar un buzzer activo, reproduce un tono (prederminado) al suministrarle un 1, el siguiente código sonaría una alarma:

from microbit import *
while True:
    pin0.write_digital(1)
    sleep(500)
    pin0.write_digital(0)
    sleep(500)

En los siguientes ejemplo usaremos siempre buzzer pasivo. Si no te queda claro lo que es un buzzer activo y un pasivo, mira esta página

CREA TUS EFECTOS

Puedes crear los efectos utilizando rangos de frecuencias, aquí en el ejemplo la función pitch reproduce durante 6mseg las frecuencias de medio 880 , aguda 1760 y grave 16  y luego lo mismo pero en orden decreciente, y así sucesivamente para dar el efecto de sirena.

import music
from microbit import *
display.show(Image.GHOST)
while True:
    for freq in range(880, 1760, 16):
        music.pitch(freq, 6)
    for freq in range(1760, 880, -16):
        music.pitch(freq, 6)

Extraído de https://microbit-micropython.readthedocs.io/en/v2-docs/tutorials/music.html#sound-effects

MUSICA PREDEFINIDA

En Reference- Sound tienes muchos tonos predefinidos para experimentar:

2024-09-24 13_13_12-micro_bit Python Editor.png

Si tienes la microbit v2 tienes otros en "Expressive sounds"  como audio.play(Sound.TWINKLE)

También puede hablar, arrastra el código que tienes en Refernce-Sound- Speech, pero no lo intentes en español, no se entiende nada

import speech
from microbit import *
display.show(Image.FABULOUS)
speaker.on()
set_volume(255)
speech.say('Hello, How are you? Do you sign up in online course in CATEDU.ES ?')
audio.play(Sound.TWINKLE)

CONSTRUYENDO TU MÚSICA

Tienes que añadir la librería music y componer las notas según la notación americana :

2024-09-24 12_45_51-Making music with the micro_bit - MicroPython version - teachComputing.png
Fuente https://www.teachwithict.com/microbit-music-python.html
BBC micro:bit "Magic 8-Ball" lesson is licenced under a Creative Commons Attribution 4.0 International License.

La duración (si no se pone, sigue con la duración anterior) 

2024-09-24 12_46_47-Making music with the micro_bit - MicroPython version - teachComputing.png
Fuente https://www.teachwithict.com/microbit-music-python.html
BBC micro:bit "Magic 8-Ball" lesson is licenced under a Creative Commons Attribution 4.0 International License.

Se puede poner incluso sostenidos, por ejemplo C#4:4 o f#5:4

Si quieres poner descansos es con la letra r seguido de su duración por ejemplo r:4 r:2

Un ejemplo

Tono Nokia (arriba la duración)
image.png

El código sería:

from microbit import *
import music

tune = ["e5:2","d5","f#4:4","g#4","c#5:2","b4","d4:4","e4","b4:2","a4","c#4:4","e4","a4:12"]

music.play(tune)

Otro ejemplo, el código lo tienes en https://microbit-micropython.readthedocs.io/en/v2-docs/music.html

Hackeando

Musica

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

MicroPython de BBC micro:bit viene acompañado de un potente módulo de música y sonido. Es muy fácil generar pitidos y zumbidos desde el dispositivo conectando un altavoz o unos auriculares con cable, o utilizando el altavoz integrado si estamos con una versión V2.

La forma de conectar unos auriculares está descrita en el apartado de MakeCode. También se puede conectar un zumbador piezoeléctrico pasivo o un altavoz con pinzas de cocodrilo. Estos elementos pueden estar polarizados por lo que tendremos que comprobar si existe un terminal "+", y si es así conectar al pin0.

conex_pasivo.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Nota: Debemos asegurarnos de que el zumbador es pasivo y no activo, que tan solo puede reproducir un tono. En el apartado 'Componentes discretos' de Conceptos técnicos podemos encontrar como distinguirlos.


Para trabajar con música hacemos:

import music
music.play(music.NYAN)

Tenemos que importar módulo music que contiene los métodos para crear y controlar el sonido.

La función de autocompletado de MicroPython nos muestra las melodías incorporadas.

melodias_up.png
Federico Coca Guia de Trabajo de Microbit CC-BY-SA

En la referencia de la API podemos encontrar mas inforamción en inglés sobre Music

Cada nota tiene un nombre como Do# (C#) o Fa (F), una octava, que indica lo alta o baja que debe tocarse y una duración. Las octavas se indican con un número, siendo 0 la octava más baja, 4 la del Do central y 8 es la más alta. Las duraciones también se expresan con números. Estos valores están relacionados entre sí: por ejemplo, una duración de 4 es el doble que una duración de 2 (y así sucesivamente). Si utilizamos como nombre de nota R, MicroPython reproducirá un silencio de la duración especificada.

Cada nota se expresa como una cadena de caracteres como ésta:

Nombre_nota[octave][:duration] #La1:4 (A1:4) es un La en la octava 1 con una duración de 4

Crear listas de notas para hacer una melodia es similar a crear una animación con una lista de imágenes. En el ejemplo vemos como sería la apertura de "Frere Jaques":

import music

frere_jaques_o = ["C4:4", "D4:4", "E4:4", "C4:4", "C4:4", "D4:4", "E4:4", "C4:4",
        "E4:4", "F4:4", "G4:8", "E4:4", "F4:4", "G4:8"]
music.play(frere_jaques_o)

El ejemplo se puede re-escribir como vemos a continuación ya que los valores de octava y duración se rpiten hasta que se indique un cambio.

import music

frere_jaques_o = ["C4:4", "D", "E", "C", "C", "D", "E", "C", "E", "F", "G:8",
        "E:4", "F", "G:8"]
music.play(frere_jaques_o)

MicroPython nos permite crear tonos que no son notas musicales. Por ejemplo, este código crea un efecto de sirena de policía:

import music

while True:
    for frecuencia in range(880, 1760, 16):
        music.pitch(frecuencia, 6)
    for frecuencia in range(1760, 880, -16):
        music.pitch(frecuencia, 6)

El método music.pitch utiliza una frecuencia que puede ser la de una nota musical. En los rangos de frecuencia se especifican los tonos de los sonidos de una sirena como "valor inicial, valor final y paso". Cuando el paso en positivo sube el tono y cuando es negativo lo baja.

El ejemplo también nos muestra como anidar distintos tipos de bucle.

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

 

Hackeando

Putty

Putty es un programa que nos permite realizar comunicaciones, normalmente se usa en protocolo SSH, por ejemplo comunicarte con tu PC y con tu Raspberry con la ventana de comandos

Pero aparte del protocolo SSH también permite la comunicación serie, que con la Microbit es lo que vamos a utilizar:

INSTALAR PUTTY EN LINUX

Actualizamos la lista de paquetes con sudo apt update podemos comprobar qué versión de Putty esta disponible con apt show putty e instalar Putty con el comando sudo apt install putty -y.

Si se quiere desinstalar sudo apt purge putty -y

INSTALAR PUTTY EN WINDOWS

Entramos en https://putty.org/ y en Downloads descarga y ejecuta el fichero correspondiente, si es un Intel x86 64bits al menos que sea un equipo viejo 32 bit. Si es un AMD insala el arm

2024-09-26 14_35_42-Download PuTTY_ latest release (0.81).png

CONFIGURAR PUTTY PUERTO SERIE CON MICROBIT LINUX

Conectamos nuestra microbit por el puerto serie, y ejecutamos la siguiente instrucción ls /dev/ttyACM* normalmente será /dev/ttyACM0 por lo que en PUTTY ponemos este dato con la velocidad 115200 :

MC2.pngAutor Federico Coca de https://fgcoca.github.io/Guia-de-trabajo-para-microbit/conceptos/serie/ licencia CC-BY-SA

CONFIGURAR PUTTY PUERTO SERIE CON MICROBIT WINDOWS

Conectamos nuestra microbit por el puerto serie, y ejecutamos el Administrador de dispositivos

2024-09-26 14_30_48-Edit Page Draft _ Librería CATEDU.png

Al ejecutarlo vemos que aparece un dispositivo nuevo conectado en los puertos COM (si tienes dudas, conecta y desconecta la microbit) en la imagen aparece el COM19

2024-09-26 14_31_59-Administrador de dispositivos.png

Por lo que en PUTTY ponemos este dato con la velocidad 115200 :

2024-09-26 14_33_45-MC2.png (1234×576).png

ATENCIÓN: ESTAS OCUPANDO EL MISMO PUERTO SERIE QUE LA COMUNICACIÓN DEL EDITOR PYTHON https://python.microbit.org/ o MU
SI QUIERES VOLVER A INSTALAR UN PROGRAMA TIENES QUE CERRAR PUTTY (sino, el editor da error al flashear pues no puede comunicarse con la placa microbit)

Hackeando

UART

Página extraída de Federico Coca Guia de Trabajo de Microbit  https://fgcoca.github.io/Guia-de-trabajo-para-microbit/conceptos/serie/ Licencia CC-BY-SA

En MicroPython es el módulo uart el que permite comunicarse a través de la interfaz serie entre la micro:bit y el ordenador. El módulo tiene diferentes funciones encomendadas a realizar diferentes tareas de comunicación serie, pero sobre todo hay una fundamental que es la de inicializar la micro:bit para trabajar.

microbit.uart.init(baudrate=9600, bits=8, parity=None, stop=1, *, tx=None, rx=None)

Inicializa la comunicación serie con los parámetros especificados en los pines Tx y Rx especificados. Hay que tener en cuenta que, para que la comunicación sea correcta, los parámetros deben ser los mismos en los dispositovos que se comunican. En la función tenemos:


Notas:
- Inicializar la UART en pines diferentes a los establecidos por defecto para USB puede originar que la consola de Python deje de ser accesible, ya que utiliza el mismo hardware. Para recuperar la consola hay que reinicializar la UART sin pasar nada por Tx o Rx (o pasando None a estos argumentos). Es decir, llamar a uart.init(115200) es suficiente para restaurar la consola Python.
- Las conexiones de dispositivos mediante Tx y Rx requieren "cruzar" los cables, de forma que el pin TX de la placa esté conectado al Rx del otro dispositivo y el pin Rx, con el pin Tx. De esta forma lo que uno transmite el otro lo escucha. También es imprescindible que los dispositivos tengan un GND común.


El ejemplo siguiente nos va a permitir comprobar la comunicación serie desde MicroPython. Grabamos el programa en la micro:bit.

from microbit import *

uart.init(115200,8,None,1)
while True:
    if button_a.was_pressed():
        #"\n" indica un salto de linea
        #\r" indica un retorno de carro
        #Con los dos se salta una linea y se lleva
        #el curso al principio
        uart.write("Python: Boton A pulsado\n\r")

Abrimos y configuramos PuTTY y la consola nos muestra:

Página extraída de Federico Coca Guia de Trabajo de Microbit  https://fgcoca.github.io/Guia-de-trabajo-para-microbit/conceptos/serie/ Licencia CC-BY-SA

2024-09-26 13_57_53-COM19 - PuTTY.png

 

En el simulador de Micropython también aparece

2024-09-26 13_58_33-micro_bit Python Editor.png

 

 

Hackeando

Registro de datos

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Grabar datos

Para utilizar el Registro de datos con micro:bit V2 tenemos disponibles en Python:

log.add({
      'temperatura': temperature(),
      'sonido': microphone.sound_level(),
      'luz': display.read_light_level()
    })
@run_every(days=1, h=1, min=20, s=30, ms=50)
def mi_funcion():
    # Hacer lo que sea
def mi_funcion():
    # Hacer lo que sea
run_every(mi_funcion, s=30)

Cada argumento corresponde a una unidad de tiempo diferente y son aditivos. Así, run_every(min=1, s=30) programa la llamada de retorno cada minuto y medio.

Cuando se lanza una excepción dentro de la función callback se desprograma la función. Para evitar esto puedes atrapar excepciones con try/except.

Los parámetros son:


Ejemplo grabación de registro simple

A continuación vemos un ejemplo de registro:

from microbit import *
import log

log.set_labels('temperatura', 'sonido', 'luz', timestamp=log.SECONDS)

@run_every(s=5)
def reg_dato():
    log.add(temperatura=temperature(),sonido=microphone.sound_level(),luz=display.read_light_level())

while True:
   sleep(500)

Lectura de datos

Para ver datos reales grabados en la micro:bit utilizaremos el ejemplo anterior de registro automáticos de aceleraciones.

Una vez que tenemos datos registrados en la micro:bit, la conectamos a un ordenador y dejamos que se monte como una unidad USB de nombre MICROBIT. Si abrimos esta unidad nos vamos a encontrar con tres archivos, uno de ellos es "MY_DATA.HTM".

2024-10-01 23_19_04-MICROBIT (D_) - Explorador de archivos.png

Si hacemos doble clic sobre el archivo "MY_DATA.HTM" se nos abrirá en una ventana de nuestro navegador por defecto.

2024-10-01 23_20_03-micro_bit data log.png

Los botones nos muestran diferentes opciones que podemos realizar con estos datos:

archivo_navegador_prev.png

Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

Ejemplo más extenso

Vamos a realizar una actividad en la que registraremos la temperatura y la luz ambiente en la misma micro:bit que contiene el programa

El programa que vemos a continuación realiza un registro automático cada 10 segundos o cuando pulsemos el botón A. Pulsando A+B se borran los datos registrados en la microbit.

from microbit import *
import log

# Configurar etiquetas y establecer la unidad de tiempo
log.set_labels("temperatura", "nivel_luz", timestamp=log.SECONDS)
display.show(Image.NO)
sleep(1000)
# Enviar cada fila de datos a la salida serie
log.set_mirroring(True)

continue_registro = True

# Decorador programado para que se ejecute cada 10s durante 50ms
@run_every(s=10, ms=50)
def reg_dato():
    # Registra cada 10s temperatura y nivel de luz y muestra un icono
    global continue_registro
    if continue_registro:
        display.show(Image.YES)
        try:
            log.add(temperatura=temperature(), nivel_luz=display.read_light_level())
        except OSError:
            continue_registro = False
            display.show(Image.CHESSBOARD)
        sleep(500)

while True:
    if button_a.is_pressed() and button_b.is_pressed():
        display.show(Image.GHOST)
        # Borra el archivo de registro con la opcion "full" lo
        # que asegura el borrado de datos aunque tarde mas tiempo.
        log.delete(full=True)
        continue_registro = True
    elif button_a.is_pressed():
        display.show(Image.YES)
        sleep(500)
        log.add(temperatura=temperature(), nivel_luz=display.read_light_level())
        display.show(Image.HEART)
    else:
        display.show(Image.NO)
    sleep(500)

A continuación vemos el registro de datos tras unos segundos y un par de entradas manuales:

A19_reg_local_literal.png

Autor Federico Coca Fuente : Guía de Trabajo de Microbit Licencia CC-BY-SA

Página extraída de Federico Coca Guia de Trabajo de Microbit CC-BY-SA

Créditos

Autoría y licencias

Cualquier observación o detección de error en soporte.catedu.es

image-1648462225402.gif

image-1648462299882.png