gobot.io/x/gobot@v1.16.0/platforms/raspi/pwm_pin.go (about) 1 package raspi 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 8 "gobot.io/x/gobot" 9 "gobot.io/x/gobot/sysfs" 10 ) 11 12 // PWMPin is the Raspberry Pi implementation of the PWMPinner interface. 13 // It uses Pi Blaster. 14 type PWMPin struct { 15 pin string 16 dc uint32 17 period uint32 18 } 19 20 // NewPwmPin returns a new PWMPin 21 func NewPWMPin(pin string) *PWMPin { 22 return &PWMPin{ 23 pin: pin} 24 } 25 26 // Export exports the pin for use by the Raspberry Pi 27 func (p *PWMPin) Export() error { 28 return nil 29 } 30 31 // Unexport unexports the pin and releases the pin from the operating system 32 func (p *PWMPin) Unexport() error { 33 return p.piBlaster(fmt.Sprintf("release %v\n", p.pin)) 34 } 35 36 // Enable enables/disables the PWM pin 37 func (p *PWMPin) Enable(e bool) (err error) { 38 return nil 39 } 40 41 // Polarity returns the polarity either normal or inverted 42 func (p *PWMPin) Polarity() (polarity string, err error) { 43 return "normal", nil 44 } 45 46 // InvertPolarity does not do anything when using PiBlaster 47 func (p *PWMPin) InvertPolarity(invert bool) (err error) { 48 return nil 49 } 50 51 // Period returns the current PWM period for pin 52 func (p *PWMPin) Period() (period uint32, err error) { 53 if p.period == 0 { 54 return p.period, errors.New("Raspi PWM pin period not set") 55 } 56 57 return p.period, nil 58 } 59 60 // SetPeriod uses PiBlaster setting and cannot be changed once set 61 func (p *PWMPin) SetPeriod(period uint32) (err error) { 62 if p.period != 0 { 63 return errors.New("Cannot set the period of individual PWM pins on Raspi") 64 } 65 p.period = period 66 return nil 67 } 68 69 // DutyCycle returns the duty cycle for the pin 70 func (p *PWMPin) DutyCycle() (duty uint32, err error) { 71 return p.dc, nil 72 } 73 74 // SetDutyCycle writes the duty cycle to the pin 75 func (p *PWMPin) SetDutyCycle(duty uint32) (err error) { 76 if p.period == 0 { 77 return errors.New("Raspi PWM pin period not set") 78 } 79 80 if duty > p.period { 81 return errors.New("Duty cycle exceeds period.") 82 } 83 p.dc = duty 84 85 val := gobot.FromScale(float64(p.dc), 0, float64(p.period)) 86 87 // never go below minimum allowed duty for pi blaster 88 // unless the duty equals to 0 89 if val < 0.05 && val != 0 { 90 val = 0.05 91 } 92 return p.piBlaster(fmt.Sprintf("%v=%v\n", p.pin, val)) 93 } 94 95 func (p *PWMPin) piBlaster(data string) (err error) { 96 fi, err := sysfs.OpenFile("/dev/pi-blaster", os.O_WRONLY|os.O_APPEND, 0644) 97 defer fi.Close() 98 99 if err != nil { 100 return err 101 } 102 103 _, err = fi.WriteString(data) 104 return 105 }