Advertisement
Guest User

Untitled

a guest
Mar 15th, 2013
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.00 KB | None | 0 0
  1.  
  2.  
  3. #include "avr/pgmspace.h"
  4.  
  5. // table of 256 sine values / one sine period / stored in flash memory
  6. PROGMEM prog_uchar sine16[] = {127, 176, 217, 245, 255, 245, 217, 176, 128, 79, 38, 10, 0, 10, 38, 79, 127 };
  7.  
  8. PROGMEM prog_uchar arctan256[] = {
  9. 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 16, 17, 18, 18, 19, 20,
  10. 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, 28, 29, 30, 30, 31, 31, 32, 33, 33, 34, 34, 35, 36, 36, 37,
  11. 38, 38, 39, 39, 40, 41, 41, 42, 42, 43, 44, 44, 45, 45, 46, 46, 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53,
  12. 54, 55, 55, 56, 56, 57, 57, 58, 58, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69,
  13. 69, 70, 70, 71, 71, 72, 72, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83,
  14. 84, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95, 96, 96,
  15. 96, 97, 97, 98, 98, 99, 99, 99, 100, 100, 101, 101, 102, 102, 102, 103, 103, 104, 104, 104, 105, 105, 106, 106,
  16. 106, 107, 107, 108, 108, 108, 109, 109, 110, 110, 110, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 115, 115,
  17. 115, 116, 116, 116, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123,
  18. 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 128
  19. };
  20.  
  21. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  22. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  23.  
  24. volatile byte V[6]; // Analogue values
  25. byte Z[6]; // Zero-offset values for each channel
  26. volatile boolean F[6]; // "You have new Volts" flag.
  27.  
  28. unsigned int A; // Angle
  29.  
  30. long Accum; // For zero-measurement and buffering
  31.  
  32. volatile byte index; // index to current mux channel
  33.  
  34. byte oldindex = 0; // Only do arctan if there is new data
  35. // variables used inside interrupt service declared as voilatile
  36. volatile byte icnt; // var inside interrupt
  37.  
  38. void setup()
  39. {
  40. DDRB = B00101111; // PORTB as output. except pin12
  41. DDRD = B11111100; // PortD as output, except serial IO
  42. Serial.begin(1000000); // connect to the serial port
  43.  
  44. //First populate the zero-volt value for each channel
  45. analogReference(EXTERNAL);
  46. for (int i = 0 ; i <= 5 ; i++) { // iterate through channels
  47. Accum = 0;
  48. for (int j = 1 ; j<=1000 ; j++) { // 1000 samples should do
  49. Accum = Accum + analogRead(i);
  50. }
  51. Z[i] = Accum / 4000; // 10-to-8 bitshift and 1000
  52. }
  53.  
  54. Setup_timer2();
  55.  
  56. // disable interrupts to avoid timing distortion
  57. cbi (TIMSK0,TOIE0); // disable Timer0 !!! delay() is now not available
  58.  
  59. SetupADC();
  60.  
  61. }
  62. void loop()
  63. {
  64. sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt
  65. while(1){
  66. // 6000 rpm is a max change of 102.4 counts per cycle.
  67. // any bigger changes will be rejected as glitches
  68. byte B;
  69. if (F[0] || F[3]){
  70. F[0] = false;
  71. F[3] = false;
  72. A = arctan(V[0] - Z[0], V[3] - Z[3]);
  73. B = (A & B00011111);
  74. Serial.write(B00000000 | B);
  75. B = ((A >> 5) & B00011111);
  76. Serial.write(B10000000 | B);
  77. }
  78. if (F[1] || F[4]){
  79. F[1] = false;
  80. F[4] = false;
  81. A = arctan(V[1] - Z[1], V[4] - Z[4]);
  82. B = (A & B00011111);
  83. Serial.write(B00100000 | B);
  84. B = ((A >> 5) & B00011111);
  85. Serial.write(B10100000 | B);
  86. }
  87. if (F[2] || F[5]){
  88. F[2] = false;
  89. F[5] = false;
  90. A = arctan(V[2] - Z[2], V[5] - Z[5]);
  91. B = (A & B00011111);
  92. Serial.write(B01000000 | B);
  93. B = ((A >> 5) & B00011111);
  94. Serial.write(B11000000 | B);
  95. }
  96. }
  97. }
  98. //******************************************************************
  99. // timer2 setup
  100. // set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
  101. void Setup_timer2() {
  102.  
  103. sbi (TCCR2B, CS20); // Timer2 Clock Prescaler to : 1
  104. cbi (TCCR2B, CS21);
  105. cbi (TCCR2B, CS22);
  106.  
  107. // Timer2 PWM Mode set to Phase Correct PWM
  108. cbi (TCCR2A, COM2A0); // clear Compare Match
  109. sbi (TCCR2A, COM2A1);
  110.  
  111. sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
  112. cbi (TCCR2A, WGM21);
  113. cbi (TCCR2B, WGM22);
  114. }
  115.  
  116. //Setup ADC
  117. void SetupADC() {
  118. // cbi(ADMUX, REFS1);
  119. //cbi(ADMUX, REFS0); // External Aref
  120. analogReference(EXTERNAL);
  121. sbi(ADMUX, ADLAR); // Left-aligned for 8-bit data
  122. cbi(ADMUX, MUX3);
  123. cbi(ADMUX, MUX2);
  124. cbi(ADMUX, MUX1);
  125. cbi(ADMUX, MUX0); // Set the Mux to zero to begin
  126.  
  127. sbi(ADCSRA, ADEN); // Enable the ADC
  128. cbi(ADCSRA, ADSC); // Don't start conversion yet
  129. cbi(ADCSRA, ADATE); // No auto-trigger
  130. cbi(ADCSRA, ADIF); // Not sure if that is possible or wise
  131. sbi(ADCSRA, ADIE); // Conversion-complete Interrupt to process data
  132. sbi(ADCSRA, ADPS2);
  133. cbi(ADCSRA, ADPS1);
  134. cbi(ADCSRA, ADPS0); // ADC Clock prescalar = 16
  135. }
  136.  
  137. //******************************************************************
  138. // Timer2 Interrupt Service at 31372,550 KHz = 32uSec
  139. // this is the timebase REFCLOCK for the DDS generator
  140. // FOUT = (M (REFCLK)) / (2 exp 32)
  141. // runtime : 8 microseconds ( inclusive push and pop)
  142. ISR(TIMER2_OVF_vect) {
  143.  
  144. icnt= 15 & (++icnt); // use upper 8 bits for phase accu as frequency information
  145. // read value fron ROM sine table and send to PWM DAC
  146. OCR2A=pgm_read_byte_near(sine16 + icnt);
  147.  
  148. if (icnt == 5 || icnt==7 || icnt == 14) {
  149. sbi(ADCSRA, ADSC); // Start Conversion
  150. }
  151. }
  152.  
  153. // ADC Conversion Complete Interrupt
  154. ISR(ADC_vect) {
  155. V[index] = ADCH; //get the data
  156. F[index] = true;
  157. if (++index > 5) index = 0; // increment the ADC channel number with wrap
  158. ADMUX = (ADMUX & B11110000) | index; // set the ACDC channel
  159.  
  160. }
  161.  
  162. // Lookup-Table based Arctan. Returns an angle from 0-1023 "Binary Degrees"
  163.  
  164. unsigned int arctan(int V1, int V2) {
  165. //Handle the quadrants explicitly
  166. if (V1 < 0)
  167. {
  168. if (V2 < 0)
  169. {
  170. if (V1 < V2) // 180-225
  171. {
  172. return 512 + pgm_read_byte_near(arctan256 + 256 * V2 / V1);
  173. }
  174. else // 225-270
  175. {
  176. return 768 - pgm_read_byte_near(arctan256 + 256 * V1 / V2);
  177. }
  178. }
  179. else // V2 => 0
  180. {
  181. if (-V1 < V2) // 90-135
  182. {
  183. return 256 + pgm_read_byte_near(arctan256 - 256 * V1 / V2);
  184. }
  185. else // 135-180
  186. {
  187. return 512 - pgm_read_byte_near(arctan256 - 256 * V2 / V1);
  188. }
  189. }
  190. }
  191. else // V1 => 0
  192. {
  193. if (V2 < 0)
  194. {
  195. if (V1 < -V2) // 270-315
  196. {
  197. return 768 + pgm_read_byte_near(arctan256 - 256 * V1 / V2);
  198. }
  199. else // 315-360
  200. {
  201. return 1023 - pgm_read_byte_near(arctan256 - 256 * V2 / V1);
  202. }
  203. }
  204. else // V2 => 0
  205. {
  206. if (V1 < V2) // 45-90
  207. {
  208. return 256 - pgm_read_byte_near(arctan256 + 256 * V1 / V2);
  209. }
  210. else // 0-45
  211. {
  212. return pgm_read_byte_near(arctan256 + 256 * V2 / V1);
  213. }
  214. }
  215. }
  216. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement