Code below is designed so when the motion sensor is triggered it starts recording data from the DHT11. The data is then sent to a site called cayenne for data transfer. The issue is that the data being recorded and sent to cayenne is not being stored into the CSV file that is also created. It successfully prints the titles for each piece of data, however the figures being read are not being printed.
Uses Raspberry Pi 3B+, DHT11 Temperature and Humidity sensor and PIR motion sensor.
import sys
import os
import Adafruit_DHT as dht
import cayenne.client
import RPi.GPIO as GPIO
# Added to deal with RPi 3B+
import platform
import re
import time
from time import strftime
import datetime
#Cayenne authentification info stuff
MQTT_USERNAME="4ff7bed0-f66b-11e8-a08c-c5a286f8c00d"
MQTT_PASSWORD="82e9cd4df60e9a8e864d0f4f80262322ad692068"
MQTT_CLIENT_ID="66751010-f7d6-11e8-898f-c12a468aadce"
client = cayenne.client.CayenneMQTTClient()
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)
# DHT sensor connected to Raspberry Pi to GPIO dhtpin.
dhtpin = 3 #pin03 is BCM2; 2 in BOARD
# Pin for Pir sensor
pirsensor = 17 # BOARD11
#GPIO.setmode(GPIO.BOARD) #for using the WiringPi numbers
GPIO.setmode(GPIO.BCM) #for the Broadcom numbers instead of the WiringPi numbers
#GPIO.setwarnings(False)
GPIO.setup(dhtpin, GPIO.OUT) # Set dhtpin as an output
GPIO.setup(pirsensor,GPIO.IN) #Set pirsensor to input
# Sensor should be set to Adafruit_DHT.DHT11, Adafruit_DHT.DHT22, or Adafruit_DHT.AM2302.
sensor = dht.DHT11
# Set Duration in second between two mesures.
period = 1
# Pir status
state = 0
#Create the log file in CSV format with header columns
with open('dhtpir.csv', 'a+') as f:
f.write(" DATE & TIME \t " + " , \t"+ "% HUMIDITY " + " , " + "T(Celcius)" + " , \t" + " T(Fahrenheit),\n")
while True:
# Note that sometimes you won't get a reading and the results will be null
# (because Linux can't guarantee the timing of calls to read the sensor).
# If this happens try again!
client.loop()
# Pir
time.sleep(0.1)
state = GPIO.input(pirsensor)
if state == 1:
humidity,tempC = dht.read_retry(dht.DHT11, dhtpin)
#Convert from Celcius to Farenheit
tempF = (9.0/5.0)*(tempC)+32
print("GPIO PIR pin %s is %s" % (pirsensor, state))
#Get the data
if humidity is not None and tempC is not None:
# Get the timestamp
timestamp = datetime.datetime.now().strftime("%Y%m%d %H:%M:%S")
client.celsiusWrite(1, tempC)
client.luxWrite(2, humidity)
# Print data to the terminal
print('{}'.format(timestamp),'\t Humidity: {0:0.1f}% Temperature: {1:0.1f} C'.format(humidity, tempC) , '({0:0.1f} F)'.format(tempF)), # print temperature in Celcius
# Fill the previously created log wile with the sensor data in csv format
#
with open('dhtpir.csv', 'a+') as f:
f.write('{}'.format(timestamp)+ " , \t" + (repr(humidity))+"%" + " , \t" + str(tempC)+" C" + " , \t" + '{0:0.1f} F,'.format(tempF) + " \n"),
#f.write(timestamp + " , \t" + (repr(humidity))+"%" + " , \t" + str(tempC)+" C" + " , \t" + str(tempF) + " F\n"), # just a different formating output
f.close() # not absolutly needed when using the 'with' syntax
else:
print('Exiting: failed to get reading.\n Try again!')
with open('dhtpir.csv', 'a+') as f:
f.write('{}'.format(timestamp)+ " , \t Exiting: failed to get reading.\n Try again!")
f.close()
sys.exit(1)
# Wait for the period in second between data reading
time.sleep(period)
GPIO.cleanup()
Related
So here is my code:
from os import system
from datetime import datetime
import time
import os
import subprocess
import sys
def status(ip_addr):
return os.system('ping ' + ip_addr + '> nul') == 0
statut[]
print("##################################")
print("Current time: ", str(datetime.now()))
print(" ")
with open('data.txt', 'r+') as adds:
add = [addrs.strip() for addrs in adds.readlines()]
for website in add:
stat = status(website)
if stat == 1:
stats = " is up!"
statut[website] = 1
else:
stats = " is down!"
statut[website] = 0
print(website, stats)
print("##################################")
while True:
print("Current time: ", str(datetime.now()))
print(" ")
with open('data.txt', 'r+') as adds:
add = [addrs.strip() for addrs in adds.readlines()]
for website in add:
stat = status(website)
if stat != statut[website]:
stats = " is up!"
statut[website] = stat
print(website, stats)
print("##################################")
time.sleep(240)
What I want to make out of it is to firstly learn if a server is up/down and after that, check at every 240 sec if it went the other way around - I can't however use boolean array "statut" like I intended. I would really apreciate some help with how I could make it work.
If you are just looking for a state change you could do something like this:
from os import system
from datetime import datetime
import time
def server_status(ip_addr):
if system('ping ' + ip_addr + '> nul') == 0:
return 'up'
else:
return 'down'
status_history = {}
print("##################################")
print("Current time: ", str(datetime.now()))
print(" ")
with open('data.txt', 'r+') as adds:
ipaddress = [addrs.strip() for addrs in adds.readlines()]
# Set inital state
for server in ipaddress:
status_history[server] = server_status(server)
print(f"{server} is {status_history[server]}")
print("##################################")
while True:
print("Current time: ", str(datetime.now()))
print(" ")
for server in ipaddress:
if server_status(server) != status_history[server]:
status_history[server] = server_status(server)
print(f"{server} has switched state to {status_history[server]}")
else:
print(f"{server} is still {status_history[server]}")
print("##################################")
time.sleep(10)
I would put a timeout on the while loop just in case and possible make some parts more configurable, such as the sleep.
I am running a Python Program on a Raspberry Pi 3 which I want to log the temperature from a DS18B20 sensor once every 0.25 seconds.
Earlier, when the program was simple and displaying the temperature on shell, it was quite fast and not having issues. Unfortunately due to the program itself now which includes logging to a file, I am getting a log every 2 seconds or 3 seconds only.
How do I ensure the 0.25 second logging interval.
I have shared the code below:
#This program logs temperature from DS18B20 and records it
#Plots the temperature-time plot.
import os
import sys
#import matplotlib.pyplot as plt
from re import findall
from time import sleep, strftime, time
from datetime import *
#plt.ion()
#x = []
#y = []
ds18b20 = ''
def setup():
global ds18b20
for i in os.listdir('/sys/bus/w1/devices'):
if i != 'w1_bus_master1':
ds18b20 = i
# Reads temperature data from the Temp sensor
# This needs to be modified for use with max31855 and K-type thermocouples
def read():
# global ds18b20
location = '/sys/bus/w1/devices/' + ds18b20 + '/w1_slave'
tfile = open(location)
text = tfile.read()
tfile.close()
secondline = text.split("\n")[1]
temperaturedata = secondline.split(" ")[9]
temperature = float(temperaturedata[2:])
temperature = temperature / 1000
return temperature
#Loop for logging - sleep, and interrupt to be configured.
def loop():
while True:
if read() != None:
print "Current temperature : %0.3f C" % read()
#sleep(0.25)
func()
def write_temp(temperature,file_name):
with open(file_name, 'a') as log:
log.write("{0},{1}\n".format(datetime.now().strftime("%d-%m-%Y %H:%M:%S"),str(temperature)))
arg = sys.argv[1]
filename1 = str(arg) + "-" + datetime.now().strftime("%d-%m-%Y-%H-%M-%S")+".csv"
def func():
temperature = read()
#sleep(0.25)
write_temp(temperature,filename1)
#graph(temperature)
#For plotting graph using MatPlotLib
#Comment out this function during foundry trials to avoid system slowdown
#Check system resource usage and slowdown using TOP or HTOP
#def graph(temperature):
# y.append(temperature)
# x.append(time())
# plt.clf()
# plt.scatter(x,y)
# plt.plot(x,y)
# plt.draw()
#Interrupt from command-line
def destroy():
pass
if __name__ == '__main__':
try:
setup()
func()
loop()
except KeyboardInterrupt:
destroy()
I have commented out sections that I thought to be resource heavy, but still I can't manage anything less than 2 seconds. I am getting results as below:
Output:
27-09-2016 12:18:41,23.0
27-09-2016 12:18:43,23.062
27-09-2016 12:18:46,23.125
27-09-2016 12:18:48,23.187
27-09-2016 12:18:50,23.187
27-09-2016 12:18:53,23.562
27-09-2016 12:18:55,25.875
27-09-2016 12:18:58,27.187
27-09-2016 12:19:00,27.5
Only open the logfile once (and close it on program exit)
Don't always re-read the temperature from the sensor. You call read() way too often.
Reduce general overhead and simplify your calls.
I am not able to completely test this, but something like this sould work:
import os
import sys
import time
from datetime import datetime
def read_temp(dev):
'''Reads temperature from sensor and returns it as float.'''
loc = '/sys/bus/w1/devices/' + dev + '/w1_slave'
with open(loc) as tf:
return float(tf.read().split('\n')[1].split(' ')[9][2:]) / 1000.0
def write_temp(t, logfile):
'''Writes temperature as .3 float to open file handle.'''
logfile.write('{0},{1:.3f}\n'.format(datetime.now().strftime('%d-%m-%Y %H:%M:%S'), t))
def loop(dev, logfile):
'''Starts temperature logging until user interrupts.'''
while True:
t = read_temp(dev)
if t:
write_temp(t, logfile)
print('Current temperature: {0:.3f} °C'.format(t))
sys.stdout.flush() # Flush. Btw, print is time-consuming!
time.sleep(.25)
if __name__ == '__main__':
# Take the first match for a device that is not 'w1_bus_master1'
dev = [d for d in os.listdir('/sys/bus/w1/devices') if d != 'w1_bus_master1'][0]
# Prepare the log filename
fname = str(sys.argv[1]) + "-" + datetime.now().strftime("%d-%m-%Y-%H-%M-%S")+".csv"
# Immediately open the log in append mode and do not close it!
logfile = open(fname, 'a')
try:
# Only pass device and file handle, not the file name.
loop(dev, logfile)
except KeyboardInterrupt:
# Close log file on exit
logfile.close()
I have been working on a weather station, which I want to be able to automatically post current weather to twitter. So far, I have been able to easily post regular strings such as t.statuses.update(status= 'twitter post!')
but whenever I attempt to post a variable, the current temperature for instance, I get this error:
Traceback (most recent call last): File
"/home/pi/Desktop/Python2Projects/MAIN.py", line 79, in
t.statuses.update (status= 'Current temperature in dowd house: %d F \n Windspeed: %d mph' %(temp, vmph) ) AttributeError: 'int' object
has no attribute 'statuses'
Here is my code so far, the twitter post line is at the very bottom:
#sets up libraries
from sys import argv
import os
import glob
import subprocess
import RPi.GPIO as GPIO
import time
import datetime
#Sets up twitter library
from twitter import *
access_token = 'secret'
access_token_secret = 'cant tell you'
consumer_key = 'i have to change all these'
consumer_secret = 'they usually have my twitter access keys'
t = Twitter(auth=OAuth(access_token, access_token_secret, consumer_key, consumer_secret))
#sets up GPIO for windspeed Hall effect sensor
GPIO.setmode(GPIO.BCM)
GPIO.setup(27, GPIO.IN)
#sets up GPIO for temperature probe
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
#usus probe to take temperature
def read_temp_raw():
catdata = subprocess.Popen(['cat',device_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out,err = catdata.communicate()
out_decode = out.decode('utf-8')
lines = out_decode.split('\n')
return lines
def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return float(temp_f) #float(temp_c)
temp = read_temp()
#setup for windspeed sensor
timy = datetime.datetime.now()
timx = datetime.datetime.now()
rotations = 0
#radious of windspeed sensor in meters
r = .1
#time in seconds you want sensor to collect data for average speed
t = 5
#main windspeed loop
timeout = time.time() + t
while True:
GPIO.wait_for_edge(27, GPIO.BOTH)
hallActive = GPIO.input(27)
if time.time() > timeout:
break
elif( hallActive == False ):
rotations = rotations + 1
elif( hallActive == True ):
pass
#function that converts rotations/s to mph
vmph = (r*6.28*rotations*2.2369) / t
GPIO.cleanup()
print 'Current temperature: %d F \n Windspeed: %d mph \n' %(temp, vmph)
t.statuses.update (status= 'Current temperature: %d F \n Windspeed: %d mph' %(temp, vmph) )
end of code
Thanks so much for any help or suggestions! It's greatly appreciated.
You are getting this problem because you assigned t to the value 5 here:
#time in seconds you want sensor to collect data for average speed
t = 5
After that point, you try to do t.statues but of course that won't work, since t is an integer and not a reference to the twitter api.
The easy way to solve this problem is to change the name of the twitter api handle at the very top of your script:
twitter_api = Twitter(auth=OAuth(access_token,
access_token_secret,
consumer_key, consumer_secret))
Then at the bottom, adjust your code accordingly:
temp_line = 'Current temperature: %d F \n Windspeed: %d mph \n' %(temp, vmph)
print(temp_line)
twitter_api.statuses.update(status=temp_line)
As a general rule, try to avoid single character named variables. They just add confusion to your code (as in this example) plus they make your code difficult to maintain in the future (for your, or anyone else that has to maintain it).
Python provides an excellent style guide, called PEP-8 which has some guidelines on how to format your code.
I have most of this app running smoothly I am trying to get this python code to send serial data through but I always get a 404 when I try to use python3 I get issues with the serialutil as far as basestring not being defined etc etc in the serial libraries. So I revert back to python 2.7 and am wondering if its possible to add the https into the string somewhere just to override whatever is happening that is reverting it back to http?
import serial
import time
import requests
import json
firebase_url = 'https://ourfleet.firebaseio.com'
auth_token = '0sBNZjz4uQvLteDoGSAJSKSDKSDBNASASJSDL'
#Connect to Serial Port for communication
ser = serial.Serial('/dev/tty.wchusbserial410', 9600, timeout=0)
#Setup a loop to send GPS values at fixed intervals
#in seconds
fixed_interval = 10
while 1:
try:
#GPS value obtained from Arduino + Ublox
gps_c = ser.readline()
#current time and date
time_hhmmss = time.strftime('%H:%M:%S')
date_mmddyyyy = time.strftime('%d/%m/%Y')
#current location name
gps_location = 'ourfleet'
print (gps_c + ',' + time_hhmmss + ',' + date_mmddyyyy + ',' + gps_location)
#insert record
data = {'date':date_mmddyyyy,'time':time_hhmmss,'location':gps_c}
result = requests.post('https://ourfleet.firebaseio.com' + '/' + gps_location + '/gps_c.json'+ auth_token, data=json.dumps(data))
#insert record
print ('Record inserted. Result Code = ' + str(result.status_code) + ',' + result.text)
time.sleep(fixed_interval)
except IOError:
print('Error! Something went wrong.')
time.sleep(fixed_interval)
I need to Write "pir sensor" motion detection COUNT to text file.
I tried with this code and this is work without writing to text file. when I put write to file it gives an error file = open("textFile.txt", "w")
IndentationError: unindent does not matchanyouter indentation level.
Expected Output is last motion count number in text file.
code is
# Import required Python libraries
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
# Define GPIO to use on Pi
GPIO_PIR = 7
# Set pin as input
GPIO.setup(GPIO_PIR,GPIO.IN)
Current_State = 0
Previous_State = 0
# I put Variable= 0 for the motion Count
Variable= 0
try:
print "Waiting for PIR to settle ..."
# Loop until PIR output is 0
while GPIO.input(GPIO_PIR)==1:
Current_State = 0
print " Ready"
# Loop until users quits with CTRL-C
while True :
# Read PIR state
Current_State = GPIO.input(GPIO_PIR)
if Current_State==1 and Previous_State==0:
# PIR is triggered
start_time=time.time()
print " Motion detected!"
# here I need to write numbers for the text file.
file = open("textFile.txt", "w")
file.write(Variable)
file.close()
Variable+=1
# Record previous state
Previous_State=1
elif Current_State==0 and Previous_State==1:
# PIR has returned to ready state
stop_time=time.time()
print " Ready ",
elapsed_time=int(stop_time-start_time)
print " (Elapsed time : " + str(elapsed_time) + " secs)"
Previous_State=0
except KeyboardInterrupt:
print " Quit"
# Reset GPIO settings
GPIO.cleanup()
import RPi.GPIO as GPIO
import time
# Use BCM GPIO references
# instead of physical pin numbers
GPIO.setmode(GPIO.BCM)
# Define GPIO to use on Pi
GPIO_PIR = 7
print "PIR Module Test (CTRL-C to exit)"
# Set pin as input
GPIO.setup(GPIO_PIR,GPIO.IN) # Echo
Current_State = 0
Previous_State = 0
Variable=0
try:
print "Waiting for PIR to settle ..."
# Loop until PIR output is 0
while GPIO.input(GPIO_PIR)==1:
Current_State = 0
print " Ready"
# Loop until users quits with CTRL-C
while True :
# Read PIR state
Current_State = GPIO.input(GPIO_PIR)
if Current_State==1 and Previous_State==0:
# PIR is triggered
print " Motion detected!"
# Record previous state
Previous_State=1
file = open("textFile.txt", "w")
file.write(Variable)
file.close()
Variable+=1
elif Current_State==0 and Previous_State==1:
# PIR has returned to ready state
print " Ready"
Previous_State=0
# Wait for 10 milliseconds
time.sleep(0.01)
except KeyboardInterrupt:
print " Quit"
# Reset GPIO settings
This is my friend's code.
(I believe nothing is wrong with your code but a few Indentation Error(e.g. spacing Error) For that you can use some sort of text editor (I use sublime text)
You need to use a string with file.write, here is an example:
file = open("textfile.txt", "rw+")
file.write(str(Variable))
file.close()