10. Exploring EMIT's GPIO Expansion Connector - ControlBits/EMIT GitHub Wiki
To enable further expansion, the EMIT development board includes a GPIO Expansion Connector. This connector is ideal for interfacing to additional sensors such as a soil moisture probe or an ambient light sensor.
10.1 EMIT's GPIO Expansion Connector Pin-out
The GPIO Expansion Connector has 8x GPIO pins plus 1x 3V3 power supply and 2x GND pins. The VIN supply is also available on the connector.
The GPIO Interface pins can be configured to provide any combination of:
- 6x digital inputs/outputs
- 4x analog inputs (12-bit resolution)
- 1x I2C serial port
- 1x Serial UART
The full expansion connector layout is shown in the table below:
To configure or use any of EMIT's IO pins, you must first import the MicroPython 'machine' module:
import machine
10.2 Using EMIT's Digital Outputs
EMIT's expansion connector pins (IO1 to IO4, IO7 & IO8) can be configured as digital outputs as long as the pins are not already configured for some other purpose.
Each individual IO pin is capable of driving 40mA at 3.3v and sinking 28mA at 0v but this capability drops to less than 30mA when multiple pins are being driven at the same time.
Our recommendation is to limit the current driven or sunk by any pin to 20mA max.
A pin is defined and configured as an output using the 'machine.Pin' function as follows:
IO1 = machine.Pin(36, machine.Pin.OUT) # where the pin number = ESP32's GPIO number
Note: The pin number referred to in the configuration, is the ESP32's GPIO Pin number. This pin number is shown in the table above: EMIT's Expansion Connector Pin-out. In this example, IO1 (connector pin 2) is connected to the ESP32's GPIO 36.
Once configured, the output 'state' of the pin is set using the 'value()' function. Setting the value to 0 sets the pins output LOW (0 volts). Setting the value to 1 sets the pins output HIGH (3.3v).
IO1.value(0) # 0 = output LOW, 1 = output HIGH
10.3 Using EMIT's Digital Inputs
EMIT's expansion connector pins (IO1 to IO4, IO7 & IO8) can be configured as digital inputs as long as the pins are not already configured for some other purpose.
Once configured as an input, each pin has a high impedance, sinking or sourcing just 50nA per pin.
A pin is defined and configured as an input using the 'machine.Pin' function as follows:
IO2 = machine.Pin(39, machine.Pin.IN) # where the pin number = ESP32's GPIO number
Note: please refer to the table above: EMIT's Expansion Connector Pin-out to determine the ESP32's GPIO pin assigned to EMIT's expansion connector.
The ESP32 has configurable pull-ups. To add a pull-up, just add 'machine.Pin.PULL_UP' to the configuration:
IO2 = machine.Pin(39, machine.Pin.IN, machine.Pin.PULL_UP) # where the pin number = ESP32's GPIO number
Once configured, as an input, the 'state' of the pin can be read using the 'value()' function:
IO2state = IO2.value() # read state of input, 0 = LOW, 1 = HIGH
When the value returns '0' the input is LOW (<1.0 volt). A value to '1' is returned when the input is HIGH (> 2.4v).
10.4 Using EMIT's Analog Inputs
Pins IO1 to IO4 of EMIT's expansion connector can be configured as analog inputs (A1 to A4) as long as the pins are not already configured for some other purpose.
The ESP32 has an integrated, 12-bit Analog to Digital Converter (ADC). The ADC converts the analog input voltage on a configured analog input pin to a digital value ranging from 1 to 1024.
The input voltage range of the analog input pins is 0 mV to 1000mV DC, where 0mV is represented as a digital '0' and 1000mV is represented by the digital value '4096'. Any voltage higher than 1000mV will be represented as '4096'. This gives an ADC resolution of 1000mV/4096 = 0.244mV.
To configure a pin as an analog input, use the machine.ADC function:
A1 = machine.ADC(Pin(36)) # where the pin number = ESP32's GPIO number
To read the ADC value of a given pin use the read() function:
A1value = A1.read() # read ADC value of pin A1
To convert the ADC value to a voltage, simply multiply it by the ADC resolution (0.244mV).
e.g. an ADC value of '1000' = 1000 * 0.244mV = 244.4mV (0.2444 Volts).
To measure voltages greater than 1 Volt, simply use a potential divider network on the input and multiply the result by the scaling factor of the potential divider.
10.5 Using EMIT's I2C interface
Pins IO7 and IO8 of EMIT's expansion connector are connected to the ESP32 hardware I2C port, where:
- IO7 = GPI21 = I2C SCL (Clock)
- IO8 = GPI22 = I2C SDA (Data)
NOTE: To use these pins, you will need to connect a 10k pull-up resistor to each of these pins (to pull the pins up to 3.3v).
To define our I2C object (EMITi2c) and configure the I2C port, use the machine.I2C() function:
EMITi2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22), freq=400000)
In this case we are setting the frequency of the clock to 400kHz.
To write to an I2C slave, use the I2C.writeto() function, where the first value is the 7-bit address of the slave we wish to write to, and the second value is the value we wish to write to the device - in this case three bytes '012'.
EMITi2c.writeto(112, b'012') # write bytes '012' to slave address 112
Reading from an I2C slave is a similar process using the I2C.readfrom() function, where the first value is the 7-bit address of the slave we wish to read from and the second value is the number of bytes we want to read.
I2Cresult = EMITi2c.readfrom(112, 6) # read 6 bytes from slave address 112
You can also scan the I2C port for slave devices, using the I2C.scan() function. A simple scanning process, which displays a list of I2C slave addresses might look like this:
# scan for I2C devices
print("Scanning for I2C devices ...")
EMITscan = EMITi2c.scan()
print("I2C devices found: " + str(EMITscan))
10.6 Using EMIT's UART
Pins IO5 and IO6 of EMIT's expansion connector are connected to the ESP32 UART0, where:
- IO5 = GPIO1 = UART0 TX
- IO6 = GPIO3 = UART0 RX
IMPORTANT NOTE: By default, the ESP32's UART0 is assigned to REPL (Read-Eval-Print-Loop) that drives the console-based development environment ... such as the Shell we've been using in Thonny. To use UART0 in your application you will need to un-assigned it from the REPL at run time. To avoid this complication, you might like to consider using a software UART implementation on pins IO1 to IO4, IO7 or IO8
The default REPL UART0 configuration has a baud rate of 115,200 bps.
NOTE: The maximum input/output voltage of these pins is 3.3v. To drive higher voltages (such as an RS-232 interface) an external high-voltage line driver will be required.
More details on using UART0 to follow ...