Guest User

Untitled

a guest
Feb 24th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.92 KB | None | 0 0
  1. /* Sample RC servo input for 4 channels using Input Capture hardware perihperal and interrupts
  2. * Written for Rick Anderson by Brian Schmalz
  3. * 11/11/2017
  4. * This software is put in the public domain.
  5. * This sketch is means for a chipKIT Fubarino SD board, but can be easily adpated to any PIC32 based Arduino compatible board.
  6. */
  7.  
  8. /* Fubarino SD can only use pins 0, 1, 2, 3, and 10 as Input Capture.
  9. * On any chipKIT board with PPS (like Fubarino Mini) additional setup is necessary to map the Input Capture
  10. * peripherals to speciffic I/O pins, but you have much more flexibility in pin assignments.
  11. */
  12. // Which pins correspond to which RC input channel?
  13. #define RC_INPUT_1 0
  14. #define RC_INPUT_2 1
  15. #define RC_INPUT_3 2
  16. #define RC_INPUT_4 3
  17. // How many RC input channels are there?
  18. #define RC_INPUT_COUNT 4
  19.  
  20. // These two arrays hold the latest pulse measurements for each RC input channel
  21. volatile uint16_t pulseHighTime[RC_INPUT_COUNT];
  22. volatile uint16_t pulseLowTime[RC_INPUT_COUNT];
  23.  
  24. /* Four Input Capture Interrupt Service Routines
  25. * These functions get called on each rising and falling edge. They check to see
  26. * if a rising edge or falling edge just happened, then read out the Timer2 value that
  27. * got latched on the edge, and calculate the high and low pulse times, then stick those
  28. * times in the proper array.
  29. */
  30. void __USER_ISR InputCatpure1_ISR(void) {
  31. static uint16_t risingEdgeTime = 0;
  32. static uint16_t fallingEdgeTime = 0;
  33.  
  34. clearIntFlag(_INPUT_CAPTURE_1_IRQ);
  35. if (IC1CONbits.ICBNE == 1)
  36. {
  37. if (digitalRead(RC_INPUT_1) == HIGH)
  38. {
  39. risingEdgeTime = IC1BUF;
  40. pulseLowTime[0] = risingEdgeTime - fallingEdgeTime;
  41. }
  42. else
  43. {
  44. fallingEdgeTime = IC1BUF;
  45. pulseHighTime[0] = fallingEdgeTime - risingEdgeTime;
  46. }
  47. }
  48. }
  49.  
  50. void __USER_ISR InputCatpure2_ISR(void) {
  51. static uint16_t risingEdgeTime = 0;
  52. static uint16_t fallingEdgeTime = 0;
  53.  
  54. clearIntFlag(_INPUT_CAPTURE_2_IRQ);
  55. if (IC2CONbits.ICBNE == 1)
  56. {
  57. if (digitalRead(RC_INPUT_2) == HIGH)
  58. {
  59. risingEdgeTime = IC2BUF;
  60. pulseLowTime[1] = risingEdgeTime - fallingEdgeTime;
  61. }
  62. else
  63. {
  64. fallingEdgeTime = IC2BUF;
  65. pulseHighTime[1] = fallingEdgeTime - risingEdgeTime;
  66. }
  67. }
  68. }
  69.  
  70. void __USER_ISR InputCatpure3_ISR(void) {
  71. static uint16_t risingEdgeTime = 0;
  72. static uint16_t fallingEdgeTime = 0;
  73.  
  74. clearIntFlag(_INPUT_CAPTURE_3_IRQ);
  75. if (IC3CONbits.ICBNE == 1)
  76. {
  77. if (digitalRead(RC_INPUT_3) == HIGH)
  78. {
  79. risingEdgeTime = IC3BUF;
  80. pulseLowTime[2] = risingEdgeTime - fallingEdgeTime;
  81. }
  82. else
  83. {
  84. fallingEdgeTime = IC3BUF;
  85. pulseHighTime[2] = fallingEdgeTime - risingEdgeTime;
  86. }
  87. }
  88. }
  89.  
  90. void __USER_ISR InputCatpure4_ISR(void) {
  91. static uint16_t risingEdgeTime = 0;
  92. static uint16_t fallingEdgeTime = 0;
  93.  
  94. clearIntFlag(_INPUT_CAPTURE_4_IRQ);
  95. if (IC4CONbits.ICBNE == 1)
  96. {
  97. if (digitalRead(RC_INPUT_4) == HIGH)
  98. {
  99. risingEdgeTime = IC4BUF;
  100. pulseLowTime[3] = risingEdgeTime - fallingEdgeTime;
  101. }
  102. else
  103. {
  104. fallingEdgeTime = IC4BUF;
  105. pulseHighTime[3] = fallingEdgeTime - risingEdgeTime;
  106. }
  107. }
  108. }
  109.  
  110. void setup() {
  111. Serial.begin(9600);
  112. delay(3000);
  113. Serial.println("OK we are starting now");
  114.  
  115. /* Set up each of the four Input Capture modules
  116. * We want them to generate an interrupt on each rising and falling edge of the input
  117. * We also want them all to use Timer2 as their timebase timer
  118. */
  119. IC1CON = 0;
  120. IC1CONbits.ICM = 1; // Captured and interrupt on every rising and falling edge
  121. IC1CONbits.ICTMR = 1; // Set to user Timer2
  122. IC1CONbits.ON = 1; // Turn IC1 on
  123.  
  124. IC2CON = 0;
  125. IC2CONbits.ICM = 1; // Captured and interrupt on every rising and falling edge
  126. IC2CONbits.ICTMR = 1; // Set to user Timer2
  127. IC2CONbits.ON = 1; // Turn IC2 on
  128.  
  129. IC3CON = 0;
  130. IC3CONbits.ICM = 1; // Captured and interrupt on every rising and falling edge
  131. IC3CONbits.ICTMR = 1; // Set to user Timer2
  132. IC3CONbits.ON = 1; // Turn IC3 on
  133.  
  134. IC4CON = 0;
  135. IC4CONbits.ICM = 1; // Captured and interrupt on every rising and falling edge
  136. IC4CONbits.ICTMR = 1; // Set to user Timer2
  137. IC4CONbits.ON = 1; // Turn IC4 on
  138.  
  139. /* Set up Timer2: We want it to simply count up. We set the prescaler to 1:64
  140. * so that the 40MHz PCLK gets divided down to 1.25Mhz. This is nice because
  141. * then it gives us both high and low periods under 65535 for normal RC servo
  142. * times (0-3 ms high time and 17-20ms low time)
  143. */
  144. PR2 = 0xFFFF; // Run from 0 to 0xFFFF
  145. T2CONbits.TCKPS = 5; // 1:32 prescale, which means 40MHz/64 or 1.25MHz clock rate
  146. T2CONbits.TON = 1; // Turn on Timer2
  147.  
  148. // Set all input captures as inputs
  149. pinMode(RC_INPUT_1, INPUT);
  150. pinMode(RC_INPUT_2, INPUT);
  151. pinMode(RC_INPUT_3, INPUT);
  152. pinMode(RC_INPUT_4, INPUT);
  153. Serial.println("ready");
  154.  
  155. // Set each Input Capture up to use its ISR routine
  156. setIntVector(_INPUT_CAPTURE_1_VECTOR, InputCatpure1_ISR);
  157. setIntPriority(_INPUT_CAPTURE_1_VECTOR, 4, 0);
  158. clearIntFlag(_INPUT_CAPTURE_1_IRQ);
  159. setIntEnable(_INPUT_CAPTURE_1_IRQ);
  160.  
  161. setIntVector(_INPUT_CAPTURE_2_VECTOR, InputCatpure2_ISR);
  162. setIntPriority(_INPUT_CAPTURE_2_VECTOR, 4, 0);
  163. clearIntFlag(_INPUT_CAPTURE_2_IRQ);
  164. setIntEnable(_INPUT_CAPTURE_2_IRQ);
  165.  
  166. setIntVector(_INPUT_CAPTURE_3_VECTOR, InputCatpure3_ISR);
  167. setIntPriority(_INPUT_CAPTURE_3_VECTOR, 4, 0);
  168. clearIntFlag(_INPUT_CAPTURE_3_IRQ);
  169. setIntEnable(_INPUT_CAPTURE_3_IRQ);
  170.  
  171. setIntVector(_INPUT_CAPTURE_4_VECTOR, InputCatpure4_ISR);
  172. setIntPriority(_INPUT_CAPTURE_4_VECTOR, 4, 0);
  173. clearIntFlag(_INPUT_CAPTURE_4_IRQ);
  174. setIntEnable(_INPUT_CAPTURE_4_IRQ);
  175. }
  176.  
  177. void loop() {
  178. static uint32_t lastPrintTime = 0;
  179. float uSscale = 0.4;
  180.  
  181. /* So the way things work, the ISRs will get called and they will constantly update
  182. * the pulseHighTime and pulseLowTime arrays "in the background". In other words the
  183. * mainline code here doesn't ever have to do anything other than simply read out
  184. * the values in the arrays, and those values will always be the most recent pulse
  185. * measurements. If you care about converting the values to real time (like in
  186. * microsconds), the units for these values are in 1.25MHz 'counts'. So 1ms = 1250
  187. * 'counts'.
  188. */
  189. // To demo things, simply print out all 4 high and low pulse times every half second
  190. if ((millis() - lastPrintTime) > 500)
  191. {
  192. lastPrintTime = millis();
  193. char pulses[100];
  194. char micros[100];
  195. sprintf(pulses, "high1: %05u low1: %05u high2: %05u low2: %05u high3: %05u low3: %05u high4: %05u low4: %05u\n",
  196. pulseHighTime[0],
  197. pulseLowTime[0],
  198. pulseHighTime[1],
  199. pulseLowTime[1],
  200. pulseHighTime[2],
  201. pulseLowTime[2],
  202. pulseHighTime[3],
  203. pulseLowTime[3]
  204. );
  205. Serial.print(pulses);
  206. sprintf(micros, "ch1: %05u ch2: %05u ch3: %05u ch4: %05u\n",
  207. (int) (pulseHighTime[0] * uSscale),
  208. (int) (pulseHighTime[1] * uSscale),
  209. (int) (pulseHighTime[2] * uSscale),
  210. (int) (pulseHighTime[3] * uSscale)
  211. );
  212.  
  213. Serial.print(micros);
  214. }
  215. }
Add Comment
Please, Sign In to add comment