Lorem Ipsum

Lorem ipsum dolor sit amet, consectetur adipiscing elit

Como instalar un servidor FTP en una Raspberry Pi

En ocasiones necesitamos ubicar archivos en algún lugar y además queremos que estos archivos estén accesibles desde cualquier lugar que este en red,  para estos casos lo ideal es tener un servidor FTP.  Existen varias opciones para tener tu propio servidor FTP, en este tutorial vamos a ver como instalar un servidor FTP en una Raspberry Pi.

Existen varios software para instalar un servidor FTP en nuestra Raspberry Pi, uno de los más usados es el proFTPd, este Software es muy fácil de instalar y muy fácil de configurar, primero trataremos las instalación del mismo y a continuación veremos el archivo de configuración del servidor FTP en nuestra Raspberry PI.

Instalando proFTPd

La instalación de proFTPd, es muy simple y se realiza como cualquier otra instalación, para ello necesitamos abrir un terminal y descargar el paquete con el comando

Sudo get-apt install proftpd

Durante la instalación del servidor ftp proftpd, se nos preguntará que tipo de instalación queremos, “from inetd” o “standalone” , la diferencia entre ambas es que la instalación de proFTPd standalone configura el servidor para estar ejecutándose 24/7 mientras que la opción inetd solo ejecuta el servidor ftp cuando un cliente se conecta con lo que ahorra recursos de la Raspberry Pi.

Si vamos a disponer de varios usuarios que se pueden conectar simultáneamente y con cierta frecuencia, es recomendable utilizar la instalación de  proFTPd standalone.

FOTO1

Una vez instalado proFTPd, solo nos queda configurarlo  y crear y dar permisos a los usuarios que queramos.

Configurando proFTPd

Antes de comenzar con la configuración, vamos a hablar de los usuarios, básicamente, existen 3 tipos de usuarios:

  • Root
  • Usuario
  • Anonimus

proFTPd, puede actuar de diferente manera según el usuario que intente acceder al servidor, por ejemplo podemos denegar el acceso a los usuarios anónimos, permitir el acceso a una carpeta de usuario específica y permitir el acceso a todas las carpetas a los usuarios root. Por defecto proFTPd utiliza la lista de usuarios y passwords de la Raspberry Pi.

El usuario y password para root por defecto de Rasberry Pi son:

User: Pi

Password: Raspberry

Adicional mente si queremos crear un usuario simple sin derechos de administrador, lo creamos con el comando:

sudo adduser usuario1

y le añadimos un password con el comando:

sudo passwd  usuario1

Creamos la carpeta destino donde podrán acceder los usuarios normales

Sudo mkdir FTPfolder

Ahora que ya tenemos creados los usuarios, vamos ver como configuramos proFTPd y permitir o denegar el acceso a los diferentes usuarios.

La configuración del servidor FTP, se realiza a través del archivo de configuración  proftpd.conf, para editarlo, ejecutamos el comando:

sudo nano /etc/proftpd/proftpd.conf

Este archivo configura el propio servidor y por otro lado la gestión de los usuarios,  es recomendable dejar la configuración por defecto del servidor,  aunque podemos cambiar el nombre del servidor, el tipo de servidor, el timeout etc…

Para asignar la carpeta que hemos creado al usuario que hemos creado, añadimos la línea:

DefaultRoot /home/FTPfolderusuario1 

Con la línea anterior asignamos al usuario1 la carpeta destino FTPfolder, pero permitimos al usuario root el acceso a todas las carpetas.

Para no permitir las conexiones de usuarios Anonymus, nos aseguramos que no hay código entre las etiquetas <Anonymous ftp> y </Anonymous> o directamente borramos el bloque entero.

Si quieres saber más sobre la gestión de los usuarios te recomiendo que visites la página de los creadores proFTPd

Una vez realizados los cambios oprtunos guardamos el archivo y volvemos a cargarlo para que se apliquen los cambios

sudo service proftpd reload

Ya tenemos nuestro servidor FTP funcionando…

Accediendo al servidor FTP.

Para verificar que todo está en orden y funciona correctamente, abrimos un navegador de internet y escribimos la dirección de nuestro servidor FTP

