Skip to content

machine/rp2040: add PWM implementation#2015

Merged
deadprogram merged 2 commits into
tinygo-org:devfrom
soypat:patch-pico-pwm
Sep 1, 2021
Merged

machine/rp2040: add PWM implementation#2015
deadprogram merged 2 commits into
tinygo-org:devfrom
soypat:patch-pico-pwm

Conversation

@soypat

@soypat soypat commented Jul 25, 2021

Copy link
Copy Markdown
Contributor

Please take a look. Tested and works with on-board LED and GPIO5. Solves #1993 .

@soypat

soypat commented Jul 25, 2021

Copy link
Copy Markdown
Contributor Author

Tests have failed probably because two functions are missing: boolToBit and umax32 which are due to be added with #2013. Below is an example of usage (PWM blinky)

PWM Blinky Example
package main

import (
	"machine"
	"time"
)

var (
	LED  = machine.GPIO25
	pin2 = machine.GPIO26
	uart = machine.UART0
)

func main() {
	// configure UART to print stuff
	{
		err := uart.Configure(machine.UARTConfig{BaudRate: 9600})
		if err != nil {
			panic(err)
		}
	}

	pin := LED

	pin.Configure(machine.PinConfig{Mode: machine.PinPWM})
	pwm, err := machine.NewPWM(pin)
	if err != nil {
		println(err.Error())
	}
	var per uint64 = 1e9 / 500
	err = pwm.Configure(machine.PWMConfig{Period: per})
	if err != nil {
		println(err.Error())
	}
	ch, err := pwm.Channel(pin)
	if err != nil {
		println(err.Error())
	}
	println("slice", pwm.Peripheral(pin), " ch:", ch)
	if !pwm.IsEnabled() {
		println("NOT ENABLED")
	}
	println("period:", pwm.Period(), "target_period:", per)
	time.Sleep(time.Millisecond)

	for {

		for i := 1; i < 255; i++ {
			pwm.Set(ch, pwm.Top()/uint32(i))
			time.Sleep(time.Millisecond * 5)
		}
	}

}

@soypat
soypat marked this pull request as draft August 1, 2021 21:57
@deadprogram

Copy link
Copy Markdown
Member

Ready for resolve of merge conflicts, please. 😸

@soypat

soypat commented Aug 7, 2021

Copy link
Copy Markdown
Contributor Author

@deadprogram Done dealio

@soypat
soypat marked this pull request as ready for review August 7, 2021 20:44
@deadprogram

Copy link
Copy Markdown
Member

@soypat

soypat commented Aug 7, 2021

Copy link
Copy Markdown
Contributor Author

Hello @deadprogram, seems like I used the wrong function name for u32max. Should be fixed by now.

@aykevl aykevl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that the PWM of the RP2040 is structured a little bit differently than other chips: it groups all PWM timers into one peripheral. Most chips have multiple PWMs where each PWM instance has just one timer. However, if you look closely you can see that it is actually not that different: it's as if the RP2040 has 8 PWM peripherals that each have two channel outputs. Therefore, I would suggest exposing it like that:

var (
    PWM0 = ...
    PWM1 = ...
    PWM2 = ...
    // etc
}

In this API, you can use the PWM like this:

pwm := machine.PWM0
pwm.Configure(...)        // enables the given PWM
ch, _ := pwm.Channel(pin) // configures the pin
ch.Set(ch, value)         // set the channel value

I understand the need for a NewPWM, and I agree we should have something like that (also for other chips). However, there is one big catch: it's not clear which PWMs alias each other. For example, if you set the frequency for pin 2, it will also change the frequency for pin 3, 18, and 19. This is in fact one of the main reasons of the somewhat complex API. That's why I would suggest leaving it out for now.

(Also, I think the name NewPWM is misleading as the function doesn't create anything new: PWM resources are fixed hardware resources and can't be made on the fly).

Comment thread src/machine/machine_rp2040_pwm.go Outdated
Comment thread src/machine/machine_rp2040_pwm.go Outdated
Comment thread src/machine/machine_rp2040_pwm.go Outdated
Comment thread src/machine/machine_rp2040_pwm.go Outdated
targetPeriod := uint32(period)
periodPerCycle := getPeriod()
top := pwm.getWrap(sliceNum)
phc := pwm.getPhaseCorrect(sliceNum)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, phase correct PWM isn't supported so I would suggest not taking this into account.
(I believe phase correct PWM is only relevant for specific motor control applications)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean I should leave it commented out as a TODO for when phase correct is added, if ever?

@soypat

soypat commented Aug 11, 2021

Copy link
Copy Markdown
Contributor Author

@aykevl I've applied sweeping changes inspired by your comments. There may be more use of unsafe but I think this is much cleaner. Let me know what you think!

@deadprogram

Copy link
Copy Markdown
Member

CI tests are failing, and there is a merge conflict. Can you please look at that @soypat thank you!

@soypat

soypat commented Aug 11, 2021

Copy link
Copy Markdown
Contributor Author

I changed a method to a function. One can obtain the peripheral number with machine.PWMPeripheral. I think it makes more sense than having it as a method.

@deadprogram

Copy link
Copy Markdown
Member

Was not able to get working with the PWM example in the main TinyGo examples. Some mappings are missing, and I might not have them correct for the Pico board.

add documentation

rp2040 pwm fixes and functionality added

machine/rp2040: add PWM implementation
@soypat

soypat commented Aug 17, 2021

Copy link
Copy Markdown
Contributor Author

@deadprogram I had to add a pin.Configure call inside pwm.Channel for the API to be the same as other implementations. I have tested it and it works with the on-board LED on the pico (which I added to the examples/pwm files.

soypat added a commit to soypat/tinygo-site that referenced this pull request Aug 18, 2021
Next release of TinyGo should have support for I2C+SPI+PWM.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
PWM would be supported as soon as tinygo-org/tinygo#2015 is merged.

Added some pointers on how to debug/get USB output using picoprobe.
@deadprogram

Copy link
Copy Markdown
Member

Tested and is now working as expected. Squashing/merging now, thanks for working on this @soypat

@deadprogram
deadprogram merged commit a7c53cc into tinygo-org:dev Sep 1, 2021
ysoldak added a commit to ysoldak/tinygo that referenced this pull request Sep 4, 2021
* 'dev' of github.com:tinygo-org/tinygo:
  src/runtime: reset heapptr to heapStart after preinit()
  docker: use go 1.17 for docker dev build
  machine/feather-rp2040: add pin name definition for feather
  targets: add openocd configuration for rp2040
  Implement os.Executable
  board/nano-rp2040: define NINA_SPI and fix wifinina pins
  machine/rp2040: add PWM implementation (tinygo-org#2015)
deadprogram pushed a commit to tinygo-org/tinygo-site that referenced this pull request Sep 19, 2021
Next release of TinyGo should have support for I2C+SPI+PWM.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
PWM would be supported as soon as tinygo-org/tinygo#2015 is merged.

Added some pointers on how to debug/get USB output using picoprobe.
deadprogram pushed a commit to tinygo-org/tinygo-site that referenced this pull request Sep 19, 2021
Next release of TinyGo should have support for I2C+SPI+PWM.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
PWM would be supported as soon as tinygo-org/tinygo#2015 is merged.

Added some pointers on how to debug/get USB output using picoprobe.
deadprogram pushed a commit to tinygo-org/tinygo-site that referenced this pull request Sep 19, 2021
Next release of TinyGo should have support for I2C+SPI+PWM.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
PWM would be supported as soon as tinygo-org/tinygo#2015 is merged.

Added some pointers on how to debug/get USB output using picoprobe.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants