data appear to be 0.00 after I2C

hi i am new here and i face some problem.
i am doing a project require me to measure some reading(pH and ORP) by using some sensor on a slave arduino and send it the master arduino by the mean of I2C. the problem is my reading of pH become 0.00 after send but the reading for ORP is still ok.

master.ino (440 Bytes)

sensor.ino (4.09 KB)

You have two pH_Value variables in your code. One is declared globally

double pH_Value;

another is declared static inside loop.

static float pH_Value, pH_voltage;

These are two completely different unrelated pH_Value variables.

You form the result of your measurements on the static variable declared inside loop. But requestEvent sends out the global variable. The global variable is always zero, so you always send zero.

Why did you suddenly decide to declare a static variable pH_Value inside loop? You do not have this problem with ORP_Value variable.


Also, this is a dormant issue, but anyway. In sensor.ino, function avergearray, this

avg = amount/number;

is integer division. It does not produce floating-point result. Apparently you already encountered this issue, since in other location you wrote

avg = (double)amount/(number-2);

The first one has to be fixed as well.

thanks btw, but the problem still there. i wonder where the “⸮⸮” come from and where my “pH value:” goes in this picture…

WongLQ:
thanks btw, but the problem still there.

I updated the post. Did you fix the "two variables" problem?

wow finally i am getting the reading now, big thanks!
something may be wrong with me as its 4am now at my country.
btw i am still trying to fix that missing "pH_Value:" from Wire.print(pH_Value);

edit
i solved the missing "pH_Value" by moving
Wire.print("pH value:");
Wire.print(pH_Value);
to before
Wire.print("ORP value: ");

it solve the problem but i dont know why...

WongLQ:
wow finally i am getting the reading now, big thanks!
something may be wrong with me as its 4am now at my country.
btw i am still trying to fix that missing "pH_Value:" from Wire.print(pH_Value);

Um... You are supposed to keep the global pH_Value and remove the static one. Not the other way around.

yea i did it that way

@OP

Can you please, post your attached sketches (of the original post) here with code tags (</>) so that we can scrutinize if you have written the I2C codes as per I2C Bus protocol.

