Browse Source

Revert "Revert "Mk3 bed fast pwm""

PavelSindler 5 years ago
parent
commit
2ea34d21e7
3 changed files with 135 additions and 9 deletions
  1. 30 7
      Firmware/temperature.cpp
  2. 2 2
      Firmware/temperature.h
  3. 103 0
      Firmware/timer02.c

+ 30 - 7
Firmware/temperature.cpp

@@ -45,6 +45,12 @@
 #include "Configuration_prusa.h"
 
 
+extern "C" {
+extern void timer02_init(void);
+extern void timer02_set_pwm0(uint8_t pwm0);
+}
+
+
 //===========================================================================
 //=============================public variables============================
 //===========================================================================
@@ -257,6 +263,7 @@ static void temp_runaway_stop(bool isPreheat, bool isBed);
   if (extruder<0)
   {
      soft_pwm_bed = (MAX_BED_POWER)/2;
+	 timer02_set_pwm0(soft_pwm_bed << 1);
      bias = d = (MAX_BED_POWER)/2;
    }
    else
@@ -293,7 +300,10 @@ static void temp_runaway_stop(bool isPreheat, bool isBed);
         if(millis() - t2 > 5000) { 
           heating=false;
           if (extruder<0)
+		  {
             soft_pwm_bed = (bias - d) >> 1;
+			timer02_set_pwm0(soft_pwm_bed << 1);
+		  }
           else
             soft_pwm[extruder] = (bias - d) >> 1;
           t1=millis();
@@ -347,7 +357,10 @@ static void temp_runaway_stop(bool isPreheat, bool isBed);
             }
           }
           if (extruder<0)
+		  {
             soft_pwm_bed = (bias + d) >> 1;
+			timer02_set_pwm0(soft_pwm_bed << 1);
+		  }
           else
             soft_pwm[extruder] = (bias + d) >> 1;
           pid_cycle++;
@@ -781,9 +794,11 @@ void manage_heater()
 	  if(current_temperature_bed < BED_MAXTEMP)
 	  {
 	    soft_pwm_bed = (int)pid_output >> 1;
+		timer02_set_pwm0(soft_pwm_bed << 1);
 	  }
 	  else {
 	    soft_pwm_bed = 0;
+		timer02_set_pwm0(soft_pwm_bed << 1);
 	  }
 
     #elif !defined(BED_LIMIT_SWITCHING)
@@ -793,15 +808,18 @@ void manage_heater()
         if(current_temperature_bed >= target_temperature_bed)
         {
           soft_pwm_bed = 0;
+		  timer02_set_pwm0(soft_pwm_bed << 1);
         }
         else 
         {
           soft_pwm_bed = MAX_BED_POWER>>1;
+		  timer02_set_pwm0(soft_pwm_bed << 1);
         }
       }
       else
       {
         soft_pwm_bed = 0;
+		timer02_set_pwm0(soft_pwm_bed << 1);
         WRITE(HEATER_BED_PIN,LOW);
       }
     #else //#ifdef BED_LIMIT_SWITCHING
@@ -811,15 +829,18 @@ void manage_heater()
         if(current_temperature_bed > target_temperature_bed + BED_HYSTERESIS)
         {
           soft_pwm_bed = 0;
+		  timer02_set_pwm0(soft_pwm_bed << 1);
         }
         else if(current_temperature_bed <= target_temperature_bed - BED_HYSTERESIS)
         {
           soft_pwm_bed = MAX_BED_POWER>>1;
+          timer02_set_pwm0(soft_pwm_bed << 1);
         }
       }
       else
       {
         soft_pwm_bed = 0;
+		timer02_set_pwm0(soft_pwm_bed << 1);
         WRITE(HEATER_BED_PIN,LOW);
       }
     #endif
@@ -996,7 +1017,6 @@ static void updateTemperaturesFromRawValues()
     CRITICAL_SECTION_END;
 }
 
-
 void tp_init()
 {
 #if MB(RUMBA) && ((TEMP_SENSOR_0==-1)||(TEMP_SENSOR_1==-1)||(TEMP_SENSOR_2==-1)||(TEMP_SENSOR_BED==-1))
@@ -1063,10 +1083,12 @@ void tp_init()
 
   adc_init();
 
+  timer02_init();
+
   // Use timer0 for temperature measurement
   // Interleave temperature interrupt with millies interrupt
-  OCR0B = 128;
-  TIMSK0 |= (1<<OCIE0B);  
+  OCR2B = 128;
+  TIMSK2 |= (1<<OCIE2B);  
   
   // Wait for temperature measurement to settle
   delay(250);
@@ -1374,6 +1396,7 @@ void disable_heater()
   #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
     target_temperature_bed=0;
     soft_pwm_bed=0;
+	timer02_set_pwm0(soft_pwm_bed << 1);
     #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1  
       WRITE(HEATER_BED_PIN,LOW);
     #endif
@@ -1538,8 +1561,8 @@ void adc_ready(void) //callback from adc when sampling finished
 } // extern "C"
 
 
