Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Amis30543 spi q [SOLVED]

Been having a rough time communicating with this chip. I am using a Raspberry Pi 3 with Python 3.4 and the spidev library. I’ve communicated with other SPI devices but this one is not responding as I expect. During a google I see a guy with an Intel Edison having very similar issues in not getting back expected data. It’s enough for me to come here and see if whoever wrote the arduino lib had any particular issues getting it to work.

Link to logic analyzer screen shot

As I read the docs, I sent a write command to set the current limit then the command to read (plus another with CS still low) but nothing came back on the second byte. I seemingly randomly get what I expect once then 0x00 of 0xff. If the chip is assumed to be working with 12VDC on the motor supply are my SPI signals not proper ?

Thanks for any info or pointers !

Hello.

We do not recall having any real issues with the SPI interface of the AMIS-30543 Stepper Motor Driver Carrier.

What are your SPI settings? It might be helpful for you to look at the AMIS-30543 library for Arduino on our GitHub page and use it as a reference on how to communicate with the stepper motor driver carrier via SPI.

If you cannot find the problem, you can post your entire code here, and I would be happy to take a look.

- Amanda

I just noticed the logic analyzer screenshot your posted. From that screenshot, it looks like you are sending the correct signals to the driver to write and read from the CR0 register. So the problem is less likely to be in your code or SPI settings and more likely to be a wiring problem. Since you said that you sometimes get the expected answer, maybe one of your connections is loose. You might try using a multimeter to verify each of your connections by doing a continuity test.

- Amanda

Thanks for the response. After I bought a couple of non-SPI boards to use from you guys, I went back determined to find out what was going on. After setting up my tests again everything worked…! On a hunch I checked it out and my original placement on my breadboard was such that a slightly warped backing on the breadboard did not allow for a common ground between board power (aka motor power) and I/O power. So, problem solved :slight_smile:

That’s great! I am glad you figured out the problem and fixed it; thanks for letting us know.

- Amanda

Hello,

I am newbie to SPI communication and coding stuff. I trying to use AMIS-30543 stepper driver to control nema 17 stepper motor by raspberry pi and python spidev library. Could you please help me how to code for enabling the driver and setting the current limits? Any help will be very much appreciated.

Thanks in advance!!

“I am newbie to SPI communication and coding stuff”

Some tips:

  • learn python: click here to learn python
    – the web tutorials are not python 3, the latest, but will get you going. Afterwards google the differences between python 2.7 and 3.x then stick with 3 as official support for 2.7 is waning and will eventually cease though there is still a strong community

  • understand how ssh works on your pi. you may be using your pi as the full development system but as you get more understanding and your project matures, you will most likely gravitate to a headless (no monitor/keyboard/mouse/etc) system where the box is controlling your steppers and you communicate via ethernet from a different development system

  • get PyCharm click here to get PyCharm
    – they have a trial for their their pro version which includes remote debug and deployment (via ssh) is a full featured IDE for python. This is a tremendous boost to development

  • take small steps; divide your project (or create a test project with a “small” goal)
    – get the py spi dev lib, connect your SPI MOSI to MISO and write a small script to transfer some data, essentially to yourself as a test. Experiment with all the options, esp speed to see how far you can push your system and discover how to handle errors in this exceptionally basic test

  • read the AMIS programming guide and write a short program to write and read AMIS registers to understand how to ensure a good start/reset state; as you are now getting into the hardware side of things ensure every ground from pi to AMIS is connected or you will have strange faults or simply nothing works; consider getting a relatively inexpensive logic probe (I have a BitScope Micro for light stuff click here to get BitScope Micro note expected values will be inverted so won’t make sense at first and is not documented); oh buy some cheap tiny heat sinks to put one on the AMIS chip

Search Pololu first but I didn’t see any for this small chip so found: click here to get Cosmos heat sink off Amazon

Good Luck !

Thanks for your reply. It’s very informative and helpful to me. Do you have any python sample code that writes and reads SPI registers? I have been searching for syntax but i haven’t found any. It will be great help to me if you can provide a sample code or syntax for writing and reading to registers so that I can start off from that point

Thanks for your time and help!!

The below is a program for testing a stepper motor I wrote and not what I would release as a finished product by any means. No guarantee of use or that the code won’t break your system so apply at your own risk. This is provided for educational purposes only:

# copyright 2016 psionprime as registered user of pololu.com support forums

import sys
if sys.version_info < (3, 5):
    raise "must use python 3.5 or greater"
else:
    print("- python interpreter >= 3.5")

import gpiozero
from spidev import SpiDev
import time
import random


class AMIS30543_Controller():

    def __init__(self, DO_STEP_PIN, DO_DIRECTION_PIN, DO_RESET_PIN, DI_FAULT_PIN):
        """
        AMIS-30543 Stepper Controller Class
        :param DO_STEP_PIN:
        :param DO_DIRECTION_PIN:
        :param DO_RESET_PIN:
        :param DI_FAULT_PIN:
        """

        # AMIS−30543 Registers & Command constants
        self.REG = {
            'WR':  0x00,
            'CR0': 0x01,
            'CR1': 0x02,
            'CR2': 0x03,
            'CR3': 0x09,
            'SR0': 0x04,
            'SR1': 0x05,
            'SR2': 0x06,
            'SR3': 0x07,
            'SR4': 0x0A
        }

        self.CMD = {
        'READ': 0x00,
        'WRITE':0x80
        }

        # InitGPIO
        self.DO_STEP = gpiozero.LED(DO_STEP_PIN)
        self.DO_RESET = gpiozero.DigitalOutputDevice(DO_RESET_PIN)
        self.DO_DIRECTION = gpiozero.DigitalOutputDevice(DO_DIRECTION_PIN)
        self.DI_NO_FAULT = gpiozero.DigitalInputDevice(DI_FAULT_PIN)

        self.spi = SpiDev()
        self.spi.open(0, 0)
        self.spi.max_speed_hz = 1000000

        self.ResetStepper()


    def __del__(self):
        self.spi.close()

    def ResetStepper(self):
        self.DO_RESET.off()     # must be off for AMIS to see reset
        time.sleep(0.11)
        self.DO_RESET.on()
        time.sleep(0.11)
        self.DO_RESET.off()


    def StepIt(self):
        # future note maybe use PWM for hopefully much more steady hardware pulses
        if not self.DI_NO_FAULT:
            return
        self.DO_STEP.on()
        time.sleep(0.0001)
        self.DO_STEP.off()


    def RegisterDump(self):
        print("\nAMIS-30543 Registers\n")

        # check stepper status
        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['WR'], 0])
        print(" WR = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['CR0'], 0])
        print("CR0 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['CR1'], 0])
        print("CR1 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['CR2'], 0])
        print("CR2 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['CR3'], 0])
        print("CR3 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['SR0'], 0])
        print("SR0 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['SR1'], 0])
        print("SR1 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['SR2'], 0])
        print("SR2 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['SR3'], 0])
        print("SR3 = ", bin(resp[1]), " ", str(resp[1]))

        resp = self.spi.xfer2([self.CMD['READ'] | self.REG['SR4'], 0])
        print("SR4 = ", bin(resp[1]), " ", str(resp[1]))

        print("")


    def ReverseBits(self, byte):
        byte = ((byte & 0xF0) >> 4) | ((byte & 0x0F) << 4)
        byte = ((byte & 0xCC) >> 2) | ((byte & 0x33) << 2)
        byte = ((byte & 0xAA) >> 1) | ((byte & 0x55) << 1)
        return byte


    def test_RegisterRW(self):
        self.ResetStepper()

        self.spi.writebytes([self.CMD['WRITE'] | self.REG['WR'],  0b01111000])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR0'], 0b11110011])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR1'], 0b00100000])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR2'], 0b00001000])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR3'], 0b01000000])

        if self.spi.xfer2([self.CMD['READ'] | self.REG['WR'], 0])[1] != 0b01111000:
            print("Writing or reading self.REG['WR'] failed; driver power might be off.")
            return False


        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR0'], 0])[1] != 0b11110011:
            print("Writing or reading self.REG['CR0'] failed; driver power might be off.")
            return False


        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR1'], 0])[1] != 0b00100000:
            print("Writing or reading self.REG['CR1'] failed; driver power might be off.")
            return False


        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR2'], 0])[1] != 0b00001000:
            print("Writing or reading self.REG['CR2'] failed; driver power might be off.")
            return False

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR3'], 0])[1] != 0b01000000:
            print("Writing or reading self.REG['CR3'] failed; driver power might be off.")
            return False

        self.RegisterDump()
        print("test_RegisterRW Passed\n")

        self.ResetStepper()
        return True


    def SetRegDefaults(self):
        """
        Sets default values:
         WR: no watchdog
        CR0: 1/32 step & current limit to 1850mA
        CR1: CW motion (depending on wiring) & step on rising edge
        CR2: motor off & no sleep & SLA no transparent & SLA gain @ 0.5
        CR3: no extended step mode
        :return:
        """

        self.ResetStepper()

        self.spi.writebytes([self.CMD['WRITE'] | self.REG['WR'], 0b00000000])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR0'], 0b00010011])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR1'], 0b00000000])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR2'], 0b00000000])
        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR3'], 0b00000000])

        if self.spi.xfer2([self.CMD['READ'] | self.REG['WR'], 0])[1] != 0b00000000:
            print("Writing or reading self.REG['WR'] failed; driver power might be off.")
            return False

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR0'], 0])[1] != 0b00010011:
            print("Writing or reading self.REG['CR0'] failed; driver power might be off.")
            return False

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR1'], 0])[1] != 0b00000000:
            print("Writing or reading self.REG['CR1'] failed; driver power might be off.")
            return False

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR2'], 0])[1] != 0b00000000:
            print("Writing or reading self.REG['CR2'] failed; driver power might be off.")
            return False

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR3'], 0])[1] != 0b00000000:
            print("Writing or reading self.REG['CR3'] failed; driver power might be off.")
            return False

        self.RegisterDump()
        print("Register Defaults Enabled\n")

        return True


    def SetMotorEnable(self):
        """
        CR2: motor on & no sleep & SLA no transparent & SLA gain @ 0.5
        :return:
        """

        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR2'], 0b10000000])

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR2'], 0])[1] != 0b10000000:
            print("Writing or reading self.REG['CR2'] failed; driver power might be off.")
            return False


    def SetMotorDisable(self):
        """
        CR2: motor on & no sleep & SLA no transparent & SLA gain @ 0.5
        :return:
        """

        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR2'], 0b00000000])

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR2'], 0])[1] != 0b00000000:
            print("Writing or reading self.REG['CR2'] failed; driver power might be off.")
            return False


    def SetDirPos(self):
        """
        CR1: CW motion (depending on wiring) & step on rising edge
        :return:
        """

        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR1'], 0b00000000])

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR1'], 0])[1] != 0b00000000:
            print("Writing or reading self.REG['CR1'] failed; driver power might be off.")
            return False


    def SetDirNeg(self):
        """
        CR1: CCW motion (depending on wiring) & step on rising edge
        :return:
        """

        self.spi.writebytes([self.CMD['WRITE'] | self.REG['CR1'], 0b10000000])

        if self.spi.xfer2([self.CMD['READ'] | self.REG['CR1'], 0])[1] != 0b10000000:
            print("Writing or reading self.REG['CR1'] failed; driver power might be off.")
            return False


