I've learned about bang-bang controllers in satellite positioning: give it one bang into the desired direction, then another bang to stop it there. The trick, as opposed to simple hysteresis-based controllers, is the time of the second bang, that shall stop the system at the right value. Such an application requires a valid model for the prediction of the dynamic behaviour of the object, and turns out to be a special case of a state regulator.
In your case you should know how the temperature evolves with a certain (typically maximal) heating, and how it behaves (over time) when heating is turned off again. You can get an estimation of the delays by monitoring the temperature after the heater is turned on or off, and adjust the delays accordingly (dynamic adaptation).
With two temperatures, taken at the heater and the interesting distant position (lead surface), you can try to determine the exponential function e^-(t/tau) that predicts the temperature at the distant position. You may notice that this function varies depending on what "load" is applied to the surface.
In a simpler model you can determine the over/undershoot, occurring after the heater is turned on or off, and adjust the switch points (hysteresis) dynamically, to minimize the overshoots. This way you'll end up in kind of a PWM controller, with both adjustable frequency and duty cycle. But if you want proper feedback about the overshoots, the frequency should be low enough to allow for taking the dynamic behaviour of the controlled system. Here the uncertainty (noise...) of the temperature measurement should be taken into account, so that a reasonable temperature difference (several degrees or ADC steps) must be allowed. Then the low PWM frequency is an immediate result of the allowed deviation, deserving no further adjustment or calculations.
Perhaps this restriction (temperature measurement) causes trouble in your PID controller, and you could make it work by filtering the temperature readings before feeding them into the PID.
So, bang-bang is essentially educated guessing (or trial and error) of timing of the on's and off's of the relay. If I'm understanding right, unfortunately, that kind of system wont work for my application unless additional sensors to determine the physical size of the load (amount of lead being heated), or someone monitors and adjusts it during use (defeats the purpose of the controller), as the load size varies during operation (2 to 20 lbs). As well, the PID will be used to control at least 2 devices, and it doesnt look like its practical to use the same bang-bang system for both devices
Thank you for your explanation, if that was a usable option for me, that would have been almost everything I needed to get a working program going.
I have since added another 0 to the Ki dividers in AdjMenu() and increased the definition in the Ki adjustments (+- .01 instead of +_ .1). This seems to have made tuning easier, but since the heat up time of the process is about 20-30 mins, it will be some time before I know if those adjustments make it good enough to use.
Still, the AutoTune library is probably the next addition I will make, once I have the SRAM freed up and I figure out how to make AutoTune work with a relay (I've put 0 effort into this so far, bigger fish).
I do kind of filter the temperature readings before feeding them to the PID, they get averaged, 4 a second, before being assigned to Input. Id like to make it faster (say, about 8-10 a second), but that is a limitation of the 6675, it wont properly return results faster than 200ms, and even that was iffy, so I made it 250ms instead, that fixed all trouble with bad returns. If you meant real filtering (tossing out numbers that dont fit in the expected range), I dont think its possible to setup a filter narrow enough to allow the real readings and discard the fluctuations, since the noise fluctuations are typically only 1 ADC step or less (does that even count as a noise fluctuation?)
Using the F() macro for a single character is a waste of space. Use single quotes around single characters.
If you can convert your floating point calculations to integers you will save a lot of space. You must do it everywhere. The floating point system uses functions so if you use a division operation once it must compile the division function but using it twice doesn't add another copy of the function.
Thanks for the clarification on the F() macro, I didn't know it wasn't needed for single chars.
I'll give my code another good once-over to see if there are any more variables I can demote. Some of them can't be, they need the decimal resolution. The Kp, Ki, and Kd values for instance, need to be decimal values, and when I tried to make them anything but double or float, they basically got chopped to an int (not even any rounding, not that I'd expect it). I thought I remember reading not to use float, due to limitations of the mcu, so they ended up being double (not sure why it seems to be acceptable to use double in place of float, same thing, just bigger, isn't it?). I would REALLY appreciate a better solution to this, as I am almost certain I don't actually need the resolution of a double, really all the variables need to hold is "x.xx", two decimal places and one whole number.
Ill check into the setCursor when I dive back into the oled library, your probably right, that seems like it would be a logical step when clearing the screen. I never actually checked it.
For the rest of it, "just a thought" and down, I don't understand how adding a variable helps me lower SRAM usage or makes it easier to add the features I'd like to add. It does make that section a little more understandable (with the proper changes to the operation orders), but seems to be a step backwards in regards to my goals.
The if statement change doesn't seem to add any benefit either, am I missing something deeper in the compiler that makes using the elseif version better? The results are identical with either method (both conditionals will never be true at the same time).
Thanks to all for your input so far. One thing to note: Program/Sketch size is not an issue, I am only using about 60% of the nano's flash memory. The big issue is SRAM, sitting at about 94% used. While making the sketch smaller cant hurt, I'd happily make it larger to decrease SRAM usage. Sorry if it was unclear that program size is not the issue I am having, hopefully this clears that up.