Switch, Case statements


Recommended Posts

Hi,

I am a beginner in any kind of scripting. I am trying to write a sequence to control the temperature of a reactor. I wish to heat until 105 C and then turn off the heat and then get down to my setpoint of 80 C by heating when temp is below 78 and stopping heat when temp is above 82. These parameters can be changed if this is not the most efficient way to do this.

Here is a copy of my code so far...I can turn off the heat after 105 C but daqfactory gets hung up when i reach my switch, case statements:

output = 1
private n = 0
while(1) <----Why do you have to put a 1?
	   read(internal)
	   waitfor(internal[0]>105,5)
	   while(n<4)
			 read(internal)
			 if(internal[0]>105)
					  n=n+1
			 endif
			 delay(10)
	   endwhile
output=0
delay(10)
endwhile

read internal
waitfor(internal[0]<79,5)
while(n<4)
	   read(internal) <-----I think im being redundant here
	   if(internal[0]<79
			   n=n+1
	   endif
	   delay(10)
endwhile
output=1

switch
case(internal[0]>82)
	output=0
case(internal[0]<78)
	output=1

waituntil(24hrs)<------basically I want my temp at 80C for 24 hours once this temp is reached
output = 0

If anyone can give me any suggestions as to what is holding up my code it would be greatly appreciated.

Link to comment
Share on other sites

So you want to heat to 105 (and get 5 measurements there), then cool to 80 and control at 80 (with 2 degrees of hystersis) for 24 hours, yes? First, I'd have the internal channel simply read itself by setting the Timing to something like 1. Then it becomes:

output = 1
while (min(internal[0,4]) < 105)
   delay(5)
endwhile
// now cool
waitfor(max(internal[0,4]) < 79)
// now control:
private starttime = systime()
// control for one day:
while (systime() < starttime + 86400)
   if (internal[0] < 78)
	  output = 1
   endif
   if (internal[0] > 82)
	  output = 0
   endif
   delay(5)
endwhile

That is about it. The details:

a) doing min(internal[0,4]) returns the minimum of the last 5 readings. If that value is > 105, then all 5 readings are > 105. Same with max, but in reverse.

B) in your sequence, you do waituntil(24hrs). That actually is not the right statement and is in the wrong syntax anyway ("hrs" is not valid). waituntil() waits for a particular time. If you want to pause for 24 hours, you want delay(86400). 86400 is the number of seconds in a day. In your case, you want to control during this time, so you have to create a loop that runs until the proper time and continues to control as I did.

c) I could have used switch, but a couple ifs work just as well. switch is better if you have a long string of ifs and general replaces the if/then/elseif/then/elseif sort of structure.

d) you have to put 1 in the while loop to have it continue indefinitely. 1 means "true", which means the loop runs forever. This is why the sequence never advances past heating to 105. Really in your sequence, you don't need the outer loop with the while(1)

Link to comment
Share on other sites

Thank you for such a quick response. I will try out your code sometime today. I only have two questions.

1) Does the first part of the code min(internal[0,4]<105 protect against noise spikes? I want to read internal at least 5 times with a delay of about 10 seconds each time and wait until all 5 times the temp is above 105. This way I can be sure that I am getting a true reading. It is okay for my process to not cool down as soon as it reaches 105. I want to make sure it is the correct temperature first.

2) If I wanted to run for 26 hours then it would just be

while (systime() < starttime + 93600)?

Thank you

Link to comment
Share on other sites

I tried the code but am unable to run the sequence because of the line 6 error. It says invalid number of parameters. I think that I am not reading the internal channel. When I created the internal channel I gave it a timing of 1. If I create another sequence to read this channel then do I just put:

read(internal)

Then how do I connect the two, or do I just run them simultaneously?

Thank you so much for your help!

Link to comment
Share on other sites

OK, first post:

1) the min() and max() stuff I did does avoid noise spikes. They basically say that 5 readings in a row must be above or below the given threshold. If any reading isn't, its not considered true. If you have a timing of 1 in your channel and want 5 readings spaced 10 seconds apart, you'll actually want [0,49], though this really means all the readings in the last 50 seconds must be above the threshold. Alternatively, set your timing to 10.

2) Yes, or just write it as: while (systime() < starttime + 3600 * 26) then you can just change the 26 to however many hours you want. A little easier to read. I just know that 86400 is the number of seconds in a day because its such a common number.

Now to your next post:

That is a typo on my part. The waitfor() function requires two parameters, so it should be:

waitfor(max(internal[0,4]) < 79,1)

I actually rarely use this function so just plain forgot. If you change your timing to 10, you should change the 1 to 10. There's no reason to check faster than the data is coming in. As for read(internal), the only reason to use read() is if you need to read a channel at varying intervals. In your case, just have the channel read every 1 or 10 seconds and let it alone.

