Alexa-fähiger USB-Stromschalter – Smarte Steuerung für USB-Geräte
Komponenten und Zubehör
| Komponente | Menge | Hinweis |
|---|---|---|
| Arduino MKR1000 | 1 | Hauptcontroller mit WLAN |
| 0,1 µF 0805 Kondensator | 8 | Entkopplung |
| LED (generisch) | 4 | Statusanzeige pro Port |
| Taster (lang) | 4 | Lokaler Ein/Aus-Schalter |
| INA219 (SOIC-8) | 1 | Strom-/Spannungsmessung |
| LM3526M | 2 | High-Side-Schalter mit Fehlererkennung |
| USB-Buchse (vertikal) | 4 | Ausgänge für USB-Geräte |
| 1 kΩ 0805 Widerstand | 4 | LED-Strombegrenzung |
| 0,1 Ω Strommesswiderstand | 1 | Für INA219 |
| 1 µF 0805 Kondensator | 1 | Zusätzliche Entkopplung |
Benötigte Werkzeuge und Maschinen
- 3D-Drucker (für das Gehäuse)
- Lötkolben
Apps und Online-Dienste
- Amazon Alexa Skills Kit
- Tinamous (IoT-Plattform)
- Amazon Web Services AWS Lambda
Projektbeschreibung
Hintergrund
Immer mehr Geräte werden über USB mit Strom versorgt – viele davon sind jedoch „dumme“ Geräte ohne Internetanbindung oder Smart-Home-Integration (z. B. LED-Leuchten). Wie lassen sie sich dennoch fernsteuern oder automatisieren? Eine an einer schaltbaren Steckdose angeschlossene USB-Stromversorgung wäre möglich, aber überdimensioniert, wenn man vier Geräte einzeln steuern möchte.
Dieses Projekt ermöglicht die Steuerung der Stromversorgung für USB-Geräte über das Internet. Durch den Tinamous SmartHome Skill für Alexa wird zusätzlich Sprachsteuerung für bisher „dumme“ USB-Geräte realisiert.
Zum Projektstart gab es kaum fertige Lösungen für die ferngesteuerte USB-Stromschaltung (in UK). Mittlerweile sind einige Mehrfachsteckdosen mit USB-Ports von No-Name-Herstellern (z. B. ZLD-34UK) aufgetaucht. Diese werfen jedoch Fragen auf: Welche Cloud wird genutzt? Wandern Daten nach China? Was passiert, wenn der Hersteller verschwindet? Wie sicher und nutzbar ist die Software? Ein offener, Arduino-basierter Ansatz bietet hier mehr Transparenz, Sicherheit und Hackbarkeit.
Anwendungsfälle
Beispiele für USB-Geräte, die man steuern möchte:
- USB-betriebene Lampen
- Fire TV Stick / Chromecast (z. B. in Kinderzimmern zur Begrenzung der Nutzungszeit)
- USB-Luftbefeuchter
- Echo Dot (z. B. nächtliches Herunterfahren oder Neustart)
- Entwicklungsboards (Remote-Reboot bei Endlosschleifen)
- Schwer zugängliche Geräte, die gelegentlich neu gestartet werden müssen (z. B. Sensoren auf dem Dachboden)
- Geräte bei Kunden vor Ort – Überwachung der Stromversorgung durch Strom- und Spannungsmessung
Einfache Stromsteuerung
Internetbasiertes Ein- und Ausschalten per Alexa-Sprachbefehl oder über Tinamous.
Intelligente Stromsteuerung
Viele USB-Lampen haben Touch-Bedienung – sie lassen sich per Stromtrennung ausschalten, aber nicht wieder einschalten. Oft reicht das Ausschalten (z. B. „Alle Lichter aus“). Mit dem „Smart Power“-Modus schaltet der Port kurz aus und wieder ein: Die Lampe geht aus, lässt sich danach aber wieder normal per Touch bedienen.
Timer-Automation
Automatisches Abschalten zu festen Zeiten – z. B. Fire-Stick um 20 Uhr ausschalten.
Leistungsüberwachung
Der onboard INA219 misst Strom und Spannung (bis ca. 1 kHz Abtastrate). So lässt sich der Einschaltstrom analysieren, das Laden von Powerbanks protokollieren oder Spannungsabfälle an langen USB-Kabeln erkennen. Ein Klemmenblock erlaubt höhere Ströme und dickere Kabel.
Stromausfall-Erkennung
Mit der Batterie-Option des MKR1000 kann die Eingangsspannung überwacht und bei Ausfall eine Benachrichtigung gesendet werden – nützlich für Remote-Installationen oder als einfacher Netzausfall-Melder für zu Hause.
Hardware
Das Herzstück ist ein Arduino MKR1000. Zwei LM3526M übernehmen High-Side-Schaltung und Fehlererkennung (Unterspannung, Überstrom). Ein INA219 misst Spannung und Strom. LEDs und Taster ermöglichen lokale Bedienung.
Die Platine wurde bei DirtyPCBs.com gefertigt (alternativ OSHPark.com). Die Arduino-Buchse hat Pads neben jedem Pin für Erweiterungen (Sensoren, OLED-Display).
Im GitHub-Repository gibt es eine 2-Port- und eine 4-Port-Version. Wichtig: Beim 2-Port-Layout sind die USB-Buchsen verpolt (falsche Polarität!). Die Lösung: USB-Buchsen auf der Rückseite bestücken – die Pinbelegung stimmt dann, nur der Seidendruck ist auf der falschen Seite. Daraus entstand die verbesserte 4-Port-Version mit Bauteilen auf der Rückseite und korrigierter LED-Ausrichtung.
Eine Erweiterung auf 6 oder 8 Ports ist machbar, evtl. ohne LEDs/Taster oder mit optimierter Anordnung.
Viele Widerstände sind optional (Pull-ups für Taster, USB-Control, Fehlererkennung). Diese können per INPUT_PULLUP im Arduino realisiert werden. Für Low-Power-Sleep mit Interrupt-Weckung sollten sie jedoch bestückt werden, um Flattern zu vermeiden.
LEDs und Taster sind komplett optional – für eine reine Remote-Box können sie weggelassen werden.
Stromversorgung
Drei Optionen (per Jumper JP6 wählbar):
- Intern: JP6 Pin 1-2 gebrückt – Strom vom Arduino 5V-Pin (nur für geringe Lasten).
- Extern per USB-Micro: JP6 Pin 2-3 gebrückt, 5V an J2 (onboard USB-Micro).
- Extern per Klemmblock: JP6 Pin 2-3 gebrückt, 5V an JP8 (Klemmblock).
Externe Versorgung speist auch den Arduino VIn-Pin – dieser braucht dann keine eigene Versorgung. Optional: 0R-Widerstände an R10, R11 und J2 für USB-Passthrough (z. B. Reboot eines an PC angeschlossenen Geräts ohne Steckverschleiß).
Gehäuse
Ein 3D-druckbares Gehäuse ist enthalten. M3-Gewindeeinsätze für PCB und Deckel, Reibschluss beim Deckel ebenfalls möglich.
Deckel-Optionen: mit/ohne Batteriefach, mit/ohne Befestigungslöcher (Füße). Der Basis-Körper lässt sich per OpenSCAD für die drei Stromversorgungsvarianten konfigurieren.
Verbindung mit Tinamous
Der MKR1000 stellt die WLAN-Verbindung her. Für Tinamous wird der MQTT-Server (Port 8883, SSL) genutzt. Das Gerät abonniert das Topic Status.To, um Befehle (z. B. von Alexa) zu empfangen.
Schritt 1: Firmware aktualisieren
In der Arduino IDE: Datei → Beispiele → WiFi101 → FirmwareUpdater aufspielen.
Schritt 2: Firmware-Updater öffnen
Werkzeuge → WiFi101 Firmware Updater
Schritt 3: Zertifikate installieren
Verbindung testen, Update Firmware. Dann Add domain → tinamous.com eingeben und Upload Certificates to WiFi module drücken.
Schritt 4: Eigene Firmware schreiben
Code liegt dem Projekt bei (auch auf GitHub, dort aktuellste Version). Benötigte Libraries: WiFi101, MQTT Client (von Joel Gaehwiler).
Datei secrets.h mit eigenen WLAN- und Tinamous-Daten befüllen:
#define SECRET_SSID "Deine SSID"
#define SECRET_PASS "Dein WLAN-Passwort"
/************************* Tinamous MQTT Setup *********************************/
#define MQTT_SERVER "deinaccount.tinamous.com"
#define MQTT_SERVERPORT 8883
#define MQTT_USERNAME "UsbSwitch.deinaccount"
#define MQTT_PASSWORD "Dein sicheres Passwort"
#define MQTT_CLIENT_ID "UsbSwitch"
#define DEVICE_USERNAME "UsbSwitch"
Noch kein Tinamous-Account? Kostenlos registrieren unter tinamous.com. Der Account-Name wird Teil der MQTT-URL (z. B. AlexaExample.tinamous.com).
Schritt 5: Gerät in Tinamous anlegen
Auf der Geräte-Seite Add klicken. Die MQTT-Einstellungen für das Beispiel-Account AlexaExample:
/************************* Tinamous MQTT Setup *********************************/
#define MQTT_SERVER "AlexaExample.tinamous.com"
#define MQTT_SERVERPORT 8883
#define MQTT_USERNAME "UsbSwitch.AlexaExample"
#define MQTT_PASSWORD "Mein super geheimes Passwort"
#define MQTT_CLIENT_ID "UsbSwitch"
#define DEVICE_USERNAME "UsbSwitch"
Mehrere Geräte möglich – einfach DEVICE_USERNAME und MQTT_USERNAME anpassen.
Schritt 6: Code hochladen und testen
Code mit angepasster secrets.h hochladen. Datei TinamousMQTTClient.ino prüfen – sie verarbeitet MQTT-Nachrichten (auch Alexa-Befehle).
SSL-Verbindung ist Pflicht für Internet-Einsatz:
WiFiSSLClient networkClient;
MQTTClient mqttClient(4096); // 4096 Bytes Puffer
Verbindung und Subscription:
mqttClient.begin(MQTT_SERVER, MQTT_SERVERPORT, networkClient);
mqttClient.onMessage(messageReceived);
if (!mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) {
// Fehlerbehandlung: LWMQTT_CONNECTION_DENIED = falsche Credentials
// Error -6 = fehlendes SSL-Zertifikat
delay(10000);
return false;
}
mqttClient.subscribe("/Tinamous/V1/Status.To/" DEVICE_USERNAME);
Die Tinamous-Timeline funktioniert wie ein privates Twitter für Geräte – sie posten Status und empfangen Befehle per MQTT oder REST-API. Für den Tinamous SmartHome Skill ist keine weitere Programmierung nötig.
Der Tinamous SmartHome Skill für Alexa
Der Skill war zum Zeitpunkt der Erstellung in der Zertifizierung (mittlerweile vermutlich im Store). Er ist generisch: Er kennt keine Geräte-Details, sondern liest Tags in Tinamous aus und erstellt passende Alexa-Geräte. So lässt sich jedes eigene Projekt mit wenigen Code-Zeilen per Sprache steuern.
Entwickelt in C# (.NET Core 2.0), ursprünglich für das BOFF Smart Fan Projekt, hier erweitert für Multi-Port-Geräte. Code inkl. Tests im Tinamous SmartHome Repository. Deployment via Visual Studio 2017 + AWS Tools nach Lambda.
Wichtige Alexa-Direktiven:
- Account Linking
- Discovery
- State Report
- Power Control
Account Linking
Wird von Alexa gehandhabt. Nach Skill-Aktivierung Weiterleitung zur Tinamous-Autorisierungsseite: Account-Name, Benutzername, Passwort eingeben.
Discovery
Nach Verknüpfung fordert Alexa Discovery an. Der Skill sucht in Tinamous nach Geräten mit Tag Alexa.SmartDevice. Ohne Tag = ignoriert.
Tags werden auf der Geräte-Bearbeitungsseite in Tinamous gesetzt. Zusatz-Tags:
MultiPort→ jeder Port wird als eigenes Alexa-Gerät angelegtAlexa.PowerController→ unterstützt Ein/AusSmartPlug→ Kategorie in Alexa-App
Für Multi-Port-Geräte müssen State Variables definiert werden (Geräte-Bearbeitung → Advanced):
PortCount= Anzahl PortsPort-1...Port-n= Namen für Alexa (unbenannte Ports werden ignoriert)
Der Skill sucht Felder mit Namen/Tag powerState oder powerState-port-n für Status-Rückmeldung.
State Report
Während Discovery meldet der Skill, dass States abfragbar sind. Alexa sendet StateReport-Anfragen. Dafür müssen die Geräte-Felder in Tinamous getaggt werden (Advanced → Edit Field → Tags). Das senml-Format im Arduino-Code pusht die Daten per MQTT.
Fehlen portspezifische Felder, fällt Alexa auf das generische powerState zurück.
Power Control
Alexa sendet TurnOn / TurnOff. Der Skill veröffentlicht eine Status-Nachricht auf der Tinamous-Timeline:
@UsbSwitch Turn On
@UsbSwitch Turn On port-1
Das Gerät empfängt die Nachricht per MQTT und schaltet. Alexa liest den Status per StateReport zurück.
AWS Lambda Funktion erstellen
- Lambda in passender Region anlegen (UK →
eu-west-1Irland). - Neue Funktion from scratch (Blueprints veraltet, nur V2 – wir nutzen V3).
- Rolle erstellen (z. B. Simple Microservices). Falls CloudWatch-Logs fehlen: IAM-Berechtigung hinzufügen.
- In Visual Studio: Rechtsklick Projekt → Publish to AWS Lambda...
- Details ausfüllen, hochladen.
- Testen, dann Actions → Publish new version.
- Trigger Alexa Smart Home hinzufügen, Skill-ID eintragen (noch nicht bekannt – siehe nächster Schritt).
Skill in der Alexa Developer Console anlegen
- developer.amazon.com → Alexa Skills Kit → Add a New Skill.
- Smart Home Skill API, Sprache (z. B. English UK), Payload Version V3.
- Konfiguration: Lambda ARN der versionierten Funktion eintragen (endet mit
:1,:2...). - In Lambda: Skill ID (Application ID) als Trigger eintragen und speichern.
- Account Linking: OAuth-App in Tinamous über Alexa Bot erstellen (Bots-Seite → Add Alexa Bot). Die Dialogbox liefert alle nötigen Daten.
- Test-Seite: Show this skill in the Alexa App = Yes.
- In Alexa App (alexa.amazon.de): Skills → Your Skills → DEV SKILLS → Skill aktivieren.
- Veröffentlichungsinfos (Beispielsprüche, Icons) auf Publishing Information Seite pflegen.
- Code-Update: Neue Lambda-Version veröffentlichen, Trigger + Skill-ID neu setzen, versionierten ARN in Skill-Konsole eintragen.
Hinweis: Beim veröffentlichten Tinamous SmartHome Skill entfällt der eigene Alexa Bot.
Erfolg!
Skill läuft in Lambda, in Alexa installiert → „Alexa, discover smart home devices“ → Geräte steuern. Logs in CloudWatch einsehen.
Skill Debugging & Tipps
- Endpoint-IDs: Nur alphanumerisch (kein
*,#geht). - Alles loggen. Kein Log → Auth-Problem oder Lambda nicht autorisiert.
- Gleiche E-Mail für AWS und Alexa nutzen.
- Lambda in derselben Region wie Skill (UK → Irland).
- Skill wird aufgerufen, aber Alexa reagiert nicht → Antwortformat fehlerhaft.
- Zweites Alexa-Konto via Amazon Household (max. 2 Erwachsene, Wechsel verzögert).
- „Alexa, switch profiles“ zum Wechsel zwischen Dev- und Normal-Profil.
- Neue Alexa Console: Bessere Validierung, aber Logs nur Success-Metriken, 36h Verzögerung – für Debugging unbrauchbar.
Ein Skill für jedes IoT-Ding!
Mit dem Tinamous SmartHome Skill: Solange dein Gerät per MQTT mit Tinamous spricht (oder per Bot angebunden ist), reicht ein paar Zeilen Code für Turn On, Turn Off, Set brightness 20. Tags in Tinamous setzen → „Alexa, discover smart home devices“ – fertig.
Code
AlexaUsbSwitcher.ino(Hauptprogramm)TinamousMQTTClient.ino(MQTT/Alexa-Handling)UsbControl.ino(USB-Schaltung)WiFiClient.ino(WLAN-Verbindung)Secrets.h(Zugangsdaten – anpassen!)
AlexaUsbSwitcher.ino
#include <MQTTClient.h>
#include <system.h>
#include <WiFi101.h>
#include <Adafruit_INA219.h>
#include "Secrets.h"
// 4-Port Board Konfiguration
#define MAX_USB_PORTS 4
int led_pin[MAX_USB_PORTS][2] = {{14,14},{13,13},{7,7},{6,6}};
int switch_pin[] = {A0, A1, A2, A3};
int usb_enable_pin[] = {5, 4, 1, 3};
int usb_fault_pin[] = {2, 2, 2, 2};
bool usb_port_state[] = {false, false, false, false};
int usb_power_mode[] = {1, 0, 0, 0}; // 0=Aus, 1=Kurz aus dann an (Smart Power)
unsigned long usb_power_switch_on_at[] = {0,0,0,0};
unsigned long usb_power_switch_off_at[] = {1,1,1,1};
Adafruit_INA219 ina219;
bool has_usb_fault = false;
float shunt_voltage, bus_voltage, current_mA, load_voltage, power_mW;
float max_current_mA=0, max_busvoltage=0, min_busvoltage=20;
unsigned long last_measurement_time = 0;
bool power_failed = false, over_current = false;
int update_interval_seconds = 20;
unsigned long next_message_send_at = 0;
void setup() {
pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH);
for(int i=0;i<MAX_USB_PORTS;i++) setupChannel(i);
delay(2000); showSetupStageCompleted(1);
Serial.begin(115200); delay(3000); showSetupStageCompleted(2);
ina219.begin(); setupWiFi(); showSetupStageCompleted(3);
setupMqtt(); showSetupStageCompleted(4);
sentNextPublishAt(5);
Serial.println("Alexa USB Power Switch v0.4 Ready");
}
void setupChannel(int ch) {
pinMode(led_pin[ch][0], OUTPUT); digitalWrite(led_pin[ch][0], LOW);
if(led_pin[ch][0]!=led_pin[ch][1]) { pinMode(led_pin[ch][1], OUTPUT); digitalWrite(led_pin[ch][1], LOW); }
pinMode(switch_pin[ch], INPUT_PULLUP);
pinMode(usb_enable_pin[ch], OUTPUT); digitalWrite(usb_enable_pin[ch], HIGH);
pinMode(usb_fault_pin[ch], INPUT_PULLUP);
}
void showSetupStageCompleted(int stage) {
if(stage>MAX_USB_PORTS) return;
SetLeds(stage-1, true, true);
}
void loop() {
if(!hasPoweredPorts()) digitalWrite(LED_BUILTIN, LOW);
bool faulted=false;
for(int ch=0;ch<MAX_USB_PORTS;ch++) {
if(checkFault(ch)) faulted=true;
has_usb_fault=faulted;
checkSwitchPressed(ch);
}
runAutomation(); readCurrent(); checkPowerSupply(); doDelay(); mqttLoop(); sendStatus();
}
void doDelay() {
if(hasPoweredPorts()) { delay(100); return; }
delay(100); digitalWrite(LED_BUILTIN, HIGH); delay(100);
}
bool isSwitchPressed(int ch) {
if(digitalRead(switch_pin[ch])) return false;
delay(50);
if(!digitalRead(switch_pin[ch])) { delay(100); return true; }
return false;
}
void checkSwitchPressed(int ch) {
if(isSwitchPressed(ch)) setUsb(ch, !usb_port_state[ch]);
}
void readCurrent() {
shunt_voltage = ina219.getShuntVoltage_mV();
bus_voltage = ina219.getBusVoltage_V();
current_mA = ina219.getCurrent_mA();
load_voltage = bus_voltage + (shunt_voltage/1000);
last_measurement_time = millis();
if(current_mA>max_current_mA) max_current_mA=current_mA;
if(bus_voltage>max_busvoltage) max_busvoltage=bus_voltage;
if(bus_voltage<min_busvoltage) min_busvoltage=bus_voltage;
printPowerSkinny();
}
void checkPowerSupply() {
if(power_failed && bus_voltage>4.5) {
Serial.print("Power restored: "); Serial.print(bus_voltage); Serial.println("V");
publishTinamousStatus("External power restored."); power_failed=false;
}
if(bus_voltage<4.2 && !power_failed) {
Serial.print("Power FAILED: "); Serial.print(bus_voltage); Serial.println("V");
publishTinamousStatus("External power lost!"); power_failed=true;
}
if(over_current && current_mA<1500) { publishTinamousStatus("Current fault cleared!"); over_current=false; }
if(current_mA>2000 && !over_current) { publishTinamousStatus("Over Current!"); over_current=true; }
}
void sendStatus() {
if(millis()>next_message_send_at) {
if(power_failed) sentNextPublishAt(update_interval_seconds*10);
else sentNextPublishAt(update_interval_seconds);
// SenML JSON erstellen und senden...
publishTinamousSenMLMeasurements(senml);
}
}
void runAutomation() {
for(int ch=0;ch<MAX_USB_PORTS;ch++) {
if(usb_power_switch_on_at[ch]>0 && usb_power_switch_on_at[ch]<millis()) {
setUsb(ch,true); usb_power_switch_on_at[ch]=0;
}
if(usb_power_switch_off_at[ch]>0 && usb_power_switch_off_at[ch]<millis()) {
setUsb(ch,false); usb_power_switch_off_at[ch]=0;
}
}
}
// ... weitere Hilfsfunktionen (SetLeds, setUsb, allOn, allOff, printPower...)
TinamousMQTTClient.ino
#include <MQTTClient.h> #include <system.h> #include "secrets.h"
WiFiSSLClient networkClient; MQTTClient mqttClient(4096);
bool was_connected=false; String senml=""; unsigned long nextSendMeasurementsAt=0;
bool setupMqtt() {
senml.reserve(4096);
mqttClient.begin(MQTT_SERVER, MQTT_SERVERPORT, networkClient);
mqttClient.onMessage(messageReceived);
return connectToMqttServer();
}
bool connectToMqttServer() {
if(mqttClient.connected()) return true;
if(WiFi.status()!=WL_CONNECTED) { delay(10000); return false; }
if(!mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) {
// Fehlerbehandlung...
delay(10000); return false;
}
mqttClient.subscribe("/Tinamous/V1/Status.To/" DEVICE_USERNAME);
publishTinamousStatus("Hello! Usb switch connected. @ me with help.");
was_connected=true; return true;
}
void mqttLoop() { connectToMqttServer(); mqttClient.loop(); }
void publishTinamousStatus(String msg) { mqttClient.publish("/Tinamous/V1/Status", msg); }
void publishTinamousSenMLMeasurements(String s) { mqttClient.publish("/Tinamous/V1/Measurements/SenML", s); }
void messageReceived(String &topic, String &payload) {
payload.toLowerCase();
if(payload.startsWith("@")) { if(handleStatusMessage(payload)) return; }
publishTinamousStatus("Hello! Didn't understand. @ me with help.");
}
bool handleStatusMessage(String p) {
char buf[25];
for(int port=0;port<MAX_USB_PORTS;port++) {
sprintf(buf,"turn on port-%d",port+1);
if(p.indexOf(buf)>0) { setUsb(port,true); return true; }
sprintf(buf,"turn off port-%d",port+1);
if(p.indexOf(buf)>0) { setUsb(port,false); return true; }
}
if(p.indexOf("turn on")>0) { allOn(); return true; }
if(p.indexOf("turn off")>0) { allOff(); return true; }
if(p.indexOf("help")>0) { /* Hilfe senden */ return true; }
return false;
}
UsbControl.ino
bool hasPoweredPorts() { for(int i=0;i<MAX_USB_PORTS;i++) if(usb_port_state[i]) return true; return false; }
bool checkFault(int ch) {
if(!digitalRead(usb_fault_pin[ch])) {
if(has_usb_fault) return true;
setUsb(ch,false); SetLeds(ch,true,false);
if(!has_usb_fault) { has_usb_fault=true; /* Meldung */ }
return true;
}
return false;
}
void allOn() { for(int i=0;i<MAX_USB_PORTS;i++) setUsb(i,true); }
void allOff() { for(int i=0;i<MAX_USB_PORTS;i++) setUsb(i,false); }
void setUsb(int ch, bool on) {
digitalWrite(usb_enable_pin[ch], on?LOW:HIGH);
SetLeds(ch,on,true); usb_port_state[ch]=on;
publishTinamousStatus("USB Port "+String(ch+1)+" "+(on?"enabled":"disabled"));
sentNextPublishAt(1);
if(!on && usb_power_mode[ch]==1) usb_power_switch_on_at[ch]=millis()+5000;
}
void SetLeds(int ch, bool on, bool green) {
if(!on) { digitalWrite(led_pin[ch][0],LOW); digitalWrite(led_pin[ch][1],LOW); return; }
if(led_pin[ch][0]==led_pin[ch][1]) digitalWrite(led_pin[ch][0],HIGH); // 4-Port: Einfarbig
else { digitalWrite(led_pin[ch][0],green?HIGH:LOW); digitalWrite(led_pin[ch][1],green?LOW:HIGH); } // 2-Port: Bi-Color
}
WiFiClient.ino
#include "Secrets.h"
char ssid[]=SECRET_SSID; char pass[]=SECRET_PASS; int status=WL_IDLE_STATUS;
void setupWiFi() {
while(status!=WL_CONNECTED) {
status=WiFi.begin(ssid,pass); delay(10000);
}
printWiFiData(); printCurrentNet();
}
void printWiFiData() {
IPAddress ip=WiFi.localIP(); Serial.print("IP: "); Serial.println(ip);
byte mac[6]; WiFi.macAddress(mac);
Serial.print("MAC: "); for(int i=5;i>=0;i--) { if(i<5) Serial.print(":"); Serial.print(mac[i],HEX); } Serial.println();
}
void printCurrentNet() {
Serial.print("SSID: "); Serial.println(WiFi.SSID());
byte bssid[6]; WiFi.BSSID(bssid);
Serial.print("BSSID: "); for(int i=5;i>=0;i--) { if(i<5) Serial.print(":"); Serial.print(bssid[i],HEX); } Serial.println();
Serial.print("RSSI: "); Serial.println(WiFi.RSSI());
}
Secrets.h (anpassen!)
#define SECRET_SSID "<WLAN-SSID>"
#define SECRET_PASS "<WLAN-Passwort>"
#define MQTT_SERVER "<DeinAccount>.tinamous.com"
#define MQTT_SERVERPORT 8883
#define MQTT_USERNAME "<GeräteName>.<DeinAccount>"
#define MQTT_PASSWORD "<Geräte-Passwort>"
#define MQTT_CLIENT_ID "UsbSwitch"
#define DEVICE_USERNAME "<GeräteName>"
Individuelle Teile & Gehäuse
Verschiedene Gehäusevarianten (alle Anschlüsse, nur nötige Öffnungen, schnellste Druckversion) als OpenSCAD-Dateien im Repository.
Schaltpläne & PCB
BRD- und SCH-Dateien für OSHPark / DirtyPCBs im Repository.
GitHub Repository
Ordner Arduino/StandAlone/, 4-Port-Version: github.com/ThingySticks/USBPowerSwitcher
Herstellungsprozess
- C# Switch Statement meistern: Syntax, Beispiele & Best Practices
- TI stellt ultra-kompakte, hocheffiziente BQ25790/BQ25792 Buck-Boost Batterielader vor
- Effizienter 230-VAC Stromausfall-Sensor für Raspberry Pi – Kostengünstig, Kompakt & Sicher
- SMS-gesteuerter Smart AC Power Switch mit Raspberry Pi & Hologram
- Windkraft: Umwandlung von Luftbewegung in sauberen Strom
- Schlaghämmer meistern: Umfassender Leitfaden für modernes Schmieden
- Automatische Exzenterpressen: Eigenschaften, Vorteile und Anwendungen
- Kraftspannfutter (Power Chucks): Definition, Einsatz, Vorteile
- Kraftspannfutter: Umfassender Leitfaden für Präzisionsbearbeitung
- Wasserkraft nutzen: Umfassender Leitfaden zur Hydroelektrizität