Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NodeMCU continuously rebooting using HX711 #67

Open
AGordiGuerrero opened this issue Mar 15, 2017 · 22 comments
Open

NodeMCU continuously rebooting using HX711 #67

AGordiGuerrero opened this issue Mar 15, 2017 · 22 comments

Comments

@AGordiGuerrero
Copy link

Hi guys,

many thanks for the nice work with this library. I am enjoying it and doing some nice scales.

I was using the library without problems in a NodeMCU 1.0 (ESP 12-E) but I changed to the smaller version of the board (ESP 12-F):
http://www.banggood.com/Mini-NodeMCU-ESP8266-WIFI-Development-Board-Based-On-ESP-12F-p-1054209.html?rmmds=search

With the same code, as soon as I include the line:

HX711 scale(D6, D8) // or whatever pins I choose.

it restarts over and over again and send the message via serie (115200 bd):

ets Jan 8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v60000318
~ld

After looking in several forums, I have not found the answer. Can anybody give me a clue?

Thanks in advance!

@AGordiGuerrero
Copy link
Author

First self-correction:
Now it neither work with the NodeMCU 12E.

Maybe it is related with the version of the compiler (it is running under Windows, Arduino IDE 1.6.12). Extremely slow compiler since last update. I will keep looking.

@bogde
Copy link
Owner

bogde commented Mar 16, 2017

can you post your sketch? i'm trying the HX711SerialBegin demo (MacOS, Arduino 1.8.1) on a "D1 mini WeMos.cc" and seems to be working after cleaning up the setup section.

@bogde
Copy link
Owner

bogde commented Mar 16, 2017

i just tried v1.6.9 on windows and it seems to work too, again, after removing most of the test code from the setup section. i'm going to update to 1.8.1 on windows too and give it one more try.

@AGordiGuerrero
Copy link
Author

Many thanks for the answer.

I have tried the Arduino IDE V1.8.1, V1.6.9, V1.6.6 and V1.6.0. All under ubuntu 64 bits. No solution found, same error and reboot. I even reinstalled every library deleting the /home/user/Arduino directory.

I paste below the code. It includes lots of comments, some timing variable and debugging flags. Please tell me if it is not clear and I will clean it. In line 93 is the scale initialization which causes the reboot.

I also tested that it is not a power issue, powering from a bench DC power supply. I see a peak on current just in the reboot, but I supose it is normal.

// WEIGHT MEASURE AND I2C OLED 128X64 SCREEN
//---------------------******--------------------------//
//
// Based on:
//    - NodeMCU and Arduino open hardware.
//    - Adafruit and Bogde libraries.
//          https://github.com/bogde/HX711
//    - Sparkfun HX711 load cell sketches
//
//    - Arduino online open community. Thank you all!
//
// Licensed under Creative Commons (SH-BY-NC). @AGordiGuerrero
//
// Antonio Gordillo Guerrero
// anto@unex.es
// @AGordiGuerrero
// Smart Open Lab. Escuela Politécnica de Cáceres. Universidad de Extremadura.
// @SolEpcc 
//
//--------------------******---------------------------//

/*/ Version Control

  
  2017/01/02: V1.4 Update to use the mini NodeMCU ESP-12F module alone.
  2017/01/02: Measure loop duration marking the start and end of the loop.
  2017/01/01: Include timing measures inside the main loop in #DEBUG .
  2016/12/31: Implementation of tare from a button. Removing shift from 1g.
  2016/12/30: AGG start coding from SmartScarecrow code. Simplifies all the code to eliminate configuration of alarms

*/

/* How to calibrate the scale (from https://github.com/bogde/HX711)
  - Call set_scale() with no parameter.
  - Call tare() with no parameter.
  - Place a known weight on the scale and call get_units(10).
  - Divide the result in step 3 to your known weight. You should get about the parameter you need to pass to set_scale.
  - Adjust the parameter in step 4 until you get an accurate reading.
*/


