ESP12 and More Pins

ESP-12I’m just about to have a go at one of the larger boards – the ESP12 (or 201)…   so can someone save me (and others) re-inventing the wheel.

Here’s what I do to initialise an ESP-01 port bit GPIO0 as an output.

Firstly the setup..

// For GPIO2 just change the 0 to 2 - there is one init line.
#define LED_GPIO 0
#define LED_GPIO_MUX PERIPHS_IO_MUX_GPIO0_U
#define LED_GPIO_FUNC FUNC_GPIO0

then initialisation

PIN_FUNC_SELECT(LED_GPIO_MUX, LED_GPIO_FUNC);

 

and here it is set to 1.

GPIO_OUTPUT_SET(LED_GPIO, OUT_ON);

 

As you can see, I’ve already figured out how to do the same with GPIO2 (though I’ve not used GPIO2 as an output yet)

So – what other pins can we use in exactly the same way and are the numbers as you would expect or different?? This general principle also seems to work for GPO4 and 5 but not for the higher numbers.

Facebooktwittergoogle_pluspinterestlinkedin

17 thoughts on “ESP12 and More Pins

  1. Im using Pin14 for the DS18B20

    //set gpio14 as gpio pin
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);
    //disable pulldown
    PIN_PULLDWN_DIS(PERIPHS_IO_MUX_MTMS_U);
    //enable pull up R
    PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);
    // Configure the GPIO14 with internal pull-up
    // PIN_PULLUP_EN( gpio );
    GPIO_DIS_OUTPUT( 14);

  2. I use two outs, one input, 3pwm's and adc.
    This shows 15 being used but in fact it has to be held low as far as my tests have gone.
    I dob't use gpio0, although I could if I wanted.

    #define LED_GPIO_14 14
    #define LED_GPIO_MUX_14 PERIPHS_IO_MUX_MTMS_U
    #define LED_GPIO_FUNC_14 FUNC_GPIO14
    #define LED_GPIO_2 2
    #define LED_GPIO_MUX_2 PERIPHS_IO_MUX_GPIO2_U
    #define LED_GPIO_FUNC_2 FUNC_GPIO2
    #define LED_GPIO_5 5
    #define LED_GPIO_MUX_5 PERIPHS_IO_MUX_GPIO5_U
    #define LED_GPIO_FUNC_5 FUNC_GPIO5
    #define LED_GPIO_15 15
    #define LED_GPIO_MUX_15 PERIPHS_IO_MUX_MTDO_U
    #define LED_GPIO_FUNC_15 FUNC_GPIO15

    ++++++++++++

    This for adc and no preparation required ....
    uint8_t buffer[16];
    uint16 adc = system_adc_read();
    adc = adc/10;
    ets_sprintf( buffer, "%d", adc );
    MQTT_Publish(client, "/echo", buffer, 3, 0, 0);

    This sets up gpio's ......
    PIN_FUNC_SELECT(LED_GPIO_MUX_14, LED_GPIO_FUNC_14);
    PIN_FUNC_SELECT(LED_GPIO_MUX_2, LED_GPIO_FUNC_2);
    PIN_FUNC_SELECT(LED_GPIO_MUX_5, LED_GPIO_FUNC_5);
    PIN_FUNC_SELECT(LED_GPIO_MUX_15, LED_GPIO_FUNC_15);

    GPIO_DIS_OUTPUT(5); /* should make input */
    PIN_PULLUP_EN(LED_GPIO_MUX_5);

    /*GPIO_OUTPUT_SET(LED_GPIO_12, 1); */
    GPIO_OUTPUT_SET(LED_GPIO_15, 0);
    GPIO_OUTPUT_SET(LED_GPIO_14, 1);
    GPIO_OUTPUT_SET(LED_GPIO_2, 1);

    This sets up and drives pwm ...
    servo_param.pwm_freq = 500;
    servo_param.pwm_duty[0]=255;
    servo_param.pwm_duty[1]=255;
    servo_param.pwm_duty[2]=255;

    pwm_init(servo_param.pwm_freq,servo_param.pwm_duty);

    pwm_set_duty(servo_param.pwm_duty[1], 1);*/
    pwm_set_duty(pwm_duty1, 0);
    pwm_set_duty(pwm_duty2, 1);
    pwm_set_duty(pwm_duty3, 2);
    pwm_start();

    I copied some routines for the intial setup of frequency,pwm. I have given credit before somewhere .
    In the routine a pointer is required to the pwm duty.
    I copied over the pwm c & h files from the Iot example.
    in the pwm.header I defined what ports I required to use ..
    #define PWM_DEPTH 255

    #define PWM_1S 1000000

    #define PWM_0_OUT_IO_MUX PERIPHS_IO_MUX_MTDI_U
    #define PWM_0_OUT_IO_NUM 12
    #define PWM_0_OUT_IO_FUNC FUNC_GPIO12

    #define PWM_1_OUT_IO_MUX PERIPHS_IO_MUX_GPIO4_U /*MTDO_U */
    #define PWM_1_OUT_IO_NUM 4
    #define PWM_1_OUT_IO_FUNC FUNC_GPIO4

    #define PWM_2_OUT_IO_MUX PERIPHS_IO_MUX_MTCK_U
    #define PWM_2_OUT_IO_NUM 13
    #define PWM_2_OUT_IO_FUNC FUNC_GPIO13

    Just a quick response .. hope it helps

    1. Do you know which pins PWM is available on?
      I'm pretty sure i've copied your example for the ESP-01 with the only change being:
      #define PWM_0_OUT_IO_NUM 12
      #define PWM_0_OUT_IO_FUNC FUNC_GPIO12

      change to:
      #define PWM_0_OUT_IO_NUM 2
      #define PWM_0_OUT_IO_FUNC FUNC_GPIO2

      I have an LED connected to GPIO2 and simple on/off switching works fine but I get no response when trying to set PWM to that pin.
      I'm starting to think the pins available on the ESP-01 just can't do PWM but then http://g-lab.ca/esp8266ex-gpio-registers/ seems to indicate that ALL pins can.

      1. well I've answered my own question again 🙂
        GPIO2 _can_ do PWM!
        For those playing along at home:
        I made the below change in pwm.h:
        #define PWM_0_OUT_IO_NUM 12
        #define PWM_0_OUT_IO_FUNC FUNC_GPIO12

        change to:
        #define PWM_0_OUT_IO_NUM 2
        #define PWM_0_OUT_IO_FUNC FUNC_GPIO2

        In user_main.c:

        pwm_init(500, 0);
        pwm_set_freq((uint16_t)myFreq, 0);
        pwm_start();

        Now the pwm_init command is not right... the code in pwm.c expect an array to be passed instead of just '0' but I found when doing that I receive: Fatal Exception(28) every time so I made an additional change in pwm.c.
        From:


        LOCAL void ICACHE_FLASH_ATTR
        pwm_set_freq_duty(uint16 freq, uint8 *duty)
        {
        uint8 i;

        pwm_set_freq(freq);

        for (i = 0; i < PWM_CHANNEL; i++) {
        pwm_set_duty(duty[i], i);
        }
        }

        to:

        LOCAL void ICACHE_FLASH_ATTR
        pwm_set_freq_duty(uint16 freq, uint8 *duty)
        {
        uint8 i;
        pwm_set_freq(freq);

        for (i = 0; i < PWM_CHANNEL; i++) {
        pwm_set_duty(0, i);
        }
        }

        Finally back in user_main.c I set up a timer to call a quick function to cycle through the duty (0-255) every 30ms:

        LOCAL void ICACHE_FLASH_ATTR pwmtest_cb(void *arg)
        {
        myDuty = myDuty + dir;
        pwm_set_duty(myDuty, 0);
        pwm_start();
        if (myDuty > 250) {
        dir = dir * -1;
        }
        if (myDuty < 10) {
        dir = dir * -1;
        }
        os_delay_us(10000);
        os_printf("Duty: %d\n",myDuty);
        }

        The result is an LED that slowly fades from nothing up to full brightness then slowly back down to nothing and repeats!

    1. This is great but for the end comment --- that the latest SDK breaks it.. have you resolved this? The reason I ask is that the 0.9.5 SDK is the nearest we have to something that does not fall over so really... getting it to work with that SDK is important - I wonder if anyone can help given that you let us know what the problem is?

      1. I've found the problem. For the basic test code of my drivers i have no need for WiFi. So i used to set:

        wifi_set_opmode(NULL_MODE);

        I don't know if it turned off the wifi chip or not, but it did make the console shut up about networking stuff. This was under 0.9.4.

        In 0.9.5 there seems to be a timer starting at wifi_set_opmode(). And it has nothing to do, so it times-out. And time-out on a timer raises an exception that halts the entire system.

        This setting seems to be persistent. So if i once flashed code that called wifi_set_opmode(NULL_MODE), it would remain in the chip. Crashing the next program i flash as well. This would go on until a program calls wifi_set_opmode with some of the 'legal' values. (STATION_MODE, SOFTAP_MODE, STATIONAP_MODE).

  3. Actually, i have not tested that library with v0.9.5. I tested a clean sdk 0.9.5 install with one of the basic examples (could have been blinky). It compiled and uploaded just fine but the esp had a infinite crash loop with some message about "MEM CHK FAIL" on the console. So i threw the whole sdk out. I will try upgrading the sdk again once tuanpmt/esp_mqtt upgrades to 0.9.5 or higher.

  4. Didn't know where to ask this but surely someone can help here. To test I have a LED connected to GPIO2 on my ESP-1, and I can turn it on/off with MQTT without problems by setting the GPIO2 output mode to 1 after it's booted.

    However, when the ESP-1 (re)boots, putting GPIO2 in HIGH mode puts it in bootloader mode preventing a normal start. Is there a way to get around this, without having to use a 47K resistor or button for example? Prefer not to use those if possible, to keep it as small as possible (and the resistor dims the LED light considerably).

    I use the following code in user_main.c:
    (header section)
    #define LED_GPIO 2
    #define LED_GPIO_MUX PERIPHS_IO_MUX_GPIO2_U
    #define LED_GPIO_FUNC FUNC_GPIO2

    and my "user_init" function starts like this:

    void user_init(void)
    {
    uart_init(BIT_RATE_115200, BIT_RATE_115200);
    os_delay_us(1000000);

    CFG_Load();
    PIN_FUNC_SELECT(LED_GPIO_MUX, LED_GPIO_FUNC);

    I'm sure it's a simple thing

    1. Patrick - surely it is GPIO0 that does that? I get around that by basing any connections on + not -.. so a LED from the port bit via a resistor to + rather than ground.

Comments are closed.