I found and edited some code that records water flow data off of a flowmeter. I have managed to edit the script to run for only 5 mins and write to a file (I tried a .csv file but I am realizing this may not be entirely possible). However, when the script runs, the data file created just lists one “row” of recorded data. The while loop runs every 5 seconds for about 5 mins and provides a timestamp and a flow-rate reading, I’m trying to get the script to continuously record data. Here is the code:
import json import time from datetime import datetime, timedelta import RPi.GPIO as GPIO import csv class FlowMeter(): ''' Class representing the flow meter sensor which handles input pulses and calculates current flow rate (L/min) measurement ''' def __init__(self): self.flow_rate = 0.0 self.last_time = datetime.now() def pulseCallback(self, p): ''' Callback that is executed with each pulse received from the sensor ''' # Calculate the time difference since last pulse recieved current_time = datetime.now() diff = (current_time - self.last_time).total_seconds() # Calculate current flow rate hertz = 1. / diff self.flow_rate = hertz / 7.5 # Reset time of last pulse self.last_time = current_time def getFlowRate(self): ''' Return the current flow rate measurement. If a pulse has not been received in more than one second, assume that flow has stopped and set flow rate to 0.0 ''' if (datetime.now() - self.last_time).total_seconds() > 1: self.flow_rate = 0.0 return self.flow_rate def main(): ''' Main function for repeatedly collecting flow rate measurements and sending them to the SORACOM API ''' # Configure GPIO pins INPUT_PIN = 7 GPIO.setmode(GPIO.BOARD) GPIO.setup(INPUT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Init FlowMeter instance and pulse callback flow_meter = FlowMeter() GPIO.add_event_detect(INPUT_PIN, GPIO.RISING, callback=flow_meter.pulseCallback, bouncetime=20) end_time = datetime.now() + timedelta(minutes=5) while True: timestamp = str(datetime.now()) flow_rate = flow_meter.getFlowRate() time.sleep(5) print('Timestamp: %s' % timestamp) print('Flow rate: %f' % flow_rate) header = ['Time','Flow Rate'] data = [timestamp, flow_rate] with open('flowrate.csv', 'w', encoding='UTF8', newline='') as f: writer = csv.writer(f) writer.writerow(header) writer.writerow(data) if datetime.now() > end_time: break if __name__ == '__main__': main()
I’ve included my “data writing” strings near the bottom in the while loop.
Advertisement
Answer
Opening the file with mode 'w'
overwrites the whole file every time. So, just write the header at the beginning, and “append” later on:
def main() with open('flowrate.csv', 'w', encoding='UTF8', newline='') as f: writer = csv.writer(f) writer.writerow(header) ... later, in the loop ... with open('flowrate.csv', 'a', encoding='UTF8', newline='') as f: writer = csv.writer(f) writer.writerow(data)
This is only practical if you’re really only writing a row every now and then. If you’re writing more often, then you should just keep the file open and reuse the writer
instance.