esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
16.05k stars 13.33k forks source link

Prevent user from "bricking" their ESP8266 w/deepSleep #136

Closed linagee closed 9 years ago

linagee commented 9 years ago

When I was playing around with deepSleep (and before I found GPIO16 and RST needed to be hooked together), I was ESP.deepSleeping just a few clock ticks after booting.

Maybe there should be something that kind of prevents the user from shooting themselves in the foot like this. My module was essentially bricked. (Tooked a long time to get out of this mode, strangely, an older esp8266/Arduino release was able to successfully flash/"unbrick".) You really need to be at least a second or two "past the boot" before going to sleep. Maybe record the boot time (if we aren't already?) and when deepSleep is called, see if we are far enough past that to deepSleep. If not, wait a second first or something.) This might save someone a headache.

codewise-nicolas commented 9 years ago

Removing power, enabling the programming pin (GPIO2 I believe) and powering up the ESP should make it boot into the bootloader and let you re-program it. There should not be a state where you can completely "brick" the ESP with deepsleep as the bootloader can be made to kick in before your program runs.

linagee commented 9 years ago

For some reason, it reflashed fine with the older release, but not the newer one. I think there might be a difference of CTS/RTS or something?

codewise-nicolas commented 9 years ago

The ESP8266 Arduino does not make use of the CTS/RTS lines. Just TX/RX, it expects you to toggle GPIO2 to enable the bootloader (Some people have come up with circuits to make use of the CTS line to do this, but in general they arent used/required)

duncan-a commented 9 years ago

codewise-nicolas Are you sure that "ESP8266 Arduino does not make use of the CTS/RTS lines"? I know of at least two people who are doing it with no 'external circuitry' except pullup/down resistors...

On 6 May 2015 at 18:19, codewise-nicolas notifications@github.com wrote:

The ESP8266 Arduino does not make use of the CTS/RTS lines. Just TX/RX, it expects you to toggle GPIO2 to enable the bootloader (Some people have come up with circuits to make use of the CTS line to do this, but in general they arent used/required)

— Reply to this email directly or view it on GitHub https://github.com/esp8266/Arduino/issues/136#issuecomment-99527520.

igrr commented 9 years ago

The current version from git toggles DTR and RTS to manipulate GPIO0 and RST(or CHPD).

codewise-nicolas commented 9 years ago

Ah good to know, i was not aware those changes had been done. Ill give them a try later.

So going back to the original problem, if you were relying on the DTR/RTS functionality to re-program your chip then it is possible that you were in a situation that would not get back into the bootloader.

duncan-a commented 9 years ago

Which version of the EPS? Is GPIO0 being pulled high via a resistor? Is Reset being pulled high via resistor? Etc...?

Software is capable of a lot, but not if the hardware isn't set up correctly.

Just a thought...

On 6 May 2015 at 21:51, codewise-nicolas notifications@github.com wrote:

Ah good to know, i was not aware those changes had been done. Ill give them a try later.

So going back to the original problem, if you were relying on the DTR/RTS functionality to re-program your chip then it is possible that you were in a situation that would not get back into the bootloader.

— Reply to this email directly or view it on GitHub https://github.com/esp8266/Arduino/issues/136#issuecomment-99585724.

tytower commented 9 years ago

Using this code and connecting DTR (GPIO16) to RST I get it going to sleep but it gets in a reset loop and does not start properly again . I must physically remove DTR from RST. ESP-12 board @igrr I still can't get the I2C towork at all ? [code]

include "DHT.h"

include "stdio.h"

include "SFE_BMP180.h" // Required to use BMP180

include "Wire.h"

include "ESP8266WiFi.h"

define DHT_PIN 2 //GPIO5 DHT22 for my sensorRHT03-others in library

define TIMEOUT 3000 //3 second timout

define SPARKFUN_UPDATE_TIME 20000 //Update SparkFun data server every 60000 ms (1 minute).

define debug

define ALTITUDE 750.0 // Altitude of My HQ in meters

unsigned long timer1 = 0; unsigned long timer2 = 0; char server[] = "data.sparkfun.com"; // name address for data.sparkFun (using DNS) // Set the static IP address to use if the DHCP fails to assign

const String publicKey = "RMzp9ANyqzfjw4drzNnZ"; const String privateKey = "........................"; const byte NUM_FIELDS = 4; const String fieldNames[NUM_FIELDS] = {"humidity" , "pressure2" , "temp" , "temp2"}; String fieldData[NUM_FIELDS];

//Character array to hold results char results[4]; //const int requestInterval = 20000; long lastAttemptTime = 0; float humidity=0; float temp=0; long pressure2 = 0; float temp2; const int dataSDA = 4; //BMP180 SDA const int clockSCL = 5;//BMP180 SCL

double T,P,p0,a; //float temp2 = 0.0;

long lastReadingTime = 0;

SFE_BMP180 pressure;

DHT dht(DHT_PIN,DHT22,15); WiFiClient client; // Time to sleep (in seconds): const int sleepTimeS = 30;

//////////////////////////////////////////////////////////////////////////////////

void setup(){

const char* ssid = "ME-HOME"; const char* password = ""; // Igrr-Wire.begin(0, 2); on ESP-01, else they default to pins 4(SDA) and 5(SCL)..

Wire.begin(dataSDA, clockSCL );//see above definiions //I2c.setSpeed(1); Wire.setClock(100000); // Create an instance of the server // specify the port to listen on as an argument WiFiServer server(80);

ifdef debug

Serial.begin(115200); delay(10);

// Connect to WiFi network Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid);

endif

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) { delay(500);

ifdef debug

Serial.print(".");
#endif 

}

ifdef debug

Serial.println(""); Serial.println("WiFi connected");

endif

// Start the server server.begin();

ifdef debug

Serial.println("Server started"); // Print the IP address Serial.println(WiFi.localIP()); Serial.println("all going");

endif

// Initialize the sensor (it is important to get calibration values stored on the device).

if (pressure.begin()) { delay(200);

ifdef debug

Serial.println("BMP180 init success");
#endif

} else { // Oops, something went wrong, this is usually a connection problem, // see the comments at the top of this sketch for the proper connections.

ifdef debug

Serial.println("BMP180 init fail\n\n");
#endif 
delay(500);
pressure.begin();
delay(500);
//while(1); // Pause forever.

} } //////////////////////////////////////////////////////////////////////////////// void loop(){

