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

reading SHT20 with Ticker (Timer) interrupt #4353

Closed
SayidHosseini opened this issue Feb 12, 2018 · 18 comments
Closed

reading SHT20 with Ticker (Timer) interrupt #4353

SayidHosseini opened this issue Feb 12, 2018 · 18 comments

Comments

@SayidHosseini
Copy link

Basic Infos

Hardware

Hardware: NodeMCU V 0.9
Core Version: 2.4.0

Description

Problem description:

I've connected SHT20 sensor to the NodeMCU V 0.9. When reading sensor data using DFRobot_SHT20 library in a loop or with a delay mechanism, it works fine. But I'm trying to get the sensor data in a Timer interrupt using the Ticker library on ESP core. it doesn't matter how long this interval is, it just doesn't work. I have also tried using SHT10 sensor with the proper library and the same happens there too. Any idea what the problem might be?

Settings in IDE

Module: NodeMCU 0.9 (ESP-12 Module)
Flash Size: 4MB
CPU Frequency: 80Mhz
Flash Mode: ?
Flash Frequency: ?
Upload Using: SERIAL
Reset Method: nodemcu

Sketch

#include <Ticker.h>
#include <Wire.h>
#include "DFRobot_SHT20.h"

Ticker tick;
DFRobot_SHT20    sht20;

void setup()
{
  Serial.begin(115200);
  Serial.println(); 
  
  sht20.initSHT20();
  delay(100);

  int humidity = sht20.readHumidity();
  int temp = sht20.readTemperature();
  //Here, it reads fine - Also checked it with a loop and delay
  Serial.print("Temp: ");
  Serial.println(temp);
  Serial.print("Humidity: ");
  Serial.println(humidity);

  tick.attach(5, getSHTData); // it doesn't matter how long this interval is
}

void loop() 
{
}

void getSHTData()
{
  int humidity = sht20.readHumidity();
  int temp = sht20.readTemperature();

  Serial.print("Temp: ");
  Serial.println(temp); // prints 998
  Serial.print("Humidity: ");
  Serial.println(humidity); // prints 998
}
@lrmoreno007
Copy link
Contributor

@lrmoreno007
Copy link
Contributor

As the examples provided in the Ticket library do precisely what should not be done, I have modified your sketch, so that you understand it better:

#include <Ticker.h>
#include <Wire.h>
#include "DFRobot_SHT20.h"

Ticker tick;
DFRobot_SHT20    sht20;

bool readTemp = false;
bool readHumidity = false;

void getSHTData(){
  readTemp = true; //Only set the flag
  readHumidity = true; //Only set the flag
}

void setup(){
  Serial.begin(115200);
  Serial.println(); 
  
  sht20.initSHT20();
  delay(100);

  tick.attach(5, getSHTData); // Interval is in seconds. 
  //tick.attach_ms(5000, getSHTData); // Interval is in milliseconds. 
}

void loop(){
  if (readTemp) {
    int temp = sht20.readTemperature();
    Serial.print("Temp: ");
    Serial.println(temp);
    readTemp = false;
  }

  if (readHumidity) {
      int humidity = sht20.readHumidity();
      Serial.print("Humidity: ");
      Serial.println(humidity);
      readHumidity = false;
  }
}

I have not tried the sketch with an SHT20 because I do not have any, but it should work.

@SayidHosseini
Copy link
Author

As I have already told, I can already get the data in a busy waiting manner. What I need, is to read the sensor data in an interruption manner via a timer on the NodeMCU. Is there a solution for that?

@lrmoreno007
Copy link
Contributor

lrmoreno007 commented Feb 12, 2018

It's as Ticker library must work, with flags, and it's as fast as your sketch.

What I understand you want is multitasking and it's not possible in ESP8266, because it has only a CPU, only one core and without OS.

I think you must lower your expectations to a non-blocking asynchronous system, like the use of Ticker or something like in the example "Blink without delay". Many functions inside the ESP8266 Arduino are made with flags and work fine.

I don't know if the @Makuna Task library or FreeRTOS can help you. I never used it. Read this: http://www.nefastor.com/esp8266-freertos-introduction/

