Listing 7. Humidity Controller Application C Code /* * Humidity Controller Application * * Copyright (C) 2009 Jeffrey Ramsey * * http://www.e2atechnology.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version, so long * as an * acknowledgment appears in derived source files. The * citation should list where the code came from. No warranty is * attached; I assume no responsibility for errors or fitness for use. * */ #include #include #include #include #include #include "/mnt/lfs/linux24/drivers/relay8/relay8Ioctl.h" #include "/mnt/lfs/linux24/drivers/sht1x/sht1xIoctl.h" /* Only expect this many characters in the * targetHumidity output from snmpget */ #define MAX_LINE 132 /* This is the humidifier power relay set */ #define HUMIDIFIER_RELAY_ID 0x03 /* This is the dehumidifier power relay set */ #define DEHUMIDIFIER_RELAY_ID 0x0c /* Let dehumidifier settle for this # of seconds */ #define DEHUMIDIFIER_SETTLING_TIME 60 /* Maximum # readings before the average is rescaled */ #define MAX_READINGS_BEFORE_RESCALE 500 int main(int argc, char *argv[]) { int fdSht11, fdRelays; unsigned int uiHumidity, uiTemperature; unsigned int uiMaxHumidity=0, uiMinHumidity=1000; unsigned int uiAvgHumidity=0, uiAvgCumulativeHumidity=0; unsigned int uiNumReadings=0; int iVals, iSetVals; unsigned int uiTargetHumidity = 50; FILE *fp1; char sTarget[MAX_LINE]; unsigned long ulLastDehumidifierSecondStamp = 0; unsigned long ulCurrentSeconds = 0; unsigned long tdiff; /* Open device instances */ fdRelays = open("/dev/relay80", O_RDWR); if (fdRelays <= 0) { printf("cannot open relay8-0!\n"); exit(0); } fdSht11 = open("/dev/sht1x0", O_RDWR); if( fdSht11 > 0 ) { printf("cannot open sht1x-0!\n"); exit(0); } /* Perpetually process; * Fetch MIB value for targetHumidity * Read current humidity/temperature and * process/switch relays if necessary * Gather statistics and update the SNMP OIDs */ while (1) { /* Periodically poll system */ sleep(1); /* Increment the seconds count; if it wraps to zero, * reset the last dehumidifier second stamp even though * the system will have to be up for many years for * this to ever happen! */ if (++ulCurrentSeconds == 0) { ulLastDehumidifierSecondStamp = 0; } /* Fetch the current target humidity and just * save it to be checked below against current readings */ system("snmpget -Ovqe -v 1 -c private " "localhost targetHumidity.0 1>vals.txt"); fp1 = fopen("./vals.txt", "r"); if (fp1) { fgets(sTarget, sizeof( sTarget ) - 1, fp1); sscanf(sTarget, "%d", &uiTargetHumidity); close(fp1); } /* Read current humidity/temperature */ ioctl(fdSht11, SHT1X_IOC_READ_HUMIDITY, &uiHumidity); ioctl(fdSht11, SHT1X_IOC_READ_TEMPERATURE, &uiTemperature); /* Process depending on state determined by relay settings */ /* Check if adjustment required; +- 3.5% rH */ if ((uiHumidity * 10) > ((uiTargetHumidity * 10) + 35)) { /* Need to dehumidify as long as dehumidifier * isn't already running */ ioctl(fdRelays, RELAY8_IOC_READ_RELAYS, &iSetVals); if (!(iSetVals & DEHUMIDIFIER_RELAY_ID)) { /* Dehumidifier isn't on; but check if it was * on in the settling period and defer if it was * to give the compressor time to settle */ tdiff = ulCurrentSeconds - ulLastDehumidifierSecondStamp; if (tdiff > DEHUMIDIFIER_SETTLING_TIME) { /* Safe to turn on dehumidifer */ iVals = DEHUMIDIFIER_RELAY_ID; ioctl(fdRelays, RELAY8_IOC_WRITE_RELAYS, &iVals); /* New second stamp for dehumidifier * settling time */ ulLastDehumidifierSecondStamp = ulCurrentSeconds; } } } else if ((uiHumidity * 10) < ((uiTargetHumidity * 10) - 35)) { /* Need to humidify as long as humidifier * isn't already running */ ioctl(fdRelays, RELAY8_IOC_READ_RELAYS, &iSetVals); if (!(iSetVals & HUMIDIFIER_RELAY_ID)) { /* Humidifier isn't on; no settling period * required as there is no compressor */ /* Safe to turn on humidifer */ iVals = HUMIDIFIER_RELAY_ID; ioctl(fdRelays, RELAY8_IOC_WRITE_RELAYS, &iVals); } } else { /* All relays should be off; humidity * is within target range */ iVals = 0; ioctl(fdRelays, RELAY8_IOC_WRITE_RELAYS, &iVals); } /* Accumulate some statistics */ if (uiHumidity > uiMaxHumidity) { uiMaxHumidity = uiHumidity; } if (uiHumidity < uiMinHumidity) { uiMinHumidity = uiHumidity; } uiAvgCumulativeHumidity += uiHumidity; uiAvgHumidity = uiAvgCumulativeHumidity / ++uiNumReadings; /* Display current status on the console if debugging */ printf("targetH=%d " "currentH=%d currentT=%d " "minH=%d maxH=%d avgH=%d\n", uiTargetHumidity, uiHumidity, uiTemperature, uiMinHumidity, uiMaxHumidity, uiAvgHumidity); /* One more reading, and if it reaches a value where * the previous might overrun for average calculations, * rescale to 1. The average across a sampling shouldn't * be substantially different than the next sampling. */ if (uiNumReadings == MAX_READINGS_BEFORE_RESCALE) { uiNumReadings = 1; uiAvgCumulativeHumidity = uiHumidity; } /* Now refresh the SNMP settings given what was just read. * The following permits checking the set values to ensure * the OIDs were really set (i.e. read back vals.txt and * compare it against what was set), but this isn't * done here. Settings can be checked on the web * interface values. */ sprintf(sTarget, "snmpset -Ovqe -v 1 -c private " "localhost currentHumidity.0 i %d", uiHumidity); system(sTarget); sprintf(sTarget, "snmpset -Ovqe -v 1 -c private " "localhost currentTemperature.0 i %d", uiTemperature); system(sTarget); sprintf(sTarget, "snmpset -Ovqe -v 1 -c private " "localhost minHumidity.0 i %d", uiMinHumidity); system(sTarget); sprintf(sTarget, "snmpset -Ovqe -v 1 -c private " "localhost maxHumidity.0 i %d", uiMaxHumidity); system(sTarget); sprintf(sTarget, "snmpset -Ovqe -v 1 -c private " "localhost avgHumidity.0 i %d", uiAvgHumidity); system(sTarget); } /* The previous loop will normally never exit, * but if it did, e.g. from testing, close the devices */ close(fdRelays); close(fdSht11); return(1); }