Raspberry Pi Remote Switch

Wer kennt es nicht, man sitzt auf dem Sofa und will einen Film schauen…RaspiRemoteSwitch_Steckplatine
Aber nein der Raspberry Pi ist noch aus…
Also wieder aufstehen und den Netzstecker ziehen 🙁

Da ich mich und die Micro USB Buchse schonen wollte
habe ich nun ein kleines Gadget gebastelt.

Teile Liste:

 

Das folgende Script muss auf den Raspberry Pi erstellt werden.
(nicht vergessen: sudo chmod 755 /home/pi/RaspiRemoteHelper.sh)

#!/bin/bash
############################################################
## Raspberry PI Remote Switch Helper Script v0.1	  ##
##							  ##
## Shojo 30/12/2014					  ##
##							  ##
## Kontakt: 						  ##
## https://www.bastelbunker.de/raspberry-pi-remote-switch/ ##
############################################################

echo "22" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio22/direction
echo "1" > /sys/class/gpio/gpio22/value

echo "23" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio23/direction

while true
do
    ButtonState=$(cat /sys/class/gpio/gpio23/value)
    if [ $ButtonState -eq "1" ]; then
      poweroff &
      exit 0
    else
      sleep 2
    fi
done

Nun wird der Script in der rc.local eingetragen (Der Autostart!)
(sudo nano /etc/rc.local)

rc.local

 

 

 

 

 

 

 

 

 

 

 

Nach einen Neustart läuft das Script nun.

Jetzt noch der Arduino Code:

Die Abhängigkeiten:

 

#include <Arduino.h>
#include <IRremote.h>
#include <EEPROM.h>
#include "EEPROMAnything.h"

// IR
#define RECV_PIN 11
// RPI-PIN's
#define WAKE_UP_PIN 8
#define GO_SLEEP_PIN 7
#define RPI_ONLINE_PIN 9
// Button
#define ON_OFF_BUTTON 4
// LED's
#define STATE_LED_ONLINE 6
#define STATE_LED_OFFLINE 10

IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long StartPressButtonTimer = 0;
boolean ShortPressButton = false;


struct config_t
{
	long WakeUPKey;
	long GoSleep;
} Data;

void setup()
{
	pinMode(WAKE_UP_PIN, OUTPUT);
	pinMode(GO_SLEEP_PIN, OUTPUT);
	pinMode(RPI_ONLINE_PIN, INPUT);
	pinMode(STATE_LED_ONLINE, OUTPUT);
	pinMode(STATE_LED_OFFLINE, OUTPUT);
	pinMode(ON_OFF_BUTTON, INPUT_PULLUP);
	// Der Raspberry Pi wird über GND resettet!
	digitalWrite(WAKE_UP_PIN, true);

	Serial.begin(115200);
	irrecv.enableIRIn();
	EEPROM_readAnything(0, Data);
}

void loop()
{

	if (!digitalRead(ON_OFF_BUTTON))
	{
		// 5 Sek. drücken um im Aufnahme Modus zu kommen.
		if (millis() - StartPressButtonTimer > 4999)
		{
			Serial.println(F("Go in rec mode."));
			RecSignal();
			StartPressButtonTimer = millis();
		}
		return;
	}
	// Unter 5 Sek. drücken um ein oder aus zuschalten.
	else if (millis() - StartPressButtonTimer > 250)
	{
		ShortPressButton = true;
		StartPressButtonTimer = millis();
	}
	else
	{
		StartPressButtonTimer = millis();
	}

	if (irrecv.decode(&results))
	{
		if ((Data.WakeUPKey == results.value) && !digitalRead(RPI_ONLINE_PIN))
		{
			Serial.println(F("IR event"));
			WakeUp();
			StartPressButtonTimer = millis();
		}
		else if ((Data.GoSleep == results.value) && digitalRead(RPI_ONLINE_PIN))
		{
			Serial.println(F("IR event"));
			GoSleep();
			StartPressButtonTimer = millis();
		}
		irrecv.resume();
	}

	if (ShortPressButton && !digitalRead(RPI_ONLINE_PIN))
	{
		Serial.println(F("Button event"));
		WakeUp();
		ShortPressButton = false;
		StartPressButtonTimer = millis();
	}
	else if (ShortPressButton && digitalRead(RPI_ONLINE_PIN))
	{
		Serial.println(F("Button event"));
		GoSleep();
		digitalWrite(GO_SLEEP_PIN, false);
		ShortPressButton = false;
		StartPressButtonTimer = millis();
	}
}

void Blinking(int LED)
{
	int counter = 0;
	while (counter <= 5)
	{
		digitalWrite(LED, true);
		delay(100);
		digitalWrite(LED, false);
		delay(100);
		counter++;
	}
}

void TwoBlinking(int LED1, int LED2)
{
	int counter = 0;
	while (counter <= 5)
	{
		digitalWrite(LED1, true);
		digitalWrite(LED2, true);
		delay(100);
		digitalWrite(LED1, false);
		digitalWrite(LED2, false);
		delay(100);
		counter++;
	}

}

