AdSense

Montag, 17. Februar 2014

Ein kostenloses Programm um Schaltkreise zu zeichnen

(English version) An dieser Stelle will ich auf ein nützliches Programm hinweisen:
TinyCAD
Mit diesem Programm kann man auf extrem einfache Weise Schaltkreise zeichnen und als Bild exportieren, kein Account erstellen oder ähnliches ist nötig. Einarbeitungszeit benötigt es auch keine, alles funktioniert intuitiv.

LED-Band mit ATmega / Arduino ansteuern

(English version) In letzter Zeit erfreuen sich LED-Streifen erhöhter Beliebtheit. Inzwischen gibt es sogar schon für Preise unter 20 Euro LED-Streifen aus China bei Ebay. Normalerweise hat ein LED-Streifen ein Steuergerät, ein Netzteil und eine Fernbedienung. Für die meisten Menschen mag das reichen, wer aber mehr will (z.B. gezielt Sequenzen durchfahren) der muss ein (ganz kleines) bisschen Arbeit hineinstecken.

Zuerst zum Aufbau des LED-Streifens: Es gibt 4 Anschlüsse, einer für + 12 V und dann noch einen je Farbe, also rot, grün und blau. Der Streifen funktioniert nun so: Schließt man + 12 V an und legt dann an einen Farb-Kanal Masse, so leuchtet diese Farbe. Die Helligkeit pro Farbe wird normalerweise per PWM eingestellt. Um den Streifen komplett selber anzusteuern braucht man jetzt:
  • Einen Microcontroller (ATmega / Arduino).
  • 3 bipolare Transistoren (NPN), diese sollten einen ausreichend hohen Strom vertragen!
Die Schaltung sieht nun folgendermaßen aus: Vom Microcontroller aus werden 3 PWM-Signale auf die Basis der Transistoren gegeben (ein kleiner Vorwiderstand ist notwendig, ich benutze 470 Ohm). Der Emitter der Transistoren liegt auf Masse (gemeinsame Masse von 12 V Stromversorgung und Microcontroller), der Kollektor wird dem entsprechenden Farb-Kanal verbunden.


Vom Microcontroller wird der entsprechende Kanal folgendermaßen geschaltet:


analogWrite(8, 127);

Dieser Befehl würde nun den Transistor, welcher an Pin 8 angeschlossen ist auf 50% setzen (255 ist Maximum), sodass die daran angeschlossene Farbe mit 50% der Helligkeit leuchtet. Zu beachten ist, dass man natürlich nur PWM-Kanäle benutzen kann (Im Datenblatt sind PWM-Kanäle mit OCR gekennzeichnet).

Um nun beliebige Farben zu mischen geht man folgendermaßen vor:
Man sucht sich eine Farbe im RGB-Raum aus, z.B. orange: diese ist R: 255, G: 255, B:0. Genau das lässt man nun den Microcontroller machen:


analogWrite(RED_PIN, 255);
analogWrite(GREEN_PIN, 255);
analogWrite(BLUE_PIN, 0);  

Es kann vorkommen dass verschiedene Farben unterschiedlich hell sind, das müsste man ausprobieren und dann z.B. für grün 127 als obere Grenze festlegen (grün wird vom Auge sehr stark wahrgenommen, daher wird es vermutlich zu hell erscheinen).

Sonntag, 16. Februar 2014

"Home Automation" mit dem Arduino und 433 MHz - Die komplette Fernsteuerung

(English version) Seit meinem letzten Beitrag zu diesem Thema sind ja nun einige Monate vergangen. Aber nun habe ich es endlich mal geschafft, die Steuerung für die Steckdose und den Rolladen in ein Programm zu bringen und vorallem das ganze vom Steckbrett auf eine Platine zu übertragen.

Hardware

Die Hardware ist recht unspektakulär:

Im Prinzip besteht die Fernbedinung nur aus einem Attiny44A, einem Pullup-Widerstand für den Reset-Eingang, drei Knöpfen (hoch, runter, stopp), einem Halter für eine CR3032-Knopfzelle und natürlich dem 433MHz-Sender. Die drei Knöpfe sind jeweils mit einem Eingang des Attiny verbunden und ziehen den Eingang bei Betätigung auf Ground

Software

Die einzelnen Funktionen der Software wurden bereits in den vorhergehenden Posts zum Thema erläutert. Außerdem ist der Code (für meine Verhältnisse) gut kommentiert. Ich werde daher nicht auf den kompletten Code eingehen.

#include <RCSwitch.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

RCSwitch mySwitch = RCSwitch();
unsigned char buttonDown = 10;
unsigned char buttonStopp = 9;
unsigned char buttonUp = 7;
unsigned char buttonPressed = 0;

char stopRequest = 0;

