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,6 +1425,12 @@
1425 1425
 // at zero value, there are 128 effective control positions.
1426 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 1434
 // Temperature status LEDs that display the hotend and bed temperature.
1429 1435
 // If all hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on.
1430 1436
 // Otherwise the RED led is on. There is 1C hysteresis.

+ 65
- 53
Marlin/temperature.cpp View File

@@ -1512,6 +1512,8 @@ void Temperature::isr() {
1512 1512
   static uint8_t temp_count = 0;
1513 1513
   static TempState temp_state = StartupDelay;
1514 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 1518
   // Static members for each heater
1517 1519
   #if ENABLED(SLOW_PWM_HEATERS)
@@ -1521,7 +1523,7 @@ void Temperature::isr() {
1521 1523
       static uint8_t state_heater_ ## n = 0; \
1522 1524
       static uint8_t state_timer_heater_ ## n = 0
1523 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 1527
   #endif
1526 1528
 
1527 1529
   // Statics per heater
@@ -1544,72 +1546,82 @@ void Temperature::isr() {
1544 1546
   #endif
1545 1547
 
1546 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 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 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 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 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 1573
           #endif
1563 1574
         #endif
1564 1575
       #endif
1565 1576
 
1566 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 1580
       #endif
1570 1581
 
1571 1582
       #if ENABLED(FAN_SOFT_PWM)
1572 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 1586
         #endif
1576 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 1590
         #endif
1580 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 1594
         #endif
1584 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 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 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 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 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 1623
       #endif
1612
-    #endif
1624
+    }
1613 1625
 
1614 1626
     // SOFT_PWM_SCALE to frequency:
1615 1627
     //
@@ -1619,8 +1631,7 @@ void Temperature::isr() {
1619 1631
     // 3:                / 16 =  61.0352 Hz
1620 1632
     // 4:                /  8 = 122.0703 Hz
1621 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 1636
   #else // SLOW_PWM_HEATERS
1626 1637
 
@@ -1694,7 +1705,8 @@ void Temperature::isr() {
1694 1705
     #endif
1695 1706
 
1696 1707
     #if ENABLED(FAN_SOFT_PWM)
1697
-      if (pwm_count == 0) {
1708
+      if (pwm_count_tmp >= 127) {
1709
+        pwm_count_tmp = 0;
1698 1710
         #if HAS_FAN0
1699 1711
           soft_pwm_fan[0] = fanSpeedSoftPwm[0] >> 1;
1700 1712
           WRITE_FAN(soft_pwm_fan[0] > 0 ? HIGH : LOW);
@@ -1709,15 +1721,15 @@ void Temperature::isr() {
1709 1721
         #endif
1710 1722
       }
1711 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 1725
       #endif
1714 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 1728
       #endif
1717 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 1731
       #endif
1720
-    #endif //FAN_SOFT_PWM
1732
+    #endif // FAN_SOFT_PWM
1721 1733
 
1722 1734
     // SOFT_PWM_SCALE to frequency:
1723 1735
     //
@@ -1727,13 +1739,13 @@ void Temperature::isr() {
1727 1739
     // 3:                / 16 =  61.0352 Hz
1728 1740
     // 4:                /  8 = 122.0703 Hz
1729 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 1747
       slow_pwm_count++;
1736
-      slow_pwm_count &= 0x7f;
1748
+      slow_pwm_count &= 0x7F;
1737 1749
 
1738 1750
       // EXTRUDER 0
1739 1751
       if (state_timer_heater_0 > 0) state_timer_heater_0--;
@@ -1749,7 +1761,7 @@ void Temperature::isr() {
1749 1761
       #if HAS_HEATER_BED
1750 1762
         if (state_timer_heater_BED > 0) state_timer_heater_BED--;
1751 1763
       #endif
1752
-    } // (pwm_count % 64) == 0
1764
+    } // ((pwm_count >> SOFT_PWM_SCALE) & 0x3F) == 0
1753 1765
 
1754 1766
   #endif // SLOW_PWM_HEATERS
1755 1767
 

Loading…
Cancel
Save