6. GPIO Pins¶
The way to connect your board to the external world, and control other components, is through the GPIO pins. Not all pins are available to use, in most cases only pins 0, 2, 4, 5, 12, 13, 14, 15, and 16 can be used.
The pins are available in the machine module, so make sure you import that first. Then you can create a pin using:
Here, the “0” is the pin that you want to access. Usually you want to configure the pin to be input or output, and you do this when constructing it. To make an input pin use:
You can either use PULL_UP or None for the input pull-mode. If it’s not specified then it defaults to None, which is no pull resistor. GPIO16 has no pull-up mode. You can read the value on the pin using:
The pin on your board may return 0 or 1 here, depending on what it’s connected to. To make an output pin use:
Then set its value using:
6.1. External interrupts¶
All pins except number 16 can be configured to trigger a hard interrupt if their input changes. You can set code (a callback function) to be executed on the trigger.
Let’s first define a callback function, which must take a single argument, being the pin that triggered the function. We will make the function just print the pin:
Next we will create two pins and configure them as inputs:
An finally we need to tell the pins when to trigger, and the function to call when they detect an event:
We set pin 0 to trigger only on a falling edge of the input (when it goes from high to low), and set pin 2 to trigger on both a rising and falling edge. After entering this code you can apply high and low voltages to pins 0 and 2 to see the interrupt being executed.
A hard interrupt will trigger as soon as the event occurs and will interrupt any running code, including Python code. As such your callback functions are limited in what they can do (they cannot allocate memory, for example) and should be as short and simple as possible.
This should work on either ESP8266 or ESP32 MicroPython, but the instructions are written for ESP8266. There are minor differences, eg: the numbers of pins and their capabilities.
The number of pins, and their capabilities, varies between ESP8266 and ESP32, and not all pins are available on all boards.
To control an output pin, you must first configure it. The library makes the pins available to your Python code, and let’s you specify how you want to use that pin. To configure a pin as a digital output::
Note: On the LoLin32Lite, used in the LoliBot, there’s an equivalent blue LED on pin 22
On the ESP-12 module, GPIO2 is connected to an on-board LED, so you should be able to turn the LED on and off:
Note that it is connected backwards: to turn the LED on, set the pin value to False and to turn it off set the pin value to True.
Of course you can do this in a loop to get ‘blinky’, the microcontroller equivalent of :
You can also turn the LED “partly on” by turning it on and off rapidly. Doing this in Python would be flickery and a waste of power, but thankfully there’s hardware support for pulse-width modulation (PWM). This just means turning the pin on and off rapidly, and it lets you set the proportion of the time the LED is on, called the ‘duty cycle’:
To configure a pin as PWM, wrap the object in a object:
sets the frequency (in Hz) and sets the duty cycle between 0 (always off) and 1023 (always on). Beyond about 30Hz, the LED will no longer appear to be flashing, instead it will be changing in perceived brightness.
This lets you fade the LED in and out like so:
Yay, it’s ‘throbby’, the microcontroller equivalent of .
Note: There isn’t an equivalent button on the LoliBot, as the button on the LoLin32Lite resets the CPU! But this should work with the reflectance sensor on GPIO4
Most ESP8266 development boards have a button attached to GPIO0. This can be used to put the device into flash mode when it is reset, but once the device has started it can be used as a general purpose input::
Note: There’s isn’t really equivalent hardware on the LoliBot, sorry
There’s also an analog input pin, sadly only one on ESP8266::
On the ESP32 there are more ADC channels available. Currently, 8 channels are available on GPIO pins 32 through 39. The ADC can be programmed with variable attenuation and resolution, shared across all the channels.
Note: On the LoliBot, there’s a string of three APA106 NeoPixels on GPIO2.
“NeoPixels” is a name given to a family of coloured LEDs with an onboard controller. There’s a tiny controller in each pixel, and you can daisy chain them together to control many pixels from a single output line. There are several different versions of these chips, including RGB and RGBW varieties. Some examples:
To control them from MicroPython, use the library:
NeoPixels can be purchased from Ebay (etc) preassembled into ribbons, rings, grids and other shapes. Controlling a handful of pixels may seem like a silly thing to do when you’re used to having millions of pixels at your disposal, but it can be a lot of fun.
Note: LoliBot features an MPU-9250 accelerometer / gyrometer on pins 18 (SDA)/19 (SCL). It should work with the code below.
I2C is a shared serial bus which allows your microcontroller to communicate with multiple peripheral devices using a single pin.
It is part of the library
The I2C library is still quite low level, and using it involves a lot of reading of datasheets. However, it is quite easy to wrap I2C functions into small library functions. For the BuzzConf Rocket Surgery project we wrapped this sensor up with a very small library
class Pin -- control I/O pins
A pin object is used to control I/O pins (also known as GPIO - general-purpose input/output). Pin objects are commonly associated with a physical pin that can drive an output voltage and read input voltages. The pin class has methods to set the mode of the pin (IN, OUT, etc) and methods to get and set the digital logic level. For analog control of a pin, see the :class:`ADC` class.
A pin object is constructed by using an identifier which unambiguously specifies a certain I/O pin. The allowed forms of the identifier and the physical pin that the identifier maps to are port-specific. Possibilities for the identifier are an integer, a string or a tuple with port and pin number.
Usage Model:from machine import Pin # create an output pin on pin #0 p0 = Pin(0, Pin.OUT) # set the value low then high p0.value(0) p0.value(1) # create an input pin on pin #2, with a pull up resistor p2 = Pin(2, Pin.IN, Pin.PULL_UP) # read and print the pin value print(p2.value()) # reconfigure pin #0 in input mode with a pull down resistor p0.init(p0.IN, p0.PULL_DOWN) # configure an irq callback p0.irq(lambda p:print(p))
Methods.. method:: Pin.init(mode=-1, pull=-1, *, value, drive, alt) Re-initialise the pin using the given parameters. Only those arguments that are specified will be set. The rest of the pin peripheral state will remain unchanged. See the constructor documentation for details of the arguments. Returns ``None``. .. method:: Pin.value([x]) This method allows to set and get the value of the pin, depending on whether the argument ``x`` is supplied or not. If the argument is omitted then this method gets the digital logic level of the pin, returning 0 or 1 corresponding to low and high voltage signals respectively. The behaviour of this method depends on the mode of the pin: - ``Pin.IN`` - The method returns the actual input value currently present on the pin. - ``Pin.OUT`` - The behaviour and return value of the method is undefined. - ``Pin.OPEN_DRAIN`` - If the pin is in state '0' then the behaviour and return value of the method is undefined. Otherwise, if the pin is in state '1', the method returns the actual input value currently present on the pin. If the argument is supplied then this method sets the digital logic level of the pin. The argument ``x`` can be anything that converts to a boolean. If it converts to ``True``, the pin is set to state '1', otherwise it is set to state '0'. The behaviour of this method depends on the mode of the pin: - ``Pin.IN`` - The value is stored in the output buffer for the pin. The pin state does not change, it remains in the high-impedance state. The stored value will become active on the pin as soon as it is changed to ``Pin.OUT`` or ``Pin.OPEN_DRAIN`` mode. - ``Pin.OUT`` - The output buffer is set to the given value immediately. - ``Pin.OPEN_DRAIN`` - If the value is '0' the pin is set to a low voltage state. Otherwise the pin is set to high-impedance state. When setting the value this method returns ``None``. .. method:: Pin.__call__([x]) Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin. It is equivalent to Pin.value([x]). See :meth:`Pin.value` for more details. .. method:: Pin.on() Set pin to "1" output level. .. method:: Pin.off() Set pin to "0" output level. .. method:: Pin.irq(handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), *, priority=1, wake=None, hard=False) Configure an interrupt handler to be called when the trigger source of the pin is active. If the pin mode is ``Pin.IN`` then the trigger source is the external value on the pin. If the pin mode is ``Pin.OUT`` then the trigger source is the output buffer of the pin. Otherwise, if the pin mode is ``Pin.OPEN_DRAIN`` then the trigger source is the output buffer for state '0' and the external pin value for state '1'. The arguments are: - ``handler`` is an optional function to be called when the interrupt triggers. The handler must take exactly one argument which is the ``Pin`` instance. - ``trigger`` configures the event which can generate an interrupt. Possible values are: - ``Pin.IRQ_FALLING`` interrupt on falling edge. - ``Pin.IRQ_RISING`` interrupt on rising edge. - ``Pin.IRQ_LOW_LEVEL`` interrupt on low level. - ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level. These values can be OR'ed together to trigger on multiple events. - ``priority`` sets the priority level of the interrupt. The values it can take are port-specific, but higher values always represent higher priorities. - ``wake`` selects the power mode in which this interrupt can wake up the system. It can be ``machine.IDLE``, ``machine.SLEEP`` or ``machine.DEEPSLEEP``. These values can also be OR'ed together to make a pin generate interrupts in more than one power mode. - ``hard`` if true a hardware interrupt is used. This reduces the delay between the pin change and the handler being called. Hard interrupt handlers may not allocate memory; see :ref:`isr_rules`. Not all ports support this argument. This method returns a callback object.
The following methods are not part of the core Pin API and only implemented on certain ports... method:: Pin.low() Set pin to "0" output level. Availability: nrf, rp2, stm32 ports. .. method:: Pin.high() Set pin to "1" output level. Availability: nrf, rp2, stm32 ports. .. method:: Pin.mode([mode]) Get or set the pin mode. See the constructor documentation for details of the ``mode`` argument. Availability: cc3200, stm32 ports. .. method:: Pin.pull([pull]) Get or set the pin pull state. See the constructor documentation for details of the ``pull`` argument. Availability: cc3200, stm32 ports. .. method:: Pin.drive([drive]) Get or set the pin drive strength. See the constructor documentation for details of the ``drive`` argument. Availability: cc3200 port.
The following constants are used to configure the pin objects. Note that not all constants are available on all ports... data:: Pin.IN Pin.OUT Pin.OPEN_DRAIN Pin.ALT Pin.ALT_OPEN_DRAIN Selects the pin mode. .. data:: Pin.PULL_UP Pin.PULL_DOWN Pin.PULL_HOLD Selects whether there is a pull up/down resistor. Use the value ``None`` for no pull. .. data:: Pin.LOW_POWER Pin.MED_POWER Pin.HIGH_POWER Selects the pin drive strength. .. data:: Pin.IRQ_FALLING Pin.IRQ_RISING Pin.IRQ_LOW_LEVEL Pin.IRQ_HIGH_LEVEL Selects the IRQ trigger type.
Class Pin – control I/O pins¶
Pin objects are used to control I / O pins (also known as GPIO-general purpose input / output). Pin objects are usually associated with physical pins that can drive the output voltage and read the input voltage. The pin class has a method to set the pin mode (IN, OUT, etc.) and a method to obtain and set the digital logic level. For analog control of pins, please refer to class.
Construct a pin object by using an identifier that explicitly specifies a certain I/O pin. The allowed identifier form and the physical pin to which the identifier is mapped are port-specific。 The possibility of the identifier is an integer, a string or a tuple with port and pin number.
- class (id, mode=1, pull=1, value, drive, alt)¶
Access the pin peripheral (GPIO pin) associated with the given. If other parameters are given in the build object, they are used to initialize the pins. Any settings not specified will maintain their previous state.
The mPython control board provides its own pin mapping, mapping pins to GPIO of ESP32.For example, the P0 pin of the control board corresponds to the IO33 of ESP32, then you can use to replace .
- is mandatory and can be any object. Possible value types include：int (Internal pin identifier), str（Pin name）and tuple（[port，pin] match）. If you use mPython, you can use Pin.P(0~20), for example (Pin.P0)P0 pin provides mapping as GPIO.
- specifies the pin mode, which can be one of the following：
- - Pin is configured as input. If it is regarded as an output, the pin is in a high-impedance state.
- - Pin is configured as (normal) output.
- - Pin is configured as an open-drain output. The open-drain output works in the following way：If the output value is set to 0, the pin is active low; if the output value is 1, the pin is high impedance. Not all ports implement this mode, or some ports may only be implemented on certain pins.
- - Pin configuration as open drain。
specifies whether a (weak) pull resistor is connected to the pin, which can be one of the following：
- - No pull-up or pull-down resistors
- - Pull-up resistor enabled
- - Pull-down resistor enabled
- is only valid for and modes, and specifies the initial output pin value, otherwise the state of the pin peripherals remains unchanged.
- (mode=1, pull=1, value, drive, alt)¶
Reinitialize the pin with the given parameters. Only set the specified parameters. The rest of the pin peripheral state will remain unchanged. For detailed information about the parameters, see the build object documentation.
This method allows setting and getting the value of the pin, depending on whether provides the parameter.
If this parameter is omitted, the method obtains the digital logic level of the pin and returns 0 or 1 corresponding to the low voltage signal and the high voltage signal, respectively. The behavior of this method depends on the mode of the pin：
- - This method returns the actual input value currently present on the pin.
- - This method returns the actual input value currently present on the pin.
- - If the pin is in state “0”, the behavior and return value of the method are undefined. Otherwise, if the pin is in state “1”, the method returns the actual input value currently present on the pin.
If parameters are provided, this method sets the digital logic level of the pin. Parameter x can be any value converted to Boolean. If converted to True, set the pin to state “1”, otherwise set it to “0” state. The behavior of this method depends on the mode of the pin：
- - This value is stored in the output buffer of the pin. The state of the pin will not change, it is still in a high impedance state. Once changed to or mode, the stored value will be activated on the pin.
- - The output buffer is immediately set to the given value.
- - If the value is “0”,the pin is set to a low voltage state. Otherwise, the pin is set to high impedance.
When setting the value returned by this method .
Pin object is callable. The call method provides a (quick) shortcut to set and get the value of the pin. It is equivalent to Pin.value([x]). For details, see 。
Set the pin to high level
Set the pin to low level
- (handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), wake=None)¶
Configure the interrupt handler to be called when the trigger source of the pin is active. If the pin mode is , then the trigger source is the external value on the pin. If the pin mode is , then the trigger source is the output buffer of the pin. Otherwise, if the pin mode is , then the trigger source is the output buffer of state ‘0’ and the external pin value of state ‘1’.
is an optional function that is called when the interrupt is triggered.
configure events that can trigger an interrupt. Possible values are：
- falling interruption
- rising interruption
- low level interruption
- high level interruption
- Used for wake-up function, high level trigger
- Used for wake-up function, low level trigger
These values can be used to perform operations together to trigger multiple events.
select this interrupt to wake up the power mode of the system. It can be ， or . These values can also be “or” calculated together to cause pins to break in multiple power consumption modes.
This method returns a callback object.
The board’s own pin mapping maps of the mPython Board pins to the GPIO of ESP32 mPython
The following constants are used to configure pin objects.
Select pin mode.
Select whether there is a pull-up / pull-down resistor. Use None value.
Select IRQ trigger type.
© Copyright 2018-2021 labplus.All Rights Reserved Revision .
class Pin – control I/O pins¶
A pin is the basic object to control I/O pins. It has methods to set the mode of the pin (input, output, etc) and methods to get and set the digital logic level. For analog control of a pin, see the ADC class.
All Board Pins are predefined as pyb.Pin.board.Name:
CPU pins which correspond to the board pins are available as . For the CPU pins, the names are the port letter followed by the pin number. On the PYBv1.0, and are the same pin.
You can also use strings:
Users can add their own names:
and can query mappings:
Users can also add their own mapping function:
So, if you were to call: then is passed directly to the mapper function.
To summarise, the following order determines how things get mapped into an ordinal pin number:
Directly specify a pin object
User supplied mapping function
User supplied mapping (object must be usable as a dictionary key)
Supply a string which matches a board pin
Supply a string which matches a CPU port/pin
You can set to get some debug information about how a particular object gets mapped to a pin.
When a pin has the or pull-mode enabled, that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND respectively (except pin Y5 which has 11k Ohm resistors).
Now every time a falling edge is seen on the gpio pin, the callback will be executed. Caution: mechanical push buttons have “bounce” and pushing or releasing a switch will often generate multiple edges. See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed explanation, along with various techniques for debouncing.
All pin objects go through the pin mapper to come up with one of the gpio pins.
- class (id, ...)¶
Create a new Pin object associated with the id. If additional arguments are given, they are used to initialise the pin. See .
- classmethod ([state])¶
Get or set the debugging state ( or for on or off).
- classmethod ([dict])¶
Get or set the pin mapper dictionary.
- classmethod ([fun])¶
Get or set the pin mapper function.
- (mode, pull=Pin.PULL_NONE, \*, value=None, alt=-1)¶
Initialise the pin:
mode can be one of:
- configure the pin for input;
- configure the pin for output, with push-pull control;
- configure the pin for output, with open-drain control;
- configure the pin for alternate function, pull-pull;
- configure the pin for alternate function, open-drain;
- configure the pin for analog.
pull can be one of:
- no pull up or down resistors;
- enable the pull-up resistor;
- enable the pull-down resistor.
value if not None will set the port output value before enabling the pin.
alt can be used when mode is or to set the index or name of one of the alternate functions associated with a pin. This arg was previously called af which can still be used if needed.
Get or set the digital logic level of the pin:
With no argument, return 0 or 1 depending on the logic level of the pin.
With given, set the logic level of the pin. can be anything that converts to a boolean. If it converts to , the pin is set high, otherwise it is set low.
Return a string describing the pin object.
Returns the currently configured alternate-function of the pin. The integer returned will match one of the allowed constants for the af argument to the init function.
Returns an array of alternate functions available for this pin.
Returns the base address of the GPIO block associated with this pin.
Returns the currently configured mode of the pin. The integer returned will match one of the allowed constants for the mode argument to the init function.
Get the pin name.
Returns the cpu and board names for this pin.
Get the pin number.
Get the pin port.
Returns the currently configured pull of the pin. The integer returned will match one of the allowed constants for the pull argument to the init function.
initialise the pin to alternate-function mode with an open-drain drive
initialise the pin to alternate-function mode with a push-pull drive
initialise the pin to analog mode
initialise the pin to input mode
initialise the pin to output mode with an open-drain drive
initialise the pin to output mode with a push-pull drive
enable the pull-down resistor on the pin
don’t enable any pull up or down resistors on the pin
enable the pull-up resistor on the pin
A Pin represents a physical pin on the microprocessor. Each pin can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF object represents a particular function for a pin.
x3_af will now contain an array of PinAF objects which are available on pin X3.
- For the pyboard, x3_af would contain:
[Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2]
Normally, each peripheral would configure the af automatically, but sometimes the same function is available on multiple pins, and having more control is desired.
To configure X3 to expose TIM2_CH3, you could use:
Return a string describing the alternate function.
Return the alternate function index.
Return the name of the alternate function.
Return the base register associated with the peripheral assigned to this alternate function. For example, if the alternate function were TIM2_CH3 this would return stm.TIM2
© Copyright - The MicroPython Documentation is Copyright © 2014-2021, Damien P. George, Paul Sokolovsky, and contributors Last updated on 18 Oct 2021.
- Hl laser cut
- Mascot logo pubg
- Shambhala lineup 2017
- 38 dog crate
- Cheap trijicon scopes
- Jon boat rebuild
- High intern morty
- Caterpillar bobcat price
- 2 door post
- Famous apaches
- Bjd stl
The objective of this post is to explain how to use external pin interrupts on MicroPython running on the ESP32. The tests were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.
The objective of this post is to explain how to use external pin interrupts on MicroPython running on the ESP32. Please note that some of the code we are going to use here was explained in more detail on this previous post about timer interrupts.
The tests were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board. The MicroPython IDE used was uPyCraft.
First of all, we will import the machine module, which we will use to configure the external interrupts.import machine
Next we will declare a global variable that will be used by the interrupt handling function to communicate to the main program that an interrupt has occurred. This variable will be a counter, in order for us to not loose interrupts. You can check at this previous post why using a counter instead of a flag for communication between the interrupt and the main code.
Note that we should not perform long operations inside interrupt service routines (such as printing content to the serial console), and thus we will design it to execute as fast as possible. So, as mentioned the interrupt service routine will just inform the main code (by incrementing the counter) that the interrupt occurred, and it will be the main code that will actually handle it.interruptCounter = 0
We will also use another variable to keep track of how many interrupts have occurred since the program started executing. We will increment it and print its value each time an interrupt occurs.totalInterruptsCounter = 0
Next we will define the callback function to be executed when the interrupt occurs. This function has an input parameter in which an object of class Pin will be passed when the interrupt happens. Nonetheless, we will not use it in this tutorial.
The actual implementation of the function will consist on incrementing the previously defined interruptCounter variable. Note that this variable needs to be declared as global before we are able to modify it inside the function.def callback(pin): global interruptCounter interruptCounter = interruptCounter+1
Next we need to create an object of class Pin, which is used to control GPIO pins in MicroPython . You can check all the available parameters for the constructor here. For our program, we will need to pass as input the number of the pin we want to use, the mode of the pin and if it has a pull resistor associated.
For this example, I’m using pin 25, but you can use other. Please note that for some ESP32 boards, the ESP32 GPIO numbers may not match the ones labeled on the board.
We will also set the pin mode to input, with the IN constant of the Pin class.
Finally, we will set the pin to use its pull up resistor, which will guarantee that it will be in a known state (VCC) when no electrical signal is applied. This is done by passing the PULL_UP constant of the Pin class.p25 = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP)
Next we will specify how the interrupt will be triggered and what is the callback function to execute, by calling the irq function of our Pin object.
For this example, we will specify that the interrupt should be triggered when a falling edge is detected in the input signal connected to the pin. To do it, we need to pass the IRQ_FALLING constant of the Pin class as the trigger argument of the irq function. You can check here all the trigger types available.
We will also specify the handling function by passing our previously defined interrupt function as the handler parameter.p25.irq(trigger=machine.Pin.IRQ_FALLING, handler=callback)
Since all the configurations are now finished, we will enter in a polling loop to check for our interruptCounter variable. Naturally, we are polling only because our program is very simple and we are not doing anything else. Nonetheless, in a real application, we would most likely be performing some computation or the board would be in sleep mode to save energy, instead of being constantly checking the value of the variable.
When we detect that its value is greater than 0, we will treat the interrupt. First, we will decrement the counter value, to signal that it is going to be handled.
Note that since this variable is shared with the interrupt service routine code, we will previously disable the interrupts, only then decrement the counter, and then re-enable the interrupts, to avoid racing conditions.
The disabling and re-enabling of interrupts is done with the disable_irq and enable_irq functions of the machine module. You can check in more detail how to use them in the previous post.
Finally, we will increment the total number of interrupts counter and print its value. In this case, since this variable is not shared with the interrupt service routine, we don’t need to disable interrupts to change its value.
The final source code for the MicroPython script can be seen below, and already includes the interrupt checking loop.import machine interruptCounter = 0 totalInterruptsCounter = 0 def callback(pin): global interruptCounter interruptCounter = interruptCounter+1 p25 = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP) p25.irq(trigger=machine.Pin.IRQ_FALLING, handler=callback) while True: if interruptCounter>0: state = machine.disable_irq() interruptCounter = interruptCounter-1 machine.enable_irq(state) totalInterruptsCounter = totalInterruptsCounter+1 print("Interrupt has occurred: " + str(totalInterruptsCounter))
Testing the code
To test the code, simply upload the previous script to your ESP32 and run it. Upon running, the easiest way to trigger an interrupt without the need for external hardware is to connect and disconnect the pin where the interrupt was attached to the board’s GND pin.
Please be careful when executing this procedure to avoid connecting the GND pin to the wrong GPIO and damage the board.
You can check below at figure 1 the result from the interrupts.
Figure 1 – ESP32 MicroPython external pin interrupts.