void Fading(bool isBooting)
{
	int STATE_LED = 0;
	// Welche LED ?
	if (isBooting)
	{
		STATE_LED = STATE_LED_ONLINE;
	}
	else
	{
		STATE_LED = STATE_LED_OFFLINE;
	}
	// Fade in
	for (int fadeValue = 0; fadeValue <= 20; fadeValue += 5)
	{
		analogWrite(STATE_LED, fadeValue);
		delay(30);
	}
	// In der FadingSchleife verweilen bis hoch oder runter gefahren wurde.
	while (GetSystemStateForWhile(isBooting))
	{
		for (int fadeValue = 20; fadeValue <= 255; fadeValue += 5)
		{
			analogWrite(STATE_LED, fadeValue);
			delay(30);
		}

		for (int fadeValue = 255; fadeValue >= 20; fadeValue -= 5)
		{
			analogWrite(STATE_LED, fadeValue);
			delay(30);
		}
	}
	// Fade out
	for (int fadeValue = 20; fadeValue >= 0; fadeValue -= 5)
	{
		analogWrite(STATE_LED, fadeValue);
		delay(30);
	}
}

// State für Boot oder Shutdown ermitteln
boolean GetSystemStateForWhile(bool isBooting)
{
	bool result;
	if (isBooting)
	{
		result = !digitalRead(RPI_ONLINE_PIN);
	}
	else
	{
		result = digitalRead(RPI_ONLINE_PIN);
	}
	return result;
}

void WakeUp()
{
	Serial.println(F("Wake UP!"));
	digitalWrite(WAKE_UP_PIN, false);
	delay(500);
	digitalWrite(WAKE_UP_PIN, true);
	Fading(true);
}

void GoSleep()
{
	Serial.println(F("Go sleep..."));
	digitalWrite(GO_SLEEP_PIN, true);
	Fading(false);
}

// Startet im Einschlatsignal aufnahme Modus.
void RecSignal()
{
	bool WakeUpSignal = true;
	int LED = 0;
	StartPressButtonTimer = millis();
	while (true)
	{
		if (!digitalRead(ON_OFF_BUTTON))
		{
			// 2 Sek. drücken um das Ausschlatsignal zu speichern.
			if (millis() - StartPressButtonTimer > 1999)
			{
				WakeUpSignal = false;
			}
			// 5 Sek. drücken um alle Einstellungen zu löschen!
			if (millis() - StartPressButtonTimer > 3999)
			{
				LED = 0;
				Serial.println(F("Delete all signals!"));
				TwoBlinking(STATE_LED_OFFLINE, STATE_LED_ONLINE);
				Data.WakeUPKey = 0;
				Data.GoSleep = 0;
				EEPROM_writeAnything(0, Data);
				break;
			}
		}
		else
		{
			StartPressButtonTimer = millis();
		}

		if (WakeUpSignal)
		{
			LED = STATE_LED_ONLINE;
			digitalWrite(STATE_LED_ONLINE, true);
			digitalWrite(STATE_LED_OFFLINE, false);
		}
		else
		{
			LED = STATE_LED_OFFLINE;
			digitalWrite(STATE_LED_OFFLINE, true);
			digitalWrite(STATE_LED_ONLINE, false);
		}

		if (irrecv.decode(&results))
		{
			if (WakeUpSignal)
			{
				Data.WakeUPKey = results.value;
			}
			else
			{
				Data.GoSleep = results.value;
			}
			EEPROM_writeAnything(0, Data);
			irrecv.resume();
			break;
		}
	}

	if (LED != 0)
	{
		Blinking(LED);
	}
}

Update 18.01.2015:

So ich habe jetzt mal die ersten Platinen hergestellt…
Hier das Ergebnis:

 

3 thoughts on “Raspberry Pi Remote Switch

  1. Hallo Shojo,

    ich muss mich als erstes als Elektronik-Neuling outen, der zwar löten und Nachbauen kann, aber das war es auch schon. Dennoch versuche ich immer die Sachen verstehen zu wollen.
    Deine Raspi-Projekte sind Klasse.

    Ich habe Deine einfache Schaltung bzgl. Raspi mittels Fernbedienung bedienen gelesen und nachgebaut und war auf der Suche, wie ich damit auch die kleine Kiste an- und ausschalten kann und stellte fest, dass Du auch eine Lösung dafür hast.

    Dennoch verstehe ich eines nicht.. Warum ein Arduino Uno? Wenn ich jetzt diese Schaltung bauen würde müsste ja der Arduino sämtliche FB-Befehle an den Raspi weiterleiten, da ich ja sonst zwei IR-Empfänger am Raspi habe.
    Macht sie das?

    Was meinst Du mit “Arduino (oder was vergleichbares)”? Einen Arduino Uno habe ich nicht und bei dem Preis für das Ding bekomme ich für die Hälfte eine fertige Lösung zum aufstecken mit AN-Aus-Schalter und IR.
    Was könnte ich denn als Alternative verwenden? Denke, ein Arduino wäre jetzt etwas oversized, wenn man noch keinen hat. Geht das nicht einfacher, eventuell mit einem Mikrocontroller, drei Widerständen und Lötzinn? 🙂

    1. Hi Ronin,

      nein der Arduino schleift nichts zum Pi durch (Da ich die Steuerung über IR nicht mehr nutze) .
      Was man aber bestimmt bewerkstelligen könnte 🙂

      Den Arduino Uno (oder vergleichbares) benutze ich nur aus Bequemlichkeit, da alles fertig ist und für den Preis kann man es auch nicht selber machen!
      (http://goo.gl/rUSz8L 4,48€ aus DE oder http://goo.gl/ZQ9ofR 1,80€ aus China)
      Für die meine Platinen nutze ich eigentlich fast immer den Pro Mini.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.