Shop OBEX P1 Docs P2 Docs Learn Events
Measuring pH with the BS2 and Arduino pH Circuit — Parallax Forums

Measuring pH with the BS2 and Arduino pH Circuit

Hi,
I am trying to find an inexpensive way to measure and monitor the pH of a nutrient solution. I tried one method a couple of years ago with the probe linked below and some other components, but I was unsuccessful. Recently browsing amazon, I came across the pH circuit linked below. Can someone please let me know if this circuit is compatible with the BS2. I own several BS2 controllers, but I do not have Arduino controllers, nor am I familiar with Arduino's coding so I would prefer to stick with the BS2 if possible.

pH Probe
amazon.com/American-Marine-PINPOINT-pH-Probe/dp/B001EHJO64/ref=pd_bxgy_147_img_2?ie=UTF8&refRID=1Q7DC1YH43JBTWGWK8QG

pH Circuit
atlas-scientific.com/product_pages/circuits/ezo_ph.html

Since the Arduino has already written the programming for the pH circuit (atlas-scientific.com/product_pages/circuits/ezo_ph.html), another possibility would be for me to by the Arduino controller and have it communicate with a BS2 controller. Would that be possible, it seems like I could do this through serial communication. What do you think> Any feedback would be greatly appreciated. Thanks!

Chris Claudet

Comments

  • You should be able to interface with the sensor directly with the BS2.

    Just send the sensor a "R" followed by a carriage return and the device will send the pH back.

    I've used these sorts of sensors myself. If you have trouble getting it to work post the code you're using and and we can take a look at it to see if we can spot any problems.
  • Looking through the demo code for that board I see that it can communicate via I2C. The stock BS2 doesn't have I2C commands built it, but you can bit-bang I2C with SHIFTOUT and SHIFTIN.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-12-06 22:30
    JonnyMac wrote: »
    it can communicate via I2C.

    It "can" communicate via I2C but don't you think asynchronous serial would be the easiest way to use the device with a BS2?

    I'd think a simple SEROUT followed by a SERIN would do the job.

    Edit: Fixed my butchered serial in/out command mistakes.

    Edit again: The "SERIN_SEROUT1.BS2" and "SERIN_SEROUT2.BS2" examples are good places to start.
  • tomcrawfordtomcrawford Posts: 1,129
    edited 2015-12-06 22:57
    This looks like a cool board and I think I have to have one. As an aside, I think what we have here is a case of confounding precision and accuracy...

    Full range pH reading from .001 to 14.000
    • Accurate pH readings down to the thousandths place (+/- 0.02)

    Edit: I hope this isn't going to be one of those cases where the BS-2 can't turn around fast enough to catch a SERIN that follows a SEROUT. May have to resort to I2C after all. EndEdit
  • I tried coming up with some demo code for the BS2 but I'm not sure of a good way to deal with the decimal point.

    I read the data in one character at a time in order to check for the decimal point. I doubt this is a good approach.

    The little PBASIC I learned is very rusty.

    Here's my untested attempt.
    ' pH_Example.bs2
    ' Program to read pH value from AtlasScientific pH sensor
    ' By Duane Degn
    ' December 6, 2015
    '
    ' Warning, this program has not been tested.
    ' For more information about this program see the following
    ' thread in the Parallax forum.
    ' http://forums.parallax.com/discussion/162978
    
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    PH_OUT             PIN 1   ' to pH RX pin
    PH_IN              PIN 0   ' to pH TX pin
    
    T9600              CON 84
    
    BAUD               CON T9600
    LOOP_DELAY         CON 2000
    
    decimalFlag        VAR       Bit
    doneFlag           VAR       Bit
    inputCharacter     VAR       Byte
    multiplier         VAR       Word
    value              VAR       Word
    
    
    Main:
      DO
        value = 0
        multiplier = 0
        decimalFlag = 0
        doneFlag = 0
        DEBUG "Reading From pH Meter", CR
        SEROUT PH_OUT, BAUD, ["R", CR]  ' send the command to read pH
        GOSUB DataIn
        GOSUB DisplayData
        PAUSE LOOP_DELAY
      LOOP
    
    DataIn:
    CharIn:
      SERIN PH_IN, BAUD, [inputCharacter]         ' receive one byte
      SELECT inputCharacter
        CASE "0" TO "9"
          value = (value * 10) + (inputCharacter - "0")
          IF decimalFlag = 1 THEN multiplier = multiplier * 10
        CASE "."
          decimalFlag = 1
        CASE CR
          doneFlag = 1
        ENDSELECT
      IF doneFlag = 0 THEN Charin
      RETURN
    
    DisplayData:
      DEBUG "pH = ", SDEC ? value / multiplier, ".", value // multiplier, CR
      RETURN
    
      END
    

    The variable "value" should contain the pH multiplied by the value of "multiplier". Hopefully this will allow the pH level to be compared in a meaningful way.

    There's got to be a better way to do this. Hopefully someone with more PBASIC knowledge will improve the code.
  • Duane,

    Read it all into a byte array then parse the result afterwards.
      result VAR byte(#)
      SERIN PH_IN, BAUD, [STR result\#] 
    

    where # is the number of bytes expected. If this is variable, then use the largest value and set a timeout. If the result is terminated with a CR, then you could stop at that too (add \CR after \#)
  • Sapphire wrote: »
    Read it all into a byte array then parse the result afterwards.

    Thanks. I didn't know how to do this in PBASIC.

  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-12-07 03:36
    I made the mistake of initializing "multiplier" to zero instead of one.

    I made the change suggested by Sapphire.

    Here's the latest version. It's still untested.
    ' pH_ExampleB.bs2
    ' Program to read pH value from AtlasScientific pH sensor
    ' By Duane Degn
    ' December 6, 2015
    '
    ' Warning, this program has not been tested.
    ' For more information about this program see the following
    ' thread in the Parallax forum.
    ' http://forums.parallax.com/discussion/162978
    
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    PH_OUT             PIN 1   ' to pH RX pin
    PH_IN              PIN 0   ' to pH TX pin
    
    T9600              CON 84
    
    BAUD               CON T9600
    LOOP_DELAY         CON 2000
    MAX_CHARACTERS     CON 20
    
    decimalFlag        VAR       Bit
    doneFlag           VAR       Bit
    index              VAR       Byte
    result             VAR       Byte(MAX_CHARACTERS)
    multiplier         VAR       Word
    value              VAR       Word
    
    
    Main:
      DO
        value = 0
        multiplier = 1
        decimalFlag = 0
        doneFlag = 0
        index = 0
        DEBUG "Reading From pH Meter", CR
        SEROUT PH_OUT, BAUD, ["R", CR]  ' send the command to read pH
        SERIN PH_IN, BAUD, [STR result\MAX_CHARACTERS]
        GOSUB ParseData
        GOSUB DisplayData
        PAUSE LOOP_DELAY
      LOOP
    
    ParseData:
    CharIn:
      SELECT result(index)
        CASE "0" TO "9"
          value = (value * 10) + (result(index) - "0")
          IF decimalFlag = 1 THEN multiplier = multiplier * 10
        CASE "."
          decimalFlag = 1
        CASE CR
          doneFlag = 1
        ENDSELECT
      index = index + 1
      IF index = MAX_CHARACTERS THEN GOSUB ReportError
      IF doneFlag = 0 THEN Charin
      RETURN
    
    ReportError:
      DEBUG "Error. No carriage return in receved message.", CR
      doneFlag = 1
      RETURN
    
    DisplayData:
      DEBUG "pH = ", SDEC ? value / multiplier, ".", value // multiplier, CR
      RETURN
    
      END
    

    Hopefully Tom's fear about the timing isn't warranted.
  • Sapphire wrote: »
    Duane,

    Read it all into a byte array then parse the result afterwards.
      result VAR byte(#)
      SERIN PH_IN, BAUD, [STR result\#] 
    

    where # is the number of bytes expected. If this is variable, then use the largest value and set a timeout. If the result is terminated with a CR, then you could stop at that too (add \CR after \#)

    This, in fact, is the only sensible idea using the BS2 and serial with this device. Nice suggestion, Sapphire.

  • I hope this isn't going to be one of those cases where the BS-2 can't turn around fast enough to catch a SERIN that follows a SEROUT.

    I just thought of a possible way around this problem, if it turns out to be a problem. The sensor can be set to continuously output data. With a continuous stream of data, the BS2 shouldn't have a problem reading the sensor.
  • I received this module yesterday (and the probe a few days ago). It turns out the BS-2 cannot turn around fast enough at 9600 baud.

    Here is a little program that just receives data from the module in continuous mode, as suggested by Duane in the previous comment. The module comes up in continuous mode, so you don't need to program it all if you are happy with the factory settings.

    The Str2Bin bit converts the floating point string into "millipH" so you could easily compare to some limit and, say, set an alarm if the tested fluid becomes too acid or alkaline.

    This program does not allow one to query the device as to its name or device info. I plan to address that by:

    1. Try a lower baud rate
    2. If that doesn't work, go to a BS-2p so I can use I2C.
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    Baud   CON   84         '9600 baud rate
    TXPin  PIN   0          'goes out of
    RXPin  PIN   1          'comes in to
    
    serStr VAR   Byte(10)   'serial string
    i      VAR   Byte       'pointer into serStr
    pH     VAR   Word       'ph times 1000
    
    begin:                        'start here
    HIGH TXPin                    'normally high
    PAUSE 100
    
    top:
      SERIN RXPin, Baud, 3000, NoString, [STR serStr \10 \CR]  'wait up to 3 seconds
      GOSUB Str2Bin              'convert to 'millipH
      GOSUB Display              'put it on the debug screen
      GOTO top
    
    Str2Bin:       'convert serStr to thousanths
      pH = 0       'initialize value
      i = 0        'start at beginning of string
      DO WHILE (serStr(i) <> CR) AND (serStr(i) <> 0)    'work up to (terminator)
        IF serStr(i) <> "." THEN  'skip over decimal point
           pH = (ph * 10) + (serStr(i) - "0")  '"shift and add"
           ENDIF
        i = i + 1                 'on to next character
        LOOP                      'until we get to CR
      RETURN
    
    Display:                               'show the string all three ways
      DEBUG "String is: ", STR serStr, CR
      DEBUG "millipH is: ", DEC5 pH, CR
      DEBUG "pH is: ", DEC pH/1000, ".", DEC3 pH//1000, CR, CR
      RETURN
    
    NoString:               'come here it didn't get a string within 3 seconds
      DEBUG "No input received from module.", CR
      GOTO begin
    


  • Nuts and Volts #85 and #115 have the bit-banged I2C routines that Jon (JonnyMac) is talking about.
    Several of the Microcontroller KickStarts on Learn use these routines.
    http://learn.parallax.com/KickStart/29133
    http://learn.parallax.com/KickStart/27911

    I2C does have the advantage that the BS2 is in control of when and how quickly data is received.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-12-18 03:27
    pH electrodes are often considered consumable items. They wear out like batteries. You can get refillable versions which seem to last longer. I've only had one refillable version and I've gone through dozens of the normal probes. I stopped needing to test pH levels not long after I purchased a refillable probe so my only purchasing a single refillable probe doesn't mean it has lasted particularly long time.

    In chemistry one usually wants to use distilled water when water is used so it's a relatively common mistake for people to use distilled water as a soaking solution. Soaking a pH electrode in distilled water is very bad for it. Tap water isn't as bad as distilled water but a probe will last much longer if you use a proper soaking solution.

    Calibrating a pH meter is very important if you want accurate readings. I don't think this sensor will let you calibrate the device at many pH levels but you really should calibrate a meter with buffers both higher in pH and lower in pH than the sample being measured.

    pH extremes are bad for probes. If you need to measure a sample with either a really high or really low pH, try to minimize the time the probe is exposed to the sample. You'll likely need to recalibrate the meter after measuring a sample with an extreme pH. It's a good idea to calibrate the meter each day it will be used.
  • Duane Degn wrote: »

    Calibrating a pH meter is very important if you want accurate readings. I don't think this sensor will let you calibrate the device at many pH levels but you really should calibrate a meter with buffers both higher in pH and lower in pH than the sample being measured.

    This sensor lets you do 1-, 2-, or 3-point calibration.

    Turns out that probes are a whole lot more complicated to use than I would ever have thought. The particular probe referenced in the original posting has a lot of bad reviews on Amazon. People complained that the soaking solution dried out (which happened with the one I got). I have subsequently purchased another from atlas-scientific.


  • Here is a pretty comprehensive program to interface the Atlas Scientific EZO pH circuit to a stock BS-2. It allows continuous monitoring, arbitrary strings, and a 1-, 2-, or 3-point calibration. It runs at 300 baud.

Sign In or Register to comment.