void setup() {
  //Interrupts global deaktivieren
  cli();

  //Pins initialisieren
  pinMode(buttonDown, INPUT_PULLUP);
  pinMode(buttonStopp, INPUT_PULLUP);
  pinMode(buttonUp, INPUT_PULLUP);

  //Funkmodul intialisieren und Steckdose ausschalten
  mySwitch.enableTransmit(0);  //Sender hängt an Pin 0
  mySwitch.setProtocol(1);
  mySwitch.switchOff("11011", "10000");

  //Energie sparen
  ADCSRA &= ~(1<<ADEN); //Deaktiviere ADC
  ACSR = (1<<ACD); //Deaktiviere Analog Comparator

  //Pin-Change-Interrupt intialisieren
  PCMSK1 |= (1<<PCINT8); //Pin-Change-Interrupt an Pin 2 (Arduino Pin  10)
  PCMSK1 |= (1<<PCINT9); //Pin-Change-Interrupt an Pin 3 (Arduino Pin 9)
  PCMSK0 |= (1<<PCINT7); //Pin-Change-Interrupt an Pin 6 (Arduino Pin 7)
 
  //Power-Down-Modus vorbereiten
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  //Interrupts global aktivieren
  sei();
}
void loop() {
  sendCommand();
  powerDown();
} 

void sendCommand() {
  if (buttonPressed == buttonDown) {
    mySwitch.switchOn("11011", "10000");
    delay(750);
    sendCommandDown();
    powerDown(25);
    mySwitch.switchOff("11011", "10000");
    buttonPressed = 0;
  }

  else if (buttonPressed == buttonUp) {
    mySwitch.switchOn("11011", "10000");
    delay(750);
    sendCommandUp();
    powerDown(25);
    mySwitch.switchOff("11011", "10000");
    buttonPressed = 0;
  }
}

//Befehl Rolladen rauf
void sendCommandUp() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100F0F0F");
  mySwitch.sendQuadState("0F0F0100QQ0F100F0F1Q");
  mySwitch.setProtocol(1);
}

//Befehl Rolladen stopp
void sendCommandStopp() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100FFFFF");
  mySwitch.setProtocol(1);
}

//Befehl Rolladen runter
void sendCommandDown() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100F0101");
  mySwitch.sendQuadState("0F0F0100QQ0F100F0110");
  mySwitch.setProtocol(1);
}

//lässt Attiny für time Sekunden warten
void powerDown(char time) {
  GIMSK |= (1<<PCIE1); //Pin-Change-Interrupt aktivieren
  GIMSK |= (1<<PCIE0);
  
  stopRequest = 0;

  for (char i = 1; i<= time*1000; i++) {
    if (stopRequest == 0) {
      delay(1);
    }
  }

  GIMSK &= ~(1<<PCIE1); //Pin-Change-Interrupt deaktivieren
  GIMSK &= ~(1<<PCIE0);
}

//setzt Attiny solange in Powerdown-Modus, bis Pin-Change-Interrupt ausgelöst wurde
void powerDown() {
  GIMSK |= (1<<PCIE1); //Pin-Change-Interrupt aktivieren
  GIMSK |= (1<<PCIE0);
  sleep_mode();  //Schlafen gehen
  //hier gehts weiter nach aufwachen
  GIMSK &= ~(1<<PCIE1); //Pin-Change-Interrupt deaktivieren
  GIMSK &= ~(1<<PCIE0);
}

void checkButton() {
  if (digitalRead(buttonDown) == LOW) {
    buttonPressed = buttonDown;
  }

  else if (digitalRead(buttonStopp) == LOW) {
    stopRequest = 1;
    mySwitch.switchOff("11011", "10000");
  }

  else if (digitalRead(buttonUp) == LOW) {
    buttonPressed = buttonUp;
  }
}

//ISR für PCINT1 und PCINT0 (Pin-Change-Interrupts)
ISR(PCINT1_vect)
{
  checkButton();
} 
ISR(PCINT0_vect)
{
  checkButton();
} 

Einige Details der Software möchte ich dennoch erläutern. Die Spannungsversorgung der Fernbedienung erfolgt über eine CR2032-Knopfzelle. Da diese so lange wie möglich halten soll und die Fernbedienung 99,999% der Zeit sowieso nur rum liegt und nichts tut, geht der Attiny bei Inaktivität mit der Funktion powerdown() in den Schlaf-Modus. Er schläft so lange, bis er durch einen Tastendruck (Pin Change Interrupt) wieder geweckt wird. Um im Schlaf-Modus so wenig Energie wie möglich zu verbrauchen, wird zu Beginn zusätzlich der AD-Wandler sowie der Analog Comparator abgeschaltet. Dadurch sinkt der Ruhestrom auf wenige µA.