Browse Source

Merge pull request #6100 from thinkyhead/rc_soft_pwm_dither

Enhancement of PWM, with dithering
Scott Lahteine 7 years ago
parent
commit
5a2abeca78
2 changed files with 71 additions and 53 deletions
  1. 6
    0
      Marlin/Configuration.h
  2. 65
    53
      Marlin/temperature.cpp

+ 6
- 0
Marlin/Configuration.h View File

1425
 // at zero value, there are 128 effective control positions.
1425
 // at zero value, there are 128 effective control positions.
1426
 #define SOFT_PWM_SCALE 0
1426
 #define SOFT_PWM_SCALE 0
1427
 
1427
 
1428
+// If SOFT_PWM_SCALE is set to a value higher than 0, dithering can
1429
+// be used to mitigate the associated resolution loss. If enabled,
1430
+// some of the PWM cycles are stretched so on average the wanted
1431
+// duty cycle is attained.
1432
+//#define SOFT_PWM_DITHER
1433
+
1428
 // Temperature status LEDs that display the hotend and bed temperature.
1434
 // Temperature status LEDs that display the hotend and bed temperature.
1429
 // If all hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on.
1435
 // If all hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on.
1430
 // Otherwise the RED led is on. There is 1C hysteresis.
1436
 // Otherwise the RED led is on. There is 1C hysteresis.

+ 65
- 53
Marlin/temperature.cpp View File

1512
   static uint8_t temp_count = 0;
1512
   static uint8_t temp_count = 0;
1513
   static TempState temp_state = StartupDelay;
1513
   static TempState temp_state = StartupDelay;
1514
   static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
1514
   static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
1515
+  // avoid multiple loads of pwm_count
1516
+  uint8_t pwm_count_tmp = pwm_count;
1515
 
1517
 
1516
   // Static members for each heater
1518
   // Static members for each heater
1517
   #if ENABLED(SLOW_PWM_HEATERS)
1519
   #if ENABLED(SLOW_PWM_HEATERS)
1521
       static uint8_t state_heater_ ## n = 0; \
1523
       static uint8_t state_heater_ ## n = 0; \
1522
       static uint8_t state_timer_heater_ ## n = 0
1524
       static uint8_t state_timer_heater_ ## n = 0
1523
   #else
1525
   #else
1524
-    #define ISR_STATICS(n) static uint8_t soft_pwm_ ## n
1526
+    #define ISR_STATICS(n) static uint8_t soft_pwm_ ## n = 0
1525
   #endif
1527
   #endif
1526
 
1528
 
1527
   // Statics per heater
1529
   // Statics per heater
1544
   #endif
1546
   #endif
1545
 
1547
 
1546
   #if DISABLED(SLOW_PWM_HEATERS)
1548
   #if DISABLED(SLOW_PWM_HEATERS)
1549
+    constexpr uint8_t pwm_mask =
1550
+      #if ENABLED(SOFT_PWM_DITHER)
1551
+        _BV(SOFT_PWM_SCALE) - 1
1552
+      #else
1553
+        0
1554
+      #endif
1555
+    ;
1556
+
1547
     /**
1557
     /**
1548
      * Standard PWM modulation
1558
      * Standard PWM modulation
1549
      */
1559
      */
