Log #3: Firmware

A project log for YATSS (Yet another T12 soldering station)

An arduino-based temperature controlled soldering station for the ubiquitous T12 clones.

JoelJoel 02/20/2019 at 17:380 Comments

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

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
      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.