I am trying to make a multizone thermostat for a project and want to use millis to delay readings so that user interaction is not inhibited by delays.
The first instance of using millis to replace delay is fine but I'm confused about implementing it again inside the if function* to replace delay(10) because it seems like it's not actually going to enable the processor to do other stuff; it will just cycle pointlessly within that bit of code until it gets all the readings. I'm taking readings from thermistors and apparently the readings can be noisy so I should take averages. Maybe it would be acceptable to just reduce the delay from 10 to 1? Otherwise I don't know how I can get five readings with a small delay between them whilst still responding when a user presses a button.
// at the thermistorReadInterval
if (millis() - previousThermistorReadTime1 >= thermistorReadInterval1) {
previousThermistorReadTime1 = millis();
// take N samples in a row, with a slight delay
for (i = 0; i < NUMSAMPLES; i++) {
samplesFront[i] = analogRead(THERMISTORPINFRONT);
samplesBack[i] = analogRead(THERMISTORPINBACK);
samplesArms[i] = analogRead(THERMISTORPINARMS);
samplesLegs[i] = analogRead(THERMISTORPINLEGS);
delay(10);
}
Serial.println('Front');
averageFrontTemp = samplesToTemp(samplesFront[NUMSAMPLES]);
Serial.println('Back');
averageBackTemp = samplesToTemp(samplesBack[NUMSAMPLES]);
Serial.println('Arms');
averageArmsTemp = samplesToTemp(samplesArms[NUMSAMPLES]);
Serial.println('Legs');
averageLegsTemp = samplesToTemp(samplesLegs[NUMSAMPLES]);
// compare temperature readings to thermostat settings and switch MOSFETs accordingly
if (averageFrontTemp < tempSettingFront) digitalWrite(HEATERMOSFETFRONT, HIGH);
else digitalWrite(HEATERMOSFETFRONT, LOW);
if (averageBackTemp < tempSettingBack) digitalWrite(HEATERMOSFETBACK, HIGH);
else digitalWrite(HEATERMOSFETBACK, LOW);
if (averageArmsTemp < tempSettingArms) digitalWrite(HEATERMOSFETARMS, HIGH);
else digitalWrite(HEATERMOSFETARMS, LOW);
if (averageLegsTemp < tempSettingLegs) digitalWrite(HEATERMOSFETLEGS, HIGH);
else digitalWrite(HEATERMOSFETLEGS, LOW);
}
There is more stuff that happens after the readings are taken.
*am I using the terminology right? The code in question is inside an if function, right?
Why are you passing the first element after the array to the "samplesToTemp()" function?!? That doesn't look at all right. It looks like you are filling an array with samples and then passing an element off the end of the array to a function that calculates an average somehow.
You cannot simply replace the delay by the millis technique. You have to rewrite the code. The for() loop needs to be transformed. To keep it simple, your top level code could be as follows.
Each task can be called as often as possible but they only work when the flags are set and the timing is correct otherwise they return. The timerTask starts the process. The samplingTask collects the samples and sets a flag when the buffer is filled. The averageTask calculates the average and finishes the sequence.
By using static variables inside the task functions we can reuse the variable name for the millis code.
You can add many more task like this without changing the overall timing as long as you have enough time. Most of the time the tasks will simply return doing nothing.
Since you return form inside the first part, it doesn't matter how the second part gets executed, whether as an else part, or just the rest of the function.
This happens in this case, be careful how you extrapolate.
Best: learn these structures, and run you finger through them "playing computer".
Thanks. It makes perfect sense. I have indeed gone through it line by line and I fully understand it (after looking up a couple of things) except for one aspect: sometimes the script returns true or false and I can't see what is happening with that returned value. I understand the flag settings to true and false but, for example, line 25: return true; - what is that doing? Why not just return? Same for lines 42, 52 and 56 - they all return values but to where? As far as I can tell they might as well just say return; because the values true or false aren't going anywhere? Is that correct?
Well that is not a real program, he must be talking about this in general terms.
Do you have a link to this Klaus_K or do I live under a rock everyone knows who he is?
Never mind, I do live under a rock.
In any case, here he makes no use of the returned value, which is fine but does mean, as you figured out, that the function could easily be changed to return void, that is nothing, and just return;, with the signal it is developing being shared as it is now through the setting of a global flag.
I'm at a loss to see why a returned value would be useful. Maybe just because it's near time for more food input to the biological system that carries my brain around.
As alto777 already confirmed they are the same thing. I did not use the else intentionally. The goal of this technique is to avoid nesting if and else statements. e.g., if() inside another if() and so on. It makes the code easier to follow. Compare the two simple examples:
Nested if() example
if ( headLight == working )
{
if ( breakLight == working )
{
if ( turnSignal == working )
{
return carSafeToDrive;
}
}
}
return carNotSafeToDrive;
Inverted Logic example without nesting
if ( headLight != working )
{
return carNotSafeToDrive;
}
if ( breakLight != working )
{
return carNotSafeToDrive;
}
if ( turnSignal != working )
{
return carNotSafeToDrive;
}
return carSafeToDrive;
Sometimes it can be useful to also return a value. It made you think about the code. Well done.