Lucassifoni

Lucassifoni

Configuring PWM channel outputs on the Allwinner D1 (MangoPi MQ Pro)

Hello dear Nerves users,

I’m trying to get a PWM output to show up on the 40-pin header on the MangoPI, specifically physical pin 35, or GPIO 38 as seen from Elixir. My goal is to have a few PWM channels physically available on the header to control them with the sysfs (/sys/class/pwm) interface.

To summarize :

  • I think I found the relevant information in the D1 manual.
  • I’m pretty sure I do not know how to properly apply it.

I found the following pin multiplexing table in the official D1 documentation (beware : 1300+ pages)

Further, since this pin should be handled by PB6, I found the relevant register address :

And the bit pattern to configure PB6 to use the PWM1 channel :

My understanding is that I should be able to get the PWM1 channel on PB6 / GPIO38 by setting the register at address 0x02000000 + 0x0030 to the bit pattern 000001010000000000000000 or 0x050000 (since PB6_SELECT is set by using the bits 27 to 24).

I found samples of DTS files online for similar purposes that I tried to modify, some compiling, and some not, but none having any tangible effect towards my goal.

I would greatly appreciate any direction on that matter. Am I looking at the wrong level of abstraction by thinking in terms of bit patterns and registers, and pinmux configuration is instead done at a slightly higher level ?
Best,
Lucas

Most Liked

ConnorRigby

ConnorRigby

Nerves Core Team

I know it’s been a while since you posted this, but just in case you haven’t figured it out, or if anyone else stumbles upon this in the future, here’s a example of enabling a PWM channel on the t113s. Pwm by ConnorRigby · Pull Request #1 · ConnorRigby/nerves_system_underglow3 · GitHub

it should be the same on the D1. The source file for pinctrl will be in here Making sure you're not a bot!

Lucassifoni

Lucassifoni

Hey ! If someone does need the PWM outputs of the mangopi to actually come out on the header, you can checkout my branch here : GitHub - Lucassifoni/nerves_system_mangopi_mq_pro at pwm-ability · GitHub

Here is a dynamic overlay that correctly muxes the pins, on top of the 6.18.36 kernel update : nerves_system_mangopi_mq_pro/pwm-7ch-overlay.dts at pwm-ability · Lucassifoni/nerves_system_mangopi_mq_pro · GitHub

For ease of use, you can checkout my two helper libraries, DtsBuddy and Pwmx, described here : Two helper libraries, DtsBuddy and Pwmx

Here is how to get leds blinking on the exposed channels in an iex session :

iex(livebook@nerves.local)1> import DtsBuddy.Sigil
DtsBuddy.Sigil
iex(livebook@nerves.local)2> DtsBuddy.enable_overlays
:ok
iex(livebook@nerves.local)3> DtsBuddy.overlays_enabled?
true
iex(livebook@nerves.local)4> compiled =
  ~DTS"""
  /dts-v1/;
  /plugin/;
  &{/soc/pinctrl@2000000} {
    pwm0_pb5:  pwm0-pb5  { pins = "PB5";  function = "pwm0"; };
    pwm1_pb6:  pwm1-pb6  { pins = "PB6";  function = "pwm1"; };
    pwm2_pb11: pwm2-pb11 { pins = "PB11"; function = "pwm2"; };
    pwm3_pb0:  pwm3-pb0  { pins = "PB0";  function = "pwm3"; };
    pwm4_pb1:  pwm4-pb1  { pins = "PB1";  function = "pwm4"; };
    pwm5_pd21: pwm5-pd21 { pins = "PD21"; function = "pwm5"; };
    pwm7_pb10: pwm7-pb10 { pins = "PB10"; function = "pwm7"; };
  };
  &{/soc/pwm@2000c00} {
    pinctrl-names = "default";
    pinctrl-0 = <&pwm0_pb5>, <&pwm1_pb6>, <&pwm2_pb11>, <&pwm3_pb0>,
                <&pwm4_pb1>, <&pwm5_pd21>, <&pwm7_pb10>;
    status = "okay";
  };
  """pwm7ch
{:ok, "/data/pwm7ch.dtbo", "pwm7ch"}
iex(livebook@nerves.local)5> DtsBuddy.load(compiled)
:ok
iex(livebook@nerves.local)6> DtsBuddy.status("pwm7ch")
:applied
iex(livebook@nerves.local)7> Pwmx.list_available_outputs()
[
  {"pwmchip0", 0},
  {"pwmchip0", 1},
  {"pwmchip0", 2},
  {"pwmchip0", 3},
  {"pwmchip0", 4},
  {"pwmchip0", 5},
  {"pwmchip0", 6},
  {"pwmchip0", 7}
]
iex(livebook@nerves.local)8>
outs = for ch <- [0, 1, 2, 3, 4, 5, 7], into: %{} 
  {:ok, pid} = Pwmx.Output.start_link({"pwmchip0", ch})
  pid |> Pwmx.Output.set_period(500_000, :us) |> Pwmx.Output.set_duty_cycle_absolute(250_000, :us)  |> Pwmx.Output.enable()
  {ch, pid}
end
  • PWM5 on header pin 11
  • PWM0 on header pin 12
  • PWM3 on header pin 15
  • PWM4 on header pin 16
  • PWM1 on header pin 35
  • PWM2 on header pin 31
  • and PWM7 on pin 29 all work :slight_smile: .
Lucassifoni

Lucassifoni

Thanks a lot for these resources, I should be able to leverage them. I’ve put the project on the backburner for a while, but should be getting to it quite soon.
It’s also very nice to have that kind of samples for more advanced topics on the forum :slight_smile: .

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement