Programación Con MicroPython (Thonny)
Programación Con MicroPython (Thonny)
Marzo 2023
Indice
INDICE Pag. 1
11.2. Infrarrojos Decodificador
12. Display OLED
12.1. OLED Dibuja texto.
12.2. OLED Señal Analógica.
12.3. OLED Dibuja varias cosas.
12.4. OLED Senoidal.
13. Usando un display LCD
13.1. LCD Básico.
13.2. LCD Lectura de valor analógico
13.3. LCD Termostato.
14. Midiendo con ultrasonidos
14.1. Medidor básico de ultrasonidos
14.2. Medidor de ultrasonidos con emisión de tonos
15. Controlando Servos.
15.1. Control de servo básico
15.2. Control de servo mediante librería “Servo”.
15.3. Servo control con Maker Pi RP2040
15.4. Control servo con potenciómetro.
16. Controlando Motores
16.1. Control de dos motores de cc. con la tarjeta Maker Pi RP2040
16.2. Contrl de un Motor de cc. sin usar librería.
16.3. Control de dos motores
16.4. Control de velocidad de un motor con un potenciómetro
16.5. Control de velocidsd y sentido de giro de un motor
17. Otros dispositivos
17.1. Control de Display Numérico de 4 cifras.
17.2. Control de matriz de LEDs Max7219
17.3. Escaneo de puertos I2C
LINK INTERESANTES
INDICE Pag. 2
1. Introducción a este libro
INDICE Pag. 3
2. Microcontrolador Raspberri Pi PICO
Descripción
¿Cuáles son las diferencias entre la Raspberry Pi 4 Modelo B y esta Raspberry Pi Pico?
Bueno, básicamente, la Raspberry Pi 4 Modelo B es una placa base o una computadora
de placa única que puede usar para jugar, trabajar, grabar datos, navegar por Internet, ver
películas, como un reproductor multimedia y muchos más. Raspberry Pi Pico no está
diseñado para reemplazar a la Raspberry Pi 4 Modelo B (o placa similar), es más para
proyectos de computación física donde controla cualquier cosa, desde pequeños
componentes electrónicos, LED, motores; Leer información de sensores o comunicarse
con otros microcontroladores.
INDICE Pag. 4
Esta Raspberry Pi Pico es una placa de microcontrolador que puede realizar computación
física y se puede reprogramar fácilmente a través de una conexión USB.
Se
El sistema operativo oficial, Raspberry Pi OS viene preinstalado con Thonny Python IDE
que está listo para que comience a escribir código MicroPython para Pico. Si está
utilizando otro sistema operativo (Windows, macOS u otra distribución de Linux),
visite https://Thonny.org/ para descargar el IDE e instalarlo.
En la siguiente pagina se muestra tabla con las características del procesador Raspberry
utilizando otro sistema operativo (Windows, macOS u otra distribución de Linux),
visite https://Thonny.org/ para descargar el IDE e instalarlo.
En la siguiente página se muestra tabla con las características del procesador Raspberry
Pi Pico
INDICE Pag. 5
INDICE Pag. 6
Lo más destacado del procesador:
INDICE Pag. 7
Compacto y listo para ser montado en el producto
Raspberry Pi Pico no solo es súper asequible, sino que también está listo para integrarse
en cualquier producto listo para usar. Si elige la versión sin cabezales presoldados, está
listo para SMT (Surface Mount Technology). Raspberry Pi Pico se extiende a 40 pines
21x51 DIP (paquete dual en línea), PCB de 1 mm de grosor con pines de orificio pasante
de 0.1 "(100 mil). Los pines se extienden aún más al borde de la PCB con una placa de
circuito almenada. Esto permite que se suelde a otra placa de PCB sin la necesidad de
pines de cabezal adicionales, lo que lo convierte en un producto terminado más pequeño
y compacto. ¡Genial!
Mientras tanto, la versión con cabezales pre-soldados es amigable con la placa de pruebas,
por lo que los estudiantes, fabricantes e ingenieros pueden usar la Raspberry Pi Pico en
una placa de prueba o cualquier placa PCB estándar para desarrollo o creación de
prototipos.
INDICE Pag. 8
MCU rico en periféricos
INDICE Pag. 9
Con 26 GPIO (3.3V) desglosados para aplicaciones, tiene más pines GPIO que Arduino
UNO, Arduino NNO o incluso Arduino MKR Zero. Entre estos 26 GPIO, 3 se pueden
configurar como ADC de 12 bits con 500ksps (kilo de muestra por segundo), 2 x UART,
2 x SPI, 2 x I2C y hasta 16 x PWM pin. Internamente, también viene con 1 x temporizador
con 4 alarmas y 1 x contador en tiempo real. Sin olvidar los periféricos duales de E/S
programables (PIO) que son E/S de alta velocidad flexibles y programables por el usuario.
Puede emular interfaces como tarjetas SD y VGA.
Nota: El Raspberry Pi Pico GPIO se ejecuta en 3.3VDC. El voltaje máximo que los pines
de E/S pueden tolerar es de 3.3V. La aplicación de voltajes superiores a 3.3V a cualquier
pin de E/S podría dañar la placa.
Con 2 MByte de QSPI Flash externo y 264 KByte de SRAM en Raspberry Pi Pico,
nunca le preguntará por no tener suficiente memoria :) Además, el gran tamaño de RAM
y Flash también permite que Raspberry Pi Pico sea compatible con lenguajes de
programación superiores como MicroPython o incluso Javascript.
Con el receptor USB Micro B listo como conexión física a un ordenador y el USB 1.1
PHY en el RP2040 (MCU), la Raspberry Pi Pico ofrece un método de carga de programas
simple y directo. Es como copiar archivos de una unidad a otra. ¡El Pico aparece como
almacenamiento masivo USB cuando se conecta a la computadora a través del puerto
USB! ¡Se convierte en una unidad USB! Escriba el código y arrastre el archivo a esa
unidad USB. Después de que el archivo se haya copiado por completo, Pico se reiniciará
y ejecutará el programa :) Fácil, ¿verdad?
INDICE Pag. 10
Python es uno de los lenguajes de programación más famosos y poderosos de la
actualidad. Se está utilizando en muchas aplicaciones de alto nivel, como IA (inteligencia
artificial), DL (aprendizaje profundo) y desarrollo web e Internet, y más. Python se utiliza
con éxito en miles de aplicaciones empresariales del mundo real en todo el mundo,
incluidos muchos sistemas grandes y de misión crítica. MicroPython es una
implementación eficiente y eficiente del lenguaje de programación Python 3 que incluye
un pequeño subconjunto de la biblioteca estándar de Python y está optimizada para
ejecutarse en microcontroladores y en entornos restringidos. Te encantará.
INDICE Pag. 11
¡Simplemente increíble! El pin es VSYS (Pin 39). Con un amplio rango de voltaje,
Raspberry Pi Pico puede ser alimentado por USB, 2 x pilas AA, 2 pilas NiMH AA, ¡1 x
18650 Li-ion o 1 x pila LiPo de celda!
Raspberry Pi Pico se inserta en una placa de pruebas, hay dos filas de orificios de puente
a ambos lados de la PCB para la creación de prototipos.
Dado que Raspberry Pi Pico es la 1ª plataforma MCU de la Fundación Raspberry Pi, todos
son nuevos en ella. ¡No temas! Es una placa de microcontrolador bastante amigable para
principiantes. Aquí están nuestras recomendaciones para el principiante, fabricante e
ingeniero:
Funciones
• 1ª placa de desarrollo de microcontroladores de la Fundación Raspberry Pi
• 1st Silicon (IC), MCU RP2040 diseñado desde cero por ingenieros de
Raspberry Pi Foundation
• Procesador ARM Cortex M0+ de doble núcleo y 32 bits
INDICE Pag. 12
• Reloj flexible, configurable máximo a 133MHz
• Preparado con receptor USB Micro B para alimentación y datos
• Soporte USB 1.1 host y dispositivo
• Conectado al puerto USB y aparecerá como almacenamiento masivo USB de
forma predeterminada, no se necesita ningún controlador
• Soporta CircuitPython, MicroPython, C y C++, lenguaje de programación
Arduino IDE
• Método de carga del programa de arrastrar y soltar, al igual que mover archivos
en el Explorador de Windows
• Viene en PCB de 40 pines de 1 mm de grosor estilo 'DIP' 21x51 con pines de
orificio pasante de 0.1 ", amigable con la placa de pruebas
• Con las castellaciones de borde PCB, está listo para ser montado en otra PCB sin
un pin de cabezal adicional, compatible con SMD
• Dos opciones:
o Viene con pines de cabezal PRE-SOLDADOS, amigable con la placa de
pruebas
o Viene sin cabecera, compatible con SMD
• Rico periférico:
o Salida extendida 26 E/S multifunción de 3,3 V de uso general (GPIO)
o 23 GPIO son solo digitales
o 3 ADC de 12 bits capaz de 500Ksps, convertidor analógico a digital
o 2 x UART (Receptor/transmisor asíncrono universal)
o 2 x SPI (interfaz periférica serie)
o 2 x I2C (Inter IC)
o 16 x PWM (modulación de ancho de pulso)
o 1 x temporizador con 4 alarmas
o 1 x contador en tiempo real
o 2 x E/S programables (PIO) que pueden emular interfaces de alta
velocidad como tarjeta SD o VGA
o Sensor de temperatura ADC de 12 bits integrado
• Puerto de depuración de cable serie (SWD) ARM de 3 pines
• LED programable integrado, GP25
• Arquitectura de fuente de alimentación simple pero altamente flexible
o Admite alimentación USB, fuente externa (2 - 5VDC) o incluso energía
de la batería.
• SDK completo, ejemplos de software y documentación
• Oficialmente de la Fundación Raspberry Pi
• Compatible con cualquier ordenador con puerto USB, Windows, macOS, Linux
• Funciona sin problemas con Raspberry Pi 4 Model B, o Raspberry Pi 400 y
Raspberry Pi OS
• Dimensiones: 51mm x 21mm x 1mm
Recursos
• Introducción a Raspberry Pi Pico (URL)
• Introducción a Raspberry Pi Pico (pdf), Desarrollo de C/C++ con Pico y otras
placas de microcontroladores basadas en RP2040
• Hoja de datos de Raspberry Pi Pico (pdf), una placa de microcontrolador basada
en RP2040
INDICE Pag. 13
• SDK de Pico Python (pdf), Un entorno de MicroPython para el
microcontrolador RP2040
• SDK de Pico C/C++ (pdf), Bibliotecas y herramientas para el desarrollo
de C/C++ en el microcontrolador RP2040
• RP2040 Hoja de datos (pdf), Un microcontrolador por Raspberry Pi
• Un nuevo retador en la plataforma MCU: Raspberry Pi Pico, un artículo sobre
Raspberry Pi Pico y RP2040
• Raspberry Pi Pico Vs Arduino UNO R3, un artículo para comparar las
especificaciones de RPi Pico y Arduino UNO R3
INDICE Pag. 14
3. Tarjetas Cytron
Maker Pi Pico y Maker Pi Pico Base incorporan el botón de reinicio más buscado
para Raspberry Pi Pico o Pico W y le da acceso a todos los pines GPIO en dos cabezales
de pines de 20 vías, con etiquetas claras. Cada GPIO se combina con un indicador LED
para realizar pruebas de código y solucionar problemas de manera conveniente. La capa
inferior de esta placa incluso viene con un diagrama de pines completo que muestra la
función de cada pin.
Nota Para los fabricantes internacionales, consulte a nuestros socios internacionales que
llevan Maker Pi Pico Base.
INDICE Pag. 15
Detalle de algunas de las partes mas importantes de la tarjeta. Los
conectores son compatibles con el estándar Grove
INDICE Pag. 16
Es una placa compacta pero repleta de funciones diseñada para sentarse en el corazón de
sus proyectos de STEM y robótica. Simplemente use los cables de puente y / o cables
Grove para conectar cualquier sensor y módulos de salida para ampliar su capacidad. ¡No
se requiere soldadura!
INDICE Pag. 17
INDICE Pag. 18
Diseño de la placa:
INDICE Pag. 19
o 1 x cable USB micro B
INDICE Pag. 20
Recursos
• Hoja de datos de Maker Pi Pico (pdf)
• Esquema de Maker Pi Pico Rev1.2.0
• Demostración de Maker Pi Pico y código de ejemplo
• CAD 3D
• Página oficial de Raspberry Pi Pico
• Primeros pasos con Raspberry Pi Pico
• Hoja de datos de Raspberry Pi Pico (pdf)
• Hoja de datos de Raspberry Pi Pico W (pdf)
• Hoja de datos de RP2040
• Raspberry Pi Pico Python SDK
• Raspberry Pi Pico C/C++ SDK
INDICE Pag. 21
Tarjeta MAKER PI RP2040
Función Descripción
Vin Terminal Conecte a cualquier fuente de alimentación dentro de 3.6 - 6V.
Conector de batería LiPo Conectar a batería LiPo / Li-Ion de celda única.
La batería es recargable a través de USB.
Conector LiPo Bateria ∗ La batería está protegida contra sobrecargas y descargas excesivas.
Si la placa no se puede encender cuando la batería está conectada,
cargue la batería para activar el circuito de protección de la batería.
INDICE Pag. 22
LED Encendico Se enciende cuando se conecta
Interruptor On/Off Enciende/apaga la alimentación.
Puerto depuración Puerto de depuración del RP2040.
Utilizado para cargar programas desde la PC.
Puerto Micro USB
También se puede utilizar para encender la placa
Botón Reinicio Presiónelo para reiniciar el RP2040.
Mantenga presionado este botón mientras se reinicia el RP2040 para
Boton Para Modo
ingresar al modo de cargador de inicio. Se utiliza para cargar el firmware
Cargador
MicroPython/Circuitpython o C/C++ personalizado.
Puertos Grove Conéctese a módulos Grove externos.
Grove Port GPIO PWM SPI I2C UART Analog
0 PWM0-A SDI0 SDA0 TX0 -
1
1 PWM0-B CSn0 SCL0 RX0 -
2 PWM1-A SCK0 SDA1 - -
2
3 PWM1-B SDO0 SCL1 - -
4 PWM2-A SDI0 SDA0 TX1 -
3
5 PWM2-B CSn0 SCL0 RX1 -
Puertos Grove
16 PWM0-A SDI0 SDA0 TX0 -
4
17 PWM0-B CSn0 SCL0 RX0 -
6 PWM3-A SCK0 SDA1 - -
5
26 PWM5-A - SDA1 - ADC0
26 PWM5-A - SDA1 - ADC0
6
27 PWM5-B - SCL1 - ADC1
7 PWM3-B SDO0 SCL1 - -
7
28 PWM6-A - - - ADC2
RGB LEDs (WS2812) LED RGB WS2812B programable por el usuario. Conectado a GP18.
Botones programables Accesibles desde el programa de usuario. Conectado a GP20 y GP21
Piezo Buzzer Se puede utilizar para reproducir tonos o melodías. Conectado a GP22.
Interruptor Buzer OFF Se utiliza para silenciar el zumbador piezoeléctrico.
LED de estado de GPIO Indicadores LED para GPIO RP2040 en puertos
GPIO Status LEDs Grove.
Encienda cuando el estado de GPIO sea alto.
Presiónelos para probar la funcionalidad del controlador de motor.
El motor funcionará a toda velocidad.
Botones Test Motor
● MxA: Adelante*
● MxB : Hacia atrás*
Conectores de puertos servo para 4 servomotores RC.
Puertos Servo La señal está conectada a GP12, GP13, GP14 y GP15.
El voltaje V+ es igual al voltaje de la fuente de alimentación.
LED de estado del motor Se encienden cuando el motor está
LEDs estado de motor funcionando.
● MxA: Adelante*
INDICE Pag. 23
● MxB : Hacia atrás*
Terminales del motor de CC Conecte al terminal del motor.
El voltaje del motor a toda velocidad es igual al voltaje de la fuente de
alimentación.
Terminales Motor DC
La dirección del motor depende de la polaridad.
● M1A: GP8 ● M2A: GP10
● M1B: GP9 ● M2B: GP11
• La dirección real del motor depende de la conexión del motor. Cambiar la conexión (MA y
MB) invertirá la dirección.
INDICE Pag. 24
4. Programando con MicroPython Thonny
Para el desarrollo de las tareas de programación de las tarjetas Cytron que hemos
seleccionad para trabajar con Raspberry Pi Pico será el entorno de programación Thonny
que es una herramienta de libre distribución y que cumple todas las exigencias para poder
trabajar de manera cómoda y sencilla.
En el siguiente epígrafe vamos a repasar los pasos que se han de dar para poder realizar
la programación de nuestras tarjetas
Paso 3: Ahora abra el IDE de Thonny Python, haga clic en Ejecutar-> Configuracion
de interprete para seleccionar MicroPython para Rapsberry Pi Pico como intérprete:
También seleccione el puerto COM al que está conectada su placa Pico: Después de eso,
haga clic en Aceptar para guardar la configuración.
INDICE Pag. 25
INDICE Pag. 26
Paso 4: Ahora escribe el Código Python en la siguiente ventana que se muestra:
INDICE Pag. 27
Si nuestra aplicación llevara varios ficheros podemos grabarlos manualmente. Para
grabar puedes pulsar en la opción “Guardar como” del menú de Fichero y te aparecerá
la siguiente ventana; selecciona Raspberry Pi Pico como destino.
INDICE Pag. 28
Step 6:Escribe el nombre del fichero pico-lesson2.py, y pulsa OK
Paso 7: Haga clic en el pequeño botón ► de nuevo para ejecutar el código Python.
El resultado será
Ahora puede ver que el LED colocado en el PIN GP7 de la tarjeta se enciende y apaga.
INDICE Pag. 29
5. Estructura básica de un programa. Uso de librerías
Nuestros programas van a tener una estructura muy parecida. De manera general las
PARTES de un programa serán:
Existen numerosos manuales y tutoriales en los que podrás aprender Python para poder
ir incorporando nuevas funciones y recursos de este poderoso lenguaje de programación.
Las LIBRERÍAS son programas que incluyen funciones a las que se puede invocar desde
nuestros programas. Existen librerías propias del lenguaje (MicroPython y Phyton) que
son las que se invocan en la cabecera del programa.
Usando las palabras reservadas from e import que provee el sistema, podemos utilizar
variables, funciones, clases, excepciones y cualquier otro objeto que estén dentro de un
módulo.
INDICE Pag. 30
6. Botones y Leds
En este apartado vamos a realizar prácticas en las que intervengan señales de E/S digital.
Contaremos con las señales que en nuestras tarjetas Cytron son accesibles a través de los
conectores Grove, pero eso no significa que estemos obligados a usar esas y no otras
señales de los pines disponibles. Podemos usarlos todos.
Normalmente las salidas digitales se conectan a diodos LEDs pero también pueden
conectarse a relés u otros dispositivos de salida.
INDICE Pag. 31
6.1. Salida Digital: Blink (intermitente)
Objetivo
Funcionalidad
Se trata de crear en la salida pin GP1 una salida digital a la que conectaremos un LED y
este se encenderá y apagara con una cadencia temporal de T.encendido=0,5 s.
T.apagado=0,5 s.
Programa
led = Pin(1, Pin.OUT) # creamos el objeto LED en el pin PG1 como salida
while True:
led.value(1) # Pone LED en on
time.sleep(0.5) # Espera 0.5s
led.value(0) # Pone el LED en off
time.sleep(0.5) # Espera 0.5s
INDICE Pag. 32
Podríamos realizar la aplicación de otra forma, usando la instrucción led.toggle() con la
librería “utime”
# LED BLINKING
while True:
led.toggle() # conmuta LED
utime.sleep(0.1) # Espera 100ms
Para esta primera practica vamos a realizar paso a paso todas las operaciones con el fin
de que aprendas los pasos a seguir en las restantes prácticas:
Pasos a seguir
#Blink Básico
from machine import Pin #Importamos librerías
import time
3. Crear un objeto, "led" que se utiliza para crear un enlace entre el pin GPIO
físico y nuestro código. En este caso, establecerá GPIO 1 (que se asigna al pin
físico 2 en la placa) como un pin de salida, donde la corriente fluirá desde la
INDICE Pag. 33
Raspberry Pi Pico GPIO 1 al LED. Luego usamos el objeto para asegurar que el
pin GP1, al iniciarse el programa este apagado
while True:
led.toggle()
print("Toggle")
utime.sleep(1)
#Blink Basico
from machine import Pin #Importamos librerías
import time
while True:
led.value(1) # Pone LED en on
time.sleep(0.5) # Espera 0.5s
led.value(0) # Pone el LED en off
time.sleep(0.5) # Espera 0.5s
INDICE Pag. 34
7. Lo que procede ahora es probar nuestro primer proyecto. Para ello lo que
haremos es establecer la conexión con nuestra tarjeta y ejecutar pulsando el
botón “Retener/Reiniciar” y si esta bien conectada la tarjeta en el puerto USB
se activara el botón de “Ejecutar script actual”
INDICE Pag. 35
Aparecerá la siguiente ventana que muestra los ficheros que hay, si es que los
hay, en la tarjeta y nos invita a poner el nombre de nuestro fichero: Ponemos
main y damos “OK”. A continuación, veremos que nuestro fichero aparece
con el nombre “main.py” en la carpeta de archivos que hay en el
microcontrolador Raspberry Pi Pico
INDICE Pag. 36
Este es el aspecto del programa
Montaje de la practica
INDICE Pag. 37
Análisis y propuesta de actividades
utime.sleep(secons)
import utime
# LED BLINKING
while True:
led.toggle() # conmuta LED
utime.sleep(0.1) # Espera 100ms
INDICE Pag. 38
# Destella un LED en un ciclo de tiempo de encendido y
# apagado dado, donde los dos tiempos se toman de un archivo txt
# guardado en la tarjeta Raspberry Pi Picoen el que se escribe
# en una linea los dos tiempos con numeros
# enteros " 200 400 ".
from machine import Pin
import time
from time import sleep
delay=line.split()
on=int(delay[0]) #designamos el tiempo activo
off=int(delay[1])#Designamos el tiempo apagado
print('Tiempo ON:',on,'mseg.') #Mostramos tiempos
print('Tiempo OFF:',off,'mseg.')
#Bucle Blink
while True:
led.value(1)
time.sleep_ms(on)
led.value(0)
time.sleep_ms(off)
INDICE Pag. 39
6.2 Activación secuencial de Salidas
Objetivo
Con esta práctica vamos a trabajar con varias salidas digitales de Raspberry Pi Pico que
se activarán de modo secuencial.
Funcionalidad
Usaremos los pines GP0 a GP7 (8 salidas digitales) en las que colocaremos LEDs
Se trata de encender y apagar cada LED de manera secuencial partiendo del pin GP0 hasta
llegar al pin GP7. Con los tiempos de encendido y apagado que se muestran en la figura
siguiente.
Programa
Los tiempos de espera asociados a cada estado de la salida se definen con la función
utime.sleep(n) donde n representa el numero de segundos de espera que en nuestro caso
será de 0,2 (200 ms.)
INDICE Pag. 40
### Secuencia de encendido del pines GP0 a GP7
# Ejecución secuencial
while True:
for i in range(7):
Pin(i).value(1) # pone en on el LED
utime.sleep(0.2) # espera 200 ms
Pin(i).value(0) # pone en off el LED
utime.sleep(0.2) # espera 200 ms
Montaje de la practica
Para realizar el montaje deberíamos usar una tarjeta protoboard y cablear las salidas a
LEDs.
Para probar nuestro montaje bastara con observar el estado de los lEDs de la tarjeta
Cytron
INDICE Pag. 41
Una vez creado el programa podemos experimentar con el modificando los tiempos de
encendido y apagado de los LEDs así como el numero de LEDs que participan en la
secuencia
1. Como actividad te propongo que realices el siguiente programa en el que los pines
implicados en la secuencia se integran en una lista con los números de pin de cada
estado de la secuencia.
pins = [0, 1, 2, 3, 4, 5, 6, 7]
def muestraLeds(): #Definimos la función muestraLeds()
#Recorremos la lista de pins en sentido ascendente
for pin in pins:
print(pin)
led = Pin(pin, Pin.OUT)
led.value(1)
time.sleep_ms(100)
led.value(0)
time.sleep_ms(100)
#Recorremos la lista de pines en sentido inverso
for pin in reversed(pins):
print(pin)
led = Pin(pin, Pin.OUT)
led.value(1)
time.sleep_ms(100)
led.value(0)
time.sleep_ms(100)
while True:
muestraLeds()
Las pruebas, como en el caso anterior se pueden hacer observando los leds de la
placa Cytron.
pins = [0, 1, 2, 3, 7, 6, 5, 4]
pins = [0, 1, 6, 7, 4, 5, 2, 3]
INDICE Pag. 42
6.3 Monoestable con monitorización de estado
Objetivo
Vamos a crear un programa en el que se active una salida digital un tiempo determinado
cunado se pulsa un botón que actúa de “disparo” o activación del “Monoestable”
Funcionalidad
Este es un circuito muy usado en los sistemas electrónicos de control. Se le llama también
“Temporizador”. Permite, ante una orden de activación, realizar la activación durante un
tiempo de la salida. En la figura se muestra un diagrama de tiempo con su
funcionamiento.
Funcionamiento:
Programa
2. Definimos los pines GP5 como entrada digital y GP3 como salida digital
INDICE Pag. 43
button = Pin(5,Pin.IN)
led = Pin(3, Pin.OUT) # GP1 LED SALIDA
led.value(0)
while True:
if button.value() == 1: # Si el Botón se presiona
led.value(1) # Se activa el LED
print('LED Activado')
time.sleep_ms(2000) #Tiempo en ms
led.value(0)
print('LED Desactivado')
print('Tiempo transcurrido', 2000,'ms')
else:
led.value(0)
INDICE Pag. 44
Montaje de la practica
En el análisis del funcionamiento del programa tenemos que fijarnos en la consola para
ver los estados de trabajo de nuestro programa.
INDICE Pag. 45
6.4. Medir tiempo entre dos eventos
Objetivo
Son numerosas las ocasiones en las que se hace necesario medir tiempos con un
microcontrolador. En esta práctica vas a aprender una sencilla forma de medir el tiempo
trascurrido entre dos eventos
Funcionalidad
Estableceremos dos eventos, uno de inicio de la cuanta del tiempo mediante un botón A
conectado en el pin GP20 y otro que marcara el final de la cuanta del tiempo que se llevara
a cabo mediante un pulsador B conectado en el pin GP21
Estos botones son los que vienen en la propia placa de Cytron que estamos usando.
Programa
2. Definimos los pines Botón A y Botón B asociados a los pines GP20 y GP21
3. Mediante dos condicionales estableceremos los eventos de inicio y fin de la
medida de tiempo testeamos el estado del botón. Téngase en cuenta que en reposo
estos botones envían un “1” por lo tanto testeamos el valor del botón como “0”.
4. Usamos dos variables:
INDICE Pag. 46
7. Para monitorizar los eventos de pulsación de botón imprimiremos
while True:
Montaje de la practica
Este sería el montaje. Como vemos solo nos basta con la tarjeta Cytron
INDICE Pag. 47
Análisis y propuesta de actividades
INDICE Pag. 48
6.5. Contador Binario
Objetivo
Crear un contador binario y probarlo usando los LEDs indicadores de la tarjeta Cytron
Funcionalidad
b = "{0:04b}".format(a)
>>> b = "{0:04b}".format(26)
>>> print(b)
11010
>>> b = "{0:08b}".format(26)
>>> print(b)
00011010
Cuando el contador alcance su valor máximo (15), comenzará nuevamente desde su valor
mínimo (0), el ciclo se repetirá indefinidamente.
INDICE Pag. 49
pin_d.value(int(b[3])) pin_d.value(int(b[3])) pin_d.value(int(b[3]))
pin_c.value(int(b[4])) pin_c.value(int(b[4]))
pin_d.value(int(b[5])) pin_d.value(int(b[5]))
pin_c.value(int(b[6]))
pin_d.value(int(b[7]))
Programa
2. Definimos los pines por los que sacaremos los códigos binarios.
def contador(a):
b = "{0:04b}".format(a)
#Imprime el valor en binario y decimal
print('Binario',b,'Decimal',i)
pin_a.value(int(b[0]))
pin_b.value(int(b[1]))
pin_c.value(int(b[2]))
pin_d.value(int(b[3]))
4. En el bucle while True lo que haremos es definir una función de tipo for en el
que el valor del puntero contador “i” varía entre 0 y 15 (se trata de recorrer 16
códigos que son los que podemos realizar con 4 bits binarios). Invocamos la
función contador y retardamos un segundo
INDICE Pag. 50
#Envia a la funcion el valor de conteo
contador(i)
#Retardo 1s
sleep(1) #espera 1 seg.
Montaje de la práctica
INDICE Pag. 51
El montaje es sencillo, solo necesitamos la tarjeta Cytron y observar el ella los LEDs
indicadores GP0 a GP3
Vemos en la imagen la venta “Consola” en la que van apareciendo los códigos binarios y
decimal tal como se van generando cada 1 segundo en la ejecución del programa
INDICE Pag. 52
6.6. Biestable
Objetivo
Con esta practica vamos a construir un biestable gobernado con un solo botón
Funcionalidad
Sabemos que un biestable es también una función “memoria” que mantiene su estado
“0” o “1” dependiendo de la actuación sobre su o sus entradas. En nuestro caso usamos
una sola entrada.
Programa
1. Importación de librerías
2. Definimos los pines E/S que usaremos y ponemos a “0” la salida del Biestable al
iniciarse el programa. El pin de entrada se define como PULL_UP para
asegurarnos su estado en reposo
INDICE Pag. 53
3. A continuación tenemos que definir la función “biestable” que la que nos
permitirá la conmutación de la salida Q del dispositivo.
Esta función lo que hace es que testea el valor del estado del led y si es “1” lo
pone en “0” y viceversa.
while True:
if button.value(): #Si el botón se pulsa se envía un "0"
biestable()
time.sleep_ms(300) #Retardo para evitar rebote en el botón
while True:
if button.value(): #Si el botón se pulsa se envía un "0"
biestable()
time.sleep_ms(300) #Retardo para evitar rebote en el botón
INDICE Pag. 54
Montaje de la practica
INDICE Pag. 55
6.7 Codificador Rotativo
Objetivo
Funcionalidad
Este módulo es ideal para añadir detección de rotación. El codificador te permite añadir
control a tu proyecto similar a los mandos de control de volumen de radio en coches,
detectando la dirección de rotación, la velocidad y el estado del botón.
En funcionamiento cuando en su estado sin girar las salidas CLK y DT serán altos,
cuando gire el codificador uno de ellos irá bajo seguido por el otro poco después. El
primero a señal bajo proporcionará su dirección. El interruptor SW se lee bajo cuando se
presiona.
El eje giratorio de 6 mm proporciona una gran variedad de pomos compatibles para elegir,
lo que le permite obtener el pomo adecuado para su trabajo.
Para este programa usaremos dos librerías que nos facilita la firma KeyStudio para poder
usar su dispositivo “Codificador rotativo”. Estas librerías son rotary_irq_rp2 y rotary.
Con estas librerías podremos crear un objeto llamado
Este objeto tiene un procedimiento que lo que hace es devolver el valor de la posición:
r.value()
INDICE Pag. 56
Programa
import time
from rotary_irq_rp2 import RotaryIRQ #Carga librerías
from machine import Pin
2. Definiremos el objeto SW digital en el GP4 que sera la señal para cargar o fijar el
valor de cuenta
pin_num_clk=2
pin_num_dt=3
min_val=0
reverse=False
range_mode=RotaryIRQ.RANGE_UNBOUNDED)
INDICE Pag. 57
El programa completo será el siguiente.
'''
* CODIFICADOR ROTATIVO Keystudio para Raspberry Pi Pico
'''
import time
from rotary_irq_rp2 import RotaryIRQ #Carga librerías
from machine import Pin
Montaje de la practica
INDICE Pag. 58
Análisis y propuesta de actividades
INDICE Pag. 59
6.8. Generador de pulsos
Objetivo
Funcionalidad
Programa
3. Seguidamente definimos nuestro bucle de ejecución while True dentro del cual
pondremos un condicional que testea la pulsación del boton 20 de GP20, el
botón en reposo envía un “1” por lo que debemos poner la condición en modo
negado if not botón.value().
4. Si se cumple la condición lo que haremos será ejecutar una instrucción for con
10 ciclos de ejecución for i in range(10)
INDICE Pag. 60
5. En cada ciclo se ejecutan las siguientes instruciones:
#Generador de pulsos
from machine import Pin
import time
led = Pin(1, Pin.OUT) # creamos el objeto LED en el pin PG1 como salida
botón=Pin(20, Pin.IN, Pin.PULL_UP)
led.value(0)
while True
if not botón.value():
for i in range(10): #Ejecutamos 10 veces
print("Pulso numero", 1+i)
led.value(1)
utime.sleep(1)
led.value(0)
utime.sleep(1)
print("FIN!")
Montaje de la practica
INDICE Pag. 61
Análisis y propuesta de actividades
Realiza cambios en el programa para que varie el número de pulsos, en este caso 20 pulsos
y los tiempos serán Tencendido=100 ms y Tapagado=300 ms
INDICE Pag. 62
6.9. Semáforo
Objetivo
Con este ejemplo vamos a realizar la simulación de un semáforo básico usando tres salida
digitales de la tarjeta Cytrón
Funcionalidad
Se usarán tres dispositivos LED de tipo Grove, si es posible de color rojo, amarillo y
verde que se activaran de manera secuencial.
En este caso se trata de que cada uno de los LEDs del semáforo conectados a los Pines
GP0, GP1 y GP2 se enciendan y apaguen de manera secuencial de acuerdo a la siguiente
tabla.
ESTADO Rojo Amarillo Verde Tiempo
1 ON OFF OFF 7 seg.
2 OFF ON OFF 5 seg.
3 OFF OFF ON 10 seg.
4 OFF ON OFF 1 seg.
Usaremos los pines
Programa
rojo.value(0)
amarillo.value(0)
verde.value(0)
INDICE Pag. 63
4. Establecimiento del bucle while True dentro del cual se colocaran las instrucciones
de activación rojo.value(1) y desactivación rojo.value(0) de los LEDs así como los
tiempos de espera utime.sleep(5). El ciclo es el que se ha puesto en la tabla anterior.
#Semáforo básico
from machine import Pin
import utime
rojo = Pin(0 , Pin.OUT)
amarillo = Pin(1 , Pin.OUT)
verde = Pin(2 , Pin.OUT)
#Puesta a cero de todas las salida
rojo.value(0)
amarillo.value(0)
verde.value(0)
while True:
rojo.value(1) #Enciende rojo
utime.sleep(7) # Espera 7 seg.
amarillo.value(1)
rojo.value(0)
utime.sleep(5)
amarillo.value(0)
verde.value(1)
utime.sleep(10)
verde.value(0)
amarillo.value(1)
utime.sleep(5)
amarillo.value(0)
Esquema de montaje:
Este sería el montaje de la aplicación.
INDICE Pag. 64
6.10. Barra de LEDs MY9221 de Seeed Grove
Objetivo
Funcionalidad
Este componente es muy útil para monitorizar el valor de una variable. Se trata de la
disposición de 10 LEDs en formato de barra que se encenderán en función del valor que
le entreguemos al dispositivo.
Para crear un valor que se use como muestra para enviar al dispositivo usaremos los dos
botones que incluye la tarjeta Cytron GP20 y GP21
Usaremos una librería que nos facilita el fabricante para usa con MicroPython my9221
Programa
4. En el bucle while True integramos los dos condicionales cuyas condiciones son
la pulsación de los botones A y B que incrementan o decrementan el valor a
mostrar en la barra de LEDs. Colocamos un retardo para evitar rebotes en el
pulsador e imprimimos el valor de la variable “num”
INDICE Pag. 65
#Barra de LEDs deMY9221
from machine import Pin
from my9221 import MY9221
import time
#Barra de LEDs = MY9221(di=pin1, dcki=pin2, reverse=False)
ledbar = MY9221(Pin(5), Pin(4))
botonA = Pin(20,Pin.IN)
botonB = Pin(21,Pin.IN)
while True:
if botonA.value() == 0: #Incrementamos el valor de num
num = num + 1
ledbar.level(num) #Mostramos num en la barra
time.sleep_ms(200)
print(num) # Imprimimos el valor de num
if botonB.value() == 0: #Decrementamos el valor de num
num = num - 1
ledbar.level(num)
time.sleep_ms(200)
print(num) # Imprimimos el valor de num
Montaje de la practica
INDICE Pag. 66
Análisis y propuesta de actividades
Una vez que se haya montado el programa se someterá a las pruebas correspondientes.
buf = [0,0,1,3,7,15,31,63,127,255]
while True:
buf.insert(0,buf.pop())
ledbar.bytes(buf)
time.sleep_ms(30)
2. En esta segunda propuesta probaras como es posible mostrar en el dispositivo de
LEDs el valor de un canal analógico entrada en el GP27 en el que se cablera un
potenciómetro. Mapearemos la señal generada por el potenciómetro (0 a 65535)
a un rango de 0 a 10 para poder visualizar el rango completo de la variable.
try:
while True:
adcValue = adc.read_u16()
voltaje = map(adcValue, 0, 65535, 0, 10)
print("ADC Valor:", adcValue, "Voltaje:", int(voltaje), "V")
ledbar.level(voltaje)
time.sleep(0.1)
except:
En la siguiente imagen vemos el aspecto de la consola mostrando los valores leídos así
como la representación grafica del valor.
INDICE Pag. 67
Este sería el montaje del ejercicio
INDICE Pag. 68
7 Señales analógicas
Raspberry Pi Pico tiene una sola resolución de 12 bits, ADC de 4 canales con una
referencia interna de 3.3V y entradas disponibles en 0-3 (GPIO 26-29), el sensor de
temperatura del chip interno está en la entrada 4.
Esto significa que puede medir voltajes de entrada entre 0V y 3.3V (Máximo) a una
resolución de 0.81mV (3.3 / 4095) aunque en MicroPython esto se escala a un valor de
16 bits de 0 a 65535.
En el primer ejemplo el voltaje a través del potenciómetro se lee como una entrada ADC
sin procesar que es un valor entre 0 y 65535. Esto se convierte en un valor de voltaje
utilizando un factor de conversión que realizara el ajuste del potenciómetro cambiando el
valor bruto de un mínimo de 0 a un máximo de 65535 y el voltaje de 0V a 3.3V
aproximadamente.
INDICE Pag. 69
7.1. Leer un valor analógico desde un pin
Objetivo
Con este ejemplo leeremos in pin de entrada analógica GP26 de la tarjeta Cytron y lo
imprimiremos en la consola de Thonny
Funcionalidad
Para generar una señal analógica usaremos un potenciómetro que conectaremos para
poner en el pin CP26 el valor necesario. Recordemos que los valores analógicos en
Raspberry Pi Pico oscilan entre el valor 0 y el 65535
Programa
while True:
# imprime el valor analogico en el puerto serie
print(potentiometro.read_u16())
time.sleep_ms(50) # espera 50ms, repite.
INDICE Pag. 70
Montaje de la practica
INDICE Pag. 71
1. En el siguiente actividad que te proponemos veremos cómo es posible ajustar el
valor leído del canal a un valor analógico que variara entre 0 y 3.3 v
try:
while True:
adcValue = adc.read_u16()
voltage = adcValue / 65535.0 * 3.3 #Escalamos la señal
print("ADC Valor:", adcValue, "Voltaje:", voltage, "V")
time.sleep(0.1)
except:
pass
Este es el aspecto del software con la aplicación funcionando
INDICE Pag. 72
7.2. Blink con tiempo variable
Objetivo
Con este ejemplo vamos a construir una aplicación en la que un LED se pondrá en
forma intermitente y el tiempo de encendido/apagado lo controlaremos con la entrada
analógica del pin GP27
Funcionalidad
El programa es exactamente igual al que ya vimos en el capítulo anterior 6.1, pero esta
vez lo que haremos será obtener el tiempo de retardo del valor leído en la entrada
analógica pin GP27 a la que le haremos un mapeado ya que como sabemos el valor que
entrega la orden de lectura del canal esta comprendida entre 0 y 65535, nosotros
pasaremos este valor a un valor entre 0 y 1 de tal manera que nuestro intervalo de
tiempo estará comprendido ente 0 y 1 seg.
#NOTAS IMPORTANTES
# Devuelve un entero
# Test
for i in range(200):
print(i, convert(i, 40, 80, 0, 1023))
INDICE Pag. 73
Programa
2. Designamos el objeto pot como una entrada ADC en el pin GP27. Designamos
un segundo objeto llamado led en el pin GP1 que será el LED sobre el que
realizaremos la función intermitente.
pot = ADC(27)
led = Pin(1, Pin.OUT)
3. Definimos la función map
4. Dentro del bucle while True leeremos el valor de la variable “raw” asignada a
la lectura de “pot”, y asignamos a la variable local delay el valor mapeado de la
señal. Imprimiremos, para ver en la consola, los valores “raw” y “delay”
debidamente formateados para su correcta impresión:
led.value(1)
sleep(delay)
led.value(0)
sleep(delay)
INDICE Pag. 74
Este sería el programa completo
pot = ADC(27)
led = Pin(1, Pin.OUT) #in de salida LED
while True:
raw = pot.read_u16()
delay = map(raw, 0, 65535, 0, 1)
print('Valor: {} '.format(raw), 'Retardo {:.1f}s'.format(delay))
led.value(1)
sleep(delay)
led.value(0)
sleep(delay)
Montaje de la práctica
INDICE Pag. 75
7.3. Salida analógica. PWM
Objetivo
Funcionalidad
La señal PWM (Modulación por Ancho de Pulso) es una señal periódica configurable
donde se puede modificar el ciclo de trabajo (Duty Cycle – En Ingles) utilizando el
MicroPython.
En la página de Sergio Andrés Castaño se muestra información sobre este tema, de ese
lugar sacamos la información que colocamos aquí.
Cada pin GPIO en la Raspberry Pi Pico puede ser configurado como salida PWM, pero
el bloque de modulación de ancho de pulso (PWM) del microcontrolador RP2040 está
compuesto por ocho segmentos, cada uno con dos salidas.
Si observamos el pinout de la Raspberry Pi Pico veremos que cada pin tiene una letra y
un número entre corchetes. El número representa el segmento PWM conectado a ese pin;
la letra representa qué salida del segmento es utilizado.
INDICE Pag. 76
PWM Raspberry Pi PICO
Se debe verificar que salidas de PWM se están utilizando bien, evitando conectar en
nuestro proyecto pines con una combinación de letras y números que ya hayamos
empleado.
Sin embargo, si intentamos configurar para este caso el PWM del GP16, note que ese
PWM ya está siendo usado por el GP0 ya que ambos están conectados a PWM_A[0]. Por
lo tanto, tendríamos un conflicto si intentamos hacer esa configuración.
Luego, creamos la instancia o objeto con el método PWM para la Raspberry Pi Pico:
led = PWM(Pin(15))
INDICE Pag. 77
led.freq(frequancy)
Para crear un objeto PWM, debemos pasar como parámetros, el pin vamos a configurar,
la frecuencia de la señal y el ciclo de trabajo.
led.duty_u16(duty_cycle)
También podemos usar duty() que sería empleado en el NodeMCU ESP8266 v3 Lolin.
led.duty(duty_cycle)
Note que para configurar el PWM necesitamos dos parámetros: Frecuencia (frequency) y
el ciclo de trabajo (duty_cycle)
El ciclo de trabajo podemos configurarlo en el loop principal del programa, por lo tanto
no hay necesidad de establecer el ciclo de trabajo al crear una instancia PWM ya que será
0 por defecto.
Para configurar el ciclo de trabajo (duty Cycle), usamos el método duty() del objeto PWM
creado y como parámetro de entrada le definimos el ciclo de trabajo deseado.
Dentro de mientras bucle, creamos un por bucle que aumenta el ciclo de trabajo en 1 en
cada bucle con un intervalo de 5 ms entre cada cambio.
INDICE Pag. 78
Nuestro programa será muy sencillo. Se trata de leer el valor de una señal analógica de
entrada desde el pin GP27 y llevar el valor leído a una salida PWM_B[3] en el pin GP7.
Las señales no se mapean. Se designa la frecuencia pwm.freq(1000)
Programa
adc = ADC(27)
pwm = PWM(Pin(7))
pwm.freq(1000)
3. Se utiliza las estructura try.. except dentro de la cual colocaremos el bucle while
True en la parte try y la parte except el reinicio del objeto pwm.deinit
INDICE Pag. 79
Montaje de la practica
INDICE Pag. 80
7.4. Efecto fadding de salida analógica
Objetivo
Se trata de emular el efecto “fading” en el encendido de un LED haciendo uso una de una
salida PWM
Funcionalidad
Se trata de sacar los valores PWM en el GP1. Creamos un bucle de cuenta ascendente con
la función for i in range(0, 65535, 10) y otro descendente for i in range(65535, 0, -10)
en la que el valor de la variable “i” es el que se escribe en la salida pwm.duty_u16(i).
Programa
2. Definimos el objeto pwm que será una salida en el pin GP1 y fijamos la frecuencia
de la señal base del PWM en 1000 hz
adc = ADC(27)
pwm.freq(1000)
INDICE Pag. 81
#Efecto Fading
from machine import Pin, PWM
import time
Montaje de la practica
INDICE Pag. 82
7.5 Joystick
Objetivo
Funcionalidad
Por los pines X e Y se obtiene u valor de tensión en función de la posición del mando.
Lo que vamos a hacer es insertar el dispositivo en el puerto Grove que ofrece los pines
analógicos GP27 y GP26 y de ellos leeremos los valores analógicos.
Programa
xValue = ADC(26)
yValue = ADC(27)
boton = Pin(1, Pin.OUT)
INDICE Pag. 83
4. En el bucle while True lo que hacemos es leer los valores analógicos a los que
llamamos x e y , los mapeamos e imprimimos dichos valores con el adecuado
formato de impresión y recorte de decimales. Mediante un condicional
detectamos el valor del parámetro valor de y>9 y activamos o no la salida en el
pin GP1
while True:
x = xValue.read_u16()
y = yValue.read_u16()
#Mapeado de los valores x e y
x= map(x, 0, 65530, 0, 10)
y= map(y, 0, 65530, 0, 10)
#Imprimimos solo dos decimales "{:.2f}".format(x)
print("X, Y:", "{:.2f}".format(x), "{:.2f}".format(y))
#Salida del botón pulsado del Joystick
if y > 9.00:
boton.value(1)
else:
boton.value(0)
time.sleep(0.1)
Montaje de la practica
INDICE Pag. 84
Análisis y propuesta de actividades
INDICE Pag. 85
8. Sonido
Conceptos introductorios
buzzer = PWM(Pin(15))
3. Asigne una propiedad freq al zumbador. Debe elegir un número que oscile entre
10 y 12,000. Cuanto mayor sea el número, más alto será el sonido. Probemos
500.
buzzer.freq(500)
5. Establezca la propiedad duty_u16 del objeto buzzer en 1000. Esto hace que el
timbre sea lo más fuerte posible. Un valor más bajo es más silencioso y 0 no es
sonido en absoluto. Teniendo en cuenta lo silenciosos que son estos zumbadores,
el volumen máximo no es muy alto en absoluto.
buzzer.duty_u16(1000)
sleep(1)
buzzer.duty_u16(0)
buzzer = PWM(Pin(15))
buzzer.freq(500)
buzzer.duty_u16(1000)
sleep(1)
buzzer.duty_u16(0)
INDICE Pag. 86
8.1. Emitir un tono
Objetivo
Funcionalidad
Programa
INDICE Pag. 87
Montaje de la practica
while True:
if boton.value() == 0:
#Definimos el rango de valores y el incremento
for i in range(500,5000,500):
buzzer.freq(i) #Frecuencia del tono
buzzer.duty_u16(8000) #Volumen del sonido
sleep(1)
buzzer.duty_u16(0) #Silencio
else:
buzzer.duty_u16(0)
INDICE Pag. 88
Montaje de la practica
INDICE Pag. 89
8.2. Alarma Sirena
Objetivo
En ocasiones tenemos que crear aplicaciones en las que se deba generar un sonido de
alarma para advertir de un evento determinado. En este caso al pulsar un botón emitiremos
un sonido de alarma cuya señal tonal responde a una función senoidal
Funcionalidad
Nuestro espectro tonal responderá a la función senoidal de tal manera que a una
frecuencia base le sumaremos un valor que varía de manera senoidal.
Programa
INDICE Pag. 90
establecemos el valor de la señal senoidal que sumamos al tono base de valor 1500
hz
#Alarma
from machine import Pin,PWM
import math
import time
PI = 3.14
boton = Pin(20, Pin.IN, Pin.PULL_UP)
buzzer = PWM(Pin(18))
buzzer.freq(1000)
try:
while True:
if not boton.value():
#Control volumen min=0 max=65535
buzzer.duty_u16(8000)
alert()
else:
#Volumen 0 en silencio
buzzer.duty_u16(0)
except:
buzzer.deinit()
INDICE Pag. 91
Montaje de la practica
INDICE Pag. 92
8.3 Generacion de una melodia
Objetivo
Funcionalidad
En esta ocasión vamos a generar melodías mediante el uso de una tabla de tonos o notas
de la que podemos crear una lista con nuestra propia melodía.
Programa
Debido a que puedes usar diferentes frecuencias, puedes crear una gama completa
de notas musicales. Hay algunas listas de frecuencias de notas musicales en línea y
muchas de ellas se remontan a la biblioteca de tonos Arduino de Brett Hagman en
Github. Usaremos estos valores para crear una lista que podamos usar para
reproducir cualquier canción al principio de nuestro código.
buzzer = PWM(Pin(15))
tones = {
"B0": 31,"C1": 33,"CS1": 35,"D1": 37,"DS1": 39,"E1": 41,"F1": 44,"FS1":
46,"G1": 49,"GS1": 52,"A1": 55,"AS1": 58,"B1": 62,"C2": 65,"CS2": 69,"D2":
73,"DS2": 78,"E2": 82,"F2": 87,"FS2": 93,"G2": 98,"GS2": 104,"A2":
110,"AS2": 117,"B2": 123,"C3": 131,"CS3": 139,"D3": 147,"DS3": 156,"E3":
INDICE Pag. 93
165,"F3": 175,"FS3": 185,"G3": 196,"GS3": 208,"A3": 220,"AS3": 233,"B3":
247,"C4": 262,"CS4": 277,"D4": 294,"DS4": 311,"E4": 330,"F4": 349,"FS4":
370,"G4": 392,"GS4": 415,"A4": 440,"AS4": 466,"B4": 494,"C5": 523,"CS5":
554,"D5": 587,"DS5": 622,"E5": 659,"F5": 698,"FS5": 740,"G5": 784,"GS5":
831,"A5": 880,"AS5": 932,"B5": 988,"C6": 1047,"CS6": 1109,"D6":
1175,"DS6": 1245,"E6": 1319,"F6": 1397,"FS6": 1480,"G6": 1568,"GS6":
1661,"A6": 1760,"AS6": 1865,"B6": 1976,"C7": 2093,"CS7": 2217,"D7":
2349,"DS7": 2489,"E7": 2637,"F7": 2794,"FS7": 2960,"G7": 3136,"GS7":
3322,"A7": 3520,"AS7": 3729,"B7": 3951,"C8": 4186,"CS8": 4435,"D8":
4699,"DS8": 4978
}
4. Crea una lista (también conocida como matriz) de notas para tu canción.
Usa la letra P para representar pausas en la música. Cada nota debe estar
entre comillas.
song =
["E5","G5","A5","P","E5","G5","B5","A5","P","E5","G5","A5","P","G5","E5"]
def playtone(frequency):
buzzer.duty_u16(1000)
buzzer.freq(frequency)
def bequiet():
buzzer.duty_u16(0)
7. Crea una función llamada playsong que usarás para iterar a través de la
matriz de notas y reproducir cada una o hacer una pausa cuando vea P.
def playsong(mysong):
for i in range(len(mysong)):
if (mysong[i] == "P"):
bequiet()
else:
playtone(tones[mysong[i]])
sleep(0.3)
bequiet()
try:
while True:
if not button.value():
#Control volumen min=0 max=65535
playsong(song)
else:
INDICE Pag. 94
#Volumen 0 en silencio
bequiet()
except:
buzzer.deinit()
Esto es lo que está pasando aquí. Primero, creamos un bucle for que itera a
través de todos los valores en la matriz mysong. Si el valor es igual a P,
activa be quiet y, si no, activa playtone. Tenga en cuenta que el tono de
reproducción requiere un valor de frecuencia numérico, por lo que tenemos
que obtener el número para cada nota de la lista de tonos. Si solo tocamos el
tono (mysong[i]), fallará porque intentará tocar la cuerda "E5", en lugar de
la frecuencia 659, que es el entero que necesita.
Para cada tono o pausa, el sistema mantiene el estado durante 0,3 segundos
de retrdo. Si quieres un tempo más rápido, puedes bajar ese tiempo. Si
quieres un tempo más lento, auméntalo.
def playtone(frequency):
buzzer.duty_u16(8000)
buzzer.freq(frequency)
def bequiet():
buzzer.duty_u16(0)
INDICE Pag. 95
def playsong(mysong):
for i in range(len(mysong)):
if (mysong[i] == "P"):
bequiet()
else:
playtone(tones[mysong[i]])
sleep(0.3)
bequiet()
try:
while True:
if not button.value():
#Control volumen min=0 max=65535
playsong(song)
else:
#Volumen 0 en silencio
bequiet()
except:
buzzer.deinit()
Montaje de la practica
INDICE Pag. 96
def playtone(frequency):
buzzer.duty_u16(1000)
buzzer.freq(frequency)
def bequiet():
buzzer.duty_u16(0)
3. Cree una función llamada playsong que usará para iterar a través de la matriz
de notas mysong y reproducir cada una o hacer una pausa cuando vea P.
def playsong(mysong):
for i in range(len(mysong)):
if (mysong[i] == "P"):
bequiet()
else:
playtone(tones[mysong[i]])
sleep(0.3)
bequiet()
Esto es lo que está pasando aquí. Primero, creamos un bucle for que itera a través
de todos los valores en la matriz mysong. Si el valor es igual a P, activa be quiet
y, si no, activa playtone. Tenga en cuenta que el tono de reproducción requiere
un valor de frecuencia numérico, por lo que tenemos que obtener el número para
cada nota de la lista de tonos. Si solo tocamos el tono (mysong[i]), fallará porque
intentará tocar la cuerda "E5", en lugar de la frecuencia 659, que es el entero que
necesita.
Para cada tono o pausa, el sistema mantiene el estado durante 0,3 segundos de
sueño. Si quieres un tempo más rápido, puedes bajar ese tiempo. Si quieres un
tempo más lento, auméntalo.
playsong(song)
Cuando ejecute este código, escuchará su timbre tocar una melodía familiar. Así es
como debería verse el código completo:
INDICE Pag. 97
tones = {
"B0": 31,"C1": 33,"CS1": 35,"D1": 37,"DS1": 39,"E1": 41,"F1": 44,"FS1":
46,"G1": 49,"GS1": 52,"A1": 55,"AS1": 58,"B1": 62,"C2": 65,"CS2":
69,"D2": 73,"DS2": 78,"E2": 82,"F2": 87,"FS2": 93,"G2": 98,"GS2":
104,"A2": 110,"AS2": 117,"B2": 123,"C3": 131,"CS3": 139,"D3": 147,"DS3":
156,"E3": 165,"F3": 175,"FS3": 185,"G3": 196,"GS3": 208,"A3": 220,"AS3":
233,"B3": 247,"C4": 262,"CS4": 277,"D4": 294,"DS4": 311,"E4": 330,"F4":
349,"FS4": 370,"G4": 392,"GS4": 415,"A4": 440,"AS4": 466,"B4": 494,"C5":
523,"CS5": 554,"D5": 587,"DS5": 622,"E5": 659,"F5": 698,"FS5": 740,"G5":
784,"GS5": 831,"A5": 880,"AS5": 932,"B5": 988,"C6": 1047,"CS6":
1109,"D6": 1175,"DS6": 1245,"E6": 1319,"F6": 1397,"FS6": 1480,"G6":
1568,"GS6": 1661,"A6": 1760,"AS6": 1865,"B6": 1976,"C7": 2093,"CS7":
2217,"D7": 2349,"DS7": 2489,"E7": 2637,"F7": 2794,"FS7": 2960,"G7":
3136,"GS7": 3322,"A7": 3520,"AS7": 3729,"B7": 3951,"C8": 4186,"CS8":
4435,"D8": 4699,"DS8": 4978
}
song =
["E5","G5","A5","P","E5","G5","B5","A5","P","E5","G5","A5","P","G5","E5
"]
def playtone(frequency):
buzzer.duty_u16(1000)
buzzer.freq(frequency)
def bequiet():
buzzer.duty_u16(0)
def playsong(mysong):
for i in range(len(mysong)):
if (mysong[i] == "P"):
bequiet()
else:
playtone(tones[mysong[i]])
sleep(0.3)
bequiet()
playsong(song)
Así que ahora sabes cómo tocar música con la Raspberry Pi Pico y un timbre
piezoeléctrico. Puedes hacer que esto reproduzca cualquier canción, siempre que
tengas las notas.
INDICE Pag. 98
INDICE Pag. 99
9. Jugando con Neopixel
Las tiras o barras de LEDs RGB son unidades que disponen de un numero determinado
de LEDs RGB que pueden ser direccionados de manera independiente y también les
podemos poner el color que queramos mediante la codificación RGB
(num1,num2,num3).
Uno de los mas importantes fabricantes de estos dispositivos es Neopixel que nos ofrece
también las librerías para MicroPython que permiten su manejo mediante distintas
funciones. En la siguiente imagen se muestra el dispositivo que vamos a usar en esta
sección de nuestro libro.
Esta barra de LEDs integra 10 LED RGB a todo color en este palo, con un solo pin de
señal puede controlar los 10 LED fácilmente. Todos los LED son WS2813 Mini, que es
un control inteligente y LED de alto costo. Además, el WS2813 admite la transmisión
continua de punto de interrupción de señal, lo que significa que puede continuar usando
otros leds con un led roto.
Mientras no se rompan dos o más LED adyacentes, los LED restantes podrán funcionar
normalmente. Puedes usar este pequeño palo para crear cientos y miles de efectos de
luz. Esperamos que te guste trabajar con este dispositivo.
Listo para usar con microcontroladores con entrada digital. Este producto también tiene
una interfaz compatible con Plug-and-play grove de diseño modular compacto.
Vamos a usar la librería neopixel que esta escrita para controlar el dispositivo de LEDs
WS2812 de Neopixel
Esta clase almacena datos de píxeles para una tira de LED WS2812 conectada a un pin.
El La aplicación debes establecer datos de píxeles y luego llamar a NeoPixel.write()
cuando esté listo para actualizar la tira.
Constructores de la librería
NeoPixel.fill(pixel)
Establece el valor de todos los píxeles en el valor de píxel especificado (es decir,
un Tupla RGB/RGBW).
NeoPixel.__len__()
NeoPixel.__setitem__(index,val)
NeoPixel.__getitem__(index)
NeoPixel.write()
Vamos a usar los dos leds de la tarjeta MAKER PI RP2040 de Cytron para empezar a
experimentar con los LEDs RGB mediante la librería “neopixel”
Funcionalidad
En la tarjeta tenemos un dispositivo RGB con dos LEDs que se gobiernan desde el pin
GP18.
Programa
import time
from machine import Pin
from neopixel import myNeopixel
np = myNeopixel(NUM_LEDS, 18)
np.brightness(200) #brillo: 0 ~ 255
NUM_LEDS = 2
#El pin GP18 es el que incluye dos RGBs en la tarjeta
np = myNeopixel(NUM_LEDS, 18)
np.brightness(200) #brillo: 0 ~ 255
np.set_pixel(1, 255,0,0)
np.set_pixel(0, 0,0,255)
np.show()
Montaje de la practica
La practica no necesita, en este caso, ningún elemento a conectar. Estamos usando los
dos LEDs RGB
NUM_LEDS = 2
#El pin GP18 es el que incluye dos RGBs en la tarjeta
np = myNeopixel(NUM_LEDS, 18)
np.brightness(255) #brillo: 0 ~ 255
while True:
np.set_pixel(1, 0,255,0) #LED1 en Rojo
np.set_pixel(0, 0,0,0) #Apaga LED0
np.show() #Muestra leds programados
time.sleep(0.1) #Espera 500 ms
np.set_pixel(1, 0,0,0) #Apaga LED1
np.set_pixel(0, 0,0,255)#Muestra LED0 3n Azul
np.show()
time.sleep(0.1)
Este es el montaje.
Con este ejemplo vas a utilizar un dispositivo externo Neopixel RGB LED de 10 LEDs
Funcionalidad
Programa
NUM_LEDS = 10
np = myNeopixel(NUM_LEDS, 3) #definimos el objeto RGB
# Lista de colores
COLORS = [red, green, blue, white, close]
#Fijación del nivel de brillo de los LEDs
np.brightness(100) #Brillo: 0 ~ 255
while True:
for color in COLORS:
np.fill(color[0], color[1], color[2])
np.show()
time.sleep(0.5)
La imagen siguiente muestra la conexión del dispositivo Neopixel a través del puerto
Grove haciendo coincidir el pin GP3 con el terminal Sig del dispositivo Neopixel.
Objetivo
Funcionalidad
En este montaje lo que haremos será crear una secuencia de luz que nos provoque la
sensación de la contemplación de una Arco Iris usando los 10 LEDs de nuestro
dispositivo.
Programa
np = myNeopixel(10, 3)
rojo = 0 #rojo
verde = 0 #verde
azul = 0 #azul
def iris(pos):
global rojo, verde, azul
Posicion = pos % 255
if Posicion < 85:
rojo = (255-Posicion*3)
verde = (Posicion*3)
azul=0
elif Posicion >= 85 and Posicion < 170:
Posicion -= 85;
rojo = 0
verde = (255 - Posicion*3)
azul = (Posicion*3)
else :
Posicion -= 170;
rojo = (Posicion*3)
5. Finalmente en la parte del bucle while True se encadenan dos bucles anidados
tipo for
rojo = 0 #rojo
verde = 0 #verde
azul = 0 #azul
def iris(pos):
global rojo, verde, azul
Posicion = pos % 255
if Posicion < 85:
rojo = (255-Posicion*3)
verde = (Posicion*3)
azul=0
elif Posicion >= 85 and Posicion < 170:
Posicion -= 85;
rojo = 0
verde = (255 - Posicion*3)
azul = (Posicion*3)
else :
Posicion -= 170;
rojo = (Posicion*3)
verde = 0
azul = (255-Posicion*3)
np.brightness(20)
while True:
for i in range(0, 255):
for j in range(0, 10):
iris(i + j*255 // 8)
np.set_pixel(j, rojo, verde, azul)
np.show()
time.sleep_ms(1)
Objetivo
Disponiendo de un dispositivo Neopixel RGB resulta muy sencillo poder simular con
el un semáforo. En esta práctica lo vamos a hacer
Funcionalidad
Programa
import time
from machine import Pin
from neopixel import myNeopixel
semaforo = myNeopixel(NUM_LEDS, 3)
3. Fijamos el brillo y aseguramos que los tres leds, al inicio del programa, esten
apagados
"""
Neopixel Semaforo dispositivo 10 LEDs RGB
en la tarjeta MAKER PI RP2040
"""
import time
from machine import Pin
from neopixel import myNeopixel
NUM_LEDS = 10
#El pin GP18 es el que incluye dos RGBs en la tarjeta
semaforo = myNeopixel(NUM_LEDS, 3)
semaforo.brightness(200) #brillo: 0 ~ 255
semaforo.set_pixel(0, 0,0,0)
semaforo.set_pixel(1, 0,0,0)
semaforo.set_pixel(2, 0,0,0)
while True:
semaforo.set_pixel(0, 255,0,0) #LED1 en Rojo
semaforo.set_pixel(2, 0,0,0) #LED2 Apagado
semaforo.show()
time.sleep(0.5)
semaforo.set_pixel(1, 100,100,0) #LED1 Amarillo
semaforo.set_pixel(0, 0,0,0) #LED0 Apagado
semaforo.show()
time.sleep(0.5)
semaforo.set_pixel(2, 0,255,0) #LED2 Verde
semaforo.set_pixel(1, 0,0,0) #LED1 en Apagado
semaforo.show()
time.sleep(0.5)
Objetivo
Funcionalidad
Sensor de temperatura
Seeed Studio ofrece una gran colección de sensores.
DHT22 DHT11
Precio 5 2
Los sensores DHT están pre calibrados. Podemos conectarlos directamente con
Raspberry Pi Pico para obtener la lectura de salida del sensor. Están compuestos
internamente por un sensor de detección de humedad y un termistor. Estos dos
componentes miden la humedad y la temperatura.
Programa
'''
* Medida de Temperatura y Humedad
* Con MAKER PI PICO de Cytron
'''
from machine import Pin
from time import sleep
import dht
while True:
print("temperatura:{} ℃ humedad:{} %".format(sensor.temperature,
sensor.humidity))
sleep(1.5) #Este valor no puede ser menor dado que el sensor no trabaja bien
Montaje de la practica
"""
Medida de temperatura mediante un sensor resistivo
Colocado en un canal de entrada analógica
"""
from machine import Pin, ADC
import time
import math
#Set ADC
adc=ADC(27)
try:
while True:
adcValue = adc.read_u16()
voltage = adcValue / 65535.0 * 3.3
#El valor 65535 es muy critico y se puede generar una divison por cero
# Si ocurre esto se puede subir a 65635
Rt = 10 * voltage / (3.3-voltage)
tempK = (1 / (1 / (273.15+25) + (math.log(Rt/10)) / 3950))
tempC = int(tempK - 273.15)
print("ADC value:", adcValue, " Voltage: %0.2f"%voltage,
" Temperature: " + str(tempC) + "ºC")
time.sleep(1)
except:
pass
Con esta práctica vamos a implementar un termostato que controlará dos equipos de
salida, un calefactor y un refrigerador.
Funcionalidad
Estableceremos dos consignas para la activación de cada uno de los dos elementos
actuadores, calefactor y refrigerador.
calefactor=Pin(3,Pin.OUT)
refrigerador=Pin(5,Pin.OUT)
pin = machine.Pin(1, machine.Pin.OUT, machine.Pin.PULL_DOWN)
sensor = dht.DHT11(pin)
'''
* Termostato con gobierno sobre calefactor
* y refrigerador
'''
from machine import Pin
import utime
import dht
calefactor=Pin(3,Pin.OUT)
refrigerador=Pin(5,Pin.OUT)
pin = machine.Pin(1, machine.Pin.OUT,
machine.Pin.PULL_DOWN)
sensor = dht.DHT11(pin)
while True:
if sensor.temperature < Cc:
calefactor.value(1) # Se activa Calefacción
print('Calefacción Encendido')
else:
calefactor.value(0) # Se desactiva Calefacción
print('Calefacción Apagada')
if sensor.temperature > Cr:
refrigerador.value(1) # Se activa Refrigeración
print('Refrigerador Encendido')
else:
refrigerador.value(0) # Se desactiva Refrigeración
print('Refrigerador Apagado')
Objetivo
Trabajaremos con un sensor de medida de luz con el que realizaremos una practica
Funcionalidad
Funciones
• Módulo sensor de luz fácil de usar
• La resistencia disminuye a medida que aumenta la luminancia
▪ Baja resistencia (con luz brillante) dispara una señal ALTA hacia el
módulo de salida
▪ Alta resistencia (en la oscuridad) dispara una señal BAJA hacia el módulo
de salida
• Se integra fácilmente con los módulos lógicos en el lado de entrada de los circuitos
Grove
• Utiliza cables Grove estándar de 4 pines para conectarse a otros módulos Grove.
Características técnicas
o Voltaje: 3-5V
o Corriente de alimentación: 0.5-3mA
o Resistencia a la luz: 20KΩ
o Resistencia oscura: 1MΩ
o Tiempo de respuesta: 20-30 segundos
o Longitud de onda máxima: 540 nm
o Temperatura ambiente: -30 ~ 70 °C
o LDR utilizado: GL5528
El valor que imprimimos lo escalamos para que se refleje en la escala de 0 a 100, por lo
que necesitamos implementar la función map para realizar el reescalado del valor leído
del puerto GP27 que como sabemos adopta los valores comprendidos en el entorno de 0
a 65530
El valor que sacamos por la salida PWM GP7 será el valor recogido directamente del
puerto GP27 es decir de 0 a 65530
Programa
# Función mapeado
def map(s, a1, a2, b1, b2):
return b1 + (s - a1) * (b2 - b1) / (a2 - a1)
try:
……
except:
salidaPwm.deinit()
valor=adc.read_u16()
luz=int(map(valor,0,65530,0,100))
salidaPwm.duty_u16(valor)
time.sleep(0.1)
print("Valor Leido", valor,"LUZ (valor mapeado)",luz)
Montaje de la practica
Objetivo
Funcionalidad
Para trabajar este tema vamos a recurrir a dos dispositivos: Mando Emisor de infrarrojos
y Receptor de señal.
Programa
recvPin = irGetCMD(3)
irValue = recvPin.ir_read()
if irValue:
print(irValue)
Montaje de la practica
Una vez que hemos cargado el programa podemos mandar datos desde el mando a
distancia y en la consola de Thonny podemos leer los datos leidos correspondientes a
cada tecla pulsada.
1. Te propongo que realices una ampliación de tu programa para que los códigos
correspondientes a las teclas “0,1,2 y3” se transformen en los valores “0,1,2
y3). Para esto puedes usar condicionales. Queremos también que se imprima el
código recibido convertido en número decimal print(int(irValue,16))
while True:
irValue = recvPin.ir_read()
if irValue:
print(irValue)
print(int(irValue,16)) # Convierte hexadecimal en decimal
if irValue == '0xffb04f': #0
print(0)
elif irValue == '0xff08f7': #1
print(1)
elif irValue == '0xff8877': #2
print(2)
elif irValue == '0xff48b7': #3
print(3)
Objetivo
Funcionalidad
Usamos tres salidas GP1, GP3 y GP5 que cambiaremos de estado cada vez que se reciba
el código correspondiente a los botones 0,1y2. En cada salida colocaremos un LED
Programa
recvPin = irGetCMD(7)
led0 = Pin(1, Pin.OUT)
led1 = Pin(3, Pin.OUT)
led2 = Pin(5, Pin.OUT)
3. Dentro del bucle lo que haremos será asignar a la variable irValue el valor leído
en el pin GP7 en el que esta conectado nuestro detector de IR . Seguidamente
imprimimos el valor en hexadecimal de la entrada detectada y seguidamente el
estado de las salidas pines GP1, GP3 y GP5. Seguidamente establecemos los
condicionales que revisan los valores de los códigos correspondientes a la teclas
0,1 y 2 para activar/desactivar las salidas con la función ledxx.toggle()
recvPin = irGetCMD(7)
led0 = Pin(1, Pin.OUT)
led1 = Pin(3, Pin.OUT)
led2 = Pin(5, Pin.OUT)
while True:
irValue = recvPin.ir_read()
print("Codigo detectado=",irValue,"//","Salida0=",
led0.value(),"Salida1=",led1.value(),
"Salida1=",led2.value())
if irValue == '0xffb04f': #0
led0.toggle() # conmuta LED
elif irValue == '0xff08f7': #1
led1.toggle()
elif irValue == '0xff8877': #2
led2.toggle()
Montaje de la practica
MicroPython dispone de una librería (no estándar) para pantallas monocromas OLED con el
controlador SSD1306 y bus de comunicación I2C o SPI.
Dado que el tipo más habitual de este modelo de pantallas que podemos encontrar en el mercado, son
las de 128×64 pixels de resolución – 0.96″ (25×14 mm) y bus de comunicaciones el I2C, se va a
desarrollar su uso para poder conocer las opciones de texto y gráficas (puntos, líneas, rectángulos e
imágenes) que están disponibles en la librería.
LA LIBRERÍA SSD1306
La librería (no estándar) para pantallas monocromas OLED con el controladores SSD1306 y bus de
comunicación I2C o SPI para MicroPython se puede localizar en GitHub:
https://github.com/MicroPython/MicroPython/blob/master/drivers/display/ssd1306.py
Se utilizará grabándola con el el nombre ssd1306.py en el directorio /lib. Este directorio está
destinado –por defecto– a guardar los módulos y librerías complementarias de una forma organizada
LA PROGRAMACIÓN
La librería ssd1306.py utiliza la librería FrameBuff de MicroPython, ya que ésta permite crear un
búferes eficientes de memoria para trabajar con vistas gráficas simples, por lo que es necesario
desarrollar su funcionamiento.
FrameBuff dispone de los métodos para dibujar puntos, líneas, rectángulos, imágenes o escribir texto,
así como desplazar imágenes por la pantalla.
▪ Las pantallas OLED son monocromas y el color se especifica como «0» (inactivo – color de
la pantalla recién inicializada) o «1» (activo – iluminado).
Es necesario utilizar .show() para mostrar en la pantalla lo que se haya dibujado. Hasta que no se haga
no mostrará ningún cambio.
Instrucciones basicas:
oled.fill(1) # Rellena la pantalla (la ilumina entera)
oled.fill(0) # Rellena la pantalla (la apaga entera)
oled.show() # Muestra el resultado
oled.contrast(50) # Regula el contraste al 50% de la intensidad
oled.inver(1) # Invierte lo que se va a mostrar
.poweron() .poweroff() La pantalla se
puede apagar y encender utilizando .poweron() y poweroff() respectivamente.
.pixel(x0, y0 [, color])
.scroll(x0, y0)
oled.scroll(20,10)
Objetivo
Funcionalidad
Programa
Objetivo
Funcionalidad
Programa
analogica=ADC(27)
while True:
oled.fill(0) # Borra el display OLED.
adcValue = analogica.read_u16() # Añade texto
oled.text("Valor= "+ str(adcValue),0,10) # Coordenada x=0, y=10
oled.show()# Descarga el texto en la pantalla y lo muestra
analogica=ADC(27)
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=200000)# Inicia I2C usando GP4 y GP5 (I2C0)
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Inicializa el OLED
while True:
# Borra el display OLED.
oled.fill(0)
# Añade texto
adcValue = analogica.read_u16()
oled.text("Valor= "+ str(adcValue),0,10) # Coordenada x=0, y=10
# Descarga el texto en la pantalla y lo muestra
oled.show()
Montaje de la practica
Objetivo
Con esta práctica vamos a seguir probando el display con las distintas funciones que
nos permiten escribir y/o dibujar varias cosas.
Funcionalidad
#Muestra un Pixel
oled.fill(0)
oled.pixel(11, 5, 1) # Dibuja un píxel iluminado en (5,10)
oled.show() # Muestra el resultado
utime.sleep(2) # Espera 2 segundos
oled.pixel(11, 5, 0) # Dibuja un píxel apagado en (10,5)
oled.show() # Muestra el resultado
#Muestra un Icono
from machine import Pin, I2C
#Linea Vertical
oled.vline(11, 5, 10, 1) # Dibuja una línea vertical iluminada. Origen (11, 5) altura 10
píxels
oled.show() # Muestra el resultado
utime.sleep(2) # Espera 2 segundos
oled.fill(0) # Rellena la pantalla (la ilumina entera)
#Linea Horizontal
oled.hline(11, 5, 10, 0) # Dibuja una línea vertical apagada. Origen (11, 5) altura 10
píxels
oled.show() # Muestra el resultado
utime.sleep(2)
#Cuadrado
oled.fill_rect(5, 3, 14, 12, 1)# Dibuja un rectángulo relleno iluminado. Origen (5, 3)y
anchura x altura 14x12 píxels
oled.show() # Muestra el resultado
utime.sleep(2) # Espera 2 segundos
#Rectángulo relleno
oled.fill_rect(5, 3, 14, 12 ,0) # Dibuja un rectángulo relleno apagado. Origen (5, 3)y
anchura x altura 14x12 píxels
oled.show()
Funcionalidad
Con este ejemplo solo queremos demostrar las posibilidades de dispositivo OLED, se
entiende que la complejidad del algoritmo se escapa al nivel de este libro por lo que solo
nos dedicamos a escribir l programa para que el lector lo pruebe y si acaso lo investigue.
Programa
#Onda Senoidal
from machine import Pin, I2C
import ssd1306
from time import sleep
import math
i2c = I2C(0, scl=Pin(5), sda=Pin(4))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
while True:
# Ángulo de giro de la línea del eje (de 0º a 360º en intervalos de 5º)
for anguloGrados in range(0, 360, 5):
# Ángulo de giro de la línea del eje en radianes
anguloRadianes = (math.pi*anguloGrados)/180
xLinea = int(math.cos(anguloRadianes)*24) # Coordenada x línea del eje
Montaje de la practica
Grove - 16 x 2 LCD es una pantalla LCD I2C perfecta para Arduino y Raspberry Pi con
alto contraste y fácil implementación. 16x2 significa dos líneas y cada línea tiene 16
columnas, 32 caracteres en total. Con la ayuda del conector Grove I2C, solo se necesitan
2 pines de señal y 2 pines de alimentación. Ni siquiera necesita preocuparse por cómo
conectar estos pines. Simplemente conéctelo a la interfaz I2C en Seeeduino o Arduino /
Raspberry Pi + base-shield a través del cable Grove. No habrá cableado complicado,
soldadura, preocuparse por quemar la pantalla LCD causada por la resistencia limitadora
de corriente incorrecta.
Versiones
Especificaciones
El Protocolo
Pantalla LCD funciona con el protocolo de comunicación serie I2C.
Que es el protocolo de comunicación que sólo utiliza dos hilos para la comunicación que
son los datos (SDA) y otro, el reloj (SCL). La dirección de comunicación entre esta
Instrucciones
## Posiciona cursor
lcd.set_cursor(0,0)
## On LCD Display
Encienda la pantalla LCD sin borrar los datos. El cursor y el parpadeo están
desactivados de forma predeterminada.
lcd.on()
lcd.on(cursor=True, blink=False)
lcd.on(cursor=True, blink=True)
lcd.off()
lcd.write("Hello World")
lcd.clear()
Objetivo
Este primer ejemplo de manejo del dispositivo LCD vamos a ver como conectarlo y
poner en el un texto y una cifra.
Funcionalidad
Este ejercicio resulta muy sencillo. Bastará con conectar el dispositivo LCD que como
hemos visto en el tema anterior se comunica con Raspberry Pi Pico a través del puerto
I2C.
En el dispositivo aparecerá:
“HOLA MUNDO”
123
Programa
1. Importación de librerías
2. Definimos el objeto lcd poniendo los números de los pines asociados a sda=4 y
scl=4
3. Situamos el cursor en la fila 0 y la columna 0 (al principio del área de escritura)
4. En el bucle while escribimos el texto “HOLA MUNDO” y la cifra “123” que
previamente hemos de convertir en una cadena de texto con la función “str” de
MicroPython
while True:
lcd.set_cursor(0,0)
lcd.write("HOLA MUNDO")# imprime una cadena de texto
lcd.set_cursor(0,1)
lcd.write(str(123)) # Se convierte en string una cifra y se imprime
Objetivo
En esta práctica vamos a imprimir un valor analógico que leeremos en uno de los canales
de Raspberry dispuesto para este tipo de señal.
Funcionalidad
En este caso el valor a escribir será un valor adquirido en tiempo real a través de un
potenciómetro que conectaremos en el pin GP27 de la tarjeta Cytron.
Valor Analógica
123
Programa
while True:
print(potentiometro.read_u16())
lcd.set_cursor(0,0)
lcd.write("Valor Analogico")# imprime el valor analógico
lcd.set_cursor(0,1)
lcd.write(str(int(potentiometro.read_u16())))
utime.sleep_ms(500)
lcd.clear()# retardo de 50ms..
Montaje de la practica
Objetivo
Funcionalidad
Nuestro algoritmo de control establecerá tres rangos de valor que se adecuaran a los tres
niveles que queremos controlar: Calor, OFF y Frío
• OFF significará que la temperatura esta comprendida entre 10ºC y 20ºC.En este
caso permanecerán desactivados los elementos Calefactor y Refrigerador. Ambos
LEDs se mantendrán apagados.
2. Definimos las variables: Calor (digital) Frio (Digital) y lcd (objeto de la librería
LCD) y pot (potenciómetro para simular las variaciones de temperatura)
3. Definimos la conocida función map que nos servirá para cambiar la escala de la
señal analógica leída en el puerto GP27 en el que tenemos que conectar el
potenciómetro.
4. La siguiente fase es la que se relaciona con el bucle while True dentro del cual
tendremos que:
• Leer la señal del pin GP27
• Mapear la señal igualando a una nueva variable local llamado “valor”
que imprimiremos dando formato.
• Posicionamos el curos del LCD en el punto (0,0), escribimos la
cadena de texto “Temperatura” y en la segunda línea escribiremos la
variable valor (ya mapeada) y leemos el valor del potenciómetro,
seguida de la cadena de texto “Grados”
while True:
lectura = pot.read_u16()
valor = map(lectura, 0, 65535, -20, 60)
#Imprimimos solo dos decimales "{:.2f}".format(x)
print("Temperatura:", "{:.2f}".format(valor)+ " ºC")
lcd.set_cursor(0,0)
lcd.write("Temperatura")# print analog value to serial
lcd.set_cursor(0,1)
lcd.write(str(int(valor))+" Grados")
if valor>20:
lcd.set_cursor(27,1)
lcd.write("Frio")
Frio.value(1)
Calor.value(0)
elif valor<10:
lcd.set_cursor(27,1)
lcd.write("Calor")
Frio.value(0)
Calor.value(1)
elif (10 < valor <20):
lcd.set_cursor(27,1)
lcd.write("OFF")
Frio.value(0)
Calor.value(0)
utime.sleep_ms(300)
lcd.clear() # retado de 50ms.
Medir distancias es una tarea muy propia de los sistemas de control y de los dispoitivos
roboticos, por ese motivo vamos a inlcuir en este libros unos nejemplos de manejo de
un sensor de medidor de distancia mediante ultrasonidos.
Vamos a usar un sensor comoel mostrado en la imagen anterior con dos pines activos:
Eco y Trigger
Objetivo
Se pretende conocer el funcionamiento de un dispositivo para medir distancias basado en
ultrasonidos.
Funcionalidad:
Vamos a manejar el sensor HC-SR04 que conectaremos a nuestra tarjeta. La medida que
realicemos la mostraremos en un display OLED
Programa
El programa sería el de la siguiente figura.
Básicamente hemos seguido los pasos:
• Cargamos las librerías
from machine import Pin, I2C,ADC
from ssd1306 import SSD1306_I2C
import framebuf
import utime
• Definimos los pines de conexión del dispositivo de ultrasonidos
Trig = machine.Pin(0,machine.Pin.OUT)
Echo = machine.Pin(1,machine.Pin.IN)
• Definimos la conexión I2C del dispositivo OLED.
WIDTH = 128 # Pixels de la Base
HEIGHT = 64 # Pixels de la Altura
# Inicia I2C usando GP4 y GP5 (I2C0)
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=200000)
• Creamos la función de control del dispositivo de ultrasonidos para generar los
impulsos de salida (Trig) y la recepción de los impulsos de (Echo).
• Dentro del bucle while se enviara al display el texto de cada una de las dos líneas
que indicaran
M.Distancia
Distancia: distancia cm
Trig = machine.Pin(0,machine.Pin.OUT)
Echo = machine.Pin(1,machine.Pin.IN)
while Echo.value() == 0:
pulse_start = utime.ticks_us()
while Echo.value() == 1:
pulse_end = utime.ticks_us()
while True:
# Borra el display OLED.
oled.fill(0)
# Añade texto
oled.text("M.Distancia",0,0)
oled.text("Distancia:"+ str(read_ultrasonic())+"cm",0,32) # Coordenada x=0, y=10
# Descarga el texto en la pantalla y lo muestra
oled.show()
Objetivo
Aplicar el uso de un detector de distancia para la emisión de un sonido en función de la
distancia. Esta es la emulación de los sistemas de aparcamiento asistido en los
automóviles.
Funcionalidad:
Vamos a montar el mismo ejemplo anterior, pero en este nuevo, incorporaremos una
función sonora. Se trata de usar la librería “Tonos” con el fin de usar el bloque de
generación de un sonido “toca la frecuencia…” cuyo valor de frecuencia será variable
estando en función de la distancia que nos mide el sensor de distancia.
Multiplicamos el valor de la “Distancia” para conseguir una variación de frecuencias
audibles, también podríamos haber usado la función “rescale”
Entradas salidas:
Los dispositivos que usaremos
Programa:
# Medimos el valor de la distancia con un sensor HC-SR04
# Muestra el valor leído en un dispositivo OLED conectado
# en el bus I2C con la librería ssd1306
# Emite un tono en función de la distancia
from machine import Pin, I2C,ADC,PWM
from ssd1306 import SSD1306_I2C
import utime
# Conectar pin Trig con GP0 como SALIDA
# Conectar pin Echo con GP1 como ENTRADA
while Echo.value() == 0:
pulse_start = utime.ticks_us()
while Echo.value() == 1:
pulse_end = utime.ticks_us()
while True:
valor=read_ultrasonic()
buzzer.freq(valor*100) #Frecuencia del tono
buzzer.duty_u16(8000) #Volumen del sonido
utime.sleep_us(10)
oled.fill(0)
# Añade texto
oled.text("M.Distancia",0,0)
oled.text("Distancia:"+ str(valor)+"cm",0,20) # Coordenada x=0, y=10
oled.text("Frec.:"+ str(valor*100)+" hz",0,40) # Coordenada x=0, y=10
# Descarga el texto en la pantalla y lo muestra
oled.show()
¿Qué es un Servomotor?
Servo
Para entender esto, veamos que físicamente el servomotor se compone de tres cables:
GND, Power (5v) y Control. Es decir que los dos primeros se usan como alimentación en
cuanto el cable de control es usado para enviar la señal de posicionamiento del motor
con una secuencia de pulsos PWM.
Los servo motores de 360° son servos Radio control estándar que se han modificado para
ofrecer un control de velocidad en lazo abierto en lugar de su control habitual de
posición de lazo cerrado, por lo tanto aquí ya no puedes especificar con tu raspberry pi
pico la posición especifica que deseas mover el rotor del motor, sino que por el contrario
estableces la velocidad de giro.
Código:
while True:
angulo = float(input('Ingrese un ángulo: '))
if angulo >= 0 and angulo <= 180:
duty = int((12.346*angulo**2 + 7777.8*angulo + 700000))
servo_180.duty_16(duty)
servo_360.duty_ns(duty)
else:
print('Digite un ángulo entre 0 y 180')
if __name__ == '__main__':
main()
Código:
while True:
angulo = float(input('Ingrese un ángulo: '))
if angulo >= 0 and angulo <= 180:
#nanosegundos
duty = ((12.346*angulo**2 + 7777.8*angulo + 700000))
#milisegundos
duty /= 1000000
#bits
duty = int(duty*1023/20)
servo_180.duty(duty)
servo_360.duty(duty)
else:
print('Digite un ángulo entre 0 y 180')
if __name__ == '__main__':
main()
Objetivo
Funcionalidad
Diagrama del ciclo de trabajo El ciclo de trabajo de la señal PWM se calcula mediante
la siguiente ecuación.
Período = 1/Frecuencia
Período= T encendido + T apagado
Ciclo de trabajo= T encendido / (T encendido +T apagado) * 100 (porcentaje)
Programa
MIN_DUTY = 1600
"""
Este código de ejemplo usa: Maker Pi Pico
Referencia: www.Cytron.io/p-maker-pi-pico
Este código de ejemplo usa: Analog Micro Servo 9g (3V-6V)
Referencia: www.cytron.io/p-analog-micro-servo-9g-3v-6v
"""
from machine import Pin, PWM
import time
while True:
servo.duty_u16(MIN_DUTY) # Establecer ciclo de trabajo
time.sleep_ms(1000)
servo.duty_u16(MAX_DUTY)
time.sleep_ms(1000)
Objetivo
Vamos a controlar un servo pero esta vez lo haremos usando una librería que nos
proporcionan.
Funcionalidad
Nuestro servo ejecutara una secuencia cíclica de 4 posiciones angulares que nosotros
introduciremos mediante un array de 4 datos
Programa
servo=Servo(15)
servo.ServoAngle(0)
Montaje de la practica
Proponemos una variante del ejemplo visto. La variación consiste en que a la vez que se
realizan los giros de posición podamos imprimir el ángulo girado en la consola de
Thonny
Trabajaremos con el servo conectado a GP15 y el tiempo entre cada posición lo fijaremos
a 1000 ms
try:
while True:
for a in angulos:
servo.ServoAngle(a)
print("angulo =",a)
time.sleep_ms(1000)
except:
servo.deinit()
Objetivo
Con este ejemplo queremos controlar cuatro servos mediante la tarjeta MAKER PI
RP2040
Funcionalidad
Vamos a conectar cuatro servos a los pines GP15, GP14, GP13 y GP12 que vamos a
controlar a la vez.
Queremos controlar el giro mediante dos pulsadores, los que están en la propia tarjeta
GP20 y GP21 de tal manera que con cada uno de ellos hacemos que los servos se muevan
en ambos sentidos de giro.
El giro será de 1º por cada vez que pulsemos el botón correspondiente. El tiempo de
retardo en el pulsador para evitar rebotes será de 100 ms (time.sleep(0.1))
Programa
import machine
import utime
import time
pwm1.freq(50)
pwm2.freq(50)
pwm3.freq(50)
pwm4.freq(50)
angle = 0.0
min_dutycycle = 2200
max_dutycycle = 8300
dutycycle = 0
import machine
import utime
import time
angle = 0.0
min_dutycycle = 2200
max_dutycycle = 8300
dutycycle = 0
while True:
print("Angulo",angle,"Ciclo de trabajo", dutycycle)
# Lee valores de los Botones.
if button1.value():
angle += 5
time.sleep(0.1)
if button2.value():
angle -= 5
time.sleep(0.1)
# Limita el angulo al rango 0 a 180 grados.
if angle > 180:
Aspecto de Thonny
Se propone una variacion del programa anterior en el que queremos que el servo realice
un movimiento de vaivén recorriendo un arco equivalente a 120º.
Queremos que el servo gire en sentido de las agujas del reloj en pasos de 1º hasta llegar
a 120º. Seguidamente queremos que el giro sea igual pero en sentido contrario.
El tiempo entre paso y paso queremos que sea de 15 ms (time.sleep_ms(15) )
El programa.
from myservo import Servo
import time
servo=Servo(15)
servo.ServoAngle(0)
time.sleep_ms(1000)
try:
while True:
for i in range(0, 120, 1):
servo.ServoAngle(i)
time.sleep_ms(15)
for i in range(120, 0, -1):
servo.ServoAngle(i)
time.sleep_ms(15)
except:
servo.deinit()
Objetivo
Funcionalidad
El valor leído de nuestro canal analógico GP27 se debe mapear al valor de 0 a 180 ya
que haremos girar el servo en ese rango de valor, para ello recurrimos a un sencillo
cálculo:
servo.ServoAngle(0)
Programa
servo=Servo(15)
adc=ADC(27)
servo.ServoAngle(0)
try:
….
Except:
Programa completo
servo=Servo(15)
adc=ADC(27)
servo.ServoAngle(0)
try:
while True:
adcValue = adc.read_u16()
angle = int((adcValue * 180) / 65535)
servo.ServoAngle(int(angle))
time.sleep_ms(50)
print(angle)
except:
servo.deinit()
Montaje de la practica
La parte de control como vemos estará en manos de los pines de la derecha que se llevaran
a la unidad MAKER PI PICO
Nuestros ejemplos los vamos a implementar con la tarjeta MAKER PI RP2040 que trae
ya implementado el controlador de motores cc.
Objetivo
Funcionalidad
Para realizar este programa usaremos la librería “motor” que nos permitirá controlar los
dos motores acoplables a la tarjeta.
Con la función “speed” podemos mover los motores modificando los parámetros de la
función. La función “brake” detiene el motor
Programa
"""
Control de dos motores MOTOR1 y MOTOR2
Con la tarjeta MAKER PI RP2640
Usando una librería
"""
Objetivo
Funcionalidad
M1A.duty_u16(xx)
M1B.duty_u16(xx)
cuyo parámetro “xx” es el valor comprendido entre 0 y 65535 que se encargara de enviar
una tensión variable en modo PWM a las salidas de control:
M1A = machine.PWM(machine.Pin(8))
M1B = machine.PWM(machine.Pin(9))
Programa
M1A = machine.PWM(machine.Pin(8))
M1B = machine.PWM(machine.Pin(9))
M1A.freq(50)
M1B.freq(50)
print("Adelante lentamente")
M1A.duty_u16(0)
M1B.duty_u16(30000)
utime.sleep(1)
M1A.freq(50)
M1B.freq(50)
while True:
print("Adelante lentamente")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(30000)
utime.sleep(1)
print("Parar")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
utime.sleep(1)
print("Adelante")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(65535)
utime.sleep(1)
print("Parar")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
print("Atras")
M1A.duty_u16(65535) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
utime.sleep(1)
print("Parar")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
utime.sleep(1)
print("Atras Lentamente")
M1A.duty_u16(30000) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
utime.sleep(1)
print("Freno")
M1A.duty_u16(65535) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(65535)
utime.sleep(1)
Montaje de la practica
• Modificar los tiempos entre cada movimiento así como comprobar los cambios
cuando se modifican los valores de la velocidad
M1A.duty_u16(xx)
M1B.duty_u16(xx)
utime.sleep(1)
Objetivo
Controlar dos motores de un robot para situarlo en distintas posiciones usando el mismo
programa anterior
Funcionalidad
Se trata de realizar el mismo programa anterior pero esta vez usando dos motores que
conectamos a los terminales Motor1 y Motor 2 de la tarjeta
Programa
while True:
print("Parar")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
M2A.duty_u16(0)
M2B.duty_u16(0)
utime.sleep(1)
print("Adelante")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(65535)
M2A.duty_u16(0)
M2B.duty_u16(65535)
utime.sleep(1)
print("Parar")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
M2A.duty_u16(0)
M2B.duty_u16(0)
utime.sleep(1)
print("Atras")
M1A.duty_u16(65535) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
M2A.duty_u16(65535)
M2B.duty_u16(0)
utime.sleep(1)
print("Parar")
M1A.duty_u16(0) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
M2A.duty_u16(0)
M2B.duty_u16(0)
utime.sleep(1)
print("Atras Lento")
M1A.duty_u16(30000) # El ciclo de trabajo debe estar entre 0 y 65535
M1B.duty_u16(0)
M2A.duty_u16(30000)
M2B.duty_u16(0)
utime.sleep(1)
print("Frenar")
Montaje de la practica
• Modificar los tiempos entre cada movimiento así como comprobar los cambios
cuando se modifican los valores de la velocidad
M1A.duty_u16(xx)
M1B.duty_u16(xx)
M2A.duty_u16(xx)
M2B.duty_u16(xx)
utime.sleep(1)
Objetivo
Funcionalidad
Trabajamos con señales PWM modificando el valor de salida de los mencionados pines
M1A y M1B con la ayuda de la señal analógica que estableceremos en el pin ADC(27)
mediante la conexión de un potenciómetro
Programa
2. Designar la entrada analógica ADC(27) y los pines de salida PWM M1A y M1B
M1A.freq(50)
M1B.freq(50)
M1A = machine.PWM(machine.Pin(8))
M1B = machine.PWM(machine.Pin(9))
M1A.freq(50)
M1B.freq(50)
while True:
velocidad = pot.read_u16()
print("velocidad", velocidad)
# El ciclo de trabajo debe estar entre 0 y 65535
M1A.duty_u16(0)
M1B.duty_u16(velocidad)
time.sleep(0.1)
Montaje de la practica
Objetivo
Funcionalidad
Para el control del sentido de giro lo haremos con un pulsador conectado en el GP17
Imprimiremos el valor de la velocidad en % de tal manera que para ello tendremos que
mapear el valor de la “velocidad”
Programa
sentido_giro = Pin(17,Pin.IN)
derecha = Pin(3, Pin.OUT) # GP3 Derecha
izquierda = Pin(5, Pin.OUT) # GP5 Izquierda
pot = ADC(27) #Lectura de señal analógica
M1A = machine.PWM(machine.Pin(8))
M1B = machine.PWM(machine.Pin(9))
M1A.freq(50)
M1B.freq(50)
derecha.value(0)
izquierda.value(0)
velocidad = pot.read_u16()
velocidad_porcentual = map(velocidad, 0, 65535, 0, 100)
if sentido_giro.value() == 1:
# El ciclo de trabajo debe estar entre 0 y 65535
M1A.duty_u16(0)
M1B.duty_u16(velocidad)
derecha.value(0)
izquierda.value(1)
print('Velocidad {:.0f}'.format(velocidad_porcentual), "Derecha")
time.sleep(0.1)
else:
M1A.duty_u16(velocidad)
M1B.duty_u16(0)
time.sleep(0.1)
derecha.value(1)
izquierda.value(0)
print('Velocidad {:.0f}'.format(velocidad_porcentual), "Izquierda")
time.sleep(0.1)
M1A.freq(50)
M1B.freq(50)
derecha.value(0)
izquierda.value(0)
while True:
velocidad = pot.read_u16()
velocidad_porcentual = map(velocidad, 0, 65535, 0, 100)
Montaje de la practica
Objetivo
El dispositivo que vamos a usar en esta práctica es muy útil para mostrar valores
numéricos en nuestras aplicaciones.
Funcionalidad
Los pines de conexión de este dispositivo son: Vcc, GND, DIO y CLK
En nuestro caso vamos a usar una librería que nos facilitará el manejo del dispositivo.
Se trata de la librería “tm1637”.
Para la prueba configuraremos el pin GP27 (entrada analógica) para que a través de un
potenciómetro envíe una señal numérica al display.
Programa
try:
while True:
#mapeamos el valor del canal GP28
z=convert(adc.read_u16(), 0, 65535, 0, 1000)
#Mostramos el valor en el display de 4 dígitos
display.number(z)
print("ADC Valor:", z, "V")
sleep_ms(100)
except:
pass
Objetivo
Vamos a realizar varios ejemplos de control de la matriz de LEDs de 8x8 con los que
probaremos sus posibilidades
Funcionalidad
Nuestro dispositivo es una matriz de LEDs que podemos controlar direccionando cada
uno de los LEDs que la componen de manera individual. Este elemento es muy usado
para montar anuncios luminosos o indicadores.
Para su gobierno usamos además de los pines Vcc y GND tres pines mas: DIN (entrada
de datos), CS (habilitación) y CLK (reloj).
Podríamos encadenar varios de estos dispositivos uniendo los pines de salida con los de
entrada del anterior.
Programas
Ejemplo1
La programación tiene una parte común que será la de configuración del dispositivo en la
que designaremos los pines y funcionalidad del la matriz 8x8
Se trata de encender y apagar los LEDs (0,0), (0,7),(7,) y (7,7) a modo de Blink
import max7219
from machine import Pin, SPI
from time import sleep
2. Inicialización de SPI
spi = SPI(0,sck=Pin(2),mosi=Pin(3))
cs = Pin(5, Pin.OUT)
display.brightness(10)
display.fill(False)
5. Blink cuatro leds. Se trata de activar y desactivar los LEDs: (0,0), (0,7),(7,) y
(7,7)
while True:
#Blink en el LED 0,7
display.pixel(0,0, True) #Enciende el LED 7,7
display.pixel(0, 7, True)
display.pixel(7, 0, True)
display.pixel(7, 7, True)
display.show()
sleep(0.5)
display.pixel(0,0, False) #Enciende el LED 7,7
display.pixel(0,7, False)
display.pixel(7,0, False)
display.pixel(7,7, False)
display.show()
sleep(0.5)
El programa completo es
spi = SPI(0,sck=Pin(2),mosi=Pin(3))
cs = Pin(5, Pin.OUT)
display.brightness(10)
display.fill(False)
while True:
#Blink en el LED 0,7
display.pixel(0,0, True) #Enciende el LED 7,7
display.pixel(0, 7, True)
display.pixel(7, 0, True)
display.pixel(7, 7, True)
display.show()
sleep(0.5)
display.pixel(0,0, False) #Enciende el LED 7,7
display.pixel(0,7, False)
Ejemplo 2
Se trata de mostrar los caracteres siguientes que los recogeremos de las cadenas
Programa completo
spi = SPI(0,sck=Pin(2),mosi=Pin(3))
cs = Pin(5, Pin.OUT)
display.brightness(10)
while True:
display.fill(0)
display.text('PICO',0,0,1)
display.show() #Muestra la letra P
display.fill(0)
display.text('1234',0,0,1)#Muestra el numero 1
display.show()
sleep(1)
display.fill(0)
display.text('done',0,0,1) #Muestra la d
display.show()
sleep(1)
Ejemplo 3
Con este ejemplo terminamos de usar funciones para dibujar puntos, líneas, cuadrados,
etc.
spi = SPI(0,sck=Pin(2),mosi=Pin(3))
cs = Pin(5, Pin.OUT)
display.brightness(10)
while True:
#Muestra un LED
display.fill(False)
display.pixel(1,2,True)
display.show()
sleep(2)
#Muestra una línea horizontal
display.fill(False)
display.hline(0,0,6,True)
display.show()
sleep(2)
#Muestra una línea vertical
display.fill(False)
display.vline(0,0,6,True)
display.show()
sleep(2)
#Muestra línea
display.fill(False)
display.line(0,0,7,7,True)
Montaje de la practica
Objetivo
Con esta práctica queremos aprender cómo usar los puertos I2C de Raspberry Pi Pico.
El bus I2C identifica periféricos (nodos) con direcciones de 7 bits. Cada nodo puede
actuar como maestro o esclavo mientras se comunica. El dispositivo maestro
generalmente genera la señal de reloj en la línea SCL. Varios dispositivos esclavos
pueden comunicarse con un único dispositivo maestro.
• Modo estándar (con velocidades de datos de 0 a 100 kbps),• modo rápido (con
velocidades de datos inferiores o iguales a 400 kbps)
• Modo rápido plus (con velocidades de datos inferiores o iguales a 1000 kbps).
Los dispositivos en modo rápido son compatibles con versiones anteriores. Por ejemplo,
con el sistema de bus I0C de 100 a 2 kbps, los dispositivos de modo rápido pueden
conectarse con dispositivos de modo estándar. Sin embargo, debido a que no pueden
mantenerse al día con la velocidad de transmisión más rápida y experimentarían estados
impredecibles, los dispositivos de modo estándar no son compatibles con versiones
superiores y no deben incluirse en un sistema de bus I2C de modo rápido.
Vemos en la siguiente imagen el pinout de Raspberry Pi Pico. Los pines marcados como
SDA y SCL se pueden utilizar para la comunicación I2C.
Métodos generales
En el caso del hardware I2C, la frecuencia de reloj real puede ser inferior a la
frecuencia solicitada. Esto depende del hardware de la plataforma. El La
velocidad se puede determinar imprimiendo el objeto I2C.
I2C. Deinit()
Apague el bus I2C.
Disponibilidad: WiPy.
I2C. escanear()
Escanee todas las direcciones I2C entre 0x08 y 0x77 inclusive y devuelva una
lista de los que responden. Un dispositivo responde si tira de la línea SDA baja
después de Su dirección (incluyendo un bit de escritura) se envía en el bus.
Los métodos siguientes implementan las operaciones primitivas del bus del controlador
I2C y pueden combinarse para realizar cualquier transacción I2C. Se proporcionan si
necesita más control sobre el bus, de lo contrario se pueden utilizar los métodos
estándar (ver más abajo).
Después de que se hayan realizado las conexiones adecuadas, podemos cargar un script
para escanear todos los dispositivos conectados al bus I2C. Copie el código siguiente y
péguelo en un nuevo proyecto en Thonny IDE.
Al ejecutarse el programa la ventana del Shell mostrará la dirección del dispositivo que
luego usaremos en nuestro código. A continuación se muestra una imagen de la salida
que se muestra en Thonny IDE, con 0x3C devuelto como la dirección I2C de la pantalla
OLED.
• Maker Pi de Cytron
Marzo 2023