Is my PH probe broken?

swisschris104

Community Member
View Badges
Joined
Mar 19, 2021
Messages
65
Reaction score
57
Location
Palos Hills
Rating - 0%
0   0   0
Everything worked fine until just a few days ago.. any idea what happened?


1618962740788.png


1618962764479.png


1618963082807.png



Last Edit: was using robotank. shorted the ph board and now i2i is responding, so it may be resolved. gottaa plug evertyhing back inm
 
Last edited:
OP
OP
S

swisschris104

Community Member
View Badges
Joined
Mar 19, 2021
Messages
65
Reaction score
57
Location
Palos Hills
Rating - 0%
0   0   0
Ahh, its now appearing when i2c detect but now i get this when trying to calibrate.
1618964579192.png


deleted connector and recreated,
deleted Ph and recreated.

With probe unplugged i get the following.
1618964877316.png


Highlighted is when i ran script with no probe plugged in.
1618965102359.png
 
Last edited:

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
Oh wow, unreal, this isn't good. Sorry for getting to this late, definitely not a probe, I don't know what's going on. Now it looks like the decimal is in the wrong place. Without probe it would have been around 4.04. It sounds like you've done the reset on board and power cycled the controller so I don't think there's much more can you do, I'm going to have to send you a replacement board. I'll send you an email with a tracking number, sorry again for the trouble.
 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
If there's any Arduino people reading this, is it possible if the memory fills up to much and it crashes can the program code get altered or portions lost in any way as in overwritten or erased?
 

attiland

2500 Club Member
View Badges
Joined
Jul 22, 2020
Messages
2,594
Reaction score
4,800
Location
United Kingdom
Rating - 0%
0   0   0
If there's any Arduino people reading this, is it possible if the memory fills up to much and it crashes can the program code get altered or portions lost in any way as in overwritten or erased?
Simple answer is no. If you have a code filling up memory a restart would sort your problem without modifying code . If you have to reload the code you have a faulty board.
 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
Simple answer is no. If you have a code filling up memory a restart would sort your problem without modifying code . If you have to reload the code you have a faulty board.
That's what I think too however the ATtiny85 eeprom can somehow be wiped out or altered and I wouldn't think that's possible either if program crashed. That's what originally happened here, there was no I2C address, then he did a hard reset on the board which writes default data back to eeprom so after power cycle the address was back and circuit worked again but now the data is wrong or possible even just as simple as decimal is in wrong position.

Now I'm wondering as eeprom can be altered without being written to maybe program can be corrupted as well too when whatever happens happens. I've never experienced anything like this and wonder if it's an ATtiny85 issue or my code.

It's really sad because I feel the circuit is pretty good but it's just not being reliable, I'm thinking of switching to the ATmega32u4 which is massive overkill but I've used this for a few things like my ATO and never a problem, this is my first go with the ATtiny85.

The program was using 99% of storage because of Wire library so just recently I've dropped the unused features bring storage down to 65%. Memory went from 40% to 32% but I'm not so confident this will solve it as I feel the same about a reset should get the program back on track, obviously that's not happening though. :(

If you're interested in seeing this is the simplified code. I've posted the full version in the main thread but not sure what page.

C++:
#include <Wire.h>
#include <EEPROM.h>

#define PROBE_IN A3 //57   // anlaog a3  - green wire
#define PROBE_REF A2 //56   // anlaog a2  - white wire

byte i2cAdd = 99;  // eeprom 1

double pH;

byte in_char = 0;
char inData[15];
byte w = 0;                      //counter used for ph_data array.
byte q = 0;                      //counter used for ph_data array.

char computerdata[31];           //we make a 31 byte character array to hold incoming data
char phData[31];           //we make a 31 byte character array to hold incoming data