-// Timer 0 is shared with millies
-ISR(TIMER0_COMPB_vect)                            // @ 1kHz ~ 1ms
+// Timer2 (originaly timer0) is shared with millies
+ISR(TIMER2_COMPB_vect)
 {
 	static bool _lock = false;
 	if (_lock) return;
@@ -1606,7 +1629,7 @@ ISR(TIMER0_COMPB_vect)                            // @ 1kHz ~ 1ms
 #endif
 #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
     soft_pwm_b = soft_pwm_bed;
-    if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
+    //if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
 #endif
 #ifdef FAN_SOFT_PWM
     soft_pwm_fan = fanSpeedSoftPwm / 2;
@@ -1740,7 +1763,7 @@ ISR(TIMER0_COMPB_vect)                            // @ 1kHz ~ 1ms
 	  state_timer_heater_b = MIN_STATE_TIME;
 	}
 	state_heater_b = 1;
-	WRITE(HEATER_BED_PIN, 1);
+	//WRITE(HEATER_BED_PIN, 1);
       }
     } else {
       // turn OFF heather only if the minimum time is up 

+ 2 - 2
Firmware/temperature.h

@@ -27,8 +27,8 @@
   #include "stepper.h"
 #endif
 
-#define ENABLE_TEMPERATURE_INTERRUPT()  TIMSK0 |= (1<<OCIE0B)
-#define DISABLE_TEMPERATURE_INTERRUPT() TIMSK0 &= ~(1<<OCIE0B)
+#define ENABLE_TEMPERATURE_INTERRUPT()  TIMSK2 |= (1<<OCIE2B)
+#define DISABLE_TEMPERATURE_INTERRUPT() TIMSK2 &= ~(1<<OCIE2B)
 
 // public functions
 void tp_init();  //initialize the heating

+ 103 - 0
Firmware/timer02.c

@@ -0,0 +1,103 @@
+//timer02.c
+// use atmega timer2 as main system timer instead of timer0
+// timer0 is used for fast pwm (OC0B output)
+// original OVF handler is disabled
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <Arduino.h>
+
+
+uint8_t timer02_pwm0 = 0;
+
+void timer02_set_pwm0(uint8_t pwm0)
+{
+	if (timer02_pwm0 == pwm0) return;
+	if (pwm0)
+	{
+		TCCR0A |= (2 << COM0B0);
+		OCR0B = pwm0 - 1;
+	}
+	else
+	{
+		TCCR0A &= ~(2 << COM0B0);
+		OCR0B = 0;
+	}
+}
+
+void timer02_init(void)
+{
+	//save sreg
+	uint8_t _sreg = SREG;
+	//disable interrupts for sure
+	cli();
+	//mask timer0 interrupts - disable all
+	TIMSK0 &= ~(1<<TOIE0);
+	TIMSK0 &= ~(1<<OCIE0A);
+	TIMSK0 &= ~(1<<OCIE0B);
+	//setup timer0
+	TCCR0A = 0x00; //COM_A-B=00, WGM_0-1=00
+	TCCR0B = (1 << CS00); //WGM_2=0, CS_0-2=011
+	//switch timer0 to fast pwm mode
+	TCCR0A |= (3 << WGM00); //WGM_0-1=11
+	//set OCR0B register to zero
+	OCR0B = 0;
+	//disable OCR0B output (will be enabled in timer02_set_pwm0)
+	TCCR0A &= ~(2 << COM0B0);
+	//setup timer2
+	TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00
+	TCCR2B = (3 << CS20); //WGM_2=0, CS_0-2=011
+	//mask timer2 interrupts - enable OVF, disable others
+	TIMSK2 |= (1<<TOIE2);
+	TIMSK2 &= ~(1<<OCIE2A);
+	TIMSK2 &= ~(1<<OCIE2B);
+	//set timer2 OCR registers (OCRB interrupt generated 0.5ms after OVF interrupt)
+	OCR2A = 0;
+	OCR2B = 128;
+	//restore sreg (enable interrupts)
+	SREG = _sreg;
+}
+
+
+//following code is OVF handler for timer 2
+//it is copy-paste from wiring.c and modified for timer2
+//variables timer0_overflow_count and timer0_millis are declared in wiring.c
+
+
+
+// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
+// the overflow handler is called every 256 ticks.
+#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
+
+// the whole number of milliseconds per timer0 overflow
+#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
+
+// the fractional number of milliseconds per timer0 overflow. we shift right
+// by three to fit these numbers into a byte. (for the clock speeds we care
+// about - 8 and 16 MHz - this doesn't lose precision.)
+#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
+#define FRACT_MAX (1000 >> 3)
+
+extern volatile unsigned long timer0_overflow_count;
+extern volatile unsigned long timer0_millis;
+unsigned char timer0_fract = 0;
+
+ISR(TIMER2_OVF_vect)
+{
+	// copy these to local variables so they can be stored in registers
+	// (volatile variables must be read from memory on every access)
+	unsigned long m = timer0_millis;
+	unsigned char f = timer0_fract;
+
+	m += MILLIS_INC;
+	f += FRACT_INC;
+	if (f >= FRACT_MAX)
+	{
+		f -= FRACT_MAX;
+		m += 1;
+	}
+
+	timer0_fract = f;
+	timer0_millis = m;
+	timer0_overflow_count++;
+}
+