diff options
Diffstat (limited to 'cphidgetphsensor.c')
-rw-r--r-- | cphidgetphsensor.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/cphidgetphsensor.c b/cphidgetphsensor.c new file mode 100644 index 0000000..751f530 --- /dev/null +++ b/cphidgetphsensor.c @@ -0,0 +1,241 @@ +#include "stdafx.h" +#include "cphidgetphsensor.h" +#include <math.h> +#include "cusb.h" +#include "csocket.h" +#include "cthread.h" + +// === Internal Functions === // + +static double calculate_ph(double Vad, double temperature); + +//clearVars - sets all device variables to unknown state +CPHIDGETCLEARVARS(PHSensor) + + phid->phMax = PUNI_DBL; + phid->phMin = PUNI_DBL; + phid->potentialMax = PUNI_DBL; + phid->potentialMin = PUNI_DBL; + + phid->Temperature = PUNI_DBL; + phid->PH = PUNI_DBL; + phid->PHLastTrigger = PUNK_DBL; + phid->Potential = PUNI_DBL; + phid->PHChangeTrigger = PUNI_DBL; + + return EPHIDGET_OK; +} + +//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed +// used during attach initialization - on every attach +CPHIDGETINIT(PHSensor) + TESTPTR(phid); + + phid->Temperature = 20; //20 degrees celcius default + + //Setup max/min values + switch(phid->phid.deviceIDSpec) + { + case PHIDID_PHSENSOR: + if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200)) + { + phid->phMax = round_double(calculate_ph((65535.0 / 13104.0), phid->Temperature), 4); + phid->phMin = round_double(calculate_ph(0, phid->Temperature), 4); + phid->potentialMax = round_double(((2.5) / 4.745) * 1000.0, 2); + phid->potentialMin = round_double(((2.5 - (65535.0 / 13104.0)) / 4.745) * 1000.0, 2); + } + else + return EPHIDGET_BADVERSION; + break; + default: + return EPHIDGET_UNEXPECTED; + } + + //initialize triggers, set data arrays to unknown + phid->PH = PUNK_DBL; + phid->PHLastTrigger = PUNK_DBL; + phid->Potential = PUNK_DBL; + phid->PHChangeTrigger = 0.05; + + //issue one read + CPhidget_read((CPhidgetHandle)phid); + + return EPHIDGET_OK; +} + +//dataInput - parses device packets +CPHIDGETDATA(PHSensor) + double PH = 0, Potential = 0; + + if (length<0) return EPHIDGET_INVALIDARG; + TESTPTR(phid); + TESTPTR(buffer); + + //Parse device packets - store data locally + switch(phid->phid.deviceIDSpec) + { + case PHIDID_PHSENSOR: + if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200)) + { + double Vad = 0, E = 0; + + Vad = ((double)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8))) / 13104.0; + PH = round_double(calculate_ph(Vad, phid->Temperature), 4); + + E = (2.5 - Vad) / 4.745; + Potential = round_double((E * 1000.0), 2); + } + else + return EPHIDGET_UNEXPECTED; + break; + default: + return EPHIDGET_UNEXPECTED; + } + + //Make sure values are within defined range, and store to structure + if(PH < phid->phMin || PH > phid->phMax) + phid->PH = PUNK_DBL; + else + phid->PH = PH; + if(Potential < phid->potentialMin || Potential > phid->potentialMax) + phid->Potential = PUNK_DBL; + else + phid->Potential = Potential; + + //send out any events that exceed or match the trigger + if ((fabs(phid->PH - phid->PHLastTrigger) >= phid->PHChangeTrigger || phid->PHLastTrigger == PUNK_DBL) + && phid->PH != PUNK_DBL) + { + FIRE(PHChange, phid->PH); + phid->PHLastTrigger = phid->PH; + } + + return EPHIDGET_OK; +} + +//eventsAfterOpen - sends out an event for all valid data, used during attach initialization +CPHIDGETINITEVENTS(PHSensor) + if (phid->PH != PUNK_DBL) + { + FIRE(PHChange, phid->PH); + phid->PHLastTrigger = phid->PH; + } + return EPHIDGET_OK; +} + +//getPacket - not used for PHSensor +CGETPACKET(PHSensor) + return EPHIDGET_UNEXPECTED; +} + +static double calculate_ph(double Vad, double temperature) +{ + double E, E0, C, T; + const double R=8.31441, N=1, F=96484.6; + T=(273.15)+temperature; + C = 2.3 * ((R*T)/(N*F)); + E0 = 7*C; + E = (2.5 - Vad) / 4.745; + return ((E0 - E) / C); +} + +// === Exported Functions === // + +//create and initialize a device structure +CCREATE(PHSensor, PHIDCLASS_PHSENSOR) + +//event setup functions +CFHANDLE(PHSensor, PHChange, double) + +CGET(PHSensor,PH,double) + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTMASGN(PH, PUNK_DBL) + + MASGN(PH) +} + +CGET(PHSensor,PHMax,double) + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTMASGN(phMax, PUNK_DBL) + + MASGN(phMax) +} + +CGET(PHSensor,PHMin,double) + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTMASGN(phMin, PUNK_DBL) + + MASGN(phMin) +} + +CGET(PHSensor,PHChangeTrigger,double) + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTMASGN(PHChangeTrigger, PUNK_DBL) + + MASGN(PHChangeTrigger) +} +CSET(PHSensor,PHChangeTrigger,double) + TESTPTR(phid) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTRANGE(0, phid->phMax - phid->phMin) + + if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) + ADDNETWORKKEY(Trigger, "%lE", PHChangeTrigger); + else + phid->PHChangeTrigger = newVal; + + return EPHIDGET_OK; +} + +CGET(PHSensor,Potential,double) + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTMASGN(Potential, PUNK_DBL) + + MASGN(Potential) +} + +CGET(PHSensor,PotentialMax,double) + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTMASGN(potentialMax, PUNK_DBL) + + MASGN(potentialMax) +} + +CGET(PHSensor,PotentialMin,double) + TESTPTRS(phid,pVal) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTMASGN(potentialMin, PUNK_DBL) + + MASGN(potentialMin) +} + +CSET(PHSensor,Temperature,double) + TESTPTR(phid) + TESTDEVICETYPE(PHIDCLASS_PHSENSOR) + TESTATTACHED + TESTRANGE(-273.15, 5000) //arbitrary but reasonable range + + if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) + ADDNETWORKKEY(Temperature, "%lE", Temperature); + else + phid->Temperature = newVal; + + phid->phMax = round_double(calculate_ph((65535.0 / 13104.0), phid->Temperature), 4); + phid->phMin = round_double(calculate_ph(0, phid->Temperature), 4); + + return EPHIDGET_OK; +} |