byte flashLED = 0;
unsigned long previousMillis = 0;
void setup()
{
  byte z = 255;
  z = EEPROM.read(50);
  if (z != 1)
  {
    defaults();  //  Defaults
  }

  pinMode(1, OUTPUT);
  flashLED = 1;
  i2cAdd = EEPROM.read(1);
  readDefaults();
  measuremV();
  Wire.begin(i2cAdd);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
}
void loop()
{
  if (flashLED == 1)
  {
    for(byte i=0; i < 4; i++)
    {
      digitalWrite(1, LOW);  // LED on circuit board
      delay(200);
      digitalWrite(1, HIGH);  // LED on circuit board
      delay(200);
    }
    flashLED = 0;
  }
  if ((millis() - previousMillis) >= 3000)
  {
    measuremV();
    previousMillis = millis();
  }
}
byte buttonPressCount = 0;
void measuremV() 
{
  double differentialmV;
  float  probeIn, probeRef, inputV;

  int buttonReset = readADC(PROBE_REF);
  if (buttonReset > 1000) 
  {
    buttonPressCount++;
    if (buttonPressCount == 1) {defaults();}
  }
  else {buttonPressCount = 0;}
    
  analogReference(INTERNAL);  // set to INTERNAL for ATtiny

  // take a reading
  probeIn  = ((readADC(PROBE_IN) * 1.1) / 1024.0);
  probeRef = ((readADC(PROBE_REF) * 1.1) / 1024.0);

  // calculate mV  
  differentialmV = (probeIn - probeRef) * 1000;
  float temp_mvPerPH = 59.16;  // calibrated mV per pH with temperature compensation
  float mVPerPH = 59.16;;  // calibrated mV per pH without temperature compensation

//  temp_mvPerPH = mVPerPH * (tempC+273.15) / ((tempCalibrated)+273.15);
  // convert to pH
  pH = fabs(7.0 - (differentialmV / temp_mvPerPH));
  
  dtostrf(pH, 0, 3, phData);  // convert float to char array so it can be sent over I2C
}
void receiveEvent()
{
  while (Wire.available()) {    // are there bytes to receive.
    in_char = Wire.read();   // receive a byte.
    inData[w] = in_char;            // load this byte into our array.
    if (q > 0)
    {
      computerdata[q-1] = inData[w];
      q += 1;
    }
    if (inData[w] == ',') {q = 1;}
    w += 1;                         // incur the counter for the array element.
    if (in_char == 0) {             // if we see that we have been sent a null command.
      w = 0;                        // reset the counter w to 0.
      q = 0;                        // reset the counter q to 0.
      digitalWrite(1, LOW);  // LED on circuit board
      break;                        // exit the while loop.
    }
  }
}
void requestEvent()
{
  if ((inData[0] == 'R'))           // send pH
  {
    memset(inData,0,sizeof(inData));
    Wire.write(1);               // send byte 1
    Wire.write(phData,30);
    digitalWrite(1, HIGH);
  }
  else if ((inData[0] == 'A'))           // change I2C address
  {
    byte a = 0;
    a = atoi(computerdata);

    if ((a > 0) && (a < 128))  // verify address is valid
    {
      flashLED = 1;
      i2cAdd = a;  // change address
      EEPROM.write(1, i2cAdd);  // I2C address - 40, 41, 42, 43, 44, 45, 46, 47
    }
    memset(inData,0,sizeof(inData));
    digitalWrite(1, HIGH);  // LED on circuit board
  }
  else if (inData[0] == 'D')  // set defaults
  {
    defaults();
    memset(inData,0,sizeof(inData));
    Wire.write(1);
//    Wire.write("ok",30);
    digitalWrite(1, HIGH);
  }
  else
  {
    memset(inData,0,sizeof(inData));
    digitalWrite(1, HIGH);  // LED on circuit board
  }
}
void defaults()
{
    flashLED = 1;
  //  Defaults
    EEPROM.write(1, 99);  // I2C address - 40, 41, 42, 43, 44, 45, 46, 47
    delay(200);

    // read defaults
    readDefaults();
}
void readDefaults()
{
    // read defaults
    i2cAdd = EEPROM.read(1);
}
double readADC(int channel)
{
  uint32_t total = 0UL;
  uint16_t sampleCount = 4096;  // 2048
  for (uint16_t i = 0; i < sampleCount; i++) {total += analogRead(channel);}
  total = total >> 6;
  double proportional = (total * 1.0) / (0b00000001 << 6);
  return proportional;
}
 