/////DHTREAD HERE////// // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)

float h = dht.readHumidity(); // Read temperature as Celsius float t = dht.readTemperature(); // Read temperature as Fahrenheit float f = dht.readTemperature(true);

// Check if any reads failed and exit early (to try again). if (isnan(h) || isnan(t) || isnan(f)) {

ifdef debug

Serial.println("Failed to read from DHT sensor!");
#endif
//return;

}

// Compute heat index // Must send in temp in Fahrenheit!

ifdef debug

Serial.print("Humidity: "); Serial.print(h); Serial.print(" %\t"); Serial.print("Temperature: "); Serial.print(t); Serial.println(" *C ");

endif

delay(2000); //////////////////////Testabove////////////// ////////DHTREAD HERE////////

humidity = dht.readHumidity(); temp = dht.readTemperature(); //temp = (temp*9/5) + 32 - 1; //To Farenheight calibrate here

String temp_string = dtostrf(temp_100, 4, 0, results); String humidity_string = dtostrf(humidity_100, 4, 0, results); delay(200); fieldData[0]=String(humidity); fieldData[2]=String(temp);

////////////get pressure and temp2 BMP180 HERE////////

if (millis() - lastReadingTime > 5000) { // if there's a reading ready, read it: // don't do anything until the data ready pin is high: if (digitalRead(dataSDA) == HIGH) ; char status; double T,P,p0,a;

// Start a temperature measurement: // If request is successful, the number of ms to wait is returned. // If request is unsuccessful, 0 is returned.

status = pressure.startTemperature(); if (status != 0) { // Wait for the measurement to complete: delay(status);

// Retrieve the completed temperature measurement:
// Note that the measurement is stored in the variable T.
// Function returns 1 if successful, 0 if failure.

status = pressure.getTemperature(T);
if (status != 0)
{
   #ifdef debug
  // Print out the measurement:
  Serial.print("temperature: ");
  Serial.print(T,2);
  Serial.print(" deg C, ");
  Serial.print((9.0/5.0)*T+32.0,2);
  Serial.println(" deg F");
  #endif
  // Start a pressure measurement:
  // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.

  status = pressure.startPressure(3);
  if (status != 0)
  {
    // Wait for the measurement to complete:
    delay(status);

    // Retrieve the completed pressure measurement:
    // Note that the measurement is stored in the variable P.
    // Note also that the function requires the previous temperature measurement (T).
    // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
    // Function returns 1 if successful, 0 if failure.

    status = pressure.getPressure(P,T);
    if (status != 0)
    {
        #ifdef debug
      // Print out the measurement:
      Serial.print("absolute pressure: ");
      Serial.print(P,2);
      Serial.print(" mb, ");
      Serial.print(P*0.0295333727,2);
      Serial.println(" inHg");
      #endif

      // The pressure sensor returns abolute pressure, which varies with altitude.
      // To remove the effects of altitude, use the sealevel function and your current altitude.
      // This number is commonly used in weather reports.
      // Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.
      // Result: p0 = sea-level compensated pressure in mb

      p0 = pressure.sealevel(P,ALTITUDE); // we're at 1655 meters (Boulder, CO)
       #ifdef debug
      Serial.print("relative (sea-level) pressure: ");
      Serial.print(p0,2);
      Serial.print(" mb, ");
      Serial.print(p0*0.0295333727,2);
      Serial.println(" inHg");
      #endif
      // On the other hand, if you want to determine your altitude from the pressure reading,
      // use the altitude function along with a baseline pressure (sea-level or other).
      // Parameters: P = absolute pressure in mb, p0 = baseline pressure in mb.
      // Result: a = altitude in m.

      a = pressure.altitude(P,p0);
       #ifdef debug
      Serial.print("computed altitude: ");
      Serial.print(a,0);
      Serial.print(" meters, ");
      Serial.print(a*3.28084,0);
      Serial.println(" feet");
      #endif
    }
    else Serial.println("error retrieving pressure measurement ln1\n");
  }
  else Serial.println("error starting pressure measurement ln2\n");
}
else Serial.println("error retrieving temperature measurement ln3\n");

} else Serial.println("error starting temperature measurement ln4\n");

delay(5000); // Pause for 5 seconds. }

  // timestamp the last time you got a reading:
  lastReadingTime = millis();
  delay(200);

////////////Update sparkfun data server every 60 seconds. // Convert each value to a string for our request to App Engine ///////////////////////////////////// if(millis() > timer1 + SPARKFUN_UPDATE_TIME) { timer1 = millis(); //Update timer1 with the current time in miliseconds since startup. delay(500); postData(); //Send data to sparkfun data server.

ifdef debug

Serial.println("Posting by timer !");
Serial.println(fieldData[0] );
Serial.println(fieldData[1] );
Serial.println(fieldData[2] );
Serial.println(fieldData[3] );
delay(500);

// deepSleep time is defined in microseconds. Multiply // seconds by 1e6

Serial.println(" Going to Sleep !" );

endif

ESP.deepSleep(sleepTimeS * 1000000);

} } [/code]

lumbric commented 7 years ago

In case you bricked your ESP8266 / D1 by putting it to sleep immediately in main.py follow these instructions: