pwm.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. """
  2. # Xytronic LF-1600
  3. # Open Source firmware
  4. # PWM calculation
  5. #
  6. # Copyright (c) 2019 Michael Buesch <m@bues.ch>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License along
  19. # with this program; if not, write to the Free Software Foundation, Inc.,
  20. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. """
  22. __all__ = [
  23. "PWMGenerator",
  24. ]
  25. class PWMGenerator(object):
  26. __slots__ = (
  27. "f",
  28. "duty",
  29. "cycleT",
  30. "out",
  31. "__errors",
  32. )
  33. def __init__(self, f, duty=0.0):
  34. self.f = max(f, 0.0)
  35. self.duty = max(min(duty, 1.0), 0.0)
  36. self.cycleT = 0.0
  37. self.out = False
  38. self.__errors = 0
  39. @property
  40. def cycleDur(self):
  41. return 1.0 / self.f
  42. def calc(self, dt):
  43. if self.f:
  44. self.cycleT += dt
  45. dur = self.cycleDur
  46. wrap = False
  47. if self.out:
  48. if self.cycleT >= dur:
  49. if self.duty < 1.0:
  50. self.out = False
  51. wrap = True
  52. else:
  53. if self.cycleT >= dur * (1.0 - self.duty):
  54. if self.duty > 0.0:
  55. self.out = True
  56. else:
  57. wrap = True
  58. if wrap:
  59. self.cycleT -= dur
  60. if self.cycleT >= dur:
  61. if self.__errors < 10:
  62. print("The PWM frequency %f Hz is "
  63. "too fast. Loosing steps." % (
  64. self.f))
  65. self.__errors += 1
  66. self.cycleT = 0.0
  67. return self.out
  68. if __name__ == "__main__":
  69. import time
  70. pwm = PWMGenerator(f=0.5, duty=0.3)
  71. dt = 0.1
  72. i = 0.0
  73. while 1:
  74. out = pwm.calc(dt)
  75. print("t=%.1f, out=%d, cycleT=%.3f" % (i, int(out), pwm.cycleT))
  76. time.sleep(dt)
  77. i += dt