Kabellose Überwachung von Fenstern und Türen mit der Raspberry Pi
Inhaltsverzeichnis
Matriel & Hardware
Empfänger
- 1x Raspberry Pi mit SD Karte + Raspbian
- 1x Transreciever Modul – RFM12Pi V2 (Jetzt rfm69pi v3)
Sender
- 1x TinyTx3 PCB (10 Stück in China (iteadstudio.com) fertigen lassen [SHOP] )
- 1x RFM12B Modul 433MHz
- 2x Kerko 100nf Keramikkondensator oder REICHELT
- 1x Schaltdraht 0,80mm für die Antenne
- 1x ATTINY84A – PU
- 1x Sockel, IC Fassung 14-polig
- 1x Magnetkontakt/Reedkontakt
- 3x AAA 1,5V 1250mAh
- 1x Batterie Halter/Gehäuse 3xAAA mit Schalter
- 1x Printstecker, Einzelstecker, gewinkelt, 2-polig
- 2x Kupplungs-Leergehäuse, Crimptechnik, 2-polig
- 1 Satz PSK-KONTAKTE
Sonstiges
- 1x Arduino Uno Rev3 R3
- Stiftleisten
- diverses Werkzeug zum Löten und Abisolieren usw
Sender
Der Sender muss aus verschiedenen Bauteilen zusammen gelötet werden. Ich habe mir 10 PCBs des TinyTX3 von iteadstudio.com (Chinesiche Firma) fertigen lassen.
Auf dieser Platine habe ich ein Sendermodul (RFM12B) , zwei Kerkos (100nf) sowie einen 14 Pin IC Sockel verlötet. Durch den Sockel kann ich den ATTINY84 zum programmieren herunter nehmen und wieder drauf stecken. Man kann den ATtiny auch fest verlöten. Vorher sollte er aber programmiert werden.
Wenn man ihn danach wieder programmieren möchte muss man sich einen „IC Test Clip“ besorgen. Damit ist es möglich auf fest verlötet Microcontroller zu programmieren.
Auf dem ATtiny läuft ein Sketch welches ebenfalls von Nathan zur Verfügung gestellt wird.
Stromversorgung: Batterien
Ich habe mir einen Batteriehalter mit Schalter (An/Aus) besorgt in dem 3 AAA Batterien (jeweils 1,5V) Platz finden. Ich habe mir noch einen PSK Stecker an die Batterien gelötet, damit der Stecker auch immer korrekt angeschlossen wird.
Empfänger Magnetkontakt
Auf Ebay habe ich günstige Magnetschalter gefunden die wirklich klasse verarbeitet sind.
Diese Schalter lösen aus, sobald sich das Gegenstück zu weit von dem eigentlichen Magnetschalter entfernt. Der Magnet wird also an dem Türblatt befestigt und der Magnetkontakt (Schalter) wird an der Zarge bzw Verkleidung angebracht.
Der Empfänger ist ein fertiges Modul für den Raspberry Pi. Es ist das RFM12Pi V2 (Jetzt rfm69pi v3). Man kann sich natürlich auch den Empfänger selber zusammen löten, was durchaus günstiger ist. Mehr dazu findet ihr im Thread von meigrafd.
Antenne
Als Antenne habe ich einen 0,8mm Kupferdraht benutzt den ich auf 165mm abgelängt habe. Dieser wird ebenfalls auf das TinyTX3 Board gelötet. Es ist auch möglich einen „Spirale“ als Antenne zu benutzten, welche vielleicht sogar im Gehäuse Platz finden kann. Das habe ich aber noch nicht ausprobiert und kann auch zu der Reichweite noch nichts sagen.
Gehäuse
Ich habe zuerst ein kleineres Gehäuse gehabt und mit einem Dremel bearbeitet. Jetzt habe ich mich für folgendes Gehäuse entschieden:
Universal-Gehäuse ABS Licht-Grau (RAL 7035) 112 x 62 x 31 Hammond Electronics
Ich habe etwas Schaumstoff zurecht geschnitten und als unterste Lage verwendet. Darauf kommt dann das TinyTx Board samt Batteriehalter. Auf dem batteriehalter und dem TinyTx habe ich zusätzlich Schaumstoff platziert damit es durch den Druck vom gehäusedeckel nicht verrutschen kann. Und das tut es auch nicht.
Damit die Kabel nach außen geführt werden könne habe ich in Gehäuse und Gehäusedeckel eine kleine Öffnung gefräst.
Derzeit habe ich 4 Sender zusammen gelötet!
Software zum empfangen
Voraussetzen ist ein Raspberry Pi mit aktuellen Raspbian. Vorab bitte per „sudo raspi-config“ das Dateisystem vergrößern.
Das Empfängermodul wird einfach nur auf die GPIO Stiftleiste aufgesteckt und schickt alle empfangenen Daten per RS232 Schnittelle an den Raspberry Pi weiter. Es muss also kein Treiber oder sonst irgendwas installiert werden.
Ich habe ein Python Script geschrieben, mit dem ich die Werte der Sender abfange und in der Konsole ausgebe.
Geht wie folgt vor:
1 2 3 4 |
sudo apt-get update sudo apt-get install python-serial sudo wget https://raw.github.com/lurch/rpi-serial-console/master/rpi-serial-console -O /usr/bin/rpi-serial-console && sudo chmod +x /usr/bin/rpi-serial-console sudo rpi-serial-console disable |
Mit diesem Befehlen installiert ihr für Python die serielle Unterstützung und „deaktiviert“ (bzw befreit) die RS232 Schnittelle. Diese ist auf dem Raspberry Pi standardmäßig für die Konsoleneingabe konfiguriert.
Mit diesem einfachen Python Script könnt ihr nun die einzelnen Sender auslesen/empfangen:
tinyserial.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#!/usr/bin/pythonimport serial import time import string# Verbindung herstellen port = serial.Serial("/dev/ttyAMA0", baudrate=9600, timeout=0.1) print "Schnitstelle:" print "/dev/ttyAMA0" print "9600" print "Warten auf Daten...."while True: # Port lesen data_r = port.read(1000) # Daten ausgeben if data_r != "" : text = data_r.split(' ') node = text[1] status = text[2] voltage = text[4] supp = round(4.5/255 * float(voltage),2) output = "NID:%s Status:%s vcc:%sv" % (node, status, supp) # Ausgabe print "Daten empfangen: %s" % (output) # CPU schonen ;-) time.sleep(0.01) |
Die Ausgabe sieht wie folgt aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pi@raspberrypi ~ $ sudo python tinyserial.py Schnitstelle: /dev/ttyAMA0 9600 Warten auf Daten.... Daten empfangen: NID:1 Status:1 vcc:4.12v Daten empfangen: NID:1 Status:0 vcc:4.12v Daten empfangen: NID:1 Status:1 vcc:4.12v Daten empfangen: NID:1 Status:0 vcc:4.12v Daten empfangen: NID:2 Status:1 vcc:3.99v Daten empfangen: NID:2 Status:0 vcc:3.99v Daten empfangen: NID:2 Status:1 vcc:4.32v Daten empfangen: NID:2 Status:0 vcc:4.32v |
Wenn eure Batterien allerdings mehr als 4,5 Volt liefern müsst ihr das Script hier anpassen:
1 |
supp = round(4.5/255 * float(voltage),2) |
Sonst werden euch falsche Werte ausgegeben.
In Zukunft möchte ich die Berechnung allerdings nicht mehr auf der Seite des Empfängers machen sondern gleich die korrekten Werte vom Sender empfangen. Dazu muss ich allerdings noch die Sender umprogrammieren. Das steht noch auf meiner To-Do Liste.
Software für die Sender
Hier findest du den Sketch der auf den ATtiny programmiert werden muss.
Wie man das ganze auf den ATtiny bekommt werde ich zu einem späteren Zeitpunkt erklären.
Sketch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
//---------------------------------------------------------------------------------------------------------------------- // TinyTX - An ATtiny84 and RFM12B Wireless Sensor Node // By Nathan Chantrell. For hardware design see rell.net/tinytx // // Detect a normally closed reed switch opening and closing with pin change interrupt to wake from sleep. // // Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence: // http://creativecommons.org/licenses/by-sa/3.0/ // // Requires Arduino IDE with arduino-tiny core: http://code.google.com/p/arduino-tiny/ //---------------------------------------------------------------------------------------------------------------------- #include #include #include #define myNodeID 1 // RF12 node ID in the range 1-30 #define network 210 // RF12 Network group #define freq RF12_433MHZ // Frequency of RFM12B module #define USE_ACK // Enable ACKs, comment out to disable #define RETRY_PERIOD 5 // How soon to retry (in seconds) if ACK didn't come in #define RETRY_LIMIT 5 // Maximum number of times to retry #define ACK_TIME 10 // Number of milliseconds to wait for an ack #define SW_PIN 10 // Reed switch connected from ground to this pin (D10/ATtiny pin 13) //######################################################################################################################## //Data Structure to be sent //######################################################################################################################## typedef struct { int switchState; // Switch state int supplyV; // Supply voltage } Payload; Payload tinytx; //######################################################################################################################## void setup() { rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above rf12_sleep(0); // Put the RFM12 to sleep pinMode(SW_PIN, INPUT); //set the pin to input digitalWrite(SW_PIN, HIGH); //use the internal pullup resistor attachPcInterrupt(SW_PIN,wakeUp,FALLING); // attach a PinChange Interrupt on the falling edge PRR = bit(PRTIM1); // only keep timer 0 going ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode sleep_mode(); // Sleep now } void wakeUp(){} void loop() { int switchState = digitalRead(SW_PIN); // Read the state of the reed switch if (switchState == LOW) { // Door/window is open tinytx.switchState = 1; // 1 indicates open } else { // Door/window is closed tinytx.switchState = 0; // 0 indicates closed } tinytx.supplyV = readVcc(); // Get supply voltage rfwrite(); // Send data via RF set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode sleep_mode(); // Sleep now } //-------------------------------------------------------------------------------------------------- // Send payload data via RF //------------------------------------------------------------------------------------------------- static void rfwrite(){ #ifdef USE_ACK for (byte i = 0; i <= RETRY_LIMIT; ++i) { // tx and wait for ack up to RETRY_LIMIT times rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(RF12_HDR_ACK, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode byte acked = waitForAck(); // Wait for ACK rf12_sleep(0); // Put RF module to sleep if (acked) { return; } // Return if ACK received Sleepy::loseSomeTime(RETRY_PERIOD * 1000); // If no ack received wait and try again } #else rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(0, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode rf12_sleep(0); // Put RF module to sleep return; #endif } // Wait a few milliseconds for proper ACK #ifdef USE_ACK static byte waitForAck() { MilliTimer ackTimer; while (!ackTimer.poll(ACK_TIME)) { if (rf12_recvDone() && rf12_crc == 0 && rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID)) return 1; } return 0; } #endif //-------------------------------------------------------------------------------------------------- // Read current supply voltage //-------------------------------------------------------------------------------------------------- long readVcc() { bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC long result; // Read 1.1V reference against Vcc #if defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84 #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328 #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = 1126400L / result; // Back-calculate Vcc in mV ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power return result; } |
Die Sender ID legt ihr hier fest:
1 |
#define myNodeID 1 |
Sketch auf Sender(ATtiny) hochladen
Arduino und ATiny verkabeln:
1 2 3 4 5 6 7 |
Arduino ATtiny84 D13 Pin 9 D12 Pin 8 D11 Pin 7 D10 Pin 4 3.3V Pin 1 GND Pin 14 |
Ich habe mir mit einer Lochrasterplatine ein kleines Board zusammen gelötet welches ich direkt auf den Arduino Uno stecken kann.
Schritt 1: Arduino IDE, WinAVR sowie Treiber installieren
Ardunio Uno – Treiberinstallation Windows
Als nächstes installiert ihr: WinAVR
Schritt 2: ATtiny Core installieren
Als erstes ändert ihr euer Sketch Verzeichnis auf z.B „C:Sketches“
- Arduino IDE starten
- Datei -> Einstellungen
- Sketchbook Speicherort auf „C:Sketches“ ändern
- Ausfürliche Ausgabe anzeigen während: [X]Kompilierung und [X] Upload
Da die Arduino IDE standardmäßig keine ATtinys ansprechen kann, muss die ATtinyCore installiert werden.
Folgende Datei herunterladen:
Den Ordner „tiny“ kopiert ihr nun in folgendes Verzeichnis: „C:Sketcheshardware„.
Als nächstes geht ihr in den Ordner „C:Sketcheshardwaretiny“ und benennt folgende Datei um:
- Prospective Boards.txt zu boards.txt
Nun erscheinen unter Tools -> Board viele ATtinys!
Schritt 3: Den Arduino zum ISP machen
Wir benutzten den Arduino Uno nur dazu um die ATtinys zu programmieren.
Deswegen müssen wir erst einmal den Arduino zum ISP Programmierer machen.
Das geht wie folgt:
- Arduino Uno über USB Kabel mit PC verbinden
- Arduino IDE starten
- Unter Datei –> Beispiele -> ArduinoISP auswählen
- Unter Tools –> Board -> Arduino UNO auswählen
- Unter Programer -> AVR ISP auswählen
- anschließend Sketch hochladen
Schritt 4: Benötigte libraries einfügen
Nun ladet euch folgende libraries herunter:
Nun fügt ihr den Inhalt der Archive in „C:Sketcheslibraries“ ein.
Die Ordnerstruktur muss danach so aussehen:
- hardware
- tiny
- libraries
- JeeLib
- PinChangeInterrupt
- PinChangeInterruptSimple
- TinyTuner
Achtet auf die korrekten Ordnernamen. Im Archiv sind diese manchmal anders.
Schritt 5: ATtiny von 1MHZ auf 8MHZ umstellen.
Also nächstes müssen wird den ATtiny auf 8Mhz umstellen. Dazu müssen wir einen Bootloader installieren:
- Den ATtiny korrekt (richtig herum) in die Programmiereinheit stecken
- Tools -> Board -> ATtiny84 @8MHz (internal oscillator; BOD disabled) auswählen
- Tools -> Programmer -> Arduino as ISP auswählen
- Tools -> Bootloader installieren
Achtung: Bitte ändern/installiert immer erst den korrekten Bootloader. Ich habe bei einem ATtiny zuerst den Sketch hochgeladen und mich gewundert warum es nicht funktioniert hat. Als mir auffiel, dass der ATtiny noch mit 1MHz arbeitet wollte ich den Bootloader nachträglich ändern, was mit aber nicht gelang: „Fehler beim installieren des Bootloaders“
Also Erst Bootloader und dann den Sketch! ;-)
Schritt 6: Sketch hochladen
- Sketch bzw Code im großes Fenster der Arduino IDE einfügen
- Oben links auf den Haken (Überprpüfen) klicken.
- Wenn kein Fehler aufgetreten ist klickt ihr daneben auf den Pfeil der nach Rechts zeigt (Upload).
Danach sollte der Sketch kompiliert und hochgeladen sein. Ihr könnt den ATtiny nun aus der Programmiereinrichtung herausnehmen (vorher den Arduino Uno stromlos machen) und in den Sockel auf eurem TinyTX stecken (achtet darauf, dass er richtig herum eingesteckt wird). Nun könnt ihr die Stomversorgung herstellen und euer Sender sollte die ersten Daten senden! ;-)
http://forum.arduino.cc/index.php/topic,116674.0.html
Erweiterung
PIR Infrarotsensor sowie mehrere Magnetkontakte an einem Sender.
Ich habe nun nach einer kleinen Pause an dem Projekt weitergearbeitet und habe nun einen PIR Bewegungssensor (HC-SR501) angeschlossen.
Außerdem kann ich nun mehrere einzelne auswertbare Magnetkontakte an den TinyTX anschließen. Das Problem, dass die Spannung nicht korrekt übertragen wird habe ich leider noch nicht lösen können, bzw weiß nicht wo der Fehler ist.
Türkontakte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
//---------------------------------------------------------------------------------------------------------------------- // TinyTX - An ATtiny84 and RFM12B Wireless Sensor Node // By Nathan Chantrell. For hardware design see http://nathan.chantrell.net/tinytx // // Detect a normally closed reed switch opening and closing with pin change interrupt to wake from sleep. // // Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence: // http://creativecommons.org/licenses/by-sa/3.0/ // // Requires Arduino IDE with arduino-tiny core: http://code.google.com/p/arduino-tiny/ //----------------------------------------------------------------------------------------------------------------------#include #include #include #define network 210 // RF12 Network group #define freq RF12_433MHZ // Frequency of RFM12B module//#define USE_ACK // Enable ACKs, comment out to disable #define RETRY_PERIOD 5 // How soon to retry (in seconds) if ACK didn't come in #define RETRY_LIMIT 5 // Maximum number of times to retry #define ACK_TIME 10 // Number of milliseconds to wait for an ack#define SW_PIN 10 #define SW_PIN2 9 #define SW_PIN3 8//######################################################################################################################## //Data Structure to be sent //########################################################################################################################typedef struct { int switchState; // Switch state int supplyV; // Supply voltage } Payload; Payload tinytx; //######################################################################################################################## void setup() { rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above rf12_sleep(0); // Put the RFM12 to sleep pinMode(SW_PIN, INPUT); digitalWrite(SW_PIN, HIGH); attachPcInterrupt(SW_PIN,wakeUp,RISING); pinMode(SW_PIN2, INPUT); digitalWrite(SW_PIN2, HIGH); attachPcInterrupt(SW_PIN2,wakeUp,RISING); pinMode(SW_PIN3, INPUT); digitalWrite(SW_PIN3, HIGH); attachPcInterrupt(SW_PIN3,wakeUp,RISING); PRR = bit(PRTIM1); // only keep timer 0 going ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode sleep_mode(); // Sleep now } void wakeUp(){} void loop() { int switchState = digitalRead(SW_PIN); int switchState2 = digitalRead(SW_PIN2); int switchState3 = digitalRead(SW_PIN3); String s_1 = ""; String s_2 = ""; String s_3 = ""; if (switchState == HIGH) { s_1 = "1"; }else{ s_1 = "2"; } if (switchState2 == HIGH) { s_2 = "1"; }else{ s_2 = "2"; } if (switchState3 == HIGH) { s_3 = "1"; }else{ s_3 = "2"; } String e = s_1+s_2+s_3; tinytx.switchState = e.toInt(); tinytx.supplyV = readVcc(); // Get supply voltage rfwrite(); // Send data via RF set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode sleep_mode(); // Sleep now } //-------------------------------------------------------------------------------------------------- // Send payload data via RF //------------------------------------------------------------------------------------------------- static void rfwrite(){ #ifdef USE_ACK for (byte i = 0; i <= RETRY_LIMIT; ++i) { // tx and wait for ack up to RETRY_LIMIT times rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(RF12_HDR_ACK, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode byte acked = waitForAck(); // Wait for ACK rf12_sleep(0); // Put RF module to sleep if (acked) { return; } // Return if ACK received Sleepy::loseSomeTime(RETRY_PERIOD * 1000); // If no ack received wait and try again } #else rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(0, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode rf12_sleep(0); // Put RF module to sleep return; #endif } // Wait a few milliseconds for proper ACK #ifdef USE_ACK static byte waitForAck() { MilliTimer ackTimer; while (!ackTimer.poll(ACK_TIME)) { if (rf12_recvDone() && rf12_crc == 0 && rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID)) return 1; } return 0; } #endif //-------------------------------------------------------------------------------------------------- // Read current supply voltage //-------------------------------------------------------------------------------------------------- long readVcc() { bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC long result; // Read 1.1V reference against Vcc #if defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84 #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328 #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = 1126400L / result; // Back-calculate Vcc in mV ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power return result; } |
1 2 3 |
Pin 10 und GND Pin 9 und GND Pin 8 und GND |
In folgendem Muster werden die Werte übertragen:
1 2 3 4 5 6 7 8 9 |
1= geschlossen 2= geöffnet 111 -> alle Kontakte geschlossen 211 -> Kontakt 1:geöffnet - Kontakt 2:geschlossen - Kontakt 3:geschlossen 221 -> Kontakt 1:geöffnet - Kontakt 2:geöffnet - Kontakt 3:geschlossen 222 -> Kontakt 1:geöffnet - Kontakt 2:geöffnet - Kontakt 3:geöffnet 121 -> Kontakt 1:geschlossen - Kontakt 2:geöffnet - Kontakt 3:geschlossen usw... |
Pir Bewegungssensor: HC-SR501
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
//---------------------------------------------------------------------------------------------------------------------- // TinyTX or Tiny328 and RFM12B Wireless Module with PIR module // By Nathan Chantrell. For hardware design see http://nathan.chantrell.net/ // // Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence: // http://creativecommons.org/licenses/by-sa/3.0/ // // For TinyTX the arduino-tiny core is required: http://code.google.com/p/arduino-tiny/ //----------------------------------------------------------------------------------------------------------------------#include #include #include #endifISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving#define myNodeID 7 // RF12 node ID in the range 1-30 #define network 210 // RF12 Network group #define freq RF12_433MHZ // Frequency of RFM12B module//#define USE_ACK // Enable ACKs, comment out to disable #define RETRY_PERIOD 5 // How soon to retry (in seconds) if ACK didn't come in #define RETRY_LIMIT 5 // Maximum number of times to retry #define ACK_TIME 10 // Number of milliseconds to wait for an ack#define PIR_PIN 3 // PIR Output pin connected to Pin 3 #define PIR_IRQ 1 // PIR Output pin connected to INT1 (only used for Tiny328) #define LEDpin 7static void activityLed (byte state) { pinMode(LEDpin, OUTPUT); digitalWrite(LEDpin, state); } //######################################################################################################################## //Data Structure to be sent //######################################################################################################################## typedef struct { int pirState; // PIR state int supplyV; // Supply voltage } Payload; Payload tinytx; //######################################################################################################################## void setup() { rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above rf12_sleep(0); // Put the RFM12 to sleep pinMode(PIR_PIN, INPUT); //set the pin to input attachPcInterrupt(PIR_PIN,wakeUp,CHANGE); // attach a PinChange Interrupt for TinyTX boards PRR = bit(PRTIM1); // only keep timer 0 going ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode sleep_mode(); // Sleep now } void wakeUp(){} void loop() { activityLed(1); // LED on int pirState = digitalRead(PIR_PIN); // Read the state of the pin if (pirState == HIGH) { // Movement detected tinytx.pirState = 1; } else { // No movement tinytx.pirState = 0; } tinytx.supplyV = readVcc(); // Get supply voltage rfwrite(); // Send data via RF activityLed(0); // LED on set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode sleep_mode(); // Sleep now } //-------------------------------------------------------------------------------------------------- // Send payload data via RF //------------------------------------------------------------------------------------------------- static void rfwrite(){ #ifdef USE_ACK for (byte i = 0; i <= RETRY_LIMIT; ++i) { // tx and wait for ack up to RETRY_LIMIT times rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(RF12_HDR_ACK, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode byte acked = waitForAck(); // Wait for ACK rf12_sleep(0); // Put RF module to sleep if (acked) { return; } // Return if ACK received Sleepy::loseSomeTime(RETRY_PERIOD * 1000); // If no ack received wait and try again } #else rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(0, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode rf12_sleep(0); // Put RF module to sleep return; #endif } // Wait a few milliseconds for proper ACK #ifdef USE_ACK static byte waitForAck() { MilliTimer ackTimer; while (!ackTimer.poll(ACK_TIME)) { if (rf12_recvDone() && rf12_crc == 0 && rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID)) return 1; } return 0; } #endif //-------------------------------------------------------------------------------------------------- // Read current supply voltage //-------------------------------------------------------------------------------------------------- long readVcc() { bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC long result; // Read 1.1V reference against Vcc #if defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84 #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328 #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = 1126400L / result; // Back-calculate Vcc in mV ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power return result; } |
HC-SR501 bitte wie folgt anschließen:
1 2 3 4 |
HC-SR501 Pins an TinyTx VCC -> VCC OUT -> Pin 3 GND -> GND |
1 |
Pin 7 und GND |
Das Tutorial, Bilder und Informationen wurden freundlicherweise von www.forum-raspberrypi.de zur Verfügung gestellt. Vielen Dank hierfür.