NodeMCU ESP32 and ESP8266 Pin Modes (analog and digital, inputs and outputs)August 1, 2018
Pin Modes on the NodeMCU ESP32 and ESP8266
Today on the hookup we’re going to learn how to pick the right microcontroller for your project by examining the different pin modes available on the ESP8266 and the ESP32 based nodemcus.
Microcontrollers have 4 major pin modes in the Arduino IDE, digital inputs, digital outputs, analog inputs, and analog outputs. Not every pin can do every job, and each microcontroller has a specific number of pins that are able to be used with each pin type. Your specific project needs will determine the best microcontroller for your project. Today we’re going to use the nodeMCU version of the ESP8266 and ESP32 because they happen to be my favorite and are readily available on amazon, but there are hundreds of board variants based on these two chips.
The first major pin mode we’re going to look at is the digital input. A digital input pin will give a value of either 0 or 1 when the digitalRead(pin) function is called. When a pin on the nodemcu is connected to ground (or a voltage under .8 volts) it will return 0, and when it is exposed to a voltage over 2.4 volts it will return high. Anywhere in between .8 and 2.4 and you won’t reliably be able to predict the pin reading. It’s worth noting that zero can also be represented in code by the words false or low, and 1 can be represented by the values true or high.
But using the correct voltage is only half the battle. Imagine you’ve got a pin setup as an input, and connected to a switch that is off. That pin is neither grounded (pulled low) or exposed to voltage (pulled high). This type of pin is called a floating pin and will basically return random values based on how much electrical interference is present around it. Floating pins are bad and you should prevent them by using either a pull down resistor or a pull up resistor. A pull up resistor will make the default state of the pin HIGH by connecting a high value resistor from the GPIO pin to the 3.3v power source. If you were to connect the other side of your switch to ground, switching it will cause the pin to go from HIGH to LOW and you can program the rest of your sketch accordingly. A pulldown resistor does exactly the opposite giving a default state of LOW by connecting a high value resistor from the GPIO pin to ground. If you were using a pulldown resistor you’d want to connect the other end of your switch to a 3.3volt source which would cause the pin to go from LOW to HIGH.
On the ESP8266 based NodeMCU you can define most GPIO pins as input_pullups and it will use a built in resistor to pull the pin high. The only pins you can’t use as input pullups on the ESP8266 based nodeMCU are pin 15 and pin 16. Pin 15 makes sense because in my last video we determined that pulling pin 15 high during boot would cause boot failure, and pin 16 is the only pin on the ESP8266 to have a pulldown resistor. The input pulldown function is actually so specific to pin 16 that instead of typing INPUT_PULLDOWN for the pinmode, you actually type INPUT_PULLDOWN_16.
On the ESP32 based NodeMCU almost all pins can be used as either INPUT_PULLUP or INPUT_PULLDOWN, but there are a few exceptions: Steer clear of pins 6-11 because they will prevent the board from booting if used as an input, Pin 34-39 don’t work with an input pullup and pins 0-3 don’t work with an input pulldown, there are plenty of other pins available, so just skip those. To set up a digital input you’ll use one of these 3 different pinModes in your sketches setup section.
Now that we’ve covered the best pins for digital inputs, lets explore digital outputs. A digital output pin will output 3.3 volts when the digitalWrite(pin, HIGH) function is used and will output 0 volts (acting as a ground) when digitalWrite(pin, LOW) is used.
In accordance with my last video we want to avoid any pin that will output voltage during the boot process because that can cause unexpected behavior in your projects. On the ESP8266 based nodemcu this eliminates pins 1, 2, 3, 9, 10, and 16.
To be safe we probably also want to eliminate pins that can’t be grounded on boot, since the device we output to often provides enough of a ground to cause problems, so we’ll also eliminate pin 0. That leaves us with these 6 pins as viable outputs, which isn’t a whole lot.
If you need more outputs you might want to consider using an ESP32 instead. We’ll do the same thing on the ESP32 and eliminate the pins that are high on boot, then eliminate pins that output a PWM signal on boot, throw out the pins that can’t be grounded on boot, and oh by the way, pins 34-39 can’t be outputs at all. Even after all that we’re still left with 15 pins that are great candidates for outputs, more than twice the amount of the ESP8266. To set up a digital output on both boards you just need to add pinMode(pin, OUTPUT) to your setup section.
Next lets look at analog inputs. An analog input utilizes a circuit called an analog to digital converter or ADC to allow for specific voltages between 0 and 3.3v to be interpreted by the microcontroller. The ADC on the nodemcu ESP8266 by default has 10 bit resolution, which means using the analogRead() function will return return a value from 0-1024 based on the input voltages. If we take 3.3v and divide it by 1024 we can see that this will allow us to differentiate between voltages of around 3.2 millivolts.
The ESP8266 based nodeMCU has a single ADC on pin A0, so if you’re looking to utilize multiple analog sensors you’re going to need add on a multiplexer, or look at using a different board. To set up your the analog input on your ESP8266 you just add pinMode(A0, INPUT) to your setup and then call analogRead(A0) in your code.
The ESP32 based nodeMCU has 8 ADC channels, on pins 32 through 39, but only 6 are actually usable since pins 37 and 38 are not exposed from the chip to a header pin. By default the ESP32 has a 12 bit resolution meaning the analogRead() function will return a value from 0-4096. If we divide 3.3 by 4096 you can see that we can decipher between voltages of about .8 millivolts using this ADC. To set up your analog input on the ESP32 it’s exactly the same as the ESP8266, except instead of using A0, you’ll use one of !these! pins.
And last we’ll cover analog outputs.
Analog outputs come in two flavors: pulse width modulation (PWM), and digital to analog converters or DACs. The ESP8266 NodeMCU does not have a DAC so it’s limited to only PWM. A PWM signal basically turns on and off a 3.3v signal rapidly to simulate other voltages. For a more detailed explanation of PWM, check out my dimmable LED ceiling light video.
The ESP8266 based nodemcu uses it’s processor to generate PWM signals and any output pin can be used as a PWM pin by calling analogWrite(pin, duty). The ESP8266 will default to a frequency of 1000hz unless you change it using analogWriteFreq(new_frequency). Because it is a processor based pwm signal it often has to drop the frequency of the signal if the processor is overloaded. Unfortunately, the ESP8266 processor is not exactly a powerhouse, so even moderate wifi traffic can cause pwm frequency throttling.
The ESP32 is clearly superior when it comes to analog output. Not only does it handle its pwm generation independent from the main processor, but it also has a true DAC, which means it doesn’t just simulate different voltages by outputting a PWM signal, it can actually output voltages between 0 and 3.2 volts.
The downside to the ESP32 is that the analogWrite function hasn’t been implemented yet, which means in order to utilize the PWM functionality you need to use the LEDC function. To do this you first setup an LEDC channel using the ledcSetup() function where you specify the hardware channel you want to use, the frequency, and the resolution. This would setup LEDC channel 1 with a frequency of 500hz and an 8 bit resolution. Remember that an 8 bit resolution will mean that you will assign it values between 0 and 256 for the duty cycle. Again, for a more detailed explanation of PWM check out my dimmable LED ceiling light video. After you’ve setup the PWM channel you just need to tell it what pin to output to using the ledcAttachPin function, where you first specify the pin to output to, and then the LEDC channel to attach to it so here we’re assigning channel 1 to pin 32.
Once the pin is set up you change your duty cycle using the function ledcWrite(channel, duty cycle). This can be confusing because you’re using the LEDC channel in the function, not the pin it is attached to. So this would set our pwm signal on pin 32 to a duty cycle of 50%.
If you don’t want PWM and you actually want to output a specific voltage you can use the ESP32’s digital to analog converter, located on pin 25 and 26. To use this feature you’ll use the function dacWrite(pin, value), the value can be between 0 and 255, so we’d expect 128 to give us approximately 1.6 volts, which is half of the 3.2 max output voltage.
So there you have it, a explaination of the most commonly used features on the ESP8266 and ESP32 based nodeMCUs. I’ve made diagrams for all of the things I’ve discussed in this video and they are posted in the description. I know this video was a bit on the technical side, but I’m planning on doing a few project videos in the near future that will use some of these functions, so I wanted to make !this! video first to explain my design choices.
The summer is over and school is back in session, which means I’m back to my day job. I’m still going to try to release new, quality content, once a week on Wednesdays. I’ve recently set up a patreon page where I will be sharing my configuration.yaml file and node red flows file. If you are interested in supporting my channel in that way please head over and check it out. Remember that using the amazon links in the description also helps support my channel. I’ve also launched a website with transcripts of each of my videos and some other information like links to the tools that I use for my electronics projects. Finally, if you enjoyed this video, please consider subscribing, and as always, thanks for watching the hookup.
ESP8266 NodeMCU pinMode Diagram: https://github.com/thehookup/Wireless_MQTT_Doorbell/blob/master/PinModes_ESP8266_NodeMCU.jpg
ESP32 NodeMCU Pin Diagram: https://github.com/thehookup/ESP32_Ceiling_Light/blob/master/PinModes_ESP32_NodeMCU.jpg
visit my website: http://www.thesmarthomehookup.com
Follow me on Twitter: @TheHookUp1
Support my channel:
Music by www.BenSound.com