Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

Raspberry Pi Zero W PWM issues #363

Closed
UnAfraid opened this issue Dec 21, 2018 · 9 comments
Closed

Raspberry Pi Zero W PWM issues #363

UnAfraid opened this issue Dec 21, 2018 · 9 comments

Comments

@UnAfraid
Copy link

UnAfraid commented Dec 21, 2018

Describe the bug
I am trying to do PWM on LED with Raspberry PI Zero W, but no matter on which pin i try i always get
bcm283x-gpio (GPIO19): bcm283x-dma: no channel available

It works only on 0% and 100%

To Reproduce
Steps to reproduce the behavior:

  1. Run program
package main

import (
	"log"
	"periph.io/x/periph/conn/gpio"
	"periph.io/x/periph/conn/gpio/gpioreg"
	"periph.io/x/periph/conn/physic"
	"periph.io/x/periph/host"
	"time"
)

func main() {
	_, err := host.Init()
	if err != nil {
		log.Fatalf("Couldn't initialize host: %s", err.Error())
	}

	greenGPIO := gpioreg.ByName("19")
	if err := greenGPIO.Out(gpio.Low); err != nil {
		log.Fatalf("Failed to parse green led to low: %s", err.Error())
	}
	go func() {
		i, err := gpio.ParseDuty("10%")
		if err != nil {
			log.Fatalf("Failed to parse duty cycle: %s", err.Error())
		}

		step := i / 2

		for {
			log.Printf("Raising PWM to: %v duty", i)
			if err := greenGPIO.PWM(i, 10*physic.KiloHertz); err != nil {
				log.Printf("Failed to set PWM: %s", err.Error())
			}

			i += step
			if i > gpio.DutyMax {
				break
			}

			time.Sleep(1000 * time.Millisecond)
		}
	}()
}
  1. Run it.
  2. See error

Expected behavior
I am expecting to dim the LED

Platform (please complete the following information):

  • OS: Raspbian Stretch Lite
  • Board: Raspberry Pi Zero Wireless

Additional context
I am attempting to control the dimming on LEDs of this button: https://www.aliexpress.com/item/30mm-red-bi-color-RGB-led-Metal-Push-Button-Switch-momentary-latching-waterpoof-2no2nc-pushbutton-switch/32954214211.html

@maruel
Copy link
Contributor

maruel commented Dec 21, 2018

Try using the pins which have native PWM; you can retrieve them with "PWM0" and "PWM1".

@UnAfraid
Copy link
Author

Okay i've set the following, but i still get the same result

pwm0 := gpioreg.ByName("PWM0")
pwm1 := gpioreg.ByName("PWM1")
Raising PWM to: 10% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 15% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 20% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 25% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 30% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 35% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 40% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 45% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 50% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 55% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 60% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 65% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 70% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 75% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 80% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 85% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 90% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available
Raising PWM to: 95% duty
Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available
Failed to set PWM1: bcm283x-gpio (GPIO13): bcm283x-dma: no channel available

@NeuralSpaz
Copy link
Collaborator

NeuralSpaz commented Dec 21, 2018

this work on my pi zero stretch

package main

import (
	"log"
	"periph.io/x/periph/conn/gpio"
	"periph.io/x/periph/conn/gpio/gpioreg"
	"periph.io/x/periph/conn/physic"
	"periph.io/x/periph/host"
	"time"
)

func main() {
	_, err := host.Init()
	if err != nil {
		log.Fatalf("Couldn't initialize host: %s", err.Error())
	}

	pwm0 := gpioreg.ByName("PWM1")
	if err := pwm0.Out(gpio.Low); err != nil {
		log.Fatalf("Failed to parse green led to low: %s", err.Error())
	}
	//	go func() {
	i, err := gpio.ParseDuty("10%")
	if err != nil {
		log.Fatalf("Failed to parse duty cycle: %s", err.Error())
	}

	step := i / 2

	for {
		log.Printf("Raising PWM to: %v duty", i)
		if err := pwm0.PWM(i, 10*physic.KiloHertz); err != nil {
			log.Printf("Failed to set PWM: %s", err.Error())
		}

		i += step
		if i > gpio.DutyMax {
			break
		}

		time.Sleep(1000 * time.Millisecond)
	}
	//	}()
}

@UnAfraid
Copy link
Author

UnAfraid commented Dec 21, 2018

After restart of my PI it worked for a while, but after restart of my application a couple of times got it into that state again
After 5 re-launches of my application it got into that Failed to set PWM0: bcm283x-gpio (GPIO12): bcm283x-dma: no channel available do i have to free up some resource maybe?

@NeuralSpaz
Copy link
Collaborator

I get that too on next execution.

@NeuralSpaz
Copy link
Collaborator

NeuralSpaz commented Dec 22, 2018

You MUST call Halt on the pin before exiting.
eg:

package main

import (
	"log"
	"periph.io/x/periph/conn/gpio"
	"periph.io/x/periph/conn/gpio/gpioreg"
	"periph.io/x/periph/conn/physic"
	"periph.io/x/periph/host"
	"time"
)

func main() {
	if _, err := host.Init(); err != nil {
		log.Println(err)
	}

	pwm0 := gpioreg.ByName("PWM1")
	defer pwm0.Halt()
	if err := pwm0.Out(gpio.Low); err != nil {
		log.Fatalf("Failed to parse green led to low: %s", err.Error())
	}

	i, err := gpio.ParseDuty("10%")
	if err != nil {
		log.Fatalf("Failed to parse duty cycle: %s", err.Error())
	}

	step := i / 2

	for {
		log.Printf("Raising PWM to: %v duty", i)
		if err := pwm0.PWM(i, 10*physic.KiloHertz); err != nil {
			log.Printf("Failed to set PWM: %s", err.Error())
		}

		i += step
		if i > gpio.DutyMax {
			break
		}

		time.Sleep(1000 * time.Millisecond)
	}
}

@NeuralSpaz
Copy link
Collaborator

@NeuralSpaz
Copy link
Collaborator

Watching the PWM out on a scope, I noticed that if there is a SIGINT (ctrl+c) that the pwm would not Halt correctly and would continue outputting the last pwm, and not release the dma?
one possible way around this is to get the handle the signal in the program and call Halt() there as well.
eg:

...
	pwm0 := gpioreg.ByName("PWM1")
	defer pwm0.Halt()
	if err := pwm0.Out(gpio.Low); err != nil {
		log.Fatalf("Failed to parse green led to low: %s", err.Error())
	}

	var halt = make(chan os.Signal)
	signal.Notify(halt, syscall.SIGTERM)
	signal.Notify(halt, syscall.SIGINT)

	go func() {
		select {
		case <-halt:
			if err := pwm0.Halt(); err != nil {
				log.Println(err)
			}
			os.Exit(1)
		}
	}()
...

@maruel
Copy link
Contributor

maruel commented Jan 14, 2019

Looks like user error, closing.

That said, the v4 API must make it very obvious so users hardly can make this error.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants