Posts

Advanced brushless DC motor controller

BLDC rev.0

BLDC rev.0

I got pretty tired of coding recently and had to switch my brain to something as distant from USB protocol as possible. Also, I’ve being planning a quadcopter build for which I need a motor controller less basic than PPM-driven R/C electronic speed controller AKA ESC. I needed something fast, reliable and scalable and at the same time not too hard to understand. After studying several existing open source designs I decided to make my own. This article is a status report of testing the initial prototype of sensorless brushless DC motor controller.

The prototype can be seen in the middle of the title picture (click on it to make it bigger). The green board contains a controller ( Allegro A4960 ) plus power stage – 6 N-type MOSFETS. In addition to performing typical control functions – setting speed and direction of 3-phase brushless sensorless DC motor, this controller also has a tachometer and fault indicator outputs as well as number of configuration registers available via SPI interface. The controller IC consists of 2 main functional blocks – a logical interface and power bridge driver. The former is compatible with 3.3V and 5V logic and the latter is specified in 5.5V-50V range (startup is possible from as low as 6V), making it suitable for projects ranging from 2S LiPo-powered models to electric scooter drives.

Here is a brief explanation of controller operation. First of all, both logic and motor voltages must be present. Then, a RUN bit must be set to “1” in RUN register using SPI – this is a safety feature which prevents uncontrolled start-ups. After that, when PWM signal is present, controller initiates start-up sequence commutating motor windings in open loop. When sensorless commutation is achieved, current to the motor is supplied according to PWM duty cycle.

Open loop start-up can be tricky, especially if a motor is heavily loaded. Even though I have had no issues starting several different motors on the bench using default power-up settings, if necessary start-up hold, timing, and ramp settings can be changed. Overall, 3 config registers are allocated for start-up parameters. Other 3 config registers hold less useful blank time, dead time, as well as current limit and internal PWM values.

The RUN register contains some very interesting settings. First of all, it holds RUN, DIR and BRAKE bits used for start/stop, direction change and braking. It is also possible to route different diagnostic signals to DIAG output pin. The most useful part of this register is phase advance angle setting. Adjusting its value according to speed/load conditions can significantly increase motor power output.

In addition to all this A4960 IC provides extensive diagnostic. Loss of sync, two-level high case temperature flags, gate drive undervoltage, as well as MOSFET faults are recorded in Diagnostic register and can be used to stop the controller. Also, other situations which can be harmful for power bridge are tracked and if something bad happens controller switches to fail-safe mode.

All this plus a number of other features make this controller ideal for builders implementing advanced motor control. I had a lot of fun playing with settings while observing how they change the motor behaviour. The first prototype is performing very well, delivering good power while staying cool. At the moment, I don’t have any numbers – I learned very quickly that a propeller makes poor (and painful) bench load and is hard to make measurements. I’m now waiting for parts to make a proper load and re-routing the board to fix the errors and add features – aiming at 100A/phase.

Stay tuned!

Oleg.