1550
-    if (pwm_count == 0) {
1551
-      soft_pwm_0 = soft_pwm[0];
1552
-      WRITE_HEATER_0(soft_pwm_0 > 0 ? HIGH : LOW);
1560
+    if (pwm_count_tmp >= 127) {
1561
+      pwm_count_tmp -= 127;
1562
+      soft_pwm_0 = (soft_pwm_0 & pwm_mask) + soft_pwm[0];
1563
+      WRITE_HEATER_0(soft_pwm_0 > pwm_mask ? HIGH : LOW);
1553
       #if HOTENDS > 1
1564
       #if HOTENDS > 1
1554
-        soft_pwm_1 = soft_pwm[1];
1555
-        WRITE_HEATER_1(soft_pwm_1 > 0 ? HIGH : LOW);
1565
+        soft_pwm_1 = (soft_pwm_1 & pwm_mask) + soft_pwm[1];
1566
+        WRITE_HEATER_1(soft_pwm_1 > pwm_mask ? HIGH : LOW);
1556
         #if HOTENDS > 2
1567
         #if HOTENDS > 2
1557
-          soft_pwm_2 = soft_pwm[2];
1558
-          WRITE_HEATER_2(soft_pwm_2 > 0 ? HIGH : LOW);
1568
+          soft_pwm_2 = (soft_pwm_2 & pwm_mask) + soft_pwm[2];
1569
+          WRITE_HEATER_2(soft_pwm_2 > pwm_mask ? HIGH : LOW);
1559
           #if HOTENDS > 3
1570
           #if HOTENDS > 3
1560
-            soft_pwm_3 = soft_pwm[3];
1561
-            WRITE_HEATER_3(soft_pwm_3 > 0 ? HIGH : LOW);
1571
+            soft_pwm_3 = (soft_pwm_3 & pwm_mask) + soft_pwm[3];
1572
+            WRITE_HEATER_3(soft_pwm_3 > pwm_mask ? HIGH : LOW);
1562
           #endif
1573
           #endif
1563
         #endif
1574
         #endif
1564
       #endif
1575
       #endif
1565
 
1576
 
1566
       #if HAS_HEATER_BED
1577
       #if HAS_HEATER_BED
1567
-        soft_pwm_BED = soft_pwm_bed;
1568
-        WRITE_HEATER_BED(soft_pwm_BED > 0 ? HIGH : LOW);
1578
+        soft_pwm_BED = (soft_pwm_BED & pwm_mask) + soft_pwm_bed;
1579
+        WRITE_HEATER_BED(soft_pwm_BED > pwm_mask ? HIGH : LOW);
1569
       #endif
1580
       #endif
1570
 
1581
 
1571
       #if ENABLED(FAN_SOFT_PWM)
1582
       #if ENABLED(FAN_SOFT_PWM)
1572
         #if HAS_FAN0
1583
         #if HAS_FAN0
1573
-          soft_pwm_fan[0] = fanSpeedSoftPwm[0] >> 1;
1574
-          WRITE_FAN(soft_pwm_fan[0] > 0 ? HIGH : LOW);
1584
+          soft_pwm_fan[0] = (soft_pwm_fan[0] & pwm_mask) + fanSpeedSoftPwm[0] >> 1;
1585
+          WRITE_FAN(soft_pwm_fan[0] > pwm_mask ? HIGH : LOW);
1575
         #endif
1586
         #endif
1576
         #if HAS_FAN1
1587
         #if HAS_FAN1
1577
-          soft_pwm_fan[1] = fanSpeedSoftPwm[1] >> 1;
1578
-          WRITE_FAN1(soft_pwm_fan[1] > 0 ? HIGH : LOW);
1588
+          soft_pwm_fan[1] = (soft_pwm_fan[1] & pwm_mask) + fanSpeedSoftPwm[1] >> 1;
1589
+          WRITE_FAN1(soft_pwm_fan[1] > pwm_mask ? HIGH : LOW);
1579
         #endif
1590
         #endif
1580
         #if HAS_FAN2
1591
         #if HAS_FAN2
1581
-          soft_pwm_fan[2] = fanSpeedSoftPwm[2] >> 1;
1582
-          WRITE_FAN2(soft_pwm_fan[2] > 0 ? HIGH : LOW);
1592
+          soft_pwm_fan[2] = (soft_pwm_fan[2] & pwm_mask) + fanSpeedSoftPwm[2] >> 1;
1593
+          WRITE_FAN2(soft_pwm_fan[2] > pwm_mask ? HIGH : LOW);
1583
         #endif
1594
         #endif
1584
       #endif
1595
       #endif
1585
     }
1596
     }
1586
-
1587
-    if (soft_pwm_0 < pwm_count) WRITE_HEATER_0(0);
1588
-    #if HOTENDS > 1
1589
-      if (soft_pwm_1 < pwm_count) WRITE_HEATER_1(0);
1597
+    else {
1598
+      if (soft_pwm_0 <= pwm_count_tmp) WRITE_HEATER_0(0);
1599
+      #if HOTENDS > 1
1600
+        if (soft_pwm_1 <= pwm_count_tmp) WRITE_HEATER_1(0);
1601
+      #endif
1590
       #if HOTENDS > 2
1602
       #if HOTENDS > 2
1591
-        if (soft_pwm_2 < pwm_count) WRITE_HEATER_2(0);
1592
-        #if HOTENDS > 3
1593
-          if (soft_pwm_3 < pwm_count) WRITE_HEATER_3(0);
1594
-        #endif
1603
+        if (soft_pwm_2 <= pwm_count_tmp) WRITE_HEATER_2(0);
1595
       #endif
1604
       #endif
1596
-    #endif
1597
-
1598
-    #if HAS_HEATER_BED
1599
-      if (soft_pwm_BED < pwm_count) WRITE_HEATER_BED(0);
1600
-    #endif
1601
-
1602
-    #if ENABLED(FAN_SOFT_PWM)
1603
-      #if HAS_FAN0
1604
-        if (soft_pwm_fan[0] < pwm_count) WRITE_FAN(0);
1605
+      #if HOTENDS > 3
1606
+        if (soft_pwm_3 <= pwm_count_tmp) WRITE_HEATER_3(0);
1605
       #endif
1607
       #endif
1606
-      #if HAS_FAN1
1607
-        if (soft_pwm_fan[1] < pwm_count) WRITE_FAN1(0);
1608
+
1609
+      #if HAS_HEATER_BED
1610
+        if (soft_pwm_BED <= pwm_count_tmp) WRITE_HEATER_BED(0);
1608
       #endif
1611
       #endif
1609
-      #if HAS_FAN2
1610
-        if (soft_pwm_fan[2] < pwm_count) WRITE_FAN2(0);
1612
+
1613
+      #if ENABLED(FAN_SOFT_PWM)
1614
+        #if HAS_FAN0
1615
+          if (soft_pwm_fan[0] <= pwm_count_tmp) WRITE_FAN(0);
1616
+        #endif
1617
+        #if HAS_FAN1
1618
+          if (soft_pwm_fan[1] <= pwm_count_tmp) WRITE_FAN1(0);
1619
+        #endif
1620
+        #if HAS_FAN2
1621
+          if (soft_pwm_fan[2] <= pwm_count_tmp) WRITE_FAN2(0);
1622
+        #endif
1611
       #endif
1623
       #endif
1612
-    #endif
1624
+    }
1613
 
1625
 
1614
     // SOFT_PWM_SCALE to frequency:
1626
     // SOFT_PWM_SCALE to frequency:
1615
     //
1627
     //
1619
     // 3:                / 16 =  61.0352 Hz
1631
     // 3:                / 16 =  61.0352 Hz
1620
     // 4:                /  8 = 122.0703 Hz
1632
     // 4:                /  8 = 122.0703 Hz
1621
     // 5:                /  4 = 244.1406 Hz
1633
     // 5:                /  4 = 244.1406 Hz
1622
-    pwm_count += _BV(SOFT_PWM_SCALE);
1623
-    pwm_count &= 0x7F;
1634
+    pwm_count = pwm_count_tmp + _BV(SOFT_PWM_SCALE);
1624
 
1635
 
1625
   #else // SLOW_PWM_HEATERS
1636
   #else // SLOW_PWM_HEATERS
1626
 
1637
 
1694
     #endif
1705
     #endif
1695
 
1706
 
1696
     #if ENABLED(FAN_SOFT_PWM)
1707
     #if ENABLED(FAN_SOFT_PWM)
1697
-      if (pwm_count == 0) {
1708
+      if (pwm_count_tmp >= 127) {
1709
+        pwm_count_tmp = 0;
1698
         #if HAS_FAN0
1710
         #if HAS_FAN0
1699
           soft_pwm_fan[0] = fanSpeedSoftPwm[0] >> 1;
1711
           soft_pwm_fan[0] = fanSpeedSoftPwm[0] >> 1;
1700
           WRITE_FAN(soft_pwm_fan[0] > 0 ? HIGH : LOW);
1712
           WRITE_FAN(soft_pwm_fan[0] > 0 ? HIGH : LOW);
1709
         #endif
1721
         #endif
1710
       }
1722
       }
1711
       #if HAS_FAN0
1723
       #if HAS_FAN0
1712
-        if (soft_pwm_fan[0] < pwm_count) WRITE_FAN(0);
1724
+        if (soft_pwm_fan[0] <= pwm_count_tmp) WRITE_FAN(0);
1713
       #endif
1725
       #endif
1714
       #if HAS_FAN1
1726
       #if HAS_FAN1
1715
-        if (soft_pwm_fan[1] < pwm_count) WRITE_FAN1(0);
1727
+        if (soft_pwm_fan[1] <= pwm_count_tmp) WRITE_FAN1(0);
1716
       #endif
1728
       #endif
1717
       #if HAS_FAN2
1729
       #if HAS_FAN2
1718
-        if (soft_pwm_fan[2] < pwm_count) WRITE_FAN2(0);
1730
+        if (soft_pwm_fan[2] <= pwm_count_tmp) WRITE_FAN2(0);
1719
       #endif
1731
       #endif
1720
-    #endif //FAN_SOFT_PWM
1732
+    #endif // FAN_SOFT_PWM
1721
 
1733
 
1722
     // SOFT_PWM_SCALE to frequency:
1734
     // SOFT_PWM_SCALE to frequency:
1723
     //
1735
     //
1727
     // 3:                / 16 =  61.0352 Hz
1739
     // 3:                / 16 =  61.0352 Hz
1728
     // 4:                /  8 = 122.0703 Hz
1740
     // 4:                /  8 = 122.0703 Hz
1729
     // 5:                /  4 = 244.1406 Hz
1741
     // 5:                /  4 = 244.1406 Hz
1730
-    pwm_count += _BV(SOFT_PWM_SCALE);
1731
-    pwm_count &= 0x7F;
1742
+    pwm_count = pwm_count_tmp + _BV(SOFT_PWM_SCALE);
1732
 
1743
 
1733
-    // increment slow_pwm_count only every 64 pwm_count (e.g., every 8s)
1734
-    if ((pwm_count % 64) == 0) {
1744
+    // increment slow_pwm_count only every 64th pwm_count,
1745
+    // i.e. yielding a PWM frequency of 16/128 Hz (8s).
1746
+    if (((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0) {
1735
       slow_pwm_count++;
1747
       slow_pwm_count++;
1736
-      slow_pwm_count &= 0x7f;
1748
+      slow_pwm_count &= 0x7F;
1737
 
1749
 
1738
       // EXTRUDER 0
1750
       // EXTRUDER 0
1739
       if (state_timer_heater_0 > 0) state_timer_heater_0--;
1751
       if (state_timer_heater_0 > 0) state_timer_heater_0--;
1749
       #if HAS_HEATER_BED
1761
       #if HAS_HEATER_BED
1750
         if (state_timer_heater_BED > 0) state_timer_heater_BED--;
1762
         if (state_timer_heater_BED > 0) state_timer_heater_BED--;
1751
       #endif
1763
       #endif
1752
-    } // (pwm_count % 64) == 0
1764
+    } // ((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0
1753
 
1765
 
1754
   #endif // SLOW_PWM_HEATERS
1766
   #endif // SLOW_PWM_HEATERS
1755
 
1767
 

Loading…
Cancel
Save