Link to comment
Share on other sites

Sorry to keep bothering you, but I ran the sequence and it worked the first time, but then I played around with the set values and something went wrong.

for the

while(min(internal[0,4]<105........shouldn't this be >105?????

I tried it both ways and the program still doesn't run.

Basically my current internal temp was 28, so I ran the sequence with the following script:

output=1

while(min(internal[0,4]>20)

delay(5)

endwhile

output=0

Shouldn't this sequence wait until the minimum of the last five values is greater than 20, delay for 5 seconds, come out of the while and then set my output to 0 so that the temp can cool down????

Link to comment
Share on other sites

You have to watch your parenthesis. You changed it from:

(min(internal[0,4]) > 20)

to

(min(internal[0,4] > 20)

This is wrong on two accounts, one you are missing a closing paren, and two, the >20 is inside the min, so it is actually going to compare each value to 20 and if the minimum of all that is 1, it goes through. This actually is not a problem because the expression is associative, just a little slower. However, not having the ) won't work.

And no, it should be < 105. We are waiting until it is > 105, and that means we want to stay in the loop while it is < 105. This is opposite to waituntil() In fact, waituntil(x,y) is essentially this:

while(!x)
   delay(y)
endwhile

! is not, and not > 105 is basically < 105 (really its <=)

Link to comment
Share on other sites

Sorry, in my last post I forgot the parentheses, but in my code they were there.

Basically i've changed the code a bit to this:

1) output = 1

2) waitfor(min(internal[0,49])>30,1) <----I assume this is just to wait until the minimum of my last 50 points is greater than 30. My internal channel timing is still one.

3) output=0 <---once 2) evaluates to true then I want to turn output off

4) waitfor(max(internal[0,49])<28,1) <---here I want to wait until the maximum of my last 50 points is less than 28.

5) the rest of the code is the same as yours when I declare private starttime.

When I run the above code I get an output of 1 initially, I bring the temp above 30 and after approx 50 seconds I see my output is set to 0. My code then gets hung up on line 4: waitfor(max.....)

I don't understand why the code is getting hung up here, when it is the same logic as in line 2. It will not jump to the next line.

Thank you again

Link to comment
Share on other sites

Its going to stick at 4 until internal drops below 28 for 50 readings in a row. I personally never use waitfor(). Its nice because its one line, but I find doing a regular while loop better because you can step through it and put a break point in the middle. So, if the sequence seems to hang, you can put a break point at the delay() and then in the command alert window do:

? max(internal[0,49])

and see what it is. The while that is the same as the waitfor() would be:

while(max(internal[0,49]) &gt;= 28)
   delay(1)
endwhile

Link to comment
Share on other sites

  • 2 weeks later...

Hi again,

I've changed all of my thinking and am just trying your code now:

output=1
while(min(internal[0,4])&lt;105)
   delay(5)
endwhile
output=0

waitfor(max(internal[0,4])&lt;79)

private starttime = systime()
while(systime()&lt;starttime + 3600*24)
   if (internal[0]&lt;78)
	  output=1
   endif
   if (internal[0]&gt;82)
	  output=0
   endif
   delay(5)
endwhile

So basically I run this sequence with a starting temp of around 25C. I manually change the internal channel gain to raise it to about 120C. As soon as I do this, I wait for about 10 seconds and my output doesn't switch to 0????? The last 20 seconds were definitely above 105 and thus it should come out of the loop. Nevertheless, I sometimes get the output to go to 0 by making a few adjustments (usually just messing with the code) and then i get caught in the second loop. Once I get output to 0, I again change the gain to lower the temp to 50C. After about a minute of waiting or more, I don't get out of the loop again???? I know for a fact that the temp is below the 79 so why won't I come out of the loop.

I even tried your waituntil command and it still has some glitches. This is such a simple code, yet it doesn't work for me. How can it not come out of the loop after the last 5 readings were below 79C????

Thanks

Link to comment
Share on other sites

1) watch your indentation. Its not just a pet peeve, but rather scripting 101. As you get more advanced, it will become more critical. I have fixed the indentation for you.

2) I had a typo in my original script. It should be: waitfor(max(internal[0,4])<79,5)

3) Other than that, I don't see anything wrong, and I created a sample that shows it working properly. To change internal, click on it in page_0. Then just wait and output should follow. Remember, though, that output will stay 0 until internal drops below 78, not 79.

od_sample.ctl

Link to comment
Share on other sites

Thank you. I will try it again. I think that by me not creating a test internal, and by manually changing the gains that I am messing up the readings. I did ?max(internal[0,4]) and I got a value higher than 105..it was 134, but it didn't come out of the line. I will try it again when I manually actually increase the temperature with the heater. Do you think this is a reading issue???? I've added a breakpoint in the loop and saw that the max internal value was 135, without it stepping out of that line. I just don't get why it doesn't step out. ANyway, if you know of anything else I would appreciate it.