#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "HX711.h"

// Mode debug. Send all the information via serial port. Includes timing variables.
#define DEBUG

// Defines for the OLED I2C display
#define OLED_RESET LED_BUILTIN  //4
#define SSD1306_LCDHEIGHT  64


// Language settings for the display. Default is English.
//#define ESP // Comment for English version


// Arduino NodeMCU pin mapping
#define D0 16
#define D1 5 // I2C Bus SCL (clock)
#define D2 4 // I2C Bus SDA (data)
#define D3 0
#define D4 2 // Same as "LED_BUILTIN", but inverted logic
#define D5 14 // SPI Bus SCK (clock)
#define D6 12 // SPI Bus MISO 
#define D7 13 // SPI Bus MOSI
#define D8 15 // SPI Bus SS (CS)
#define D9 3 // RX0 (Serial console)
#define D10 1 // TX0 (Serial console)
#define SD3 10 // GPIO10 
#define SD2 9  // GPIO09 
#define SD1 8 // GPIO08 

//------------Global Variable-----------//

// Pin definitions:
//  - We use Rx and Tx for ....
//  - We use SCL in D1 and SDA in D2 for I2C communication
//  - We use CLS in D5 and DAT in D6 for SPI communication
//  - SD3 for digital input for tare

const int tare_button = D7;    // number of the pushbutton pin
//const int ledPin = D8;      // number of the LED pin


//OLED display object
Adafruit_SSD1306 display(OLED_RESET);

//HX711 scale;
HX711 scale(D5, D6);    // (CLS,DAT) parameter "gain" is ommited; the default value 128 is used by the library

// Timing variables
const int PROGMEM weightmeasure_period =  200; // interval to change the dimming level
unsigned long previousMillis_weightmeasure=0;

#ifdef DEBUG
const int PROGMEM serial_send_period = 2000; // interval to change the dimming level
unsigned long previousMillis_serial=0;
unsigned long loopstart_time=0;
unsigned long loop_duration_beforeserial=0;
unsigned long loop_duration=0;
unsigned long start_taring_time=0;
unsigned long iloop=0;
#endif


// weight variable
float weight=0.0;
float last_weight=0.0;
const int PROGMEM nmeasures=6; // number of measures to perform the average in each weight estimation

// Button variable
int tare_button_reading;



/////////////////////////// SETUP FUNCTION ///////////////////////////////
void setup() {

  Serial.begin(38400);  //start serial communication
  
  // Say hello...
  Serial.println();  Serial.println();  Serial.println();
  Serial.println("/////     WELCOME TO OPEN DIGITAL WEIGHT SCALE     ///////");
  Serial.println("              by @AGordiGuerrero");
  Serial.println();
  
#ifdef DEBUG
  Serial.println();  Serial.println(); Serial.println(" ******************** DEBUG MODE  ******************************");
#endif
  
  Serial.println(" Initializing the scale.....");

  // Buttons pins  pinMode(buttonPin, INPUT);
  pinMode(tare_button, INPUT);
//  pinMode(ledPin, OUTPUT);
  // set initial LED state
//  digitalWrite(ledPin, ledState);
  
  // OLED I2C begin
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display_INIT(); // initial screen


  Serial.println("Before setting up the scale:");
  Serial.print("read: \t\t");
//  Serial.println(scale.read());     // print a raw reading from the ADC

  Serial.print("read average: \t\t");
//  Serial.println(scale.read_average(20));   // print the average of 20 readings from the ADC

  Serial.print("get value: \t\t");
//  Serial.println(scale.get_value(5));   // print the average of 5 readings from the ADC minus the tare weight (not set yet)

  Serial.print("get units: \t\t");
//  Serial.println(scale.get_units(5), 1);  // print the average of 5 readings from the ADC minus tare weight (not set) divided
            // by the SCALE parameter (not set yet)


  // Following the calibration method....
  // I use an LGmagna (145 gr measured with another balance) returned with set_scale() weight= 62000 aprox.
  // I use a Schweppes bottle (379 gr measured with another balance) returned with set_scale() weight= 159300 aprox.
    
  //scale.set_scale(62000/145);                      // this value is obtained by calibrating the scale with known weights; see the README for details
//  scale.set_scale(159300/379);                      // this value is obtained by calibrating the scale with known weights; see the README for details
//  scale.tare();               // reset the scale to 0

/*
  Serial.println("After setting up the scale:");
  Serial.print("read: \t\t");
  Serial.println(scale.read());                 // print a raw reading from the ADC

  Serial.print("read average: \t\t");
  Serial.println(scale.read_average(20));       // print the average of 20 readings from the ADC

  Serial.print("get value: \t\t");
  Serial.println(scale.get_value(5));   // print the average of 5 readings from the ADC minus the tare weight, set with tare()

  Serial.print("get units: \t\t");
  Serial.println(scale.get_units(5), 1);        // print the average of 5 readings from the ADC minus tare weight, divided
            // by the SCALE parameter set with set_scale
*/

  Serial.println("Scale ready!");

}


/////////////////////////// LOOP FUNCTION ///////////////////////////////


void loop() {




#ifdef DEBUG
   loopstart_time = millis(); // This loop start time (ms)
#endif


// reading buttons
  // read the state of the tare_button:
   tare_button_reading = digitalRead(tare_button);


// Timing the weight measure
//    currentMillis = millis(); // Get current mseconds from millis
    if(millis() - previousMillis_weightmeasure > weightmeasure_period){

     // save this time
     previousMillis_weightmeasure = millis(); //update timing variable   

 //    scale.power_up();  // wakeup scale

  //   weight=scale.get_units(nmeasures); // measure and average for nmeasures times

  weight=0; // set zero for debug

     //weight=-weight; // sign correction if necessary

     // Correcting oscillations. We disregard all oscillations smaller than 0.5g away from the last one.
     if (abs(last_weight-weight) <= 0.2) {
        weight=last_weight; // sign correction if necessary
     }
     else{   
        last_weight=weight; // update last_weight if there was a significative diference with current measure
     }
     
     // Correcting non zero value. We disregard all measures smaller 0.5g.
     if (abs(weight) <= 0.5) {
        weight=0.0; // sign correction if necessary
     }
     
     display_WEIGHT();
    
  //   Serial.println("Tare button state: ");Serial.print(tare_button_reading);Serial.println();
     if (tare_button_reading == LOW) {
       Serial.println("Taring....");
       
#ifdef DEBUG
      start_taring_time=millis();
#endif
       display_TARING();     
       //scale.tare(nmeasures); // set the current weight as the tare
       Serial.println("Tared!");
       display_TARED();     
#ifdef DEBUG
       Serial.print("             Taring duration: "); Serial.print(millis()-start_taring_time, DEC); Serial.println(" ms.");
#endif
     }

//     scale.power_down(); // sleep scale

     
    }


#ifdef DEBUG
  
// counting the loop index
  iloop++;

// estimate this loop duration before serial communication
//  loop_duration_beforeserial=millis()-loopstart_time;

// Timing the serial communication for debug
    if(millis() - previousMillis_serial > serial_send_period){
      previousMillis_serial = millis(); //update timing variable   
      print_to_serial(); // printing all the information via serial port
    }

  loop_duration=millis()-loopstart_time;
#endif


}



// Display the model name and information
void display_MODEL(void) {
  display.drawRoundRect(0, 0, display.width(), display.height(), display.height() / 10, WHITE);
  display.drawRoundRect(15, 0, 100, 20, display.height() / 30, WHITE);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(21, 6);
#ifdef ESP
  display.println("Balanza");
#else
  display.println("Weight Balance");
#endif

  display.setCursor(6, 26);
#ifdef ESP
  display.println("Peso, 5kg OLED");
#else
  display.println("Weight measure (5kg)");
#endif
  display.setCursor(97, 42);
  display.println("V0.1");
  display.setCursor(12, 52);
  display.println("by @AGordiGuerrero");
  display.display();
  display.clearDisplay();
}



