Skip to content
Snippets Groups Projects
Commit aa5afec6 authored by Elisabetta Pianori's avatar Elisabetta Pianori
Browse files

Merge branch 'jgk_add_ClimateSensor' into 'devel'

add Pt100(0) and HIH4000 sensors read via Arduino

See merge request berkeleylab/labRemote!160
parents ce6fd4ab 0675c3c0
Branches
No related tags found
No related merge requests found
Pipeline #2122470 passed
......@@ -22,9 +22,11 @@ target_sources(DevCom
ClimateSensor.cpp
#BME280.cpp
HIH6130.cpp
HIH4000.cpp
SHT85.cpp
Si7021.cpp
NTCSensor.cpp
PtSensor.cpp
DACDevice.cpp
DAC5571.cpp
......
#include "HIH4000.h"
#include "NotSupportedException.h"
#include <cmath>
HIH4000::HIH4000(uint8_t chan, std::shared_ptr<ADCDevice> dev, std::shared_ptr<ClimateSensor> tempSens)
: m_adcdev(dev), m_tempSens(tempSens), m_chan(chan)
{ }
HIH4000::~HIH4000()
{ }
void HIH4000::init()
{ }
void HIH4000::reset()
{ }
void HIH4000::read()
{
m_tempSens->read();
m_temperature=m_tempSens->temperature();
m_humidity = 0.;
const uint navg = 5;
for(uint i=0;i<navg;i++)
m_humidity += (float)m_adcdev->read(m_chan);
m_humidity/=(float)navg;
// temperature correction
m_humidity=(m_humidity-0.16)/0.0062/(1.0546-0.00216*m_temperature);
}
float HIH4000::temperature() const
{
return m_temperature;
}
float HIH4000::humidity() const
{
return m_humidity;
}
float HIH4000::pressure() const
{
throw NotSupportedException("Pressure not supported for HIH4000");
return 0;
}
#ifndef HIH4000_H
#define HIH4000_H
#include "ClimateSensor.h"
#include "TextSerialCom.h"
#include "ADCDevice.h"
//! \brief An implementation of 'ClimateSensor' for reading an HIH4000 sensor
/**
* Measures humidity using a HIH4000 sensor connected to one of the analog pins
* on an Arduino via an ADC intereface.
* humiditry requires temperature connection: according sensor has to be provided
* HIH4000 specs: https://sensing.honeywell.com/HIH-4000-001-humidity-sensors
*/
class HIH4000: public ClimateSensor
{
public:
/**
* \param chan The channel number of the analog channel connected to the Pt
* \param dev The ADCDevice for interfacing with the Adruino or similar - should be calibrated
* to return measured voltage as 0...100% of the operational voltage
*/
HIH4000(uint8_t chan, std::shared_ptr<ADCDevice> dev, std::shared_ptr<ClimateSensor> tempSens);
virtual ~HIH4000();
virtual void init();
virtual void reset();
virtual void read();
virtual float temperature() const;
virtual float humidity() const;
virtual float pressure() const;
private:
//! Interface with the Arduino via the ADC protocol
std::shared_ptr<ADCDevice> m_adcdev;
//! The channel of the ADC connected to the Pt
uint8_t m_chan;
//! The temperature recorded in the last reading (defaults to -273.15)
float m_temperature = -273.15;
//! The humidity recorded in the last reading (defaults to 0)
float m_humidity = 0.;
//! ref. to the temperature sensor from which temp. correction is derived
std::shared_ptr<ClimateSensor> m_tempSens;
};
#endif // HIH4000_H
#include "PtSensor.h"
#include "NotSupportedException.h"
#include <cmath>
PtSensor::PtSensor(uint8_t chan, std::shared_ptr<ADCDevice> dev, float Rref, float Apt, float Bpt, float Rdiv)
: m_adcdev(dev), m_chan(chan), m_Rref(Rref), m_Apt(Apt), m_Bpt(Bpt), m_Rdiv(Rdiv)
{ }
PtSensor::~PtSensor()
{ }
void PtSensor::init()
{ }
void PtSensor::reset()
{ }
void PtSensor::read()
{
m_temperature=0.;
for(uint i=0;i<10;i++)
m_temperature+=(float)m_adcdev->read(m_chan);
m_temperature/=10;
m_temperature=raw_to_C(m_temperature);
}
float PtSensor::temperature() const
{
return m_temperature;
}
float PtSensor::humidity() const
{
throw NotSupportedException("Humidity not supported for Pt");
return 0;
}
float PtSensor::pressure() const
{
throw NotSupportedException("Pressure not supported for Pt");
return 0;
}
float PtSensor::raw_to_C(float raw)
{
// If there is a reading error, return a default value
if(raw>=1.) return -273.15;
float res = m_Apt*m_Apt-4.*m_Bpt*(1.-m_Rdiv/m_Rref*(1./raw-1.));
if(res<0.) return -273.15;
else return (std::sqrt(res)-m_Apt)/2./m_Bpt;
}
#ifndef PTSENSOR_H
#define PTSENSOR_H
#include <string>
#include <cstdint>
#include "ClimateSensor.h"
#include "ADCDevice.h"
//! \brief An implementation of 'ClimateSensor' for reading an Pt temperature sensor
/**
* Measures temperature using an Pt sensor (Pt100, Pt1000 etc.) connected to one of the
* analog channelss on an Arduino via an ADC intereface.
* PT sensors are available from various sources; this code was tested with a Pt1000 from TE -
* specs: https://www.te.com/global-en/product-NB-PTCO-157.html
*/
class PtSensor : public ClimateSensor
{
public:
/**
* \param chan The channel number of the analog channel connected to the Pt
* \param dev The ADCDevice for interfacing with the Adruino or similar - should be calibrated
* to return measured voltage as 0...100% of the operational voltage
* \param Rref The Pt's resistance at 0degC
* \param Apt The value of the linear calibration coefficient
* \param Bpt The value of the quadratic calibration coefficient
* \param Rdiv The resistance of the resistor in the voltage divider
* (the Pt and the resistor)
*/
PtSensor(uint8_t chan, std::shared_ptr<ADCDevice> dev, float Rref=1.e3,
float Apt=3.9083e-3, float Bpt=-5.775e-7, float Rdiv=1.e3);
virtual ~PtSensor();
//! Does nothing (requried to implement ClimateSensor)
virtual void init();
//! Does nothing (required to implement ClimateSensor)
virtual void reset();
//! Reads the temperature from the NTC and stores it in m_temperature
virtual void read();
//! Returns the temperature (in Celsius) from the most recent reading
// (defaults to -273.15)
virtual float temperature() const;
//! Throws a Not Supported exception (required to implement ClimateSensor)
virtual float humidity() const;
//! Throws a Not Supported exception (required to implement ClimateSensor
virtual float pressure() const;
private:
//! Interface with the Arduino via the ADC protocol
std::shared_ptr<ADCDevice> m_adcdev;
//! The resistance of the Pt at 0degC
float m_Rref;
//! The value of the linear calibration coefficient
float m_Apt;
//! The value of the quadratic calibration coefficient
float m_Bpt;
//! The resistance of the resistor in the voltage divider circuit
float m_Rdiv;
//! The channel of the ADCS connected to the Pt
uint8_t m_chan;
//! The temperature recorded in the last reading (defaults to -273.15)
float m_temperature = -273.15;
//! Converts from the raw readout of the Arduino channel to temperature in Celsius
float raw_to_C(float volt);
};
#endif // PTSENSOR_H
......@@ -9,7 +9,7 @@ foreach(target ${examples})
add_executable(${execname})
target_sources(${execname} PRIVATE ${srcfile})
target_link_libraries(${execname} DevCom Utils PS)
target_link_libraries(${execname} DevCom Utils PS DataSink EquipConf)
if ( ${ENABLE_FTDI} )
target_compile_definitions(${execname} PUBLIC FTDI=1)
......
#include <getopt.h>
#include <string.h>
#include <signal.h>
#include <fstream>
#include <string>
#include <iostream>
#include <iomanip>
#include <thread>
#include <chrono>
#include <sys/stat.h>
#include <map>
#include <TextSerialCom.h>
#include <ADCDevComuino.h>
#include <NTCSensor.h>
#include <PtSensor.h>
#include <HIH4000.h>
#include <DataSinkConf.h>
#include <IDataSink.h>
//------ SETTINGS
uint32_t tsleep = 1000;
std::string configFile="config.json";
std::string streamName="Climate";
int rport = 0;
//---------------
bool quit=false;
void cleanup(int signum)
{ quit=true; }
void usage(char *argv[])
{
std::cout << "Usage: "<< argv[0] << " [-c config file] [-s stream name] [-p serial port] [-t sleep time (ms)]"<< std::endl;
std::cout << " defaults: -c " << configFile << " -s " << streamName<< " -p " << rport << " -t " << tsleep << std::endl;
}
int main(int argc, char** argv)
{
//Parse command-line
if (argc < 1)
{
usage(argv);
return 1;
}
int c;
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"port", required_argument, 0, 'p' },
{"config", required_argument, 0, 'c' },
{"stream", required_argument, 0, 's' },
{"tsleep", required_argument, 0, 't' },
{"debug", no_argument , 0, 'd' },
{"help", no_argument , 0, 'h' },
{0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "s:c:p:t:dh", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 's':
streamName = optarg;
break;
case 'c':
configFile = optarg;
break;
case 'p':
rport = atoi(optarg);
break;
case 't':
tsleep = atoi(optarg);
break;
case 'd':
logIt::incrDebug();
break;
case 'h':
usage(argv);
return 1;
default:
std::cerr << "Invalid option '" << c << "' supplied. Aborting." << std::endl;
std::cerr << std::endl;
usage(argv);
return 1;
}
}
// open serial device
speed_t baud=B9600;
std::shared_ptr<TextSerialCom> sc(new TextSerialCom("/dev/ttyACM"+std::to_string(rport), baud));
sc->init();
sc->setTermination("\r\n");
// somehow needed to initiate communication to Arduino
try{
sc->send("HELP");
std::cout << sc->receive() << std::endl;
} catch(...){
//std::cerr << "ERROR testing Arduino communication" << std::endl;
}
// create Arduino as ADC device
std::shared_ptr<ADCDevice> dev(new ADCDevComuino(1.,sc));
// create NTC
std::shared_ptr<NTCSensor> ntc(new NTCSensor(1, sc, 298.15, 10e3, 3435.0, 18e3, 5.0));
// create Pt1000
std::shared_ptr<PtSensor> pt(new PtSensor(0, dev, 1.e3, 3.9083e-3, -5.775e-7, 970.0));
// create HIH4000
std::shared_ptr<HIH4000> hum(new HIH4000(2, dev, std::static_pointer_cast<ClimateSensor>(pt)));
// Create sink
DataSinkConf ds;
ds.setHardwareConfig(configFile);
std::shared_ptr<IDataSink> stream = ds.getDataStream(streamName);
// Register interrupt for cleanup
signal(SIGINT, cleanup);
// request data from selected measurement
while(!quit)
{
// Ambient T and H
hum->read();
stream->setTag("Sensor", "Ambient");
stream->startMeasurement("environment", std::chrono::system_clock::now());
stream->setField("temperature", hum->temperature()); // actual reading from Pt1000
stream->setField("humidity", hum->humidity());
stream->recordPoint();
stream->endMeasurement();
// module T
ntc->read();
stream->setTag("Sensor", "Module");
stream->startMeasurement("environment", std::chrono::system_clock::now());
stream->setField("temperature", ntc->temperature());
stream->setField("dewpoint", hum->dewPoint());
stream->recordPoint();
stream->endMeasurement();
std::this_thread::sleep_for(std::chrono::milliseconds(tsleep));
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment