Amis 30543 spi

Hello,

Do you have a library (or sample code) to control 4 wired stepper motor with AMIS 30543 driver and mbed LPX 1768 uC ?

Hello.

We do not have any libraries for using the AMIS-30543 driver with the mbed LPC1768 microcontroller, but you could use the AMIS-30543 library for Arduino as a starting point. You can find that library as one of the recommended links under the “Resources” tab of the driver’s product page, titled “AMIS-30543 library for Arduino”.

The commands to send to the AMIS 30543 over the SPI bus would be the same, but you would need to adapt the code to send them using the LPC1768 controller’s SPI module. If you get started writing your program and run into trouble, you could post the code you have so far and a description of your issue here and we might be able to help you troubleshoot.

-Josh.

DONE

#include "mbed.h"

SPI amis30543(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8); // chip sellect
DigitalOut nextStep(p9); // Step move
DigitalOut direction(p10); // Direction

void writeReg(uint8_t address, uint8_t value) {
    cs = 0;
    amis30543.write(0x80 | (address & 0b11111)); // I do not know why :S
    amis30543.write(value);
    cs = 1;
    wait(0.005);
}

void step(void) {
  nextStep = 1;
  wait(0.005);
  nextStep = 0;
  wait(0.005);
}

void changeDir(int dir) {
    wait(0.005);
    if(dir == 0) {
        writeReg(0x02, 0x80); // CR1 - Change Direction
    }
    else {
        writeReg(0x02, 0x00); // CR1 - Change Direction
    }
    wait(0.005);
}

int main() {
    int i = 0;
    wait(1);

    writeReg(0x03, 0x80); // CR2
    writeReg(0x00, 0x00); // WR
    // for CR0: 132mA->E0, 485mA->E5, 955mA-> EC 
    writeReg(0x01, 0xE0); // CR0
    writeReg(0x02, 0x80); // CR1
    writeReg(0x09, 0x00); // CR3

    wait(0.005);
    while(1) {
        changeDir(0);
        for(i=0; i<=1000; i++)
            step();
        changeDir(1);
        for(i=0; i<=1000; i++)
            step();
    }
}

Just to confirm, does the code work now or is there a specific problem you are having with it?

I noticed the “I do not know why :S” in your code comments, so maybe I can help clarify why the packet is formed that way. A common method of working with data packets is using bitfields. The format for the SPI packet you are using can be found in pages 31 and 32 of the AMIS-30543 datasheet:

From there, you can see that the first BYTE of the SPI transfer is specified in the following way:

MSB				 .... 			LSB
CMD2	CMD1	CMD0	ADDR4	ADDR3	ADDR2	ADDR1	ADDR0

In this case, the command and address are packed into a single byte instead of two separate ones. As you can see, the three most significant bits (CMD2:0) specify the command to be performed, while the last 5 bits (ADDR4:0) specify the address of the register.

Bitfields are constructed and manipulated via a series of bit-wise logic operations. By starting off with 0x80, it sets the CMD2 bit to 1, which selects the “WRITE” operation, which you can see if you convert 0x80 to binary and overlay it on the bitfield:

0x80 = 0b10000000

MSB				 .... 			LSB
CMD2	CMD1	CMD0	ADDR4	ADDR3	ADDR2	ADDR1	ADDR0
1	0	0	0	0	0	0	0

This also sets the address bits (ADDR4:0) to zero; in order to include the address bits (ADDR4:0), the result is ORed with address. Since those bits are zero, this has the effect of setting the address bits to whatever address happens to be, while leaving the command bits unchanged. Before ORing, the address is first masked with the “& 0b11111” operation which effectively zeros out the three most significant bits of the address while leaving the last 5 bits of the address intact. This ensures the command bits (CMD2:0) are not accidentally overwritten by the final OR operation in the event an invalid address is sent to your writeReg function.

Of course the second byte sent is just the data to be written to the selected address and does not require any special manipulation because it is not packed into a bitfield. To learn more about bitfields (and how to manipulate them) in more detail, check out this wikipedia article:

The code (I wrote above) works very well. Motor spins with no problem. I improved the code as below, but Josh you seems like claver one. So could you please explain why I can not read every steps one by one? Serial output shows 4-5 steps period. You know, I should read 0-511 step numbers, but I read say 1, 5, 9, 13, 18, 23, 27, 31… sometimes 4 and sometimes 5 steps. Do you have an idea?

#include "mbed.h"

SPI amis30543(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8); // chip sellect
DigitalOut nextStep(p9); // Step move
DigitalOut direction(p10); // Direction
Serial pc(USBTX, USBRX); //  Used for printf to PC over USB
// Delays are in MicroSeconds
float stepDelay = 20.0f;
float directionDelay = 100.0f;
float registerDelay = 5.0f;
uint8_t tempByte = 0;
uint16_t readPos = 0;

void writeReg(uint8_t address, uint8_t value) {
    cs = 0;
    amis30543.write(0x80 | (address & 0b11111)); // I do not know why :S, Josh explained why anyway
    amis30543.write(value);
    cs = 1;
    wait_us(registerDelay);
}

void step(void) {
  nextStep = 1;
  wait_us(stepDelay);
  nextStep = 0;
  wait_us(stepDelay);
}

void changeDir(int dir) {
    wait_us(directionDelay);
    if(dir == 0) {
        writeReg(0x02, 0x80); // CR1 - Change Direction
    }
    else {
        writeReg(0x02, 0x00); // CR1 - Change Direction
    }
    wait_us(directionDelay);
}

uint8_t readReg(uint8_t address) {
    cs = 0;
    tempByte = amis30543.write(address & 0b11111);
    cs = 1;
    return tempByte;
}

/*! Reads a status register and returns the lower 7 bits (the parity bit is
 *  set to 0 in the return value). */
uint8_t readStatusReg(uint8_t address) {
    // Mask off the parity bit.
    // (Later we might add code here to check the parity
    // bit and record errors.)
    return readReg(address) & 0x7F;
}

uint16_t readPosition() {
    uint8_t sr3 = readStatusReg(0x07); // SR3 0x07
    uint8_t sr4 = readStatusReg(0x0A); // SR4 0x0A
    return ((uint16_t)sr3 << 2) | (sr4 & 3);
}

int main() {
    pc.baud(9600);
    int i = 0;
    wait(1);

    writeReg(0x03, 0x80); // CR2
    writeReg(0x00, 0x00); // WR
    // for CR0: 132mA->X0, 485mA->X5, 955mA-> XC 
    writeReg(0x01, 0x00); // CR0
    writeReg(0x02, 0x80); // CR1
    writeReg(0x09, 0x01); // CR3

    wait_us(registerDelay);
    while(1) {
        changeDir(0);
        for(i=0; i<=51200; i++) {
            if(i%1 == 0) {
                //readPos = readPosition();
                //pc.printf("%hd\n", readPos);
            }
            step();
        }
        changeDir(1);
        for(i=0; i<=51200; i++) {
            step();
            //wait_us(200);
            if(i%1 == 0) {
                //readPos = readPosition();
                //pc.printf("%hd\n", readPos);
            }
        }
    }
}

It could be that you are sending data too fast to the serial terminal. If you send step pulses at a lower rate, do the numbers still skip?