Guest User

Electronic Load Code (1 MOSFET Set)

a guest
Mar 23rd, 2019
200
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * Electronic Load
  3.  * http://www.kerrywong.com
  4.  * 10/2013
  5.  */
  6. #include <SPI.h>
  7. #include <LiquidCrystal.h>
  8. #include <Encoder.h>
  9. #include <SPI.h>
  10.  
  11. //LCD pins
  12. const int pinRS = 7;
  13. const int pinEn = 6;
  14. const int pinD4 = 5;
  15. const int pinD5 = 4;
  16. const int pinD6 = 3;
  17. const int pinD7 = 2;
  18.  
  19. //analog pin 5
  20. const int pinLoadVoltage = 14;
  21.  
  22. //MCP4921 SPI
  23. const int PIN_CS = 10;
  24.  
  25. const int BTN_RESET = 16;
  26. const int BTN_RANGE_X2 = 17;
  27. const int BTN_MODE = 18;
  28. const int BTN_ENC = 15;
  29.  
  30. const int IDX_BTN_RESET = 0;
  31. const int IDX_BTN_RANGE_X2 = 1;
  32. const int IDX_BTN_MODE = 2;
  33. const int IDX_BTN_ENC = 3;
  34. const int LOOP_MAX_COUNT = 2000;
  35.  
  36. int DACGain = 1; //default gain 1xVref.
  37.  
  38. int loadMode = 0; // 0: Constant Current, 1: Constant Power
  39. const float EXT_REF_VOLTAGE = 0.333;
  40.  
  41. LiquidCrystal lcd(pinRS, pinEn, pinD4, pinD5, pinD6, pinD7);
  42. Encoder currentAdjEnc(8, 9);
  43.  
  44. int buttons[]={BTN_RESET, BTN_RANGE_X2, BTN_MODE, BTN_ENC};
  45. int buttonReadings[3];
  46. int lastButtonStates[]={HIGH, HIGH, HIGH, HIGH};
  47. int currentButtonStates[]={HIGH, HIGH, HIGH, HIGH};
  48. long lastDebounceTime[3];
  49.  
  50. long oldEncPosition = -999;
  51. long curEncPosition = 0;
  52. int DACSetStep = 1;
  53. int encoderValue = 0;
  54. int loopCounter = 0;
  55. int DACSetValue = 0;
  56.  
  57. long ADSum = 0;
  58.  
  59. float vLoad = 0.0;
  60. float setPower = 0.0;
  61. float setCurrent = 0.0;
  62.  
  63. void setup()
  64. {
  65.     for (int i = 0 ; i < 4 ; i++) {
  66.         pinMode(buttons[i], INPUT);
  67.         digitalWrite(buttons[i], HIGH);
  68.     }
  69.    
  70.     pinMode(PIN_CS, OUTPUT);
  71.     SPI.begin();  
  72.     SPI.setClockDivider(SPI_CLOCK_DIV2);
  73.  
  74.     lcd.begin(16, 2);
  75. }
  76.  
  77. void getCurrentEncPosition()
  78. {
  79.     curEncPosition = currentAdjEnc.read() / 4;
  80.    
  81.     if (curEncPosition != oldEncPosition) {
  82.         if (curEncPosition > oldEncPosition) {
  83.             encoderValue += DACSetStep;
  84.            
  85.             if (encoderValue > 4095) encoderValue = 4095;
  86.         } else {
  87.             encoderValue -= DACSetStep;
  88.            
  89.             if (encoderValue < 0) encoderValue = 0;
  90.         }
  91.        
  92.         oldEncPosition = curEncPosition;
  93.        
  94.         if (loadMode == 0) //Constant Current mode
  95.         {
  96.             setDACOutput(encoderValue);
  97.         } else { //Constant Power mode
  98.             setDACOutput(DACSetValue);
  99.         }
  100.     }
  101. }
  102.  
  103. //Buffered DAC output
  104. void setDACOutput(unsigned int val)
  105. {
  106.     byte lByte = val & 0xff;
  107.     //                      SHDN     GA            BUF
  108.     byte hByte = val >> 8 | 0x10 | DACGain << 5 | 1 << 6;
  109.    
  110.     PORTB &= 0xfb;
  111.     SPI.transfer(hByte);
  112.     SPI.transfer(lByte);
  113.     PORTB |= 0x4;    
  114. }
  115.  
  116. void displayStatus()
  117. {  
  118.     lcd.clear();    
  119.  
  120.     //average load voltage
  121.     vLoad = ADSum * 1.0 / (float) LOOP_MAX_COUNT / 1024.0 * 5.0  * (2 + 1);
  122.  
  123.     if (loadMode == 0) //Constant Current
  124.     {
  125.         float vSense = 1.0 * encoderValue / 4096.0 * EXT_REF_VOLTAGE;
  126.         float i = 1 * 10 * vSense; // 1 sets of MOSFET in parallel, 0.1 ohm
  127.         if  (DACGain == 0) i *=2; // x2
  128.    
  129.         lcd.print("CI,I Set=");
  130.    
  131.         if (i < 1.0) {
  132.             lcd.print(i * 1000,0);
  133.             lcd.print(" mA");
  134.         } else {
  135.             lcd.print(i ,2);
  136.             lcd.print(" A");
  137.         }
  138.     } else { //Constant Power
  139.         setPower = (float) encoderValue / 20.0; //approximately 0-200W
  140.  
  141.         lcd.print("CP, P Set=");        
  142.         if (vLoad > 0.5) {//minimum 0.5V
  143.             setCurrent = setPower / (float) vLoad;
  144.            
  145.             //desired sense voltage. Since we have 1
  146.             //sets of MOSFETS, the results are devided
  147.             //by 1 and multipled by the value of the sense
  148.             //resistor
  149.             float vSense = setCurrent / 1.0 * 0.1;
  150.          
  151.             DACSetValue = (int) (vSense/EXT_REF_VOLTAGE * 4096.0 + 0.5);
  152.  
  153.             if (setCurrent < 10.0) {
  154.                 DACGain = 1;                
  155.             } else {
  156.                 DACGain = 0;
  157.                 DACSetValue = (int) ((float) DACSetValue / 2.0 + 0.5);
  158.             }                        
  159.            
  160.             if (setPower >= 100.0) {
  161.                 lcd.print(setPower, 1);
  162.             }
  163.             else {
  164.                lcd.print(setPower, 2);    
  165.             }
  166.         } else {
  167.             setPower = 0;
  168.             lcd.print(setPower, 2);
  169.         }
  170.        
  171.         setDACOutput(DACSetValue);
  172.         lcd.print("W");
  173.     }
  174.    
  175.     lcd.setCursor(0, 1);
  176.     lcd.print("LOAD V=");
  177.     lcd.print(vLoad, 2);
  178.     lcd.print(" V");        
  179. }
  180.  
  181. void loop()
  182. {
  183.     int idx = 0;
  184.    
  185.     for (int i = 0 ; i < 4; i++) {
  186.         buttonReadings[i] = digitalRead(buttons[i]);
  187.        
  188.         if (buttonReadings[i] != lastButtonStates[i]) lastDebounceTime[i] = millis();
  189.        
  190.         if (millis() - lastDebounceTime[i] > 50) { //debouncing the buttons
  191.             if (currentButtonStates[i] != buttonReadings[i]) {
  192.                 currentButtonStates[i] = buttonReadings[i];                                
  193.                
  194.                 //actions
  195.                 if (currentButtonStates[i] == LOW) {
  196.                     switch (i) {
  197.                         case IDX_BTN_RESET:
  198.                         //reset output current to 0
  199.                            encoderValue = 0;
  200.                            DACSetValue = 0;
  201.                            break;
  202.                         case IDX_BTN_RANGE_X2:
  203.                         //switch between 100W/200W maximum power mode
  204.                             DACGain = DACGain == 1? 0 : 1;
  205.                            
  206.                             if (loadMode == 0) {
  207.                                 setDACOutput(encoderValue);
  208.                             }
  209.                             break;
  210.                         case IDX_BTN_MODE:
  211.                         //switch between constant current and constant power
  212.                             loadMode = loadMode == 1? 0 : 1;
  213.                             break;
  214.                         case IDX_BTN_ENC:
  215.                         //cycle through different encoder steps: 1/10/100
  216.                             DACSetStep *= 10;
  217.                            
  218.                             if (DACSetStep > 100) DACSetStep = 1;
  219.                             break;
  220.                     }
  221.                 }
  222.             }
  223.         }
  224.        
  225.         lastButtonStates[i] = buttonReadings[i];
  226.     }        
  227.  
  228.     getCurrentEncPosition();    
  229.     loopCounter++;
  230.    
  231.     // used to smooth out the analogRead results
  232.     ADSum += analogRead(pinLoadVoltage);
  233.    
  234.     if (loopCounter == LOOP_MAX_COUNT) {
  235.         displayStatus();
  236.         loopCounter = 0;
  237.         ADSum = 0;
  238.     }
  239. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×