104 comments to Advanced brushless DC motor controller

  • Kevin Groce

    Awesome project Oleg!

  • Markus

    That looks like a really cool project Oleg. I’d love to try the A4960 myself – would you be interested in sharing your prototype board (design or physical prototype if you have spares)?

    • The design is not complete yet and I don’t have any more boards, sorry. Stay tuned – the next prototype will be much better.

  • hhanff

    Hi! We are using the a4960 and I have observed an undocumented behaviour. To ensure that the problem does not lie within I my code, I would like to know if you too had do the following to change the direction of the BLDC motor:
    (i) Transmit RUN register with disabled RUN bit
    (ii) Transmit RUN register with toggled DIR bit
    (iii) Transmit RUN register with ENabled RUN bit

    • I haven’t tried to switch directions on the running motor. Maybe the start sequence times out too fast? Try to disable the timeout (don’t remember the bit name).

  • uhallgeo

    Oleg-

    I am playing with the A4960 too. It is driving me crazy. It will not reliably start my motor. Sometimes it runs my motor, sometimes it doesn’t. When it doesn’t, the DIAG register reports a 0xC000, a POR (power on reset). When it does run the motor, the DIAG reports a 0x823F.

    I am driving the A4960 with a C8051F310 with a 3.3vDC VDD, but running the A4960 at 5vDC does make things better.

    I feel as if I’m doing something fundamentally wrong. However I have followed the reference design.

    Do you have any suggestions???

    • Thomas

      Have you been able to solve this problem?
      If – how?

      Regards, Thomas

      • I meant ‘I always getting POR bit in the first read of the chip’. I’m not considering this to be a problem, it clears up by itself in subsequent reads.

  • uhallgeo

    Oleg-

    Running the A4960 at 5vDC does NOT make things better. (Sorry about my typing.)

    • IIRC you need to set RSC bit so controller would keep trying to open-loop after timeout (or any other loss of BEMF sync. I can stop the motor by hand and it will start in open-loop ). POR is always set after power-on, you need to read the register once to clear it.

  • uhallgeo

    Oleg-

    Spot on! Thanks!!

    Are you running your A4960 VDD at 5vDC or 3.3vDC??

    • I only tried logic part at 5V. Motor should be 6 or more to function. Also, the A4960 is quite sensitive to voltage sags on motor power rail. I was unable to reliably start even small motor off of 6A bench supply and had to run 3S LiPo in parallel to it.

  • Vitalii

    Hi!
    I develop new controller for brushless BLDC motor (the same as you use).
    But my goal is to manage motors on low rotation speeds with microstepping.
    So, I want use this kind of motors as stepper.
    It’s interesting for different goals because while I use BLDC instead of stepper, I have effect like magnetic levitation, which make movements smoother.

    If you interested in, we can start work together.
    If not, please, give me a help with it.
    because now my biggest issue is to chouse right controller for motor.

    Thanks!

  • paolo_s46

    hello! this is a request for help/suggestions. I have an arduino usb shield and its library. What I want to do is to collect the data from the meteo station oregon wmrs200. I know the protocol to decode the data, what I want to know is how to get the stream of reports of 8 bytes from which extract the info. I do not need descriptors and other conplex things. I started with the example USBHID_desc and I get just a page, and stop. I am quite an usb novice !!
    is this the right place to post this request ??

  • yarden

    hey oleg, how did you know which values of parameters to send the driver in order to start up the motor?
    did you use any considerations?

  • Awesome project Oleg,

    I’m wondering if you could offer sharing for arduino code and the A4960 schematic? I’m building an opensource electric bicycle. Currently I work for the battery protection and charger, but I would love to include, in a near futur, the motor controller 😉

    Cheers,
    Olivier

  • Ed Beamon

    I need help finding a simple circuit i can build out of old electronics to run a hard drive motor with a battery

  • Hello. I’m working in a project of a brushless using the same controller, A4960, but I’m having problems to make it work. Please, can you send the arduino code to me?

    Thanks and congratulations for the project

    • #include <SPI.h>
       
      const int slaveSelectPin = 9;
       
      uint8_t pwm = 20;
       
      #define PWM 3
      #define STATUS_DLY 2000
       
      void setup(){
       
        pinMode ( 10, OUTPUT);
        pinMode (slaveSelectPin, OUTPUT);
       
        TCCR2B = TCCR2B & 0b11111000 | 0x01;
       
        pinMode( PWM, OUTPUT );
        analogWrite( PWM, pwm );
        digitalWrite(10,HIGH);
       
        SPI.begin();
        SPI.setClockDivider(SPI_CLOCK_DIV4);
       
       
        Serial.begin(115200);
        Serial.println(F("Start"));
       
          // take the SS pin low to select the chip:
        digitalWrite(10,LOW);
        //  send in the address and value via SPI:
        SPI.transfer(0xf0);
        SPI.transfer(0x39);
        // take the SS pin high to de-select the chip:
        digitalWrite(10,HIGH); 
      }
       
      void loop() {
       
       
        uint8_t tmp;
        static uint32_t dly;
       
        if( Serial.available() > 0 ) {
          tmp = Serial.read();
       
          switch( tmp ) {
            case 'u':
              analogWrite( PWM, ++pwm );
              Serial.println( pwm );
              break;
       
            case 'd':
               analogWrite( PWM, --pwm );
               Serial.println( pwm );
               break;
          }
        } 
       
        if(dly < millis()) {
          dly = millis() + STATUS_DLY;
          Serial.print(F("Status: "));
           digitalWrite(10,LOW);
          Serial.print(SPI.transfer(0xf0), HEX);
          Serial.print(F(" "));
          Serial.print(SPI.transfer(0x39), HEX);
          Serial.println(F(""));
          digitalWrite(10,HIGH);
        }
      /*  
        uint8_t tmp;
       
        delay(5000);
        Serial.println(F(""));
       
            // take the SS pin low to select the chip:
        digitalWrite(10,LOW);
        //  send in the address and value via SPI:
        tmp = SPI.transfer(0xf0);
        Serial.print(tmp, HEX);
        Serial.print(F(" "));
        tmp = SPI.transfer(0x39);
        Serial.print(tmp, HEX);
          // take the SS pin high to de-select the chip:
        digitalWrite(10,HIGH); 
       
      */
       
      }
  • Hey, thanks for the code. It’s very simple.
    And, I’d like to as for one more thing.
    Could you sent the schematic to my email? I’m having problems to make my board works, and have already tryed everything in the code. Maybe I have a hardware problem.

  • Y.S.

    Hello Oleg:

    Could you share us the complete circuit diagram? Please and thanks.

  • Y.S.

    Hmmm, I read the datasheet by myself before, but I just cannot really understand it. (http://www.allegromicro.com/Products/Motor-Driver-And-Interface-ICs/Brushless-DC-Motor-Drivers/~/media/Files/Datasheets/A4960-Datasheet.ashx)

    I am not good at electronics X_X

    Anyway, thanks for your replying.

  • Niklas

    Hi Oleg!

    Im wondering if it’s possible to look at your schematic on your BLDC controller, im currently working on the same chip for a quadcopter ESC.

    Regards

  • Niklas

    Ok, but cant you drive a less Amp motor(10A) with your setup or is it only for 100A motors?

    Do you think theese N-Fet’s will work ?
    http://www.st.com/internet/analog/product/219669.jsp

    • You can but it’s going to be too expensive. Any MOSFET will work as long as specs are not exceeded. At this time, I don’t understand this controller well enough to offer any advice on components.

  • Niklas

    Ok Oleg, thank you anyway for your time on this.

    Regards Niklas

  • markP

    Oleg, Quick question. What value caps did you end up using for Cboot and Creg?

  • Thomas

    Hello Oleg,
    What frequency do you use for the PWM-input of A4960?
    Regards, Thomas

  • Thomas

    And what’s about the config register? In your code, you’ve posted above you only set the DG1, DG0, RSC and RUN bits. Do you initialize the other registers somewhere else?

    • No, the code is all that is necessary to start the controller. The frequency is also set in the sketch since default Arduino PWM freq. is too low.

  • Thomas

    okay, thanks!

  • Thomas

    Feel free to copy my header-file for A4960:

    http://pastebin.com/dQA79wxf

    Regards, Thomas

  • Thomas

    Hysteresis was wrong. heres the new one:
    http://pastebin.com/Ac8RbhAD

  • Augusto

    Hi !

    I’m working on a project that involves the A4960 and it’s giving me a lot of trouble. The brushless is having problems to start runing. First I thougt it was the program, by the way, I’m using a PIC 18F1220, I saw your code and mine is no diffrent (in the main code) so I think It could be the schematic that is wrong.I did use the one shown in the datasheet but i steel don’t see what is wrong. Would you please send your schematic file to me ? So I can see if/what is wrong with my project.

    Thanks a lot !

  • Hi Oleg,

    i am going to build my own A4960 Application, also aiming for up to 100A. I wonder what R sense Value you’ve chosen for the CSP/CSM resistor. My calculations result in a tremendous small Value, about 0.01OHM and lower.

    Regards,
    Michael

  • Thomas

    Hello Oleg!

    At the motor-start – what do you get from A4960 on SDO?

    Because my motor is running, but if I set the run-reg I get 0xC000 on the SDO, what means a power-on-reset.
    One reason for a POR could be, that the Vdd voltage drops under Vdduv. But since I’ve decoupled it with 100nF to Ground this can’t be the reason. I’ve also measured Vdd and it’s stable on 3V3.

    Do you (or anybody else) have an idea?

    Regards,
    Thomas

  • Hi Oleg. Very good project. I will tried to do It. What N-Mosfets have used?

    Regards,
    Jaume Nogues

  • nathaya

    hai oleg sir,
    I am working on a project with brushless dc motor control using arduino … and i am having some problem to drive the motor…sir can u suggest a program including that sensor positon(reference papper AN00857, microchip)

  • khs

    hi
    I just want to run bldc motor in open loop mode. Does controller is required for open loop operation and if yes which controller should I prefer

  • Damian

    Hello Oleg
    Can you give me complette code and schematic of your project ? 😉
    J can try build bldc driver to quadrocopter based on A4960 and J can’t find any practical materials of this topic :<
    Sorry for my bad english (I come from Poland :))

  • Al B

    Oleg,

    You should try to build your prototype as an Arduino shield since so far I have not been able to find one that can control BLDC motors.

  • Mehrshd

    Nice info.
    I was thinking to designe an ESC with 4960 and IMO there is not enough and detiled informtion about it.
    Now I am turning to dspic33fj based controller with reluctance startup.
    I have finished the dsp based and 4960 based pcbs but after reading this topic I will consentrate on dsp based.

  • Mehrshad

    Dear Oleg,

    What will happen if we START the chip when motor is turning?
    In RC ESCs when brake is off, they can run the motor on the fly.Can this chip do that?or motor should be stopped before starting?
    Did you ever test this?

    • The controller senses back EMF to time energizing of the windings. I tried to start the controller while the motor was spinning – it seems that in this case a startup open-loop swithching is skipped. It also initiates the startup when I stop the spinning motor, e.g., by hand.

  • Mehrshd

    Thanks a lot Oleg,

    It was very helpful for me.
    My target application is a 200A/34V ESC for large scale RC car.(PCBs are ready)
    The start up quality and time is very important for me. do you think it will do the job by tuning the startup parameters?
    Thanks in advance,
    Ali

    • If you want good startup torque use sensored motor/controller. Allegro makes sensored controller similar to one I’ve used.

  • Mehrshad

    You are right but large inrunner motors for RC car applications are sensorless.(Like one I have)
    I am designing a dsp based controller at the same time and I think the reluctance method will do the job better.
    A custom design is more flexible and of course more difficult!
    The dealer says that the moq of 4960 is 5pcs and 25$ each!!!!(Unfortunately there is no official distributor for electronic parts in Iran )
    Thats why I am going to be sure about the performance of the chip before my order.
    Finally thanks for helping me to find out the best solution.
    Ali

  • JoãoF

    Hello, Oleg!

    Thanks for this amazing job.
    I’m trying to make my project work with your code, but my motor doesn’t move at all. All I keep getting at the Serial Monitor is “Status: 80 0”, even when I don’t power the circuit with the 11.8V Battery.
    How did you connect your Arduino with the A4960 interface?

    On my Arduino Mega 2560, I’m using MOSI pin (51) as SDI; MISO (50) as SDO; SCK (52) as SCK; Pin 10 as STRN; and Pin 3 as the PWM signal output.

    Thanks in advance.

  • JoãoF

    Thanks! But just another thing:
    Did you connect the TACHO (pin 7) from A4960 to any pin on your Arduino?
    Thanks in advance.

  • cuukee

    I made same A4960 module with same UNO board.
    but motor doesn’t work.
    I receive serial like this,

    Status: 80 0

    I cann’t find my faults.. How can I make like Oleg’s one..
    Oleg god, do you guess something?
    I always start RESETN to low during 4us for reset faults, then high. else source is same with commented Oleg’s.
    DIAG and TACHO pins is not connected.
    I connected only SPI(4wires) and PWM and RESETN.

  • cuukee

    Oleg, I made it. It works. I love you. thanks so.

  • claytoncn

    Hi Oleg, thanks for your great work on the A4960 bldc driver, how did you deal with the exposed pad, shoul we tie it to GND or just make it float(not connected), this just made me confused. Thanks for your reply 🙂

  • Viktor

    Hy Oleg!
    I have a problem with my A4960. It start the motor, but when i try to raise the spreed it allways stop. I can just run my motor on a very low speed. Do you have any idea what can be the problem. I use 5kHz for pwm frekvency.

    • You can read the status from the chip to see what’s going on. My guess is your power supply is not good enough for the motor, when you spin the motor up the voltage drops, the chip detects undervoltage (or insufficient top gate drive) and shuts down the output until you reset the chip.

  • jeff

    Ok, the controller works great with a small (I guess about 50W) motor. Once I switch to a larger 500W motor, it just does not work. The power stage alone was tested and it works fine with the large motor.
    I’ve tried the large motor with a different controller as well and it works too. Since my large motor has greater moment of inertia, I suspect that the controller (A4960 one) can not handle it-I hear a “click” as it would try and start the large motor and then nothing.
    Is there a possibility that I have to adjust the controller settings? If so, which ones?
    Thanks!

    • What is the max.current into the winding? The controller has current limit set by a sense resistor and a value in a register, make sure you’ll never exceed it otherwise current limit will trip and then you’d have to reset it in software. The A4960 itself is just a MOSFET driver, it won’t provide any power to the motor.

      • jeff

        The VR[3:0] register is set to 1111, Vref is 5V, R_sense is .01 ohm. So according to the datasheet I_trip should be around 50 Amp. Will try to measure the current spike on startup…
        Are there any other controller parameters that could affect?
        Thanks!

        • Affect what? You don’t even know the current into the motor, without this type of data your guess is as good as mine.

          Make sure you’re measuring with a fast instrument like an oscilloscope equipped with a current probe. DMM won’t give you meaningful data.

        • mrkvo

          Be aware that Vref, if is greater than 2V, is clambed with internal zener diode to 2V. So Vref is always 2V if the input to Vref pin is >2V.

  • zara

    Hi
    but what about controlling this motor by position.
    i didn’t find any project to control it with a accuracy of 1 degree!!!!

    and there are millions of project about DC motor !

    please let me know

    • A brushless motor is like a stepper with 120 degree step, you can control it to one degree but it would require a microstepping of 120 and the motor will become very weak. If you need fine stepping use a stepper motor, like everyone else.

  • Ivan

    Hi Oleg,

    Just a quick one I’m struggling a bit with my A4960. I’m not sure just what PWM control to give it. What frequency and duty cycle range have you used please ?

    I would be very grateful for a tip on this.

    Happy new year

    Ivan

  • mrkvo

    Hi!
    I’m just developing diploma thesis with A4960. I’ve 4 drivers with motors
    http://www.modelmotors.cz/index.php?page=61&product=4120&serie=20&line=GOLD .
    Mosfets I’m using are StrongIRFet with 0.0011Ohm Rds(on), 40V Vds max and 90A Idmax. http://www.irf.com/product-info/datasheets/data/irf7946pbf.pdf .

    I’ve a problem that caused 24 mosfets to blow. Everything O.K., but after ~100 startups, the reading of TACHO pin goes wrong, it’s very harsh. Very variable pulse lenght is there. Then, there’s shoot-through and sad eyes. Pair of mosfets blown, next have some leakage, they’re not ok. But, the controller ok! I think there’ll be a problem whith startup, some big current occures there and causes the slow degradation of mosfets every startup. I use Rsense 0.005Ohm, current limit set at 35A. I’ve a few questions.. The motor does not startup smoothly. Is that correct, that you use powerful motor with default startup parameters? And do you know, what the Start commutation time and End commutation time means?
    BTW: Startup is limited by current, there is 20A limitation. Duty cycle 40uS, (PWM 25KHz because of high freq of sounds).

  • mrkvo

    RG= 2.7Ω in datasheet, I have 10R! I can’t ever imagine this could do such a disaster.. Low fall and rise times, local overheating in subrstrate. Could it be?
    Thank you

    • mrkvo

      I’m soory I’m asking a lot, but what do you think about the A4960 Gate output drive Rds(on)up = 21Ohm and Rds(on)down = 3Ohm? The down resistance seems to be ok, but the up resistance is by far the recommended 2.7Ohms at gate. I’m afraid I have chosen bad Mosfets for this application.

      • It’s likely not a resistor but a boost capacitor. IIRC the recommended value is 100x gate capacitance which is for your MOSFET would be 0.68uF. This could be excessive though; try to find minimum value with which a MOSFET is still happy. You don’t need to fully load your MOSFETs either, give them ~2-3A for the start, this way you won’t be burning them that fast.

        • mrkvo

          That could be the solution. I have only 220nF bootstrap capacitors in there. Thank you, I’ll post the results.

  • Ganesh

    Hi Oleg,

    I am working on sensorless BLDC motor, I m new bie to here so I am not that much familiar with this type of motor. Actually my requirement is to work the BLDC motor in Regenerative breaking type. I am using LPC2148 controller and BLDC is Avionics and ESP 20A.

    Thanks in advance,
    Ganesh K

  • Balázs

    Dear Oleg

    I readed your script from a4960 driver. It is interesting. I builded a bldc motor driver module with this, work wery well, but i failed to change the direction of rotation. Simply to change the dir bit value in the run register not is sufficient. Can you tell me, how y can solve this problem.

    Thank you

    • I don’t have this problem, mine switches direction just fine.

      • Balázs

        Thank you for your reply, today I solved this problem, In the APEK4960 application note are specified “Any change in direction not take place until the A4960is set to “stop” ten “run””, I observed this only today.

  • mrkvo

    Hi Oleg.
    Please, help again. See the picture, phase voltage. Rsense does not affects this. The BEMF rising waveform causes very bad behaviour. What could cause this?
    http://postimg.org/image/c9xf7rkzx/

    Thank you
    Milan