Go Down

Topic: Analog reading of Temperature Sensor (Read 440 times) previous topic - next topic

avalanchd

I have an arduino uno that runs the code below minus the WiFi parts with the correct temperature readings (around 75°).  However when I take the code and copy it to a sketch for the MKR 1010 board the readings from the Temp sensor read around 156°F.  I use the 5V and GND pins to power the temp sensor from the MKR 1010 and plug the other wire from the temp sensor to A5 (I've tried also tried A0 and A1 all roughly the same outcome).  I have even tried powering the temp sensor with the arduino uno but running the sensing wire to the MKR 1010.  I'm new at this so I'm not sure if it is the hardware, does the MKR1010 have a different range for the analog pins?  Do I need to multiple the Thermistor value by something other than 0.004882814?  Any guidance would be helpful.

Could I connect the MKR 1010 board to the Uno board so I can read the value from the Uno board and then upload the value with the MKR 1010?  Completely lost on how to do that, so I was trying the above instead.

Code: [Select]

#include <SPI.h>
#include <WiFiNINA.h>
//#include <WiFi.h>
#include <Time.h>
#include <TimeLib.h>
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;     // the Wifi radio's status
char server[] = "localhost"; 
int port = 44321;
WiFiClient client;

const int ThermistorPin = A5;  //USE Pin A0 on arduino board for data input change if Pin number changes
// Conversion constant converts analog reading, which varies from 0 to 1023 back to a voltage value from 0-5 volts
const double convertVolt = 0.004882814;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

 String fv = WiFi.firmwareVersion();
  if (fv < "1.0.0") {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA2 SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }

  // you're connected now, so print out the data:
  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();

}

void loop() {
 // read Temp sensor voltage and send to cloud database repeat every 1 second or 15 seconds?
  const int readWaitTime = 15000; //5 seconds - value in milliseconds

  double sensorValue = 0;  // Clear previous sensor reading
  double calculatedTemp = 0;

  sensorValue = analogRead(ThermistorPin) * convertVolt;  // Get reading from thermistor and convert back to a voltage
  Serial.print("Direct Read: ");
  Serial.println(analogRead(ThermistorPin));
  Serial.print("Converted value to voltage: ");
  Serial.println(sensorValue);
  //Get Temperature from voltage
  calculatedTemp = convertVoltageToTemp(sensorValue);
  Serial.print("Calculated Temp - ");
  Serial.println(calculatedTemp);
  //Send sensor data to the web API
  if (calculatedTemp > -40 && calculatedTemp < 257) { //lower and upper bound of thermistor
    writeDb(calculatedTemp);
  }

  delay(readWaitTime);
}

double convertVoltageToTemp (double Voltage) { //0V to 5V range based on hardware
  // Input voltage - output temperature for saving back to DB
  // Convert from celsius to fahrenheit? F= 9/5*C+32
  const double vOffset = 0.5;
  const int degreeMultiplier = 100;
  double degreesC = 0;
  double degreesF = 0;

  degreesC = (Voltage - vOffset) * degreeMultiplier;
  degreesF = convertTempToFahrenheit(degreesC);

  return degreesF;
  // return degreesC;  Comment out "degreesF = convertTemp..." and "return degreesF" to get temp in celsius
}

double convertTempToFahrenheit (double Celsius) {
  const double DConstant = 1.8; //Math constant for conversion formula (9/5) * Celsius + 32
  const int FConstant = 32;     //Math constant for conversion formula

  double Temp = 0;

  Temp = DConstant * Celsius + FConstant;

  return Temp;
}

void writeDb (double Temp) {
  //write value to database - need timestamp and degree value
  const int collectionPointId = 1; //Just picked the first collectionPointId since it is just for prototyping
  String PostData = "";  //Clear PostData
  time_t timestamp = now(); //Get current time

 
  // Used Postman then clicked on "Code" to get the data portion of the request.  Changed dropdown to C (LibCurl) example from Postman - curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\n\"collectionPointID\": 1,\n\"timestamp\": \"2018-10-09T1:09:01\",\n\"temperature\": 70.1\n}");
  PostData = "{\n\"collectionPointID\": " ;
  PostData += collectionPointId;
  PostData += ",\n\"timestamp\": \"";
  PostData += timestamp;
  PostData += "\",\n\"temperature\": ";
  PostData += Temp;
  PostData += "\n}";

 if (status != WL_CONNECTED) {
    Serial.println("Lost WiFi connection");
    while (true); //Stop program inifinite loop
  }
  else {
    Serial.println("Connected to WiFi... Starting connection to the server...");
    if (client.connect(server, port)) {
      Serial.println("connected to the server");
      // Make the request client.println prints the data to the server
      client.println("POST /apiSonsorsAPI HTTP/1.1");
      client.print("Host: ");
      client.println(server);
      client.println("User-Agent: Arduino/1.0");
      client.println("Connection: close");
      client.print("content-type: ");
      client.println("application/json");
      client.print("Content-Length: ");
      client.println(PostData.length());
      client.println();  //closes header
      client.println(PostData);
      client.stop();
    }
    else{
      Serial.println("not connected to server");
    }
  }

  //Testing
  Serial.print("timestamp: ");
  Serial.println(timestamp);
  Serial.print(" - temperature: ");
  Serial.println(PostData);
}

