im trying to change the amount of times the analog pin ph1Pin and ph2Pin are read. more specifically slow down the read rate hoping for a more stable reading. this is the code segment
if (millis() - phRefreshMarker > 1000) {
if (phreadstate == 1) {
for (int i = 0; i < 10; i++) {
buf[i] = analogRead(pH1Pin);
delay(100);
if (i >= 9) {
phreadstate = 2;
delay(250);
}
}
}
if (phreadstate == 2) {
for (int i = 0; i < 10; i++) {
buf2[i] = analogRead(pH2Pin); //ph 2 set to ph1pin for now
delay(100);
if (i >= 9) {
phreadstate = 1;
delay(250);
}
}
//
}
pH1avgValue = 0;
for (int i = 2; i < 8; i++)
pH1avgValue += buf[i];
float pHVol = (float)pH1avgValue * 5.0 / 1024 / 6;
ph1Value = -5.7 * pHVol + 24.4;
pH2avgValue = 0;
for (int i = 2; i < 8; i++)
pH2avgValue += buf2[i];
float pHVol2 = (float)pH2avgValue * 5.0 / 1024 / 6;
ph2Value = -5.7 * pHVol2 + 24.4;
phRefreshMarker = millis();
}
}
so i change the amount of times the pins are read by changing the code to this
if (phreadstate == 1) {
if (millis() - phRefreshMarker > 1000) {
if (phreadstate == 1) {
for (int i = 0; i < 5; i++) {
buf[i] = analogRead(pH1Pin);
delay(100);
if (i >= 4) {
phreadstate = 2;
delay(250);
}
}
}
if (phreadstate == 2) {
for (int i = 0; i < 5; i++) {
buf2[i] = analogRead(pH2Pin); //ph 2 set to ph1pin for now
delay(100);
if (i >= 4) {
phreadstate = 1;
delay(250);
}
}
}
and that part works as expected. the part i dont understand is
if i change " for (int i = 2; i < 8; i++)" to anything other than what it is, for example ""for (int i = 0; i < 4; i++)"" i dont get my expected value. so im lost can someone explain what going on? i dont get why these values are what thay are in this piece of code below
"for (int i = 2; i < 8; i++)"
if i change " for (int i = 2; i < 8; i++)" to anything other than what it is, for example ""for (int i = 0; i < 4; i++)"" i dont get my expected value.
What do you expect ?
What do you get ?
Please post a complete program that demonstrates the problem
Please post a complete program that demonstrates the problem
well first of all i don know why theres and interger "i" delcared with a value of 2 instead of 0. then it appears pH1avgValue = 0 + i "6" times? can you further explain this to me?
I think you need to consider the logic of what you are doing.
i is declared and a range is set
for (int i = 0; i < 10; i++)
so the range of numbers is 0, 1, 2, 3, 4, 5, 6, 7, 8 ,9
then a condition is checked
if (i >= 9)
this is over complicated. The number will never be greater than 9 because of the range. You could check it 2 other ways if (i == 9)orif (i > 8)
so like I said you need to understand the logic of what you are asking it to do.
The values are stored in the buffer in order. Then we get to the buffer read. With your example the first item read is the 3rd value
for (int i = 2; i < 8; i++)
....
buf[i]
(where i = 2) which seems like a strange place to start. So you're not slowing anything down. Just reading from a different point.
If you want to change the amount of times they are read then change the initial loop ranges for (int i = 0; i < 10; i++) to a value smaller than 10 (10 reads)
If you want to slow the reads down change the ms difference if (millis() - phRefreshMarker > 1000) to a value larger than 1000ms (1 second)
ee_es_pe:
I think you need to consider the logic of what you are doing.
thanks for clarifying that but i cannot change the "amount of reads" by doing what you said. ive already tried that
for example this code give me the wrong value. "based on what the sensor is reading lets say i expect value 7.0, if i dont modify the code and leave everything the way it works as in the first segment at the top of this thread i get the expected value of 7 aka calibration value, however the code below changes from the expected value 7 to 15. and the code no longer works right
if (millis() - phRefreshMarker > 1500) {
if (phreadstate == 1) {
for (int i = 0; i < 5; i++) {
buf[i] = analogRead(pH1Pin);
// delay(55);
if (i >= 4) {
phreadstate = 2;
delay(100);
}
}
}
if (phreadstate == 2) {
for (int i = 0; i < 5; i++) {
buf2[i] = analogRead(pH2Pin); //ph 2 set to ph1pin for now
//delay(55);
if (i >= 4) {
phreadstate = 1;
delay(100);
}
}
}
pH1avgValue = 0;
for (int i = 0; i < 4; i++)
pH1avgValue += buf[i];
float pHVol = (float)pH1avgValue * 5.0 / 1024 / 6;
ph1Value = -5.7 * pHVol + 24.4;
pH2avgValue = 0;
for (int i = 0; i < 4; i++)
pH2avgValue += buf2[i];
float pHVol2 = (float)pH2avgValue * 5.0 / 1024 / 6;
ph2Value = -5.7 * pHVol2 + 24.4;
phRefreshMarker = millis();
}
}
If you're doing an average of 4 values, then what's the 6 for?
i understand the voltage 5.0 and the resolution of analog read but i did not understand the dividing it by 6 was doing. i found this code a long time ago when i bought the dm 4507 ph module and was looking for sample code. that is the code i found i have slightly modified it but i didnt touch the for loops. why is it being divided by 6. what is the point of the for loop at all? it dont look like its averaging a value at all?
Since ( i >= 9 ) will only be true at the last iteration of the if statement, seems it would be a lot simpler to change:
if (phreadstate == 1) {
for (int i = 0; i < 10; i++) {
buf[i] = analogRead(pH1Pin);
delay(100);
if (i >= 9) {
phreadstate = 2;
delay(250);
}
}
}
to this:
if (phreadstate == 1) {
for (int i = 0; i < 10; i++) {
buf[i] = analogRead(pH1Pin);
delay(100);
}
phreadstate = 2;
delay(250);
}
If you want to slow down the read rate of the analog input, you can change the delay(100) line to a longer delay, that will change the delay between individual samples that are written into the buf[] array. You can also change the amount in the line
if (millis() - phRefreshMarker > 1000) {
and that will change the delay between each group of samples (although with a delay(100) and 10 samples, you will already be taking a bit over 1000mS to fill the array).
I'm not sure why the first two and last two samples are being discarded in the calculation, but it would be easier if you set a constant to the number of elements in buf[], then based all the conditional statements and calculations off that, so you could easily change the number of samples in a single place instead of making several changes throughout the code. Such as:
const byte bufSize = 10;
int buf[bufSize];
int buf2[bufSize];
if (millis() - phRefreshMarker > 1000) {
if (phreadstate == 1) {
for (int i = 0; i < bufSize; i++) {
buf[i] = analogRead(pH1Pin);
delay(100);
}
phreadstate = 2;
delay(250);
}
if (phreadstate == 2) {
for (int i = 0; i < bufSize; i++) {
buf2[i] = analogRead(pH2Pin); //ph 2 set to ph1pin for now
delay(100);
}
phreadstate = 1;
delay(250);
}
pH1avgValue = 0;
for (int i = (bufSize + 2); i < (bufSize - 2); i++)
pH1avgValue += buf[i];
float pHVol = (float)pH1avgValue * 5.0 / 1024 / (bufSize - 4);
ph1Value = -5.7 * pHVol + 24.4;
pH2avgValue = 0;
for (int i = (bufSize + 2); i < (bufSize - 2); i++)
pH2avgValue += buf2[i];
float pHVol2 = (float)pH2avgValue * 5.0 / 1024 / (bufSize - 4);
ph2Value = -5.7 * pHVol2 + 24.4;
phRefreshMarker = millis();
}
}
is there any reason for the for loop then? to correct my math,
analogRead spits out a value of 678 i end up with a list buf{i with 5 entries of a values reads from analogRead. then pH1avgValue += buf[i ends up being 678 x 4 and == 2,712. then "float pHVol = (float)pH1avgValue * 5.0 / 1024/4;" Because pH1avgValue == 2,712 then next part of the formula is 2712 5 == 13,560 divided by 1024 / 4 == 3.31. and the final step ph1Value has a value of -5.7 so -5.73.31+24.4 == 5.53.
how can i actually pick the average value? im already using ac isolation transformers dc-dc optical converters id like to smooth it out some more
Delta_G:
Again, third grade math class. Not hard. You don't "pick" an average. To get an average you add up a bunch of readings and then divide by the number of readings you added up. There's nothing esoteric about it.
8th grade math. and how many times cant i take a reading with this interger variable can i declare an unsigned long as the list and take more readings?
Delta_G:
Third grade grammar class as well. Add some punctuation. I can't figure out what this sentence is supposed to mean.
okay but your logic is still wrong because im going to take a list of readings that most likely have all different values and always have about the same amount of error therefore it dont matter how many readings i take or what i divide it by its always going to jump around just as much as 1 reading or 10
Delta_G:
You don't understand the concept of an average do you.
If you take ten readings that are jumping around by random error, then the average "averages out" the random error.
Okay so how can i average out some more error. Without averaging any of the numbers on a scale of 1 - 14.0, I get an error range of about .1 - 1.2 "which is not that bad IMO". I know i can only cover-up the problem in the code so much. With averaging 10 readings my error range becomes about 0.1 -1.0. This is where im at im not sure what to do next. I know i'm getting noise in my signal but I've already done everything i can think of to limit the noise. I use a 9v AC 2.0 AMP transformer fed into a bridge rectifier, decoupling caps, each pH module has its own linear regulator and DC-DC optical converters. I've made sure to shield everything including the power supply for the,wire,analog signal isolators. Do you think there is any more room in the code to condition the readings? My readings in just a cup of water are perfect its when i put the electrode in something with a pump or some sorts the become erratic. These pH electrodes operating in the millions of OHM's range
Delta_G:
If there is fluctuation or error in your readings then it isn't because of the code.
pH readings are hard. It takes some electrical expertise (and attention to detail) to get the noise out. You're not going to home-brew a pH meter that has the noise characteristics of a commercially available one unless you are a real expert with electronics.
If you want to smooth out the readings more then you want MORE averaging and not less.
I think the commercial ones are only account to around 1.0 too. The isolation i'm getting is good i can drop an extension cord in a bucket of water at 120v and my reading move maybe 1.5 at the most. But i'm having problems smoothing out that last 1.0 in a normal non excruciating test environment but there is still that inductance of the isolation transformer i'm using i think may be causing a problem. My biggest concern comes when automatically adding chemicals based on these readings.
Why when i take more than 10 readings in the for loop do it interfere with sensor 2's reading. I dont know how else to explain it. If I set the for loop to more than 10 readings then they are way off and sensors 2's readings start affecting sensor 1's reading?
notsolowki:
Why when i take more than 10 readings in the for loop do it interfere with sensor 2's reading. I dont know how else to explain it. If I set the for loop to more than 10 readings then they are way off and sensors 2's readings start affecting sensor 1's reading?
Did you increase the size of the buf[] and buf[2] arrays to allow for the additional readings? Likely you are going past the end of the array, and the buf[2] array is adjacent to buf[] in memory.
david_2018:
Did you increase the size of the buf[] and buf[2] arrays to allow for the additional readings? Likely you are going past the end of the array, and the buf[2] array is adjacent to buf[] in memory.
yes you were exactly right i forgot to increase the size of the buffer thankyou
Is there any reason not to take 60 samples and average the 60 samples. Even with 32 samples my readings are so stable now i'm seeing .03 swings every now and then instead of .10 The readings would only swing .10 very rarely seems like the liquid was having some capacitance problems ill deal with later. Also in my previous i mentioned the reading would swing by 1.0 i didnt mean 1.0 i meant .10
notsolowki:
Is there any reason not to take 60 samples and average the 60 samples. Even with 32 samples my readings are so stable now i'm seeing .03 swings every now and then instead of .10 The readings would only swing .10 very rarely seems like the liquid was having some capacitance problems ill deal with later. Also in my previous i mentioned the reading would swing by 1.0 i didnt mean 1.0 i meant .10
One thing to be careful of is that the total doesn't exceed the allowable maximum value of the variable you are storing it in. An analogRead() can return a maximum value of 1023, and 32 * 1023 is 32736, just below the maximum value for a signed integer. Any more samples, and you would need to change to either an unsigned integer or long.