17 junio, 2024

Rust-Embebido «Arduino» Introducción parte 1

Continuamos con la experiencia en Rust en el desarrollo de sistemas integrados (Embebidos) en sistemas basado en microcontrolador, podemos ver una descripción del Rust-embebidos en el enlace https://docs.rust-embedded.org/book/ y nosotros utilizaremos una placa de Arduino que esta más extendida.

Lo primero es saber que deberemos instalar para tener nuestro entorno para programar Arduino con Rust, en nuestro caso realizaremos la pruebas en un entorno Linux (distribución ArchLinux)) pero podremos utilizar cualquier sistema que disponga de las herramientas de desarrollo del microprocesador AVR que es el que utiliza Arduino.

Nuestro Arduino trabaja normalmente con el micro AVR(atmega328) por lo tanto lo primero sera instalar las herramientas necesarias que nos permitan compilar, enlazar y subir el ejecutable a la placa.

Todo el código de esta serie de POST los podremos encontrar donde tenemos los códigos del libro «De 0 a 100 con Arduino y ESP32» «https://github.com/pinguytaz/Arduino-ESP32/tree/master/CuadernoTecnico» exactamente en la carpeta «RustArduino» estarán los códigos y ejemplos de esta serie de POST de programación de Arduino con Rust.

Entorno AVR

  • pacman -S avr-gcc avr-libc (Linker y compilador)
  • pacman -S arduino-avr-core avrdude (avrdude para Flashear el microprocesador)
  • pacman -S systemd pkgconf
  • Debugs (No necesarias en principio)
  • pacman -S avr-gdb qemu-system-avr
  • pacman -S elf2nucleus

También precisaremos configurar nuestro Rust con herramientas para integrar Rust con las herramientas anteriores:

rustup toolchain install nightly
cargo install ravedude

Como es muy cómodo iniciar el primer código desde una plantilla ejecutaremos las siguientes instrucciones que nos preguntarán por el nombre del proyecto.

cargo install cargo-generate
cargo generate --git https://github.com/Rahix/avr-hal-template.git

Esto nos genera una serie de directorios y ficheros y deberemos configurar algunos:

.cargo/config.toml

En este fichero definimos el target y como ejecutar ravedude para la carga del programa.

UNO: runner = "ravedude uno -cb 57600" 
NANO Boot OLD: runner = “ravedude nano -P /dev/ttyUSB0 -cb 57600" 

Deberemos poner el puerto que corresponda en nuestro caso.

/avr-specs Ficheros json que define los target.

/src/main.rs Nuestro código a compilar.

Cargo.toml Con las dependencias necesarias inicialmente.

README.md, rust-toolchain.toml, etc.

Para ejecutar la consola, una vez este cargado el programa, y así poder debugear nuestro programa ejecutaremos

~/.cargo/bin/ravedude -P --open-console --baudrate 57600
Los tipos de placa se pueden ver ejecutando --help en nuestro caso sera uno.

Con todo esto ya podremos compilar «cargo build» que nos generara un fichero ELF que con el comando file podemos ver que es de tipo AVR de 8 bits.

file analogicos.elf
analogicos.elf: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, with debug_info, not stripped

y para que ademas de compilarlo se suba a nuestra placa, gracias a las configuraciones anteriores, es tan sencillo como ejecutar «cargo run» y ademas nos ejecutara la consola de forma automatica.

Ahora ya estamos preparados para generar nuestro primer programa (el típico blinker de un led) que es el que se crea con la plantilla, en nuestro ejemplo le hemos añadido una salida por consola.

#![no_std]
#![no_main]

use panic_halt as _;


#[arduino_hal::entry]
fn main() -> ! {
    let dp = arduino_hal::Peripherals::take().unwrap();
    let pins = arduino_hal::pins!(dp);      // Obtenemos los pines.
    let mut led = pins.d13.into_output();   // define el Pin13 digital como salida. (led de la placa)
    let mut led2 = pins.d4.into_output();   // define el Pin4 digital como salida.

    // Configuracion de consola
    let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

    loop {
        led.toggle();
        led2.toggle();
        arduino_hal::delay_ms(10000);

        // Escribe blink
        _ = ufmt::uwriteln!(serial, "Blink!");    // Salida por consola.
    }
}

Debemos tener en cuenta en la programación el poner las directivas siguientes al principio:

  • #![no_std] No usa la librería estándar y si la Core.
  • #![no_main] No utilizar la función main estándar de un programa típico de Rust.
  • use panic_halt as _; Tratamiento de pánicos y errores graves.
  • #[arduino_hal::entry] Punto de entrada del programación, donde iniciamos nuestro programa.

En este caso no tenemos una función setup() y otra loop() sino que tenemos una función main en la cual pondremos un bucle loop para realizar la función loop() de la programación normal de Arduino.

Antes de esta función y al igual que solemos hacer en la función setup() de una programación típica de Arduino es definir los periféricos a utilizar, en nuestro caso solo pines de salida.

Hemos podido ver en el código anterior como con la macro «uwriteln!» podíamos sacar información por consola, o lo que es lo mismo tener una comunicación serie, a continuación ponemos un pequeño fragmento de código en la que se ve como manejar el puerto serie de nuestro Arduino no solo para salida de datos sino también para entrada.

use arduino_hal::prelude::*;   // Liberia necesaria para 

// Configuración de la velocidad.
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

// Envío texto
_ = ufmt::uwriteln!(serial, "Añade nueva linea");
_ = ufmt::uwriteln!(serial, "Sin nueva linea");

// Permite parámetros {}
_ = ufmt::uwriteln!(serial, "Añade nueva linea {}",a);


// Lectura de datos y envío.
let b = nb::block!(serial.read());   // Lectura
nb::block!(serial.write(b.expect("POOOOO")));    // Escritura

Con esto terminamos la primera parte pero aun queda por explicar:

  • E/S Digitales
  • Uso de las entradas analógicas ADC
  • Uso de los pines PWM
  • Uso de interrupciones externas.
  • Bus I2C
  • Timer usando servomotores
  • Timer para uso del sonar HC-SR04

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Información básica sobre protección de datos Ver más

  • Responsable: Javier.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento:  No se ceden o comunican datos a terceros para prestar este servicio. El Titular ha contratado los servicios de alojamiento web a Hostinger.es que actúa como encargado de tratamiento.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos. Contiene enlaces a sitios web de terceros con políticas de privacidad ajenas que podrás aceptar o no cuando accedas a ellos. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Ver
Privacidad