It is much easier to work with unitless quantities, expressing the error as a fraction. Otherwise it is more difficult to interpret the values of the coefficients Ki,Kd; then also your ouput variable will contain temperature units and as Tomorokoshi pointed out you cannot assign it directly to a pwm.
Here is a modified version:
error_4 = (Setpoint_Temp - temperature)/temperature; //normalized error (-1 to +1)
integral_4 = integral_4 + (error_4 * dt_4*ki); // 1/ki is the integration characteristic time
if (integral_4>1) integral_4=1; //integral windup protection
if (integral_4<-1) integral_4=-1;
derivative_4 = - (error_4 - previous_err_4)*kd/dt_4;
output_4 = (kp * error_4) + integral_4 + derivative_4;
previous_err_4 = error_4;
if (output_4>1) output_4=1; //limit the output to 0-1 interval
if (output_4<0) output_4=0;
TIMER_16_PWM = 0xFFFF * output_4; // put into timer 16 bit PWM register
Here kp,ki, kd have clear definitions. kp gives the percentage of the output for 100% error, if dt_4 is the loop time then ki is the inverse of the time needed for the integral to reach 1 for a 100% error. I have integrated ki in the integral definition so the integral is now unitless too. Limiting the integral to +/-1 will help at startup (
https://en.wikipedia.org/wiki/Integral_windup).
Edit: My controllers work in Kelvin, if you use a different unit it will be better to normalize the error in a different way, something like
error_4 = (Setpoint_Temp - temperature)/max_temperature_error