WS2812 and DHTxx Sensor (Pulsing and timing issue)

Hi there,

I wish to make a little thermometer with one WS2812 led and a DHT11 sensor.

I have two questions here.

1). I was trying to delay the sensor reading for 2s, but then the fading of WS2812 will not work as expected.

2). I wish to add a color fading definitions to it, like: Red, Yellow, Orange, Green, White and Blue (going in and out like Pulsing).

#include <DHT.h>
#include <Adafruit_NeoPixel.h>


#define DHT_PIN 2
#define DHT_TYPE DHT11   // DHT 11
//#define DHT_TYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHT_TYPE DHT21   // DHT 21 (AM2301)

#define NEO_PIN 6
#define NEO_NUM_LEDS 1
#define NEO_WAIT_MS 10

DHT dht(DHT_PIN, DHT_TYPE);

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NEO_NUM_LEDS, NEO_PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
  Serial.begin(9600);
  dht.begin();
  strip.begin();
  strip.show();
  strip.clear();
}

void fadeIn()
{
  for(int i = 5; i < 255; i++)
  {
    colorWipe(strip.Color(i,0,0));
  }
}

void fadeOut()
{
  for(int i = 255; i > 5; i--)
  {
    colorWipe(strip.Color(i,0,0)); 
  }
}

void colorWipe(uint32_t c)
{
  for(uint16_t i = 0; i < strip.numPixels(); i++)
  {
    strip.setPixelColor(i, c);
    strip.show();
    delay(NEO_WAIT_MS);
  }
}

void loop()
{
  delay(2000);

  float h = dht.readHumidity();
  float t = dht.readTemperature();

  if (isnan(h) || isnan(t))
  {
    Serial.println(F("Failed to read from DHT sensor!"));
  } else {
    Serial.print(F("Temperature: "));
    Serial.print(t);
    Serial.print(F(" *C "));
    Serial.print(F("Humidity: "));
    Serial.print(h);
    Serial.print(F(" %"));
    Serial.println(F("")); 
  }
  
  fadeIn();
  fadeOut();
}

Basicaly I wanted to do somthing like this for temperature:

If ((t > 18) && (t < 27)) {
  fadeIn(GREEN);
  fadeOut(GREEN);
}else if ((t > 26) && (t < 32)){
  fadeIn(YELLOW);
  fadeOut(YELLOW);
}else if ((t > 32) && (t < 37)){
  fadeIn(ORANGE);
  fadeOut(ORANGE);
}else if ((t > 37) && (t < 45)){
  fadeIn(RED);
  fadeOut(RED);
}else if ((t > 0) && (t < 10)){
  fadeIn(BLUE);
  fadeOut(BLUE);
}

Hope someone can help me out a little bit!

Thank you as always! :wink:

 delay(2000);

Nothing happens during delay().

Here are a couple of posts to help get rid of delay().

http://forum.arduino.cc/index.php?topic=223286.0
http://forum.arduino.cc/index.php?topic=503368.0

groundFungus:

 delay(2000);

Nothing happens during delay().

Yes, I was aware of the delay, it's stops the whole loop for 2s in my case.

Ok, I managed to deal with my second question, and added the millis() to my code for the DHT reading, but how to replace/change this two delays in the code bellow?

wait = 10

void fadeNeoPixel(uint32_t color, uint8_t wait)
{
  for(uint8_t b = 0; b < 255; b++)
  {
     for(uint8_t i = 0; i < strip.numPixels(); i++)
     {
        strip.setPixelColor(i, color*b/255);
     }
     strip.show();
     delay(wait);
  }

  for(uint8_t b = 255; b > 0; b--)
  {
     for(uint8_t i = 0; i < strip.numPixels(); i++)
     {
        strip.setPixelColor(i, color*b/255);
     }
     strip.show();
     delay(wait);
  }
}

How would YOU make the pixels fade without using delay? You have to get rid of the for loops, and call the function once for every value that you want the LEDs to take on. That means that the function itself won't handle the fading. The function, probably loop(), will handle the fading. The now-misnamed function will simply set all the pixels to the same color value, and make them all show the set color at the same time.

PaulS:
How would YOU make the pixels fade without using delay? You have to get rid of the for loops, and call the function once for every value that you want the LEDs to take on. That means that the function itself won't handle the fading. The function, probably loop(), will handle the fading. The now-misnamed function will simply set all the pixels to the same color value, and make them all show the set color at the same time.

I meant to use maybe millis() there, instead of the delay() function.

I meant to use maybe millis() there, instead of the delay() function.

I know what you meant. You meant that you wanted to shake some magic millis dust on your code and have it magically work. Welcome to the real world.

PaulS:
You meant that you wanted to shake some magic millis dust on your code and have it magically work.

As always I really like your humor! :smiley: but please if you know somehow help me out here.

Here is my new full code (best performace so far, but not 100% what I wish):

#include <DHT.h>
#include <Adafruit_NeoPixel.h>

unsigned long interval = 2000;
unsigned long previousMillis = 0;

#define DEBUG

#define DHT_PIN 2
#define DHT_TYPE DHT11   // DHT 11

DHT dht(DHT_PIN, DHT_TYPE);

#define NEO_PIN 6
#define NEO_NUM_LEDS 1
#define NEO_WAIT_uMS 5000

#define NEO_BLACK   0x000000  // 0, 0, 0
#define NEO_WHITE   0xFFFFFF  // 255, 255, 255
#define NEO_YELLOW  0xFFFF00  // 255, 255, 0
#define NEO_ORANGE  0xFF6600  // 255, 102, 0
#define NEO_RED     0xFF0000  // 255, 0, 0
#define NEO_GREEN   0x00FF00  // 0, 255, 0
#define NEO_BLUE    0x0000FF  // 0, 0, 255

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NEO_NUM_LEDS, NEO_PIN, NEO_BRG + NEO_KHZ800);

void setup()
{
  #ifdef DEBUG
    Serial.begin(9600);
  #endif  
  dht.begin();
  strip.begin();
  strip.show();
  strip.clear();
}

void loop()
{

  offNeoPixel();
  
  unsigned long currentMillis = millis();
  if ((unsigned long)(currentMillis - previousMillis) >= interval)
  {
    readSensor();
    previousMillis = millis();
  }
}

void readSensor()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  if (isnan(h) || isnan(t))
  {
    #ifdef DEBUG
      Serial.println(F("Failed to read from DHT sensor!"));
    #endif
    fadeNeoPixel(NEO_WHITE, NEO_WAIT_uMS);
  }
  else
  {
    #ifdef DEBUG
      Serial.print(F("Temperature: "));
      Serial.print(t);
      Serial.print(F(" *C "));
      Serial.print(F("Humidity: "));
      Serial.print(h);
      Serial.print(F(" %"));
      Serial.println(F(""));
    #endif
    fadeOnSensorRead(t);
  }
}

void fadeOnSensorRead(float t)
{
  if ((t >= 0) && (t <= 10))
  {
    fadeNeoPixel(NEO_BLUE, NEO_WAIT_uMS);
  }
  
  else if ((t >= 18) && (t <= 27))
  {
    fadeNeoPixel(NEO_GREEN, NEO_WAIT_uMS);
  }
  
  else if ((t >= 26) && (t <= 32))
  {
    fadeNeoPixel(NEO_YELLOW, NEO_WAIT_uMS);
  }
  
  else if ((t >= 32) && (t <= 37))
  {
    fadeNeoPixel(NEO_ORANGE, NEO_WAIT_uMS);
  }
  
  else if ((t >= 37) && (t <= 45))
  {
    fadeNeoPixel(NEO_RED, NEO_WAIT_uMS);
  }
}

void fadeNeoPixel(uint32_t color, int wait)
{ 
  for(int b = 0; b < 255; b++)
  {
    for(int i = 0; i < strip.numPixels(); i++)
     {
        strip.setPixelColor(i, color*b/255);
     }
     strip.show();
     delayMicroseconds(wait);
  }

  for(int b = 255; b > 0; b--)
  {
    for(int i = 0; i < strip.numPixels(); i++)
     {
        strip.setPixelColor(i, color*b/255);
     }
     strip.show();
     delayMicroseconds(wait);
  }
}

void offNeoPixel()
{
  for( int i = 0; i < strip.numPixels(); i++)
  {
    strip.setPixelColor(i, NEO_BLACK);
    strip.show();
  } 
}

if you know somehow help me out here.

I already told you what you need to do. There are two functions that every Arduino sketch must have. One is setup() that is executed once.

The other is loop(). Notice that they did not call this function thatDogIsSureUgly(). There is a reason for the name. It loops. Let it handle all the looping that program needs to do.

On any given pass through loop(), it may, or may not, be time to change the brightness of the LEDs. If it is, do it, and record when the change happened. If not, move on to the next task, if there is one.

The next change may be to increase the brightness value, or it may be to decrease the brightness value. The loop() function needs to keep track of that, not a for loop index.

There is NO magic millis dust that you can sprinkle on blocking code to unblock it. You must scrap that whole sketch and start over. You already know how to use millis() to determine if it is time to do something. So, using it to decide whether the strip brightness needs to change, or not, should be trivial.

The action that needs to happen when it is time for a change is already defined in the fadeNeoPixel() function, but it is wrapped in two for loops with delay calls. Get rid of one of the for loops and the delay call. Rename the function, because it is no longer responsible for fading the LEDs. Call that function with three arguments, not two. The new argument will be the value that is b in the for loops.

Of course, you'll have issues with fadeOnSensorRead() because that expects the fadeNewPixel() function to be blocking.

But, I'm sure you'll figure that out.

By the way, having fadeOnSensorRead() take a float makes no sense, since all the tests involving that float compare it to integer values.