Welche Revision / Version von den RFM12B hast du denn?
Entwicklung: Temperatur Funk Sensor
-
meigrafd -
23. August 2013 um 13:46 -
Erledigt
-
-
Entwicklung: Temperatur Funk Sensor? Schau mal ob du hier fündig wirst!
-
Kann es sein das ich den RFM12B mit 3x AAA Batterien mit gesamt 4,5 V geschrottet habe?
Laut Datenblatt sind ja maximal 3.8 V zulässig. Im Eingagsthread wird zwar beschrieben es nichts ausmacht dort mehr Volt draufzugeben, aber ich bin mir jetzt unsicher, da meine Funkübertragung nicht funktioniert.Such mal im Datenblatt nach 6V.
Das müsste die maximal Spannung sein. -
Ich hätte da mal eine Frage zwecks Stromverbrauch.
Leider hat mein Transceiver Sketch einen Stromverbrauch von 18,6 ma.
Wenn eine Batterie aber eine Kapazität von 1500 mah hat, müsste der Sender doch eigentlich zumindest 80 Stunden (1500/18,6) schaffen, oder?Durch drei Batterien in Reihe bleibt die Kapazität ja identisch und das ganze liefert 4,5 Volt. Wenn der Sender zusätzlich weniger Volt braucht müsste doch die Ausdauer der Batterien nochmals steigen, oder?
Vielen Dank für eine Aufklärung
Grüße
bigdane
-
Naja du kannst in den Sketch ja trotzdem noch ein bisschen Stromsparende Sachen einbauen, wie den ADC abzuschalten
"Transceiver"
C
Alles anzeigen// RFM12B Transceiver for RaspberryPI. // to Receiving Data from SenderNodes and Transmit something away // // Basiert zum Teil auf der Arbeit von Nathan Chantrell // // modified by meigrafd @ 06.02.2015 // modified by bigdane69 @ 27.01.2015 - for UART read and send 433mhz //------------------------------------------------------------------------------ #include <JeeLib.h> // https://github.com/jcw/jeelib #include <SoftwareSerial.h> ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving //------------------------------------------------------------------------------ // You will need to initialize the radio by telling it what ID it has and what network it's on // The NodeID takes values from 1-127, 0 is reserved for sending broadcast messages (send to all nodes) // The Network ID takes values from 0-255 // By default the SPI-SS line used is D10 on Atmega328. You can change it by calling .SetCS(pin) where pin can be {8,9,10} #define NODEID 22 //network ID used for this unit #define NETWORKID 210 //the network ID we are on #define requestACK true #define SERIAL_BAUD 9600 //------------------------------------------------------------------------------ // PIN-Konfiguration //------------------------------------------------------------------------------ // UART pins #define rxPin 7 // D7, PA3 #define txPin 3 // D3, PA7. pin der an RXD vom PI geht. // LED pin #define LEDpin 8 // D8, PA2 - set to 0 to disable LED /* +-\/-+ VCC 1| |14 GND (D0) PB0 2| |13 AREF (D10) (D1) PB1 3| |12 PA1 (D9) RESET 4| |11 PA2 (D8) INT0 PWM (D2) PB2 5| |10 PA3 (D7) PWM (D3) PA7 6| |9 PA4 (D6) PWM (D4) PA6 7| |8 PA5 (D5) PWM +----+ */ // Initialise UART SoftwareSerial mySerial(rxPin, txPin); // Store input String Message, inputString = ""; int SENDTO = 0; //############################################################################## static void activityLED (byte state, byte time = 0) { if (LEDpin) { pinMode(LEDpin, OUTPUT); if (time == 0) { digitalWrite(LEDpin, state); } else { digitalWrite(LEDpin, state); delay(time); digitalWrite(LEDpin, !state); } } } // init Setup void setup() { pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); mySerial.begin(SERIAL_BAUD); rf12_initialize(NODEID, RF12_433MHZ, NETWORKID); analogReference(INTERNAL); // Set the aref to the internal 1.1V reference ADCSRA &= ~ bit(ADEN); // disable the ADC bitSet(PRR, PRADC); // power down the ADC PRR = bit(PRTIM1); // only keep timer 0 going if (LEDpin) { activityLED(1, 1000); // LED on/off } } // Loop void loop() { if (rf12_recvDone()) { if (rf12_crc == 0) { // zero indicates correct reception if (RF12_WANTS_ACK) { rf12_sendStart(RF12_ACK_REPLY, 0, 0); //mySerial.print(" - ACK send"); } //node ID of TX, extracted from RF datapacket. Not transmitted as part of structure mySerial.print(rf12_hdr, DEC); mySerial.print(" "); int i; for (byte i = 0; i < rf12_len; i++) mySerial.print((char)rf12_data[i]); if (LEDpin) { activityLED(1, 100); // LED on/off activityLED(1, 100); // LED on/off } } else { mySerial.print("BAD-CRC"); if (LEDpin) { activityLED(1, 1000); // LED on/off } } mySerial.println(); } while (mySerial.available() > 0){ inputString += (char)mySerial.read(); } if (inputString != ""){ // get SENDTO NodeID for (int i = 0; i < inputString.length(); i++) { if (inputString.substring(i, i+1) == ':') { SENDTO = inputString.substring(0, i).toInt(); Message = inputString.substring(i+1); break; } } char msg[Message.length() + 1]; Message.toCharArray(msg, Message.length() + 1); activityLED(1); // LED on rf12_sendStart(SENDTO, (uint8_t *)msg, strlen(msg), requestACK); rf12_sendWait(2); activityLED(0); // LED off inputString = ""; msg[0] = (char)0; } }
-
Die einzige Anpassung die man im Sketch bezüglich der Frequenz vornehmen muss ist besagte FREQ Einstellung welche dann beim "Initialize" verwendet wird. Zerstören tut man sich dadurch nichts.
Kommentare sind halt Kommentare und werden ignoriert.Auch bei den TinyTX3 kann man eine LED anschließen. Genauso wie bei den TinyTX4 sind oben Lötaugen die ebenso nummeriert sind, z.B.: Lötauge 0 ist der ATtiny D0 pin. Schließ also einfach eine LED an einen der freien Lötaugen sowie GND an und pass den Sketch entsprechend an.
Also das Problem mit den Frequenzen hab ich in den Griff bekommen. Es lag anscheinend an falschen Parametern in den Sketchen. Sprich ich habe NodeID nicht einheitlich gehalten.
Nun aber zu der LED Geschichte. Ich bekomme es einfach nicht hin. Nutze Sketche von Meigraf aus 2013. link
wenn ich es recht sehe und den Code richtig verstehe, ist dort die LED angesprochen.
Welche Lötaugen muss ich bei den TinyTX3 verwenden?Danke für Hinweise.
-
-
...Ich arbeite gerade an einer (hoffentlich) verbesserten Version vom Sensor.pl sowie dem Web-Interface...
Die Sensor.pl will ich durch TinySensor.py ersetzen - ein python3 Script was die Daten vom TinyRX annimmt und direkt in SQLite schreibt. Eine add.php würde dann also entfallen.
Allerdings habe ich das aufgrund von möglichst hoher Flexibilität umstrukturiert:
- Für jede NodeID wird ein Verzeichnis angelegt.
- In diesem Unterordner liegt die SQLite3 Datenbankdatei sensor.db
- Für jeden Wert wird in der Datenbankdatei eine eigene Tabelle erstellt.Der empfangene String von zB. " 22 v=3100&t=3400&h=6700&r=0 " wird zerlegt.
Als erstes anhand des Leerzeichens um die NodeID von den Daten zu trennen und schon mal zu speichern.
Dann wir der Daten-String anhand von " & " zerlegt, um dann jeden einzelnen Wert in einer Schleife abzuarbeiten. Also zB ein Schleifendurchgang für "v=3100", danach ein Durchgang für "t=3400" usw.
Dann zerlege ich diesen Wert ebenfalls noch mal anhand des " = " um eben den Wert-Namen vom eigentlichen Wert zu trennen...
Nun wird eine Tabelle (falls noch nicht vorhanden) mit dem "Wert-Namen" angelegt, ein timestamp von dem Moment wo die Daten empfangen wurden (selber timestamp in allen Tabellen) eingefügt sowie der "value" also tatsächliche Wert.Was ich mir dabei gedacht habe ist folgendes:
Wer sein Funksensor Netzwerk später mit einem Sensor erweitern möchte der aber noch nicht eingepflegt ist, musste bisher selber die SQLite Datenbank um eine weitere Spalte erweitern. Das geht meistens nicht so einfach bzw nur mit entsprechenden Kentnissen, oder eben sowas wie phpMyAdmin für SQLite....
Also wie ihr bestimmt schon gesehen habt steht " t= " für Temperatur, " h= " für Luftfeuchte, " p= " für Luftdruck , " v= " für supplyV usw.
Nimmt man jetzt aber einen anderen Sensor wie zB einen Ultraschall, muss man sich einen anderen Wert-Namen überlegen bzw in den Sketch einsetzen - wie zum Beispiel " us= ". Dieser Wert wird dann aber aktuell nicht eingepflegt da weder die add.php davon "weiß" noch die SQLite Datenbankdatei dafür eine Spalte hat.Eben genau aus diesem Grund wird mit der Version die ich aktuell entwickle, nur im TinySensor.py ein mal eingestellt welcher "kurze Wert-Name" (also " t= " usw) in wirklichkeit wofür steht bzw wie dann der Tabellen-Name lauten soll.
Alle anderen Werte die nicht in dem Script stehen werden in die Tabelle "unknown" eingetragen.
Diese Einstellung sieht wie folgt aus:PHP
Alles anzeigenSensorTypes = ["v=volt", "t=temp", "h=hum", "r=reed", "p=pres"][/php] Alle Werte erhalten den selben/identischen timestamp Wert, können also später anhand dieses Wertes auseinander gehalten werden bzw ist der Timestamp vom "Unknown" Wert der selbe wie vom "volt" Wert, ergo gehören die irgendwie zum selben Sensor ;) Das Script müsste eigentlich bereits funktionieren: [spoiler="TinySensor.py"][code=php]#!/usr/bin/python3 # coding: utf-8 # # Receive Data from TinyRX over UART and save directly to SQLite Datanbase files. # creating for each Node an own Directory and for each Sensor Value an own Database-Table. # # v0.1 by meigrafd @ 06.02.2015 # import serial, time, os, string import sqlite3 as sqlite #------------------------------------------------------------------------ # Specify your serial port path (/dev/ttyAMA0 is default for Raspberry Pi) ser = serial.Serial("/dev/ttyAMA0", baudrate=9600, timeout=0.1) # Specify the directory of SQLite Database files DBdir = "/var/Sensors" # Specify the known types from sensors # e.g.: ["v=volt", "t=temp", "h=hum", "r=reed", "p=pres"] # -> v must be in Datastring and volt is the name of Database-Table # Not known types goes to Database Table -> unknown SensorTypes = ["v=volt", "t=temp", "h=hum", "r=reed", "p=pres"] #------------------------------------------------------------------------ # This function process data from serial port and prints received values in human readable format def processData(rx): tempTypes = [] # rx: 22 v=3100&t=3400&h=6700&r=0 data = rx.strip().split(' ') nodeID = data[0] #analyse data: v=3100&t=3400&h=6700&r=0 sensorData = data[1].split('&') for senD in sensorData: #sensorData eg: v=3100 t=3400 h=6700 r=0 typeFound = False value = senD.split('=') #value eg: v 3100 for sT in SensorTypes: #sT eg: v=volt sT2 = sT.split('=') #eg: v volt if value[0] == sT2[0]: dbTable = sT2[1] typeFound = True break if typeFound == False: dbTable = "unknown" if dbTable == "volt": voltage = value[1] supplyV = round(float(voltage)/1000.0, 2) else: tempTypes.append(dbTable+":"+value[1]) #insert into Database insertData(nodeID, dbTable, value[1]) output = "NID:%s vcc:%sv" % (nodeID, supplyV) for tT in tempTypes: output = output +" "+ tT # Ausgabe print(output) if int(voltage) < 3100: print("Battery in your TinyTX id "+nodeID+" is running low! Actual reading shows: "+str(voltage)+" Millivolts") # This function inserts received data into sqlite database def insertData(node, table, data): try: directory = DBdir+"/"+node+"/" dbfile = "sensor.db" if not os.path.exists(directory): os.makedirs(directory) open(dbfile, 'a').close() except OSError as ose: print("Error creating directory '{}': {}".format(directory, str(ose))) try: con = None con = sqlite.connect(directory+dbfile) cur = con.cursor() cur.execute("CREATE TABLE IF NOT EXISTS "+table+" (id INTEGER PRIMARY KEY,time INT,value TEXT);") cur.execute("INSERT INTO "+table+" (time, value) VALUES (?,?);", (timestamp, data)) con.commit() except sqlite.Error as e: print("Error %s:" % e.args[0]) finally: if con: con.close() if __name__ == '__main__': running = True try: ser.open() except Exception as e: print("Error open serial port: %s" % str(e)) if ser.isOpen(): try: ser.flushInput() #flush input buffer, discarding all its contents ser.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer print("Tiny Sensors with RFM12B. Waiting for Data...\r\n") while running: data = ser.read(1) # read one, blocking n = ser.inWaiting() # look if there is more if n: data = data + ser.read(n) # and get as much as possible if len(data) > 0: timestamp = int(time.time()) print("Got data: " + data) processData(data) except serial.SerialException as e: print("Could not open serial port: {}".format(e)) except Exception as e1: print("Error: " + str(e1)) except (KeyboardInterrupt, SystemExit): print("\nSchliesse Programme..") running = False else: print("Cannot open serial port") ser.close()[/php][code]apt-get install python3-serial
[/spoiler]
Allerdings bringt das noch nicht sooo viel, solange das Web-Interface noch nicht angepasst wurde Daran arbeite ich zZt noch...
-
Ist dieser Spannungswert in Ordnung? Ich messe an den AKKUS 4.15V.
15 v=3362&t=2380&h=3750Warum zeigt er mir 3362mV?
-
Welcher Sketch, welche Platine , wieviel Sensoren?
-
Send_DHT22_Watchdog.ino, Platine von erster Sammelbestellung mit Booster, Insgesamt 7 Sensor aber erstmal ein Sensor zum Testen angeschlossen
-
Ist dieser Spannungswert in Ordnung? Ich messe an den AKKUS 4.15V.
15 v=3362&t=2380&h=3750Warum zeigt er mir 3362mV?
Der Booster regelt die Spannung auch bei höherer Eingangsspannung auf 3,3V . Ist also in Ordnung.
Fraglich ist, ob wir mit der aktuellen Umsetzung überhaupt mitbekommen, ob sich die Akkus langsam leeren...
-
Der Booster regelt die Spannung auch bei höherer Eingangsspannung auf 3,3V .Sicher? Das war doch nur ein Step-UP aber kein Step-DOWN :s
Fraglich ist, ob wir mit der aktuellen Umsetzung überhaupt mitbekommen, ob sich die Akkus langsam leeren...
Naja ich denke der Booster wird mit sinkender Kapazität auch unter 3.3V fallen und das wär dann ein Indikator dafür - aber auch wenn der Sensor länger als dem üblichen Intervall nichts mehr gesendet hat wäre es ein Hinweiß
Send_DHT22_Watchdog.ino
Kannst du Deinen Sketch bitte auch mal posten?
(bitte in CODE!)Insgesamt 7 Sensor
7 Sensoren an einem Sender? Wie geht das denn :s Eigentlich gehen nur maximal sechs Sensoren an einen TinyTX4
-
Haha, ich habe dich falsch verstanden. Es hängt nur ein DHT22 dran. Es sind sieben Sender [emoji2]
An deinem Sketch wurde nichts geändert ausser die ID des Sensors. Ich bin gerade unterwegs, kann dir daher den Code nicht mitteilen.
Ich probiere es später mit fast leeren Batterien ob er mir was anderes anzeigt. -
-
Hallo Leute,
ich habe mir für dieses Projekt selber Platinen hergestellt. Bei meiner Pinbelegung gibt es allerdings ein Problem, denn ich habe MOSI auf SDI und MISO auf SDO gelegt. Dies ist ja eigentlich auch richtig aber die Attiny84 Pinbelegung in der RF12.cpp von Jeelib scheint "Falsch" zu sein.
#define SPI_MISO 4 // PA6, pin 7
#define SPI_MOSI 5 // PA5, pin 8
Mir ist klar das hier ein Software SPI läuft und die Pins eigentlich egal sind, aber in der Beschreibung von RF12.cpp wird darauf hingewiesen das die Pins übereinstimmen sollten mit denen des Hardware SPI.
Nun habe ich die Pins einfach anders definiert:
#define SPI_MISO 5
#define SPI_MOSI 4
aber dies funkioniert nicht, die loop bleibt beim senden hängen. Wer kann mir auf die Sprünge helfen was habe ich übersehen?Vielen Dank
atommeyer -
Ein paar Änderungen in der TinySensor.py von gestern:
- Es wird nicht mehr für jede NodeID ein Verzeichnis angelegt, sondern einfach nur die Datenbankdatei mit der NodeID benannt: 1.db 2.db , 3.db ... 29.db
Diese Änderung musste ja zum glück auch nur in def insertData vorgenommen werden, und dazu auch gleich der Hinweiß das künftige Anpassungen für zB MySQL o.ä. ebenfalls eigentlich auch nur dort gemacht werden müssten - es sollte nun also leichter sein das eben jüst anzupassen.- Auch habe ich ein paar kleinere Fehler behoben, welche die Ausgabe auf der Konsole betroffen hat.
- Für SensorTypes hab ich die Tabellen-Namen vernünftig benannt, da diese Namen auch im Web-Interface die Spalten benennen werden:
[code=php]SensorTypes = ["v=Voltage=1000", "t=Temperature=100", "h=Humidity=100", "r=ReedSwitch", "p=Pressure", "us=Distance"][/php]Die tatsächlichen Namen (zB. Voltage) können nach belieben anders benannt werden, aber Falls das nachträglich gemacht wird muss die Datenbank gelöscht oder zumindest manuell angepasst werden denn sonst gibts noch die alte Tabelle.
Einzig ' v= ' muss aber so bleiben, der Rest ist eher nebensächlich.Wenn ihr aber vor habt mehrere Temperaturwerte von einem Sender zu erfassen, dann solltet ihr auch mehrere ' t=Temperature ' definieren, also zum Beispiel:[code=php]SensorTypes = ["v=Voltage=1000", "t1=Temperatur_Kuehlschrank=100", "t2=Temperatur_Kueche=100", "h=Humidity=100"][/php]..und natürlich auch vom Sketch t1= und t2= usw übertragen lassen..
- Die Werte von Voltage, Temperatur und Humidity usw werden bereits im TinySensor.py entsprechend geteilt/berechnet und fertig in die Datenbank eingetragen, damit es nicht zu kompliziert wird im Web-Interface herausfinden zu müssen ob die Werte durch 100 oder 1000 geteilt werden müssten... Dafür ist die optionale 2.Angabe: v=Voltage=1000
- Ich speicher auch nicht mehr "place" in der Datenbank. Das wird nur ein mal in der config.php festgelegt, da das für die Datenbank an sich eigentlich nicht wichtig ist, denk ich :s
- Zuvor gab es auch noch ein Rechteproblem, wodurch der www-data Benutzer kein Zugriff auf die Dateien hatte. Das Python Script regelt das jetzt ebenfalls.
- Hab auch ein testMode eingebaut um die Einstellungen des Scripts zu überprüfen. Dabei werden 5 empfangene Node-Daten simuliert und durch processData gejagt, aber ohne irgend etwas in die Datenbanken zu schreiben.
[code=php]
processData("22 v=4100&t=3421&h=6712&r=0")
processData("21 v=3099&us=321")
processData("23 v=3100&t=3487&h=6798&r=0&p=926")
processData("19 v=3000&t=4512&h=9911&r=0&p=321")
processData("10 v=4321&t2=5612")
[/php]"TinySensor.py"
[code=php]
#!/usr/bin/python3
# coding: utf-8
#
# Receive Data from TinyRX over UART and save directly to SQLite Datanbase files.
# creating for each Node an own Directory and for each Sensor Value an own Database-Table.
#
# v0.2 by meigrafd @ 08.02.2015
#
import serial, time, os
import sqlite3 as sqlite
#------------------------------------------------------------------------
# Specify your serial port path (/dev/ttyAMA0 is default for Raspberry Pi)
ser = serial.Serial("/dev/ttyAMA0", baudrate=9600, timeout=0.1)# Specify the directory of SQLite Database files
DBdir = "/var/Sensors"# Specify the known types from sensors
# e.g.: ["v=Voltage=1000", "t=Temperature=100", "h=Humidity=100", "r=ReedSwitch", "p=Pressure", "us=Distance"]
# -> v must be in Datastring and volt is the name of Database-Table
# Not known types goes to Database Table -> unknown
# The second setting after Voltage (=1000) is the optional divide value eg. Voltage needs to get divide by 1000.
SensorTypes = ["v=Voltage=1000", "t=Temperature=100", "h=Humidity=100", "r=ReedSwitch", "p=Pressure", "us=Distance"]# Specify the battery limit in milliVolt for notice
batteryLimit = 3100# Enable TEST-MODE?
# If set to True the Script process's static lines and quits without adding or receiving anything.. (debugging)
testMode = False
#------------------------------------------------------------------------# This function process data from serial port and prints received values in human readable format
def processData(rx):
# rx: 22 v=3100&t=3400&h=6700&r=0
data = rx.strip().split(' ')
nodeID = data[0]
output = "NID:%s" % nodeID
#analyse data: v=3100&t=3400&h=6700&r=0
sensorData = data[1].split('&')
for senD in sensorData: #sensorData eg: v=3100 t=3400 h=6700 r=0
typeFound = False
divide = False
value = senD.split('=') #value eg: v 3100
for sType in SensorTypes: #sType eg: v=Voltage=1000
ssType = sType.split('=') #eg: v Voltage 1000
if value[0] == ssType[0]:
dbTable = ssType[1]
typeFound = True
if len(ssType) > 2:
divide = ssType[2]
break
if divide:
if value[0] == "v":
if int(value[1]) < batteryLimit:
print("Battery in your TinyTX id "+nodeID+" is running low! Actual reading shows: "+str(value[1])+"mV")
VALUE = round(float(value[1]) / float(divide), 2)
output += " VCC:%sv" % VALUE
else:
VALUE = round(float(value[1]) / float(divide), 2)
else:
VALUE = value[1]
if typeFound == False:
output += " unknown:%s" % VALUE
dbTable = "unknown"
else:
output += " "+dbTable+":%s" % VALUE
#insert into Database
if not testMode:
insertData(nodeID, dbTable, VALUE)
# Ausgabe
print(output)# This function inserts received data into sqlite database
def insertData(node, table, data):
database = DBdir +"/"+ node +".db"
if not os.path.isfile(database):
open(database, 'a').close()
os.chown(database, 33, 33)
try:
con = None
con = sqlite.connect(database)
cur = con.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS "+table+" (id INTEGER PRIMARY KEY,time INT,value TEXT);")
cur.execute("INSERT INTO "+table+" (time, value) VALUES (?,?);", (timestamp, data))
con.commit()
except sqlite.Error as e:
print("Error %s:" % e.args[0])
finally:
if con:
con.close()if __name__ == '__main__':
try:
if not os.path.exists(DBdir):
os.makedirs(DBdir)
os.chown(DBdir, 33, 33)
except OSError as ose:
print("Error creating directory '{}': {}".format(DBdir, str(ose)))
running = True
try:
ser.open()
except Exception as e:
print("Error open serial port: %s" % str(e))
if ser.isOpen():
try:
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer
print("Tiny Sensors with RFM12B. Waiting for Data...\r\n")
if testMode:
timestamp = int(time.time())
processData("22 v=4100&t=3421&h=6712&r=0")
processData("21 v=3099&us=321")
processData("23 v=3100&t=3487&h=6798&r=0&p=926")
processData("19 v=3000&t=4512&h=9911&r=0&p=321")
processData("10 v=4321&t2=5612")
exit()
while running:
data = ser.read(1) # read one, blocking
n = ser.inWaiting() # look if there is more
if n:
data = data + ser.read(n) # and get as much as possible
if len(data) > 0:
timestamp = int(time.time())
print("Got data: " + data)
processData(data)
except serial.SerialException as e:
print("Could not open serial port: {}".format(e))
except Exception as e1:
print("Error: " + str(e1))
except (KeyboardInterrupt, SystemExit):
print("\nSchliesse Programm..")
running = False
else:
print("Cannot open serial port")ser.close()
[/php]Vom Web-Interface werden nur Datenbank-Dateien beachtet die eine Zahl am Anfang des Dateinamens enthalten. So könnte später also auch noch eine Datenbank-Datei existieren in der die NodeID und der 'place' hinterlegt ist, aber das behalte ich mir vor vielleicht irgendwann mal zu erweitern
Mit dem WI bin ich aber noch nicht fertig
-
So, noch ein paar kleinere Änderungen
- Unterstützung für MySQL eingebaut, für den Fall das jemand zB. mehrere RaspberryPI's hat aber alle in eine Datenbank schreiben sollen, oder einfach nur um die Daten auszulagern.
Dafür verwende ich CyMySQL da das einfacher einzubauen ist (für MySQLdb mit python3 ist der Installationsaufwand größer).Aber ich muss euch dennoch warnen, MySQL ist (zumindest auf dem Pi-1) langsamer und verursacht auch mehr CPU+RAM Auslastung! Außerdem verballert es permanent CPU+RAM auch wenn es gar nicht genutzt wird.
Es wird wie mit SQLite pro NodeID eine Datenbank angelegt die aber mit dem Prefix TinyTX_ benannt ist (also zB. TinyTX_22) und in dieser Datenbank auch pro SensorType eine Tabelle.
- Serial ist etwas umfangreicher implementiert um genauere Einstellungen vornehmen zu können.
- Konsolen Ausgaben sind jetzt in Farbe Also insbesondere der Hinweis das die Battery leer sein könnte, aber auch Fehlermeldungen. Später könnte man auch die SensorTypen Ausgaben einfärben aber ich will's ja nicht gleich übertreiben...
Zur Verwaltung der SQLite Datenbanken empfehle ich phpLiteAdmin, das ist nur ein PHP File was man irgendwo in /var/www/ ablegen brauch und ist so ähnlich wie phpMyAdmin.
"TinySensor.py"
[code=php]
#!/usr/bin/python3
# coding: utf-8
#
# Receive Data from TinyRX over UART and save directly to Datanbase.
# - SQLite and MySQL Support.
# - Creating for each Node an own Database and for each SensorType an own Table.
#
# v0.31 by meigrafd @ 08.02.2015
#
### Setup:
# You must install following packages:
# apt-get install python3 python3-serial
#
# Do following steps if you want to use MySQL instead of SQLite:
# apt-get install python3-pip
# pip3 install cymysql
#
#------------------------------------------------------------------------
# Specify your serial port path (/dev/ttyAMA0 is default for RaspberryPi)
SerialPort = '/dev/ttyAMA0'
# And its Speed
SerialBaudrate = 9600# Use SQLite or MySQL? [mysql / sqlite]
dbServ = 'sqlite'# Specify the directory for SQLite Database files
DBdir = '/var/Sensors'# If using MySQL specify Host, Port, Login and Password
mysqlHost = '127.0.0.1'
mysqlPort = '3306'
mysqlLogin = 'root'
mysqlPass = 'raspberry'# Specify the known types from sensors
# e.g.: ["v=Voltage=1000", "t=Temperature=100", "h=Humidity=100", "r=ReedSwitch", "p=Pressure", "us=Distance"]
# -> v must be in Datastring and volt is the name of Database-Table
# Not known types goes to Database Table -> unknown
# The second setting after Voltage (=1000) is the optional divide value eg. Voltage needs to get divide by 1000.
SensorTypes = ["v=Voltage=1000", "t=Temperature=100", "h=Humidity=100", "r=ReedSwitch", "p=Pressure", "us=Distance"]# Specify the battery limit in milliVolt for notice
batteryLimit = 3100# Enable TEST-MODE?
# If set to True the Script process's static lines and quits without adding or receiving anything.. (debugging)
testMode = False#------------------------------------------------------------------------
import time, os
try:
import serial
except ImportError:
print("ERROR: You must install serial Module: apt-get install python3-serial")
exit()
if dbServ == 'sqlite':
import sqlite3 as sqlite
elif dbServ == 'mysql':
try:
import cymysql
except ImportError:
print("ERROR: You must install cymysql Module: apt-get install python3-pip && pip3 install cymysql")
exit()
else:
print("ERROR: invalid 'dbServ' setting!")
exit()# serial docu: http://pyserial.sourceforge.net/pyserial.html
# initialization and open the port.
# possible timeout values:
# 1. None: wait forever, block call
# 2. 0: non-blocking mode, return immediately
# 3. x, x is bigger than 0, float allowed, timeout block call
ser = serial.Serial()
ser.port = SerialPort
ser.baudrate = SerialBaudrate
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
#ser.timeout = None #block read
ser.timeout = 1 #non-block read
#ser.timeout = 2 #timeout block read
ser.xonxoff = False #disable software flow control
ser.rtscts = False #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 2 #timeout for write
#------------------------------------------------------------------------# This handles console colors used for print's
#http://misc.flogisoft.com/bash/tip_colors_and_formatting
class c:
ENDC='\33[0m'
DEFAULT='\33[39m'; BOLD='\33[1m'; DIM='\33[2m'
RESBOLD='\33[21m'; RESDIM='\33[22m'
RED='\33[31m'; GREEN='\33[32m'; YELLOW='\33[33m'; CYAN='\33[36m'# This function process data from serial port and prints received values in human readable format
def processData(rx):
# rx: 22 v=3100&t=3400&h=6700&r=0
data = rx.strip().split(' ')
nodeID = data[0]
output = "NID:%s" % nodeID
#analyse data: v=3100&t=3400&h=6700&r=0
sensorData = data[1].split('&')
for senD in sensorData: #sensorData eg: v=3100 t=3400 h=6700 r=0
dbTable = "unknown"
divide = False
value = senD.split('=') #value eg: v 3100
for sType in SensorTypes: #sType eg: v=Voltage=1000
ssType = sType.split('=') #eg: v Voltage 1000
if value[0] == ssType[0]:
dbTable = ssType[1]
if len(ssType) > 2:
divide = ssType[2]
break
if divide:
VALUE = round(float(value[1]) / float(divide), 2)
if value[0] == "v":
if int(value[1]) < batteryLimit:
print(c.BOLD+c.RED+"Battery in your TinyTX id "+c.CYAN+nodeID+c.RED+" is running low!"+c.ENDC, end='')
print(" Actual reading shows: "+c.BOLD+c.YELLOW+str(value[1])+"mV"+c.ENDC)
output += " VCC:%sv" % VALUE
continue
else:
VALUE = value[1]
output += " "+dbTable+":%s" % VALUE
#insert into Database
if not testMode:
insertData(int(nodeID), dbTable, VALUE)
# Ausgabe
print(output)# This function inserts received data into sqlite database
def insertData(nodeID, table, data):
try:
con = None
if dbServ == 'mysql':
try:
con = cymysql.connect(host=mysqlHost, port=int(mysqlPort), user=mysqlLogin, passwd=mysqlPass)
cur = con.cursor()
cur.execute("CREATE DATABASE IF NOT EXISTS TinyTX_%s;", (nodeID))
cur.execute("USE TinyTX_%s;", (nodeID))
con.commit()
cur.execute("CREATE TABLE IF NOT EXISTS "+table+" (id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,time INT(11),value VARCHAR(20));")
cur.execute("INSERT INTO "+table+" (time, value) VALUES (%s,%s);", (timestamp, data))
except Exception as err:
print(c.BOLD+c.RED+"MySQL Error: "+str(err)+c.ENDC)
except (KeyboardInterrupt, SystemExit):
exit()
else:
database = DBdir +"/"+ nodeID +".db"
if not os.path.isfile(database):
open(database, 'a').close()
os.chown(database, 33, 33)
con = sqlite.connect(database)
cur = con.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS "+table+" (id INTEGER PRIMARY KEY,time INT,value TEXT);")
cur.execute("INSERT INTO "+table+" (time, value) VALUES (?,?);", (timestamp, data))con.commit()
except sqlite.Error as err:
print(c.BOLD+c.RED+"SQLite Error "+err.args[0]+c.ENDC)
except Exception as err:
print(c.BOLD+c.RED+"DB Error: "+str(err)+c.ENDC)
finally:
if con:
con.close()if __name__ == '__main__':
try:
if not os.path.exists(DBdir):
os.makedirs(DBdir)
os.chown(DBdir, 33, 33)
except OSError as ose:
print("Error creating directory '{}': {}".format(DBdir, str(ose)))
running = True
try:
ser.open()
except Exception as e:
print("Error open serial port: %s" % str(e))
if ser.isOpen():
try:
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer
print("Tiny Sensors with RFM12B. Waiting for Data...\r\n")
if testMode:
timestamp = int(time.time())
processData("22 v=4100&t=3421&h=6712&r=0")
processData("21 v=3099&us=321")
processData("23 v=3100&t=3487&h=6798&r=0&p=926")
processData("19 v=3000&t=4512&h=9911&r=0&p=321")
processData("10 v=4321&t2=5612")
exit()
while running:
data = ser.read(1) # read one, blocking
n = ser.inWaiting() # look if there is more
if n:
data = data + ser.read(n) # and get as much as possible
if len(data) > 0:
timestamp = int(time.time())
print("Got data: " + data)
processData(data)
except serial.SerialException as e:
print("Could not open serial port: {}".format(e))
except Exception as e1:
print("Error: " + str(e1))
except (KeyboardInterrupt, SystemExit):
print("\nSchliesse Programm..")
running = False
else:
print("Cannot open serial port")ser.close()
[/php]Das sollte es aber auch erst mal zur TinySensor.py sein. Werde mich jetzt nur noch ums WebIf kümmern
-
Nein, brauch ich aber auch nicht hab noch 6 hier rumfliegen
Bin ich bisher nicht zu gekomm das zu testen - vielleicht morgen
Hi meigrafd,bis Du u.U. schon mal zum Testen gekommen? Evtl. im Rahmen Deiner TinySensor.py Weiterentwicklung - da hast Du als Beispiel ja einen Ultraschall-Sensor erwähnt :thumbs1:
-
Hallo,
ich bin heute hierauf http://hallard.me/bp-ulpnode/ gestossen. Nach der Suche im Forum scheint mir, als ob dieses Projekt hier noch nicht zur Sprache kam.
VG
-
-
Jetzt mitmachen!
Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!