Capturing Analogue Signals with a Raspberry Pi
In the quest to making my Raspberry Pi hospital bed monitoring system, it was easy enough to hook up a moisture sensor, since it was a digital signal after all. The compression cell however, not such a breeze. The compression cell isn’t just measuring a wet or dry, on or off state; it’s measuring varying values — analogue measurements that the Raspberry Pi can’t quantitate. First let’s look at the differences in the signals types and then at how we can marry them up
Analogue v Digital signals
Input signals can either be Analogue or Digital. Analogue signals are continuous signals that vary in value over time. Digital data by contrast to that is not continuous, it changes in individual steps and is either one thing or another. In my mind the easiest way to think about it is to think about light switches. A dimmer switch that can change the brightness of the bulb up and down, that’s analogue. A bog standard on or of light switch, that’s digital. It’s not quite as simple as that, but that’s what it basically boils down to. There’s upsides and down sides to both. Take the graph below.
If we read the blue analogue signal, we could get a value of 0.1,0.11, 0.12, 0.13Where with analogue we could be given a result of 0.01,0.02,0.03,0.04 or 0.05, the binary read out for all of these values would be 100. If we read the blue analogue signal, we could get a value of 0.1,0.11, 0.12, 0.13 — there’s over 100 values possible — but if we read the red digital signal, it’s either binary 0(000), 1(001) up to a max of 7(111), only 8 possible values. Meaning that with analogue we get more precise data, but with digital we have the potential to store more results.
We are living in a digital world, and my Pi is a digital girl, I need a way to change my analogue weight measurements into a digital signal the Pi can understand. Here comes the analogue-to-digital converter (ADC) to save the day!
An ADC takes the analogue value and converts it into a digital signal. Again, like the dumbing down of the differences between the signals, the converter is internally performing other kinds of magic to get this digital value, but that’s the bare bones of it. If we look at it in more depth, the ADC is not continuously measuring, but takes samples periodically, quantising the analogue value and producing a sequence of digital values based on the continuous input. An ADC is characterised by its bandwidth and signal-to-noise ratio (SNR). What will affect our values the most is the dynamic range of the ADC, and this is effected by how accurately the signal is sampled and measured, the amount of aliasing, where signals become indistinguishable from one another, but primarily on the resolution. Resolution is the amount of digital values we can get from the range of analogue values. Remember before when we had 100 analogue input values and only 7 digital output values, that not a great amount. We discuss this amount in terms of “bits”. We’re talking about binary here so were looking at base 2 numbers, so a 2bit converter, 22 =4, so you can store 4 values, 00,01,10 and 11. If we imagine that the analogue input we are converting is voltage which ranges from 0v to 20v, the representation would be:
Each bit represents a range of 5v, therefore the resolution is 5v per bit. For a 12-bit resolution we can represent 4096 values digitally, 20/4096= 4.8828125x10-3 0.00488 volts per bit or 4.88mv/bit. When we see manufacturer information stating it’s a 12-bit, 16bit or 64-bit device, that simply means that is has an analogue to digital converter that returns 12-bits, 16 bits or 64 bits — this is known as the word length. The higher the word length/ Bit count, usually better, but this is not always the case. The number says little about the quality of the bits. Anyway, clearly the bigger the bit count, the higher resolution you can capture and the more accurately you can represent your original input. To make sure that measurements would be sufficiently accurate for my application I chose a 10-bit serial ADC.
This is an 8 channel, 10 bit resolution chip, meaning we can represent 210 , 1024 values. My compression load cell has an optimum weight range of 5-45kg. I’m looking at range of 40kg/1024= 0.039kg/bit, making it precise. Some of the other great features that make it compatible are the 2.7-5.5v single supply operation voltage and a great per second sampling rate. At 2.7v it will take 75 samples per second, and at 5.5 it will take a 200 samples a second. While somewhat slow in the world of ADCs, that’s more productive than I’ve ever been, and will be more than sufficient for what I need. I also has an optimum temperature range that works well for what I need, -40 to 85 degrees Celsius. Meaning Blighty stands comfortable somewhere near the middle of that and who knows, if this takes off I can sell it Russia and Australia and retire at the ripe old age of still in my 20s, just.
The MCP3008/Raspberry Pi circuit
Above is the breadboard layout of the circuit I created on Fritzing. The output from the amplifier I will be using to boost the compression cell signal will eventually replace the LDR and be converted into a digital value by the MCP3008, then read by the Raspberry Pi to be processed. The great part about this is that we can use the power from the Pi to power the circuit too, using the 3.3v pin 1. I looked into the General Purpose input/output pins (GPIO pins) in a previous post, so I knew that the type of information I would be sending into the Pi, required me to use certain Pins. This particular chip makes use of the SPI , Serial Peripheral Interface bus, so I needed to use the SPI pins, Pins 9-11 to make sure the information was received and processed correctly. Below you can see the finished circuit.
The Pie and Chip
It’s all well and good hooking the circuitry up to the Pi, but we need to tell it how to process what is happening through our coding. This particular chip makes use of the SPI , Serial Peripheral Interface bus, which means it will only require four pins and is fairly easily communicated with when using Python via the Spidev library. We will be telling the Pi to take a sample once a second, so we need a Time library too. So it is essential to make our first lines of code ‘import spidev’ and ‘import time’, which can be seen in the following screenshot. While I am using Python to program the Pi, there are many other programming languages that could be used that will have libraries with different names.
We then need to define our variables. We need a time delay between each measurement. I have chosen to make my time delay 1 second for the purposes of the test, in practice it’s not going to be necessary to weigh a patient that often so I’ll go with 10,800 seconds, which is 3 hours.
Next we need to let it know which ADC channel our input is on, in this case channel 0.
Next we need to create out SPI object, allowing us to get the weight values we need from the chip via the SPI bus on the Pi. The great thing about importing the spidiv library is that the Pi now knows all the pin information without us having to input it manually. Hallelujah!
Next we need to define the function to read the ADC converter. First off, checking the channels values. As I mentioned earlier, this is an 8 channel chip, the channels start at 0, so actually go from 0-7. The coding lets the Pi know that if it is getting reading from channels bigger than 0 or less than 7 to return -1, which is an error or a false value. If channel number 7, actually channel 8, the one we are using is specified, the function will initiate an SPI read of the transaction and hopefully the return us a value. In the main While loop we call the function to read the ADC and then sleep for the delay be defined earlier before measuring again.
The %d portion of the code means it will return a decimal value. We can then hook up our circuit and feed an analogue signal into the ADC and see the digital value returned to the Pi and printed out.
When we run the program and then adjusted the amount of light entering the LDR by waving a hand over it, the figure changes accordingly. I can now convert analogue to digital, and can start to adapt this to weigh someone.
My ultimate goal is to create a device that will save the NHS money through pressure sore prevention, make a patients stay in hospital more pleasant and make a nurses job easier. The next step is to set up an amplifier that will boost the signal from the compression cell I wrote about previously and use this as the input for my ADC, to give me read out of a patient’s weight. I can then combine that with the moisture sensor from an earlier post. The final device will not only set off a discrete LED on the Nurses station if a bed is wet without a patient having to embarrass them and avoid a long weight, but will also automatically weigh a patient, saving time for the nurses and unnecessary movement and discomfort for the patient. It will then document all this information so it can be reviewed and used to help further improvements. All I have to do now is combine everything. Easier said than done, but I’m excited to get started.