gobot.io/x/gobot/v2@v2.1.0/platforms/jetson/pwm_pin.go (about) 1 package jetson 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path" 8 9 "gobot.io/x/gobot/v2" 10 "gobot.io/x/gobot/v2/system" 11 ) 12 13 const ( 14 minimumPeriod = 5334 15 minimumRate = 0.05 16 ) 17 18 // PWMPin is the Jetson Nano implementation of the PWMPinner interface. 19 // It uses gpio pwm. 20 type PWMPin struct { 21 sys *system.Accesser 22 path string 23 fn string 24 dc uint32 25 period uint32 26 enabled bool 27 } 28 29 // NewPWMPin returns a new PWMPin 30 // pin32 pwm0, pin33 pwm2 31 func NewPWMPin(sys *system.Accesser, path string, fn string) *PWMPin { 32 p := &PWMPin{ 33 sys: sys, 34 path: path, 35 fn: fn, 36 } 37 return p 38 } 39 40 // Export exports the pin for use by the Jetson Nano 41 func (p *PWMPin) Export() error { 42 return p.writeFile("export", p.fn) 43 } 44 45 // Unexport releases the pin from the operating system 46 func (p *PWMPin) Unexport() error { 47 return p.writeFile("unexport", p.fn) 48 } 49 50 // Enabled returns the cached enabled state of the PWM pin 51 func (p *PWMPin) Enabled() (bool, error) { 52 return p.enabled, nil 53 } 54 55 // SetEnabled enables/disables the PWM pin 56 func (p *PWMPin) SetEnabled(e bool) error { 57 if err := p.writeFile(fmt.Sprintf("pwm%s/enable", p.fn), fmt.Sprintf("%v", bool2int(e))); err != nil { 58 return err 59 } 60 p.enabled = e 61 return nil 62 } 63 64 // Polarity returns always the polarity "true" for normal 65 func (p *PWMPin) Polarity() (bool, error) { 66 return true, nil 67 } 68 69 // SetPolarity does not do anything when using Jetson Nano 70 func (p *PWMPin) SetPolarity(bool) error { 71 return nil 72 } 73 74 // Period returns the cached PWM period for pin 75 func (p *PWMPin) Period() (period uint32, err error) { 76 if p.period == 0 { 77 return p.period, errors.New("Jetson PWM pin period not set") 78 } 79 80 return p.period, nil 81 } 82 83 // SetPeriod uses Jetson Nano setting and cannot be changed once set 84 func (p *PWMPin) SetPeriod(period uint32) error { 85 if p.period != 0 { 86 return errors.New("Cannot set the period of individual PWM pins on Jetson") 87 } 88 // JetsonNano Minimum period 89 if period < minimumPeriod { 90 return errors.New("Cannot set the period more then minimum") 91 } 92 if err := p.writeFile(fmt.Sprintf("pwm%s/period", p.fn), fmt.Sprintf("%v", p.period)); err != nil { 93 return err 94 } 95 p.period = period 96 return nil 97 } 98 99 // DutyCycle returns the cached duty cycle for the pin 100 func (p *PWMPin) DutyCycle() (uint32, error) { 101 return p.dc, nil 102 } 103 104 // SetDutyCycle writes the duty cycle to the pin 105 func (p *PWMPin) SetDutyCycle(duty uint32) error { 106 if p.period == 0 { 107 return errors.New("Jetson PWM pin period not set") 108 } 109 110 if duty > p.period { 111 return errors.New("Duty cycle exceeds period") 112 } 113 114 rate := gobot.FromScale(float64(duty), 0, float64(p.period)) 115 // never go below minimum allowed duty because very short duty 116 if rate < minimumRate { 117 duty = uint32(minimumRate * float64(p.period) / 100) 118 } 119 if err := p.writeFile(fmt.Sprintf("pwm%s/duty_cycle", p.fn), fmt.Sprintf("%v", duty)); err != nil { 120 return err 121 } 122 123 p.dc = duty 124 return nil 125 } 126 127 func (p *PWMPin) writeFile(subpath string, value string) error { 128 sysfspath := path.Join(p.path, subpath) 129 fi, err := p.sys.OpenFile(sysfspath, os.O_WRONLY|os.O_APPEND, 0644) 130 defer fi.Close() //nolint:staticcheck // for historical reasons 131 132 if err != nil { 133 return err 134 } 135 136 _, err = fi.WriteString(value) 137 return err 138 } 139 140 func bool2int(b bool) int { 141 if b { 142 return 1 143 } 144 return 0 145 }