[Master]#include <Wire.h>
void setup() {
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop() {
  Wire.requestFrom(8,32); // request 32 bytes from slave device #8

  while (Wire.available()) { // slave may send less than requested
    char c = Wire.read(); // receive a byte as character
 Serial.print(c);         // print the character

  }
  delay(500);
[slave(sensors)]/*
  pH and ORP measurements on Arduino
*/

//libraries

#include <Wire.h>      //I2C
//const byte i2c_address=0x78;

//pH and ORP variables
#define samplingInterval 1       //sample values every 10 milliseconds
#define pH_Pin A0           //pH meter Analog output to Arduino Analog Input 0
#define ORP_Pin A1                 //orp meter output,connect to Arduino controller ADC pin

#define pH_Offset 0.06            //deviation compensation
#define ORP_OFFSET 98             //zero drift voltage

#define arrayLenth 400             //times of collection
int pH_Array[arrayLenth];         //store the average value of the sensor feedback
int pH_ArrayIndex=0;

double ORP_Value;
double pH_Value;

int ORP_Array[arrayLenth];
int ORP_ArrayIndex=0;
int data_point_counter=0;

//general variables
#define voltage 5.00              //system voltage
#define printInterval 1000       //write values every 10000 milliseconds


//general formula returning average
double avergearray(int* arr, int number){
       int i;
       int max,min;
       double avg;
       long amount=0;
       if(number<=0) {
               printf("Error number for the array average!/n");
               return 0;
       }
       if(number<5) { //less than 5, calculated directly statistics
               for(i=0; i<number; i++) {
                       amount+=arr[i];
               }
               avg = (double)amount/(number-2);
               return avg;
       }else{
               if(arr[0]<arr[1]) {
                       min = arr[0]; max=arr[1];
               }
               else{
                       min=arr[1]; max=arr[0];
               }
               for(i=2; i<number; i++) {
                       if(arr[i]<min) {
                               amount+=min;
                               min=arr[i];
                       }else {
                               if(arr[i]>max) {
                                       amount+=max;
                                       max=arr[i];
                               }else{
                                       amount+=arr[i];
                               }
                       }
               }
               avg = (double)amount/(number-2);
       }
       return avg;
}

void setup(void)
{
       Serial.begin(9600);
       Wire.begin(8);
    Wire.onRequest(requestEvent);
  
}

void loop(void)
{
       static unsigned long pH_samplingTime = millis();
       static unsigned long GENERAL_printTime = millis();
       static float pH_voltage;

       if(millis()-pH_samplingTime > samplingInterval) //read an analog value every 20ms
       {
               pH_Array[pH_ArrayIndex++]=analogRead(pH_Pin);
               ORP_Array[ORP_ArrayIndex++]=analogRead(ORP_Pin);
               if(pH_ArrayIndex==arrayLenth) {
                       pH_ArrayIndex=0;
               }
               if (ORP_ArrayIndex==arrayLenth) {
                       ORP_ArrayIndex=0;
               }
               pH_voltage = avergearray(pH_Array, arrayLenth)*5.0/1024;
               pH_Value=3.5*pH_voltage+pH_Offset;
               pH_samplingTime=millis()+10;

               ORP_Value=((30*(double)voltage*1000)-(75*avergearray(ORP_Array, arrayLenth)*voltage*1000/1024))/75-ORP_OFFSET;

       }

       if(millis() - GENERAL_printTime >= printInterval) //print to serial monitor and write to file
       {
             //  Serial.print(millis()/1000);
           // Serial.print(" sec -- ");
                
               Serial.print("ORP value: ");
               Serial.print(ORP_Value);
               Serial.print(" mV -- ");
               Serial.print("pH value: ");
               Serial.println(pH_Value);
              
            

               GENERAL_printTime=millis();

           
               }
       }
void requestEvent()
{
             
             Wire.print("pH value:");
               Wire.print(pH_Value);
               Wire.print("ORP value: ");
               Wire.print(ORP_Value);
               Wire.println(" mV--  ");
               
              
              
               
         
              
               
               
}

this problem is solved btw

WongLQ:
this problem is solved btw

Please, post the screenshot of the Serial Monitor of Master that is showing the values received from Slave.

//===Few Comments=================================================
1. The Master has requested for 32-byte data from Slave by issuing this command:
Wire.requestFrom(8, 32);

2. You have queued the following data bytes into the I2C Buffer of Slave for onward transfer to Master.

Wire.print("pH value:");    //9 bytes (ASCII codes)
Wire.print(pH_Value);                 //3/4 bytes (ASCII coded) range:00.00 - 14.00 
Wire.print("ORP value: ");           //10 bytes
Wire.print(ORP_Value);               //6 bytes? xxx.xx
Wire.println(" mV--  ");               //7 bytes

3. You have queued 36 bytes data (Step-2); but, the Master is reading only 32 bytes in Step-1. Why is this mismatch? Try with this command at the Master side:

Wire.requestFrom(8, 36);

4. As you are not sure about the number of digits present in the float type variables pH_Value and ORP_Value, it is safe to send the binary32 formatted (4-byte) values for these variables instead of ASCII coded values. The procedures are:

union
{
   float pH_Value;
   byte pH[4];

}mypH;

mypH.pH_Value = pH_value;

union
{
   float ORP_Value;
   byte ORP[4];

}myORP;

myORP.ORP_Value = ORP_value;

void requestEvent()
{
             
    Wire.print("pH value:");                             //9 bytes
    Wire.write(mypH.pH, sizeof(myPh.pH));      //4 bytes
    Wire.print("ORP value:");                          //10 bytes
    Wire.write(myOPR.ORP, sizeof(myORP.ORP)); //4 bytes    
    Wire.println("mV--");                                  //4 bytes 
 }

At the Master side, let us execute the following code:

Wire.requestFrom(8, 31);

And also, use the union at the Master side to reconstruct the float values for the variables pH_Value and ORP_Value.
//===============================================================