Pwm.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // PCA9685 PWM控制模块
  2. const i2cBus = require("i2c-bus")
  3. const { Pca9685Driver } = require("pca9685")
  4. const RPIO = require("rpio");
  5. class ContrlService {
  6. constructor() {
  7. // PWM 和 舵机配置
  8. this.pwmOption = {
  9. i2c: i2cBus.openSync(1), // 树莓派1:scl1
  10. address: 0x40, //板子地址
  11. frequency: 50, //频率
  12. debug: false
  13. }
  14. //PCA 板子位置电调+舵机
  15. this.MoAndSero = {
  16. m1: 1,
  17. m2: 0,
  18. s1: 2,
  19. s2: 3
  20. }
  21. // prio init
  22. RPIO.init({ mapping: "gpio" });
  23. // 关闭继电器
  24. RPIO.open(6, RPIO.OUTPUT, RPIO.LOW);
  25. RPIO.open(13, RPIO.OUTPUT, RPIO.LOW);
  26. RPIO.open(19, RPIO.OUTPUT, RPIO.LOW);
  27. // init PWM
  28. this.PWM = new Pca9685Driver(this.pwmOption, er => {
  29. if (er) {
  30. console.error("Error initializing PCA9685");
  31. }
  32. })
  33. // 解锁计数器
  34. this.Snum = 0
  35. // 解锁状态
  36. this.enable = false
  37. // 摇杆解锁
  38. this.contrlEnable = false
  39. // 摇杆中立值110-120
  40. this.centerNum = 120
  41. }
  42. // 设置pwm
  43. async changPWM(params) {
  44. const { v0, v1, v2, v3 } = params
  45. if (typeof (v0) == 'number' && typeof (v2) == 'number' && typeof (v1) == 'number' && typeof (v3) == 'number') {
  46. // 内八解锁
  47. if (this.enable) {
  48. //中位值
  49. if (!this.contrlEnable) {
  50. this.PWM.setPulseLength(this.MoAndSero.m1, this.Motor2pwm(Math.abs(this.centerNum)));
  51. this.PWM.setPulseLength(this.MoAndSero.m2, this.Motor2pwm(Math.abs(this.centerNum)));
  52. }
  53. //上推解锁
  54. if (!this.contrlEnable && +v3 < 200) this.contrlEnable = true
  55. // PWM操作
  56. if (this.contrlEnable) {
  57. // 注意中位误差
  58. if (Math.abs(+v3 - this.centerNum) < 20) {
  59. this.PWM.setPulseLength(this.MoAndSero.m1, this.Motor2pwm(Math.abs(+v2 - 255)));
  60. this.PWM.setPulseLength(this.MoAndSero.m2, this.Motor2pwm(Math.abs(+v2 - 255)));
  61. } else {
  62. // 分左右 注意左右误差
  63. if ((+v3 - this.centerNum) > 20) {
  64. // 右
  65. const a = this.centerNum - (+v3 - this.centerNum)
  66. const b = this.centerNum + (+v3 - this.centerNum)
  67. this.PWM.setPulseLength(this.MoAndSero.m1, this.Motor2pwm(+a));
  68. this.PWM.setPulseLength(this.MoAndSero.m2, this.Motor2pwm(+b));
  69. } else if (+v3 - this.centerNum < -20) {
  70. // 左
  71. const a = this.centerNum - (+v3 - this.centerNum)
  72. const b = this.centerNum + (+v3 - this.centerNum)
  73. this.PWM.setPulseLength(this.MoAndSero.m1, this.Motor2pwm(+a));
  74. this.PWM.setPulseLength(this.MoAndSero.m2, this.Motor2pwm(+b));
  75. }
  76. }
  77. }
  78. //云台
  79. if (v0 || v1) {
  80. const a = +v1 > 200 ? 200 : +v1
  81. this.PWM.setPulseLength(this.MoAndSero.s1, this.Servo2pwm(+v0));
  82. this.PWM.setPulseLength(this.MoAndSero.s2, this.Servo2pwm(+a));
  83. }
  84. console.log('前后', v3, '左右', v2, '云台', v0, v1)
  85. } else {
  86. this.unLOCK(v0, v1, v2, v3)
  87. }
  88. } else {
  89. // 遥杆数据错误,断开继电器
  90. this.stop()
  91. process.exit(1)
  92. return
  93. }
  94. }
  95. /**
  96. * 内八解锁
  97. * @param {*} v0
  98. * @param {*} v1
  99. * @param {*} v2
  100. * @param {*} v3
  101. */
  102. unLOCK(v0, v1, v2, v3) {
  103. // 未解锁=>进行解锁:发送端的频率是0.05S,0.05*60 = 3S
  104. // 内八 :v0<50,v1>200,v2>200,v3<50
  105. if (+v0 <= 60 && +v1 >= 190 && +v3 >= 190 && +v2 <= 60) {
  106. if (this.Snum >= 0 && this.Snum <= 51) this.Snum++
  107. } else {
  108. this.Snum = 0
  109. }
  110. if (this.Snum == 50) {
  111. //继电器开灯
  112. RPIO.open(19, RPIO.OUTPUT, RPIO.HIGH);
  113. //空闲继电器
  114. //RPIO.open(13, RPIO.OUTPUT, RPIO.HIGH);
  115. //空闲继电器
  116. //RPIO.open(6, RPIO.OUTPUT, RPIO.HIGH);
  117. this.enable = true
  118. }
  119. console.log('解锁中', v0, v1, v2, v3)
  120. }
  121. /**
  122. * 电调换算比例:摇杆范围0-255,PWM范围500~1500~2500
  123. * @param {number} v
  124. * @returns
  125. */
  126. Motor2pwm(v) {
  127. // 使用低速
  128. let num = 128
  129. if (v < 116) {
  130. num = 116;
  131. } else if (v >= 120 && v <= 131) {
  132. num = 128;
  133. } else if (v > 140) {
  134. num = 140;
  135. }
  136. return parseInt(num / (255 / 2000)) + 500
  137. }
  138. /**
  139. * 舵机换算比例:摇杆范围0-256,PWM范围1000~1500~2000
  140. * @param {number} v
  141. * @returns
  142. */
  143. Servo2pwm(v) {
  144. return parseInt(v / (256 / 1000)) + 1000
  145. }
  146. // 关闭
  147. stop() {
  148. if (this.PWM) this.PWM.dispose()
  149. RPIO.open(6, RPIO.OUTPUT, RPIO.LOW);
  150. RPIO.open(13, RPIO.OUTPUT, RPIO.LOW);
  151. RPIO.open(19, RPIO.OUTPUT, RPIO.LOW);
  152. this.PWM = null
  153. }
  154. }
  155. module.exports = new ContrlService()