# cPy - driver class for PWM servo
# Provided by Anthony Vogelaar, Perth Scotland
# rev 0.10  2026-01-09  initial release

from 	machine	import	Pin, PWM

# Implemented:
# Servo(pin=27, min=0, max=100)
#    Servo.close()
#    Servo.goToMax(speed=100)
#    Servo.goToMin(speed=100)
#    Servo.exe100()

# ========================== Servo ==============================

class Servo:
    
    # min and max in % of 1..2 mSec width, speed in %/sec
    def __init__(self, pin_nr=27, min=0, max=100):
        self.servo = PWM(Pin(pin_nr), freq=50)	
        self.servo.duty_ns(1_500_000)				# center position
        self.min   = 1_000_000 + min * 10_000
        self.max   = 1_000_000 + max * 10_000
        self.istw  = 1_500_000
        self.setp  = 1_500_000
        self.speed = None
        
    
    def close(self):
        self.servo.deinit()
        
    
    # speed in PWM uS per 100 mS.
    # 100 = 100% in 1 sec, 200 = 100% in 0.5 Sec, 20 = 100% in 5 Sec
    def goToMax(self, speed=100):
        self.setp  = self.max
        self.speed = speed * 1_000		# nSec per 100 mSec 
        
        
    # speed in PWM uS per 100 mS.
    # 100 = 100% in 1 sec, 200 = 100% in 0.5 Sec, 20 = 100% in 5 Sec
    def goToMin(self, speed=100):
        self.setp  = self.min
        self.speed = speed * 1_000		# nSec per 100 mSec
        
        
    # to be called at 100 mSec
    def exe100(self):
        if self.istw == self.setp: return
        if self.istw < self.setp:
            self.istw = min(self.setp, self.istw + self.speed)
        else:
            self.istw = max(self.setp, self.istw - self.speed)
        self.servo.duty_ns(self.istw)
            
# ========================== test ==============================

if __name__ == '__main__':
    
    import	time
    
    # slow forward, fast reverse
    def test():
        servo = Servo()					# servo on pin 27
        try:
            ticks = 0
            while True:
                time.sleep_ms(100)
                ticks += 1
                servo.exe100()
                if   ticks ==  1: servo.goToMax(speed=20)		# @ 0 Sec  min --> max in 5.0 Sec 
                elif ticks == 60: servo.goToMin(speed=200)		# @ 6 Sec  max --> min in 0.5 Sec
                elif ticks == 80: ticks = 0						# @ 8 Sec  reset
        finally:
            servo.close()
        
        
    test()
    
# ============================= end =============================
