Hardstop with goUntilPress()


#1

Testing my new Slushengine board has led to the following observations (please correct me if I’m wrong):
goUntilPress() always stops hard, even if hardStop() hasn’t been set. Is there a way to make a softStop if a switch is hit?
I dont’t care if the motor overshoots, I can slowly track back to the stop. With a heavy load this is important.

Btw. also move() and goTo() immedeately stop hard at a press-event. Is this by design?


#2

Hi Wfk,

In L6470 Data Sheet, the GoUntil(ACT, DIR, SPD) command states,

if the SW_MODE bit of the CONFIG register is set low, the external switch turn-on event causes a HardStop interrupt instead of the SoftStop

By default, it is set to HardStop.

Set acceleration and deceleration appropriately, so that the stepper motor ramps-up and ramps-down.


#3

Hi Rakesh,
The PARAM register is accessible with the getParam() command, but I find no reference for a Slush-command for accessing the CONFIG register.
How to toggle the SW_MODE bit (bit 4) of the CONFIG register programmatically?


#4

Hi Wft,

See my last post here - to toggle the bit, you will need to use something like self.setParam(LReg.CONFIG, [Shift bit left to set SW_MODE]).

When I get back home, I’ll provide you with sample code.


#5

I’ll give it a try…


#6

So far I’ve done this:

def getConfig(self):
    return self.getParam(LReg.CONFIG)

''' toggle 4th bit in CONFIG register '''
def setSWmode(self,value):
    if value == 1:
        self.xfer(LReg.CONFIG | 8)

However, I get this error:
self.xfer(LReg.CONFIG | 8)
TypeError: unsupported operand type(s) for |: ‘tuple’ and ‘int’

This is the same type of error we discussed in a previous post…


#7

The coding should be similar to,

def setSWMode(self, sw_mode):
	self.setParam(LReg.CONFIG, (sw_mode << 4))

You pass either 0 (HardStop) or 1 (User disposal) to the method.

To confirm that the correct bit is set, convert the integer value returned by def getConfig(self) to binary, to see which bits are set in the CONFIG register.

Here’s a good guide about Bit Fields.


#8

Your code seems to replace the whole REGISTER byte with 00010000 (NB. working with the 5th bit; should be 4th methinks). See this example:


print(m0.getConfig())
m0.setSWmode(1)
print(m0.getConfig())

Result in Shell:
============ RESTART: /home/wfk/slushengine/examples/Test run,.py ============
Motor Drive Connected on GPIO 24
11912
16

I would prefer to OR my value 8 (00001000) to force the SW_mode bit (bit 4) to 1 using the operand ‘|’, like so:

''' toggle 4th bit in CONFIG register '''
def setSWmode(self,sw_mode):
    if sw_mode == 1: 
byte = 8
    self.setParam(LReg.CONFIG | byte)

But it gives this error
File “/usr/local/lib/python3.5/dist-packages/Slush-0.1d-py3.5.egg/Slush/Motor.py”, line 69, in setSWmode
self.setParam(LReg.CONFIG | byte)
TypeError: unsupported operand type(s) for |: ‘tuple’ and ‘int’

What’s wrong?


#9
  1. You need to create the bit mask of a given width.
  2. Shift the mask and the value left to the proper bit position.
  3. Invert the mask, so that the existing values in the byte are preserved.
  4. Write the bit field.
SW_MODE_MASK = 0x01

def setSwMode(self, sw_mode):
	value = self.getParam(CONFIG)
	value = (value & ~SW_MODE_MASK) | (sw_mode << 4)
	self.setParam(CONFIG, value)

Note, that setParam() method takes two parameters. In your example, self.setParam(LReg.CONFIG | byte) you are only passing in one parameter.


#10

Yes, you’re right of course, setParam needs two parameters, and the SW_mode bit is bit 4, the fifth bit, so it needs indeed |16 to set it. Now I can at least use my code to set the SW_code bit.
With your code it’s possible to really toggle it. However, I don’t know where exactly to put the code SW_MODE_MASK = 0x01. Not in class Motor itself. I keep getting the error:
value = (value & ~SW_MODE_MASK) | (sw_mode << 4)
NameError: name ‘SW_MODE_MASK’ is not defined


#11

Insert the constant SW_MODE_MASK = 0x01 in file L6470Registers.py and the method setSwMode() in Motor.py.


#12

Done that. Put the constant in L6470Registers.py like so:

‘’‘step mode register masks’’’
STEP_MODE_STEP_EN = 0x70
STEP_MODE_SYNC_EN = 0x80
STEP_MODE_SYNC_SEL = 0x70
SYNC_EN = 0x80
SW_MODE_MASK = 0x01

But I still get the error:
value = (value & ~SW_MODE_MASK) | (sw_mode << 4)
NameError: name ‘SW_MODE_MASK’ is not defined


#13

Hi Wfk,

Hint: how is the constant CONFIG that’s defined in L6470Registers.py, used in Motor.py? Note, you have already written some coding.


#14

I’m sorry, but I can’t get the SW_MODE bit to toggle both ways. I can only set it to ‘1’, and then leave it so. For me that’s good enough. goUntilPress() now works as I want it: it runs, and when a switch is hit, it marks the spot and then decelerates nicely.
But the SW_MODE==1 setting does not work for the goTo() function (and others), goTo() always stops hard when a switch is hit. That can be nasty when the system inadvertently meets a switch at full speed. Is there a way to change this behavior?


#15

Hi Wfk,

I don’t fully understand what you mean by “but I can’t get the SW_MODE bit to toggle both ways”? To change the state of SW_MODE bit, you either pass 0 and 1 to the method

You should read the L6470 Datasheet, this describes all the features the motor driver supports.


#16

Hi Rakesh,

I’ve got it figured out.
Thanks.