In any case, this is not the best place to discuss it. Do not you think?

@SayidHosseini
Copy link
Author

Let me get one thing straight. Is there a hardware Timer on ESP modules? like other Microcontrollers?

@lrmoreno007
Copy link
Contributor

Yes, there are two hardware timer: timer0 and timer1.

@SayidHosseini
Copy link
Author

OK. So how come we can't have a timer interrupt then? and have non-blocking asynchronous tasks done?

@WereCatf
Copy link
Contributor

@SayidHosseini AFAIK I2C doesn't work during an interrupt-handler, because all other interrupts are disabled during its execution.

@lrmoreno007
Copy link
Contributor

We have interrupts, but they are in use.

@WereCatf
Copy link
Contributor

@lrmoreno007 You misunderstood: when the ESP8266 is already executing an interrupt-handler, the other interrupts are disabled. Since I2C is software-one and relies on interrupts, it doesn't work until interrupts are enabled again, ie. the interrupt-handler has exited.

@lrmoreno007
Copy link
Contributor

lrmoreno007 commented Feb 13, 2018

We are telling the same. no?
We have interrupts, but they are in use
when the ESP8266 is already executing an interrupt-handler, the other interrupts are disabled.

@lrmoreno007
Copy link
Contributor

In any case, I don't understand where the problem is in using flags.
c12-image002

@WereCatf
Copy link
Contributor

@lrmoreno007 Me neither. I use flags in my stuff all the damn time. You're not even supposed to be doing heavy lifting in interrupts, because you may then miss other interrupts, not to mention the wdt-reset, if you're taking too long. shrug

Nevertheless, @SayidHosseini can't do what he wants the way he wants, so either he has to use flags or abandon his project.

@lrmoreno007
Copy link
Contributor

Here is a library with RTOS for ESP8266/Arduino and compatible with Wire. I don't know if it work.
https://github.com/aleksmarcelo/LibEspArduino

@SayidHosseini
Copy link
Author

SayidHosseini commented Feb 13, 2018

WereCatf, Your first reply helped me understand what the problem was.
lrmoreno007, The reason I'm interested in this is if you design your system in an interruption manner, you can use sleep modes and get waken up by interrupts, which seems not possible here.

Generally, we wanted to implement ESP based system with batteries. For that, it seemed logical to design the system in an interruption manner and to use sleep modes.

@hreintke
Copy link
Contributor

See #4062 & #4209.

That provides the possibility to run the ticker callback scheduled.

-> No problem to use blocking functions

@WereCatf
Copy link
Contributor

WereCatf commented Feb 14, 2018

@SayidHosseini Indeed, AFAIK the ESP8266 does not support external wakeups, unless you count pulling on the reset-pin as an external wakeup. If you need something more precise than that or a larger amount of wakeups, it'd be best to use another MCU to handle that part and having the ESP8266 in deep-sleep most of the time, and the other MCU then pulling the reset-pin on the ESP whenever you wish to send data via WiFi.

You could also take a look at the ESP32 instead, which does support external wakeups and you could even use the low-power core of it to perform light tasks even when the ESP32 itself is in deep-sleep -- very handy. The downside with the low-power core is that it needs to be programmed in assembly, which takes a bit of learning to how to do.

@devyte
Copy link
Collaborator

devyte commented Feb 16, 2018

@SayidHosseini the Ticker callback executes as a scheduled SDK task, and therefore blocking operations like reading an SHT can't be done in it. This is documented. There are also certain timing constraints at play. If you're thinking on a traditional hardware timer with an ISR, then there are even stricter timing constraints at play. This is the reason behind @lrmoreno007 's suggestions to set a flag in the ISR or Ticker callback, and check it in the loop.
In addition, a Ticker doesn't trigger an interrupt to wake up the ESP. I think maybe the deepsleep mode can give you what you want, which on wakeup behaves like a reset. You could take a look at that.
In any case, this is not the right place to discuss this.
Closing per issue POLICY doc.

@devyte devyte closed this as completed Feb 16, 2018
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

5 participants