Last edited:

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
I think I found the answer to my question. I happened to be looking in the ATmega328 datasheet and noticed "Preventing Flash Corruption", looks like the flash can be corrupted along with the eeprom. I checked the ATtiny85 and same is talked about. Some how the internal Brown-out Detector needs to be enabled.

Page 144

This sounds familiar.

 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
Fingers crossed problem is fixed from this day on, feeling good about it.

Turns out I only needed to change the internal fuses on ATtiny85 to enable brownout detection. Apparently now if input voltage goes under 2.7v the chip will shut down and restart once it goes above, I'm going to see if I can test this.

Here's the fuse settings, you can see under HIGH fuse presets is brown out, my settings were disabled. Seems like a simple change of fuse 0xD7 to 0xD5 a year ago could have prevented a lot of headaches.

 

attiland

2500 Club Member
View Badges
Joined
Jul 22, 2020
Messages
2,594
Reaction score
4,800
Location
United Kingdom
Rating - 0%
0   0   0
That's what I think too however the ATtiny85 eeprom can somehow be wiped out or altered and I wouldn't think that's possible either if program crashed. That's what originally happened here, there was no I2C address, then he did a hard reset on the board which writes default data back to eeprom so after power cycle the address was back and circuit worked again but now the data is wrong or possible even just as simple as decimal is in wrong position.

Now I'm wondering as eeprom can be altered without being written to maybe program can be corrupted as well too when whatever happens happens. I've never experienced anything like this and wonder if it's an ATtiny85 issue or my code.

It's really sad because I feel the circuit is pretty good but it's just not being reliable, I'm thinking of switching to the ATmega32u4 which is massive overkill but I've used this for a few things like my ATO and never a problem, this is my first go with the ATtiny85.

The program was using 99% of storage because of Wire library so just recently I've dropped the unused features bring storage down to 65%. Memory went from 40% to 32% but I'm not so confident this will solve it as I feel the same about a reset should get the program back on track, obviously that's not happening though. :(

If you're interested in seeing this is the simplified code. I've posted the full version in the main thread but not sure what page.

C++:
#include <Wire.h>
#include <EEPROM.h>

#define PROBE_IN A3 //57   // anlaog a3  - green wire
#define PROBE_REF A2 //56   // anlaog a2  - white wire

byte i2cAdd = 99;  // eeprom 1

double pH;

byte in_char = 0;
char inData[15];
byte w = 0;                      //counter used for ph_data array.
byte q = 0;                      //counter used for ph_data array.

char computerdata[31];           //we make a 31 byte character array to hold incoming data
char phData[31];           //we make a 31 byte character array to hold incoming data

