combining Python codes and capturing to CSV
I have been tasking myself with making a device that will monitor an NHS bed. One that will detect and record a patient’s weight and if the bed is wet or dry. I have built the sensor circuits and written code that will allow a Raspberry Pi to process the information from the sensors which will be attached through the GPIO pins. I have built each stage of the device separately, with separate codes and circuits —, that way I could narrow any errors down to the specific circuit or code. In this post, I will be looking at combining the code I wrote for my moisture sensor and the analogue- to- digital converter that takes a voltage reading from the load cell and converts the reading into a weight. I'll then look at writing the two values, along with the date and time, into a comma separated value file. I'll be going into a little detail about the error handing I used too.
The code so far
The moisture sensor code and the print out it gives in the terminal can be seen below. I covered how this e code worked in my previous post
The code for weighing the patient was a little more tasking., That was all explained in
and can be seen below, again along with its terminal print out
My task now was to try and combine them into one code and then have them write to a comma separated file.
Comma Separated Values Files (CSV)
A CSV is a file that contains and displays values as a series of text lines arranged so that each column value is separated from the next by a comma and where each row starts with a new line. Here's an example: 25/12/3000, Bissett, Design spark blog 4, …. 25/12/3001, Bissett, Design spark blog 5,….. A CSV file is the perfect starting point for data that will eventually end up in a table orientated application like Excel. Excel is where I plan on shipping all of these rows to be packaged in a neat little graph I can glance at and instantly process, rather than troll through rows and rows of info to pick out what I need. A screen shot of my CSV file can be seen below, I did not hook up the Pi for the purpose of this, all I wanted to know was that the code would run, the values didn't really matter at this point.
Now to take a look at how I got there.
The combined code
To get to this point I combined my code in the way that can be seen below in the screenshot. Rather than write a long paragraph about it here, I wanted anyone that came across the code to be able to grasp what is was doing so I commented on each line about its purpose within the code. This can be seen more clearly in the screen shots blow.
Good practice for coding
The code at first glance looks quite different. Some parts are, but the majority has stayed the same. The differences are mainly due to where in the code each line has been placed. One of the biggest parts about combining them is to trim it down to only the essentials and clean it up a little. It is good practice to group like things together —, imports, variables etc —, so everything I needed to import I did first, then I defined all my variables and created opened the file I was going to write to. Both sets of the original codes used “import time”, but it’s only necessary to do this once to cut down on unnecessary lines of code. It is also good practice to space the sections of the code in a way that makes it easier for the reader to follow and, much like a book or a blog, it needs to be broken into easy to follow sections. Paragraphing, but for coding so to speak. In the comments, I said that file=open (bedlog.csv, “w”) opens the file bedlog.csv and the “w” instructs that we are going to write to it. What I didn't mention is that there is no need to create the file first, by instructing it to be opened, the Pi automatically creates the file, even more time saved.
The main body of the code is the different function blocks. A function block works in the same way that inbuilt functions like 'print' do. It informs the Pi to perform a single, related action. Function blocks begin with the keyword def followed by the function name and parentheses ( ). Whatever you want the function follows Eg def getBedStatus() if GPIO.input(collector) == False: status = "wet" else: status = "dry" return status I have explained what that block actually does on the screenshot. Once the function is defined it can be performed at any point in the code without having to type it all out again, again saving time.
A string is usually a line of information that you are going to export out of the program, like I am to the CSV file. I did a little bit of an internal cry when I read other posts about strings. Everything looked so complex, there were percentage signs all over the place and more colons and brackets than my eyes could even differentiate. However, once I’d pieced together the information from a few and used each to work out what the other meant I understood this. Python is pretty smart —, just put some double (“) or single (') quotes around it and it knowns it’s a sting. If there’s multiple parts to it, put it in brackets and separate them with commas. Strings can contain format characters, but simply put the formatted variables in the string, and then a %percent character, followed by the variable. See the screen shot below for an informative and nerd based humour example of the string code and the terminal print what it would produce when the program is run.
SO it turns out, really not as scary or as mind blowing as I first thought. I could simply use print "time: " + now + ", weight: " + weight + ", status: " + status
file.write("Time: " + now + ", Weight: " + weight + ", Bed status: " + status + '\n') in order to export my string of variables to the CSV file.
Error handling is always good practice, so I chose to use try and except as my error handling heroes. My try block code contained a while true loop that the program will run until it encounters an error, either by someone closing the program using Ctrl C or an error on the sensors etc. Once this error is encountered the program is forced out of the try block and into the except block where it is further instructed what to do. So, in my case I am saying try this while true loop, if the loop has an error, close the file. Raising your own exceptions means that you can tell the Pi what do when encountering different errors. Best practice means you should use the most specific exception constructs that systematically fits your issue, as mine was quite simple so was my exception, just to close the file, but it could be used to print out different warnings based on the type of error, e.g “moisture sensor error” or “weigh patient error” cutting down the time needed to locate and repair the fault.
The next step
Now I have my code up and running and writing to the file the next step is to take the information from the CSV file and produce my graphs with it. However, graphs that say depict a constant patient weight of 0kg and an unchanging dry bed status won’t be very interesting to look at. Therefore, I will look at combining all of my circuits, soldering and encasing them into a more professional looking format. The I can get the device up and running so I can process some real values and create some graphs worth looking at.