The problem of multi-tasking. NI-3000
Nudge the, please, on the right idea how to solve the problem.
The controller works with three pairs of devices:
The problem appears when the need to handle events from all devices.
For example, the IO port gets a permanent event and starts the cycle. At the same moment, tuner sends a large amount of feedback and, accordingly, is required to disassemble the cycle by using the string character by character.
In such a situation, pressing buttons MIO reaction occurs with great delay.
Is it possible to have Netlink prioritize?
For example, to stop the implementation of all cycles, processing feedback, during the execution of Button_event.
Share your experience, how to solve these problems ?!
In advance thank you very much.
The controller works with three pairs of devices:
- port I/O > Relay Receiving event IO port starts the cycle lamp is flashing through the relay.
- T.Panel > Rs232, Tuner. Panel receives feedback (A complex algorithm with symbol-wise analysis of the string) and controls tuner.
- Mio4 > Rs232, Projector Feedback and control
The problem appears when the need to handle events from all devices.
For example, the IO port gets a permanent event and starts the cycle. At the same moment, tuner sends a large amount of feedback and, accordingly, is required to disassemble the cycle by using the string character by character.
In such a situation, pressing buttons MIO reaction occurs with great delay.
Is it possible to have Netlink prioritize?
For example, to stop the implementation of all cycles, processing feedback, during the execution of Button_event.
Share your experience, how to solve these problems ?!
In advance thank you very much.
Comments
Can you post the code you're having trouble with? That will help us help you.
Kevin D.
I correctly understand that while working cycle (triggered in the presence of the event in the IO port), a cycle that handles feedback from the tuner does not start?
For example, here are two of my piece of code:
******Port IO event handler*****
MODULE_NAME='signaliz' (DEV Relay, DEV io, DEV Panel) (***********************************************************) (***********************************************************) (* FILE_LAST_MODIFIED_ON: 04/04/2006 AT: 11:33:16 *) (***********************************************************) (* System Type : NetLinx *) (***********************************************************) (* REV HISTORY: *) (***********************************************************) (* $History: $ *) (***********************************************************) (* DEVICE NUMBER DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_DEVICE (***********************************************************) (* CONSTANT DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_CONSTANT sirena_countdown = 1 svet_countdown = 2 (***********************************************************) (* DATA TYPE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_TYPE (***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_VARIABLE non_volatile integer stateflag //TRUE когда сигнализация включена long countdowntimes[2] //long sirena_countdowntimes[2] (***********************************************************) (* LATCHING DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_LATCHING (***********************************************************) (* MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_MUTUALLY_EXCLUSIVE (***********************************************************) (* SUBROUTINE/FUNCTION DEFINITIONS GO BELOW *) (***********************************************************) (* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *) (* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *) (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START switch (stateflag) { case true: on[Panel,678] case false: off [Panel,678] } (***********************************************************) (* THE EVENTS GO BELOW *) (***********************************************************) DEFINE_EVENT button_event [Panel, 678] {push: { if (!stateflag) {on[Panel,678]} if (stateflag) {off[Panel,678]} }} channel_event [Panel, 678] { on: {stateflag = true} off: {stateflag = false} } channel_event [io,1] { on: { on[Panel, 680] // jотправить на панель "ворота открыты" countdowntimes[1] = 1000 countdowntimes[2] = 1000 timeline_create(svet_countdown,countdowntimes,2,timeline_relative,timeline_repeat) timeline_create(sirena_countdown,countdowntimes,2,timeline_relative,timeline_repeat)} off: { off [Panel,680] // отправить на панель "ворота закрыты" timeline_kill(sirena_countdown) timeline_kill(svet_countdown) off[relay,1] off[relay,2] } } timeline_event[svet_countdown] { //send_string 0, "'seq- ',itoa (timeline.sequence)" //send_string 0, "'rep- ',itoa (timeline.repetition)" if (timeline.sequence = 1) {on[relay,1]} if (timeline.sequence = 2) {off[relay,1]} } timeline_event[sirena_countdown] { stack_var waittime stack_var disabletime waittime = 250 //ожидать перед включением секунд x2 ... 30x2=60 disabletime = 250 // сколько звучать сирене до отключения с повторным включением, сек x2 send_string 0, "'seq- ',itoa (timeline.sequence)" send_string 0, "'rep- ',itoa (timeline.repetition)" SWITCH (stateflag) { case true: { if (timeline.repetition >= waittime ) { switch (timeline.sequence) { case 1: on[relay,2] case 2: off[relay,2] } } if (timeline.repetition >= waittime+disabletime ) {off[relay,2] TIMELINE_RELOAD(sirena_countdown,countdowntimes,2)} } case false: { off[relay,2]} } }******Tuner feedback handler*****
DATA_EVENT [dvReciv] { string: { //ячейка 101 - 1 строка //ячейка 102 - 2 строка //ячейка 103 - 3 строка //ячейка 104 - 4 строка if ( volButtonState = 0) { stack_var integer i stack_var char f_back [100] stack_var char razbor_simvol [80] stack_var char alone_char // // spc_char = null_str f_back = data.text if (find_string(data.text,'power=on!',1)) {SEND_COMMAND Panel,"'@PPN-Loading'" //отключение окна происходит в TPDesing //wait 50 // SEND_COMMAND Panel,"'@PPF-Loading'" } if (find_string(f_back,'display=',1)) {remove_string(f_back,'display=0',1) dispalay_string = f_back} else {dispalay_string = "dispalay_string,f_back"} //dispalay_string = mid_string(dispalay_string,3,100) if (length_string(dispalay_string) >=80 ) { //razbor_simvol = string_fn (dispalay_string) // send_char (razbor_simvol) string_send (dispalay_string) } send_string 0, "'display_string - ',dispalay_string" // SEND_COMMAND Panel, "'^TXT-101,0,',mid_string(dispalay_string,3,20)" // SEND_COMMAND Panel, "'^TXT-102,0,',mid_string(dispalay_string,23,20)" // SEND_COMMAND Panel, "'^TXT-103,0,',mid_string(dispalay_string,43,20)" // SEND_COMMAND Panel, "'^TXT-104,0,',mid_string(dispalay_string,63,20)" } else { send_string 0 , "'datavolstate = ',itoa(volButtonState)"} } } DEFINE_FUNCTION char[80] string_send (char fString [100]){ stack_var integer i stack_var integer n stack_var integer strLength stack_var razb_stroka [80] stack_var char specsimvol [3] strLength = length_string(fString) n = 0 for (i=4; i<=strLength; i++) { n = n + 1 razb_stroka = mid_string(fString,i,1) //spc_char = "spc_char,fb_char" // SEND_COMMAND Panel, "'^TXT-',itoa(i),',0,',fb_char" // // if (find_string(SpChar,"$EE,$82,$80",1)) { } switch (razb_stroka) { case $EE: specsimvol = mid_string(fString,i,3) select { active(specsimvol = "$EE,$82,$80"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,T'" i = i+2} active(specsimvol = "$EE,$82,$82"): {SEND_COMMAND Panel,"'^BMF-',itoa (n),',0,%F34%CF255%CTWhite'" //play SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,0041'" i = i+2} active(specsimvol = "$EE,$82,$97"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF255%CTWhite'" //play SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,0041'" i = i+2} active(specsimvol = "$EE,$82,$85"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,A'" i = i+2} active(specsimvol = "$EE,$82,$84"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,C'" i = i+2} active(specsimvol = "$EE,$82,$92"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,F'" i = i+2} active(specsimvol = "$EE,$82,$87"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,G'" i = i+2} active(specsimvol = "$EE,$82,$8E"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,I'" i = i+2} active(specsimvol = "$EE,$82,$89"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,L'" i = i+2} active(specsimvol = "$EE,$82,$93"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,M'" i = i+2} active(specsimvol = "$EE,$82,$8C"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,R'" i = i+2} active(specsimvol = "$EE,$82,$8F"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,S'" i = i+2} active(specsimvol = "$EE,$82,$8A"): {i = i+2} active(specsimvol = "$EE,$82,$8B"): {i = i+2} active(specsimvol = "$EE,$82,$81"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF255%CTWhite'" //pause SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,0043'" i = i+2} active(specsimvol = "$EE,$82,$83"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF255%CTWhite'" //stop SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,0042'" i = i+2} active(specsimvol = "$EE,$82,$94"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF255%CTWhite'" //play revers SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,004B'" i = i+2} active(specsimvol = "$EE,$82,$98"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF255%CTWhite'" //play revers SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,004B'" i = i+2} active(specsimvol = "$EE,$82,$99"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" //пустая заливка i = i+2} active(specsimvol = "$EE,$82,$9A"): {i = i+2} active(specsimvol = "$EE,$82,$88"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF00%CTBlack'" //Загогулина SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,0077'" i = i+2} active(specsimvol = "$EE,$82,$95"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF255%CTWhite'" //стрелка вправо SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,004E'" i = i+2} active(specsimvol = "$EE,$82,$96"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F34%CF255%CTWhite'" //стрелка влево SEND_COMMAND Panel, "'^UNI-',itoa(n),',0,004F'" i = i+2} active(specsimvol = "$EE,$82,$90"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF255%CTWhite'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,*'" i = i+2} active(specsimvol = "$EE,$82,$91"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" // пустая залика i = i+2} active(specsimvol = "$EE,$82,$8D"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,Z'" i = i+2} active(specsimvol = "$EE,$80,$80"): {i = i+8 //эти три символа лишь часть 9ти символьной строки SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,E'" SEND_COMMAND Panel, "'^TXT-',itoa(n+1),',0,N'" SEND_COMMAND Panel, "'^TXT-',itoa(n+2),',0,D'" n=n+2} } default: SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF255%CTWhite'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,',razb_stroka" break } } }P.S. If someone has the desire and free time, I can send the full project!
But, In the code present, there is a portion that deals with button feedback on the panel in which the feeback triggers a channel event (the feedback on the panel) then in turn starts a timeline. the timeline has two "ticks", each at one second intervals (1000ms) Those "Ticks" turn the relay on and off respectively. Then the whole thing repeats. So, you should see a relay pulsing on and off each second.
In addition, within the timeline there is essentially a pair of constants which are counters (each is set to 250 if I recall) The timeline is keeping track of how many times it has fired. So when the whole timeline has run 250 times, it shuts itself off by turning off the feedback channel, thus "killing" the timeline.
Is the thing I describe above seem to be killing your master? (not allowing it to do other stuff?)
1. If the IO port included - Includes relay 1 operation (1sec - On, 1 sec - off) ... endlessly until enabled port IO.
2. If a certain time has passed, and IO port still included - in addition to the work include Relay2.
3. button_event [Panel, and 678] and channel_event [Panel, 678] - a button on the panel, which allows you to disable Relay2.
I also think that the main problem in this module. But, to be confirmed more experienced programmers that this solution of the problem "kills" the Master.
switch (razb_stroka) { case $EE: specsimvol = mid_string(fString,i,3) select { active(specsimvol = "$EE,$82,$80"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,T'" i = i+2}But I don't think that will include anything more than "specsimvol = mid_string(fString,i,3)" as part of the first case. And it will keep executing this whole select active section as part of the default case. You may want to add another layer of braces like this:
switch (razb_stroka) { case $EE: { specsimvol = mid_string(fString,i,3) select { active(specsimvol = "$EE,$82,$80"): {SEND_COMMAND Panel,"'^BMF-',itoa(n),',0,%F19%CF00%CTBlack'" SEND_COMMAND Panel, "'^TXT-',itoa(n),',0,T'" i = i+2}Yeah, I believe a case with out braces after will only execute the 1st line of code after where as all lines will exectute if enclosed in braces. Similar to how code after a Wait works. You would think the compiler would see that as a malformed switch case and not compile though.
However, this part of the code itself operates.
The problem comes when you need to handle both events IO port and feedback from tuner.
Or something I do not to understand?
This triggers an infinite loop and the system can not respond quickly to other commands.
I think we should try to put the code handling events IO port in the "buffer" ... and return to its implementation only if the controller has a free system time.
But, I do not know how to do it correctly. I will try....
I would appreciate any advice or example code.
If I succeed, I'll show how I solved the problem
Can you post the code in which the infinite loop occurs? Then perhaps we can help.
I will repeat it (remove all unnecessary and translated into English commentary)
MODULE_NAME='signaliz' (DEV Relay, DEV io, DEV Panel) DEFINE_CONSTANT Siren_countdown = 1 flash_countdown = 2 DEFINE_VARIABLE non_volatile integer stateflag //TRUE then Signaling is ON long countdowntimes[2] (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START //Check the status of the buttons on the touch panel switch (stateflag) { case true: on[Panel,678] case false: off [Panel,678] } (***********************************************************) (* THE EVENTS GO BELOW *) (***********************************************************) DEFINE_EVENT (**************Using the button on the touch panel****************) button_event [Panel, 678] {push: { if (!stateflag) {on[Panel,678]} if (stateflag) {off[Panel,678]} }} channel_event [Panel, 678] { on: {stateflag = true} off: {stateflag = false} } (************End of using the button on the touch panel*********) //Check the state of the port IO1 channel_event [io,1] { // If channel is on - Create a timer that will trigger the relay. on: { on[Panel, 680] // Send to panel "Door open" countdowntimes[1] = 1000 countdowntimes[2] = 1000 timeline_create(flash_countdown,countdowntimes,2,timeline_relative,timeline_repeat) timeline_create(siren_countdown,countdowntimes,2,timeline_relative,timeline_repeat)} off: { off [Panel,680] // Send to panel "Door close" timeline_kill(siren_countdown) timeline_kill(flash_countdown) off[relay,1] off[relay,2] } } timeline_event[flash_countdown] { //relay1 - 1Sec ON, 1 Sec OFF if (timeline.sequence = 1) {on[relay,1]} if (timeline.sequence = 2) {off[relay,1]} } timeline_event[siren_countdown] { stack_var waittime stack_var disabletime waittime = 250 //Waiting time before switching Relay2 disabletime = 250 // Working time Relay2, before disconnecting and reconnecting //If button on the touch Panel is on - start using Relay2 SWITCH (stateflag) { case true: { if (timeline.repetition >= waittime ) { switch (timeline.sequence) { case 1: on[relay,2] case 2: off[relay,2] } } if (timeline.repetition >= waittime+disabletime ) {off[relay,2] TIMELINE_RELOAD(siren_countdown,countdowntimes,2)} } case false: { off[relay,2]} } }I also don't see the point of doing that TIMELINE_RELOAD() when you didn't change the timing at all. Maybe you meant to use TIMELINE_SET, to reset the timeline.repetition back to the begining?
Here's an example using a feedback timeline, and also combining your 2 identical timelines.
MODULE_NAME='signaliz' (DEV Relay, DEV io, DEV Panel) DEFINE_CONSTANT one_second_countdown = 1 feedback_timeline = 2 DEFINE_VARIABLE non_volatile integer stateflag //TRUE then Signaling is ON long feedback_time[1] long countdowntimes[2] DEFINE_START feedback_time[1] = 300 countdowntimes[1] = 1000 countdowntimes[2] = 1000 // Start a permanently repeating timeline for feedback Timeline_Create(feedback_timeline,feedback_time,1,timeline_relative,timeline_repeat) DEFINE_EVENT (**************Using the button on the touch panel****************) button_event [Panel, 678] { push: { stateflag = !stateflag }} timeline_event[feedback_timeline] { [Panel, 678] = stateflag } (************End of using the button on the touch panel*********) //Check the state of the port IO1 channel_event [io,1] { // If channel is on - Create a timer that will trigger the relay. on: { // Send to panel "Door open" timeline_create(one_second_countdown,countdowntimes,2,timeline_relative,timeline_repeat) } off: { // Send to panel "Door close" timeline_kill(one_second_countdown) off[relay,1] off[relay,2] } } timeline_event[feedback_timeline] { [Panel, 680] = [io,1] } timeline_event[one_second_countdown] { stack_var waittime stack_var disabletime waittime = 250 //Waiting time before switching Relay2 disabletime = 250 // Working time Relay2, before disconnecting and reconnecting //relay1 - 1Sec ON, 1 Sec OFF if (timeline.sequence = 1) {on[relay,1]} if (timeline.sequence = 2) {off[relay,1]} //If button on the touch Panel is on - start using Relay2 if (stateflag) { if (timeline.repetition >= waittime ) { switch (timeline.sequence) { case 1: on[relay,2] case 2: off[relay,2] } } if (timeline.repetition >= waittime+disabletime ) {off[relay,2] TIMELINE_SET(one_second_countdown,0)} } Else { off[relay,2]} }Troubleshooting: so rare nowadays it's a fricken super power.
Yeah I've been toubleshooting my entire life, actually no, I've been getting in trouble my entire life, that sounds more accurate.