ftp://<IP-Rapsberry> 

Si todo ha funcionado, el navegador nos debería mostrar nuestra carpeta destino, según el usuario con el que estemos logeados en la Raspberry

Para poder subir ficheros desde cualquier ordenador se puede utilizar cualquier cliente FTP disponible como FILEZILLA, WinSCP, etc…

Como conectarnos a un módulo ESP32-CAM desde Python

Hoy en día la difusión multimedia está muy extendida e integrada en nuestras vidas sin que seamos consciente de ello, el termino stream lo relacionamos con la reproducción de información de audio o video. Esta información puede estar disponible en forma de archivo como puede ser un archivo de video o audio almacenado en el disco de un servidor o bien puede ser una cámara IP a la cual podemos acceder para ver la imagen en tiempo real.

Una de las grandes ventajas del streaming es que la información se muestra en tiempo real, es decir, no es necesario descargar el archivo completo para poder verlo o escucharlo.

Existen varios protocolos para poder hacer streaming, algunos son más avanzados como puede ser RSTP, que da la posibilidad de pausar, la reproducción y otros más simples que no ofrecen ningún control.

En este tutorial, vamos ver como conectarnos a un módulo ESP32-CAM desde Python con la librería OPENCV, mediante Http.

Es necesario que en el IDE que utilices tengas instaladas las tarjetas ESP32, si no las tienes, en el IDE de arduino ves a archivo–> preferencias  y en el gestor de URLs adicionales de tarjetas pega la siguiente dirección:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 

Ahora vamos a Herramientas–> Placa –> Gestor de tarjetas y buscamos ESP32 (expressif) e instalamos la última versión disponible.

Seleccionamos la placa AI Thinker ESP32-CAM (aunque sea el clon de china) y el puerto serie correspondiente, seleccionando esta placa, no es necesario realizar nada más, las particiones ya se configuran solas.

Lo primero que hacemos será cargar en el módulo ESP32-CAM el software de ejemplo para la cámara,  recordar que tenemos que introducir el SSID de nuestra red y el Password.

Este módulo viene sin una interface para poder subir el SW, por lo que para poder subir el SW al módulo necesitaremos un conversor USB a TTL y conectarlo al ESP32-CAM tan y como se ve en la imagen.

Solo nos queda compilar y subir el SW al ESP32-CAM, una vez se ha subido el software, eliminamos el puente entre  D01 y GND y apretamos el botón de Reset. Si lo hemos hecho bien, en modulo se conectará a nuestra red Wifi y por la consola nos indicará la IP asignada y los puertos asignados para Web Server y para el Streaming de video, será el puerto 81.

Necesitamos apuntar la IP y toda la ruta para que desde Python podamos acceder a la cámara, esta ruta debería ser algo:

http://<tu_ip_asignada>:81/stream 

Para verificar que es la url correcta, cópiala  en el navegador y deberías tener acceso directo al video, si no es así, hay algo que no tienes bien.

Es hora de ponernos con Python, para ello hemos de tener instaladas las librerías OpenCV y numpy.

Accederemos a la cámara mediante su dirección IP, para ello abrimos la url y buscamos el inicio y final de la imagen enviada, una vez sabemos la ubicación y la longitud de la imagen, la decodificamos y la mostramos en una ventana.

import cv2
from urllib.request import urlopen
import numpy as np

stream = urlopen('http://192.168.43.6:81/stream')
bytes = bytes()
while True:
    bytes += stream.read(1024)
    a = bytes.find(b'\xff\xd8')
    b = bytes.find(b'\xff\xd9')
    if a != -1 and b != -1:
        jpg = bytes[a:b+2]
        bytes = bytes[b+2:]
        if jpg :
            img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
            cv2.imshow('ESP32 CAM', img)
    if cv2.waitKey(1) & 0xff == ord('q'):
        break
stream.release()
cv2.destroyAllWindows()

En la variable img tenemos la imagen que nos envía el ESP32-CAM, podemos guardar, reenviarla, tratarla, buscar algún objeto, etc…  a partir de aquí es cosa tuya….

