View Single Post
Old 03-25-14, 11:15 AM   #101
AC_Hacker
Supreme EcoRenovator
 
AC_Hacker's Avatar
 
Join Date: Mar 2009
Location: Portland, OR
Posts: 4,002
Thanks: 303
Thanked 712 Times in 532 Posts
Default Project Improvement...

Although the fan-control part of the program worked just fine, I had a persistent problem with the display of the CO2 values, in that values below 999 ppm were all showing properly, but once the displayed values exceeded 999 ppm, and went into 4-digits (EX: 1032 ppm) and then dropped below a 4-digit value, the last digit would hang, and a value like 984 ppm would read out something like 9842 ppm, with the last digit being a persistent artifact from the last 4-digit value that had been displayed.

The fix was to flush the ppm value part of the display with 4 blank spaces before printing the ppm value. Fix code is at lines 239 through 247.

Below, is the revised code.

By the way, I've been watching my monitor-controller which senses CO2, temperature and humidity for a bit over a year now, and I am amazed at how accurate the temperature-humidity chip (SHT15) has been. In fact, it has become my reference monitor!

Best,

-AC

Code:
/*
 * Example code for SHT1x or SHT7x sensors demonstrating blocking calls
 * for temperature and humidity measurement in the setup routine and
 * non-blocking calls in the main loop.  The pin 13 LED is flashed as a
 * background task while temperature and humidity measurements are made.
 * In addition, the sensor may be placed in low resolution mode by
 * uncommenting the status register write call in setup().
 */
 
 /*
 
  The circuit:
 * LCD RS pin to digital pin 12      => Teensy 5
 * LCD Enable pin to digital pin 11  => Teensy 4
 * LCD D4 pin to digital pin 5       => Teensy 23
 * LCD D5 pin to digital pin 4       => Teensy 22
 * LCD D6 pin to digital pin 3       => Teensy 21
 * LCD D7 pin to digital pin 2       => Teensy 20
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 */
 
 //Celsius to Fahrenheit conversion
 double Fahrenheit(double celsius)
 {
 	return 1.8 * celsius + 32;
}

//Celsius to Kelvin conversion
double Kelvin(double celsius)
{
	return celsius + 273.15;
}

// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm 
double dewPoint(double celsius, double humidity)
{
	double A0= 373.15/(273.15 + celsius);
	double SUM = -7.90298 * (A0-1);
	SUM += 5.02808 * log10(A0);
	SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
	SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
	SUM += log10(1013.246);
	double VP = pow(10, SUM-3) * humidity;
	double T = log(VP/0.61078);   // temp var
	return (241.88 * T) / (17.558-T);
}

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
	double a = 17.271;
	double b = 237.7;
	double temp = (a * celsius) / (b + celsius) + log(humidity/100);
	double Td = (b * temp) / (a - temp);
	return Td;
}

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(5, 4, 23, 22, 21, 20);

// Define pins for CO2 Sensor
int CO2_ReadPin = 38;                    // initialize pin 38 for analog voltage in
int PWM_WritePin = 14;                   // initialize pin 14 for PWM
int CO2_Value;
int PWM_Value;
int DutyCycle;
int ppm;

 

#include <Sensirion.h>

const uint8_t dataPin =  10;            // SHT serial data (Teensy)
const uint8_t sclkPin =  11;            // SHT serial clock (Teensy)
const uint8_t ledPin  =  6;            // Arduino built-in LED (Teensy)


const uint32_t TRHSTEP   = 3000UL;     // Sensor query period
const uint32_t BLINKSTEP =  250UL;     // LED blink period

Sensirion sht = Sensirion(dataPin, sclkPin);

uint16_t rawData;
float temperature;
float humidity;
float dewpoint;

byte shtState = 0;
byte ledState = 0;

unsigned long curMillis;               // Time interval tracking
unsigned long trhMillis = 0;
unsigned long blinkMillis = 0;

void setup(){
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  //lcd.print("ACHacker");
  
  // Setup for CO2 Sensor
  pinMode(PWM_WritePin, OUTPUT);         // Make PWM_pin (AKA: pin 14) an output pin
  int CO2_Value = 0;                     // variable set to zero
  int PWM_Value = 0;                     // variable set to zero
  int DutyCycle = 0;                     // variable set to zero  
  int ppm = 0;                           // variable set to zero 
  
//Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  delay(15);                           // Wait at least 11 ms before first cmd
//  sht.writeSR(LOW_RES);                // Set sensor to low resolution
  sht.measTemp(&rawData);              // Maps to: sht.meas(TEMP, &rawData, BLOCK)
  temperature = sht.calcTemp(rawData);
  sht.measHumi(&rawData);              // Maps to: sht.meas(HUMI, &rawData, BLOCK)
  humidity = sht.calcHumi(rawData, temperature);
  dewpoint = sht.calcDewpoint(humidity, temperature);
  logData();
}

