chiark / gitweb /
Merge remote-tracking branch 'origin/Marlin_v1' into Marlin_v1
authorErik van der Zalm <erik@vdzalm.eu>
Mon, 14 Nov 2011 17:26:57 +0000 (18:26 +0100)
committerErik van der Zalm <erik@vdzalm.eu>
Mon, 14 Nov 2011 17:26:57 +0000 (18:26 +0100)
1  2 
Marlin/Configuration.h
Marlin/Marlin.pde
Marlin/temperature.cpp

Simple merge
Simple merge
index 3e6edeec9acf267199abfb7abb7e9642f4bdff92,ac299399dc1049236c31e09b5b2e430dc514e223..89ee47d8470e2374c54034ed634d495ed6378b5f
 -/*\r
 -  temperature.c - temperature control\r
 -  Part of Marlin\r
 -  \r
 - Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm\r
 - \r
 - This program is free software: you can redistribute it and/or modify\r
 - it under the terms of the GNU General Public License as published by\r
 - the Free Software Foundation, either version 3 of the License, or\r
 - (at your option) any later version.\r
 - \r
 - This program is distributed in the hope that it will be useful,\r
 - but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 - GNU General Public License for more details.\r
 - \r
 - You should have received a copy of the GNU General Public License\r
 - along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
 - */\r
 -\r
 -/*\r
 - This firmware is a mashup between Sprinter and grbl.\r
 -  (https://github.com/kliment/Sprinter)\r
 -  (https://github.com/simen/grbl/tree)\r
 - \r
 - It has preliminary support for Matthew Roberts advance algorithm \r
 -    http://reprap.org/pipermail/reprap-dev/2011-May/003323.html\r
 -\r
 - This firmware is optimized for gen6 electronics.\r
 - */\r
 -\r
 -#include "fastio.h"\r
 -#include "Configuration.h"\r
 -#include "pins.h"\r
 -#include "Marlin.h"\r
 -#include "ultralcd.h"\r
 -#include "temperature.h"\r
 -#include "watchdog.h"\r
 -\r
 -//===========================================================================\r
 -//=============================public variables============================\r
 -//===========================================================================\r
 -int target_raw[3] = {0, 0, 0};\r
 -int current_raw[3] = {0, 0, 0};\r
 -\r
 -#ifdef PIDTEMP\r
 -  \r
 -  // probably used external\r
 -  float HeaterPower;\r
 -  float pid_setpoint = 0.0;\r
 -\r
 -  \r
 -  float Kp=DEFAULT_Kp;\r
 -  float Ki=DEFAULT_Ki;\r
 -  float Kd=DEFAULT_Kd;\r
 -  float Kc=DEFAULT_Kc;\r
 -#endif //PIDTEMP\r
 -  \r
 -  \r
 -//===========================================================================\r
 -//=============================private variables============================\r
 -//===========================================================================\r
 -static bool temp_meas_ready = false;\r
 -\r
 -static unsigned long previous_millis_heater, previous_millis_bed_heater;\r
 -\r
 -#ifdef PIDTEMP\r
 -  //static cannot be external:\r
 -  static float temp_iState = 0;\r
 -  static float temp_dState = 0;\r
 -  static float pTerm;\r
 -  static float iTerm;\r
 -  static float dTerm;\r
 -  //int output;\r
 -  static float pid_error;\r
 -  static float temp_iState_min;\r
 -  static float temp_iState_max;\r
 -  static float pid_input;\r
 -  static float pid_output;\r
 -  static bool pid_reset;\r
 - \r
 -#endif //PIDTEMP\r
 -  \r
 -#ifdef WATCHPERIOD\r
 -  static int watch_raw[3] = {-1000,-1000,-1000};\r
 -  static unsigned long watchmillis = 0;\r
 -#endif //WATCHPERIOD\r
 -\r
 -#ifdef HEATER_0_MINTEMP\r
 -  static int minttemp_0 = temp2analog(HEATER_0_MINTEMP);\r
 -#endif //MINTEMP\r
 -#ifdef HEATER_0_MAXTEMP\r
 -  static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP);\r
 -#endif //MAXTEMP\r
 -\r
 -#ifdef HEATER_1_MINTEMP\r
 -  static int minttemp_1 = temp2analog(HEATER_1_MINTEMP);\r
 -#endif //MINTEMP\r
 -#ifdef HEATER_1_MAXTEMP\r
 -  static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP);\r
 -#endif //MAXTEMP\r
 -\r
 -#ifdef BED_MINTEMP\r
 -  static int bed_minttemp = temp2analog(BED_MINTEMP);\r
 -#endif //BED_MINTEMP\r
 -#ifdef BED_MAXTEMP\r
 -  static int bed_maxttemp = temp2analog(BED_MAXTEMP);\r
 -#endif //BED_MAXTEMP\r
 -\r
 -//===========================================================================\r
 -//=============================functions         ============================\r
 -//===========================================================================\r
 -  \r
 -void updatePID()\r
 -{\r
 -#ifdef PIDTEMP\r
 -  temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki;\r
 -#endif\r
 -}\r
 -  \r
 -void manage_heater()\r
 -{\r
 -  #ifdef USE_WATCHDOG\r
 -    wd_reset();\r
 -  #endif\r
 -  \r
 -  float pid_input;\r
 -  float pid_output;\r
 -  if(temp_meas_ready != true)   //better readability\r
 -    return; \r
 -\r
 -  CRITICAL_SECTION_START;\r
 -    temp_meas_ready = false;\r
 -  CRITICAL_SECTION_END;\r
 -\r
 -  #ifdef PIDTEMP\r
 -    pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);\r
 -\r
 -    #ifndef PID_OPENLOOP\r
 -        pid_error = pid_setpoint - pid_input;\r
 -        if(pid_error > 10){\r
 -          pid_output = PID_MAX;\r
 -          pid_reset = true;\r
 -        }\r
 -        else if(pid_error < -10) {\r
 -          pid_output = 0;\r
 -          pid_reset = true;\r
 -        }\r
 -        else {\r
 -          if(pid_reset == true) {\r
 -            temp_iState = 0.0;\r
 -            pid_reset = false;\r
 -          }\r
 -          pTerm = Kp * pid_error;\r
 -          temp_iState += pid_error;\r
 -          temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max);\r
 -          iTerm = Ki * temp_iState;\r
 -          //K1 defined in Configuration.h in the PID settings\r
 -          #define K2 (1.0-K1)\r
 -          dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm);\r
 -          temp_dState = pid_input;\r
 -          #ifdef PID_ADD_EXTRUSION_RATE\r
 -            pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high\r
 -          #endif\r
 -          pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX);\r
 -          \r
 -        }\r
 -    #endif //PID_OPENLOOP\r
 -    #ifdef PID_DEBUG\r
 -     //SERIAL_ECHOLN(" PIDDEBUG Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm<<" iTerm "<<iTerm<<" dTerm "<<dTerm);  \r
 -    #endif //PID_DEBUG\r
 -    HeaterPower=pid_output;\r
 -    analogWrite(HEATER_0_PIN, pid_output);\r
 -  #endif //PIDTEMP\r
 -\r
 -  #ifndef PIDTEMP\r
 -    if(current_raw[0] >= target_raw[0])\r
 -    {\r
 -      WRITE(HEATER_0_PIN,LOW);\r
 -    }\r
 -    else \r
 -    {\r
 -      WRITE(HEATER_0_PIN,HIGH);\r
 -    }\r
 -  #endif\r
 -    \r
 -  if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)\r
 -    return;\r
 -  previous_millis_bed_heater = millis();\r
 -  \r
 -  #if TEMP_1_PIN > -1\r
 -    if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED])\r
 -    {\r
 -      WRITE(HEATER_1_PIN,LOW);\r
 -    }\r
 -    else \r
 -    {\r
 -      WRITE(HEATER_1_PIN,HIGH);\r
 -    }\r
 -  #endif\r
 -}\r
 -\r
 -// Takes hot end temperature value as input and returns corresponding raw value. \r
 -// For a thermistor, it uses the RepRap thermistor temp table.\r
 -// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value.\r
 -// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware.\r
 -int temp2analog(int celsius) {\r
 -  #ifdef HEATER_0_USES_THERMISTOR\r
 -    int raw = 0;\r
 -    byte i;\r
 -    \r
 -    for (i=1; i<NUMTEMPS_HEATER_0; i++)\r
 -    {\r
 -      if (heater_0_temptable[i][1] < celsius)\r
 -      {\r
 -        raw = heater_0_temptable[i-1][0] + \r
 -          (celsius - heater_0_temptable[i-1][1]) * \r
 -          (heater_0_temptable[i][0] - heater_0_temptable[i-1][0]) /\r
 -          (heater_0_temptable[i][1] - heater_0_temptable[i-1][1]);  \r
 -        break;\r
 -      }\r
 -    }\r
 -\r
 -    // Overflow: Set to last value in the table\r
 -    if (i == NUMTEMPS_HEATER_0) raw = heater_0_temptable[i-1][0];\r
 -\r
 -    return (1023 * OVERSAMPLENR) - raw;\r
 -  #elif defined HEATER_0_USES_AD595\r
 -    return celsius * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR;\r
 -  #endif\r
 -}\r
 -\r
 -// Takes bed temperature value as input and returns corresponding raw value. \r
 -// For a thermistor, it uses the RepRap thermistor temp table.\r
 -// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value.\r
 -// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware.\r
 -int temp2analogBed(int celsius) {\r
 -  #ifdef BED_USES_THERMISTOR\r
 -\r
 -    int raw = 0;\r
 -    byte i;\r
 -    \r
 -    for (i=1; i<BNUMTEMPS; i++)\r
 -    {\r
 -      if (bedtemptable[i][1] < celsius)\r
 -      {\r
 -        raw = bedtemptable[i-1][0] + \r
 -          (celsius - bedtemptable[i-1][1]) * \r
 -          (bedtemptable[i][0] - bedtemptable[i-1][0]) /\r
 -          (bedtemptable[i][1] - bedtemptable[i-1][1]);\r
 -      \r
 -        break;\r
 -      }\r
 -    }\r
 -\r
 -    // Overflow: Set to last value in the table\r
 -    if (i == BNUMTEMPS) raw = bedtemptable[i-1][0];\r
 -\r
 -    return (1023 * OVERSAMPLENR) - raw;\r
 -  #elif defined BED_USES_AD595\r
 -    return lround(celsius * (1024.0 * OVERSAMPLENR/ (5.0 * 100.0) ) );\r
 -  #endif\r
 -}\r
 -\r
 -// Derived from RepRap FiveD extruder::getTemperature()\r
 -// For hot end temperature measurement.\r
 -float analog2temp(int raw) {\r
 -  #ifdef HEATER_0_USES_THERMISTOR\r
 -    float celsius = 0;\r
 -    byte i;  \r
 -    raw = (1023 * OVERSAMPLENR) - raw;\r
 -    for (i=1; i<NUMTEMPS_HEATER_0; i++)\r
 -    {\r
 -      if (heater_0_temptable[i][0] > raw)\r
 -      {\r
 -        celsius  = heater_0_temptable[i-1][1] + \r
 -          (raw - heater_0_temptable[i-1][0]) * \r
 -          (float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) /\r
 -          (float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]);\r
 -\r
 -        break;\r
 -      }\r
 -    }\r
 -\r
 -    // Overflow: Set to last value in the table\r
 -    if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1];\r
 -\r
 -    return celsius;\r
 -  #elif defined HEATER_0_USES_AD595\r
 -    return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR;\r
 -  #endif\r
 -}\r
 -\r
 -// Derived from RepRap FiveD extruder::getTemperature()\r
 -// For bed temperature measurement.\r
 -float analog2tempBed(int raw) {\r
 -  #ifdef BED_USES_THERMISTOR\r
 -    int celsius = 0;\r
 -    byte i;\r
 -\r
 -    raw = (1023 * OVERSAMPLENR) - raw;\r
 -\r
 -    for (i=1; i<BNUMTEMPS; i++)\r
 -    {\r
 -      if (bedtemptable[i][0] > raw)\r
 -      {\r
 -        celsius  = bedtemptable[i-1][1] + \r
 -          (raw - bedtemptable[i-1][0]) * \r
 -          (bedtemptable[i][1] - bedtemptable[i-1][1]) /\r
 -          (bedtemptable[i][0] - bedtemptable[i-1][0]);\r
 -\r
 -        break;\r
 -      }\r
 -    }\r
 -\r
 -    // Overflow: Set to last value in the table\r
 -    if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1];\r
 -\r
 -    return celsius;\r
 -    \r
 -  #elif defined BED_USES_AD595\r
 -    return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR;\r
 -  #endif\r
 -}\r
 -\r
 -void tp_init()\r
 -{\r
 -  #if (HEATER_0_PIN > -1) \r
 -    SET_OUTPUT(HEATER_0_PIN);\r
 -  #endif  \r
 -  #if (HEATER_1_PIN > -1) \r
 -    SET_OUTPUT(HEATER_1_PIN);\r
 -  #endif  \r
 -  #if (HEATER_2_PIN > -1) \r
 -    SET_OUTPUT(HEATER_2_PIN);\r
 -  #endif  \r
 -\r
 -  #ifdef PIDTEMP\r
 -    temp_iState_min = 0.0;\r
 -    temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki;\r
 -  #endif //PIDTEMP\r
 -\r
 -  // Set analog inputs\r
 -  ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADIF | 0x07;\r
 -  \r
 -  // Use timer0 for temperature measurement\r
 -  // Interleave temperature interrupt with millies interrupt\r
 -  OCR0B = 128;\r
 -  TIMSK0 |= (1<<OCIE0B);  \r
 -}\r
 -\r
 -\r
 -\r
 -void setWatch() \r
 -{  \r
 -#ifdef WATCHPERIOD\r
 -  if(isHeatingHotend0())\r
 -  {\r
 -    watchmillis = max(1,millis());\r
 -    watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0];\r
 -  }\r
 -  else\r
 -  {\r
 -    watchmillis = 0;\r
 -  } \r
 -#endif \r
 -}\r
 -\r
 -\r
 -void disable_heater()\r
 -{\r
 -  #if TEMP_0_PIN > -1\r
 -  target_raw[0]=0;\r
 -   #if HEATER_0_PIN > -1  \r
 -     WRITE(HEATER_0_PIN,LOW);\r
 -   #endif\r
 -  #endif\r
 -     \r
 -  #if TEMP_1_PIN > -1\r
 -    target_raw[1]=0;\r
 -    #if HEATER_1_PIN > -1 \r
 -      WRITE(HEATER_1_PIN,LOW);\r
 -    #endif\r
 -  #endif\r
 -      \r
 -  #if TEMP_2_PIN > -1\r
 -    target_raw[2]=0;\r
 -    #if HEATER_2_PIN > -1  \r
 -      WRITE(HEATER_2_PIN,LOW);\r
 -    #endif\r
 -  #endif \r
 -}\r
 -\r
 -// Timer 0 is shared with millies\r
 -ISR(TIMER0_COMPB_vect)\r
 -{\r
 -  //these variables are only accesible from the ISR, but static, so they don't loose their value\r
 -  static unsigned char temp_count = 0;\r
 -  static unsigned long raw_temp_0_value = 0;\r
 -  static unsigned long raw_temp_1_value = 0;\r
 -  static unsigned long raw_temp_2_value = 0;\r
 -  static unsigned char temp_state = 0;\r
 -  \r
 -  switch(temp_state) {\r
 -    case 0: // Prepare TEMP_0\r
 -      #if (TEMP_0_PIN > -1)\r
 -        #if TEMP_0_PIN < 8\r
 -          DIDR0 = 1 << TEMP_0_PIN; \r
 -        #else\r
 -          DIDR2 = 1<<(TEMP_0_PIN - 8); \r
 -          ADCSRB = 1<<MUX5;\r
 -        #endif\r
 -        ADMUX = ((1 << REFS0) | (TEMP_0_PIN & 0x07));\r
 -        ADCSRA |= 1<<ADSC; // Start conversion\r
 -      #endif\r
 -      #ifdef ULTIPANEL\r
 -        buttons_check();\r
 -      #endif\r
 -      temp_state = 1;\r
 -      break;\r
 -    case 1: // Measure TEMP_0\r
 -      #if (TEMP_0_PIN > -1)\r
 -        raw_temp_0_value += ADC;\r
 -      #endif\r
 -      temp_state = 2;\r
 -      break;\r
 -    case 2: // Prepare TEMP_1\r
 -      #if (TEMP_1_PIN > -1)\r
 -        #if TEMP_1_PIN < 7\r
 -          DIDR0 = 1<<TEMP_1_PIN; \r
 -        #else\r
 -          DIDR2 = 1<<(TEMP_1_PIN - 8); \r
 -          ADCSRB = 1<<MUX5;\r
 -        #endif\r
 -        ADMUX = ((1 << REFS0) | (TEMP_1_PIN & 0x07));\r
 -        ADCSRA |= 1<<ADSC; // Start conversion\r
 -      #endif\r
 -      #ifdef ULTIPANEL\r
 -        buttons_check();\r
 -      #endif\r
 -      temp_state = 3;\r
 -      break;\r
 -    case 3: // Measure TEMP_1\r
 -      #if (TEMP_1_PIN > -1)\r
 -        raw_temp_1_value += ADC;\r
 -      #endif\r
 -      temp_state = 4;\r
 -      break;\r
 -    case 4: // Prepare TEMP_2\r
 -      #if (TEMP_2_PIN > -1)\r
 -        #if TEMP_2_PIN < 7\r
 -          DIDR0 = 1 << TEMP_2_PIN; \r
 -        #else\r
 -          DIDR2 = 1<<(TEMP_2_PIN - 8); \r
 -          ADCSRB = 1<<MUX5;\r
 -        #endif\r
 -        ADMUX = ((1 << REFS0) | (TEMP_2_PIN & 0x07));\r
 -        ADCSRA |= 1<<ADSC; // Start conversion\r
 -      #endif\r
 -      #ifdef ULTIPANEL\r
 -        buttons_check();\r
 -      #endif\r
 -      temp_state = 5;\r
 -      break;\r
 -    case 5: // Measure TEMP_2\r
 -      #if (TEMP_2_PIN > -1)\r
 -        raw_temp_2_value += ADC;\r
 -      #endif\r
 -      temp_state = 0;\r
 -      temp_count++;\r
 -      break;\r
 -    default:\r
 -      SERIAL_ERROR_START;\r
 -      SERIAL_ERRORLNPGM("Temp measurement error!");\r
 -      break;\r
 -  }\r
 -    \r
 -  if(temp_count >= 16) // 6 ms * 16 = 96ms.\r
 -  {\r
 -    #ifdef HEATER_0_USES_AD595\r
 -      current_raw[0] = raw_temp_0_value;\r
 -    #else\r
 -      current_raw[0] = 16383 - raw_temp_0_value;\r
 -    #endif\r
 -    \r
 -    #ifdef HEATER_1_USES_AD595\r
 -      current_raw[2] = raw_temp_2_value;\r
 -    #else\r
 -      current_raw[2] = 16383 - raw_temp_2_value;\r
 -    #endif\r
 -    \r
 -    #ifdef BED_USES_AD595\r
 -      current_raw[1] = raw_temp_1_value;\r
 -    #else\r
 -      current_raw[1] = 16383 - raw_temp_1_value;\r
 -    #endif\r
 -    \r
 -    temp_meas_ready = true;\r
 -    temp_count = 0;\r
 -    raw_temp_0_value = 0;\r
 -    raw_temp_1_value = 0;\r
 -    raw_temp_2_value = 0;\r
 -    #ifdef HEATER_0_MAXTEMP\r
 -      #if (HEATER_0_PIN > -1)\r
 -        if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) {\r
 -          target_raw[TEMPSENSOR_HOTEND_0] = 0;\r
 -          analogWrite(HEATER_0_PIN, 0);\r
 -          SERIAL_ERROR_START;\r
 -          SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MAXTEMP triggered !!");\r
 -          kill();\r
 -        }\r
 -      #endif\r
 -    #endif\r
 -  #ifdef HEATER_1_MAXTEMP\r
 -    #if (HEATER_1_PIN > -1)\r
 -      if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) {\r
 -        target_raw[TEMPSENSOR_HOTEND_1] = 0;\r
 -      if(current_raw[2] >= maxttemp_1) {\r
 -        analogWrite(HEATER_2_PIN, 0);\r
 -        SERIAL_ERROR_START;\r
 -        SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MAXTEMP triggered !!");\r
 -        kill()\r
 -      }\r
 -    #endif\r
 -  #endif //MAXTEMP\r
 -  \r
 -  #ifdef HEATER_0_MINTEMP\r
 -    #if (HEATER_0_PIN > -1)\r
 -      if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) {\r
 -        target_raw[TEMPSENSOR_HOTEND_0] = 0;\r
 -        analogWrite(HEATER_0_PIN, 0);\r
 -        SERIAL_ERROR_START;\r
 -        SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MINTEMP triggered !!");\r
 -        kill();\r
 -      }\r
 -    #endif\r
 -  #endif\r
 -  \r
 -  #ifdef HEATER_1_MINTEMP\r
 -    #if (HEATER_2_PIN > -1)\r
 -      if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) {\r
 -        target_raw[TEMPSENSOR_HOTEND_1] = 0;\r
 -        analogWrite(HEATER_2_PIN, 0);\r
 -        SERIAL_ERROR_START;\r
 -        SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MINTEMP triggered !!");\r
 -        kill();\r
 -      }\r
 -    #endif\r
 -  #endif //MAXTEMP\r
 -  \r
 -  #ifdef BED_MINTEMP\r
 -    #if (HEATER_1_PIN > -1)\r
 -      if(current_raw[1] <= bed_minttemp) {\r
 -        target_raw[1] = 0;\r
 -        WRITE(HEATER_1_PIN, 0);\r
 -        SERIAL_ERROR_START;\r
 -        SERIAL_ERRORLNPGM("Temperatur heated bed switched off. MINTEMP triggered !!");\r
 -        kill();\r
 -      }\r
 -    #endif\r
 -  #endif\r
 -  \r
 -  #ifdef BED_MAXTEMP\r
 -    #if (HEATER_1_PIN > -1)\r
 -      if(current_raw[1] >= bed_maxttemp) {\r
 -        target_raw[1] = 0;\r
 -        WRITE(HEATER_1_PIN, 0);\r
 -        SERIAL_ERROR_START;\r
 -        SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!");\r
 -        kill();\r
 -      }\r
 -    #endif\r
 -  #endif\r
 -  }\r
 -}\r
 -\r
 -\r
 +/*
 +  temperature.c - temperature control
 +  Part of Marlin
 +  
 + Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
 + 
 + This program is free software: you can redistribute it and/or modify
 + it under the terms of the GNU General Public License as published by
 + the Free Software Foundation, either version 3 of the License, or
 + (at your option) any later version.
 + 
 + This program is distributed in the hope that it will be useful,
 + but WITHOUT ANY WARRANTY; without even the implied warranty of
 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + GNU General Public License for more details.
 + 
 + You should have received a copy of the GNU General Public License
 + along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + */
 +
 +/*
 + This firmware is a mashup between Sprinter and grbl.
 +  (https://github.com/kliment/Sprinter)
 +  (https://github.com/simen/grbl/tree)
 + 
 + It has preliminary support for Matthew Roberts advance algorithm 
 +    http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
 +
 + This firmware is optimized for gen6 electronics.
 + */
 +#include <avr/pgmspace.h>
 +
 +#include "fastio.h"
 +#include "Configuration.h"
 +#include "pins.h"
 +#include "Marlin.h"
 +#include "ultralcd.h"
 +#include "temperature.h"
 +#include "watchdog.h"
 +
 +//===========================================================================
 +//=============================public variables============================
 +//===========================================================================
 +int target_raw[3] = {0, 0, 0};
 +int current_raw[3] = {0, 0, 0};
 +
 +#ifdef PIDTEMP
 +  
 +  // probably used external
 +  float HeaterPower;
 +  float pid_setpoint = 0.0;
 +
 +  
 +  float Kp=DEFAULT_Kp;
 +  float Ki=DEFAULT_Ki;
 +  float Kd=DEFAULT_Kd;
 +  #ifdef PID_ADD_EXTRUSION_RATE
 +    float Kc=DEFAULT_Kc;
 +  #endif
 +#endif //PIDTEMP
 +  
 +  
 +//===========================================================================
 +//=============================private variables============================
 +//===========================================================================
 +static bool temp_meas_ready = false;
 +
 +static unsigned long previous_millis_heater, previous_millis_bed_heater;
 +
 +#ifdef PIDTEMP
 +  //static cannot be external:
 +  static float temp_iState = 0;
 +  static float temp_dState = 0;
 +  static float pTerm;
 +  static float iTerm;
 +  static float dTerm;
 +  //int output;
 +  static float pid_error;
 +  static float temp_iState_min;
 +  static float temp_iState_max;
 +  static float pid_input;
 +  static float pid_output;
 +  static bool pid_reset;
 + 
 +#endif //PIDTEMP
 +  
 +#ifdef WATCHPERIOD
 +  static int watch_raw[3] = {-1000,-1000,-1000};
 +  static unsigned long watchmillis = 0;
 +#endif //WATCHPERIOD
 +
 +#ifdef HEATER_0_MINTEMP
 +  static int minttemp_0 = temp2analog(HEATER_0_MINTEMP);
 +#endif //MINTEMP
 +#ifdef HEATER_0_MAXTEMP
 +  static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP);
 +#endif //MAXTEMP
 +
 +#ifdef HEATER_1_MINTEMP
 +  static int minttemp_1 = temp2analog(HEATER_1_MINTEMP);
 +#endif //MINTEMP
 +#ifdef HEATER_1_MAXTEMP
 +  static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP);
 +#endif //MAXTEMP
 +
 +#ifdef BED_MINTEMP
 +  static int bed_minttemp = temp2analog(BED_MINTEMP);
 +#endif //BED_MINTEMP
 +#ifdef BED_MAXTEMP
 +  static int bed_maxttemp = temp2analog(BED_MAXTEMP);
 +#endif //BED_MAXTEMP
 +
 +//===========================================================================
 +//=============================functions         ============================
 +//===========================================================================
 +  
