- Offizieller Beitrag
Ziel des Projekts:
Kabellose Überwachung von Fenstern und Türen
Nach jeder Statusänderung (geöffnet o. geschlossen) soll der Raspberry Pi ein Funk Signal erhalten welches weiter verarbeitet wird. Verwendungszweck könnte sein: Tür-/Fenster Überwachung, Alarmanlage usw...
Achtung:
Vorwort
Durch das Projekt "Temperatur Funk Sensor" von [user]meigrafd[/user] bin ich auf die Idee gekommen einen kabellosen Tür-/Fenstersensor zu basteln. Noch einmal ein Großes Dankeschön an [user]meigrafd[/user] für seine Arbeit. Es lohnt sich wirklich sein Thema (vor allem der erste Beitrag) zu lesen.
Grundgerüst ist dabei das Projekt "TinyTX Wireless Sensor". Darauf baut dieses Projekt eigentlich zum größten Teil auf.
Was wird benötigt:
Empfänger:
- 1x Raspberry Pi mit SD Karte + Raspbian
- 1x Transreciever Modul - RFM12Pi V2
Sender:
- 1x TinyTx3 PCB (10 Stück in China (iteadstudio.com) fertigen lassen [SHOP] Beschreibung Bestellvorgang im Spoiler)
- 1x RFM12B Modul 433MHz EBAY oder POLLIN
- 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 [Anzeige]
- 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 [Anzeige]
- 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.
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.
Empfänger
Der Empfänger ist ein fertiges Modul für den Raspberry Pi. Es ist das RFM12Pi V2. 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:
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
#!/usr/bin/python
import 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)
Alles anzeigen
Die Ausgabe sieht wie folgt aus:
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
Alles anzeigen
Wenn eure Batterien allerdings mehr als 4,5 Volt liefern müsst ihr das Script hier anpassen:
Zitat
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:
//----------------------------------------------------------------------------------------------------------------------
// 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 <JeeLib.h> // https://github.com/jcw/jeelib
#include <PinChangeInterrupt.h> // http://code.google.com/p/arduino-tiny/downloads/list
#include <avr/sleep.h>
ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving
#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;
}
Alles anzeigen
Die Sender ID legt ihr hier fest:
#define myNodeID 1
Sketch auf Sender(ATtiny) hochladen:
Arduino und ATiny verkabeln:
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:\Sketches\hardware".
Als nächstes geht ihr in den Ordner "C:\Sketches\hardware\tiny" 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:\Sketches\libraries" 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!
Ich werde dieses Projekt weiter pfelgen und neue Erkentnisse oder Veränderungen einpflegen.
DHT Compile Error Fix
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.
Hier die beiden neuen Sketche:
Türkontakte:
//----------------------------------------------------------------------------------------------------------------------
// 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 <JeeLib.h> // https://github.com/jcw/jeelib
#include <PinChangeInterrupt.h> // http://code.google.com/p/arduino-tiny/downloads/list
#include <avr/sleep.h>
ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving
#define myNodeID 6 // 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
#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;
}
Alles anzeigen
Magnetkontakte bitte wie folgt anschließen:
Pin 10 und GND
Pin 9 und GND
Pin 8 und GND
Auf dem TinyTX sind nur 2 GNDs vorhanden. Der dritte Pin unter den GND Pins ist mit nichts verbunden. Ich habe diesen einfach über eine Lötzinnbrücke verbunden.
In folgendem Muster werden die Werte übertragen:
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
//----------------------------------------------------------------------------------------------------------------------
// 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 <JeeLib.h> // https://github.com/jcw/jeelib
#include <avr/sleep.h>
#if defined(__AVR_ATtiny84__) // If we are running on a TinyTX
#include <PinChangeInterrupt.h> // http://code.google.com/p/arduino-tiny/downloads/list
#endif
ISR(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 7
static 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;
}
Alles anzeigen
HC-SR501 bitte wie folgt anschließen:
HC-SR501 Pins an TinyTx
VCC -> VCC
OUT -> Pin 3
GND -> GND
Zusätzlich kann an noch eine LED angeschlossen werden.
Pin 7 und GND
To-Do Liste
-
Passendes Gehäuse findenerledigt -
Mehrer Sensoren an einem Sensor (Sketch ändern)erledigt - Sketch: Spannung als Zeichen übertragen sodass nicht umgerechnet werden muss
-
Raspberry Pi: Graphische Auswertung mit Webanwendungerledigt - Raspberry Pi: Warnung wenn Spannung eines Sensors zu gering ist!
-
Infrarot Bewegungssensor HC-SR501 anschließenerledigt