axis_X1 = AMIS30543_Controller(19, 26, 20, 21)
axis_X1.RegisterDump()
axis_X1.test_RegisterRW()

if not axis_X1.SetRegDefaults():
    sys.exit("Failed to set register defaults")

axis_X1.SetMotorEnable()

# steps for 250mm = .3mm/step with GT2 2mm belt and 30 tooth pully and using 1/32 micro steps
steps = int(250 * ((200 * 32) / (2 * 30)))

print("\nStep Test for 250mm requires ", steps, " steps")

tStart = time.monotonic()

# long test to see if still running in morning
# add a little randomness to not land on the same spot the whole test and potentialy shorten the life of th motor
random.seed()
bToggle = True
while(True):

    for step in range(int(steps + random.getrandbits(8))):
        axis_X1.StepIt()
        if not axis_X1.DI_NO_FAULT:
            print("FAULT")
            axis_X1.RegisterDump()
            break

    if bToggle:
        axis_X1.SetDirNeg()
        bToggle = False
    else:
        axis_X1.SetDirPos()
        bToggle = True

# axis_X1.DO_STEP.blink(.000005, .000005, steps, False)
tEnd = time.monotonic()

print("\nStep Test took ", tEnd - tStart, " secs")
print("\nSpeed: ", 250 / (tEnd - tStart), " mm/sec\n")

axis_X1.SetMotorDisable()

Thank you very much. I would try to write my own code using code as a reference.

Appreciate your help!!