The firmware for this project is pretty straight forward, so I won't be cover it all, but I will discuss some of the code, and in a later log, I'll discuss what's left to implement and what I might re-implement in a later version.
Rolling average for analog inputs:
int temp_values[10];
int getTemp(int arr[]) {
long temp_value = 0;
for (int i = 0; i < 10; i++) { // loop through the array and sum values
temp_value += arr[i];
}
for (int i = 9; i > 0; i--) { // move the values along
arr[i] = arr[i-1];
}
arr[0] = analogRead(TEMP_SENS);
temp_value /= 10; // average the adc inputs
return tempCurve(temp_value, cal);
}
This function takes an input (from the temperature sensor amplifier) and returns an average of the last 10 readings (in C, through the function tempCurve. Note that the sensor is polled once per loop. This was done to smooth out the readings, without slowing down the loop with nested loops. But as you can see, there are still two loops, so it would probably be faster to simple poll the sensor 10 times and average it. This might be changed in a future version, but probably not, because as we will see later on, we have too much time on our hands already.
Converting to C:
int temp_multiplier = 91; // adjust slope of temp curve
const float adc_voltage = 0.0049; // 5V / 1023 = 0.0049 = volts/adc-step
int tempCurve(int in, int offset) {
float k = adc_voltage * temp_multiplier;
// the linear expression for the temperature is: (adc_voltage*temp_multiplier*adc_in) + offset (offset is ambient + cal)
// it is required that the output from the thermocouple amp is 1V/100C
in = (k * in) + offset;
return int(in);
}
This function takes the the raw value from the ADC and converts it to C. Ideally the temp_multiplier would be 100, since we were aiming for 1V/100C from the temp amplifier. Since we are a little of because of non-ideal component values, I've tweaked it to got a close match across the entire temperature range. This will be solved when the calibration function is implemented.
Waiting for temperature reading to settle:
if (current_time - sense_start < sense_time) {
// sense
//Serial.println("Sensing");
if (current_time - sense_start > settle_time) {
actual_temp = getTemp(temp_values);
}
}
This is probably the trickest problem so far, and something I don't know the cause of yet. When the power is removed from the the heater, it takes a while for the sense voltage from the op-amp to settle back down, which means we have to wait before sampling the temperature of the iron. We could sense immediately, but that would cause problems in the next part of the code.
power_time = (set_temp - actual_temp) * 50; power_time = min(power_time, 1000);
This calculation simply checks how far from the set point we are and sets the time for the iron to be on before shutting down again to measure the temperature. If we were to measure immediately, we would start at the measured temp being above the set temp, and keep measuring until the actual temperature was under the set temp, but since the temperature decreases over time, we would always end up powering on the iron the minimum time, because the measured temp is only a tiny bit below the set temp.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.