This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MCF8329A: Cannot get motor spinning on custom hardware

Part Number: MCF8329A
Other Parts Discussed in Thread: MOTORSTUDIO

Tool/software:

Hi,

I am trying to get going with a motordriver based around mcf8329a. However there seems to be a few issues in my setup. 

I have bought and tested everything with ti:s evaluation board for this device, and it is really working well with my motor. I have tuned and exported all the settings in a json.

Now however I am trying the same code on our own hardware and I am getting no expected results. The motor does not start spinning. Once scoped the phases ABC I can see that the driver is doing something, beginning with switching the phases with a 50kHz square on all phases, but after that nothing, no movement, no faults reported or anything. So I am a bit stuck. Do you have any idea of what could be the issue?

I have communication and I can talk to the mcf8329a, but I cannot get the motor turning over. I am using Arduino as a test platform.

Theese are my register settings;

    Register registers[] = {
        {0x00000080, 0xE2EBD667},
        {0x00000082, 0xC0E89EE6},
        {0x00000084, 0x50A24EC2},
        {0x00000086, 0x93372007},
        {0x00000088, 0x16788328},
        {0x0000008A, 0x9AAD5721},
        {0x0000008C, 0x1BF4182A},
        {0x0000008E, 0x60980960},
        {0x00000094, 0x00000000},
        {0x00000096, 0x00000000},
        {0x00000098, 0x80000004},
        {0x0000009A, 0x00000000},
        {0x0000009C, 0x00000000},
        {0x0000009E, 0x00000000},
        {0x00000090, 0x26483186},
        {0x00000092, 0x71402888},
        {0x000000A0, 0x0946027D},
        {0x000000A2, 0x02008165},
        {0x000000A4, 0x40032310},
        {0x000000A6, 0x40100000},
        {0x000000A8, 0x03E8C00C},
        {0x000000AA, 0x06A045C0},
        {0x000000AC, 0x80008079},
        {0x000000AE, 0x80000102},
        {0x000000E0, 0x00000000},
        {0x000000E2, 0x00000000},
        {0x000000E4, 0x24318C94},
        {0x000000E6, 0x00000000},
        {0x000000E8, 0x3A000000},
        {0x000000EA, 0x00000000},
        {0x000000EC, 0x80000000},
        {0x000000EE, 0x00000018},
        {0x000000F0, 0x030503A0},
        {0x000000F2, 0x02600160},
        {0x000000F4, 0x00000000},
        {0x00000196, 0x00000000},
        {0x0000019C, 0x045C1DE8},
        {0x0000040E, 0x00197857},
        {0x0000043C, 0x00440000},
        {0x0000043E, 0x00680000},
        {0x00000440, 0x00CC0000},
        {0x00000450, 0x00000002},
        {0x00000458, 0x00020002},
        {0x0000045C, 0x01FDA000},
        {0x00000460, 0x00033F62},
        {0x00000462, 0x000376CF},
        {0x00000464, 0x000261AE},
        {0x000004AA, 0xFA88A300},
        {0x000004AC, 0xF86B7264},
        {0x000004CC, 0x00A80000},
        {0x000004CE, 0x00A89616},
        {0x000004D0, 0xFFADDE8B},
        {0x000004D2, 0x008D6DC2},
        {0x000004DC, 0xFFA8A1F4},
        {0x000004DE, 0x0075FB02},
        {0x000004E0, 0x000BB21E},
        {0x000004E2, 0x008FFF8F},
        {0x0000051A, 0x00000000},
        {0x00000532, 0x00E9C550},
        {0x00000542, 0x04CCBAB0},
        {0x000005D0, 0x00000000},
        {0x0000060A, 0x00000000},
        {0x0000060C, 0x005F3E12},
        {0x000006B0, 0x00000005},
        {0x000006BA, 0x00000172},
        {0x000006E4, 0x0004000B},
        {0x0000071A, 0x00A737C2},
        {0x0000075C, 0xFFFFFEA1},
        {0x0000075E, 0x008E5BE6},
        {0x0000076E, 0x00000000},
        {0x00000774, 0x58830AD3}
    };

This is my layout;

I am interested in how startup and speed command is set over i2c with the evaluation kit. Which pins are asserted high/low to startup? 

I have tried to clear all faults, but no difference.

This is my code for setting speed;

// Function to set the motor speed using ALGO_DEBUG1 register
void setMotorSpeed(uint8_t address, uint16_t speed) {
    // Read the current value of ALGO_DEBUG1 register (address 0xEC)
    uint32_t currentValue = MCF8329AReadRegister(address, 0xEC);

    // Modify the SPEED_OVER_RIDE and DIGITAL_SPEED_CTRL fields
    currentValue |= 0x80000000; // Set SPEED_OVER_RIDE to 1 (bit 31)
    currentValue &= ~(0x1FFFF << 16); // Clear DIGITAL_SPEED_CTRL bits (30-16)
    currentValue |= ((speed & 0x1FFFF) << 16); // Set DIGITAL_SPEED_CTRL bits (30-16)

    // Split the modified value into bytes
    uint8_t byte4 = (currentValue >> 24) & 0xFF;
    uint8_t byte3 = (currentValue >> 16) & 0xFF;
    uint8_t byte2 = (currentValue >> 8) & 0xFF;
    uint8_t byte1 = currentValue & 0xFF;

    // Write the updated value back to ALGO_DEBUG1 register
    MCF8329AWriteRegister(address, 0xEC, byte4, byte3, byte2, byte1);
}

I am not sure if this is the correct way to set the motor rpm. Seems odd that it is a debug register.

