Botón-Pulsador para la Raspberry Pi 3

Ultima revisión de esta página: 25-Julio-2016

Botón conectado mediante resistencia pull up utilizado para apagar la Raspberry Pi 3.

Diseño eléctrico basado en el artículo: http://iot-projects.com/index.php?id=raspberry-pi-shutdown-button

Pulsador para la Raspberry Pi 3

Los códigos o números de PIN indicados en el esquema corresponden al conector GPIO de las Raspberry Pi 3 modelo B y pueden ser distintos para otros modelos de Raspberry Pi.

El esquema publicado en esta página web podría contener errores que provoquen daños a la Raspberry Pi 3, cortocircuitos eléctricos, etc. Si alguien sigue este diseño deberá hacerlo bajo su propia responsabilidad.


Programa para REINICIAR o APAGAR la Raspberry Pi 3 con un botón pulsador

A continuación se muestra el código fuente en lenguaje C para Reiniciar o Apagar la Raspberry Pi 3 al pulsar el botón.

Si se hace una pulsación rápida del botón (menos de 1 segundo), el programa realizará un Reinicio ("sudo shutdown -r now") del Linux. Si el botón se pulsa durante más de 1 segundo, se Apagará la Raspberry Pi 3 ("sudo shutdown -h now").

Son necesarios permisos de administrador (sudo) para ejecutar el programa. Se puede añadir al "/etc/rc.local" para que se ejecute cada vez que se reinicie la Raspberry Pi 3.

El programa hace uso de Interrupciones del microprocesador con lo que prácticamente no consume CPU ni memoria RAM.

El programa "resetoff.c" ha sido realizado por JIDS (Ponferrada-España)

http://alinos.sytes.net

Versión 1.0 realizada el 27-Julio-2016

Este programa se ha realizado a partir del programa "isr4pi.c" de D. Thiebaut, encontrada en la web:

"http://cs.smith.edu/dftwiki/index.php/Tutorial:_Interrupt-Driven_Event-Counter_on_the_Raspberry_Pi"

A su vez el programa de D. Thiebaut se basaba en "isr.c" de la librería WiringPi de Gordon Henderson

"https://github.com/WiringPi/WiringPi/blob/master/examples/isr.c"

También se han utilizado algunas líneas e ideas del código fuente de Phil Lavin:

"https://github.com/phil-lavin/raspberry-pi-gpio-interrupt"



/*
Programa para REINICIAR o APAGAR la RASPBERRY PI 3 con un botón pulsador

Finalidad:  
     - Este programa configura el uso de un botón tipo pulsador
       conectado al interface GPIO 25 (PIN físico 22 ó PIN 6 de la
       librería WiringPi) de una Raspberry Pi 3 para realizar un
       "reset" o un "poweroff" del sistema operativo Linux.
            
Funcionamiento: 
     - Pulsando menos de 1 segundo el botón, se ejecuta un REINICIO 
       del sistema operativo ejecutando una orden "shutdown -h now".
     
     - Si se pulsa el botón durante más de 1 segundo, el sistema se
       APAGARA ejecutando un "shutdown -h now" 

Características:
     - Utiliza interrupciones del microprocesador para capturar la
       pulsación del botón utilizando una cantidad mínima de CPU y RAM.
       
       Una vez lanzada la función asociada a la interrupción, lo primero
       que hace esa función es consultar la Hora del sistema y luego 
       entra en un bucle que se seguirá ejecutándose hasta que se suelte
       el pulsador. 
       
       Cuando se ha liberado el pulsador, esta función vuelve a consultar 
       la Hora del sistema para saber el tiempo que ha durado la 
       pulsación del botón. Si ese tiempo es menor de un segundo, lanza 
       una instrucción para REINICIAR el sistema y si el tiempo en el que
       ha estado pulsado el botón es mayor de un segundo, lanza la orden 
       para APAGAR el sistema.
       
     - Este programa necesita permisos de administrador (sudo) para 
       ejecutarse.

Los números de PIN indicados corresponden a una Raspberry Pi 3 modelo B
y podrían no corresponder con otras versiones de las Raspberry Pi.

El programa "resetoff.c" ha sido realizado por JIDS (Ponferrada-España)
http://alinos.sytes.net
Versión 1.0 realizada el 27-Julio-2016

Este programa se ha realizado a partir del programa "isr4pi.c" de 
D. Thiebaut, encontrada en la web:
  http://cs.smith.edu/dftwiki/index.php/Tutorial:_Interrupt-Driven_Event-Counter_on_the_Raspberry_Pi 
A su vez el programa de D. Thiebaut se basaba en "isr.c" de la librería 
WiringPi de Gordon Henderson
  https://github.com/WiringPi/WiringPi/blob/master/examples/isr.c
También se han utilizado algunas líneas e ideas del código fuente de Phil Lavin: 
  https://github.com/phil-lavin/raspberry-pi-gpio-interrupt 
  
Para compilar este código se puede usar:

    gcc -o resetoff resetoff.c -lwiringPi

Y se puede ejecutar con la orden:

    sudo ./resetoff
    
También se puede añadir al final del fichero "/etc/rc.local" (antes de 
la última línea "exit 0") para que el programa se inicie automáticamente
cada vez que se arranque la Raspberry Pi 3.

*/

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <sys/time.h>

// El botón-pulsador está conectado al GPIO 25 que corresponde con el 
// PIN físico número 22 de la Raspberry Pi 3 y también con el PIN 6 de
// la librería wiringPi
#define BUTTON_PIN 6

// -------------------------------------------------------------------------
// Función a la que llama la interrupción de la CPU cuando se pulsa el botón
void myInterrupt(void) {
  struct timeval last_change; // Registra la Hora cuando se pulsa el botón
  struct timeval now;         // Registra la Hora cuando se libera el pulsador
  unsigned long diff;         // Utilizada para saber el tiempo transcurrido

  // Registra la hora al comenzar la pulsación del botón
  gettimeofday(&last_change, NULL);

  // Ahora se ejecuta un bucle que simplemente espera indefinidamente hasta
  // que se suelte el botón
  while ( digitalRead(BUTTON_PIN) == 0 ) {
    // printf( ".");
  }
   
  // Volvemos a consultar la Hora en la que se ha liberado el pulsador
  gettimeofday(&now, NULL);

  // Tiempo que dura la pulsación del botón (en microsegundos)
  diff = (now.tv_sec * 1000000 + now.tv_usec) - (last_change.tv_sec * 1000000 + last_change.tv_usec);
	
  // Si el tiempo durante el que se pulsó el botón ha sido mayor de 1 segundo, se ejecuta el apagado del sistema
  if (diff > 1000000) { 
	   printf("APAGANDO el sistema  Tiempo pulsación del botón=%d \n", diff); 
	   system("sudo shutdown -h now");
     }
  
  // Si el botón se pulsó menos de 1 segundo, se ejecuta un Reinicio
  if ((diff > 300) && (diff < 1000000)) { 
	   printf("REINICIANDO el sistema  Tiempo pulsación del botón=%d \n", diff); 
	   system("sudo shutdown -r now");
	 }
   
   diff = 0;
}

int main(void) {
  printf("*******************************************************************************\n");
  printf("Programa para REINICIAR y APAGAR la Raspberry Pi 3 utilizando un botón pulsador\n");
  printf("Vers. 1.0 - JIDS 27/07/2016\n");
  printf("*******************************************************************************\n");
  printf("Funcionamiento:\n");
  printf("  - Pulsación del botón inferior a 1 segundo = REINICIAR el sistema\n");	
  printf("  - Pulsación del botón superior a 1 segundo = APAGAR el sistema\n");	
  printf("\n");
  printf("El botón debería estar conectado en el GPIO25 (Pin 6 de WiringPi / Pin 22)\n");
  printf("\n");

  // Inicialización de la librería wiringPi
  if (wiringPiSetup () < 0) {
      fprintf (stderr, "Error: Imposible inicalizar la librería wiringPi: %s\n", strerror (errno));
      return 1;
  }

  // Configura el GPIO 25 (wiringPi 6 ó PIN físico 22) para generar una interrupción del microprocesador
  // cuando hay cambios de señal de Hight-a-Low y asocia la función myInterrupt() a dicha interrupción
  if ( wiringPiISR (BUTTON_PIN, INT_EDGE_FALLING, &myInterrupt) < 0 ) {
      fprintf (stderr, "Error: Imposible establecer la interrupción: %s\n", strerror (errno));
      return 1;
  }

  while ( 1 ) {
    delay( 1000 ); // Espera de 1 segundo. No incrementa el consumo de CPU o memoria RAM
  }

  return 0;
}


Descargar código fuente: "resetoff.c"


Consumo de CPU y RAM del programa resetoff.c

Consumo de CPU y RAM del programa resetoff.c