byte flashLED = 0;
unsigned long previousMillis = 0;
void setup()
{
  byte z = 255;
  z = EEPROM.read(50);
  if (z != 1)
  {
    defaults();  //  Defaults
  }

  pinMode(1, OUTPUT);
  flashLED = 1;
  i2cAdd = EEPROM.read(1);
  readDefaults();
  measuremV();
  Wire.begin(i2cAdd);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
}
void loop()
{
  if (flashLED == 1)
  {
    for(byte i=0; i < 4; i++)
    {
      digitalWrite(1, LOW);  // LED on circuit board
      delay(200);
      digitalWrite(1, HIGH);  // LED on circuit board
      delay(200);
    }
    flashLED = 0;
  }
  if ((millis() - previousMillis) >= 3000)
  {
    measuremV();
    previousMillis = millis();
  }
}
byte buttonPressCount = 0;
void measuremV()
{
  double differentialmV;
  float  probeIn, probeRef, inputV;

  int buttonReset = readADC(PROBE_REF);
  if (buttonReset > 1000)
  {
    buttonPressCount++;
    if (buttonPressCount == 1) {defaults();}
  }
  else {buttonPressCount = 0;}
   
  analogReference(INTERNAL);  // set to INTERNAL for ATtiny

  // take a reading
  probeIn  = ((readADC(PROBE_IN) * 1.1) / 1024.0);
  probeRef = ((readADC(PROBE_REF) * 1.1) / 1024.0);

  // calculate mV 
  differentialmV = (probeIn - probeRef) * 1000;
  float temp_mvPerPH = 59.16;  // calibrated mV per pH with temperature compensation
  float mVPerPH = 59.16;;  // calibrated mV per pH without temperature compensation

//  temp_mvPerPH = mVPerPH * (tempC+273.15) / ((tempCalibrated)+273.15);
  // convert to pH
  pH = fabs(7.0 - (differentialmV / temp_mvPerPH));
 
  dtostrf(pH, 0, 3, phData);  // convert float to char array so it can be sent over I2C
}
void receiveEvent()
{
  while (Wire.available()) {    // are there bytes to receive.
    in_char = Wire.read();   // receive a byte.
    inData[w] = in_char;            // load this byte into our array.
    if (q > 0)
    {
      computerdata[q-1] = inData[w];
      q += 1;
    }
    if (inData[w] == ',') {q = 1;}
    w += 1;                         // incur the counter for the array element.
    if (in_char == 0) {             // if we see that we have been sent a null command.
      w = 0;                        // reset the counter w to 0.
      q = 0;                        // reset the counter q to 0.
      digitalWrite(1, LOW);  // LED on circuit board
      break;                        // exit the while loop.
    }
  }
}
void requestEvent()
{
  if ((inData[0] == 'R'))           // send pH
  {
    memset(inData,0,sizeof(inData));
    Wire.write(1);               // send byte 1
    Wire.write(phData,30);
    digitalWrite(1, HIGH);
  }
  else if ((inData[0] == 'A'))           // change I2C address
  {
    byte a = 0;
    a = atoi(computerdata);

    if ((a > 0) && (a < 128))  // verify address is valid
    {
      flashLED = 1;
      i2cAdd = a;  // change address
      EEPROM.write(1, i2cAdd);  // I2C address - 40, 41, 42, 43, 44, 45, 46, 47
    }
    memset(inData,0,sizeof(inData));
    digitalWrite(1, HIGH);  // LED on circuit board
  }
  else if (inData[0] == 'D')  // set defaults
  {
    defaults();
    memset(inData,0,sizeof(inData));
    Wire.write(1);
//    Wire.write("ok",30);
    digitalWrite(1, HIGH);
  }
  else
  {
    memset(inData,0,sizeof(inData));
    digitalWrite(1, HIGH);  // LED on circuit board
  }
}
void defaults()
{
    flashLED = 1;
  //  Defaults
    EEPROM.write(1, 99);  // I2C address - 40, 41, 42, 43, 44, 45, 46, 47
    delay(200);

    // read defaults
    readDefaults();
}
void readDefaults()
{
    // read defaults
    i2cAdd = EEPROM.read(1);
}
double readADC(int channel)
{
  uint32_t total = 0UL;
  uint16_t sampleCount = 4096;  // 2048
  for (uint16_t i = 0; i < sampleCount; i++) {total += analogRead(channel);}
  total = total >> 6;
  double proportional = (total * 1.0) / (0b00000001 << 6);
  return proportional;
}
This is very interesting. Although the smallest board I have ever used was the Nano and just assumed that ATtiny85 was working the same principle. I know that eprom can programmatically written however I never needed it so never tried I prefer to use a logger for such a task.
 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
This is very interesting. Although the smallest board I have ever used was the Nano and just assumed that ATtiny85 was working the same principle. I know that eprom can programmatically written however I never needed it so never tried I prefer to use a logger for such a task.
Looks like the fuses are already set to enable brown out detection on Arduino boards but when you use the chips on their own you need to enable as it's disabled from the factory. The ATtiny85 is an AVR so same principle as Nano, Uno etc... however it's not used on any Arduino board due to the size and not useful for most projects.
 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
After some more reading and testing I'm 99.9% confident these pH issues are a thing of the past. My gut feeling has always been some kind of code / programming issue and after discovering the eeprom and flash memory can be corrupted with low voltage I'm certain this is the reason for this random issue. It turns out many have experienced this with various AVR's, not something new. Using that hardware reset for eeprom I've been able to confirm the eeprom does get corrupted and based on what I'm seeing it certainly makes sense the program is also being corrupted, it's kind of what I've always been thinking.

I did some testing to see if I could see the brown out in action. First before enabling I connected to variable power supply and monitored the +3.3v power for the ATtiny85. When the input voltage was down to 5.4v the DC/DC power isolator output started dropping along with the 3.3v. Once it dropped to 2.6v the light for pH circuit went very dim and after 2.5v it went out completely, when I turned voltage back up 8 out of 10 times the light didn't come back on so it was clear the program crashed as a power cycle got the program running again. None of these instances corrupted anything though but I can see that as it's very random and rare for that to actually happen.

Then I enabled the brown out and did the same test. This time when voltage dropped to 2.7v the LED went out, it never dimmed, when I turned voltage back up the LED flashed 4 times just like it would when the circuit is first powered up. This verifies the brown out did in fact shut down the ATtiny85 and restarted it when voltage was in a safe operating level, beautiful!

Page 163 shows the safe operating voltage, the ATtiny85 is running at 8 Mhz so the minimum safe operating voltage is 2.5v, now with BOT enabled it will always shut down at 2.7v well before the 2.5v limit.


I'm guessing this has happened so many times to you due to a power supply or DC noise issue, this would explain why some have problems and most don't. I've personally never experienced this and I'm always messing with it but I have a good power supply and AC power rarely goes out which could cause it. I had one person who had a power outage after running controller 6 months and then the pH circuit no longer worked correctly, just gibberish because the program got corrupted. Hugh weight off my shoulders whewww....

Again I'm very sorry for the troubles I've caused you, I'm certain it'll be clear sailing from here on in.
 
Last edited:
OP
OP
S

swisschris104

Community Member
View Badges
Joined
Mar 19, 2021
Messages
65
Reaction score
57
Location
Palos Hills
Rating - 0%
0   0   0
Not sure if this helps at all but the issue may have come in stages.

1st day I got
FDCBA058-B3FA-47C5-91C3-0C158B7D185E.jpeg


fre days later got the long decimal
C40ABD57-7835-491E-9D00-87BA4BD56DB7.jpeg

5D52FDE3-0E32-4275-919C-AE54F27331A1.jpeg

Few days later it began to display like 3.7563e24 but I don’t have a screenshot of that
 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
Not sure if this helps at all but the issue may have come in stages.

1st day I got
FDCBA058-B3FA-47C5-91C3-0C158B7D185E.jpeg


fre days later got the long decimal
C40ABD57-7835-491E-9D00-87BA4BD56DB7.jpeg

5D52FDE3-0E32-4275-919C-AE54F27331A1.jpeg

Few days later it began to display like 3.7563e24 but I don’t have a screenshot of that
Thanks, that long decimal is reef-pi not rounding it but the last number you posted is when it went bad.
 
OP
OP
S

swisschris104

Community Member
View Badges
Joined
Mar 19, 2021
Messages
65
Reaction score
57
Location
Palos Hills
Rating - 0%
0   0   0
Lol, it is appearing in a more normal form now.I hope/sure my PH isnt 5.7 but it is a closer number than 65905609653. Wonder what would actually read correctly now if i calibrate it.
w.
1619186727465.png
 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
Lol, it is appearing in a more normal form now.I hope/sure my PH isnt 5.7 but it is a closer number than 65905609653. Wonder what would actually read correctly now if i calibrate it.
w.
1619186727465.png
No it won't work. You can see the e+ in the number so it's not a real value. I'm pretty sure once I get the boards from you I will reprogram and they will be ok.
 

robsworld78

Well-Known Member
View Badges
Joined
Feb 14, 2020
Messages
952
Reaction score
1,281
Location
Edmonton, Canada
Rating - 0%
0   0   0
Im curious why we haven't encounter this with ezo or the opensource ph board? is it the absence of eeprom?
The pH board uses an analog to digital converter so there's no onboard flash memory or eeprom like mine or Atlas board. Atlas board doesn't do it because I imagine they will have the brown out detection enabled, rookie mistake by me, I wasn't aware of this feature or that flash and eeprom could be corrupted.
 
Back
Top