SOLVED: DF Robot: PH Probe SEN0161 Publishing Issues

I’ve searched high an wide for an answer to this with no luck. I have this DF Robot Probe and I’m trying to get it to publish the PH reading but not having any luck, worked on it for 2 days now.

Here is the code that is straight from the manufacturer:

    /*
    # This sample codes is for testing the pH meter V1.0.
    # Editor : YouYou
    # Date   : 2013.10.12
    # Ver    : 0.1
    # Product: pH meter
    # SKU    : SEN0161
    */

    #define SensorPin A0          //pH meter Analog output to Arduino Analog Input 0
    unsigned long int avgValue;  //Store the average value of the sensor feedback
    float b;
    int buf[10],temp;

    void setup()
    {   
    }
    void loop()
    {
    for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
    { 
    buf[i]=analogRead(SensorPin);
    delay(10);
    }
    for(int i=0;i<9;i++)        //sort the analog from small to large
    {
    for(int j=i+1;j<10;j++)
    {
    if(buf[i]>buf[j])
    {
    temp=buf[i];
    buf[i]=buf[j];
    buf[j]=temp;
    }
    }
    }
    avgValue=0;
    for(int i=2;i<8;i++)                      //take the average value of 6 center sample
    avgValue+=buf[i];
    float phValue=(float)avgValue*5.0/1024/6; //convert the analog into millivolt
    phValue=3.5*phValue;                      //convert the millivolt into pH value
    Serial.print(phValue,2);
    }

Here’s the code that I’m trying to get to work on the Photon, the issue is with the float in the Particle.publish (the last line):

    /*
    # This sample codes is for testing the pH meter V1.0.
     # Editor : YouYou
     # Date   : 2013.10.12
     # Ver    : 0.1
     # Product: pH meter
     # SKU    : SEN0161
    */

    #define SensorPin A0          //pH meter Analog output to Arduino Analog Input 0
    unsigned long int avgValue;  //Store the average value of the sensor feedback
    float b;
    int buf[10],temp;

    void setup()
    {
      
    }
    void loop()
    {
      for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
      { 
        buf[i]=analogRead(SensorPin);
        delay(10);
      }
      for(int i=0;i<9;i++)        //sort the analog from small to large
      {
        for(int j=i+1;j<10;j++)
        {
          if(buf[i]>buf[j])
          {
            temp=buf[i];
            buf[i]=buf[j];
            buf[j]=temp;
          }
        }
      }
      avgValue=0;
      for(int i=2;i<8;i++)                      //take the average value of 6 center sample
        avgValue+=buf[i];
      float phValue=(float)avgValue*5.0/1024/6; //convert the analog into millivolt
      phValue=3.5*phValue;                      //convert the millivolt into pH value
      Particle.publish(phValue,2);
    }

I’ve checked the manufacturer page and they don’t have a fix for the issue and was wondering if anyone can point out the issue for me, very frustrating…

Many thanks!!

Peace,
EJ

Did that search include the Particle docs, because you're not using Particle.publish correctly. The first argument should be a String or const char* that is the name of the event you want to publish, and the second argument is the data you want to send, also a String or a const char*. See the docs here for the various versions of that function.

Be aware, that to see the result of that publication, you need to subscribe to it on another device, or through an app or the CLI. You can also see the result on the Particle console (without subscribing).

1 Like

Hi Ric,

This works fine in Arduino and produces the PH reading:

Serial.print(phValue,2);

Read the docs? Yeah, cos I didn’t try that…

Thanks for the non-answer…

Did you look at the reference that I provided? That provides the answer. You're trying to use the Particle publish like it's a Serial print, which it is not.

If all you want to do is print to a serial monitor, then Serial.print() works on the Photon the same way it does on an Arduino.

1 Like

Ric,

If you look at the first bit of code that I posted, it’s directly from the manufacturer of the probe. There is no other resource on the internet that shows you how to get the probe working with the Photon, not even on the manufacturers website. I’d rather not chock this up to ‘More stuff that doesn’t work on the Photon’ but rather work through the issue.

You can see what I’m trying to do if you look at both bits of code, trying to publish a 2 digit number, 3 if you count the decimal. A great way to help would be to maybe provide a better way? Because as I mentioned earlier, the manufacturer has no explanation either.

Peace,
EJ

I'm not sure what you're trying to do, publish or print? I can't tell if you're using the word "publish" in its generic english usage sense, or as in "Particle.publish", which, after all, is what you show in your second bit of code. If you're just translating directly from the Arduino to a Particle device, then you can just use Serial.print() on the Photon. If you actually want to publish (as in a Particle.publish), then the reference I provided shows how to do that instead.

2 Likes

If you are trying to use Particle.publish, the following will work:

Particle.publish("phValue", String(phValue, 2));

However, with you current loop(), you would be calling Particle.publish too frequently, so I would advise using a delay, a timer, or a flag to achieve this.

@Learjet, just to step in as a mod @Ric has in fact contributed valuable input on your question from the first post on.
His points were valid all along, even if you didn't see it that way.

If you want to use the Arduino code you can leave it as is with Serial.print() but you opted to change that for Particle.publish() which is a completely different function and hence has to be used accordingky.

So instead of refusing the help like

A genuine "Thank you, but what do you mean?" would have been more appropriate.

And now to a point that wasn't addressed yet:
The ADC on Particle devices has a 12bit resolution at 3.3V, so this calculation has to be changed from

float phValue=(float)avgValue*5.0/1024/6; 

to

float phValue=(float)avgValue*3.3/4095/6; 

And you need to make sure that the output of the sensor maps into this 0..3.3V window via external circuitry.

And about Particle.publish() there is a documented rate limit of 1/sec which your code is violating and hence getting muted by the cloud.

Usually we would post a link to the docs for such cases, but due to your own statement

We may leave you to it

2 Likes

You know what? You're right...

Ric, I sincerely apologize and I'm sorry for my earlier post. I was having a terrible day and regardless what the situation was, it was wrong.

Have a wonderful day and again, I'm very sorry :slight_smile:

Peace,
EJ

5 Likes

To all who come afterwards :slight_smile:

Here’s the completed code, works on the Photon wonderfully:

/*
# Product: Analog pH Meter Kit / DF Robot
# SKU    : SEN0161
# Code revised by EJ Lear http://www.eaeroponics.com 
# NOTE: This code is for the DF Robot SEN0161 on the Photon, it updates to the console log every 10 Seconds as is, which 
# is great for calibration.  If you want to use this in production (aeroponics/hydroponics) I would reccomend testing with a minimum of 30 minutes between tests so you don't burn out the probe too quickly.
# CALIBRATION VIDEO: Mike Ratcliffe put together a great calibration video for both the SEN0161 and the larger, higher quality DFRobot Analog pH Meter Pro here: https://www.youtube.com/watch?v=BgHR5MutKHY
*/
#define SensorPin A0          //pH meter Analog output to Photon Analog Input A0
unsigned long int avgValue;  //Store the average value of the sensor feedback
float b;
int buf[10],temp;
void setup()
{  
}
void loop()
{
  for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
  { 
    buf[i]=analogRead(SensorPin);
    delay(10);
  }
  for(int i=0;i<9;i++)        //sort the analog from small to large
  {
    for(int j=i+1;j<10;j++)
    {
      if(buf[i]>buf[j])
      {
        temp=buf[i];
        buf[i]=buf[j];
        buf[j]=temp;
      }
    }
  }
  avgValue=0;
  for(int i=2;i<8;i++)      //take the average value of 6 center sample
    avgValue+=buf[i];
  //float phValue=(float)avgValue*5.0/4095/6; // This code is for the Arduino only to use it, uncomment this line, and comment out the next one!
  float phValue=(float)avgValue*3.3/4095/6; // Works on Photon! (convert the analog into millivolt) You can tweak the middle (the 2890)number to get your measurements exact if you are calibrating with buffer solutions
  //ADDITIONAL NOTE: I used these settings and then adjusted the rheostat on the circuit board to get the calibration perfect.
  phValue=5.28*phValue;                      //convert the millivolt into pH value
  Particle.publish("phValue", String(phValue, 2));
  delay (10000); // Make sure you don't overload the console!  Keep above 2000 (2 seconds), also keep in mind that you have to let the probe sit for 2 minutes in the buffer solution anyway to get a correct reading.
}
/*
  Special thanks to:
  Rik Delmar who took a lot of sh!@ unnecessarily, my fault. :-( https://community.particle.io/u/ric/summary. 
  Nathan Robinson who got the publishing working! Thanks Nathan https://community.particle.io/u/nrobinson2000/summary
  Scruff for calling out on my crap :-) and helping with the 3.3v conversion! https://community.particle.io/u/scruffr/summary
*/    
// Much love :-)

** Edited code to reflect ScruffR’s point below **

Please keep in mind that you may have to adjust the rheostat on the circuit board to get your probe calibrated exactly.

Have fun!

Peace,
EJ

5 Likes

Yeah, we all have those, unfortunately. Apology gladly accepted.

3 Likes

Glad you got your project working :+1:

Just one note for clarity:
I'd stick with the 4095 constant (instead of 2890) as this is a hardware specific constant and can easily be recognized and accounted for as it reflects the 12bit (2^12) resolution of the ADC.
So I'd rather change the 6 or the 3.5 values to get the correct result as these are "arbitrary" values.

And as a word of caution, double check that the sensor really never will feed more than 3.3V to the pin, otherwise you may say goodbye to your ADC :wink:

See this FAQ which also applies to Particle devices

The easiest would be a voltage divider that translates the 0..5V to 0..3.3V

1 Like

Thanks again Scruff, I calibrated my unit and made the appropriate changes to the code above, it's a good ballpark figure but requires a bit of tweaking on the rheostat.

Peace,
EJ

1 Like

I’ve shorted the probes BNC connection to simulate PH neutral. I’ve adjusted the board to read 2.5v on my multimeter which should give me a PH 7.0. All is well there.
Using the following, I get the voltage expected

int sensorValue = analogRead(A0);
 // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
 float voltage = sensorValue * (3.3 / 4095.0);

Your code outputs a PH of 2.17 - see below

 float phValue2=(float)sensorValue*3.3/4095/6; // Works on Photon! (convert the analog into millivolt) 
 phValue2=5.28*phValue2;    

When I use the following code I get 7.0

phValue = (sensorValue*-0.00443349753695 + 20.5438423645);

I’m not sure why your code seems to work for you. Anyone have any ideas? I’m using the photon and I am doing a sampling average. what is the difference in the Math? I’ve even used ph calibration solution for both 7.0 and 4.0 and the results are consistent. I’m not comfortable with phValue = (sensorValue*-0.00443349753695 + 20.5438423645); even though it works.

That’s better.

// PH_step = (voltage@PH7 - voltage@PH4) / (PH7 - PH4)
// PH_probe = PH7 - ((voltage@PH7 - voltage@probe) / PH_step)
pHValue = 7.00 + ((2.5 - voltage) / 0.19);