ICCARS
By: Robert Kurkowski
Brief Description: This project is used to test the temperature, altitude, and pressure of an area. These variables are taken in by a Thermometer that tests for the temperature of a surface, and a barometer that measures the altitude and the pressure. This data is then stred on a memory card.
Detailed Description: This project takes in the information of the barometer and the infrared thermometer and stored it on a memory card which is located in a log shield. The temperature, pressure, date, time, and altitude are taken and calculated by the arduino using an I2C master library(calculates the pressure, altitude, and temperature) and a RTClip library(calculated date and time). Once the variables have been calculated and stored the memory card is taken out of the shield and placed into a computer where we can view the files as a spreadsheet.
My Code:
Text Box
#include <i2cmaster.h> //Arduino 1.0+ Only//Arduino 1.0+ Only/*Based largely on code by Jim Lindblom//Made by Robert Kurkowski Get pressure, altitude, and temperature from the BMP085. Serial.print it out at 9600 baud to serial monitor. */ #include <Wire.h> #include <SD.h> #include "RTClib.h"// A simple data logger for the Arduino analog pins// how many milliseconds between grabbing data and logging it. 1000 ms is once a second #define LOG_INTERVAL 1000 // mills between entries (reduce to take more/faster data)// how many milliseconds before writing the logged data permanently to disk// set it to the LOG_INTERVAL to write each time (safest)// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to // the last 10 reads if power is lost but it uses less power and is much faster! #define SYNC_INTERVAL 1000 // mills between calls to flush() - to write data to the card uint32_t syncTime = 0; // time of last sync() #define ECHO_TO_SERIAL 1 // echo data to serial port #define WAIT_TO_START 0 // Wait for serial input in setup()// the digital pins that connect to the LEDs #define redLEDpin 2 #define greenLEDpin 3 // The analog pins that connect to the sensors #define BMP085_ADDRESS 0x77 // I2C address of BMP085 const unsigned char OSS = 0; // Oversampling Setting #define IRthermometer #define BANDGAPREF 14 // special indicator that we want to measure the bandgap #define aref_voltage 3.3 // we tie 3.3V to ARef and measure it with a multimeter! #define bandgap_voltage 1.1 // this is not super guaranteed but its not -too- offRTC_DS1307 RTC; // define the Real Time Clock object// for the data logging shield, we use digital pin 10 for the SD cs line const int chipSelect = 10; float celcius; float pressure; // the logging fileFile logfile; void error(char *str) { Serial.print("error: "); Serial.println(str); // red LED indicates error digitalWrite(redLEDpin, HIGH); while(1); } // Calibration valuesint ac1; int ac2; int ac3; unsigned int ac4; unsigned int ac5; unsigned int ac6; int b1; int b2; int mb; int mc; int md; // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)// so ...Temperature(...) must be called before ...Pressure(...).long b5; void setup(){ Serial.begin(9600); Serial.println(); // use debugging LEDs pinMode(redLEDpin, OUTPUT); pinMode(greenLEDpin, OUTPUT); #if WAIT_TO_START Serial.println("Type any character to start"); while (!Serial.available()); #endif //WAIT_TO_START // initialize the SD card Serial.print("Initializing SD card..."); // make sure that the default chip select pin is set to // output, even if you don't use it: pinMode(10, OUTPUT); // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { error("Card failed, or not present"); } Serial.println("card initialized."); // create a new file char filename[] = "LOGGER00.CSV"; for (uint8_t i = 0; i < 100; i++) { filename[6] = i/10 + '0'; filename[7] = i%10 + '0'; if (! SD.exists(filename)) { // only open a new file if it doesn't exist logfile = SD.open(filename, FILE_WRITE); break; // leave the loop! } } if (! logfile) { error("couldnt create file"); } Serial.print("Logging to: "); Serial.println(filename); // connect to RTC Wire.begin(); if (!RTC.begin()) { logfile.println("RTC failed"); #if ECHO_TO_SERIAL Serial.println("RTC failed"); #endif //ECHO_TO_SERIAL } logfile.println("millis,stamp,datetime,altitude,temp,pressure,volt"); #if ECHO_TO_SERIAL Serial.println("millis,stamp,datetime,altitude,temp,pressure,volt"); #endif //ECHO_TO_SERIAL // If you want to set the aref to something other than 5v analogReference(EXTERNAL); Serial.println("Setup..."); i2c_init(); //Initialise the i2c bus PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups Wire.begin(); bmp085Calibration(); } void loop() { DateTime now; // delay for the amount of time we want between readings delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); digitalWrite(greenLEDpin, HIGH); // log milliseconds since starting uint32_t m = millis(); logfile.print(m); // milliseconds since start logfile.print(", "); #if ECHO_TO_SERIAL Serial.print(m); // milliseconds since start Serial.print(", "); #endif // fetch the time now = RTC.now(); // log time logfile.print(now.unixtime()); // seconds since 1/1/1970 logfile.print(", "); logfile.print('"'); logfile.print(now.year(), DEC); logfile.print("/"); logfile.print(now.month(), DEC); logfile.print("/"); logfile.print(now.day(), DEC); logfile.print(" "); logfile.print(now.hour(), DEC); logfile.print(":"); logfile.print(now.minute(), DEC); logfile.print(":"); logfile.print(now.second(), DEC); logfile.print('"'); logfile.print(", "); #if ECHO_TO_SERIAL Serial.print(now.unixtime()); // seconds since 1/1/1970 Serial.print(", "); Serial.print('"'); Serial.print(now.year(), DEC); Serial.print("/"); Serial.print(now.month(), DEC); Serial.print("/"); Serial.print(now.day(), DEC); Serial.print(" "); Serial.print(now.hour(), DEC); Serial.print(":"); Serial.print(now.minute(), DEC); Serial.print(":"); Serial.print(now.second(), DEC); Serial.print('"'); #endif //ECHO_TO_SERIAL bob(); float temperature = bmp085GetTemperature(bmp085ReadUT()); //MUST be called first pressure = bmp085GetPressure(bmp085ReadUP()); float atm = pressure / 101325; // "standard atmosphere" float altitude = calcAltitude(pressure); //Uncompensated caculation - in Meters Serial.print("Temperature: "); Serial.print(temperature, 2); //display 2 decimal places Serial.println("deg C"); Serial.print("Pressure: "); Serial.print(pressure, 0); //whole number only. Serial.println(" Pa"); Serial.print("Standard Atmosphere: "); Serial.println(atm, 4); //display 4 decimal places Serial.print("Altitude: "); Serial.print(altitude, 2); //display 2 decimal places Serial.println(" M"); //logfile.print();//line break logfile.print(altitude,2); //display 2 decimal places logfile.print(" ,"); // delay(1000); //wait a second and get values again. logfile.print(int(celcius)); logfile.print(","); logfile.print(pressure, 0); //whole number only. logfile.print(","); #if ECHO_TO_SERIAL Serial.print(", "); Serial.print(int(celcius)); #endif //ECHO_TO_SERIAL // Log the estimated 'VCC' voltage by measuring the internal 1.1v ref analogRead(BANDGAPREF); delay(10); int refReading = analogRead(BANDGAPREF); float supplyvoltage = (bandgap_voltage * 1024) / refReading; logfile.print(supplyvoltage); #if ECHO_TO_SERIAL Serial.print(", "); Serial.print(supplyvoltage); #endif // ECHO_TO_SERIAL logfile.println(); #if ECHO_TO_SERIAL Serial.println(); #endif // ECHO_TO_SERIAL digitalWrite(greenLEDpin, LOW); // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card // which uses a bunch of power and takes time if ((millis() - syncTime) < SYNC_INTERVAL) return; syncTime = millis(); // blink LED to show we are syncing data to the card & updating FAT! digitalWrite(redLEDpin, HIGH); logfile.flush(); digitalWrite(redLEDpin, LOW); } // Stores all of the bmp085's calibration values into global variables// Calibration values are required to calculate temp and pressure// This function should be called at the beginning of the programvoid bmp085Calibration() { ac1 = bmp085ReadInt(0xAA); ac2 = bmp085ReadInt(0xAC); ac3 = bmp085ReadInt(0xAE); ac4 = bmp085ReadInt(0xB0); ac5 = bmp085ReadInt(0xB2); ac6 = bmp085ReadInt(0xB4); b1 = bmp085ReadInt(0xB6); b2 = bmp085ReadInt(0xB8); mb = bmp085ReadInt(0xBA); mc = bmp085ReadInt(0xBC); md = bmp085ReadInt(0xBE); } // Calculate temperature in deg Cfloat bmp085GetTemperature(unsigned int ut){ long x1, x2; x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; x2 = ((long)mc << 11)/(x1 + md); b5 = x1 + x2; float temp = ((b5 + 8)>>4); temp = temp /10; return temp; } // Calculate pressure given up// calibration values must be known// b5 is also required so bmp085GetTemperature(...) must be called first.// Value returned will be pressure in units of Pa.long bmp085GetPressure(unsigned long up){ long x1, x2, x3, b3, b6, p; unsigned long b4, b7; b6 = b5 - 4000; // Calculate B3 x1 = (b2 * (b6 * b6)>>12)>>11; x2 = (ac2 * b6)>>11; x3 = x1 + x2; b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2; // Calculate B4 x1 = (ac3 * b6)>>13; x2 = (b1 * ((b6 * b6)>>12))>>16; x3 = ((x1 + x2) + 2)>>2; b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; b7 = ((unsigned long)(up - b3) * (50000>>OSS)); if (b7 < 0x80000000) p = (b7<<1)/b4; else p = (b7/b4)<<1; x1 = (p>>8) * (p>>8); x1 = (x1 * 3038)>>16; x2 = (-7357 * p)>>16; p += (x1 + x2 + 3791)>>4; long temp = p; return temp; } // Read 1 byte from the BMP085 at 'address'char bmp085Read(unsigned char address) { unsigned char data; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP085_ADDRESS, 1); while(!Wire.available()) ; return Wire.read(); } // Read 2 bytes from the BMP085// First byte will be from 'address'// Second byte will be from 'address'+1int bmp085ReadInt(unsigned char address) { unsigned char msb, lsb; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP085_ADDRESS, 2); while(Wire.available()<2) ; msb = Wire.read(); lsb = Wire.read(); return (int) msb<<8 | lsb; } // Read the uncompensated temperature valueunsigned int bmp085ReadUT(){ unsigned int ut; // Write 0x2E into Register 0xF4 // This requests a temperature reading Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x2E); Wire.endTransmission(); // Wait at least 4.5ms delay(5); // Read two bytes from registers 0xF6 and 0xF7 ut = bmp085ReadInt(0xF6); return ut; } // Read the uncompensated pressure valueunsigned long bmp085ReadUP(){ unsigned char msb, lsb, xlsb; unsigned long up = 0; // Write 0x34+(OSS<<6) into register 0xF4 // Request a pressure reading w/ oversampling setting Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x34 + (OSS<<6)); Wire.endTransmission(); // Wait for conversion, delay time dependent on OSS delay(2 + (3<<OSS)); // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB) msb = bmp085Read(0xF6); lsb = bmp085Read(0xF7); xlsb = bmp085Read(0xF8); up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS); return up; } void writeRegister(int deviceAddress, byte address, byte val) { Wire.beginTransmission(deviceAddress); // start transmission to device Wire.write(address); // send register address Wire.write(val); // send value to write Wire.endTransmission(); // end transmission } int readRegister(int deviceAddress, byte address){ int v; Wire.beginTransmission(deviceAddress); Wire.write(address); // register to read Wire.endTransmission(); Wire.requestFrom(deviceAddress, 1); // read a byte while(!Wire.available()) { // waiting } v = Wire.read(); return v; } float calcAltitude(float pressureA){ float A = pressureA/101388; float B = 1/5.25588; float C = pow(A,B); C = 1 - C; C = C /0.0000225577; return C; } void bob() { int dev = 0x5A<<1; int data_low = 0; int data_high = 0; int pec = 0; i2c_start_wait(dev+I2C_WRITE); i2c_write(0x07); // readi2c_rep_start(dev+I2C_READ); data_low = i2c_readAck(); //Read 1 byte and then send ack data_high = i2c_readAck(); //Read 1 byte and then send ack pec = i2c_readNak(); i2c_stop(); //This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for tempsdouble tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)double tempData = 0x0000; // zero out the dataint frac; // data past the decimal point// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte. tempData = (double)(((data_high & 0x007F) << 8) + data_low); tempData = (tempData * tempFactor)-0.01; celcius = tempData - 273.15; float fahrenheit = (celcius*1.8) + 32; Serial.print("Celcius: "); Serial.println(celcius); Serial.print("Fahrenheit: "); Serial.println(fahrenheit); delay(1000); // wait a second before printing again }
Problems Encountered: The problems encountered while making this project where combining the different code codes especially the I2C master libraries. In order to make this project work i had to pull together three different codes to make one. In order to do this I had to combine different codes and change variables that would then mess up another part of the code.