6 |
6 |
7 from MotionLibrary import Headers, AxisXSD |
7 from MotionLibrary import Headers, AxisXSD |
8 from EthercatSlave import _EthercatSlaveCTN, _CommonSlave |
8 from EthercatSlave import _EthercatSlaveCTN, _CommonSlave |
9 from ConfigEditor import CIA402NodeEditor |
9 from ConfigEditor import CIA402NodeEditor |
10 |
10 |
11 #------------------------------------------ |
11 # Definition of node variables that have to be mapped in PDO |
12 #from CommonSlave import _CommonSlave |
12 # [(name, index, subindex, type, |
13 #------------------------------------------ |
13 # direction for master ('I': input, 'Q': output)),...] |
14 |
|
15 NODE_VARIABLES = [ |
14 NODE_VARIABLES = [ |
16 ("ControlWord", 0x6040, 0x00, "UINT", "Q"), |
15 ("ControlWord", 0x6040, 0x00, "UINT", "Q"), |
17 ("TargetPosition", 0x607a, 0x00, "DINT", "Q"), |
16 ("TargetPosition", 0x607a, 0x00, "DINT", "Q"), |
18 ("TargetVelocity", 0x60ff, 0x00, "DINT", "Q"), |
17 ("TargetVelocity", 0x60ff, 0x00, "DINT", "Q"), |
19 ("TargetTorque", 0x6071, 0x00, "INT", "Q"), |
18 ("TargetTorque", 0x6071, 0x00, "INT", "Q"), |
20 ("ModesOfOperation", 0x06060, 0x00, "SINT", "Q"), |
19 ("ModesOfOperation", 0x6060, 0x00, "SINT", "Q"), |
21 ("StatusWord", 0x6041, 0x00, "UINT", "I"), |
20 ("StatusWord", 0x6041, 0x00, "UINT", "I"), |
22 ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"), |
21 ("ModesOfOperationDisplay", 0x6061, 0x00, "SINT", "I"), |
23 ("ActualPosition", 0x6064, 0x00, "DINT", "I"), |
22 ("ActualPosition", 0x6064, 0x00, "DINT", "I"), |
24 ("ActualVelocity", 0x606c, 0x00, "DINT", "I"), |
23 ("ActualVelocity", 0x606c, 0x00, "DINT", "I"), |
25 ("ActualTorque", 0x6077, 0x00, "INT", "I"), |
24 ("ActualTorque", 0x6077, 0x00, "INT", "I"), |
26 ] |
25 ] |
27 |
26 |
28 DEFAULT_RETRIEVE = " __CIA402Node_%(location)s.axis->%(name)s = *(__CIA402Node_%(location)s.%(name)s);" |
27 # Definition of optional node variables that can be added to PDO mapping. |
29 DEFAULT_PUBLISH = " *(__CIA402Node_%(location)s.%(name)s) = __CIA402Node_%(location)s.axis->%(name)s;" |
28 # A checkbox will be displayed for each section in node configuration panel to |
30 |
29 # enable them |
|
30 # [(section_name, |
|
31 # [{'description', (name, index, subindex, type, |
|
32 # direction for master ('I': input, 'Q': output)), |
|
33 # 'retrieve', string_template_for_retrieve_variable (None: not retrieved, |
|
34 # default string template if not defined), |
|
35 # 'publish', string_template_for_publish_variable (None: not published, |
|
36 # default string template if not defined), |
|
37 # },...] |
31 EXTRA_NODE_VARIABLES = [ |
38 EXTRA_NODE_VARIABLES = [ |
32 ("ErrorCode", [ |
39 ("ErrorCode", [ |
33 {"description": ("ErrorCode", 0x603F, 0x00, "UINT", "I"), |
40 {"description": ("ErrorCode", 0x603F, 0x00, "UINT", "I"), |
34 "publish": None} |
41 "publish": None} |
35 ]), |
42 ]), |
144 "children": children, |
143 "children": children, |
145 } |
144 } |
146 |
145 |
147 def CTNGlobalInstances(self): |
146 def CTNGlobalInstances(self): |
148 current_location = self.GetCurrentLocation() |
147 current_location = self.GetCurrentLocation() |
149 return [("%s_%s" % (block_infos["blocktype"], "_".join(map(str, current_location))), |
148 return [("%s_%s" % (block_infos["blocktype"], |
150 "EtherLab%s" % block_infos["blocktype"], "") for block_infos in GLOBAL_INSTANCES] |
149 "_".join(map(str, current_location))), |
|
150 "EtherLab%s" % block_infos["blocktype"], "") |
|
151 for block_infos in FIELDBUS_INTERFACE_GLOBAL_INSTANCES] |
151 |
152 |
152 def _getCIA402AxisRef(self): |
153 def _getCIA402AxisRef(self): |
153 data = wx.TextDataObject(str(("%%IW%s.0" % ".".join(map(str, self.GetCurrentLocation())), |
154 data = wx.TextDataObject(str( |
154 "location", "AXIS_REF", self.CTNName(), ""))) |
155 ("%%IW%s.0" % ".".join(map(str, self.GetCurrentLocation())), |
|
156 "location", "AXIS_REF", self.CTNName(), ""))) |
155 dragSource = wx.DropSource(self.GetCTRoot().AppFrame) |
157 dragSource = wx.DropSource(self.GetCTRoot().AppFrame) |
156 dragSource.SetData(data) |
158 dragSource.SetData(data) |
157 dragSource.DoDragDrop() |
159 dragSource.DoDragDrop() |
158 |
160 |
159 def CTNGenerate_C(self, buildpath, locations): |
161 def CTNGenerate_C(self, buildpath, locations): |
160 current_location = self.GetCurrentLocation() |
162 current_location = self.GetCurrentLocation() |
161 |
163 |
162 location_str = "_".join(map(lambda x:str(x), current_location)) |
164 location_str = "_".join(map(lambda x:str(x), current_location)) |
163 |
165 slave_pos = self.GetSlavePos() |
164 plc_cia402node_filepath = os.path.join(os.path.split(__file__)[0], "plc_cia402node.c") |
166 MCL_headers = Headers |
|
167 |
|
168 # Open CIA402 node code template file |
|
169 plc_cia402node_filepath = os.path.join(os.path.split(__file__)[0], |
|
170 "plc_cia402node.c") |
165 plc_cia402node_file = open(plc_cia402node_filepath, 'r') |
171 plc_cia402node_file = open(plc_cia402node_filepath, 'r') |
166 plc_cia402node_code = plc_cia402node_file.read() |
172 plc_cia402node_code = plc_cia402node_file.read() |
167 plc_cia402node_file.close() |
173 plc_cia402node_file.close() |
168 |
174 |
169 str_completion = { |
175 # Init list of generated strings for each code template file section |
170 "slave_pos": self.GetSlavePos(), |
176 fieldbus_interface_declaration = [] |
171 "location": location_str, |
177 fieldbus_interface_definition = [] |
172 "MCL_headers": Headers, |
178 init_axis_params = [] |
173 "extern_located_variables_declaration": [], |
179 extra_variables_retrieve = [] |
174 "fieldbus_interface_declaration": [], |
180 extra_variables_publish = [] |
175 "fieldbus_interface_definition": [], |
181 extern_located_variables_declaration = [] |
176 "entry_variables": [], |
182 entry_variables = [] |
177 "init_axis_params": [], |
183 init_entry_variables = [] |
178 "init_entry_variables": [], |
184 |
179 "extra_variables_retrieve": [], |
185 # Fieldbus interface code sections |
180 "extra_variables_publish": [] |
186 for blocktype_infos in FIELDBUS_INTERFACE_GLOBAL_INSTANCES: |
181 } |
187 blocktype = blocktype_infos["blocktype"] |
182 |
188 ucase_blocktype = blocktype.upper() |
183 for blocktype_infos in GLOBAL_INSTANCES: |
189 blockname = "_".join([ucase_blocktype, location_str]) |
184 texts = { |
190 |
185 "blocktype": blocktype_infos["blocktype"], |
191 extract_inputs = "\n".join(["""\ |
186 "ucase_blocktype": blocktype_infos["blocktype"].upper(), |
192 __SET_VAR(%s->, %s, %s);""" % (blockname, input_name, input_value) |
187 "location": "_".join(map(str, current_location)) |
193 for (input_name, input_value) in [ |
188 } |
194 ("EXECUTE", "__GET_VAR(data__->EXECUTE)")] + [ |
189 texts["blockname"] = "%(ucase_blocktype)s_%(location)s" % texts |
195 (input["name"].upper(), |
190 |
196 "__GET_VAR(data__->%s)" % input["name"].upper()) |
191 inputs = [{"input_name": "POS", "input_value": str(self.GetSlavePos())}, |
197 for input in blocktype_infos["inputs"]] |
192 {"input_name": "EXECUTE", "input_value": "__GET_VAR(data__->EXECUTE)"}] +\ |
198 ]) |
193 [{"input_name": input["name"].upper(), |
199 |
194 "input_value": "__GET_VAR(data__->%s)" % input["name"].upper()} |
200 |
195 for input in blocktype_infos["inputs"]] |
201 return_outputs = "\n".join(["""\ |
196 input_texts = [] |
202 __SET_VAR(data__->,%(output_name)s, |
197 for input_infos in inputs: |
203 __GET_VAR(%(blockname)s->%(output_name)s));""" % locals() |
198 input_infos.update(texts) |
204 for output_name in ["DONE", "BUSY", "ERROR"] + [ |
199 input_texts.append(BLOCK_INPUT_TEMPLATE % input_infos) |
205 output["name"].upper() |
200 texts["extract_inputs"] = "\n".join(input_texts) |
206 for output in blocktype_infos["outputs"]] |
201 |
207 ]) |
202 outputs = [{"output_name": output} for output in ["DONE", "BUSY", "ERROR"]] + \ |
208 |
203 [{"output_name": output["name"].upper()} for output in blocktype_infos["outputs"]] |
209 fieldbus_interface_declaration.append(""" |
204 output_texts = [] |
210 extern void ETHERLAB%(ucase_blocktype)s_body__(ETHERLAB%(ucase_blocktype)s* data__); |
205 for output_infos in outputs: |
211 void __%(blocktype)s_%(location_str)s(MC_%(ucase_blocktype)s *data__) { |
206 output_infos.update(texts) |
212 __DECLARE_GLOBAL_PROTOTYPE(ETHERLAB%(ucase_blocktype)s, %(blockname)s); |
207 output_texts.append(BLOCK_OUTPUT_TEMPLATE % output_infos) |
213 ETHERLAB%(ucase_blocktype)s* %(blockname)s = __GET_GLOBAL_%(blockname)s(); |
208 texts["return_outputs"] = "\n".join(output_texts) |
214 __SET_VAR(%(blockname)s->, POS, AxsPub.axis->NetworkPosition); |
209 |
215 %(extract_inputs)s |
210 str_completion["fieldbus_interface_declaration"].append( |
216 ETHERLAB%(ucase_blocktype)s_body__(%(blockname)s); |
211 BLOCK_FUNCTION_TEMPLATE % texts) |
217 %(return_outputs)s |
212 |
218 }""" % locals()) |
213 str_completion["fieldbus_interface_definition"].append( |
219 |
214 BLOCK_FUNTION_DEFINITION_TEMPLATE % texts) |
220 fieldbus_interface_definition.append("""\ |
215 |
221 AxsPub.axis->__mcl_func_MC_%(blocktype)s = __%(blocktype)s_%(location_str)s;\ |
|
222 """ % locals()) |
|
223 |
|
224 # Get a copy list of default variables to map |
216 variables = NODE_VARIABLES[:] |
225 variables = NODE_VARIABLES[:] |
217 |
226 |
218 params = self.CTNParams[1].getElementInfos(self.CTNParams[0]) |
227 # Set AxisRef public struct members value |
219 for param in params["children"]: |
228 node_params = self.CTNParams[1].getElementInfos(self.CTNParams[0]) |
220 if param["name"] in EXTRA_NODE_VARIABLES_DICT: |
229 for param in node_params["children"]: |
221 if param["value"]: |
230 param_name = param["name"] |
222 extra_variables = EXTRA_NODE_VARIABLES_DICT.get(param["name"]) |
231 |
223 for variable_infos in extra_variables: |
232 # Param is optional variables section enable flag |
224 var_infos = { |
233 extra_node_variable_infos = EXTRA_NODE_VARIABLES_DICT.get(param_name) |
225 "location": location_str, |
234 if extra_node_variable_infos is not None: |
226 "name": variable_infos["description"][0] |
235 |
227 } |
236 if not param["value"]: |
228 variables.append(variable_infos["description"]) |
237 continue |
229 retrieve_template = variable_infos.get("retrieve", DEFAULT_RETRIEVE) |
238 |
230 publish_template = variable_infos.get("publish", DEFAULT_PUBLISH) |
239 # Optional variables section is enabled |
|
240 for variable_infos in extra_node_variable_infos: |
|
241 var_name = variable_infos["description"][0] |
|
242 |
|
243 # Add each variables defined in section description to the |
|
244 # list of variables to map |
|
245 variables.append(variable_infos["description"]) |
|
246 |
|
247 # Add code to publish or retrive variable |
|
248 for var_exchange_dir, str_list, default_template in [ |
|
249 ("retrieve", extra_variables_retrieve, |
|
250 " AxsPub.axis->%(var_name)s = *(AxsPub.%(var_name)s);"), |
|
251 ("publish", extra_variables_publish, |
|
252 " *(AxsPub.%(var_name)s) = AxsPub.axis->%(var_name)s;")]: |
231 |
253 |
232 if retrieve_template is not None: |
254 template = variable_infos.get(var_exchange_dir, |
233 str_completion["extra_variables_retrieve"].append( |
255 default_template) |
234 retrieve_template % var_infos) |
256 if template is not None: |
235 if publish_template is not None: |
257 extra_variables_publish.append(template % locals()) |
236 str_completion["extra_variables_publish"].append( |
258 |
237 publish_template % var_infos) |
259 # Set AxisRef public struct member value if defined |
238 elif param["value"] is not None: |
260 elif param["value"] is not None: |
239 param_infos = { |
261 param_value = ({True: "1", False: "0"}[param["value"]] |
240 "location": location_str, |
262 if param["type"] == "boolean" |
241 "param_name": param["name"], |
263 else str(param["value"])) |
242 } |
264 |
243 if param["type"] == "boolean": |
265 init_axis_params.append("""\ |
244 param_infos["param_value"] = {True: "1", False: "0"}[param["value"]] |
266 AxsPub.axis->%(param_name)s = %(param_value)s;""" % locals()) |
245 else: |
267 |
246 param_infos["param_value"] = str(param["value"]) |
268 # Add each variable in list of variables to map to master list of |
247 str_completion["init_axis_params"].append( |
269 # variables to add to network configuration |
248 " __CIA402Node_%(location)s.axis->%(param_name)s = %(param_value)s;" % param_infos) |
270 for name, index, subindex, var_type, dir in variables: |
249 |
271 var_size = self.GetSizeOfType(var_type) |
250 for variable in variables: |
272 var_name = """\ |
251 var_infos = dict(zip(["name", "index", "subindex", "var_type", "dir"], variable)) |
273 __%(dir)s%(var_size)s%(location_str)s_%(index)d_%(subindex)d""" % locals() |
252 var_infos["location"] = location_str |
274 |
253 var_infos["var_size"] = self.GetSizeOfType(var_infos["var_type"]) |
275 extern_located_variables_declaration.append( |
254 var_infos["var_name"] = "__%(dir)s%(var_size)s%(location)s_%(index)d_%(subindex)d" % var_infos |
276 "IEC_%(var_type)s *%(var_name)s;" % locals()) |
255 |
277 entry_variables.append( |
256 str_completion["extern_located_variables_declaration"].append( |
278 " IEC_%(var_type)s *%(name)s;" % locals()) |
257 "IEC_%(var_type)s *%(var_name)s;" % var_infos) |
279 init_entry_variables.append( |
258 str_completion["entry_variables"].append( |
280 " AxsPub.%(name)s = %(var_name)s;" % locals()) |
259 " IEC_%(var_type)s *%(name)s;" % var_infos) |
|
260 str_completion["init_entry_variables"].append( |
|
261 " __CIA402Node_%(location)s.%(name)s = %(var_name)s;" % var_infos) |
|
262 |
281 |
263 self.CTNParent.FileGenerator.DeclareVariable( |
282 self.CTNParent.FileGenerator.DeclareVariable( |
264 self.GetSlavePos(), var_infos["index"], var_infos["subindex"], |
283 slave_pos, index, subindex, var_type, dir, var_name) |
265 var_infos["var_type"], var_infos["dir"], var_infos["var_name"]) |
284 |
266 |
285 # Add newline between string in list of generated strings for sections |
267 for element in ["extern_located_variables_declaration", |
286 [fieldbus_interface_declaration, fieldbus_interface_definition, |
268 "fieldbus_interface_declaration", |
287 init_axis_params, extra_variables_retrieve, extra_variables_publish, |
269 "fieldbus_interface_definition", |
288 extern_located_variables_declaration, entry_variables, |
270 "entry_variables", |
289 init_entry_variables] = map(lambda l: "\n".join(l), [ |
271 "init_axis_params", |
290 fieldbus_interface_declaration, fieldbus_interface_definition, |
272 "init_entry_variables", |
291 init_axis_params, extra_variables_retrieve, extra_variables_publish, |
273 "extra_variables_retrieve", |
292 extern_located_variables_declaration, entry_variables, |
274 "extra_variables_publish"]: |
293 init_entry_variables]) |
275 str_completion[element] = "\n".join(str_completion[element]) |
294 |
276 |
295 # Write generated content to CIA402 node file |
277 Gen_CIA402Nodefile_path = os.path.join(buildpath, "cia402node_%s.c"%location_str) |
296 Gen_CIA402Nodefile_path = os.path.join(buildpath, |
|
297 "cia402node_%s.c"%location_str) |
278 cia402nodefile = open(Gen_CIA402Nodefile_path, 'w') |
298 cia402nodefile = open(Gen_CIA402Nodefile_path, 'w') |
279 cia402nodefile.write(plc_cia402node_code % str_completion) |
299 cia402nodefile.write(plc_cia402node_code % locals()) |
280 cia402nodefile.close() |
300 cia402nodefile.close() |
281 |
301 |
282 return [(Gen_CIA402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))],"",True |
302 return [(Gen_CIA402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))],"",True |
283 |
|