Simulate The Output of a pH Probe

I am currently working on a project where I need to simulate a pH probe's output voltage. For those that don't know, a pH probe uses pH-sensitive materials and fluids to output a voltage. The output voltage varies based on the hydrogen concentration of the solution the probe is measuring. The probe is hooked up to a pH meter, which is in essence just a multimeter, and the small voltage value is then converted into a pH value. A basic breakdown of this conversion is as follows:

``````            pH Value |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  10  |  11  |
Probe output (in mV) | 237 | 177 | 118 |  59 |  0  | -59 | -118| -177 | -237 |
``````

To sum up very briefly, values below 7 pH cause the probe to output a positive voltage. Values above 7 pH cause the probe to output a negative voltage. Values of 7 pH exactly cause the probe to output no voltage.

Basically, I need my Raspberry Pi to be able to output voltages in this range. The goal is that the RPi can then be hooked up to any standard pH meter via BNC. The Pi would then output a voltage similar to the ones described above, and the pH meter would believe a real pH probe was attached, and display the pH that corresponds with the voltage the Pi is generating.

I am rather new to "making" and electronics in general. I have done some research and it appears that I will need a DAC to convert the Pi's digital output to an analog voltage. What complicates things is that I would need to output a negative voltage for values above 7 pH. Since the scale appears to be linear, I may be able to simply output the proper mV, then flip the voltage if the values are over 7 pH. I don't know how easy or feasible this is, however.

As I mentioned, I really am sort of lost at where to start. If anyone could give me some advice as to where to begin reading, or some chips/tutorials that may be useful to learn how to accomplish my goal, I would be grateful. Thank you!

• Which programming language are you using? Commented Aug 11, 2017 at 20:47
• @stevieb I'd prefer Python, but I'm open to whatever language will help me get this working. Thanks
– user31713
Commented Aug 11, 2017 at 20:53
• Ok, so I did some testing with an ADS1115 and figured out the voltage to pH reading just fine (using PWM), but it is beyond my expertise to output the negative voltages out of the Pi in any way. None of my DACs or digipots are capable of this, but I have a couple of types of op-amps that I'm going to throw into the mix to see if I can get the desired effect. Normally I don't spend so much time on something like this, but I am genuinely curious :) Commented Aug 11, 2017 at 22:40

Assuming that your pH meter does not have a common ground with your RPI, you can connect the "GND" input to the pH meter to a 3.3V/2 resistor divider from the PI 3.3V supply and use a PI PWM output with an RC low pass filter to generate a programmable voltage without any DAC. Tie the RC low passed PWM output to the non-GND pH input and as the PWM value is set above and below 50%, the voltage into the pH meter will vary above and below zero, relative to 3.3V/2. If you want finer voltage control, you can use pull up/down resistors on the capacitor of the RC filter so that the resistor from the PI PWM output can only drive the output to some fraction of the 0-3.3V range as the PWM varies from 0% to 100%. The ratio of the RC resistor to the pull up/down resistors determines the range reduction.

As for generating the PWM outputs, you can use the pigpio library to easily generate PWM signals on any PI output.

All of this assumes that the rate of change on the pH voltages is relatively small, since it will be limited by the RC low pass filter time constant. In general, after a large change, the voltage through an RC settles to the final value within about 10*RC seconds. The PWM period should also be much shorter than the RC time constant, say ~1000 times, in order to filter out the PWM frequency.

See http://www.ti.com/lit/an/spraa88a/spraa88a.pdf for a detailed PWM DAC application note from Texas Instruments.

LTSpice Schematic: Output with 8KHz PWM swept from 20uS on to 110uS on, plotting PWM relative to VCC/2