// Display the weight measure in the display
void display_WEIGHT(void) {

  display.drawRoundRect(0, 0, display.width(), display.height(), display.height() / 10, WHITE);
//  display.drawRoundRect(15, 0, 100, 20, display.height() / 30, WHITE);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(9, 9);

    #ifdef ESP
  display.println("Peso:");
  #else
  display.println("Weight:");
  #endif
  
  display.setCursor(20, 36);
  display.print(weight,2);
  display.print(" g");
     
  display.display();
  display.clearDisplay();

}

// Display the weight measure in the display
void display_TARING(void) {

  display.drawRoundRect(0, 0, display.width(), display.height(), display.height() / 10, WHITE);
//  display.drawRoundRect(15, 0, 100, 20, display.height() / 30, WHITE);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(6, 19);

  #ifdef ESP
  display.println("Tarando..");
  #else
  display.println("Taring...");
  #endif
  
  display.display();
  display.clearDisplay();

}



// Display the weight measure in the display
void display_TARED(void) {

  display.drawRoundRect(0, 0, display.width(), display.height(), display.height() / 10, WHITE);
//  display.drawRoundRect(15, 0, 100, 20, display.height() / 30, WHITE);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(9, 19);

  #ifdef ESP
  display.println("Tarado.");
  #else
  display.println("Tared!");
  #endif
  
  display.display();
  display.clearDisplay();

}


// Display the weight measure in the display
void display_INIT(void) {

  display.drawRoundRect(0, 0, display.width(), display.height(), display.height() / 10, WHITE);
//  display.drawRoundRect(15, 0, 100, 20, display.height() / 30, WHITE);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);

    #ifdef ESP
  display.println("Configurando...");
  #else
  display.println("Initializing...");
  #endif
     
  display.display();
  display.clearDisplay();

}





#ifdef DEBUG

// Print information to serial port
void print_to_serial() {

    //Current time
    Serial.println();
    Serial.println();
    Serial.print("Main loop iteration: "); Serial.println(iloop, DEC);
    Serial.println();
    Serial.print("     Weight ("); Serial.print(nmeasures);Serial.print(" measures): ");  Serial.print(weight, DEC); Serial.println(" g.");
    Serial.println();
    Serial.println("     Timing: "); 
    Serial.print("          Current time: "); Serial.print(millis(), DEC); Serial.println(" ms.");  
    Serial.print("          Last loop duration (without serial): "); Serial.print(loop_duration_beforeserial, DEC); Serial.println(" ms.");
    Serial.print("          Last loop duration: "); Serial.print(loop_duration, DEC); Serial.println(" ms.");
    
}
#endif

@bogde
Copy link
Owner

bogde commented Mar 18, 2017

i dont seem to be able to reproduce you're issue, but i'm not sure we're using the same boards. i removed your oled display calls and replaced them with console output and everything seems to work as expected.

these are the boards i tested with:

img_2883
img_2884

@fishersolutions
Copy link

Hi All,
I have been having the same issue with the HX creating reboots on the ESP8266.
It only happens when I added the OLED library.

This code is is being executed and therefore yield() no longer works.
Once I commented out this code everything started working :)

#if ARDUINO_VERSION <= 106
// "yield" is not implemented as noop in older Arduino Core releases, so let's define it.
// See also: https://stackoverflow.com/questions/34497758/what-is-the-secret-of-the-arduino
void yield(void) {};
#endif

The long HX711::read() is also will lock the processor forever if the HX711 is never ready.

@AGordiGuerrero
Copy link
Author

Many thanks for your attention!

