Set Pins values synchroniously

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Set Pins values synchroniously

Post by pidou46 » Wed Oct 30, 2019 9:55 am

Hello,

Is there a way to set severals Pins values synchroniously rather than sequencialy ?

In other words, is it possible to change Pin(1) and Pin(2) value in the same time ?

My specific use case is to change microstepping configuration of a drv8825 while motor spin.

Code: Select all

  Mode2  |    Mode1    |    Mode0    |   STEP MODE
     0   |      0      |    0        |     Full step
     0   |      0      |    1        |     1/2
     0   |      1      |    0        |     1/4

to change from 1/2 to 1/4, I need to change Mode0 and Mode1 pins, but if I do it asynchroniuously I will switch shortly to Full step or 1/8 before getting the right setting for 1/4.
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Set Pins values synchroniously

Post by Roberthh » Wed Oct 30, 2019 12:23 pm

You can write directly to the GPIO registers, using the machine.mem8(), mem16() or mem32() functions. The address of the GPIO registers can be found in the ESP32 reference manual, snapshot below. For convenience, it is easier to use the Pin functions for set-up and do only the actual write using the mem-functions. Using them is easy, because there are three addresses. One for setting the GPIO port as given by the binary pattern. That would affect all GPIO pins. But also one each for setting or clearing a bit, whever the corresponding written bit it one or zero.

Code: Select all

GPIO_OUT_REG		GPIO 0-31 	output register 	  0x3FF44004 R/W
GPIO_OUT_W1TS_REG	GPIO 0-31 	output register_W1TS 	  0x3FF44008 WO
GPIO_OUT_W1TC_REG	GPIO 0-31 	output register_W1TC 	  0x3FF4400C WO
GPIO_OUT1_REG		GPIO 32-39 	output register 	  0x3FF44010 R/W
GPIO_OUT1_W1TS_REG	GPIO 32-39 	output bit set register   0x3FF44014 WO
GPIO_OUT1_W1TC_REG	GPIO 32-39 	output bit clear register 0x3FF44018 WO

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: Set Pins values synchroniously

Post by pidou46 » Thu Oct 31, 2019 1:40 pm

Thanks Roberthh for your reply,

I've found another post with a reply from you for the ESP8266:

viewtopic.php?t=5736

I get the point but I still have a hard time to make it work.

Code: Select all

import machine
machine.mem16(0x3FF44008)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'mem' object isn't callable
What arguments should I pass to theses functions ? hexadecimal address you gave I suppose ?

Still need some help please.
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: Set Pins values synchroniously

Post by kevinkk525 » Thu Oct 31, 2019 1:47 pm

machine.mem16[0x3FF44008]=xxxx
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Set Pins values synchroniously

Post by Roberthh » Thu Oct 31, 2019 2:40 pm

Or the memory access function as viper code:

Code: Select all

@micropython.viper
def memread(p: ptr16) -> int:
    return p[0]
Call be called e.g. with memread(0x3FF44008)

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: Set Pins values synchroniously

Post by pidou46 » Thu Nov 07, 2019 8:12 pm

Thanks,

I have build a complete working sample:

Code: Select all

from machine import Pin, mem16

p12=Pin(12, Pin.OUT)
p14=Pin(14, Pin.OUT)

p12.value(0)
print(p12.value())

p14.value(0)
print(p14.value())

#esp32
GPIO_OUT_REG=0x3FF44004

#set GPIO12 and GPIO14 to 1
GPIO=0b00000000000000000101000000000000

mem16[GPIO_OUT_REG]=GPIO

print(p12.value())
print(p14.value())

I haven't try the viper code right now, does it bring any advantages?
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: Set Pins values synchroniously

Post by OutoftheBOTS_ » Thu Nov 07, 2019 8:18 pm

I think it should be considered adding the the feature to the machine class the ability to be able to set multiple pins at once that all are in the 1 register as it is not uncommon that people will want to write code for parallel pin operations.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Set Pins values synchroniously

Post by Roberthh » Thu Nov 07, 2019 8:21 pm

Note, that writing to 0x3FF44004 will set all 32 bits to the value defined in the pattern. If you want to change individual bits but leave the others unchanged, you have to read the ports state first, mask the bits out you want to change, insert the new pattern and write it back.

Viper code is faster.

pidou46
Posts: 101
Joined: Sat May 28, 2016 7:01 pm

Re: Set Pins values synchroniously

Post by pidou46 » Thu Nov 07, 2019 8:25 pm

I have tried the viper code, but I get the following error:

Code: Select all

Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
SyntaxError: invalid micropython decorator
I run the same code on esp8862 and doesn't get the error
nodemcu V2 (amica)
micropython firmware Daily build 05/31/2016

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Set Pins values synchroniously

Post by Roberthh » Thu Nov 07, 2019 8:29 pm

the decorator is:

@micropython.viper

If that fails, you may need to update the firmware.
Edit: and yes, it has to be at the line before a function definition, like

Code: Select all

@micropython.viper
def my_viper_fct():
    pass

Post Reply