CO2 Sensor
Contents |
Requirements
Hardware
http://www.appliedsensor.com/products/indoor-air-monitor.html
aka:
Voltcraft CO-20 USB
MSR CO2 Air Guard USB
Butterfly Indoor Air Monitor USB
Dwyer AQStick model ASQ-1
eNasco Indoor Air monitor USB
FRAKTA CO2-Air Gard USB
Sentinel-Haus Institut RaumluftWächter
Software
Windows XP
AirMonitor application: http://www.appliedsensor.com/download/
CVS (CO2/VOC Sensor plugin for MiOS): https://docs.google.com/open?id=0Bz4omZm4gYcsaktBUkMyajZqV00
Installation
Connect the USB stick to your Windows XP computer.
Install the AirMonitor software.
In AirMonitor: activate the 'Support Tools' menu item: Hold down the left CTRL-key and double-click on the right top logo.
In AirMonitor: Support Tools -> Edit knobs: activate 'Act as server', adjust the port to your needs (see ...\AirMonitor\engineering.txt for details).
Install CVS, restart LuaUPnP.
Configure CVS: Set ServerIP, ServerPort, UpdateInterval (seconds, default: 60 s), restart LuaUPnP.
Limitations
Only one sensor per server is supported.
If the connection to the server fails/is lost, CVS doesn't try to re/establish the connection again, but fails with an error message.
Further reading
http://forum.micasaverde.com/index.php/topic,4705.0.html
http://code.google.com/p/airsensor-linux-usb/wiki/About
Screenshots
Using the CO-20 sensor with the Raspberry Pi
Installation
Raspberry Pi instructions:
sudo apt-get install libusb-dev gcc -o air air.c -lusb sudo ./air
MiOS instructions:
Create a Temperature sensor and use it as a container for the ppm values from the Raspberry Pi/CO-20 combo.
air.c source code
Written by Rodric Yates, based on airsensor-linux-usb, modified for MiOS by Ap15e (published with permission from Rodric Yates).
Modify
sprintf( command, "wget -O /dev/null 'http://192.168.178.116:3480/data_request?id=variableset&DeviceNum=480&serviceId=urn:upnp-org:serviceId:TemperatureSensor1&Variable=CurrentTemperature&Value=%d'", rresult);
to your needs (Vera's IP address, device number of the Temperature sensor).
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <usb.h>
#include <asm/byteorder.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#define AQ_GREEN 1000
#define AQ_YELLOW 1500
#define AQ_RED 4000
#define GREEN 0
#define YELLOW 1
#define RED 2
#define BLINK 3
char *airqual[] = { "GREEN", "YELLOW", "RED" };
struct usb_dev_handle *devh;
void release_usb_device(int dummy) {
int ret;
ret = usb_release_interface(devh, 0);
usb_close(devh);
exit(ret);
}
struct usb_device* find_device(int vendor, int product) {
struct usb_bus *bus;
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == vendor
&& dev->descriptor.idProduct == product)
return dev;
}
}
return NULL;
}
int main(int argc, char **argv)
{
int ret, reteth0, retwlan0,vendor, product;
struct usb_device *dev;
char buf[1000];
char command[2048];
FILE *fp;
char eth0mac[32];
char wlan0mac[32];
char eth0ip[32];
char wlan0ip[32];
char hostname[] = "raspberrypi" ;
char brokername[] = "api.cosm.com";
char portname [] = "1883";
// char topicname [] = "pi";
char topicname [] = "Your-Data-Feed-e.g./v2/feeds/91754/datastreams/AirPollution.csv";
char cosmapikey [] = "My-Cosm-API-Key";
char *mac;
/*
Check endianess of the router. The Voltcraft stick is little endian.
The TP-Link router is big endian.
*/
/*
int x = 1;
if (*(char *)&x == 1) {
fprintf(stderr, "Little Endian\n");
} else {
fprintf(stderr, "Big Endian\n");
}
*/
vendor = 0x03eb;
product = 0x2013;
dev = NULL;
usb_init();
while (1) {
#if 0
hostname = "raspberrypi";
fp = popen("uci get system.@system[0].hostname", "r");
if (fp != NULL) {
while (fgets(hostname, sizeof(hostname)-1, fp) != NULL) {
printf("hostname %s\n", hostname);
}
hostname[strlen(hostname)-1] = '\0';
}
#endif
eth0mac[0] = '\0';
wlan0mac[0] = '\0';
eth0ip[0] = '\0';
wlan0ip[0] = '\0';
// eth0 ip
fp = popen("ip addr list eth0 | grep inet | grep -v 192.168.3.3 \
| awk '{ print $2 }' ", "r");
// fp = popen("ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}' ", "r");
if (fp != NULL) {
while (fgets(eth0ip, sizeof(eth0ip)-1, fp) != NULL) {
printf("eth0ip %s\n", eth0ip);
eth0ip[strlen(eth0ip)-1] = '\0';
}
}
pclose(fp);
// eth0 mac
fp = popen("ifconfig eth0 | grep eth0 | awk '{ print $5 }'", "r");
if (fp != NULL) {
while (fgets(eth0mac, sizeof(eth0mac)-1, fp) != NULL) {
}
eth0mac[strlen(eth0mac)-1] = '\0';
printf("eth0mac %s\n", eth0mac);
}
pclose(fp);
// wlan0 ip
fp = popen("ifconfig wlan0 | grep 'inet addr:' \
| cut -d: -f2 | awk '{ print $1}' ", "r");
if (fp != NULL) {
while (fgets(wlan0ip, sizeof(wlan0ip)-1, fp) != NULL) {
printf("wlan0ip %s\n", wlan0ip);
wlan0ip[strlen(wlan0ip)-1] = '\0';
}
}
pclose(fp);
// wlan0 mac
fp = popen("ifconfig wlan0 | grep wlan0 | awk '{ print $5 }'", "r");
if (fp != NULL) {
while (fgets(wlan0mac, sizeof(wlan0mac)-1, fp) != NULL) {
printf("wlan0mac %s\n", wlan0mac);
}
wlan0mac[strlen(wlan0mac)-1] = '\0';
}
pclose(fp);
retwlan0 = -1;
reteth0 = -1;
do {
usb_set_debug(0);
usb_find_busses();
usb_find_devices();
dev = find_device(vendor, product);
printf("No device found ... sleeping ...\n");
sleep(10);
} while (dev == NULL);
assert(dev);
printf("device found\n");
devh = usb_open(dev);
assert(devh);
signal(SIGTERM, release_usb_device);
ret = usb_get_driver_np(devh, 0, buf, sizeof(buf));
if (ret == 0) {
// printf("interface 0 already claimed by driver \"%s\", attempting to detach it\n", buf);
ret = usb_detach_kernel_driver_np(devh, 0);
// printf("usb_detach_kernel_driver_np returned %d\n", ret);
}
ret = usb_claim_interface(devh, 0);
if (ret != 0) {
printf("claim failed with error %d\n", ret);
continue;
// exit(1);
}
// int c0 = 104;
// int c1 = 37;
unsigned char c0 = 104;
unsigned char c1 = 37;
unsigned short iresult=BLINK;
unsigned short oresult=BLINK;
unsigned short rresult=0;
while(0==0){
memcpy(buf, "\x40\x68\x2a\x54\x52\x0a\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40", 0x0000010);
ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000010, 1000);
// usleep(94*1000);
ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000010, 1000);
if ( !((ret == 0) || (ret == 16))) {
printf("device not ok: Unplug it, and plug it back in again.\n");
exit;
}
if (ret == 0) {
ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000010, 1000);
}
memcpy(&iresult,buf+2,2);
iresult = __le16_to_cpu(iresult);
printf("iresult %d (%X) ret %d\n", iresult, iresult, ret);
sleep(1);
ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000010, 1000);
printf("2 ret %d\n", ret);
if (iresult > 15000) {
printf("bogus iresult %d, skipping ...\n", iresult);
continue;
}
rresult = iresult;
if ( iresult < AQ_GREEN ) {
iresult = GREEN;
} else {
if ( iresult < AQ_YELLOW ) {
iresult = YELLOW;
} else {
iresult = RED;
}
}
if ( rresult < 15000) {
time_t t = time(NULL);
struct tm tm = *localtime(&t);
printf("now: %d-%d-%d %d:%d:%d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
printf("%s\n", airqual[iresult]);
//sprintf( command, "mosquitto_pub -i generic-client-identifier-change-as-needed -h %s -p %s -q 0 -u %s -t \"%s\" -m \"%d\" ", brokername, portname, cosmapikey, topicname, rresult);
sprintf( command, "wget -O /dev/null 'http://192.168.178.116:3480/data_request?id=variableset&DeviceNum=480&serviceId=urn:upnp-org:serviceId:TemperatureSensor1&Variable=CurrentTemperature&Value=%d'", rresult);
printf("command: %s\n", command);
ret = system(command);
if ( WEXITSTATUS(ret) == 0 ) {
oresult = iresult;
} else {
printf("Send error...will retry...\n");
oresult = BLINK;
}
}
sleep(20);
}
}
}