Puedes descargar el script para Python 3 desde mi repositorio.

Sensor de temperatura con Arduino y Termistor

Hoy en día es posible hacer un medidor de temperatura de varias maneras, aquí os explicaré como hacer un sensor de temperatura con Arduino y un termistor.  Un termistor es un componente pasivo bastante barato comparado con sensores digitales para medición de temperatura. Para poder interactuar con los sensores digitales, arduino necesita las librerías específicas, las cuales las podemos encontrar por la red o las podemos programar con ayuda de los datasheet…

Básicamente un termistor es una resistencia que varía su valor en función de la temperatura del entorno. Existen 2 tipos de termistores que se categorizan en PTC (Positive Temperature Coefficient) y NTC (Negative Temperature Coefficient), la diferencia es que las PTC aumentan su resistencia con el aumento de temperatura y las NTC disminuyen su resistencia  con el aumento de temperatura.

En este tutorial, vamos a utilizar el típico termistor  que utilizan lasimpresoras 3D en el extrusor, son muy baratos y muy fáciles de encontrar. El modelo que utilizaré es de 100K y un coeficiente B 3950, estos dos valores son básicos para poder hacer los cálculos y conversiones a temperatura.

Termistor NTC 100K 3950 Arduino

Los 100K es el valor de la NTC que nos indica el fabricante para una temperatura ambiente de 25ºC, y el parámetro B y una constante que define la curva de temperatura del termistor, este parámetro nos lo da el fabricante.

Circuito básico del termistor

Como he dicho anteriormente, un termistor es un elemento pasivo resistivo,  que varía su resistencia en función de la temperatura, por lo que si sabemos el valor de la resistencia del termistor, podremos calcular la temperatura.

Para conocer el valor del termistor, 

colocamos una resistencia en serie con el termistor y medimos la caída de tensión en el termistor, una vez conocemos la caída de tensión en el termistor, conoceremos la caída de tensión en la resistencia y con un  simple divisor de tensión conoceremos el valor resistivo de la NTC.

Divisor de tension Arduino

En el circuito de la figura anterior la salida VOUT viene dada por la fórmula:

Vout=\frac{R2}{R1+R2}*Vcc

Si consideramos que VOut, la mediremos con el ADC (VADC) de arduino, R1 = 100K y VCC = 3v3 y su valor en el ADC 1023, podemos despejar R2 para conocer el valor del termistor:

R2=\frac{Vout*R1}{Vcc-Vout}= \frac{Vadc*100k}{1023-Vadc}

R2=\frac{Vadc*R1}{1023-Vadc}

Conversión a temperatura

Y ahora que ya conocemos el valor resistivo del termistor que hacemos?, pues solo nos hace falta aplicar las ecuaciones de Steinhart–Hart, para ello utilizamos la siguiente formula:

\frac{1}{T}=\frac{1}{T0}+\frac{1}{B}*\ln \frac{R}{R0}

T –> Temperatura que queremos conocer (grados Kelvin)

T0–> Temperatura nominal de la NTC para esta NTC 25º

B –> Constante de la NTC para este modelo 3950

R –> Resistencia nominal de la NTC para este modelo 100K

R0 –> Resistencia que hemos calculado anteriormente

Una vez calculado el valor de T lo pasamos a grados centígrados simplemente restándole 273,15 y ya conocemos la temperatura de ambiente donde se encuentra la NTC

Si queremos saber el valor en grados Fahrenheit aplicamos la siguiente formula de conversión:

F=\frac{C*9}{5}+32

Conectando el termistor a Arduino

En este punto nos toca realizar el montaje final del divisor de tensión con el termistor a Arduino, para ello conectamos la salida VOut al pin A0 de Arduino y alimentamos nuestro divisor de tensión mediante la salida estabilizada de 3v3 que dispone Arduino Nano.

Conectamos la entrada Aref de Arduino a 3v3, con esta conexión le indicaremos a Arduino que el valor máximo del ADC (1023) corresponde a una tensión de 3v3.

analogReference(EXTERNAL);
Termistor divisor de tension arduino

Sensor de temperatura con Arduino y un termistor, el software de Arduino

