Advertisement
Guest User

Arduino 3-phase motor control

a guest
Dec 23rd, 2015
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.98 KB | None | 0 0
  1. #define USE_LCD
  2. #define REQUIRE_ENABLE_BUTTON
  3.  
  4.  
  5. #ifdef USE_LCD
  6. #include <Wire.h>
  7. #include <LiquidCrystal_I2C.h>
  8.  
  9. LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
  10.  
  11. #define LCD_UPDATEINTERVAL_MS 50
  12.  
  13. #endif //USE_LCD
  14.  
  15. /*
  16. //NOTE: Changing timer 0 (or was it some other...) will fuck up delay(), millis() etc., need to scale the values again
  17. //---------------------------------------------- Set PWM frequency for D5 & D6 -------------------------------
  18.  
  19. //TCCR0B = TCCR0B & BRIDGE11111000 | B00000001;    // set timer 0 divisor to     1 for PWM frequency of 62500.00 Hz
  20. //TCCR0B = TCCR0B & BRIDGE11111000 | B00000010;    // set timer 0 divisor to     8 for PWM frequency of  7812.50 Hz
  21.   TCCR0B = TCCR0B & BRIDGE11111000 | B00000011;    // set timer 0 divisor to    64 for PWM frequency of   976.56 Hz (The DEFAULT)
  22. //TCCR0B = TCCR0B & BRIDGE11111000 | B00000100;    // set timer 0 divisor to   256 for PWM frequency of   244.14 Hz
  23. //TCCR0B = TCCR0B & BRIDGE11111000 | B00000101;    // set timer 0 divisor to  1024 for PWM frequency of    61.04 Hz
  24.  
  25.  
  26. //---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------
  27.  
  28. //TCCR1B = TCCR1B & BRIDGE11111000 | B00000001;    // set timer 1 divisor to     1 for PWM frequency of 31372.55 Hz
  29. //TCCR1B = TCCR1B & BRIDGE11111000 | B00000010;    // set timer 1 divisor to     8 for PWM frequency of  3921.16 Hz
  30.   TCCR1B = TCCR1B & BRIDGE11111000 | B00000011;    // set timer 1 divisor to    64 for PWM frequency of   490.20 Hz (The DEFAULT)
  31. //TCCR1B = TCCR1B & BRIDGE11111000 | B00000100;    // set timer 1 divisor to   256 for PWM frequency of   122.55 Hz
  32. //TCCR1B = TCCR1B & BRIDGE11111000 | B00000101;    // set timer 1 divisor to  1024 for PWM frequency of    30.64 Hz
  33.  
  34. //---------------------------------------------- Set PWM frequency for D3 & D11 ------------------------------
  35.  
  36. //TCCR2B = TCCR2B & BRIDGE11111000 | B00000001;    // set timer 2 divisor to     1 for PWM frequency of 31372.55 Hz
  37. //TCCR2B = TCCR2B & BRIDGE11111000 | B00000010;    // set timer 2 divisor to     8 for PWM frequency of  3921.16 Hz
  38. //TCCR2B = TCCR2B & BRIDGE11111000 | B00000011;    // set timer 2 divisor to    32 for PWM frequency of   980.39 Hz
  39.   TCCR2B = TCCR2B & BRIDGE11111000 | B00000100;    // set timer 2 divisor to    64 for PWM frequency of   490.20 Hz (The DEFAULT)
  40. //TCCR2B = TCCR2B & BRIDGE11111000 | B00000101;    // set timer 2 divisor to   128 for PWM frequency of   245.10 Hz
  41. //TCCR2B = TCCR2B & BRIDGE11111000 | B00000110;    // set timer 2 divisor to   256 for PWM frequency of   122.55 Hz
  42. //TCCR2B = TCCR2B & BRIDGE11111000 | B00000111;    // set timer 2 divisor to  1024 for PWM frequency of    30.64 Hz
  43.  
  44.  */
  45.  
  46. #ifdef REQUIRE_ENABLE_BUTTON
  47. //DEBUGGING: Enable switch must be held down for commutation to occur
  48. #define ENABLE_PIN 12
  49. #endif //REQUIRE_ENABLE_BUTTON
  50.  
  51. //PWM pins
  52. #define BRIDGE1_HIGH 5
  53. #define BRIDGE1_LOW 6
  54. #define BRIDGE2_HIGH 9
  55. #define BRIDGE2_LOW 10
  56. #define BRIDGE3_HIGH 3
  57. #define BRIDGE3_LOW 11
  58.  
  59. #define HALL1_PIN 2
  60. #define HALL2_PIN 4
  61. #define HALL3_PIN 7
  62.  
  63. #define H1 1
  64. #define H2 2
  65. #define H3 4
  66. #define H1H2 3
  67. #define H1H3 5
  68. #define H2H3 6
  69.  
  70. #define DTI_MICROSECONDS 100
  71.  
  72. bool hall1 = false;
  73. bool hall2 = false;
  74. bool hall3 = false;
  75.  
  76. //"Old" values for detecting changes, different values than the h1-h3 above so first call will cause commutation
  77. bool oldHall1 = true;
  78. bool oldHall2 = true;
  79. bool oldHall3 = true;
  80.  
  81. //Controlling simple dead time insertion
  82. unsigned long dtiStart = 0;
  83.  
  84. bool phaseSwitch = false;
  85.  
  86. #ifdef USE_LCD
  87. unsigned long lcdUpdate = 0;
  88. #endif //USE_LCD
  89.  
  90. void setup()
  91. {
  92. #ifdef REQUIRE_ENABLE_BUTTON
  93.   //NOTE: Pullup-setup, the button needs to connect to GND
  94.   pinMode(ENABLE_PIN, INPUT_PULLUP);
  95. #endif
  96.  
  97.   pinMode(HALL1_PIN, INPUT);
  98.   pinMode(HALL2_PIN, INPUT);
  99.   pinMode(HALL3_PIN, INPUT);
  100.  
  101.   pinMode(BRIDGE1_HIGH, OUTPUT);
  102.   pinMode(BRIDGE1_LOW, OUTPUT);
  103.   pinMode(BRIDGE2_HIGH, OUTPUT);
  104.   pinMode(BRIDGE2_LOW, OUTPUT);
  105.   pinMode(BRIDGE3_HIGH, OUTPUT);
  106.   pinMode(BRIDGE3_LOW, OUTPUT);
  107.  
  108.   killPWM();
  109.  
  110. #ifdef USE_LCD
  111.   lcd.begin(16,2);
  112.   lcd.home ();
  113.   lcd.print("Initializing...");  
  114. #endif //USE_LCD
  115.  
  116.  
  117. }
  118.  
  119. void loop()
  120. {
  121.  
  122. #ifdef REQUIRE_ENABLE_BUTTON
  123.   if(digitalRead(ENABLE_PIN))
  124.   {
  125.     killPWM();
  126.     #ifdef USE_LCD
  127.       lcd.home ();
  128.       lcd.print("Not enabled    ");
  129.       delay(100);
  130.     #endif
  131.     return;
  132.   }
  133. #endif
  134.  
  135.   if(readHalls())
  136.   {    
  137.     killPWM();
  138.   }
  139.  
  140.  
  141.   commutate();    
  142.  
  143. #ifdef USE_LCD
  144.    if((millis() - lcdUpdate) > LCD_UPDATEINTERVAL_MS)
  145.    {
  146.     lcd.home ();
  147.     lcd.print("H1:");
  148.     lcd.print(hall1 ? "1" : "0");
  149.     lcd.print(" H2:");
  150.     lcd.print(hall2 ? "1" : "0");
  151.     lcd.print(" H3:");
  152.     lcd.print(hall3 ? "1" : "0");
  153.     lcdUpdate = millis();
  154.    }
  155.    
  156. #endif
  157.  
  158. }
  159.  
  160. /**
  161.  * Reads the inputs from hall-pins and returns whether changes were detected
  162.  * @return True, if a hall-sensor state has changed, otherwise false
  163.  */
  164. bool readHalls()
  165. {
  166.   oldHall1 = hall1;
  167.   oldHall2 = hall2;
  168.   oldHall3 = hall3;
  169.   hall1 = digitalRead(HALL1_PIN);
  170.   hall2 = digitalRead(HALL2_PIN);
  171.   hall3 = digitalRead(HALL3_PIN);
  172.  
  173.   if(oldHall1 != hall1 || oldHall2 != hall2 || oldHall3 != hall3)
  174.   {
  175.     return true;
  176.   }
  177.  
  178.   return false;
  179. }
  180.  
  181. void killPWM()
  182. {
  183.   analogWrite(BRIDGE1_HIGH, 0);
  184.   analogWrite(BRIDGE1_LOW, 0);
  185.   analogWrite(BRIDGE2_HIGH, 0);
  186.   analogWrite(BRIDGE2_LOW, 0);
  187.   analogWrite(BRIDGE3_HIGH, 0);
  188.   analogWrite(BRIDGE3_LOW, 0);
  189.  
  190.   //Prepare to switch phase PWMs after DTI
  191.   dtiStart = micros();
  192.   phaseSwitch = true;
  193. }
  194.  
  195. void commutate()
  196. {
  197.   //TODO: Constant duty cycle for now
  198.   int dutyCycle = 255;
  199.   if(phaseSwitch && (micros() - dtiStart) > DTI_MICROSECONDS)
  200.   {
  201.     //Read latest states
  202.     readHalls();
  203.  
  204.     unsigned int hallState = (hall1 << 0) | (hall2 << 1) | (hall3 << 2);
  205.    
  206.     switch(hallState)
  207.     {
  208.       case H1:
  209.         analogWrite(BRIDGE1_HIGH, dutyCycle);
  210.         analogWrite(BRIDGE3_LOW, dutyCycle);
  211.         break;
  212.       case H2:        
  213.         analogWrite(BRIDGE2_HIGH, dutyCycle);
  214.         analogWrite(BRIDGE1_LOW, dutyCycle);
  215.         break;
  216.       case H3:        
  217.         analogWrite(BRIDGE3_HIGH, dutyCycle);
  218.         analogWrite(BRIDGE2_LOW, dutyCycle);
  219.         break;
  220.       case H1H2:        
  221.         analogWrite(BRIDGE2_HIGH, dutyCycle);      
  222.         analogWrite(BRIDGE3_LOW, dutyCycle);
  223.         break;
  224.       case H1H3:
  225.         analogWrite(BRIDGE1_HIGH, dutyCycle);
  226.         analogWrite(BRIDGE2_LOW, dutyCycle);      
  227.         break;
  228.       case H2H3:
  229.         analogWrite(BRIDGE3_HIGH, dutyCycle);
  230.         analogWrite(BRIDGE1_LOW, dutyCycle);      
  231.         break;
  232.       default:
  233.         #ifdef USE_LCD
  234.         lcd.home();
  235.         lcd.print("Unknown hallstate:");
  236.         lcd.setCursor(0, 1);
  237.         lcd.print(hallState);
  238.         delay(1000);
  239.         #endif
  240.         break;      
  241.     }
  242.  
  243.     #ifdef USE_LCD
  244.     lcd.setCursor(0, 1);
  245.     lcd.print(hallState);    
  246.     #endif
  247.  
  248.     phaseSwitch = false;
  249.   }
  250. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement