Table of Contents

Stromsteuerung mit Arduino und Relay

Idee und Fernziel

Bis anhin waren die externen (Backup-)Festplatten 24h pro Tag an den Server angebunden obwohl sie nur wenige Minuten pro Tag genutzt wurden. Durch automatisches ein- und ausschalten sollte der Stromverbrauch verringert werden.

Die Stromversorgung wird von einer Arduino/Relay-Kombination übernommen, die Einbindung (mount/unmount) durch ein Python Script auf dem Server selbst.

Aktueller Stand

Nach Ende der Woche was der Prototyp mehr oder weniger Funktionsfähig. Die Stromsteuerung und Kommunikation zwischen Server und Arduino bzw. Relay funktioniert einigermassen Zuverlässig, wenn auch mit einigen Sekunden Verzögerung. Die Einbindung der eingeschalteten Festplatten lässt noch zu wünschen übrig, da eine wiederholte Einbindung ohne Neustart des Servers an den temporären Ordnern der Laufwerke scheitert.

Da das Relay Netzspannung regelt wurde es in ein 3D gedrucktes Gehäuse verpackt, um Kontakt zu vermeiden.

Bericht

Material

Aufbau

Schema mit Relay (gestrichelte Linien sind Netzspannung [230V])

Arduino Code

code.txt

Code

Code

void setup() {
  // Serial dialect
  Serial.begin(115200);
 
  // Status LEDs
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(10, OUTPUT);
}
 
void loop() {
  // Check for input
  check_input();
}
 
void check_input() {
  if (Serial.available() > 0) {
    if (Serial.read() == '0') {
      // Device unmounted
      // Cut power
      if (cut_power() == 1) {
        // Successful
        light_pin(3);
        delay(1000);
        dark_pin(3);
      } else {
        error();
      }
    } else {
      // Wanting device
      // Give power
      if (give_power() == 1) {
        // Successful
        light_pin(6);
        delay(1000);
        dark_pin(6);
      } else {
        error();
      }      
    }
  }
  // Execution delay
  delay(100);
}
 
int cut_power() {
  // Deactivate Relay => 0V
  digitalWrite(10, LOW);
  return 1;
}
 
int give_power() {
  // Activate Relay => 5V
  digitalWrite(10, HIGH);
  return 1;
}
 
void light_pin(int pin) {
  // Turn pin on
  digitalWrite(pin, 100);
}
 
void dark_pin(int pin) {
  // Turn pin off
  digitalWrite(pin, 0);
}
 
void error() {
  // Unknown command received
  light_pin(5);
  delay(1000);
  dark_pin(5);
}
 
// 42

Python Code (Server-Side)

Verwendete Libraries

code_py.txt

Code

Code

# Imports
import serial, time, glib, os
from pyudev import Context, Monitor
from pyudev.glib import MonitorObserver
 
# Variables
dialect = 115200
timeout = 5
 
# Functions
def send_bit(bit):
	# Send bit to ardunio
	arduino = serial.Serial('/dev/ttyACM0', dialect)
	time.sleep(2)
	arduino.write(bit)
 
def mount(dev_id):
	os.system("bash mount.sh -d %s" % dev_id)
	return True
 
def unmount(dev_id):
	os.system("bash unmount.sh -d %s" % dev_id)
	return True
 
# Userinput
do = raw_input("Do you want to:\n\n(1) Power up the device\n(2) Power down the device\n\n>>> ")
 
if do == '1':
	send_bit('1')
	action = 'starting'
elif do == '2':
	send_bit('0')
	action = 'stopping'
 
print "\nCommand sent"
print "Waiting for response"
time.sleep(timeout)
 
def device_event(observer, device):
	if device.action == 'add' and action == 'starting':
		print "Device started successfully."
		print "Mounting device..."
		mount(device.get('DEVNAME'))
		exit()
	if device.action == 'remove' and action == 'stopping':
		unmount(device.get('DEVNAME'))
		print "Device shut down successfully."
		exit()
 
context = Context()
monitor = Monitor.from_netlink(context)
 
monitor.filter_by(subsystem='usb')
observer = MonitorObserver(monitor)
 
observer.connect('device-event', device_event)
monitor.start()
 
glib.MainLoop().run()

Da das Einbinden unter Windows und Linux unterschiedlich geregelt wird, wird die Einbindung in externen Scripten geregelt. Auf Linux mit mount.sh, unter Windows wäre das wohl ein Batch Script.

Fazit

Fotos und Film

Video 3D Druck

Modell in Fusion 360

Modell des Gehäuses in Cura (3D Slicer)

Drucker bei der Arbeit