I want to use buttons in HMI screen to control the plc. The result should be when I turn on one of the button and another one will be turned off. What should I type in the screen cycle macro in order to make the function work?
Buttons in HMI and screen for macro
Because you didn't specify the model or brand of the HMI, and I couldn't identify it from the image and the code doesn't seem to be standardized as ST from IEC-61131, I'll put it as a "pseudo-code", so you'll have to adjust it according to the correct syntax.
//Declare as global or equivalent, or use a PLC memory
Bool oldM3
Bool oldM4
//------- Run cycllic --------
//Get the transition of M3
IF NOT oldM3 AND M3 THEN
oldM3 = true
M4 = false
ENDIF
IF NOT M3 THEN
oldM3 = false
ENDIF
//Get the transition of M4
IF NOT oldM4 AND M4 THEN
oldM4 = true
M3 = false
ENDIF
IF NOT M4 THEN
oldM4 = false
ENDIF
Related
I'm trying to understand Shiny apps in particular this example of the bus dashboard located at
https://github.com/rstudio/shiny-examples/tree/master/086-bus-dashboard
I'd like to modify the update rule so colors are displayed depending on whether or not locations$Bearing >= 200.
I tried modifying the locations dataframe which has Bearing but can't figure out how to chnage the color on map when the leaflet map is updated. It looks like it may have something to do with color = ~dirPal(Direction)
addTiles('http://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png') %>%
addCircleMarkers(
~VehicleLongitude,
~VehicleLatitude,
color = ~dirPal(Direction),
opacity = 0.8,
radius = 16
)```
where dirColors is defined at beginning of script
dirColors <-c("1"="#595490", "2"="#527525", "3"="#A93F35", "4"="#BA48AA", "5" = "#BA48AA")
I'd like to basically add a color here but conditionally displayed only for buses where Bearing >= 200 in location dataframe.
routeVehicleLocations <- reactive({
if (is.null(input$routeNum))
return()
locations <- vehicleLocations()
anomalies <- locations[locations$Bearing > 200,]
if (as.numeric(input$routeNum) == 0)
return(locations)
locations[locations$Route == input$routeNum, ]
})
The rest of the app is fine but would like to overwrite the color if condition above is met (Bearing >=200). Eventually would like to replace this rule with my own model and own data sources.
I want to draw a specific curve line to Photoshop or to mspaint. This drawing action should be saved for the possibility to redraw that curve in the exact same way. How can I do it with Autoit? Is there a recording and play mechanism? As far as I read, the AU3 recorder is not available anymore.
Photoshop is just an example. I want to be able to do that kind of drawing record for different purposes and programs. Maybe also for online image editors or something.
I am not that familiar with Autoit yet. I do not expect a full code example, maybe you can give me an idea - that would be very helpful.
Currently I tried a bit with mouse functions like MouseDown, MouseMove etc. and it is quite funny, but i do not really have a concept to record and redraw these mouse actions.
If I have to clarify more please let me know - i will do my best to be precise.
I recommend using two scripts, one for recording and the second to replay recorded actions.
Code for the recording:
; declaration
Global $sFileCoordinates = #ScriptDir & '\RecordedMouseMoveCoordinates.txt'
Global $iRecordingDurationInSeconds = 10
Global $iXSave, $iYSave
; functions
Func _recordMouseMoveCoordinatesToFile()
Local $aPos = MouseGetPos()
If $aPos[0] <> $iXSave Or $aPos[1] <> $iYSave Then
FileWrite($hFile, $aPos[0] & ',' & $aPos[1] & #CRLF)
Local $aPos = MouseGetPos()
$iXSave = $aPos[0]
$iYSave = $aPos[1]
EndIf
Sleep(80)
EndFunc
; processing
Sleep(4000) ; wait 4 seconds to place your mouse to the start position
Global $hFile = FileOpen($sFileCoordinates, 1 + 256)
Global $hTimer = TimerInit()
While Round((TimerDiff($hTimer) / 1000), 1) <= $iRecordingDurationInSeconds
ToolTip(Round((TimerDiff($hTimer) / 1000), 1))
_recordMouseMoveCoordinatesToFile()
WEnd
FileClose($hFile)
Recording will start after a 4 second delay. This should allow to move your mouse to the start point of your drawing action.
Global $iRecordingDurationInSeconds = 10 means your drawing action should be finished in 10 seconds (a tooltip displays remaining seconds). And here the seconds script.
Code to redraw curve:
; declaration
Global $sFileCoordinates = #ScriptDir & '\RecordedMouseMoveCoordinates.txt'
; functions
Func _getFileContent($sFile)
Local $hFile = FileOpen($sFile, 256)
Local $sFileContent = FileRead($hFile)
FileClose($hFile)
Return $sFileContent
EndFunc
Func _drawRecordedMouseMoveCoordinatesFromFile($sContent)
Local $aFileContent = StringSplit($sContent, #CRLF, 1)
Local $iX = StringSplit($aFileContent[1], ',')[1]
Local $iY = StringSplit($aFileContent[1], ',')[2]
MouseMove($iX, $iY, 4)
MouseDown('left')
For $i = 1 To $aFileContent[0] Step 1
If $aFileContent[$i] <> '' Then
Local $iX = StringSplit($aFileContent[$i], ',')[1]
Local $iY = StringSplit($aFileContent[$i], ',')[2]
MouseMove($iX, $iY, 4)
EndIf
Next
MouseUp('left')
EndFunc
; processing
Sleep(2000) ; wait 2 seconds till start
Global $sFileContent = _getFileContent($sFileCoordinates)
_drawRecordedMouseMoveCoordinatesFromFile($sFileContent)
There is a start delay of 2 seconds. All saved coordinates will be executed in the same way recorded. It starts with MouseDown('left'), then the mouse movements to MouseUp('left').
Notice:
This approach isn't really robust because of the coordinates which aren't relative to your window. Please see Opt('MouseCoordMode', 0|1|2) in the help file for more information. If you want to draw more than just one line or curve this approach isn't the best. But as your question describes only that requirement it should be fine.
I am trying to implement an interactive dashboard in Bokeh with a "play" function that loops through all value pairs for two indicators selected by widgets.
Screen cap of dashboard
While the loop works, the dashboard resets the axis values for each step of the loop. So what I need is to set axis values based on the widget.value selected. To this end, I have built a data frame "ranges" that has the name of the indicator as index and the min/max value for each indicator as columns.
The updates for controls work thusly (x_axis,etc. are the names of the widgets):
controls = [x_axis, y_axis, start_yr, end_yr, years]
for control in controls:
control.on_change('value', lambda attr, old, new: update())
The update function is supposed to update the ranges upon change in the controls like this:
def update():
p.x_range = Range1d(start = ranges.loc[x_axis.value,"Min"],
end = ranges.loc[x_axis.value,"Max"])
p.y_range = Range1d(start = ranges.loc[y_axis.value,"Min"],
end = ranges.loc[y_axis.value,"Max"])
What should happen: Whenever I change the value of the widget, the ranges should update, but other than that, they should remain constant
What does happen: The ranges are set based on the value of the widget initially set and don't change on update.
I've tried to find examples trying to achieve something similar but no luck.
This is a working example:
import numpy as np
from bokeh.plotting import figure
from bokeh.models import Range1d
from bokeh.io import curdoc
x = np.linspace(0, 100, 1000)
y = np.sin(x)
p = figure(x_range=(0, 100))
p.circle(x, y)
def cb():
# this works:
p.x_range.start += 1
p.x_range.end += 1
# this also works:
#p.x_range = Range1d(p.x_range.start+1, p.x_range.end+1)
curdoc().add_periodic_callback(cb, 200)
curdoc().add_root(p)
I know I can turn axes on and off in bokeh with p1.xaxis.visible = None or p1.yaxis.visible = None from Hide Axis in Bokeh. What if I have an extra y range I want to change the visibility of? I've defined my extra axis like this:
plot.extra_y_ranges = {'ORP': Range1d(start=0, end=plot_d['y_axis2_max'])}
plot.add_layout(LinearAxis(y_range_name='ORP', axis_label='ORP, mV'), 'left')
I tried plot.extra_y_ranges.visible = None but it has no effect, and I wasn't able to find anything in the documentation. Have I missed something?
You need to change the visibility of the lines, not the axis.
I've done this in a project on Github that displays temperature and humidity data (amongst other things). The humidity data is the extra y axis and I have check boxes to show/hide temperature and/or humidity. Here's the function that shows/hides the lines on the chart:
def h_t_lines_changed(self, active):
"""Helper function for h_t_tab - turns lines on and off"""
for index in range(len(self.h_t_line)):
self.h_t_line[index].visible = index in active
Here's the line definitions:
self.h_t_line[0] = self.h_t_fig.line(x='Timestamp',
y='Temperature (C)',
source=self.source,
color="blue",
legend="Temperature",
line_width=2)
self.h_t_line[1] = self.h_t_fig.line(x="Timestamp",
y="Relative humidity (%)",
source=self.source,
y_range_name="humidity",
color="green",
legend="Humidity",
line_width=2)
and here's the checkbox code, including the callback:
resp_b = [0, 1]
h_t_check_head = Div(text="Responses")
h_t_check = CheckboxGroup(labels=["Temperature", "Humidity"],
active=resp_b,
name="Lines")
h_t_check.on_click(self.h_t_lines_changed)
I'm updating my project now. If you want me to post a link to it, let me know.
self.mb = Menubutton ( self.window2, text="Sound Toggler", relief=RAISED )
self.mb.grid(row=4, column = 0)
self.mb.menu = Menu ( self.mb, tearoff = 0 )
self.mb["menu"] = self.mb.menu
self.ONSound = IntVar()
self.ONSound.set(1)
self.OFFSound = IntVar()
self.OFFSound.set(0)
self.mb.menu.add_checkbutton ( label="ONSound", variable=self.ONSound, command = self.turnON(), onvalue=1,offvalue=0)
self.mb.menu.add_checkbutton ( label="OFFSound", variable=self.OFFSound, command = self.turnOFF(), onvalue=1,offvalue=0)
def turnON(self):
self.ONSound.set(1)
self.OFFSound.set(0)
def turnOFF(self):
self.ONSound.set(0)
self.OFFSound.set(1)
My goal is to turn these two check buttons to toggle sound On and OFF and in doing so only one of these check buttons can be on/off at a single time. Currently this effect is not working and I've been looking at my code for an hour and can't find the problem. Everything shows up when my full program is run but this ON/OFF toggle doesn't work how I want it to.
All help is appreciated,
Thanks
The problem is that you set the command to a function call instead of a funciton reference. This makes the functions run once and assign the return value (None) to command. You should remove the parentheses after the function names.
To make two options of which only one can be selected however, why don't you make them radiobuttons? Then it's as simple as
self.Sound = IntVar()
self.mb.menu.add_radiobutton(label= "ONSound", variable=self.Sound, value=1)
self.mb.menu.add_radiobutton(label="OFFSound", variable=self.Sound, value=0)