Go Down

Topic: Uploading data to Thingspeak - IoT, water sensors (Read 875 times) previous topic - next topic

Birdrew

Hi All,

I'm currently in the middle of a project to create a water monitoring device that can upload data to the internet on a regular basis. I'm trying to use thingspeak as an example of a platform for uploading the data to.

My issue - As it stands, my code will write the correct data to the serial, however it will not upload the same data to thingspeak, using a set combination of setfields and writefields (so all fields can be updated at the same time.

I'm not sure why this is not working. I've tried running the writefields code at various different locations in the code, all to no result.

I know that there isn't an issue with the connection to thingspeak, as I am able to upload data from just the pressure and temperature sensor (from the MS5803-14)

My code is too long to post in full here. However, this is the majority of it, the rest is to do with calculating the pressure and temperature, whilst also getting calibration factors from EEPROM

Many thanks for any suggestions


Code: [Select]
#include <OneWire.h>
#include <Wire.h>
#include <MS5803_14.h>
#include <EEPROM.h>
#include "ThingSpeak.h"




#define USE_ETHERNET_SHIELD
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
EthernetClient client;


#define StartConvert 0
#define ReadTemperature 1
#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}
#define compensationFactorAddress 8    //the address of the factor stored in the EEPROM
#define VREF 5000  //for arduino uno, the ADC reference is the power(AVCC), that is 5000mV
float compensationFactor;

const byte numReadings = 20;     //the number of sample times
byte ECsensorPin = A1;  //EC Meter analog output,pin on analog 1
byte DS18B20_Pin = 2; //DS18B20 signal, pin on digital 2
unsigned int AnalogSampleInterval = 25, printInterval = 1000, tempSampleInterval = 1000; //analog sample interval;serial print interval;temperature sample interval
unsigned int readings[numReadings];      // the readings from the analog input
byte index = 0;                  // the index of the current reading
unsigned long AnalogValueTotal = 0;                  // the running total
unsigned int AnalogAverage = 0, averageVoltage = 0;             // the average
unsigned long AnalogSampleTime, printTime, tempSampleTime;
float temperature, ECcurrent, ECcurrentRaw;

//Temperature chip i/o
OneWire ds(DS18B20_Pin);  // on digital pin 2

//Pressure sensor
MS_5803 sensor = MS_5803(4096);
float pressure;
float prestemperature;

unsigned long myChannelNumber = 413693;
const char * myWriteAPIKey = "6RWGP1O11WFOGKDC";

void setup() {

  Ethernet.begin(mac);
  ThingSpeak.begin(client);
  // initialize serial communication with computer:
  Serial.begin(9600);



  // initialize all the readings to 0:

  for (byte thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;
  TempProcess(StartConvert);   //let the DS18B20 start the convert
  readCharacteristicValues();
  AnalogSampleTime = millis();
  printTime = millis();
  tempSampleTime = millis();
  if (sensor.initializeMS_5803()) {
    Serial.println( "MS5803 CRC check OK." );
  }
  else {
    Serial.println( "MS5803 CRC check FAILED!" );
  }
  Serial.println("CLEARDATA");
  Serial.println("Analog value,Voltage(mV),Temperature,EC, Pressure(mBar), Pressuretemp");


  delay(3000);
}

void loop()
{



  /*
    Every once in a while,sample the analog value and calculate the average.
  */
  sensor.readSensor();
  float pressure = sensor.pressure();
  float prestemperature = sensor.temperature();



  if (millis() - AnalogSampleTime >= AnalogSampleInterval)
  {
    AnalogSampleTime = millis();
    // subtract the last reading:
    AnalogValueTotal = AnalogValueTotal - readings[index];
    // read from the sensor:
    readings[index] = analogRead(ECsensorPin);
    // add the reading to the total:
    AnalogValueTotal = AnalogValueTotal + readings[index];
    // advance to the next position in the array:
    index = index + 1;
    // if we're at the end of the array...
    if (index >= numReadings)
      // ...wrap around to the beginning:
      index = 0;
    // calculate the average:
    AnalogAverage = AnalogValueTotal / numReadings;
  }

  /*
    Every once in a while,MCU read the temperature from the DS18B20 and then let the DS18B20 start the convert.
    Attention:The interval between start the convert and read the temperature should be greater than 750 millisecond,or the temperature is not accurate!
  */
  if (millis() - tempSampleTime >= tempSampleInterval)
  {
    tempSampleTime = millis();
    temperature = TempProcess(ReadTemperature);  // read the current temperature from the  DS18B20
    TempProcess(StartConvert);                   //after the reading,start the convert for next reading
  }
  /*
    Every once in a while,print the information on the serial monitor.
  */
  if (millis() - printTime >= printInterval)
  {
    printTime = millis();
    averageVoltage = AnalogAverage * (float)5000 / 1024;

    ThingSpeak.setField( 1, String(AnalogAverage));
    ThingSpeak.setField( 2, String(averageVoltage));
    ThingSpeak.setField( 3, String(temperature));
    Serial.print(AnalogAverage);   //analog average,from 0 to 1023
    Serial.print(", ");
    Serial.print(averageVoltage);  //millivolt average,from 0mv to 4995mV
    Serial.print(", ");
    Serial.print(temperature);    //current temperature
    Serial.print(", ");




    float TempCoefficient = 1.0 + 0.0185 * (temperature - 25.0); //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.0185*(fTP-25.0));
    float CoefficientVolatge = (float)averageVoltage / TempCoefficient;



    if (CoefficientVolatge < 50)
    {

      ThingSpeak.setField( 5, String(pressure));
      ThingSpeak.setField( 6, String(prestemperature));
      Serial.print("No solution!");   //25^C 1413us/cm<-->about 216mv  if the voltage(compensate)<150,that is <1ms/cm,out of the range
      Serial.print (",  ");
      Serial.print(pressure);
      Serial.print(", ");
      Serial.println(prestemperature);




      ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);



    }

    else if (CoefficientVolatge > 3300)
    {


      ThingSpeak.setField( 5, String(pressure));
      ThingSpeak.setField( 6, String(prestemperature));
      Serial.println("Out of the range!");  //>20ms/cm,out of the range
      Serial.print (",  ");
      //Serial.print(milli_time);
      Serial.print(pressure);
      Serial.print(", ");
      Serial.println(prestemperature);



      ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);


    }
    else
    {
      if (CoefficientVolatge <= 448)ECcurrent = 6.84 * CoefficientVolatge - 64.32; //1ms/cm<EC<=3ms/cm
      else if (CoefficientVolatge <= 1457)ECcurrent = 6.98 * CoefficientVolatge - 127; //3ms/cm<EC<=10ms/cm
      else ECcurrent = 5.3 * CoefficientVolatge + 2278;                     //10ms/cm<EC<20ms/cm
      ECcurrentRaw = ECcurrent / 1000;
      ECcurrent = ECcurrent / compensationFactor / 1000;

      ThingSpeak.setField( 4, String(ECcurrent));
      ThingSpeak.setField( 5, String(pressure));
      ThingSpeak.setField( 6, String(prestemperature));

      Serial.print(ECcurrent, 2); //two decimal
      Serial.print(", ");
      Serial.print(pressure);
      Serial.print(", ");
      Serial.println(prestemperature);



      ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);




    }


  }

  delay (16000);
}


PaulS

Quote
Many thanks for any suggestions
I'd suggest that you show the serial output and the data as you see it in thingsqueak. It's hard to explain why the data is not the same when we can't see the data.

I think that you need to completely ditch the String class. There ARE other ways to make a string of a float or int, which the ThingSpeak class ought to accept.

If it only accepts Strings, find another class.
The art of getting good answers lies in asking good questions.

Birdrew

thanks, I ran out of space in the original post.

here is the output to the serial:

Code: [Select]
Oversampling setting: 4096
C0 = 0
C1 = 47098
C2 = 41365
C3 = 30128
C4 = 28248
C5 = 32112
C6 = 29075
C7 = 15
p_crc: 15
n_crc: 15
MS5803 CRC check OK.
CLEARDATA
Analog value,Voltage(mV),Temperature,EC, Pressure(mBar), Pressuretemp
3, 14, 22.37, No solution!,  979.80, 25.75
6, 29, 22.37, No solution!,  979.80, 25.35
10, 48, 22.44, 0.28, 980.00, 25.00
13, 63, 22.44, 0.39, 980.10, 24.76
16, 78, 22.50, 0.50, 980.20, 24.52
20, 97, 22.50, 0.63, 980.00, 24.33
23, 112, 22.56, 0.74, 980.00, 24.19
26, 126, 22.56, 0.84, 980.00, 24.09
30, 146, 22.56, 0.98, 979.90, 23.99
33, 161, 22.62, 1.09, 979.80, 23.91
37, 180, 22.62, 1.22, 979.70, 23.84
40, 195, 22.69, 1.33, 980.00, 23.80
44, 214, 22.69, 1.46, 979.90, 23.76
47, 229, 22.69, 1.57, 980.00, 23.73
50, 244, 22.75, 1.68, 980.10, 23.71
54, 263, 22.75, 1.81, 980.00, 23.69
57, 278, 22.75, 1.92, 979.90, 23.68
60, 292, 22.81, 2.02, 979.90, 23.70
64, 312, 22.81, 2.16, 980.20, 23.72
67, 327, 22.81, 2.27, 979.90, 23.72
67, 327, 22.87, 2.26, 980.00, 23.72




nothing currently posts to thingspeak, the number of entries does not increase. so it is not sending an empty entry, as has happened in the past.


The reason that i've used the string class is due to when getting just the temperature and pressure sensor to upload data, thingspeak was increasing the number of entires but no adding data, sending it as a string solved that. Based on that, I thought that if I can send data as a string it should still add it.

My major issue appears to be that for whatever reason data is not being sent through to thingspeak, rather than the string form. that said, for all but the conductivity reading an int would likely be better, though I'm not sure exactly which data forms thingspeak will accept.

Thanks for your help


rw950431

Many people have experienced weird bugs with trying to write too many fields to thingspeak with the thingspeak library.    Try reducing the number of fields you write and see if that makes any difference. There is some suspicion that there is a hidden limit on total length being enforced somewhere in the library code that breaks updates if too much data is included.
 

Birdrew

I tried commenting out all but one of setfields with no success unfortunately.

I think I may have to go back to the drawing board to some extent, and maybe look at using a HTML post rather than the thingspeak library.

Thanks

JosRi

Maybe a bit late on this topic, but you might have a look at my post:
https://forum.arduino.cc/index.php?topic=560605.0

Cheers,
Jos Richters

Go Up