1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-24 13:48:49 +08:00

raspi: export PiBlasterPeriod in Adaptor

By setting PiBlasterPeriod to a raspi.Adaptor, the PWM pin will now
reflect the correct duty cycle to /dev/pi-blaster.

Signed-off-by: Mark Kuo <starryalley@gmail.com>
This commit is contained in:
Mark Kuo 2018-08-16 21:41:44 +10:00
parent a4d54794e0
commit 5ca29d0ba9
4 changed files with 48 additions and 18 deletions

View File

@ -9,13 +9,12 @@ import (
"gobot.io/x/gobot/sysfs"
)
const piBlasterPeriod = 10000000
// PWMPin is the Raspberry Pi implementation of the PWMPinner interface.
// It uses Pi Blaster.
type PWMPin struct {
pin string
dc uint32
pin string
dc uint32
period uint32
}
// NewPwmPin returns a new PWMPin
@ -51,11 +50,19 @@ func (p *PWMPin) InvertPolarity(invert bool) (err error) {
// Period returns the current PWM period for pin
func (p *PWMPin) Period() (period uint32, err error) {
return piBlasterPeriod, nil
if p.period == 0 {
return p.period, errors.New("Raspi PWM pin period not set")
}
return p.period, nil
}
// SetPeriod does not do anything when using PiBlaster
// SetPeriod uses PiBlaster setting and cannot be changed once set
func (p *PWMPin) SetPeriod(period uint32) (err error) {
if p.period != 0 {
return errors.New("Cannot set the period of individual PWM pins on Raspi")
}
p.period = period
return nil
}
@ -66,12 +73,16 @@ func (p *PWMPin) DutyCycle() (duty uint32, err error) {
// SetDutyCycle writes the duty cycle to the pin
func (p *PWMPin) SetDutyCycle(duty uint32) (err error) {
if duty > piBlasterPeriod {
if p.period == 0 {
return errors.New("Raspi PWM pin period not set")
}
if duty > p.period {
return errors.New("Duty cycle exceeds period.")
}
p.dc = duty
val := gobot.FromScale(float64(p.dc), 0, piBlasterPeriod)
val := gobot.FromScale(float64(p.dc), 0, float64(p.period))
// never go below minimum allowed duty for pi blaster
if val < 0.05 {

View File

@ -20,11 +20,14 @@ func TestPwmPin(t *testing.T) {
val, _ = pin.Polarity()
gobottest.Assert(t, val, "normal")
period, _ := pin.Period()
gobottest.Assert(t, period, uint32(10000000))
gobottest.Assert(t, pin.SetPeriod(1000), nil)
period, err := pin.Period()
gobottest.Assert(t, err, errors.New("Raspi PWM pin period not set"))
gobottest.Assert(t, pin.SetDutyCycle(10000), errors.New("Raspi PWM pin period not set"))
gobottest.Assert(t, pin.SetPeriod(20000000), nil)
period, _ = pin.Period()
gobottest.Assert(t, period, uint32(10000000))
gobottest.Assert(t, period, uint32(20000000))
gobottest.Assert(t, pin.SetPeriod(10000000), errors.New("Cannot set the period of individual PWM pins on Raspi"))
dc, _ := pin.DutyCycle()
gobottest.Assert(t, dc, uint32(0))

View File

@ -34,15 +34,17 @@ type Adaptor struct {
spiDevices [2]spi.Connection
spiDefaultMode int
spiDefaultMaxSpeed int64
PiBlasterPeriod uint32
}
// NewAdaptor creates a Raspi Adaptor
func NewAdaptor() *Adaptor {
r := &Adaptor{
mutex: &sync.Mutex{},
name: gobot.DefaultName("RaspberryPi"),
digitalPins: make(map[int]*sysfs.DigitalPin),
pwmPins: make(map[int]*PWMPin),
mutex: &sync.Mutex{},
name: gobot.DefaultName("RaspberryPi"),
digitalPins: make(map[int]*sysfs.DigitalPin),
pwmPins: make(map[int]*PWMPin),
PiBlasterPeriod: 10000000,
}
content, _ := readFile()
for _, v := range strings.Split(string(content), "\n") {
@ -261,6 +263,7 @@ func (r *Adaptor) PWMPin(pin string) (raspiPWMPin sysfs.PWMPinner, err error) {
if r.pwmPins[i] == nil {
r.pwmPins[i] = NewPWMPin(strconv.Itoa(i))
r.pwmPins[i].SetPeriod(r.PiBlasterPeriod)
}
return r.pwmPins[i], nil
@ -273,7 +276,7 @@ func (r *Adaptor) PwmWrite(pin string, val byte) (err error) {
return err
}
duty := uint32(gobot.FromScale(float64(val), 0, 255) * piBlasterPeriod)
duty := uint32(gobot.FromScale(float64(val), 0, 255) * float64(r.PiBlasterPeriod))
return sysfsPin.SetDutyCycle(duty)
}
@ -284,7 +287,7 @@ func (r *Adaptor) ServoWrite(pin string, angle byte) (err error) {
return err
}
duty := uint32(gobot.FromScale(float64(angle), 0, 180) * piBlasterPeriod)
duty := uint32(gobot.FromScale(float64(angle), 0, 180) * float64(r.PiBlasterPeriod))
return sysfsPin.SetDutyCycle(duty)
}

View File

@ -110,6 +110,7 @@ func TestAdaptorFinalize(t *testing.T) {
func TestAdaptorDigitalPWM(t *testing.T) {
a := initTestAdaptor()
a.PiBlasterPeriod = 20000000
gobottest.Assert(t, a.PwmWrite("7", 4), nil)
@ -118,6 +119,10 @@ func TestAdaptorDigitalPWM(t *testing.T) {
})
sysfs.SetFilesystem(fs)
pin, _ := a.PWMPin("7")
period, _ := pin.Period()
gobottest.Assert(t, period, uint32(20000000))
gobottest.Assert(t, a.PwmWrite("7", 255), nil)
gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "4=1")
@ -128,6 +133,14 @@ func TestAdaptorDigitalPWM(t *testing.T) {
gobottest.Assert(t, a.PwmWrite("notexist", 1), errors.New("Not a valid pin"))
gobottest.Assert(t, a.ServoWrite("notexist", 1), errors.New("Not a valid pin"))
pin, _ = a.PWMPin("12")
period, _ = pin.Period()
gobottest.Assert(t, period, uint32(20000000))
gobottest.Assert(t, pin.SetDutyCycle(1.5*1000*1000), nil)
gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "18=0.075")
}
func TestAdaptorDigitalIO(t *testing.T) {