Setting a servo to sleep

Hi,

I am using the Sparkfun Servo HAT on a Pi to control some servos using Python and it’s working magically so far.

What I have been able to do previously (before the HAT) is allow the servos to sleep in between moves. This allows me to physically adjust their position and, if they can’t get in the right position, stops them from burning out.

I’d managed to do this before programmatically by setting the duty cycle and frequency to 0.

Is there a way to do this using the HAT?

Sure - it should be as simple as including/importing “time” or “os.time” packages at the beginning of your program, then invoking time.sleep(x) for which channel “[0-15]” being controlled :smiley:

Hmm. I must be doing something wrong then.

The code itself only runs when a button is pushed on a web interface. Currently, if the servo is unable to achieve the set position it will carry on trying to get there despite the code having completed. I would have thought this would have achieved the same as adding a pause in between commands?

Here’s a cut down overview of the code I’m using:

import smbus
bus = smbus.SMBus(1)
addr = 0x40
bus.write_byte_data(addr, 0, 0x20)

servo_start_addresses = [List of start channels here]
servo_stop_addresses = [List of end channels here]

for a in range(len(servo_start_addresses)):
    bus.write_word_data(addr, servo_start_addresses[a], 0)

servo_close_position = 995
servo_open_position = 1275

def Move(x):
        if x == "open":            
                for a in range(len(servo_stop_addresses)):
                        bus.write_word_data(addr, servo_stop_addresses[a], servo_open_position)
                return "Done"
        elif x == "close":
                for a in range(len(servo_stop_addresses)):
                        bus.write_word_data(addr, servo_stop_addresses[a], servo_close_position)
                return "Done"

I can of course easily add a “time.sleep(.25)” after each write command, but I’m thinking it shouldn’t be necessary.

What have I missed?

Just bumping this in case someone can help.

I finally worked it out, I needed to pass the following code after a move to shut the servo off (I presume drop the duty cycle to zero):

bus.write_word_data(addr, servo_stop_addresses[a], 0)

Roughly, in its entirety…

import smbus
bus = smbus.SMBus(1)
addr = 0x40 #I2C address of Sparkfun controller
bus.write_byte_data(addr, 0, 0x20) # enable the PWM chip
time.sleep(.25) # delay for reset
bus.write_byte_data(addr, 0, 0x10) # enable Prescale change as noted in the datasheet
time.sleep(.25) # delay for reset
bus.write_byte_data(addr, 0xfe, 0x79) #changes the Prescale register value to 50 Hz, using the equation in the datasheet.
bus.write_byte_data(addr, 0, 0x20) # enables the chip

servo_start_addresses = [List of start channels here]
servo_stop_addresses = [List of end channels here]

for a in range(len(servo_start_addresses)):
    bus.write_word_data(addr, servo_start_addresses[a], 0)

servo_close_position = 995
servo_open_position = 1275

def Move(x):
        if x == "open":            
                for a in range(len(servo_stop_addresses)):
                        bus.write_word_data(addr, servo_stop_addresses[a], servo_open_position)
                        time.sleep(.25)
                       bus.write_word_data(addr, servo_stop_addresses[a], 0) #Turn servo off after move.
                return "Done"
        elif x == "close":
                for a in range(len(servo_stop_addresses)):
                        bus.write_word_data(addr, servo_stop_addresses[a], servo_close_position)
                        time.sleep(.25)
                       bus.write_word_data(addr, servo_stop_addresses[a], 0) #Turn servo off after move.
                return "Done"

Thanks for sharing, this is very useful!