Quick question: In the daqfactory manual pg. 104/407

while(1)
   read(Pressure)
   if (Pressure[0] &gt; 50) // if pressure is too high
	  VacuumPump = 1 // start pump
	  while(Pressure[0] &gt; 50) // wait until pressure drops
		 delay(1)
		 read(Pressure) // read pressure again to check current value
	  endwhile
	  VacuumPump = 0 // then stop pump
   endif
   read(Temperature)
   if (Temperature[0] &lt; 30) // if temperature too low
	  Heater = 1 // turn on heater
	  while (Temperature[0] &lt; 30) // wait until warmer
		 delay(1)
		 read(Temperature)
	  endwhile
	  Heater = 0 // turn off heater
   endif
   delay(1)
endwhile

I've changed pressure to internal, but I can't get out of the while(1) line. I know what you told me before about it, but why doesn't this example work. ANyway, this is just a random question if you get the time.

Last thing, sorry.

I've seen you post on help with getting correct readings with thermocouples.

I have a type K thermocouple attached to a LJTick-InAmp to a Labjack U3-HV. My internal channel is 5, and external is 4. On the InAmp, i've given them a gain of 201 and an output offset of 1.25 V.

I've created a channel: LabJacktemp (ch 30 on the U3) to read the labjack internal temperature.

I've given it a conversion: LabJackinternal = Value - 273.

I've then created a display for this and I correctly read about 25C room temp.

My conversion for the internal and external channels is :

temperature = Type K(Value/201,LabJacktemp[0])

I then get readings of around 170C instead of around 27C or so. What did I do wrong???

Is there a labjack internal temperature channel already created in the system??

Thanks a bunch!

Link to comment
Share on other sites

I believe the internal temperature reading channel on the LabJack returns degrees K, not degrees C. The TypeK and other thermocouple functions expect CJC in degrees C, so subtract 273.15.

The latest version of DAQFactory (5.80) has a bit more information on thermocouples (and samples) in the DAQFactory-LabJack application guide. You can download an update at www.azeotech.com or from www.daqexpress.com if you are using Express.

Link to comment
Share on other sites

  • 3 weeks later...

Hi again,

I tried out my code with the labjack. I want to control a solid state relay. The labjack forum told me that in order to control it I must set my output channel (F106) as output low (meaning relay turns on and control current flows) or as input (control relay turns off and no current flows). I need to incorporate this into my code as the 1 and 0 outputs do nothing.

He suggested:

Section 7.1 of the DAQFactory-LabJack Application Guide shows how do control a digital output based on an input, but this is changing the line between output-high and output-low. I am not sure how you change it between input and output-low. I suspect the solution is to not use a DAQFactory channel, but rather just make calls to our driver. See Section 2.5 of the LabJack UD Driver for Windows Quick Reference, and I think it will look something like this:

if (Temperature[0] < 15)

ePut (DeviceNum, LJ_ioPUT_DIGITAL_BIT, 6, 0, 0) // Set FIO6 to output-low

endif

if (Temperature[0] > 22)

eGet (DeviceNum, LJ_ioGET_DIGITAL_BIT, 6, @FIO6Reading, 0) // Read FIO6 (which sets it to input)

endif

Is this right or do I use different calling functions?

Or do I use some of these?

LJ_ioGET_DIGITAL_BIT // Also sets direction to input.

LJ_ioGET_DIGITAL_BIT_DIR // Read direction without changing direction.

LJ_ioGET_DIGITAL_BIT_STATE // Read state without changing direction.

LJ_ioGET_DIGITAL_PORT // Also sets directions to input. Channel is starting bit. x1 is number of bits.

LJ_ioGET_DIGITAL_PORT_DIR // Does not change directions. Channel is starting bit. x1 is number of bits.

LJ_ioGET_DIGITAL_PORT_STATE // Does not change directions. Channel is starting bit. x1 is number of bits.

LJ_ioPUT_DIGITAL_BIT // Also sets direction to output.

LJ_ioPUT_DIGITAL_PORT // Also sets directions to output. Channel is starting bit. x1 is number of bits.

0-7 = FIO0-FIO7

8-15 = EIO0-EIO7

16-19 = CIO0-CIO3

AddRequest (DeviceNum, LJ_ioGET_DIGITAL_BIT, 2, 0, 0, 0) // Request a read from FIO2.

AddRequest (DeviceNum, LJ_ioGET_DIGITAL_PORT, 4, 0, 10, 0) // Request a read from FIO4-EIO5.

AddRequest (DeviceNum, LJ_ioPUT_DIGITAL_BIT, 3, 1, 0, 0) // Set FIO3 to output-high.

AddRequest (DeviceNum, LJ_ioPUT_DIGITAL_PORT, 14, 7, 5, 0) // Set EIO6-CIO2 to b00111 (=d7).

GoOne (DeviceNum)

GetResult (DeviceNum, LJ_ioGET_DIGITAL_BIT, 2, @Value) // Get the FIO2 read.

GetResult (DeviceNum, LJ_ioGET_DIGITAL_PORT, 4, @Value) // Get the FIO4-EIO5 read.

// A typical application might also get the other 2 results just to check for errors.

This one looks good:

AddRequest (DeviceNum, LJ_ioPUT_DIGITAL_BIT, 3, 1, 0, 0) // Set FIO3 to output-high.

Would I do something like:

while(min(internal[0,49] <105)

addrequest(1 (the device # i use), LJ_ioPUT_DIGITAL_BIT, x, x, x, x)

I don't know what to put for the X's.

THanks for your help and sorry for the mess. I just wanted to give you as much info as possible.

Link to comment
Share on other sites

I have tried this in the code and the sequence does not run. I get an error stating that the channel or function does not exist. THe error is for line 4 which is:

ePut(1,LJ_ioPUT_DIGITAL_BIT,6,0,0)//Set FI06 to output-low.

I have changed my output channel to channel 7 so that I may still see if I am getting through the code. Therefore, there is no assignment of any channel to FI06. I have done as labjack forum requested and did not specify that channel. Instead I am just calling the function.

Do I have to run any other functions before these, to assure that I am communicating with the labjack.

Link to comment
Share on other sites

Please review the beginning of the DAQFactory LabJack Application guide as this is critical for doing any script with the LabJack. Bottom line is that you need the using() and include() lines described there so that DAQFactory recognizes the function and the constants you are using.

Link to comment
Share on other sites

I see from the LabJack forum post that you tried that and it didn't help. Is your LabJack files actually stored in the path specified in the include()? I can start a new doc and just create a sequence with these lines:

using("device.labjack.")

include("c:\program files\labjack\drivers\labjackud.h")

ePut(0, LJ_ioPUT_DIGITAL_BIT, 6, 0, 0)

and the error I get is that no labjack is found (because I don't have one hooked up).

Try this:

At the command alert window, type in:

ePut()

You should get Incorrect number of parameters. If you do, then the using() is correct and executed. If not, then using() was never called.

Then try:

? LJ_ioPUT_DIGITAL_BIT

it should say 40. If not, then the include() didn't find the header file and that is your problem.

It has to be one or the other (or both).

Link to comment
Share on other sites

Thank you. As it turns out, I typed devide instead of device. Everything works now.

Sorry to bother you, but I have one more big question.

I am trying to also use a different version of daqfactory. It is DAQ Factory Control Standard V4.14, and the sequences work as tables. I would like to convert my code into this version as well. I cannot find any good table sequence tutorials or user guides. I am lost because I don't know how to use eGet and ePut there. None of the command sequences from that version seem to set labjack channels to low, high, etc.

My working code is as follows:

using("device.labjack.")

include("c:\program files\labjack\drivers\labjackud.h")

//Heat up to 105

while(min(internal[0,4])<105)

ePut(0, LJ_ioPUT_DIGITAL_BIT,6,0,0)//set FI06 to output-low

output=3.6

delay(1)

endwhile

//Cool to 80

while(max(internal[0,4])>80)

eGet(0, LJ_ioGET_DIGITAL_BIT,6,@FI06Reading,0)//set FI06 to input

output=0

delay(1)

endwhile

//Control for one day

private starttime = systime()

while(systime()<starttime + 3600*24)

if (internal[0]<78)

ePut(0, LJ_ioPUT_DIGITAL_BIT,6,0,0)

output=3.6

endif

if (internal[0]>82)

eGet(0, LJ_ioGET_DIGITAL_BIT,6,@FI06Reading,0)

output=0

endif

delay(5)

endwhile

THank you so much for your help

Link to comment
Share on other sites

I'll save you the trouble: you can't do it. 4.14 is probably 5 years old and predates the LabJack U3/UE9 series of devices, so there is no support for these devices. There also are no device functions even for the devices that release supports. Using 4.14 is a bit like still running on Windows 95 and expecting your new camera to be recognized.

Link to comment
Share on other sites

That actually sounds great! I hate that version anyway. I will try your recipee2 example. I will need to add a few lines for incorporating my code. Could I have done this from the beginning and not needed to write my old code? I'm just wondering, because your temperature recipee can pretty much do it. I know I have to tweak it again and add ePut and eGet.

If you have any suggestions on incorporating my code, it would be appreciated.

Thanks so much and for ALL your fast replies!

Link to comment
Share on other sites

Archived

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