Any help appreciated!

  • Hi Mikael,

    Thanks for sharing all details, I will go through this and get back to you.

    Thanks and Best Regards

    Venkatadri S

  • Hi,

    I proceeded and hooked up your eval-kit to my hardware, and with the same register settings i went to the gui and tried spinning my motor. This is working, at least a bit. I am getting to the part where I "Run MPET", where the motor spins up once. I then get the following error.

    19:15:7:685 | : Could not detect any MPET fault. Please check the tuning file..

    19:15:7:671 | :Beginning Motor Ke measurement...(Your motor will spin up slowly during this time)

    19:15:7:671 | : Motor ke measurement error...checking for faults.

    19:15:4:271 | :Beginning Motor Ke measurement...(Your motor will spin up slowly during this time)

    19:15:1:365 | : MPET run is successful.

    19:15:0:853 | :Motor MECH measurement complete.

    19:15:0:853 | : Beginning Motor MECH measurement.

    19:15:0:853 | : Motor Ke measurement complete.

    19:14:30:203 | :Beginning Motor Ke measurement...(Your motor will spin up slowly during this time)

    19:14:27:3 | : Running MPET...

    Any idea what is going on?

  • Ok, more progress here. I have managed to run the motor well from the eval-kit with my hardware. Now I just need a way of setting rpm using i2c. It is working from the eval mcu, but not from mine. So please verify that I am writing to the correct register. I am not sure which registers you write to when one click enable i2c speed setting in the gui? What is taking place in the background at that time? Also, what is the register setting correspond to in the bit 16-30 in 0xEC? Is this the correct reg to write speed commands through?

    I am very close, the motor runs from my arduino, but i cannot adjust rpm using i2c.

  • Hi Mikael,

    I will reply to you by end of my day today. Thanks for sharing the details.

    I will send instruction for MPET as well. 

    Please wait for my reply and then continue with MPET.

    Thanks and Best Regards

    Venkatadri S

  • Hi,

    The problem have since been resolved. I had some interfering features on my oem-board that made the MCF8329 unstable. 

    Since you have been very helpful to me I'd like to share something back. 

    So here are a few tips to get this module running with a motor, using Arduino and i2c;

    1. Use the evaluation kit and the motorstudio GUI to play around and set parameters for your specific motor. This is more or less mandatory. The amounts of settings is very demanding to get right without it. Export the register settings and update your Arduino code accordingly. (In the code below, sendAllMotorRegisters(address).
    2. Pay attention to the motor specific parameters, inductance and resistance is vital to get right for good performance. If you measure your motor using a LCR-meter, remember to cut phase to phase measurments in half.
    3. Make sure the hardware pins like Dir/wakeSleep/Brake and so on are in the correct state for your usage.
    4. If you have several drivers on the same i2c-bus, be sure to set the device_config2 dev_mode bit to sleep mode to be able to inactivate one of the modules while setting the address on the other using the wakeSleep-pin.
    5. In Arduino make sure to write to the registers with a slight delay, for settings to bite. I use the regular wire-libs successfully, but with a delay of 100us after each sent complete register.

    The code below is what I am using to run mcf8329a in Arduino, for anyone getting started with a similar project. This can handle up to 3 motor drivers on the same i2c-bus. The input speed command accepts positive and negative speed values, setting the direction pin accordingly, so that the motor is fully reverseable. The code example uses a MCF8329A with a set i2c-address of 0x02.

    #include <Wire.h>
    
    #define NUM_MOTORS 3 // Define the number of motors
    
    // Define arrays for motor constants
    uint8_t motorSpeedPins[NUM_MOTORS] = {0, 0, 13};
    uint8_t motorOnOffPins[NUM_MOTORS] = {0, 0, 41};
    uint8_t fgPins[NUM_MOTORS] = {0, 0, 22};
    uint8_t nFaultPins[NUM_MOTORS] = {0, 0, 14};
    uint8_t brakePins[NUM_MOTORS] = {0, 0, 15};
    uint8_t directionPins[NUM_MOTORS] = {0, 0, 21};
    uint8_t speedAnaPins[NUM_MOTORS] = {0, 0, 20};
    
    void setup() {
    
        // Define the motor pins
        for (int i = 0; i < NUM_MOTORS; i++) {
            pinMode(directionPins[i], OUTPUT);
            pinMode(motorSpeedPins[i], OUTPUT);
            pinMode(brakePins[i], OUTPUT);
            pinMode(motorOnOffPins[i], OUTPUT);
            pinMode(speedAnaPins[i], OUTPUT);
    
            digitalWrite(motorOnOffPins[i], LOW);
            digitalWrite(motorSpeedPins[i], LOW);
            digitalWrite(brakePins[i], LOW);
            digitalWrite(speedAnaPins[i], LOW);
        }
    
        for (int i = 0; i < NUM_MOTORS; i++) {
            pinMode(nFaultPins[i], INPUT_PULLUP);
            pinMode(fgPins[i], INPUT_PULLDOWN);
        }
    
        Wire.begin(); // Join I2C bus as master
        Serial.begin(9600);
        delay(100);
    
        // Clear faults and send initial register values for each motor
        for (int i = 0; i < NUM_MOTORS; i++) {
            clearFaults(i);
            sendAllMotorRegisters(i);
            digitalWrite(motorOnOffPins[i], LOW);
        }
    
        delay(1000);
    }
    
    void readAndPrintMotorFaultStatus(uint8_t address) {
        uint32_t gateDriverFaultStatus;
        uint32_t controllerFaultStatus;
    
        gateDriverFaultStatus = MCF8329AReadRegister(address, 0xE0);
        controllerFaultStatus = MCF8329AReadRegister(address, 0xE2);
    
    
        // Serial.print("GATE_DRIVER_FAULT_STATUS: 0x");
        // Serial.println(gateDriverFaultStatus, HEX);
        if (gateDriverFaultStatus == 0x00000000 && controllerFaultStatus == 0x00000000) {
            Serial.println("No faults");
        }
    
        if (gateDriverFaultStatus != 0x00000000) {
            Serial.println("Gate Driver Faults detected:");
            if (gateDriverFaultStatus & (1 << 31)) Serial.println("  - DRIVER_FAULT");
            if (gateDriverFaultStatus & (1 << 29)) Serial.println("  - OTS_FAULT (Over Temperature Fault)");
            if (gateDriverFaultStatus & (1 << 28)) Serial.println("  - OCP_VDS_FAULT (Overcurrent VDS Fault)");
            if (gateDriverFaultStatus & (1 << 26)) Serial.println("  - OCP_SNS_FAULT (Overcurrent Sense Fault)");
            if (gateDriverFaultStatus & (1 << 25)) Serial.println("  - BST_UV_FAULT (Bootstrap UV Fault)");
            if (gateDriverFaultStatus & (1 << 24)) Serial.println("  - GVDD_UV_FLT (GVDD UV Fault)");
            if (gateDriverFaultStatus & (1 << 23)) Serial.println("  - DRV_OFF (DRV Off Status)");
        }
    
        if (controllerFaultStatus != 0x00000000) {
            Serial.println("Controller Faults detected:");
            if (controllerFaultStatus & (1 << 31)) Serial.println("  - CONTROLLER_FAULT");
            if (controllerFaultStatus & (1 << 29)) Serial.println("  - IPD_FREQ_FAULT (IPD Frequency Fault)");
            if (controllerFaultStatus & (1 << 28)) Serial.println("  - IPD_T1_FAULT (IPD T1 Fault)");
            if (controllerFaultStatus & (1 << 26)) Serial.println("  - BUS_CURRENT_LIMIT_STATUS");
            if (controllerFaultStatus & (1 << 24)) Serial.println("  - MPET_BEMF_FAULT (BEMF Constant Measurement Error)");
            if (controllerFaultStatus & (1 << 23)) Serial.println("  - ABN_SPEED (Abnormal Speed Motor Lock)");
            if (controllerFaultStatus & (1 << 22)) Serial.println("  - ABN_BEMF (Abnormal BEMF Motor Lock)");
            if (controllerFaultStatus & (1 << 21)) Serial.println("  - NO_MTR (No Motor Fault)");
            if (controllerFaultStatus & (1 << 20)) Serial.println("  - MTR_LCK (Motor Lock Triggered)");
            if (controllerFaultStatus & (1 << 19)) Serial.println("  - LOCK_LIMIT (Lock Ilimit Fault)");
            if (controllerFaultStatus & (1 << 18)) Serial.println("  - HW_LOCK_LIMIT (Hardware Lock Ilimit Fault)");
            if (controllerFaultStatus & (1 << 17)) Serial.println("  - DCBUS_UNDER_VOLTAGE (DC Bus Undervoltage Fault)");
            if (controllerFaultStatus & (1 << 16)) Serial.println("  - DCBUS_OVER_VOLTAGE (DC Bus Overvoltage Fault)");
            if (controllerFaultStatus & (1 << 15)) Serial.println("  - SPEED_LOOP_SATURATION");
            if (controllerFaultStatus & (1 << 14)) Serial.println("  - CURRENT_LOOP_SATURATION");
            if (controllerFaultStatus & (1 << 3)) Serial.println("  - WATCHDOG_FAULT");
        }
    }
    
    
    
    void clearFaults(uint8_t address) {
        uint32_t currentValue;
    
        // Read the current value of ALGO_CTRL1 register (address 0xEA)
        currentValue = MCF8329AReadRegister(address, 0xEA);
    
    
        // Modify the CLR_FLT bit (bit 29) to clear all faults
        currentValue |= (1 << 29); // Set CLR_FLT bit to 1
    
        // Split the modified value into bytes
        uint8_t byte4 = (currentValue >> 24) & 0xFF;
        uint8_t byte3 = (currentValue >> 16) & 0xFF;
        uint8_t byte2 = (currentValue >> 8) & 0xFF;
        uint8_t byte1 = currentValue & 0xFF;
    
    
    }
    
    
    void MCF8329AWriteRegister(uint8_t address, uint8_t control_word, uint8_t byte4, uint8_t byte3, uint8_t byte2, uint8_t byte1) {
        Wire.beginTransmission(address);
        Wire.write(0x10); // Control Word MSB
        Wire.write(0x00); // Control Word
        Wire.write(control_word); // Control Word LSB
        Wire.write(byte1); // Data LSB first
        Wire.write(byte2);
        Wire.write(byte3);
        Wire.write(byte4); // Data MSB last
        uint8_t error = Wire.endTransmission(); // Send stop condition
        if (error != 0) {
            Serial.println("Error: Write transmission failed");
        } else {
        }
        delayMicroseconds(100); // Stability delay
    }
    
    void sendAllMotorRegisters(uint8_t address) {
        // Register data
        struct Register {
            uint32_t addr;
            uint32_t value;
        };
        Register registers[] = {
            {0x00000080, 0xE2EBD667},
            {0x00000082, 0xC0E89EE6},
            {0x00000084, 0x50A24EC2},
            {0x00000086, 0x93372007},
            {0x00000088, 0x16788328},
            {0x0000008A, 0x9AAD5721},
            {0x0000008C, 0x1BF4182A},
            {0x0000008E, 0x60980960},
            {0x00000094, 0x00000000},
            {0x00000096, 0x00000000},
            {0x00000098, 0x80000004},
            {0x0000009A, 0x00000000},
            {0x0000009C, 0x00000000},
            {0x0000009E, 0x00000000},
            {0x00000090, 0x26483186},
            {0x00000092, 0x71402888},
            {0x000000A0, 0x0946027D},
            {0x000000A2, 0x02008165},
            //{0x000000A4, 0x40232300}, //this sets the address of i2c, do not enable if you don't intend to change default address of motor driver
            {0x000000A6, 0x40100000},
            {0x000000A8, 0x03E8C00C},
            {0x000000AA, 0x06A045C0},
            {0x000000AC, 0x80008079},
            {0x000000AE, 0x80000102},
            {0x000000E0, 0x00000000},
            {0x000000E2, 0x00000000},
            {0x000000E4, 0x24318C94},
            {0x000000E6, 0x00000000},
            {0x000000E8, 0x3A000000},
            {0x000000EA, 0x00000000},
            {0x000000EC, 0x80000000},
            {0x000000EE, 0x00000018},
            {0x000000F0, 0x030503A0},
            {0x000000F2, 0x02600160},
            {0x000000F4, 0x00000000}
        };
    
        for (int i = 0; i < sizeof(registers) / sizeof(registers[0]); i++) {
            uint8_t control_word = (registers[i].addr >> 24) & 0xFF; // Extract control word from address
            uint8_t byte4 = (registers[i].value >> 24) & 0xFF;
            uint8_t byte3 = (registers[i].value >> 16) & 0xFF;
            uint8_t byte2 = (registers[i].value >> 8) & 0xFF;
            uint8_t byte1 = registers[i].value & 0xFF;
    
            MCF8329AWriteRegister(address, control_word, byte4, byte3, byte2, byte1);
        }
    }
    
    
    
    void loop() {
        // Test Write Operation
        readAndPrintMotorFaultStatus(0x02);
        digitalWrite(motorSpeedPins[0x02], HIGH);
        clearFaults(0x02);
        setMotorSpeed(0x02,4000);
        delay(3000);
        setMotorSpeed(0x02,-6000);
        delay(3000);
    
    }
    
    
    uint32_t MCF8329AReadRegister(uint8_t address, uint8_t command) {
        uint8_t data[4] = {0};
    
        // Send command
        Wire.beginTransmission(address);
        Wire.write(0xA0); // Register MSB
        Wire.write(0x00); // Register LSB
        Wire.write(command); // Register LSB
        Wire.endTransmission(false);
        delayMicroseconds(100);
        Wire.endTransmission(true);
        // Read results
        Wire.requestFrom(address, (uint8_t)4); // Request 4 bytes
        if (Wire.available() == 4) {
            data[0] = Wire.read();
            data[1] = Wire.read();
            data[2] = Wire.read();
            data[3] = Wire.read();
        } else {
            return 0xFFFFFFFF;
        }
    
        uint32_t result = (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0];
        return result;
    }
    
    void setMotorSpeed(uint8_t address, int16_t speed) {
        // Ensure the address is within range
        if (address >= NUM_MOTORS) {
            Serial.println("Error: Invalid motor address");
            return;
        }
    
        // Determine direction pin based on the address
        uint8_t directionPin = directionPins[address];
    
        // Determine direction based on the sign of the speed
        if (speed < 0) {
            digitalWrite(directionPin, HIGH); // Set direction to reverse
            speed = -speed; // Use the absolute value of speed
        } else {
            digitalWrite(directionPin, LOW); // Set direction to forward
        }
    
        uint32_t currentValue;
    
        // Read the current value of ALGO_DEBUG1 register (address 0xEC)
    
        currentValue = MCF8329AReadRegister(address, 0xEC);
    
        // Enable SPEED_OVER_RIDE bit and set the new 15-bit speed value
        currentValue |= 0x80000000; // Set SPEED_OVER_RIDE to 1 (bit 31)
        currentValue &= 0x8000FFFF; // Preserve SPEED_OVER_RIDE bit and clear DIGITAL_SPEED_CTRL bits (30-16) and lower two bytes
        currentValue |= ((speed & 0x7FFF) << 16); // Set new 15-bit speed value in bits 30-16
    
        // Extract the bytes from the modified value
        uint8_t byte1 = currentValue & 0xFF; // LSB
        uint8_t byte2 = (currentValue >> 8) & 0xFF;
        uint8_t byte3 = (currentValue >> 16) & 0xFF;
        uint8_t byte4 = (currentValue >> 24) & 0xFF; // MSB
    
        // Write the updated value back to ALGO_DEBUG1 register
        MCF8329AWriteRegister(address, 0xEC, byte4, byte3, byte2, byte1);
    }
    
    
    

  • Hi Mikael,

    Appreciated the details and status which you are providing. I am going through this thread and provide observations.

    This thread got locked, I am trying to reopen to continue discussion.

    Thanks and Best Regards

    Venkatadri S