• Thank you, I will take a look at this approach. To answer your other question, no, the pH meter will be a stand-alone device. It will not share any wiring with the Pi, aside from a BNC connector going from the Pi to the meter that transmits the voltage discussed in the original post.
– user31713
Commented Aug 12, 2017 at 13:42
• Additionally, the rate of change needn't be very fast. The Pi will need to output a new value every 1 to 5 minutes. Any new values generated by the Pi are likely to be very, very close to the previous value, +/- a few mV.
– user31713
Commented Aug 12, 2017 at 13:43
• I'm looking at a low pass filter and this appears to be what I need. Could you please supply some more info on how I would wire this? I can find plenty of resources on using PWM with a low pass filter to generate specific voltage, but I am unable to find any info about doing this with the divider you mention and getting +/- outputs. Thanks again.
– user31713
Commented Aug 12, 2017 at 16:29
• I added a schematic and simulation. The RC time constants give about a 5 second settling time and less than 1mv of feedthrough on the PWM ripple. The capacitor on the VCC_DIV2 divider also low passes the noise from the 3.3V supply in order to minimize noise. You can adjust the range by changing the value of R1. Commented Aug 12, 2017 at 18:02
• Thank you very much for the advice and the schematic. I did some reading and I think I understand how everything works. I'll order some parts and get to building. Can't thank you enough!
– user31713
Commented Aug 12, 2017 at 19:27

Supplementary Schematic with Source

This is an alternative version of @crj11's answer (but it's his answer) all I did is some rearrangement, parametrisation and including the source.

``````Version 4
SHEET 1 1000 680
WIRE 224 32 48 32
WIRE 448 32 224 32
WIRE 224 48 224 32
WIRE 448 48 448 32
WIRE 96 160 64 160
WIRE 224 160 224 128
WIRE 224 160 176 160
WIRE 224 176 224 160
WIRE 288 176 224 176
WIRE 352 176 288 176
WIRE 448 176 448 128
WIRE 512 176 448 176
WIRE 576 176 512 176
WIRE 224 192 224 176
WIRE 352 192 352 176
WIRE 448 192 448 176
WIRE 576 192 576 176
WIRE 224 288 224 272
WIRE 352 288 352 256
WIRE 352 288 224 288
WIRE 400 288 352 288
WIRE 448 288 448 272
WIRE 448 288 400 288
WIRE 576 288 576 256
WIRE 576 288 448 288
WIRE 400 320 400 288
WIRE 352 432 336 432
WIRE 480 432 464 432
WIRE 336 448 336 432
WIRE 464 448 464 432
WIRE 336 544 336 528
WIRE 464 544 464 528
FLAG 336 544 0
FLAG 464 544 0
FLAG 352 432 3V3
IOPIN 352 432 Out
FLAG 480 432 PWM
IOPIN 480 432 Out
FLAG 48 32 3V3
IOPIN 48 32 In
FLAG 400 320 0
FLAG 64 160 PWM
IOPIN 64 160 In
FLAG 288 176 DIV_PWM
FLAG 512 176 DIV_DC
SYMBOL res 208 32 R0
SYMATTR InstName R1
SYMATTR Value {R}
SYMBOL res 208 176 R0
SYMATTR InstName R2
SYMATTR Value {R}
SYMBOL cap 336 192 R0
SYMATTR InstName C1
SYMATTR Value 10�
SYMBOL res 432 32 R0
SYMATTR InstName R3
SYMATTR Value {R}
SYMBOL res 432 176 R0
SYMATTR InstName R4
SYMATTR Value {R}
SYMBOL cap 560 192 R0
SYMATTR InstName C2
SYMATTR Value 10�
SYMBOL res 192 144 R90
WINDOW 0 5 56 VBottom 2
WINDOW 3 27 56 VTop 2
SYMATTR InstName R5
SYMATTR Value {R_PWM}
SYMBOL voltage 336 432 R0
WINDOW 0 -63 47 Left 2
WINDOW 3 -68 67 Left 2
WINDOW 123 0 0 Left 0
WINDOW 39 -100 85 Left 2
SYMATTR InstName V1
SYMATTR Value 3.3
SYMATTR SpiceLine Rser=1
SYMBOL voltage 464 432 M0
WINDOW 0 -59 47 Left 2
WINDOW 123 0 0 Left 0
WINDOW 39 -98 88 Left 2
WINDOW 3 -279 68 Left 1
SYMATTR InstName V2
SYMATTR SpiceLine Rser=1
SYMATTR Value PULSE(0 3.3 0 1u 1u {on_time} 125u 1e6)
TEXT 640 104 Left 2 !.step param on_time list 10u 61.5u 113u
TEXT 640 216 Left 2 !.tran 5
TEXT 640 192 Left 2 !.option nomarch
TEXT 640 152 Left 2 !.param R 100k
TEXT 640 128 Left 2 !.param R_PWM 200k
``````