Hora de implementar en Arduino toda la teoría que he explicado anteriormente, el sketch básico para leer la temperatura y mostrarla por la consola es el siguiente:

#define termistorPin A0
#define termistorNominalRes 100000
#define termistorNominalTemp 25
#define termistorBValue 3950
#define VoltageDividerResistor 100000
float termistorRes = 0.0;
float steinhart;
void setup() {
    Serial.begin(115200);
    analogReference(EXTERNAL);
}

void loop() {
  termistorRes = ((float)analogRead (termistorPin)* VoltageDividerResistor)/(1023 - (float)analogRead (termistorPin));
  steinhart = termistorRes / termistorNominalRes;     // (R/Ro)
  steinhart = log(steinhart);                         // ln(R/Ro)
  steinhart /= termistorBValue;                       // 1/B * ln(R/Ro)
  steinhart += 1.0 / (termistorNominalTemp + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                        // Invert  
  steinhart -= 273.15;                                // convert to C
  Serial.print("Temperature "); 
  Serial.print(steinhart);
  Serial.println(" *C");
  delay(1000);
}

Podéis descargar el software dese mi repositorio en este link.

Manejo de Interrupciones en Arduino

Hay ocasiones en la que nos interesa que el flujo principal del programa este haciendo unas tareas y cuando se genera un evento pre-programado dejarlo todo para atender este evento, una vez atendido se continúa con la ejecución normal del programa, esto se consigue con el manejo de interrupciones en Arduino. Para estos casos existen las interrupciones, una característica de todos los microcontroladores incluido arduino.

Un ejemplo muy simple podría ser un simple motor, imaginemos que tenemos que controlar el giro de un motor y nos interesa saber cuándo el eje llega a una posición determinada en la tenemos instalado algún tipo de sensor, óptico, inductivo, capacitivo… este sensor nos dará un pulso justo cuando el eje este en la posición y es ese preciso momento que el software necesita conocer que el eje está en la posición, para este caso utilizaremos una interrupción por hardware.

También existen las llamadas interrupciones de software, este tipo de interrupciones están bastante limitadas en Arduino, la mayoría de microcontroladores te permiten activar por software algún Flag de interrupción para poder generar una interrupción cunado programamos el Software para reconocer alguna situación, lamentablemente en Arduino este tipo de interrupciones están limitadas a los timers, el timer0 ya dispone de una función específica para poder generar una interrupción cada x tiempo.

Interrupciones por Hardware

Según qué placa de desarrollo Arduino tengamos, dispondremos de más o menos pines con capacidad de interrupción, aquí pongo una tabla por modelo de placa de desarrollo y los pines de interrupción asociados:

ModeloINT0INT1INT2INT3INT4INT5
Mini23
Nano23
Uno23
Leonardo32017
Mega2321201918
DueTodos los pines
Definicion pines Arduino Interrupciones Pinout

A la hora de programar nuestra ISR (Interruption Service Routine) debemos tener en cuenta varias cosas:

  • El código ha de ser muy simple, activar alguna bandera, actualizar variable…. Durante el tiempo que se está ejecutando la ISR, el programa está parado, pudiendo llegar nuevas interrupciones las cuales no serían atendidas.
  • Las variables que se manipulen en la ISR se han de declarar como variables “volatile”
  • Las funciones de los timers como micros(), milis(), etc… dejan de dar servicio, esto es debido a que estas funciones también utilizan interrupciones y al estar tratando una interrupción, se desatiende el resto de interrupciones.

ISR es la rutina que realiza el manejo de interrupciones en Arduino, es una abreviacion generica dentro del mundo de la programacion.

¿Cómo se detecta una interrupción por Hardware?

Cuando hablamos de interrupciones por hardware, decimos que el micro ha de ser capaz de reconocer que en el pin asociado a la interrupción ha ocurrido algún evento que queremos controlar.El manejo de interrupciones en Arduino puede ser por Hardware o por Software (interrupcion que veremos mas tarde). Estos eventos pueden ser de 5 tipos:

  • FALLING, arduino detecta un flanco de bajada en el pin de interrupción
  • RISING, Arduino detecta un flanco de subida en el pin de la interrupción
  • CHANGE, Arduino detecta un cambio de estado en el pin de la interrupción
  • LOW, Arduino detecta el estado LOW en el pin de la interrupción
  • HIGH, Arduino detecta el estado HIGH en el pin de la interrupción

Para definir la interrupción, son necesarios 2 pasos, el primer paso es parametrizar la interrupción, es decir indicar el pin a controlar, el evento a controlar y la función que se ejecutará al reconocer la interrupción, el segundo paso es generar la propia ISR para tratar la interrupción.

attachInterrupt ( digitalPinToInterrupt (pin), ISR, mode );
  • pin –> pin donde recibimos el evento ( pin 2 o 3 para arduino nano)
  • ISR –> Nombre de la ISR donde se tratará la interrupción
  • mode –> FALLING, RISING, CHANGE, LOW o HIGH

Ejemplo de manejo de una Interrupción por Hardware

En un Arduino nano, conectaremos la salida de algún sensor al pin D2 de arduino, debemos conocer qué tipo de salida nos ofrece el sensor que conectamos, para este ejemplo imaginamos que el sensor nos da cero mientras está detectando y conectamos un led al Arduino en el pin D10. El circuito básico es el siguiente:

Esquematico Arduino interrupciones

Cada vez que el sensor detecte, activaremos el led y cuando no detecte, lo apagaremos.

int ledPin = 10;
int intSensorPin = 2;
volatile bool sensorStatus = false;

void setup()
{
  pinMode (ledPin, OUTPUT);
  pinMode(intSensorPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(intSensorPin), ISR_SENSOR, CHANGE);
}

void loop()
{
 if (sensorStatus){
  digitalWrite(ledPin, LOW);
 }else{
  digitalWrite(ledPin, HIGH);
 } 
}

void ISR_SENSOR (){
  if (digitalRead(2) == LOW)
  {
    sensorStatus = true;
  } else {
    sensorStatus = false;
  }
}

Tienes el software disponible aquí.

Interrupción por software Timer1

En el Tutorial para generar señales PWM con Arduino, vimos que los timers tienen varias funcionalidades, pueden actuar como temporizadores, contadores o generadores de señales PWM, en este apartado vermos una libreria muy simple para configurar nuestro TimerOne de Arduino y lincar la interrrupcion a su ISR correspondiente

Para este ejemplo vamos a conservar el mismo montaje y vamos a variar un poco el código, de manera que tendremos la interrupción por Hardware que activará el led y añadiremos una interrupción del Timer1 para que nos genere una interrupción cada 500ms ya haga parpadear el led cuando esté activado. Recordar que este Timer se utiliza para controlar servos, por lo que si programamos alguna interrupción de timer1, no será posible utilizar servos.

Para aprender a programar interrupciones de los 1 y 2 mira esta entrada donde te explico cómo hacerlo modificando los timers registros del Arduino.

  • Primero, debemos descargar e incluir la librería TimerOne.h
  • Segundo, cargamos el timer1 con el valor de los 500ms
  • Tercero asignamos el nombre de la ISR para esta interrupción
#include <TimerOne.h>
int ledPin = 10;
int intSensorPin = 2;
volatile bool sensorStatus = false;
volatile bool ledStatus = false;

void setup()
{
  pinMode (ledPin, OUTPUT);
  pinMode(intSensorPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(intSensorPin), ISR_SENSOR, CHANGE);

  Timer1.initialize (500000);
  Timer1.attachInterrupt (ISR_BlinkLed);
}

void loop()
{
 if (sensorStatus && !ledStatus){
  digitalWrite(ledPin, LOW);
 }else{
  digitalWrite(ledPin, HIGH);
 } 
}

void ISR_BlinkLed (){
   if (sensorStatus){
    if (ledStatus){
      ledStatus = false;
    } else {
      ledStatus = true;
    }
   }
 }

void ISR_SENSOR (){
  if (digitalRead(2) == LOW)
  {
    sensorStatus = true;
  } else {
    sensorStatus = false;
  }
}

Tienes disponible el codigo en mi repositorio