Measuring Solution PH Relative to Solution Temp.

Hi guys,
this is my first message in here :]

I'm working on aquarium project and there for i need to measure the PH level of the solution and i would like your helps with the code debugging.

(I didn't tried this yet cause I didn't got the products yet)

I decided to use the phidget 1130 - pH/ORP Adapter
Product Link:

Product Manual

and regular PH prob - Analytical grade chemicals, lab materials PH Probe, USA
Product Link:
http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=290513215434

and regular LM35 Temperature Sensor (Because the PH level is relative to the solution temperature)

const int LM35 = A0
const int PHprobe = A1;
void setup()
{
 Serial.begin(9600);
}
void loop()
{
int WaterTemp = 0;
int WaterPH = 0;
WaterTemp = TankTemperature();
WaterPH = TankPHLevel(WaterTemp);
Serial.println(WaterPH, DEC);
}[ch8195]
int TankTempetraure()
{
   float TankTemp = 0;
   float tempc = 0; // temperature variables
    float samples[8]; // variables to make a better precision
    float maxi = -100,mini = 100; // to start max/min temperature
    int i;
    for(i = 0;i< =7;i++) // gets 8 samples of temperature 
    {
        samples[i] = ( 5.0 * analogRead(LM35) * 100.0) / 1024.0;
        tempc = tempc + samples[i];
        delay(300);
    }
    CurrentTankTemp  = tempc/8.0; // better precision
    if(CurrentTankTemp > maxi) {maxi = CurrentTankTemp;} 
    if(CurrentTankTemp < mini) {mini = CurrentTankTemp;} 
    return CurrentTankTemp;   
}
[ch8195]
int TankPHLevel(float temp)
{
    float CurrentTankPH = 0;
    float PH = 0; // PH variables
    float samples[8]; // variables to make a better precision
    float maxi = -100,mini = 100; // to start max/min PH
    int i;

    for(i = 0;i< =7;i++) // gets 8 samples of PH
    {
        samples[i] = 7 - (2.5 - analogRead(PHprobe)/200) / (0.257179 + 0.000941468 * temp);
        PH = PH + samples[i];
        delay(1000);
    }
    CurrentPH  = PH/8.0; // better precision
    if(CurrentPH > maxi) {maxi = CurrentPH;} 
    if(CurrentPH < mini) {mini = CurrentPH;}
    return CurrentkPH;    
}

I want to highlight this line from the code:
samples = 7 - (2.5 - analogRead(PHprobe)/200) / (0.257179 + 0.000941468 * temp);
PH = PH + samples*;*
CurrentPH = PH = PH/8.0;
[/glow]
This is the function that consulate the PH level in the solution is it correct? or should i add somewhere the "/1024" ?
Thanks a lot for the helpers :slight_smile:

maxi and mini are local variables, in the TankTempetraure() function. They go out of scope at the end of the function. What purpose does it do to value them?

CurrentTankTemp is a global variable, apparently, although the code you posted is incomplete, so it is impossible to determine this for sure. If CurrentTankTemp is to be returned by TankTempetraure(), it doesn't need to be global. Or, if it needs to be global for some other reason, then TankTempetraure() doesn't need to return a value.

The samples collected in TankTempetraure() are stored in an array, and accumulated in tempc. What purpose does the array serve?

TankTempetraure() works with floats, but returns an int. TankPHLevel expects a float.

Which is correct?

        samples[i] = 7 - (2.5 - analogRead(PHprobe)/200) / (0.257179 + 0.000941468 * temp);

Lots of magic numbers here. What do they mean?

Again, why is the data stored in an array? The array is never accessed again.
Same questions about maxi and mini, too.

I decided to use the phidget 1130 - pH/ORP Adapter
and regular PH prob - Analytical grade chemicals, lab materials PH Probe, USA

Links to e-bay auctions are generally useless. Too often they contain no useful information. A link to a data sheet would be more useful.

Did you see this note in the phidget 1130 product manual?

Measuring pH in electrically noisy environments such as tanks with mixing pumps, and even other measuring devices, is not recommended.

Presumably your aquarium has a pump.

This is the function that consulate the PH level in the solution is it correct?

With all those magic numbers in it? Who can tell.

Where did you get the formula? What do the magic numbers mean?

Ok first of all thanks for helping,

about the global variables and so, i think this verse of the code will be more correct.

const int LM35 = A0
const int PHprobe = A1;

void setup() { Serial.begin(9600); }

void loop() 
{
      float x = TankTemperature;
      Serial.println(TankPHLevel(x), DEC);
}
[ch8195]
int TankTemperature()
{
      float tempc = 0; // temperature variables
      float samples[8]; // variables to make a better precision
      int i;

      for(i = 0;i< =7;i++) // gets 8 samples of temperature
      {
            samples[i] = ( 5.0 * analogRead(LM35) * 100.0) / 1024.0;
            tempc = tempc + samples[i];
            delay(300);
          }

    tempc = tempc/8.0; // average of the 8samples for better precision
    return tempc;  
}
[ch8195]
int TankPHLevel(float temp)
{
      float PHLevel = 0; // PH variables
      float samples[8]; // variables to make a better precision
      int i;

      for(i = 0;i< =7;i++) // gets 8 samples of PH
      {
            samples[i] = 7 - (2.5 - analogRead(PHprobe)/200) / (0.257179 + 0.000941468 * temp);
            PH = PH + samples[i];
            delay(1000);
      }
      PHLevel  = PH/8.0; // average of the 8samples for better precision
          return PHLevel;    
}