void loop()
{
  curMillis = millis();

  if (curMillis - blinkMillis >= BLINKSTEP) {    // Time to toggle the LED state?
    ledState ^= 1;
    digitalWrite(ledPin, ledState);
    blinkMillis = curMillis;
  }

  switch (shtState) {
  case 0:
    if (curMillis - trhMillis >= TRHSTEP) {      // Start new temp/humi measurement?
      sht.meas(TEMP, &rawData, NONBLOCK);
      shtState++;
      trhMillis = curMillis;
    }
    break;
  case 1:
    if (sht.measRdy()) {                         // Process temperature measurement?
      temperature = sht.calcTemp(rawData);
      sht.meas(HUMI, &rawData, NONBLOCK);
      shtState++;
    }
    break;
  case 2:
    if (sht.measRdy()) {                         // Process humidity measurement?
      humidity = sht.calcHumi(rawData, temperature);
      dewpoint = sht.calcDewpoint(humidity, temperature);
      shtState = 0;
      logData();
    }
    break;
  default:
    Serial.println("How did I get here?");
    break;
  }
}

void logData() {
  //Serial.print("Temperature = ");   Serial.print(temperature);
  //Serial.print(" C, Humidity = ");  Serial.print(humidity);
  //Serial.print(" %, Dewpoint = ");  Serial.print(dewpoint);
  //Serial.println(" C");
  
  
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    // Loop for CO2 Sensor
    CO2_Value = analogRead(CO2_ReadPin);   // read Teensy input pin 38
    unsigned int ppm = ((unsigned long)analogRead(CO2_ReadPin) * 2500)/1024;  // calc ppm
    //Serial.print("CO2 level     = ");      // Write ppm to serial monitor
    //Serial.print(ppm); 
    //Serial.println(" ppm");
    PWM_Value = CO2_Value/4;               // Scale CO2_Value (range = 1024) to PWM_Value (range = 256)
    analogWrite(PWM_WritePin, (PWM_Value + 54));  // Write PWM_Value to PWM_WritePin
    //Serial.print("PWM_Value is  = ");      // Write val to serial monitor
    //Serial.println(PWM_Value + 54);
    DutyCycle = (100 * (PWM_Value + 54) / 256);   // Calculate DutyCycle
    //Serial.print("PWM DutyCycle = ");      // Write DutyCycle to serial monitor
    //Serial.print(DutyCycle);
    //Serial.println("%");

  //PRINTING TEMPERATURE
  // set the cursor to column 0, line 0
  // (note: line 0 is the first row, since counting begins with 0): %column, row%
  lcd.setCursor(0, 0);  
  // print the Temperature title
  lcd.print("Temp");
  
   // set the cursor to column 5, line 0
  // (note: line 0 is the first row, since counting begins with 0):
  lcd.setCursor(5, 0);  
  // print the Temperature valie
  //****lcd.print(Fahrenheit(DHT11.temperature), 0);
  lcd.print(Fahrenheit(temperature), 0);
  
  // set the cursor to column 7, line 0
  // (note: line 0 is the first row, since counting begins with 0): %column, row%
  lcd.setCursor(7, 0);  
  // print the Temperature 'F'
  lcd.print("F");
  
  //PRINTING RELATIVE HUMIDITY
  // set the cursor to column 10, line 0
  // (note: line 0 is the first row, since counting begins with 0):
  lcd.setCursor(10, 0);  
  // print the Relative Humidity title
  lcd.print("RH");
  
  // set the cursor to column 13, line 0
  // (note: line 0 is the first row, since counting begins with 0):
  lcd.setCursor(13, 0);  
  // print the Relative Humidity value
  //*****lcd.print((float)DHT11.humidity, 0);
  lcd.print(humidity, 0);
  
  // set the cursor to column 15, line 0
  // (note: line 0 is the first row, since counting begins with 0): %column, row%
  lcd.setCursor(15, 0);  
  // print the Relative Humidity percent sign
  lcd.print("%");
  
  
  //PRINTING CO2 READINGS
  // set the cursor to column 0, line 1
  // (note: line 0 is the first row, since counting begins with 0):
  lcd.setCursor(2, 1);  
  // print the CO2 title
  lcd.print("CO2 ");
  
  // set the cursor to column 6, line 1
  // (note: line 0 is the first row, since counting begins with 0):
  lcd.setCursor(6, 1);
  // print 'purge' characters to eliminate persistent last digit
  lcd.print("    ");
  // reposition the cursor to column 6, line 1
  lcd.setCursor(6, 1);
  // print the CO2 value
  lcd.print(ppm);
  
    // set the cursor to column 11, line 1
  // (note: line 0 is the first row, since counting begins with 0): %column, row%
  lcd.setCursor(11, 1);  
  // print the CO2 'ppm'
  lcd.print("ppm");
  
  
  delay(2000);

}

__________________
I'm not an HVAC technician. In fact, I'm barely even a hacker...

Last edited by AC_Hacker; 03-25-14 at 11:36 AM..
AC_Hacker is offline   Reply With Quote
The Following User Says Thank You to AC_Hacker For This Useful Post:
buffalobillpatrick (03-27-14)