++void updatePID()
++{
++#ifdef PIDTEMP
++  temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki;
++#endif
++}
++  
 +void manage_heater()
 +{
 +  #ifdef USE_WATCHDOG
 +    wd_reset();
 +  #endif
 +  
 +  float pid_input;
 +  float pid_output;
 +  if(temp_meas_ready != true)   //better readability
 +    return; 
 +
 +  CRITICAL_SECTION_START;
 +    temp_meas_ready = false;
 +  CRITICAL_SECTION_END;
 +
 +  #ifdef PIDTEMP
 +    pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);
 +
 +    #ifndef PID_OPENLOOP
 +        pid_error = pid_setpoint - pid_input;
 +        if(pid_error > 10){
 +          pid_output = PID_MAX;
 +          pid_reset = true;
 +        }
 +        else if(pid_error < -10) {
 +          pid_output = 0;
 +          pid_reset = true;
 +        }
 +        else {
 +          if(pid_reset == true) {
 +            temp_iState = 0.0;
 +            pid_reset = false;
 +          }
 +          pTerm = Kp * pid_error;
 +          temp_iState += pid_error;
 +          temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max);
 +          iTerm = Ki * temp_iState;
 +          //K1 defined in Configuration.h in the PID settings
 +          #define K2 (1.0-K1)
 +          dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm);
 +          temp_dState = pid_input;
 +//          #ifdef PID_ADD_EXTRUSION_RATE
 +//            pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high
 +//          #endif
 +          pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX);
 +          
 +        }
 +    #endif //PID_OPENLOOP
 +    #ifdef PID_DEBUG
 +     //SERIAL_ECHOLN(" PIDDEBUG Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm<<" iTerm "<<iTerm<<" dTerm "<<dTerm);  
 +    #endif //PID_DEBUG
 +    HeaterPower=pid_output;
 +    analogWrite(HEATER_0_PIN, pid_output);
 +  #endif //PIDTEMP
 +
 +  #ifndef PIDTEMP
 +    if(current_raw[0] >= target_raw[0])
 +    {
 +      WRITE(HEATER_0_PIN,LOW);
 +    }
 +    else 
 +    {
 +      WRITE(HEATER_0_PIN,HIGH);
 +    }
 +  #endif
 +    
 +  if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
 +    return;
 +  previous_millis_bed_heater = millis();
 +  
 +  #if TEMP_1_PIN > -1
 +    if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED])
 +    {
 +      WRITE(HEATER_1_PIN,LOW);
 +    }
 +    else 
 +    {
 +      WRITE(HEATER_1_PIN,HIGH);
 +    }
 +  #endif
 +}
 +
 +// Takes hot end temperature value as input and returns corresponding raw value. 
 +// For a thermistor, it uses the RepRap thermistor temp table.
 +// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value.
 +// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware.
 +int temp2analog(int celsius) {
 +  #ifdef HEATER_0_USES_THERMISTOR
 +    int raw = 0;
 +    byte i;
 +
 +    for (i=1; i<NUMTEMPS_HEATER_0; i++)
 +    {
 +      if (pgm_read_word(&(heater_0_temptable[i][1])) < celsius)
 +      {
 +        raw = pgm_read_word(&(heater_0_temptable[i-1][0])) + 
 +          (celsius - pgm_read_word(&(heater_0_temptable[i-1][1]))) * 
 +          (pgm_read_word(&(heater_0_temptable[i][0])) - pgm_read_word(&(heater_0_temptable[i-1][0]))) /
 +          (pgm_read_word(&(heater_0_temptable[i][1])) - pgm_read_word(&(heater_0_temptable[i-1][1])));  
 +        break;
 +      }
 +    }
 +
 +    // Overflow: Set to last value in the table
 +    if (i == NUMTEMPS_HEATER_0) raw = pgm_read_word(&(heater_0_temptable[i-1][0]));
 +
 +    return (1023 * OVERSAMPLENR) - raw;
 +  #elif defined HEATER_0_USES_AD595
 +    return celsius * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR;
 +  #endif
 +}
 +
 +// Takes bed temperature value as input and returns corresponding raw value. 
 +// For a thermistor, it uses the RepRap thermistor temp table.
 +// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value.
 +// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware.
 +int temp2analogBed(int celsius) {
 +  #ifdef BED_USES_THERMISTOR
 +
 +    int raw = 0;
 +    byte i;
 +    
 +    for (i=1; i<BNUMTEMPS; i++)
 +    {
 +      if (pgm_read_word(&)bedtemptable[i][1])) < celsius)
 +      {
 +        raw = pgm_read_word(&(bedtemptable[i-1][0])) + 
 +          (celsius - pgm_read_word(&(bedtemptable[i-1][1]))) * 
 +          (pgm_read_word(&(bedtemptable[i][0])) - pgm_read_word(&(bedtemptable[i-1][0]))) /
 +          (pgm_read_word(&(bedtemptable[i][1])) - pgm_read_word(&(bedtemptable[i-1][1])));
 +      
 +        break;
 +      }
 +    }
 +
 +    // Overflow: Set to last value in the table
 +    if (i == BNUMTEMPS) raw = pgm_read_word(&(bedtemptable[i-1][0]));
 +
 +    return (1023 * OVERSAMPLENR) - raw;
 +  #elif defined BED_USES_AD595
 +    return lround(celsius * (1024.0 * OVERSAMPLENR/ (5.0 * 100.0) ) );
 +  #endif
 +}
 +
 +// Derived from RepRap FiveD extruder::getTemperature()
 +// For hot end temperature measurement.
 +float analog2temp(int raw) {
 +  #ifdef HEATER_0_USES_THERMISTOR
 +    float celsius = 0;
 +    byte i;  
 +    raw = (1023 * OVERSAMPLENR) - raw;
 +    for (i=1; i<NUMTEMPS_HEATER_0; i++)
 +    {
 +      if ((short)pgm_read_word(&heater_0_temptable[i][0]) > raw)
 +      {
 +        celsius  = (short)pgm_read_word(&heater_0_temptable[i-1][1]) + 
 +          (raw - (short)pgm_read_word(&heater_0_temptable[i-1][0])) * 
 +          (float)((short)pgm_read_word(&heater_0_temptable[i][1]) - (short)pgm_read_word(&heater_0_temptable[i-1][1])) /
 +          (float)((short)pgm_read_word(&heater_0_temptable[i][0]) - (short)pgm_read_word(&heater_0_temptable[i-1][0]));
 +        break;
 +      }
 +    }
 +
 +    // Overflow: Set to last value in the table
 +    if (i == NUMTEMPS_HEATER_0) celsius = (short)pgm_read_word(&(heater_0_temptable[i-1][1]));
 +
 +    return celsius;
 +  #elif defined HEATER_0_USES_AD595
 +    return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR;
 +  #endif
 +}
 +
 +// Derived from RepRap FiveD extruder::getTemperature()
 +// For bed temperature measurement.
 +float analog2tempBed(int raw) {
 +  #ifdef BED_USES_THERMISTOR
 +    int celsius = 0;
 +    byte i;
 +
 +    raw = (1023 * OVERSAMPLENR) - raw;
 +
 +    for (i=1; i<BNUMTEMPS; i++)
 +    {
 +      if (pgm_read_word(&(bedtemptable[i][0])) > raw)
 +      {
 +        celsius  = pgm_read_word(&(bedtemptable[i-1][1])) + 
 +          (raw - pgm_read_word(&(bedtemptable[i-1][0]))) * 
 +          (pgm_read_word(&(bedtemptable[i][1])) - pgm_read_word(&(bedtemptable[i-1][1]))) /
 +          (pgm_read_word(&(bedtemptable[i][0])) - pgm_read_word(&(bedtemptable[i-1][0])));
 +
 +        break;
 +      }
 +    }
 +
 +    // Overflow: Set to last value in the table
 +    if (i == BNUMTEMPS) celsius = pgm_read_word(&(bedtemptable[i-1][1]));
 +
 +    return celsius;
 +    
 +  #elif defined BED_USES_AD595
 +    return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR;
 +  #endif
 +}
 +
 +void tp_init()
 +{
 +  #if (HEATER_0_PIN > -1) 
 +    SET_OUTPUT(HEATER_0_PIN);
 +  #endif  
 +  #if (HEATER_1_PIN > -1) 
 +    SET_OUTPUT(HEATER_1_PIN);
 +  #endif  
 +  #if (HEATER_2_PIN > -1) 
 +    SET_OUTPUT(HEATER_2_PIN);
 +  #endif  
 +
 +  #ifdef PIDTEMP
 +    temp_iState_min = 0.0;
 +    temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki;
 +  #endif //PIDTEMP
 +
 +  // Set analog inputs
 +  ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADIF | 0x07;
 +  
 +  // Use timer0 for temperature measurement
 +  // Interleave temperature interrupt with millies interrupt
 +  OCR0B = 128;
 +  TIMSK0 |= (1<<OCIE0B);  
 +}
 +
 +
 +
 +void setWatch() 
 +{  
 +#ifdef WATCHPERIOD
 +  if(isHeatingHotend0())
 +  {
 +    watchmillis = max(1,millis());
 +    watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0];
 +  }
 +  else
 +  {
 +    watchmillis = 0;
 +  } 
 +#endif 
 +}
 +
 +
 +void disable_heater()
 +{
 +  #if TEMP_0_PIN > -1
 +  target_raw[0]=0;
 +   #if HEATER_0_PIN > -1  
 +     WRITE(HEATER_0_PIN,LOW);
 +   #endif
 +  #endif
 +     
 +  #if TEMP_1_PIN > -1
 +    target_raw[1]=0;
 +    #if HEATER_1_PIN > -1 
 +      WRITE(HEATER_1_PIN,LOW);
 +    #endif
 +  #endif
 +      
 +  #if TEMP_2_PIN > -1
 +    target_raw[2]=0;
 +    #if HEATER_2_PIN > -1  
 +      WRITE(HEATER_2_PIN,LOW);
 +    #endif
 +  #endif 
 +}
 +
 +// Timer 0 is shared with millies
 +ISR(TIMER0_COMPB_vect)
 +{
 +  //these variables are only accesible from the ISR, but static, so they don't loose their value
 +  static unsigned char temp_count = 0;
 +  static unsigned long raw_temp_0_value = 0;
 +  static unsigned long raw_temp_1_value = 0;
 +  static unsigned long raw_temp_2_value = 0;
 +  static unsigned char temp_state = 0;
 +  
 +  switch(temp_state) {
 +    case 0: // Prepare TEMP_0
 +      #if (TEMP_0_PIN > -1)
 +        #if TEMP_0_PIN < 8
 +          DIDR0 = 1 << TEMP_0_PIN; 
 +        #else
 +          DIDR2 = 1<<(TEMP_0_PIN - 8); 
 +          ADCSRB = 1<<MUX5;
 +        #endif
 +        ADMUX = ((1 << REFS0) | (TEMP_0_PIN & 0x07));
 +        ADCSRA |= 1<<ADSC; // Start conversion
 +      #endif
 +      #ifdef ULTIPANEL
 +        buttons_check();
 +      #endif
 +      temp_state = 1;
 +      break;
 +    case 1: // Measure TEMP_0
 +      #if (TEMP_0_PIN > -1)
 +        raw_temp_0_value += ADC;
 +      #endif
 +      temp_state = 2;
 +      break;
 +    case 2: // Prepare TEMP_1
 +      #if (TEMP_1_PIN > -1)
 +        #if TEMP_1_PIN < 7
 +          DIDR0 = 1<<TEMP_1_PIN; 
 +        #else
 +          DIDR2 = 1<<(TEMP_1_PIN - 8); 
 +          ADCSRB = 1<<MUX5;
 +        #endif
 +        ADMUX = ((1 << REFS0) | (TEMP_1_PIN & 0x07));
 +        ADCSRA |= 1<<ADSC; // Start conversion
 +      #endif
 +      #ifdef ULTIPANEL
 +        buttons_check();
 +      #endif
 +      temp_state = 3;
 +      break;
 +    case 3: // Measure TEMP_1
 +      #if (TEMP_1_PIN > -1)
 +        raw_temp_1_value += ADC;
 +      #endif
 +      temp_state = 4;
 +      break;
 +    case 4: // Prepare TEMP_2
 +      #if (TEMP_2_PIN > -1)
 +        #if TEMP_2_PIN < 7
 +          DIDR0 = 1 << TEMP_2_PIN; 
 +        #else
 +          DIDR2 = 1<<(TEMP_2_PIN - 8); 
 +          ADCSRB = 1<<MUX5;
 +        #endif
 +        ADMUX = ((1 << REFS0) | (TEMP_2_PIN & 0x07));
 +        ADCSRA |= 1<<ADSC; // Start conversion
 +      #endif
 +      #ifdef ULTIPANEL
 +        buttons_check();
 +      #endif
 +      temp_state = 5;
 +      break;
 +    case 5: // Measure TEMP_2
 +      #if (TEMP_2_PIN > -1)
 +        raw_temp_2_value += ADC;
 +      #endif
 +      temp_state = 0;
 +      temp_count++;
 +      break;
 +    default:
 +      SERIAL_ERROR_START;
 +      SERIAL_ERRORLNPGM("Temp measurement error!");
 +      break;
 +  }
 +    
 +  if(temp_count >= 16) // 6 ms * 16 = 96ms.
 +  {
 +    #ifdef HEATER_0_USES_AD595
 +      current_raw[0] = raw_temp_0_value;
 +    #else
 +      current_raw[0] = 16383 - raw_temp_0_value;
 +    #endif
 +    
 +    #ifdef HEATER_1_USES_AD595
 +      current_raw[2] = raw_temp_2_value;
 +    #else
 +      current_raw[2] = 16383 - raw_temp_2_value;
 +    #endif
 +    
 +    #ifdef BED_USES_AD595
 +      current_raw[1] = raw_temp_1_value;
 +    #else
 +      current_raw[1] = 16383 - raw_temp_1_value;
 +    #endif
 +    
 +    temp_meas_ready = true;
 +    temp_count = 0;
 +    raw_temp_0_value = 0;
 +    raw_temp_1_value = 0;
 +    raw_temp_2_value = 0;
 +    #ifdef HEATER_0_MAXTEMP
 +      #if (HEATER_0_PIN > -1)
 +        if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) {
 +          target_raw[TEMPSENSOR_HOTEND_0] = 0;
 +          analogWrite(HEATER_0_PIN, 0);
 +          SERIAL_ERROR_START;
 +          SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MAXTEMP triggered !!");
 +          kill();
 +        }
 +      #endif
 +    #endif
 +  #ifdef HEATER_1_MAXTEMP
 +    #if (HEATER_1_PIN > -1)
 +      if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) {
 +        target_raw[TEMPSENSOR_HOTEND_1] = 0;
 +      if(current_raw[2] >= maxttemp_1) {
 +        analogWrite(HEATER_2_PIN, 0);
 +        SERIAL_ERROR_START;
 +        SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MAXTEMP triggered !!");
 +        kill()
 +      }
 +    #endif
 +  #endif //MAXTEMP
 +  
 +  #ifdef HEATER_0_MINTEMP
 +    #if (HEATER_0_PIN > -1)
 +      if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) {
 +        target_raw[TEMPSENSOR_HOTEND_0] = 0;
 +        analogWrite(HEATER_0_PIN, 0);
 +        SERIAL_ERROR_START;
 +        SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MINTEMP triggered !!");
 +        kill();
 +      }
 +    #endif
 +  #endif
 +  
 +  #ifdef HEATER_1_MINTEMP
 +    #if (HEATER_2_PIN > -1)
 +      if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) {
 +        target_raw[TEMPSENSOR_HOTEND_1] = 0;
 +        analogWrite(HEATER_2_PIN, 0);
 +        SERIAL_ERROR_START;
 +        SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MINTEMP triggered !!");
 +        kill();
 +      }
 +    #endif
 +  #endif //MAXTEMP
 +  
 +  #ifdef BED_MINTEMP
 +    #if (HEATER_1_PIN > -1)
 +      if(current_raw[1] <= bed_minttemp) {
 +        target_raw[1] = 0;
 +        WRITE(HEATER_1_PIN, 0);
 +        SERIAL_ERROR_START;
 +        SERIAL_ERRORLNPGM("Temperatur heated bed switched off. MINTEMP triggered !!");
 +        kill();
 +      }
 +    #endif
 +  #endif
 +  
 +  #ifdef BED_MAXTEMP
 +    #if (HEATER_1_PIN > -1)
 +      if(current_raw[1] >= bed_maxttemp) {
 +        target_raw[1] = 0;
 +        WRITE(HEATER_1_PIN, 0);
 +        SERIAL_ERROR_START;
 +        SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!");
 +        kill();
 +      }
 +    #endif
 +  #endif
 +  }
 +}
 +
 +