Skip to content
Advertisement

Have each loop iteration create a new line of data in a file

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.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement