Comparing Channel Array Values By Time


Recommended Posts

What is the best way to compare a channel value by time? For example, comparing the temperature reading from channel "temperature1" to the "temperature1" reading from 1 hour ago, or a day ago.

Making this comparison in a sequence or channel event, but if I have too many channel events its easy to lose track of where they are.

global temp1byHour

temp1byHour=read(temperature1)(SysTime()-3600)

while(1)

delay(3600)

endwhile


global temp1byHour
temp1byHour=channel.Read(temperature1)(SysTime()-3600)
while(1)
delay(3600)
endwhile
[/CODE]

To display this, I need to assign it to a variable (global temp1byHour) or an object (class)

I get the error "all channels and function must start with a letter, I must have the "read(temperature)" wrong.

What is the correct way to do this?

Thanks

Link to comment
Share on other sites

Well, first:

read(temperature1)(SysTime()-3600)

is not valid for a number of reasons. 1) read(temperature1) is a function that returns nothing, and 2) there isn't anything in DAQFactory that returns a function as a variable like Javascript, so you can't do ()(). You can do ()[] if the result is an array, but in this case it isn't. read() just triggers the read of the given channel

Second, you have an infinite while loop that does nothing. That's ok in a sequence, though it will do nothing, but should never be in an event as it will hang that timing loop.

Fortunately, the answer is quite simple and can be placed right in the expression for the component. For example, to get the change in temperature between now and 1 hour ago (for clarity, I'm going to call your channel t instead of temperature1):

(t[0] - t[t.time[0] - 3600, t.time[0]-3700])[0]

To explain:

t[0] is the most recent value.

t.time[0] is the time of that data point, which might not be the same as systime().

t[t.time[0] - 3600, t.time[0]-3700] is an array containing all the data points with a time stamp that is 1 hour to 1 hour and 100 seconds before the most recent data point.

Subtracting that array from t[0] results in an array with the delta for each of those points. But we only want the first, so we put parenthesis around the whole expression and do [0] on the result which gives us the most recent reading.

We have to do this range thing because it is very unlikely that there is a data point at EXACTLY 3600 seconds from the most recent data point. At least not to the microsecond, which is how precise DF records time. So, we have to specify a range and then just use the first result in that range. I suppose technically this would actually be better:

t[0] - (t[t.time[0] - 3600, t.time[0]-3700])[0]

as this would do math on scalars, not an array.

Note you can make the 3700 something smaller or larger as needed. I figured 100 seconds was big enough, but it depends on your data rate and reliability.

Link to comment
Share on other sites

This is really good and helpful!

For the array I can use:

(t[0] - t[t.time[0] - 3600, t.time[0]-3700])[0]

to get the difference or change in value over the past hour.

If I want to just read/display value of the last hour, I use:

(t[t.time[0] - 3600, t.time[0]-3700])[0]

Thank You

Link to comment
Share on other sites

If I want to make an room object, for multiple rooms/environments, where I wanted to monitor and control the conditions of CO2 level, Temperature, Humidity--and rate of change (or difference every hour). If I plan to have lots of rooms, it would be better to make objects to reuse.

I am trying to do in a sequence:


class room
local string Temp
local string Humid
local string co2
endclass
global lab1 = new(room)
lab1.Temp = Temp1 //Temp 1 is the channle name
lab1.Humid = HIH5031_humidity //HIH5031_humidity is channel name
lab1.co2 = co2sensor //co2sensor is channel name
class roomTempChange parent room
local string temphrch = Temp[0]-(Temp(Temp.Time[0]-3600, Temp.Time[0]-3700])[0]
endclass
[/CODE]

I want to call lab1.temphrch to show value in a component. But I have a problem with the derived class hrlyTempChange... Not sure what I did wrong.

Link to comment
Share on other sites

roomTempChange is derived from room, not lab1. Lab1 isn't a class, its an object. Room doesn't have any values in Temp, so the initialization of temphrch doesn't work the way you think.

I'm not quite sure why you are creating a derived class. I'd imagine you just want a room class, probably with a member function called tempChange:


class room
local string Temp
local string Humid
local string co2
function tempChange()
return Temp[0]-(Temp(Temp.Time[0]-3600, Temp.Time[0]-3700])[0]
endfunction
endclass
[/CODE]

Then you could call tempChange on any object you instantiated from that class, once you initialize temp and humidity.

Please note, doing:

lab1.temp = temp1

assigns the current history of temp1 to lab1.temp. It does not make lab1.temp automatically update with new values of temp1.

Link to comment
Share on other sites

Your right, it doesn't work the way I thought.

I want to be able to control the environmental conditions in 50 lab rooms, with the ability to set (control) conditions for each individual room (different) as well as uniquely. Meaning, I would like to hit a button (or condition) that turns the temperature control (and other) off. But I would also like to set each room individually. From my very limited understanding of OOP, I thought it would be better to control each room as an object.

I could be wrong. I think that I am lacking the structural understanding of how objects in my scenario should work together. I am not sure how the channels fit into room objects if they are all different.

Thanks

Link to comment
Share on other sites

It would make sense to use OOP, but channels aren't really an object, so if you assign a channel to a variable, the channel's history at that instant is copied to the variable, not a reference to the channel. There are two ways to do it:

1) store a string with the name of the appropriate channel. If you have multiples, I'd probably use a common prefix / postfix. You tell each object the prefix, and then it knows the various postfix options (temperature, humidity, etc).

2) don't use channels at all, use objects and scripted reads.

Link to comment
Share on other sites

Well, first:

read(temperature1)(SysTime()-3600)

is not valid for a number of reasons. 1) read(temperature1) is a function that returns nothing, and 2) there isn't anything in DAQFactory that returns a function as a variable like Javascript, so you can't do ()(). You can do ()[] if the result is an array, but in this case it isn't. read() just triggers the read of the given channel

Second, you have an infinite while loop that does nothing. That's ok in a sequence, though it will do nothing, but should never be in an event as it will hang that timing loop.

Fortunately, the answer is quite simple and can be placed right in the expression for the component. For example, to get the change in temperature between now and 1 hour ago (for clarity, I'm going to call your channel t instead of temperature1):

(t[0] - t[t.time[0] - 3600, t.time[0]-3700])[0]

To explain:

t[0] is the most recent value.

t.time[0] is the time of that data point, which might not be the same as systime().

t[t.time[0] - 3600, t.time[0]-3700] is an array containing all the data points with a time stamp that is 1 hour to 1 hour and 100 seconds before the most recent data point.

Subtracting that array from t[0] results in an array with the delta for each of those points. But we only want the first, so we put parenthesis around the whole expression and do [0] on the result which gives us the most recent reading.

We have to do this range thing because it is very unlikely that there is a data point at EXACTLY 3600 seconds from the most recent data point. At least not to the microsecond, which is how precise DF records time. So, we have to specify a range and then just use the first result in that range. I suppose technically this would actually be better:

t[0] - (t[t.time[0] - 3600, t.time[0]-3700])[0]

as this would do math on scalars, not an array.

Note you can make the 3700 something smaller or larger as needed. I figured 100 seconds was big enough, but it depends on your data rate and reliability.

How would I use the time reading by hour or say for yesterday from 0h to 23hr?

Link to comment
Share on other sites

No, because 14h isn't 50400, its whatever the absolute time is for today at 14:00 (something in the 1.3 billions). 15h - 14h therefore is just 3600, the number of seconds between 15:00 and 14:00 today.

If you want to do the mean from 2-3 today it would be:

Mean(co2sensor[14h, 15h])

while yesterday would be:

Mean(co2sensor[14h-86400, 15h-86400])

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.