Difference between revisions of "Arduino - 12V DC Motor with constant RPM"

From Blue-IT.org Wiki

(Realisation)
(Code)
Line 55: Line 55:
 
   // ...
 
   // ...
 
    
 
    
 +
  // set PWM pins 9 and 10 to 31000 MHz for better motor management
 
   TCCR1B = TCCR1B & 0b11111000 | 0x01;   
 
   TCCR1B = TCCR1B & 0b11111000 | 0x01;   
 
   pinMode(pwmPin_Motor, OUTPUT);
 
   pinMode(pwmPin_Motor, OUTPUT);
 
   pinMode(sensorPinTCST2103, INPUT);
 
   pinMode(sensorPinTCST2103, INPUT);
 
   
 
   
 +
  ///////////////////////////////////////////
 
   // INIT MOTOR AND TEST
 
   // INIT MOTOR AND TEST
actualRPM = 2;  // should start the motor  
+
  actualRPM = 2;  // should start the motor  
 +
  ///////////////////////////////////////////
 
   
 
   
 
  }
 
  }
 
   
 
   
+
 
 
  void loop() {
 
  void loop() {
 
   
 
   
   // Drehgeber (pulseCount)
+
   // pulseCount
 
   
 
   
 
   // you have to determine in which range the TCST2103 delivers data.  
 
   // you have to determine in which range the TCST2103 delivers data.  
Line 92: Line 95:
 
   }
 
   }
 
   
 
   
   ////////////////////////////////////
+
   /////////////////////////////////////////////////
 
   // CHECK ONLY EVERY 1000ms (usigned interval)
 
   // CHECK ONLY EVERY 1000ms (usigned interval)
 
   // check to see if it's time to do something -  
 
   // check to see if it's time to do something -  

Revision as of 02:34, 6 February 2017

Motivation

There are many manuals out there how to control large DC motors with e.g. a Mosfet or ready to install pwm boards with an arduino. In practical usage however you will be confronted with some problems using this methods in real world setups. Especially when a nearly constant revolution speed is needed.

You could use a large stepper motor to achieve this. But this could be very expensive. On the other hand the approach shown here is very simple and only needs very few skills.

Realisation

We will power an 12V wind shield motor:

  1. Wind shield 12V motor from an old car, get it from a scrap yard or ebay (~ 15 €)
  2. BTS7960 43A H-Bridge PWM - 5,5 V bis 27V and lot of amps (~ 10 €)
  3. OR a Mosfet Fairchild BUZ11, a big diode (6 amps), resistor 100 Ohm (see: http://bildr.org/2012/03/rfp30n06le-arduino) (~2 €)
  4. Power supply 12V (for LED) 80W (~ 12 €)

What we do for this is a feedback from the motor about its driving speed. We will therefore need a sensor:

  1. Light barrier sensor - infrared type TCST2103 (~ 2 €)
  2. Two resistors 100 Ohm (some cents)
  3. A simple self made gear wheel (costs: 0)
  4. Arduino


How to wire up your keypad or your lcd is not shown in the code.

I am also only checking ONE direction. For resolving directory change you need two light barrier sensors and a slightly more complicated code.

Code

const int pwmPin_Motor = 9;
const int sensorPinLB_TCST2103 = A0;

int minSpeed_Motor = 30; // minimum PWM to get the motor turning
int increment_Motor = 5; // increment in PWM  (soft speedup / - down)
 
int actualRPM = 0;    // range: 0 - 9; 
                      // theoretical speed of the motor 
                      // multiplier necessary see later in the code
int actualPWM = 0;    // range: 0 - 255;
int pulseCount = 0;   // max. Interval 0-9 when using a foiled keyboard like me
int prevLBLevel = 0;  // for TCST2103

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time of action was updated

// interval at which to check pulses (milliseconds)
// be careful changing: affects pulseCountExzenter!
const unsigned long interval = 1000;
  
 
void setup() {

  // lcd and other stuff
  // ...
 
  // set PWM pins 9 and 10 to 31000 MHz for better motor management
  TCCR1B = TCCR1B & 0b11111000 | 0x01;  
  pinMode(pwmPin_Motor, OUTPUT);
  pinMode(sensorPinTCST2103, INPUT);

 ///////////////////////////////////////////
 // INIT MOTOR AND TEST
 actualRPM = 2;   // should start the motor 
 ///////////////////////////////////////////

}

 
void loop() {

 // pulseCount

 // you have to determine in which range the TCST2103 delivers data. 
 // in my setup ( twp 100 ohm resistors) it delivers data between 740 and 900 (theoretically 0-1023)
 int actLBLevel = map(analogRead(sensorPinLB_TCST2103),740,900,0,9);
 
 if ( prevLBLevel == actLBLevel )
 {
   // wait until the next segment is comming ...
 }
 else
 {  
   if (actLBLevel >= 5 && prevLBLevel < 3 ) // actual Level is High (Sensor is hidden)
   {   
      pulseCount +=1;
      prevLBLevel = actLBLevel;
   }

   if (actLBLevel < 3 && prevLBLevel >= 5 ) // actual Level is LOW (Sensor is free)
   {   
      pulseCount +=1;
      prevLBLevel = actLBLevel;
   }
 }

 /////////////////////////////////////////////////
 // CHECK ONLY EVERY 1000ms (usigned interval)
 // check to see if it's time to do something - 
 // the difference between the current time and last time
 unsigned long currentMillis = millis();

 if (currentMillis - previousMillis >= interval)
 {

   // save the last time
   previousMillis = currentMillis;    

   ////////////////////////////////////////////////////////////////
   // SpeedUP the motor according due to its possibilities
   // actualRPMExzenter is limited to 9
   // pulseCountExzenter depends on the motor - you should reach a value
   // slightly above 200 - to have reserves at maximum speed
   pulseCountExzenter = (int)(pulseCountExzenter/1.2);

   int increment = increment_Motor; 

   if (actualPWM <= 255 && actualPWM >= 0) 
   { 
       if ( pulseCount == actualRPM )
       {
         // Motor speed is reached - do nothing
       }
       else 
       {
         // increase speed
         if (pulseCount < actualRPM) 
         {
           if ( actualPWM < minSpeed_Motor )
           {              
               actualPWM += minSpeed_Motor;
           }
           // almost reached, only 1 PWM steps ...
           else if ( pulseCount >= actualRPM-1 )
           {
              actualPWM += 1; 
           }
           // not over 255
           else if (actualPWM <= ( 255 - increment ) ) 
           {
                 actualPWM += increment;
           }
          }
         
         // decrease speed
         else
         {
           if (  pulseCount <= actualRPM+1 )
             actualPWM -= 1;
           else
             actualPWM -= increment;
         }
       }     
   }

   analogWrite(pwmPin_Motor, actualPWM);

   // RESET pulseCountExzenter
   pulseCount = 0;

   // end if for interval
 }
 
// end loop
}