About the Magic Numbers in the formulas :smiley:
Well to tell you the true I'm pretty new with this Arduino and it's interface.
I used this post

to get a start with the temperature code,

samples[i] = ( 5.0 * analogRead(LM35) * 100.0) / 1024.0;

but the meaning of the number is in the replies of the post..:

The Analog to Digital Converter (ADC) compares a sample voltage to the supply voltage and provides a digital number based on 1024 steps. The formula (Sample Voltage * 1024 / Supply voltage) shows that 2.5volts * 1024 / 5volts would result in a digital number of 512 which is what we would expect for a voltage half the supply voltage.

To get the find the sample voltage from a digital number the formula is reversed (Digital number * supply voltage / 1024). So our count of 512 would give (512 * 5volts / 1024) and tell us that there is 2.5volts on the sample pin.

However, that doesn't explain the 100 in his formula. That is there because the LM35 supplies 10 millivolts per degrees Celsius. So, let's look at an example. The room temperature is 19 Celsius which means the LM35 supplies 190 millivolts, or .190volts. Putting that number into the first formula (.19volts * 1024 / 5volts) means we would expect to see a digital number of 39 on the analog pin. So let's say we do get a reading of 39, what does the program do with it?

The formula in the program says ( 5volts * 39 * 100 / 1024) which equals 19 meaning 19 Celsius. As I said in my program, a close approximation of the temperature in Celsius can be found by dividing the input number by 2. Daniel's program divides the number by 2.048 (5 * 100 / 1024) which is a little more accurate but because both programs are using integer values, the result is roughly the same. Use which ever formula you will be able to understand when reading your program six months from now. (grin)

and i used the temperature code + the phidget 1130 - pH/ORP Adapter data sheet: 1130 User Guide - Phidgets Support

Technical Information
Measuring the pH
To determine the pH of a solution, make sure the DIP switch on the board is flipped to the pH side. Given the
SensorValue from the Phidget InterfaceKit, the following formula can be applied:
pH = 0.0178 * SensorValue - 1.889
This formula assumes that the solution is at 25 degrees Celsius. Depending on the temperature of the solution and
on the actual pH level, the SensorValue can change dramatically. To incorporate temperature (in degrees Celsius) for
added accuracy, the following formula can be used:
pH = 7 - (2.5 - SensorValue / 200) / (0.257179 + 0.000941468 * Temperature)
The following example is to give an idea of how the temperature affects the SensorValue. A solution with a pH
of 2 at a temperature of 25 degrees Celsius yields a SensorValue of 219. At 100 degrees Celsius, the SensorValue
decreases to 148, and at 0 degrees celsius, the SensorValue reports 242. A solution with a pH of 8 with a
temperature of 0, 25 and 100 degrees Celsius gives a SensorValue of 551, 556 and 570, respectively. It can be
seen that the temperature has a greater affect on solutions that have a pH further away from the reference pH of
7. Additionally, temperature affects the impedance of the glass electrode, and can result in increased errors if not
properly calibrated.

to create the PH code..

Lets start at the top of the code.

[glow]int[/glow] TankTemperature()
{
      [glow]float tempc[/glow] = 0; // temperature variables
      float samples[8]; // variables to make a better precision
      int i;

      for(i = 0;i< =7;i++) // gets 8 samples of temperature
      {
            samples[i] = ( 5.0 * analogRead(LM35) * 100.0) / 1024.0;
            tempc = tempc + samples[i];
            delay(300);
          }

    tempc = tempc/8.0; // average of the 8samples for better precision
    return [glow]tempc[/glow];
}

The type of value returned by a function MUST match the type that the function is defined to return. Otherwise, nasty things happen.

There is still no reason to store the 8 values in an array.

When you right, you right.

const int LM35 = A0
const int PHprobe = A1;

void setup() { Serial.begin(9600); }

void loop() 
{
      float x = TankTemperature();
      Serial.println(TankPHLevel(x), DEC);
}
?
float TankTemperature()
{
      float tempc = 0; // temperature variables
      int i;

      for(i = 0;i< =7;i++) // gets 8 samples of temperature
      {
            tempc += ( 5.0 * analogRead(LM35) * 100.0) / 1024.0;
            delay(300);
          }

    tempc = tempc/8.0; // average of the 8samples for better precision
    return tempc;  
}
?
float TankPHLevel(float temp)
{
      float PHLevel = 0; // PH variables
      int i;

      for(i = 0;i< =7;i++) // gets 8 samples of PH
      {
            PHLevel += 7 - (2.5 - analogRead(PHprobe)/200) / (0.257179 + 0.000941468 * temp);
            delay(1000);
      }
      PHLevel  = PHLevel/8.0; // average of the 8samples for better precision
          return PHLevel;    
}

One final point. A0 and A1 are aliases for the analog pins WHEN THEY ARE USED AS DIGITAL PINS. Since you are NOT using them as digital pins, you should use the analog pin numbers, 0 and 1, instead.

what do you mean? and how i do it?

Change

const int LM35 = A0;
const int PHprobe = A1;

to

const int LM35 = 0;
const int PHprobe = 1;

Not exactly rocket science.

thanks