I use basically the same hardware than you. NodeMCU and "micro" NodeMCU. All based on ESP8266 V1.0. I got several NodeMCUs and I get the same errors in them.

scale8266

Still no luck. I did not work too much last days but tonight I still do not get the answer.

I do not understand the solution from Fishersolutions. Where I should comment the yield() function? Thanks!

I will keep trying. I think it is related with the wdt. There are a lot of forums with the same issue but I still not found the solution. :-(

@bogde
Copy link
Owner

bogde commented Mar 21, 2017

if i were you, i would first isolate the issue by commenting out the oled display code, to test @fishersolutions tip. btw, thanks David for chiming in.

or you can try commenting out:

void yield(void) {};

in HX711.cpp and see how that works.

@AGordiGuerrero
Copy link
Author

Good advices. It worked!! :-) But still partially...

I commented in HX711.cpp the lines:
/* // wait for the chip to become ready while (!is_ready()) { // Will do nothing on Arduino but prevent resets of ESP8266 (Watchdog Issue) yield(); } */
`
And the other yield() calll in the read_average function. It now does not reboot automatically. Good!

But the measure I obtain is continuously zero. In fact when I upload the HX711serial test code, I get the serial messages:
Before setting up the scale: read: -1 read average: -1 get value: -1.00 get units: -1.0 After setting up the scale: read: -1 read average: -1 get value: 0.00 get units: 0.0 Readings: one reading: 0.0 | average: 0.0
So the read seems to be -1 at start. Maybe it is due to the comment on the yield() function and the fact that the chip is not ready to measure?

I tested with different pins, different loads and different HX711 boards. I should construct the same with simple a Arduino for testing..... It is quite confusing (for a noob as me) to work with the different execution layers in ESP8266.

Thanks again!

@bogde
Copy link
Owner

bogde commented Mar 21, 2017

you shouldnt comment out the is_ready code. you probably get 0.0 readings because the chip is indeed not ready. according to @fishersolutions tip, you should comment out the definition of yield. you should see that in HX711.cpp, in your arduino libraries folder.

however, since the sketch seems to work without the is_ready code, but you dont get correct readings, that could mean your wiring is wrong, or something else is wrong with your hx711 board. is_ready should definitely return true if the communication is working. you might want to further investigate that with a more simple sketch.

@dhmsjs
Copy link
Contributor

dhmsjs commented Mar 22, 2017

Isn't the normal state of DOUT always high, until the HX711 has a reading available? So then without the is_ready() wait loop in place, any call to read() during that (100msec) not-ready time will return all 1's, which is the bit pattern for -1. That is exactly what you are observing.

If you are getting a watchdog reset when the is_ready() wait loop is not commented out, then that says that the loop is waiting too long for the watchdog timer. The purpose of having the "real" yield() in that wait loop is to kick (reset) the watchdog while waiting. As @bogde says you can't just cut out is_ready(), so one way or another you have to make sure that the watchdog timer gets kicked while you are in that wait loop.

From @fishersolutions' post it sounds to me like without OLED, the watchdog was getting kicked often enough even with the do-nothing yield() call in the wait loop. Adding OLED caused enough delay (when added to the is_ready() wait loop delay) to time out the watchdog. His fix commented out the do-nothing yield() which then allowed is_ready() to call the "real" yield() -- i.e. the one that really does kick the watchdog timer. You need to do the same.

@AGordiGuerrero
Copy link
Author

Exactly! @fishersolutions gave the answer. Just commenting what he said solved the error. If not commented, watchdog is not feed in time and reboot occurs.

My fault was mixed with a wiring error (.......) that I found testing with a clone of the hardware.

Now I got problems with stability of the measures but it is for sure an algorithm issue.

Thank you all again! Cheers from Spain.

@dhmsjs
Copy link
Contributor

dhmsjs commented Mar 23, 2017

Good to know; thanks for the update!

If you are having problems with random strange readings from the HX711, note that @bogde's library will do this if your system uses interrupts and those interrupts ever take longer than about 60 uSec to service. In that case, if one of these interrupts occurs during the time read() is clocking data out of the HX711, it can cause the HX711 device to go into shutdown mode, which corrupts the rest of that reading (all subsequent bits will read out as 1s). One possible fix for this problem is to prevent interrupts from occurring during the entire clocking sequence. See my pull request for one version of this solution.

Poor connections on the HX711 wiring can also cause random strange readings, so make sure your connections are all good and tight.

@zinkkrysty
Copy link

I have the same error on a NodeMCU v1.

Managed to copy the entire code of HX711 into my program and it worked - got reasonable readings.

However, whenever I import the HX711 library and use it my code, it restarts the device

@electrokean
Copy link

@zinkkrysty As per suggestions above, comment out or remove the section in HX711.cpp that says:
void yield(void) {};
and see if that works.
This will cause problems on any ESP based hardware, as the ARDUINO_VERSION isn't set as expected.
See also discussion in issue #73

@zinkkrysty
Copy link

zinkkrysty commented Jul 9, 2017

Tried that. Not working.

Actually I can reproduce the error with this code:

#include "HX711.h"

HX711 scale(D5, D6); // This line is creating the error, if I remove it, everything works

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  Serial.println("HX711 Demo");
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LED_BUILTIN, LOW);
  delay(2000);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(2000);
}

Where I'm not using the library at all besides initializing the instance.

This code, on the other hands works: https://gist.github.com/zinkkrysty/3e0afdfb7c9a3cb219096555a4863d99
I copied the entire library method by method into my program and use it like that.

@zinkkrysty
Copy link

zinkkrysty commented Jul 9, 2017

I suspect the #include <Arduino.h> at the beginning of the code that is messing the setup of NodeMCU/ESP8266 somewhat

@electrokean
Copy link

Are you removing the problematic yield() definition from the correct version of your HX711.cpp file
i.e. make sure you edit the copy in your Arduino libraries folder, and restart Arduino environment.
That seems to have fixed the issue for others: e.g. #69

@zinkkrysty
Copy link

zinkkrysty commented Jul 9, 2017

I am sure I am editing the right file because I tried to remove the #include <Arduino.h> and the compilation broke.

I am trying to introduce the methods in the library one by one and see which one breaks the code.

So far only having this in the headers doesn't break my program (also commented out the corresponding methods in the cpp file):

#ifndef HX711_h
#define HX711_h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class HX711
{
	private:
		byte PD_SCK;	// Power Down and Serial Clock Input Pin
		byte DOUT;		// Serial Data Output Pin
		byte GAIN;		// amplification factor
		long OFFSET = 0;	// used for tare weight
		float SCALE = 1;	// used to return weight in grams, kg, ounces, whatever

	public:
		HX711(byte dout, byte pd_sck, byte gain = 128);

		void begin(byte dout, byte pd_sck, byte gain = 128);
}

@zinkkrysty
Copy link

Ok, I managed to fix this.

The issue was that I reversed the pins when instantiating the scale (maybe this tutorial was using older version of HX711 or they got it wrong)

Trying to fix it by commenting out the

void yield(void) {};

actually causes the error for me when the pins are in correct order.

So the version that works for me:

HX711 scale(D6, D5); // D6 is DT, D5 is SCK

and with the library as is in the master of this repository (that has void yield(void) {}; enabled)

Curiously enough, the difference between my version and the master is that the sides of the load cell are opposite (I have to use the other side to generate readings)

@sravyachatti
Copy link

hi AgordiGuerrero sir,we are facing the same problem with hx711 code which you have faced

(ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v60000318
~ld)

can you please explain in detail
Thank you
waiting for your reply

@amotl
Copy link
Contributor

amotl commented Feb 19, 2019

Hi there, just wanted to let you know we are working on #123, which you might want to give a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants