efinf:blc2016:bu1:projekt4:projekt

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
efinf:blc2016:bu1:projekt4:projekt [2017/03/16 14:34] – [Code] noel_ottigerefinf:blc2016:bu1:projekt4:projekt [2017/03/17 08:01] (current) – [Arduino Code] noel_ottiger
Line 1: Line 1:
 +{{backlinks>.}}
 +====== 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 ====
 +  * Solid State Relay (z.B. [[https://goo.gl/aN8PzP]])
 +  * Arduino Uno
 +  * 3 LEDs zum Debuggen
 +  * 3 220Ω Widerstände für LEDS
 +  * Div. Kabel
 +==== Aufbau ====
 +Schema mit Relay (gestrichelte Linien sind Netzspannung [230V])
 +
 +{{ :efinf:blc2016:bu1:projekt4:drawing.svg |}}
 +==== Arduino Code ====
 +{{ :efinf:blc2016:bu1:projekt4:code.txt |}}
 +
 +<hidden Code>
 +<code c++>
 +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
 +</code>
 +</hidden>
 +
 +==== Python Code (Server-Side) ====
 +
 +Verwendete Libraries
 +  * Pyudev - Serien Schnittstellenüberwachung (erkennt, wenn Festplatte hochgefahren ist und per USB "anklopft" [[https://pyudev.readthedocs.io/en/latest/]]
 +  * Python Serial - Kommunikation mit Arduino (Standart Library)
 +  * Python Glib - Laufzeit Library für Loops (Standart Library)
 +
 +
 +{{ :efinf:blc2016:bu1:projekt4:code_py.txt |}}
 +
 +<hidden Code>
 +<code python>
 +# 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()
 +</code>
 +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.
 +</hidden>
 +==== Fazit ====
 +  * Vieles über die Verwendungszwecke von Arduinos gelernt 
 +  * Grundlagen von Elektronik mit Relays
 +  * Bei Problemen Austausch mit Mitschülern
 +==== Fotos und Film ====
 +[[https://dev.noelottiger.com/files/fginfo_printer_video.mp4|Video 3D Druck]]
 +
 +Modell in Fusion 360
 +
 +{{:efinf:blc2016:bu1:projekt4:img_fusion.jpg?400|}}
 +
 +Modell des Gehäuses in Cura (3D Slicer)
 +
 +{{:efinf:blc2016:bu1:projekt4:img_cura.jpg?400|}}
 +
 +Drucker bei der Arbeit
 +
 +{{:efinf:blc2016:bu1:projekt4:img_print.jpg?400|}}
 +