Incorrect data send to xively (occasionaly), when using external antenna


#1

Hi all,

I ignored my Cores for a while after getting stuck with them, but when I read about the progress that was made on the problems with getting some Cores (including mine) to connect to wifi, I tried once more and… luckily now got them running without any problem. I extracted some code from different posts and now got my own small environmental logger that report temperature and humidity to Xively, using DHT22’s.

Two core are located inhouse and one is in my greenhouse. The onboard antenna is not strong enough to make a connection between the greenhouse and my router, therefore I now use a core with an external antenna. This works perfectly, except that the greenhouse core (and not the other cores) report extreme values, which you can see in the figure below. It is not very frequent, and not regularly, which makes it more difficult to troubleshoot.

Does anyone has an idea what is causing this? Since the cores with the onboard antenna do not show this behavior, I guess it is caused by the communication over wifi using the external antenna. But I though that wifi has safeguard installed to correct miscommunication (although I have to admit I know very little about this subject).

Once again, great thanks for the developers or the spark core and the strong community!


Uploading Spark data to Xively
#2

The code I’ve running on all three cores. Might make it into a nice libarary one day I guess.

//https://community.spark.io/t/dht22-dht11-and-similar-blocking-version/998
/*
- Pin 1: VCC
- Pin 2: Spark Core D2
- Pin 3: Nothing
- Pin 4: Ground
There is also a 10k resistor connecting Pin 1 (VCC) and Pin 2 (Spark Core D2).*/

#define FEED_ID "xxxxxxxx"
#define XIVELY_API_KEY "yyyyyyyyyyyyy"

#define MAXTIMINGS 85
#define cli noInterrupts
#define sei interrupts
#define DHT11 11
#define DHT22 22
#define DHT21 21
#define AM2301 21
#define NAN 999999

#define DHTPIN D2 // Digital pin D2
#define DHTTYPE DHT22

TCPClient client;

class DHT {
    private:
    uint8_t data[6];
    uint8_t _pin, _type, _count;
    bool read(void);
    unsigned long _lastreadtime;
    bool firstreading;
    public:
    DHT(uint8_t pin, uint8_t type, uint8_t count=6);
    void begin(void);
    float readTemperature(bool S=false);
    float convertCtoF(float);
    float readHumidity(void);
};
 
DHT dht(DHTPIN, DHTTYPE);
 
float h;
float t;

int ledD = D7; /////
unsigned long LastUpTime = 0;/////
uint32_t lastReset = 0; /////

void setup() {
    dht.begin();
    Serial.begin(9600);
    Serial.println("Start");
    pinMode(ledD, OUTPUT);/////
    ledStatus(2,100);/////
    lastReset = millis();/////
}
 
void loop() {
    if (millis()-LastUpTime>10000)   {/////
        h = dht.readHumidity();
        t = dht.readTemperature();
        xivelySend("Humidity3", h);
        xivelySend("Temperature3", t);
        LastUpTime = millis();/////
}}

DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
    _pin = pin;
    _type = type;
    _count = count;
    firstreading = true;
}
 
void DHT::begin(void) {
    // set up the pins!
    pinMode(_pin, INPUT);
    digitalWrite(_pin, HIGH);
    _lastreadtime = 0;
}
 
 
//boolean S == Scale. True == Farenheit; False == Celcius
float DHT::readTemperature(bool S) {
    float _f;
    if (read()) {
        switch (_type) {
        case DHT11:
        _f = data[2];
        if(S)
        _f = convertCtoF(_f);
        return _f;
        case DHT22:
        case DHT21:
        _f = data[2] & 0x7F;
        _f *= 256;
        _f += data[3];
        _f /= 10;
        if (data[2] & 0x80)
        _f *= -1;
        if(S)
        _f = convertCtoF(_f);
        return _f;
        }
    }
    return NAN;
}

float DHT::convertCtoF(float c) {return c * 9 / 5 + 32;}
 
float DHT::readHumidity(void) {
    float _f;
    if (read()) {
        switch (_type) {
        case DHT11:
        _f = data[0];
        return _f;
        case DHT22:
        case DHT21:
        _f = data[0];
        _f *= 256;
        _f += data[1];
        _f /= 10;
        return _f;
        }
    }
    return NAN;
    }

bool DHT::read(void) {
    uint8_t laststate = HIGH;
    uint8_t counter = 0;
    uint8_t j = 0, i;
    unsigned long currenttime;
    // pull the pin high and wait 250 milliseconds
    digitalWrite(_pin, HIGH);
    delay(250);
    currenttime = millis();
    if (currenttime < _lastreadtime) {
        // ie there was a rollover
        _lastreadtime = 0;
    }
    if (!firstreading && ((currenttime - _lastreadtime) < 2000)) {
        //delay(2000 - (currenttime - _lastreadtime));
        return true; // return last correct measurement
    }
    firstreading = false;
    //Serial.print("Currtime: "); Serial.println(currenttime);
    //Serial.print(" Lasttime: "); Serial.println(_lastreadtime);
    _lastreadtime = millis();
    data[0] = data[1] = data[2] = data[3] = data[4] = 0;
    // now pull it low for ~20 milliseconds
    pinMode(_pin, OUTPUT);
    digitalWrite(_pin, LOW);
    delay(20);
    cli();
    digitalWrite(_pin, HIGH);
    delayMicroseconds(40);
    pinMode(_pin, INPUT);
    // read in timings
    for ( i=0; i< MAXTIMINGS; i++) {
        counter = 0;
        while (digitalRead(_pin) == laststate) {
            counter++;
            delayMicroseconds(1);
            if (counter == 255) break;
        }
        laststate = digitalRead(_pin);
        if (counter == 255) break;
        // ignore first 3 transitions
        if ((i >= 4) && (i%2 == 0)) {
            // shove each bit into the storage bytes
            data[j/8] <<= 1;
            if (counter > _count) data[j/8] |= 1;
            j++;
        }
    }
    sei();
 
    // check we read 40 bits and that the checksum matches
    if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF))) return true;
    return false;
}

/////////////////////////////
void xivelySend(char* type, float data) {
   Serial.print("Sending to server... ");
   Serial.print(type); Serial.print(": "); Serial.println(data);
    if (client.connect("api.xively.com", 8081))     {
        // Connection succesful, update datastreams
        client.print("{");
        client.print("  \"method\" : \"put\",");
        client.print(" \"resource\" : \"/feeds/");
        client.print(FEED_ID);
        client.print("\",");
        client.print("  \"params\" : {},");
        client.print("  \"headers\" : {\"X-ApiKey\":\"");
        client.print(XIVELY_API_KEY);
        client.print("\"},");
        client.print("  \"body\" :");
        client.print("    {");
        client.print("      \"version\" : \"1.0.0\",");
        client.print("      \"datastreams\" : [");
        client.print("        {");
        client.print("          \"id\" : \"");
        client.print(type);
        client.print("\",");
//        client.print("          \"id\" : \"temp8\",");
        client.print("          \"current_value\" : \"");
        client.print(data);
        client.print("\"");
        client.print("        }");
        client.print("      ]");
        client.print("    },");
        client.print("  \"token\" : \"0x123abc\"");
        client.print("}");
        client.println();

        ledStatus(2, 500);            } 
    else     {
        // Connection failed
        //Serial.println("connection failed");
        ledStatus(4, 500);    }

    if (client.available())    {
        // Read response
        //char c = client.read();
        //Serial.print(c);
    }

    if (!client.connected())    {
        //Serial.println();
        //Serial.println("disconnecting.");
        client.stop();    }

    client.flush();
    client.stop();
}

void ledStatus(int x, int t){
    for (int j = 0; j <= x-1; j++)    {
        digitalWrite(ledD, HIGH);
        delay(t);
        digitalWrite(ledD, LOW);
        delay(t); 
   }
}

#3

i’ve had the same issue with arduino’s and DHT11’s. i’ve even had odd readings from DS18B20’s, BMP180’s and BMP085’s.

I’ve ended up having to do lots of exception handling in software - like check if the temperature is higher than 50c (i’ve seen 1000c!) and if it is, break out of the loop and reinitialise the sensor. adding delays etc; so the sensors can warm up. the BMP altitude measurements are just plain B.S, even on the sparkcore.

i’ve got a feeling they don’t really like 3.3v despite being rated for it. decoupling caps, regulators and all sorts don’t seem to help. I don’t recall if i’ve had problems from 5v supplies (USB, DC adaptors etc.)

One thing to note is that I don’t seem to have problems with sensors inside the house, just outside or in my shed, so maybe they’re very sensitive to moisture, see this graph - the inside temps are consistently around 20-25c, but there’s no way England has reached 40c outside in May ever!

The DS18B20’s are the most accurate with the BMP085 and DHT11 having very odd readings sometimes. I’ve only just got the BMP180 so can’t really say about that.

Oh these are using nRF24L01+ transmitters with a mixture of on-chip and various external antennas, the Raspberry Pi receives the data and publishes it over wifi. I had intended to replace all of that with a bunch of Sparks, but with no SSL I’d still need the Pi.

Perhaps all consumer-grade temperature sensors are just rubbish…?


#4

Thanks for your reply. Well, these sensors were very cheap and they do function very well inside, so cant complain too much :smile:. I had the same sensors running in my greenhouse last year using my arduino, so it then must be the combination of the sensor and the 3.3v.

Based on your comment, I now let the outside core also report an arbitrary value of 50 to another channel (test3) to see if these spikes are related to the sensor or the communication.

I made the feed publicly available https://xively.com/feeds/174145413


#5

yup, my arduino’s were running at 3.3v as is the rpi and beaglebone i’ve tried. i really should get around to long-term testing a 5v arduino i guess.


#6

I have found that at 3.3V all my DHT22 sensors were “on the verge” of working or not working. Sometimes, they simply stall and other times they are off on their readings with occasional sporadic readings… As @sej7278 pointed out, regardless of their ratings, these sensor are not always happy at 3.3V. :smile:


#7

I too have seen the same readings and just have to do exception handling in code. If you are using a stable USB power supply, you can try powering the DHT22 from the VIN/GND pins (top left if looking at the top of the Core with the USB connector facing away from you) and bring the data line back to a 5V-tolerant pin (see here for those pins).

I honestly haven’t tried that yet, but it couldn’t hurt to try. I would like someone else (maybe @peekay123 or @sej7278?) to verify my theory before plugging in any 5V that feeds back into the core.


#8

@wgbartley, I will try and test that later today :smile:


#9

Thanks for your suggestion @wgbartley!

The core is feeded with 5V through the USB connection, so I have connected pin 1 of the DHT22 to Vin of the Core and connected pin 2 of DHT22 to D3 instead of D2, since it is 5V tolerant. For now, it appears to have solved the spike problem.

Perhaps I’ll change the DHT22 code from blocking to non-blocking now, since the non-blocking code wasn’t function at all due to the 3.3V input.


DHT22, DHT11 and similar (Blocking version)
#10

Glad to hear it worked!!

I was able to help on an electrical/hardware level. That’s a rarity for me!