You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

226 line
7.5 KiB

  1. // WiringPi test program: PWM test
  2. // Compile: gcc -Wall wiringpi_test9_pwm.c -o wiringpi_test9_pwm -lwiringPi
  3. #include "wpi_test.h"
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7. #include <sys/time.h>
  8. #include <time.h>
  9. #include <stdint.h>
  10. int PWM_OUT[4] = { 18, 12, 13, 19 };
  11. int PWM_IN[4] = { 17, 13, 12, 26 };
  12. volatile int gCounter = 0;
  13. //Interrupt Service Routine for FREQIN
  14. void ISR_FREQIN(void) {
  15. gCounter++;
  16. }
  17. double MeasureAndCheckFreq(const char* msg, double expect_freq) {
  18. double fFrequency;
  19. clock_t CPUClockBegin, CPUClockEnd;
  20. int CountBegin, CountEnd;
  21. double CPUClockInterval, CountInterval;
  22. double elapsed_time, CPULoad;
  23. uint64_t tbegin, tend;
  24. int SleepMs = 1200;
  25. CPUClockBegin = clock();
  26. tbegin = piMicros64();
  27. CountBegin = gCounter;
  28. delay(SleepMs);
  29. CountEnd = gCounter;
  30. CPUClockEnd = clock();
  31. tend = piMicros64();
  32. elapsed_time = (double)(tend-tbegin)/1.0e6;
  33. CountInterval = CountEnd - CountBegin;
  34. CPUClockInterval = CPUClockEnd - CPUClockBegin;
  35. CPULoad = CPUClockInterval*100.0 / CLOCKS_PER_SEC / elapsed_time;
  36. fFrequency = CountInterval / elapsed_time / 1000;
  37. printf("\nInterval: time: %.6f sec (CPU: %3.1f %%), count: %g -> frequency: %.3f kHz\n",
  38. elapsed_time, CPULoad, CountInterval, fFrequency);
  39. CheckSameDouble("Wait for freq. meas.", elapsed_time, SleepMs/1000.0, 0.1); //100ms tolerance. maybe problematic on high freq/cpu load
  40. CheckSameDouble(msg, fFrequency, expect_freq, expect_freq*2/100); //2% toleranc
  41. return fFrequency;
  42. }
  43. int tests_pwmc[7] = {1456, 1000, 512, 200, 2000, 3000, 4000};
  44. int tests_duty[7] = { 512, 768, 682, 922, 256, 341, 102};
  45. int tests_pwmr[12]= { 50, 100, 200, 512, 1024, 1456, 2000, 3000, 5000, 10000, 15000, 20000};
  46. int tests_pwm[3] = { 50, 25, 75};
  47. int main (void) {
  48. int major, minor;
  49. char msg[255];
  50. int testruns = 4;
  51. int PWM, FREQIN;
  52. wiringPiVersion(&major, &minor);
  53. printf("WiringPi GPIO test program 9\n");
  54. printf("PWM/ISR test (WiringPi %d.%d)\n", major, minor);
  55. wiringPiSetupGpio() ;
  56. int rev, mem, maker, overVolted, RaspberryPiModel;
  57. piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted);
  58. CheckNotSame("Model: ", RaspberryPiModel, -1);
  59. int Pi4 = 0;
  60. int Pi5 = 0;
  61. double MaxFreq = 100.0;
  62. switch(RaspberryPiModel) {
  63. case PI_MODEL_A:
  64. case PI_MODEL_B:
  65. case PI_MODEL_BP:
  66. case PI_MODEL_AP:
  67. case PI_MODEL_ZERO:
  68. case PI_MODEL_ZERO_W:
  69. case PI_MODEL_CM:
  70. MaxFreq = 13.0; // 12.5 kHz -> ~40% CPU@800 MHz
  71. printf(" - Pi1/BCM2835 detected, will skip tests with frequency above %g kHz\n", MaxFreq);
  72. break;
  73. case PI_MODEL_2:
  74. MaxFreq = 20.0;
  75. printf(" - Pi2/BCM2836 detected, will skip tests with frequency above %g kHz\n", MaxFreq);
  76. break;
  77. case PI_MODEL_3B:
  78. case PI_MODEL_CM3:
  79. case PI_MODEL_3BP:
  80. case PI_MODEL_3AP:
  81. case PI_MODEL_CM3P:
  82. case PI_MODEL_ZERO_2W:
  83. MaxFreq = 50.0;
  84. printf(" - Pi3/BCM2837 detected, will skip tests with frequency above %g kHz\n", MaxFreq);
  85. break;
  86. case PI_MODEL_4B:
  87. case PI_MODEL_400:
  88. case PI_MODEL_CM4:
  89. case PI_MODEL_CM4S:
  90. Pi4 = 1;
  91. break;
  92. case PI_MODEL_5:
  93. Pi5 = 1;
  94. break;
  95. }
  96. if (!piBoard40Pin()) {
  97. testruns = 1; // only fist PWM0, supported
  98. }
  99. for (int testrun=0; testrun<testruns; testrun++) {
  100. PWM = PWM_OUT[testrun];
  101. FREQIN = PWM_IN[testrun];
  102. printf("using PWM@GPIO%d (output) and GPIO%d (input)\n", PWM, FREQIN);
  103. delay(1000);
  104. printf("\n");
  105. printf("*********************************\n");
  106. printf("* PWM BAL mode *\n");
  107. printf("*********************************\n");
  108. const int pmw = 512;
  109. int pmwr = 1024; //default!
  110. printf("Set pwm 50%% and enable PWM output (600 kHz?) \n");
  111. pwmWrite(PWM, pmw); //50% Duty
  112. pinMode(PWM, PWM_OUTPUT); //Mode BAL, pwmr=1024, pwmc=32
  113. printf("pwmc 4.8kHz\n");
  114. pwmSetClock(2000);
  115. delay(250);
  116. printf("Register ISR@%d\n", PWM);
  117. // INT_EDGE_BOTH, INT_EDGE_FALLING, INT_EDGE_RISING only one ISR per input
  118. int result = wiringPiISR(FREQIN, INT_EDGE_RISING, &ISR_FREQIN);
  119. CheckSame("Register ISR", result, 0);
  120. if (result < 0) {
  121. printf("Unable to setup ISR for GPIO %d (%s)\n\n", FREQIN, strerror(errno));
  122. return UnitTestState();
  123. }
  124. printf("Wait for start ...\n");
  125. delay(500);
  126. printf("Start:\n");
  127. //MeasureAndCheckFreq("50\% Duty (default)", 300.000); //FAIL , freq (pwmc=32) to high for irq count
  128. if(!Pi5) {
  129. for (int c_duty=0, c_duty_end = sizeof(tests_duty)/sizeof(tests_duty[0]); c_duty<c_duty_end; c_duty++) {
  130. double tests_duty_corr;
  131. if (tests_duty[c_duty]>(pmwr/2)) {
  132. tests_duty_corr = pmwr-tests_duty[c_duty];
  133. } else {
  134. tests_duty_corr = tests_duty[c_duty];
  135. }
  136. double duty_fact = tests_duty_corr/(double)pmwr;
  137. printf("\n%d/%d set duty %d/%d\n",c_duty+1, c_duty_end, tests_duty[c_duty], pmwr);
  138. pwmWrite(PWM, tests_duty[c_duty]);
  139. for (int c_pwmc=0, end = sizeof(tests_pwmc)/sizeof(tests_pwmc[0]); c_pwmc<end; c_pwmc++) {
  140. int pwmc = tests_pwmc[c_pwmc];
  141. if (Pi4 && pwmc>1456) {
  142. printf("* Set clock (pwmc) %d not possible on BCM2711 system (OSC 54 MHz), ignore\n", pwmc);
  143. continue;
  144. }
  145. double freq = 19200.0/pwmc*duty_fact;
  146. if (freq>MaxFreq) {
  147. printf("* Set clock (pwmc) %d not possible on system (to slow to measure %g kHz with ISR), ignore\n", pwmc, freq);
  148. continue;
  149. }
  150. pwmSetClock(pwmc);
  151. delay(250);
  152. sprintf(msg, "Set Clock (pwmc) %d, %d%% duty", pwmc, tests_duty[c_duty]*100/pmwr);
  153. MeasureAndCheckFreq(msg, freq);
  154. }
  155. }
  156. }
  157. delay(250);
  158. printf("\n");
  159. printf("*********************************\n");
  160. printf("* PWM MS mode *\n");
  161. printf("*********************************\n");
  162. int pwmc = 10;
  163. printf("SetClock pwmc=%d and enable MS mode\n", pwmc);
  164. pwmSetClock(pwmc);
  165. pwmSetMode(PWM_MODE_MS);
  166. printf("Wait for start ...\n");
  167. delay(250);
  168. printf("Start:\n");
  169. for (int c_pmwr=0, c_pmwr_end = sizeof(tests_pwmr)/sizeof(tests_pwmr[0]); c_pmwr<c_pmwr_end; c_pmwr++) {
  170. int pwmr = tests_pwmr[c_pmwr];
  171. double freq = 19200.0/(double)pwmc/(double)pwmr;
  172. if (freq>MaxFreq) {
  173. printf("* Set Clock (pwmc, pwmr) %d, %d not possible on system (to slow to measure %g kHz with ISR), ignore\n", pwmc, pwmr, freq);
  174. continue;
  175. }
  176. sprintf(msg, "Set range (pwmr) %d", pwmr);
  177. pwmSetRange(pwmr);
  178. for (int c_pmw=0, c_pmw_end = sizeof(tests_pwm)/sizeof(tests_pwm[0]); c_pmw<c_pmw_end; c_pmw++) {
  179. int pwm = pwmr*tests_pwm[c_pmw]/100;
  180. sprintf(msg, "Set pwm %d/%d (%d %%)", pwm, pwmr, tests_pwm[c_pmw]);
  181. pwmWrite(PWM, pwm);
  182. delay(250);
  183. MeasureAndCheckFreq(msg, freq);
  184. }
  185. }
  186. result = wiringPiISRStop(FREQIN);
  187. CheckSame("\n\nRelease ISR", result, 0);
  188. if (result < 0) {
  189. printf("Unable to release ISR for GPIO %d (%s)\n\n", FREQIN, strerror(errno));
  190. return UnitTestState();
  191. }
  192. printf("set PWM@GPIO%d (output) back to input\n", PWM);
  193. pinMode(PWM, INPUT);
  194. }
  195. printf("\nDid %d PWM GPIO tests with model %d\n", testruns, RaspberryPiModel);
  196. return UnitTestState();
  197. }