Juraj

the MKR is a 3.3 V board. the analog pins read from 0 to 3.3 V, so yes, the range if different
You can't write an Arduino sketch if you didn't learn programming. Not the language, but the concepts of programming - algorithms and data types.

avalanchd

But I have it on the 5V pin and checked it with a volt meter and it reads 5.35V and the arduino uno is running at 5.29V.  Would a .06V difference make it that far off?

Juraj

#3
Oct 13, 2018, 07:31 am Last Edit: Oct 13, 2018, 07:34 am by Juraj
But I have it on the 5V pin and checked it with a volt meter and it reads 5.35V and the arduino uno is running at 5.29V.  Would a .06V difference make it that far off?
the sensor's output is from 0 to 5 V. the analog pin on MKR can read until 3.3 V. so if output of sensor is 3.3 V, you will read maximum.

in case of Uno 0 to 5 V is 0 to 1023. on MKR 0 to 3.3 is 0 to 1023
You can't write an Arduino sketch if you didn't learn programming. Not the language, but the concepts of programming - algorithms and data types.

ballscrewbob

#4
Oct 13, 2018, 04:25 pm Last Edit: Oct 13, 2018, 04:25 pm by ballscrewbob
Totally with Juraj on this.

The normal method would be
Quote
float voltage= sensorValue * (5.0 / 1023.0);
for a 5 volt board but a 3.3 would use
Quote
float voltage= sensorValue * (3.3 / 1023.0);
You could change the 3.3 to suit the ACTUAL voltage if you need better accuracy or you could use the AREF (but double check its voltage with a meter)

Another option would be to use the MAP function.

It may not be the answer you were looking for but its the one I am giving based on either experience, educated guess, google or the fact that you gave nothing to go with in the first place so I used my wonky crystal ball.

Juraj

but at higher temperatures the sensor will output more then 3.3 V and the ADC can't handle it
You can't write an Arduino sketch if you didn't learn programming. Not the language, but the concepts of programming - algorithms and data types.

ballscrewbob

My bad Juraj.

What I should have said is that if the 3.3 voltage was off by a small factor eg. 3.2 volts you could offset that for the 3.3.
Which would put the readings more in line with expected results.


Hope thats a little clearer

It may not be the answer you were looking for but its the one I am giving based on either experience, educated guess, google or the fact that you gave nothing to go with in the first place so I used my wonky crystal ball.

avalanchd

#7
Oct 15, 2018, 05:25 pm Last Edit: Oct 15, 2018, 05:58 pm by avalanchd
Thanks for all the help!  I changed it to use 3.2/1023 and I'm only off by 1° F now.  I figured since I was still using the 5V pin, the calculations would remain the same.  I commented out the WiFi code in order to figure out what was wrong with the temperature readings.  When I uncomment the WiFi code, so it connects to the network I started getting reading that would jump around a lot.  For example it would go from 25°F to 94°F in about 1.5 seconds.  Could I be drawing to much power?  Do I need a capacitor on the temp sensor?  I connected the power wires for the sensor to the UNO and the readings are more stable.

How difficult would it be to use the MRK 1010 just for the wifi connection and have the sensor on the UNO board?  I searched last week online for some type of demo or wiring schematic on connecting the two and came up empty.

I included the WiFiNINA and SPI libraries with the MRK board connected to the UNO via pins 0->RX to pin 14<-TX on the MRK board and 1<-TX to pin 13->RX.  I would get a compile error about PINCOUNT.


ballscrewbob

#8
Oct 15, 2018, 06:09 pm Last Edit: Oct 15, 2018, 06:10 pm by ballscrewbob
There should be no real need to use two boards.

If you really wanted to there are plenty of serial libs out there to do what you want.
I see in the sketch it says THERMISTOR but we have no idea which one or its range ?

The process you seem to be doing is suited for a web server application (sounds complex but in your case quite simple)

BTW you can tweak the 3.2 a little to get better accuracy but if you want it that accurate you really do need to take into account the reference voltages etc (AREF) Or if you just want to do it on the fly so to speak change 3.2 to 3.2x with X being a small offset or 3.1X etc. but you would also need a reference temperature to go with that.

It may not be the answer you were looking for but its the one I am giving based on either experience, educated guess, google or the fact that you gave nothing to go with in the first place so I used my wonky crystal ball.

avalanchd

Exactly, I'm trying to send the temperature to a online time series database.  I have the TMP36, within a degree or so is accurate enough for me for now.  It just seems strange that the MRK board would fluctuate so much, I changed the amount of readings to once every 15 seconds and now the readings are stable and within a degree of each other.  It appears that lengthening the delay solved the fluctuation problem that I was having before.

I appreciate the help and the guidance!

ballscrewbob

Sometimes its better to use some form of "AVERAGE" function.

Seen fluctuations here with some projects and ended up inserting small sampling routines.

There is lots about but a couple JIC you need to get to grips with them.

First.
Second.

Another trick is to take two samples consecutively but ignore the first.
One of the other regulars told me about that trick and YES it did work quite well ! (not for all numbers though)
It may not be the answer you were looking for but its the one I am giving based on either experience, educated guess, google or the fact that you gave nothing to go with in the first place so I used my wonky crystal ball.

Go Up