Author |
Message |
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 12:50am 15 May 2015 |
Copy link to clipboard |
Print this post |
|
This post describes a Micromite-based data logger. The project uses Big Mick's MuP Micromite board, a DHT22 for measuring humidity, a DS18B20 for temperature, and a Sparkfun BMP180 breakout board for logging atmospheric pressure.
The data is logged on a Sparkfun OpenLog device equipped with a 16GB micro flash card. The setup includes a RTC and all devices are powered using 3.3 volts.
The following is the source code for this data logger. The code for the BMP180 pressure sensor uses part of the code posted by TassyJim in a different thread. The data is saved approximately every minute in a comma-separated-variable (CSV) data file which includes the calendar date and local civil time for each measurement. Temperature is logged in degrees F and atmospheric pressure in inches of mercury.
option autorun on
' data_logger.bas
' May 15, 2015
' MMBasic version 4.6B
' thanks to TassyJim for the BMP code
' RTC pin-to-CPU pin wiring
' -------------------------
' SCL ==> I2C
' SCL ==> I2C
' sensor pin-to-CPU pin wiring
' ----------------------------
' DS18B20 ==> 15
' DHT22 ==> 16
' BMP180 ==> I2C
' OpenLog pin-to-CPU wiring
' -------------------------
' TXD ==> 22 (COM1: receive)
' RXD ==> 21 (COM1: transmit)
'''''''''''''''''''''''''''''
' store data from BMP180
DIM BMPData(2)
' calibration data array
DIM cal(11)
' over sampling (0 to 3)
oss = 3
' start of 11 calibration values
BMP180calMEM = &HAA
' BMP180 address
BMP180address = &H77
' BMP180 control register
BMP180control = &HF4
' BMP180 temperature command
BMP180temp = &H2E
' BMP180 pressure command
BMP180pres = &H34
' adjust command for oversampling
BMP180pres = BMP180pres + oss*&H40
' register for results of reading
BMP180reading = &HF6
' enable I2C. use slow speeds for long leads
I2C OPEN 400, 200
' extract calibration constants
z = calibrate_bmp180()
open "COM1:9600" as #5
' initial five second pause
pause 5000
do
' extract current epoch from RTC
rtc gettime
hours = val(left$(time$, 2))
minutes = val(mid$(time$, 4, 2))
seconds = val(right$(time$, 2))
time_hrs = hours + minutes / 60.0 + seconds / 3600.0
' format date in mm/dd/yyyy form
wrk_month$ = mid$(date$, 4, 2)
wrk_day$ = left$(date$, 2)
wrk_year$ = right$(date$, 4)
usa_date$ = wrk_month$ + "-" + wrk_day$ + "-" + wrk_year$
' temperature (pin 15)
temp_c = ds18b20(15)
temp_f = 1.8 * temp_c + 32.0
' humidity (pin 16)
dht22 16, temp, humidity
' atmospheric pressure
atmos = pressure(oss)
' print current data
print #5, usa_date$; ", "; time$; ","; time_hrs; ","; temp_f; ","; humidity; ","; atmos
'print usa_date$; ","; time$; ","; time_hrs; ","; temp_f; ","; humidity; ","; atmos
' pause 60 seconds between measurements
pause 60000
loop
close #5
end
'''''''''''''''''''''''''
FUNCTION calibrate_bmp180()
' extract bmp180 calibration constants
LOCAL n, calMEM
calMEM= BMP180calMEM
FOR n = 1 TO 11
' first calibration location
I2C WRITE BMP180address, 0, 1, calMEM
PAUSE 1
I2C READ BMP180address, 0, 2, BMPData(0)
cal(n) = BMPData(0)*256 + BMPData(1)
IF (n < 4 OR n > 6) THEN
' need to convert some to signed numbers
IF (cal(n) > 32767) THEN
cal(n) = cal(n) - 65536
ENDIF
ENDIF
PAUSE 1
' advance to the next calibration location
calMEM = calMEM + 2
NEXT n
END FUNCTION
''''''''''''''''''''
FUNCTION pressure(oss)
' atmospheric pressure in inches of mercury
LOCAL UT, UP, x1, x2, x3, b5, b6, b7, pres, p
pres = BMP180pres + oss * &H40
I2C WRITE BMP180address, 0, 2, BMP180control, BMP180temp
PAUSE 5
I2C WRITE BMP180address, 0, 1, BMP180reading
I2C READ BMP180address, 0, 2, BMPData(0)
UT = BMPData(0) * 256 + BMPData(1)
I2C WRITE BMP180address, 0, 2, BMP180control, pres
' different oversampling requires different reading times
IF (oss = 0) THEN
' ulta low power
PAUSE 5
ELSEIF (oss = 1) THEN
' standard
PAUSE 8
ELSEIF (oss = 2) THEN
' high resolution
PAUSE 14
ELSE
' ulta high resolution
PAUSE 26
ENDIF
I2C WRITE BMP180address, 0, 1, BMP180reading
I2C READ BMP180address, 0, 2, BMPData(0)
UP = BMPData(0) * 256 + BMPData(1)
I2C WRITE BMP180address, 0, 1, BMP180reading+2
I2C READ BMP180address, 0, 1, BMPData(0)
UP = (UP * 256 + BMPData(0)) / 2^(8 - oss)
' calculate true temperature
x1 = INT((UT - cal(6)) * cal(5) / 32768)
x2 = INT(cal(10) * 2048 / (x1 + cal(11)))
b5 = x1 + x2
t = INT((b5 + 8) / 16) / 10
' calculate true atmospheric pressure
b6 = b5 - 4000
x1 = INT((cal(8) * (b6 * b6 / 4096)) / 2048)
x2 = INT(cal(2) * b6 / 2048)
x3 = x1 + x2
b3 = INT(((cal(1) * 4 + x3) * 2^oss + 2) / 4)
x1 = INT(cal(3) * b6 / 8192)
x2 = INT((cal(7) * (b6 * b6 / 4096)) / 65536)
x3 = INT(((x1 + x2) + 2) / 4)
b4 = INT(cal(4) * x3 / 32768 + cal(4))
b7 = INT((UP - b3) * (50000 / 2^oss))
p = INT((b7 * 2) / b4)
x1 = INT(INT(p / 256) * INT(p / 256))
x1 = INT((x1 * 3038) / 65536)
x2 = INT((-7357 * p) / 65536)
pressure = 0.01 * INT(p + (x1 + x2 + 3791) / 16) / 33.86388158
END FUNCTION
The following is a picture of the data logger. The 3.3 volt power supply, sensors and OpenLog are located on the large breadboard. From left to right; the DHT22, the DS18B0, the RTC, the BMP180 and the OpenLog device.
A USB-to-TTL interface is located on the bottom left and Big Mick's MuP board is on the bottom right.
|
|
viscomjim Guru
Joined: 08/01/2014 Location: United StatesPosts: 925 |
Posted: 05:30am 15 May 2015 |
Copy link to clipboard |
Print this post |
|
cdeagle, this is great stuff. I am glad to see another great project (including code)! What are your plans with this? Are you going to put it in an enclosure and use it for something specific? What are you doing with the data on the sd card, excel or something like that? Again, great work!!!! |
|
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 07:12am 15 May 2015 |
Copy link to clipboard |
Print this post |
|
Thanks for the positive feedback.
Eventually I plan to put the prototype in an enclosure so that I can monitor the dynamic outside weather we have here on the Space Coast of Florida. Hopefully no hurricanes this year! And perhaps add additional sensors.
I have an SD card reader that I use to download the CSV data files. I then plot the different data items as a function of time using a program called Grapher. I stop the program from running with a control-C. The use of the MMBasic OPTION autorun ON command starts a new log each time power is re-applied.
Here's an excerpt from a typical data file. Column 1 is the calendar date, column 2 is the local civil time, column 3 is the elapsed time since midnight in hours, column 4 is the temperature in degrees F, column 5 is the relative humidity and the last column is the barometric pressure in inches of mercury. This data is relatively "stable" because it was measured inside my house. Of course, the outside data should show more variations.
05-14-2015, 15:55:14, 15.9206, 78.8, 50.8, 30.2104
05-14-2015, 15:55:45, 15.9292, 78.8, 52.1, 30.2127
05-14-2015, 15:56:15, 15.9375, 78.8, 52, 30.2095
05-14-2015, 15:56:46, 15.9458, 78.8, 52, 30.2101
05-14-2015, 15:57:15, 15.9542, 78.8, 52, 30.2086
05-14-2015, 15:57:46, 15.9628, 78.8, 51.9, 30.213
05-14-2015, 15:58:16, 15.9711, 78.8, 51.8, 30.2112
05-14-2015, 15:58:47, 15.9794, 78.8, 51.7, 30.2098
05-14-2015, 15:59:16, 15.9878, 78.8, 51.9, 30.2098
05-14-2015, 15:59:46, 15.9961, 78.8, 51.8, 30.2098
05-14-2015, 16:00:17, 16.0047, 78.8, 52, 30.2083
I'll post some plots later.
|
|
OA47
Guru
Joined: 11/04/2012 Location: AustraliaPosts: 911 |
Posted: 08:28pm 15 May 2015 |
Copy link to clipboard |
Print this post |
|
cdeagle, can you explain why you are not using the DHT22 to read the temp?
GM |
|
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 11:41pm 15 May 2015 |
Copy link to clipboard |
Print this post |
|
Hi Graeme,
The main reason for using the DS18B20 sensor is the fact that I plan to eventually use a waterproof version of the sensor for outside data logging.
The DS18B20 also has a wider temperature measurement range (-55 C to 125 C) than the DHT22 (-40 C to 80 C). The DS18B20 has a default 12 bit temperature resolution (0.0625 deg C) while the DHT22 has a resolution of 0.1 deg C.
Hope this answers your question.
|
|
viscomjim Guru
Joined: 08/01/2014 Location: United StatesPosts: 925 |
Posted: 12:05am 16 May 2015 |
Copy link to clipboard |
Print this post |
|
cdeagle, Holy Smokes... another person in the state of Florida that uses the uMite. What are the odds... I wonder if there are more of us. I'm in the St. Pete, Clearwater area on the west coast. Where are you? |
|
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 12:22am 16 May 2015 |
Copy link to clipboard |
Print this post |
|
Hi Jim,
I'm in Cape Canaveral on the east coast. |
|
viscomjim Guru
Joined: 08/01/2014 Location: United StatesPosts: 925 |
Posted: 12:26am 16 May 2015 |
Copy link to clipboard |
Print this post |
|
And your up early on a Saturday morning also. |
|
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 12:30am 16 May 2015 |
Copy link to clipboard |
Print this post |
|
Up at 5 am every morning. Old (sleeping) habits are hard to break! |
|
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 07:57am 16 May 2015 |
Copy link to clipboard |
Print this post |
|
Here are several plots created using data from the data logger. They illustrate outdoor atmospheric conditions yesterday, May 15, 2015, at Cape Canaveral, Florida.
It was an overcast day with rain showers several times during the day.
|
|
cdeagle Senior Member
Joined: 22/06/2014 Location: United StatesPosts: 261 |
Posted: 07:58am 22 May 2015 |
Copy link to clipboard |
Print this post |
|
Here's a version of the source code which includes the BH1750 ambient light sensor.
Thanks to TassyJim for the BH1750 source code.
option autorun on
' data_logger.bas
' May 22, 2015
' MMBasic version 4.6B
' thanks to TassyJim for the BMP and BH1750 code
' RTC pin-to-CPU pin wiring
' -------------------------
' SCL ==> I2C
' SCL ==> I2C
' sensor pin-to-CPU pin wiring
' ----------------------------
' DS18B20 ==> 15
' DHT22 ==> 16
' BMP180 ==> I2C
' BH1750 ==> I2C
' OpenLog pin-to-CPU wiring
' -------------------------
' TXD ==> 22 (COM1: receive)
' RXD ==> 21 (COM1: transmit)
'''''''''''''''''''''''''''''
' ----------------
' setup for BMP180
' ----------------
' store data from BMP180
DIM BMPData(2)
' calibration data array
DIM cal(11)
' over sampling (0 to 3)
oss = 3
' start of 11 calibration values
BMP180calMEM = &HAA
' BMP180 address
BMP180address = &H77
' BMP180 control register
BMP180control = &HF4
' BMP180 temperature command
BMP180temp = &H2E
' BMP180 pressure command
BMP180pres = &H34
' adjust command for oversampling
BMP180pres = BMP180pres + oss*&H40
' register for results of reading
BMP180reading = &HF6
' enable I2C. use slow speeds for long leads
I2C OPEN 400, 200
' extract calibration constants
z = calibrate_bmp180()
' ----------------
' setup for BH1750
' ----------------
Dim LightData(2)
' BH1750 address
BH1750address = &H23
' open comm port
open "COM1:9600" as #5
' initial five second pause
pause 5000
do
' extract current epoch from RTC
rtc gettime
hours = val(left$(time$, 2))
minutes = val(mid$(time$, 4, 2))
seconds = val(right$(time$, 2))
time_hrs = hours + minutes / 60.0 + seconds / 3600.0
' format date in mm/dd/yyyy form
wrk_month$ = mid$(date$, 4, 2)
wrk_day$ = left$(date$, 2)
wrk_year$ = right$(date$, 4)
usa_date$ = wrk_month$ + "-" + wrk_day$ + "-" + wrk_year$
' temperature (pin 15)
temp_c = ds18b20(15)
temp_f = 1.8 * temp_c + 32.0
' humidity (pin 16)
dht22 16, temp, humidity
' atmospheric pressure
atmos = pressure(oss)
' ambient light
light = lux()
' print current data
print #5, usa_date$; ", "; time$; ","; time_hrs; ","; temp_f; ","; humidity; ","; atmos; ","; light
' uncomment this line to send data to the screen
' print usa_date$; ","; time$; ","; time_hrs; ","; temp_f; ","; humidity; ","; atmos; ","; light
' pause 60 seconds between measurements
pause 60000
loop
close #5
end
'''''''''''''''''''''''''
FUNCTION calibrate_bmp180()
' extract bmp180 calibration constants
LOCAL n, calMEM
calMEM= BMP180calMEM
FOR n = 1 TO 11
' first calibration location
I2C WRITE BMP180address, 0, 1, calMEM
PAUSE 1
I2C READ BMP180address, 0, 2, BMPData(0)
cal(n) = BMPData(0)*256 + BMPData(1)
IF (n < 4 OR n > 6) THEN
' need to convert some to signed numbers
IF (cal(n) > 32767) THEN
cal(n) = cal(n) - 65536
ENDIF
ENDIF
PAUSE 1
' advance to the next calibration location
calMEM = calMEM + 2
NEXT n
END FUNCTION
''''''''''''''''''''
FUNCTION pressure(oss)
' atmospheric pressure in inches of mercury
LOCAL UT, UP, x1, x2, x3, b5, b6, b7, pres, p
pres = BMP180pres + oss * &H40
I2C WRITE BMP180address, 0, 2, BMP180control, BMP180temp
PAUSE 5
I2C WRITE BMP180address, 0, 1, BMP180reading
I2C READ BMP180address, 0, 2, BMPData(0)
UT = BMPData(0) * 256 + BMPData(1)
I2C WRITE BMP180address, 0, 2, BMP180control, pres
' different oversampling requires different reading times
IF (oss = 0) THEN
' ulta low power
PAUSE 5
ELSEIF (oss = 1) THEN
' standard
PAUSE 8
ELSEIF (oss = 2) THEN
' high resolution
PAUSE 14
ELSE
' ulta high resolution
PAUSE 26
ENDIF
I2C WRITE BMP180address, 0, 1, BMP180reading
I2C READ BMP180address, 0, 2, BMPData(0)
UP = BMPData(0) * 256 + BMPData(1)
I2C WRITE BMP180address, 0, 1, BMP180reading+2
I2C READ BMP180address, 0, 1, BMPData(0)
UP = (UP * 256 + BMPData(0)) / 2^(8 - oss)
' calculate true temperature
x1 = INT((UT - cal(6)) * cal(5) / 32768)
x2 = INT(cal(10) * 2048 / (x1 + cal(11)))
b5 = x1 + x2
t = INT((b5 + 8) / 16) / 10
' calculate true atmospheric pressure
b6 = b5 - 4000
x1 = INT((cal(8) * (b6 * b6 / 4096)) / 2048)
x2 = INT(cal(2) * b6 / 2048)
x3 = x1 + x2
b3 = INT(((cal(1) * 4 + x3) * 2^oss + 2) / 4)
x1 = INT(cal(3) * b6 / 8192)
x2 = INT((cal(7) * (b6 * b6 / 4096)) / 65536)
x3 = INT(((x1 + x2) + 2) / 4)
b4 = INT(cal(4) * x3 / 32768 + cal(4))
b7 = INT((UP - b3) * (50000 / 2^oss))
p = INT((b7 * 2) / b4)
x1 = INT(INT(p / 256) * INT(p / 256))
x1 = INT((x1 * 3038) / 65536)
x2 = INT((-7357 * p) / 65536)
pressure = 0.01 * INT(p + (x1 + x2 + 3791) / 16) / 33.86388158
END FUNCTION
''''''''''''
function lux()
' read ambient light data from BH1750
' power on
I2C write BH1750address, 0, 1, &H01
pause 50
' 1 lx scaling, single reading (H-resolution mode)
I2C write BH1750address, 0, 1, &H20
pause 150
I2C Read BH1750address, 0, 2, LightData(0)
lux = (LightData(0) * 256.0 + LightData(1)) / 1.2
end function
|
|