141 import commands |
162 import commands |
142 result = commands.getoutput("ethercat rescan -p %d") |
163 result = commands.getoutput("ethercat rescan -p %d") |
143 returnVal =result |
164 returnVal =result |
144 """ |
165 """ |
145 |
166 |
|
167 # ethercat pdos |
|
168 PDOS = """ |
|
169 import commands |
|
170 result = commands.getoutput("ethercat pdos -p 0") |
|
171 returnVal =result |
|
172 """ |
146 |
173 |
147 # -------------------------------------------------- |
174 # -------------------------------------------------- |
148 # Common Method For EtherCAT Management |
175 # Common Method For EtherCAT Management |
149 # -------------------------------------------------- |
176 # -------------------------------------------------- |
150 class _CommonSlave(object): |
177 class _CommonSlave(object): |
151 |
178 |
152 # ----- Data Structure for ethercat management ---- |
179 # ----- Data Structure for ethercat management ---- |
153 SlaveState = "" |
180 SlaveState = "" |
154 |
181 |
|
182 # SDO base data type for Ethercatmaster |
|
183 BaseDataTypes = { |
|
184 "bool": ["BOOLEAN", "BOOL", "BIT"], |
|
185 "uint8": ["BYTE", "USINT", "BIT1", "BIT2", "BIT3", "BIT4", "BIT5", "BIT6", |
|
186 "BIT7", "BIT8", "BITARR8", "UNSIGNED8"], |
|
187 "uint16": ["BITARR16", "UNSIGNED16", "UINT"], |
|
188 "uint32": ["BITARR32", "UNSIGNED24", "UINT24", "UNSIGNED32", "UDINT"], |
|
189 "uint64": ["UNSINED40", "UINT40", "UNSIGNED48", "UINT48", "UNSIGNED56", |
|
190 "UINT56", "UNSIGNED64", "ULINT"], |
|
191 "int8": ["INTEGER8", "SINT"], |
|
192 "int16": ["INTEGER16", "INT"], |
|
193 "int32": ["INTEGER24", "INT24", "INTEGER32", "DINT"], |
|
194 "int64": ["INTEGER40", "INT40", "INTEGER48", "INT48", "INTEGER56", "INT56", |
|
195 "INTEGER64", "LINT"], |
|
196 "float": ["REAL", "REAL32"], |
|
197 "double": ["LREAL", "REAL64"], |
|
198 "string": ["VISUBLE_STRING", "STRING(n)"], |
|
199 "octet_string": ["OCTET_STRING"], |
|
200 "unicode_string": ["UNICODE_STRING"] |
|
201 } |
|
202 |
155 # category of SDO data |
203 # category of SDO data |
156 DatatypeDescription, CommunicationObject, ManufacturerSpecific, \ |
204 DatatypeDescription, CommunicationObject, ManufacturerSpecific, \ |
157 ProfileSpecific, Reserved, AllSDOData = range(6) |
205 ProfileSpecific, Reserved, AllSDOData = range(6) |
158 |
206 |
159 # store the execution result of "ethercat sdos" command into SaveSDOData. |
207 # SDO data informations: index, sub-index, type, bit size, category-name |
160 SaveSDOData = [] |
208 SDOVariables = [] |
161 |
209 SDOSubEntryData = [] |
162 # Flags for checking "write" permission of OD entries |
210 |
|
211 # defalut value of SDO data in XML |
|
212 # Not Used |
|
213 DefaultValueDic = {} |
|
214 |
|
215 # Flags for checking "write" permission of OD entries |
163 CheckPREOP = False |
216 CheckPREOP = False |
164 CheckSAFEOP = False |
217 CheckSAFEOP = False |
165 CheckOP = False |
218 CheckOP = False |
166 |
219 |
167 # Save PDO Data |
220 # Save PDO Data |
239 return return_val |
292 return return_val |
240 |
293 |
241 # ------------------------------------------------------------------------------- |
294 # ------------------------------------------------------------------------------- |
242 # Used SDO Management |
295 # Used SDO Management |
243 # ------------------------------------------------------------------------------- |
296 # ------------------------------------------------------------------------------- |
244 def GetSlaveSDOFromSlave(self): |
|
245 """ |
|
246 Get SDO objects information of current slave using "ethercat sdos -p %d" command. |
|
247 Command example : "ethercat sdos -p 0" |
|
248 @return return_val : execution results of "ethercat sdos" command (need to be parsed later) |
|
249 """ |
|
250 _error, return_val = self.Controler.RemoteExec(SLAVE_SDO % (self.Controler.GetSlavePos()), return_val=None) |
|
251 return return_val |
|
252 |
|
253 def SDODownload(self, data_type, idx, sub_idx, value): |
297 def SDODownload(self, data_type, idx, sub_idx, value): |
254 """ |
298 """ |
255 Set an SDO object value to user-specified value using "ethercat download" command. |
299 Set an SDO object value to user-specified value using "ethercat download" command. |
256 Command example : "ethercat download --type int32 -p 0 0x8020 0x12 0x00000000" |
300 Command example : "ethercat download --type int32 -p 0 0x8020 0x12 0x00000000" |
257 @param data_type : data type of SDO entry |
301 @param data_type : data type of SDO entry |
258 @param idx : index of the SDO entry |
302 @param idx : index of the SDO entry |
259 @param sub_idx : subindex of the SDO entry |
303 @param sub_idx : subindex of the SDO entry |
260 @param value : value of SDO entry |
304 @param value : value of SDO entry |
261 """ |
305 """ |
262 _error, _return_val = self.Controler.RemoteExec( |
306 valid_type = self.GetValidDataType(data_type) |
263 SDO_DOWNLOAD % (data_type, self.Controler.GetSlavePos(), idx, sub_idx, value), |
307 _error, return_val = self.Controler.RemoteExec( |
264 return_val=None) |
308 SDO_DOWNLOAD%(valid_type, self.Controler.GetSlavePos(), |
265 |
309 idx, sub_idx, value), return_val = None) |
|
310 |
|
311 return return_val |
|
312 |
266 def BackupSDODataSet(self): |
313 def BackupSDODataSet(self): |
267 """ |
314 """ |
268 Back-up current SDO entry information to restore the SDO data |
315 Back-up current SDO entry information to restore the SDO data |
269 in case that the user cancels SDO update operation. |
316 in case that the user cancels SDO update operation. |
270 """ |
317 """ |
280 Clear the specified SDO entry information. |
327 Clear the specified SDO entry information. |
281 """ |
328 """ |
282 for dummy in range(6): |
329 for dummy in range(6): |
283 self.SaveSDOData.append([]) |
330 self.SaveSDOData.append([]) |
284 |
331 |
|
332 def GetAllSDOValuesFromSlave(self): |
|
333 """ |
|
334 Get SDO values of All SDO entries. |
|
335 @return return_val: list of result of "SDO_UPLOAD" |
|
336 """ |
|
337 entry_infos = "" |
|
338 alldata_idx = len(self.SDOVariables) |
|
339 counter = 0 |
|
340 for category in self.SDOVariables: |
|
341 counter +=1 |
|
342 # for avoid redundant repetition |
|
343 if counter == alldata_idx: |
|
344 continue |
|
345 |
|
346 for entry in category: |
|
347 valid_type = self.GetValidDataType(entry["type"]) |
|
348 for_command_string = "%s %s %s ," % \ |
|
349 (valid_type, entry["idx"], entry["subIdx"]) |
|
350 entry_infos += for_command_string |
|
351 |
|
352 error, return_val = self.Controler.RemoteExec(SDO_UPLOAD%(entry_infos, self.Controler.GetSlavePos()), return_val = None) |
|
353 |
|
354 return return_val |
|
355 |
|
356 def GetSDOValuesFromSlave(self, entries_info): |
|
357 """ |
|
358 Get SDO values of some SDO entries. |
|
359 @param entries_info: dictionary of SDO entries that is wanted to know the value. |
|
360 @return return_val: list of result of "SDO_UPLOAD" |
|
361 """ |
|
362 entry_infos = "" |
|
363 |
|
364 entries_info_list = entries_info.items() |
|
365 entries_info_list.sort() |
|
366 |
|
367 for (idx, subIdx), entry in entries_info_list: |
|
368 valid_type = self.GetValidDataType(entry["type"]) |
|
369 for_command_string = "%s %s %s ," % \ |
|
370 (valid_type, str(idx), str(subIdx)) |
|
371 entry_infos += for_command_string |
|
372 |
|
373 error, return_val = self.Controler.RemoteExec(SDO_UPLOAD%(entry_infos, self.Controler.GetSlavePos()), return_val = None) |
|
374 |
|
375 return return_val |
|
376 |
|
377 def ExtractObjects(self): |
|
378 """ |
|
379 Extract object type items from imported ESI xml. |
|
380 And they are stuctured as dictionary. |
|
381 @return objects: dictionary of objects |
|
382 """ |
|
383 objects = {} |
|
384 |
|
385 slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) |
|
386 type_infos = slave.getType() |
|
387 device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos) |
|
388 |
|
389 if device is not None : |
|
390 for dictionary in device.GetProfileDictionaries(): |
|
391 dictionary.load() |
|
392 for object in dictionary.getObjects().getObject(): |
|
393 object_index = ExtractHexDecValue(object.getIndex().getcontent()) |
|
394 objects[(object_index)] = object |
|
395 |
|
396 return objects |
|
397 |
|
398 def ExtractAllDataTypes(self): |
|
399 """ |
|
400 Extract all data types from imported ESI xml. |
|
401 @return dataTypes: dictionary of datatypes |
|
402 """ |
|
403 dataTypes = {} |
|
404 |
|
405 slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) |
|
406 type_infos = slave.getType() |
|
407 device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos) |
|
408 |
|
409 for dictionary in device.GetProfileDictionaries(): |
|
410 dictionary.load() |
|
411 |
|
412 datatypes = dictionary.getDataTypes() |
|
413 if datatypes is not None: |
|
414 |
|
415 for datatype in datatypes.getDataType(): |
|
416 dataTypes[datatype.getName()] = datatype |
|
417 return dataTypes |
|
418 |
|
419 def IsBaseDataType(self, datatype): |
|
420 """ |
|
421 Check if the datatype is a base data type. |
|
422 @return baseTypeFlag: true if datatype is a base data type, unless false |
|
423 """ |
|
424 baseTypeFlag = False |
|
425 for baseDataTypeList in self.BaseDataTypes.values(): |
|
426 if datatype in baseDataTypeList: |
|
427 baseTypeFlag = True |
|
428 break |
|
429 return baseTypeFlag |
|
430 |
|
431 def GetBaseDataType(self, datatype): |
|
432 """ |
|
433 Get a base data type corresponding the datatype. |
|
434 @param datatype: Some data type (string format) |
|
435 @return base data type |
|
436 """ |
|
437 if self.IsBaseDataType(datatype): |
|
438 return datatype |
|
439 elif not datatype.find("STRING") == -1: |
|
440 return datatype |
|
441 else: |
|
442 datatypes = self.ExtractAllDataTypes() |
|
443 base_datatype = datatypes[datatype].getBaseType() |
|
444 return self.GetBaseDataType(base_datatype) |
|
445 |
|
446 def GetValidDataType(self, datatype): |
|
447 """ |
|
448 Convert the datatype into a data type that is possible to download/upload |
|
449 in etherlab master stack. |
|
450 @param datatype: Some data type (string format) |
|
451 @return base_type: vaild data type |
|
452 """ |
|
453 base_type = self.GetBaseDataType(datatype) |
|
454 |
|
455 if re.match("STRING\([0-9]*\)", datatype) is not None: |
|
456 return "string" |
|
457 else: |
|
458 for key, value in self.BaseDataTypes.items(): |
|
459 if base_type in value: |
|
460 return key |
|
461 return base_type |
|
462 |
|
463 # Not Used |
|
464 def GetAllEntriesList(self): |
|
465 """ |
|
466 Get All entries information that includes index, sub-index, name, |
|
467 type, bit size, PDO mapping, and default value. |
|
468 @return self.entries: dictionary of entry |
|
469 """ |
|
470 slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) |
|
471 type_infos = slave.getType() |
|
472 device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos) |
|
473 self.entries = device.GetEntriesList() |
|
474 datatypes = self.ExtractAllDataTypes() |
|
475 objects = self.ExtractObjects() |
|
476 entries_list = self.entries.items() |
|
477 entries_list.sort() |
|
478 |
|
479 # append sub entries |
|
480 for (index, subidx), entry in entries_list: |
|
481 # entry_* is string type |
|
482 entry_type = entry["Type"] |
|
483 entry_index = entry["Index"] |
|
484 |
|
485 try: |
|
486 object_info = objects[index].getInfo() |
|
487 except: |
|
488 continue |
|
489 |
|
490 if object_info is not None: |
|
491 obj_content = object_info.getcontent() |
|
492 |
|
493 typeinfo = datatypes.get(entry_type, None) |
|
494 bitsize = typeinfo.getBitSize() |
|
495 type_content = typeinfo.getcontent() |
|
496 |
|
497 # ArrayInfo type |
|
498 if type_content is not None and type_content["name"] == "ArrayInfo": |
|
499 for arrayinfo in type_content["value"]: |
|
500 element_num = arrayinfo.getElements() |
|
501 first_subidx = arrayinfo.getLBound() |
|
502 for offset in range(element_num): |
|
503 new_subidx = int(first_subidx) + offset |
|
504 entry_subidx = hex(new_subidx) |
|
505 if obj_content["value"][new_subidx]["name"] == "SubItem": |
|
506 subitem = obj_content["value"][new_subidx]["value"] |
|
507 subname = subitem[new_subidx].getName() |
|
508 if subname is not None: |
|
509 entry_name = "%s - %s" % \ |
|
510 (ExtractName(objects[index].getName()), subname) |
|
511 else: |
|
512 entry_name = ExtractName(objects[index].getName()) |
|
513 self.entries[(index, new_subidx)] = { |
|
514 "Index": entry_index, |
|
515 "SubIndex": entry_subidx, |
|
516 "Name": entry_name, |
|
517 "Type": typeinfo.getBaseType(), |
|
518 "BitSize": str(bitsize/element_num), |
|
519 "Access": entry["Access"], |
|
520 "PDOMapping": entry["PDOMapping"]} |
|
521 try: |
|
522 value_info = subitem[new_subidx].getInfo().getcontent()\ |
|
523 ["value"][0]["value"][0] |
|
524 self.AppendDefaultValue(index, new_subidx, value_info) |
|
525 except: |
|
526 pass |
|
527 |
|
528 try: |
|
529 value_info = subitem[subidx].getInfo().getcontent()\ |
|
530 ["value"][0]["value"][0] |
|
531 self.AppendDefaultValue(index, subidx, value_info) |
|
532 except: |
|
533 pass |
|
534 |
|
535 # EnumInfo type |
|
536 elif type_content is not None and type_content["name"] == "EnumInfo": |
|
537 self.entries[(index, subidx)]["EnumInfo"] = {} |
|
538 |
|
539 for enuminfo in type_content["value"]: |
|
540 text = enuminfo.getText() |
|
541 enum = enuminfo.getEnum() |
|
542 self.entries[(index, subidx)]["EnumInfo"][str(enum)] = text |
|
543 |
|
544 self.entries[(index, subidx)]["DefaultValue"] = "0x00" |
|
545 |
|
546 # another types |
|
547 else: |
|
548 if subidx == 0x00: |
|
549 tmp_subidx = 0x00 |
|
550 |
|
551 try: |
|
552 if obj_content["value"][tmp_subidx]["name"] == "SubItem": |
|
553 sub_name = entry["Name"].split(" - ")[1] |
|
554 for num in range(len(obj_content["value"])): |
|
555 if sub_name == \ |
|
556 obj_content["value"][num]["value"][num].getName(): |
|
557 subitem_content = obj_content["value"][tmp_subidx]\ |
|
558 ["value"][tmp_subidx] |
|
559 value_info = subitem_content.getInfo().getcontent()\ |
|
560 ["value"][0]["value"][0] |
|
561 tmp_subidx += 1 |
|
562 break |
|
563 else: |
|
564 value_info = None |
|
565 |
|
566 else: |
|
567 value_info = \ |
|
568 obj_content["value"][tmp_subidx]["value"][tmp_subidx] |
|
569 |
|
570 self.AppendDefaultValue(index, subidx, value_info) |
|
571 |
|
572 except: |
|
573 pass |
|
574 |
|
575 return self.entries |
|
576 |
|
577 # Not Used |
|
578 def AppendDefaultValue(self, index, subidx, value_info=None): |
|
579 """ |
|
580 Get the default value from the ESI xml |
|
581 @param index: entry index |
|
582 @param subidx: entry sub index |
|
583 @param value_info: dictionary of infomation about default value |
|
584 |
|
585 """ |
|
586 # there is not default value. |
|
587 if value_info == None: |
|
588 return |
|
589 |
|
590 raw_value = value_info["value"] |
|
591 |
|
592 # default value is hex binary type. |
|
593 if value_info["name"] == "DefaultData": |
|
594 raw_value_bit = list(hex(raw_value).split("0x")[1]) |
|
595 |
|
596 datatype = self.GetValidDataType(self.entries[(index, subidx)]["Type"]) |
|
597 if datatype is "string" or datatype is "octet_string": |
|
598 |
|
599 if "L" in raw_value_bit: |
|
600 raw_value_bit.remove("L") |
|
601 |
|
602 default_value = "".join(raw_value_bit).decode("hex") |
|
603 |
|
604 elif datatype is "unicode_string": |
|
605 default_value = "".join(raw_value_bit).decode("hex").\ |
|
606 decode("utf-8") |
|
607 |
|
608 else: |
|
609 bit_num = len(raw_value_bit) |
|
610 # padding |
|
611 if not bit_num%2 == 0: |
|
612 raw_value_bit.insert(0, "0") |
|
613 |
|
614 default_value_bit = [] |
|
615 |
|
616 # little endian -> big endian |
|
617 for num in range(bit_num): |
|
618 if num%2 == 0: |
|
619 default_value_bit.insert(0, raw_value_bit[num]) |
|
620 default_value_bit.insert(1, raw_value_bit[num+1]) |
|
621 |
|
622 default_value = "0x%s" % "".join(default_value_bit) |
|
623 |
|
624 # default value is string type. |
|
625 # this case is not tested yet. |
|
626 elif value_info["name"] == "DefaultString": |
|
627 default_value = raw_value |
|
628 |
|
629 # default value is Hex or Dec type. |
|
630 elif value_info["name"] == "DefaultValue": |
|
631 default_value = "0x" + hex(ExtractHexDecValue(raw_value)) |
|
632 |
|
633 self.entries[(index, subidx)]["DefaultValue"] = default_value |
|
634 |
285 # ------------------------------------------------------------------------------- |
635 # ------------------------------------------------------------------------------- |
286 # Used PDO Monitoring |
636 # Used PDO Monitoring |
287 # ------------------------------------------------------------------------------- |
637 # ------------------------------------------------------------------------------- |
288 def RequestPDOInfo(self): |
638 def RequestPDOInfo(self): |
289 """ |
639 """ |
290 Load slave information from RootClass (XML data) and parse the information (calling SlavePDOData() method). |
640 Load slave information from RootClass (XML data) and parse the information |
|
641 (calling SlavePDOData() method). |
291 """ |
642 """ |
292 # Load slave information from ESI XML file (def EthercatMaster.py) |
643 # Load slave information from ESI XML file (def EthercatMaster.py) |
293 slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) |
644 slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) |
294 |
645 |
295 type_infos = slave.getType() |
646 type_infos = slave.getType() |
327 if ExtractName(entry.getName()) is not None: |
685 if ExtractName(entry.getName()) is not None: |
328 entry_infos = { |
686 entry_infos = { |
329 "entry_index": index, |
687 "entry_index": index, |
330 "subindex": subindex, |
688 "subindex": subindex, |
331 "name": ExtractName(entry.getName()), |
689 "name": ExtractName(entry.getName()), |
332 "bitlen": entry.getBitLen(), |
690 "bitlen": entry.getBitLen() |
333 "type": entry.getDataType().getcontent() |
|
334 } |
691 } |
|
692 if entry.getDataType() is not None: |
|
693 entry_infos["type"] = entry.getDataType().getcontent() |
335 self.TxPDOInfo.append(entry_infos) |
694 self.TxPDOInfo.append(entry_infos) |
336 count += 1 |
695 count += 1 |
337 |
696 |
338 categorys = {"pdo_index": pdo_index, "name": pdo_name, "number_of_entry": count} |
697 categorys = {"pdo_index" : pdo_index, "name" : pdo_name, "sm" : Sm, |
|
698 "number_of_entry" : count, "exclude_list" : exclude_list} |
339 self.TxPDOCategory.append(categorys) |
699 self.TxPDOCategory.append(categorys) |
340 |
700 |
341 # Parsing RxPDO entries |
701 # Parsing RxPDO entries |
342 for pdo, _pdo_info in ([(rxpdo, "Outputs") for rxpdo in device.getRxPdo()]): |
702 for pdo, _pdo_info in ([(rxpdo, "Outputs") for rxpdo in device.getRxPdo()]): |
343 # Save pdo_index, entry, and name of each entry |
703 # Save pdo_index, entry, and name of each entry |
344 pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) |
704 pdo_index = ExtractHexDecValue(pdo.getIndex().getcontent()) |
345 entries = pdo.getEntry() |
705 entries = pdo.getEntry() |
346 pdo_name = ExtractName(pdo.getName()) |
706 pdo_name = ExtractName(pdo.getName()) |
|
707 excludes = pdo.getExclude() |
|
708 exclude_list = [] |
|
709 Sm = pdo.getSm() |
|
710 |
|
711 if excludes : |
|
712 for exclude in excludes: |
|
713 exclude_list.append(ExtractHexDecValue(exclude.getcontent())) |
347 |
714 |
348 # Initialize entry number count |
715 # Initialize entry number count |
349 count = 0 |
716 count = 0 |
350 |
717 |
351 # Parse entries |
718 # Parse entries |
792 eeprom.append(standard_send_mailbox_size[2:4]) |
1161 eeprom.append(standard_send_mailbox_size[2:4]) |
793 eeprom.append(standard_send_mailbox_size[0:2]) |
1162 eeprom.append(standard_send_mailbox_size[0:2]) |
794 |
1163 |
795 # get supported mailbox protocols for EEPROM offset 0x0038-0x0039; |
1164 # get supported mailbox protocols for EEPROM offset 0x0038-0x0039; |
796 data = 0 |
1165 data = 0 |
797 mb = device.getMailbox() |
1166 with device.getMailbox() as mb: |
798 if mb is not None: |
1167 if mb is not None: |
799 for bit, mbprot in enumerate(mailbox_protocols): |
1168 for bit, mbprot in enumerate(mailbox_protocols): |
800 if getattr(mb, "get%s" % mbprot)() is not None: |
1169 if getattr(mb, "get%s" % mbprot)() is not None: |
801 data += 1 << bit |
1170 data += 1 << bit |
802 data = "{:0>4x}".format(data) |
1171 data = "{:0>4x}".format(data) |
803 eeprom.append(data[2:4]) |
1172 eeprom.append(data[2:4]) |
804 eeprom.append(data[0:2]) |
1173 eeprom.append(data[0:2]) |
805 |
1174 |
806 # resereved for EEPROM offset 0x003a-0x007b; |
1175 # resereved for EEPROM offset 0x003a-0x007b; |
807 for i in range(0x007b-0x003a+0x0001): |
1176 for i in range(0x007b-0x003a+0x0001): |
808 eeprom.append("00") |
1177 eeprom.append("00") |
809 |
1178 |
810 # get EEPROM size for EEPROM offset 0x007c-0x007d; |
1179 # get EEPROM size for EEPROM offset 0x007c-0x007d; |
|
1180 # Modify by jblee because of update IDE module (minidom -> lxml) |
811 data = "" |
1181 data = "" |
812 for eeprom_element in device.getEeprom().getcontent(): |
1182 for eeprom_element in device.getEeprom().getchildren(): |
813 if eeprom_element["name"] == "ByteSize": |
1183 if eeprom_element.tag == "ByteSize": |
814 eeprom_size = int(str(eeprom_element)) |
1184 eeprom_size = int(objectify.fromstring(eeprom_element.tostring()).text) |
815 data = "{:0>4x}".format(int(eeprom_element)//1024*8-1) |
1185 data = "{:0>4x}".format(eeprom_size/1024*8-1) |
816 |
1186 |
817 if data == "": |
1187 if data == "": |
818 eeprom.append("00") |
1188 eeprom.append("00") |
819 eeprom.append("00") |
1189 eeprom.append("00") |
820 else: |
1190 else: |
821 eeprom.append(data[2:4]) |
1191 eeprom.append(data[2:4]) |
822 eeprom.append(data[0:2]) |
1192 eeprom.append(data[0:2]) |
823 |
1193 |
824 # Version for EEPROM 0x007e-0x007f; |
1194 # Version for EEPROM 0x007e-0x007f; |
825 # According to "EtherCAT Slave Device Description(V0.3.0)" |
1195 # According to "EtherCAT Slave Device Description(V0.3.0)" |
826 eeprom.append("01") |
1196 eeprom.append("01") |
827 eeprom.append("00") |
1197 eeprom.append("00") |
828 |
1198 |
829 # append String Category data |
1199 # append String Category data |
830 for data in self.ExtractEEPROMStringCategory(device): |
1200 for data in self.ExtractEEPROMStringCategory(device): |
1181 eeprom.append("{:0>2x}".format(self.NameIdx)) |
1552 eeprom.append("{:0>2x}".format(self.NameIdx)) |
1182 |
1553 |
1183 # word 3 : Physical Layer Port info. and CoE Details |
1554 # word 3 : Physical Layer Port info. and CoE Details |
1184 eeprom.append("01") # Physical Layer Port info - assume 01 |
1555 eeprom.append("01") # Physical Layer Port info - assume 01 |
1185 # CoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE> |
1556 # CoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE> |
1186 coe_details = 0 |
|
1187 mb = device.getMailbox() |
|
1188 coe_details = 1 # sdo enabled |
1557 coe_details = 1 # sdo enabled |
1189 if mb is not None: |
1558 with device.getMailbox() as mb |
1190 coe = mb.getCoE() |
1559 if mb is not None: |
1191 if coe is not None: |
1560 coe = mb.getCoE() |
1192 for bit, flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig", |
1561 if coe is not None: |
1193 "PdoUpload", "CompleteAccess"]): |
1562 for bit, flag in enumerate(["SdoInfo", "PdoAssign", "PdoConfig", |
1194 if getattr(coe, "get%s" % flag)() is not None: |
1563 "PdoUpload", "CompleteAccess"]): |
1195 coe_details += 1 << bit |
1564 if getattr(coe, "get%s" % flag)() is not None: |
1196 eeprom.append("{:0>2x}".format(coe_details)) |
1565 coe_details += 1 << bit |
1197 |
1566 eeprom.append("{:0>2x}".format(coe_details)) |
1198 # word 4 : FoE Details and EoE Details |
1567 |
1199 # FoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<FoE> |
1568 # word 4 : FoE Details and EoE Details |
1200 if mb is not None and mb.getFoE() is not None: |
1569 # FoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<FoE> |
1201 eeprom.append("01") |
1570 if mb is not None and mb.getFoE() is not None: |
1202 else: |
1571 eeprom.append("01") |
1203 eeprom.append("00") |
1572 else: |
1204 # EoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<EoE> |
1573 eeprom.append("00") |
1205 if mb is not None and mb.getEoE() is not None: |
1574 # EoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<EoE> |
1206 eeprom.append("01") |
1575 if mb is not None and mb.getEoE() is not None: |
1207 else: |
1576 eeprom.append("01") |
1208 eeprom.append("00") |
1577 else: |
1209 |
1578 eeprom.append("00") |
1210 # word 5 : SoE Channels(reserved) and DS402 Channels |
1579 |
1211 # SoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<SoE> |
1580 # word 5 : SoE Channels(reserved) and DS402 Channels |
1212 if mb is not None and mb.getSoE() is not None: |
1581 # SoE Details; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<SoE> |
1213 eeprom.append("01") |
1582 if mb is not None and mb.getSoE() is not None: |
1214 else: |
1583 eeprom.append("01") |
1215 eeprom.append("00") |
1584 else: |
1216 # DS402Channels; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>: DS402Channels |
1585 eeprom.append("00") |
1217 ds402ch = False |
1586 # DS402Channels; <EtherCATInfo>-<Descriptions>-<Devices>-<Device>-<Mailbox>-<CoE>: DS402Channels |
1218 if mb is not None: |
1587 ds402ch = False |
1219 coe = mb.getCoE() |
1588 if mb is not None: |
1220 if coe is not None: |
1589 coe = mb.getCoE() |
1221 ds402ch = coe.getDS402Channels() |
1590 if coe is not None: |
|
1591 ds402ch = coe.getDS402Channels() |
1222 eeprom.append("01" if ds402ch in [True, 1] else "00") |
1592 eeprom.append("01" if ds402ch in [True, 1] else "00") |
1223 |
1593 |
1224 # word 6 : SysmanClass(reserved) and Flags |
1594 # word 6 : SysmanClass(reserved) and Flags |
1225 eeprom.append("00") # reserved |
1595 eeprom.append("00") # reserved |
1226 # Flags |
1596 # Flags |
1565 Command example : "ethercat rescan -p 0" |
1953 Command example : "ethercat rescan -p 0" |
1566 """ |
1954 """ |
1567 _error, _return_val = self.Controler.RemoteExec(RESCAN % (self.Controler.GetSlavePos()), return_val=None) |
1955 _error, _return_val = self.Controler.RemoteExec(RESCAN % (self.Controler.GetSlavePos()), return_val=None) |
1568 |
1956 |
1569 # ------------------------------------------------------------------------------- |
1957 # ------------------------------------------------------------------------------- |
|
1958 # Used DC Configuration |
|
1959 #------------------------------------------------------------------------------- |
|
1960 def LoadESIData(self): |
|
1961 return_data = [] |
|
1962 slave = self.Controler.CTNParent.GetSlave(self.Controler.GetSlavePos()) |
|
1963 type_infos = slave.getType() |
|
1964 device, alignment = self.Controler.CTNParent.GetModuleInfos(type_infos) |
|
1965 if device.getDc() is not None: |
|
1966 for OpMode in device.getDc().getOpMode(): |
|
1967 temp_data = { |
|
1968 "desc" : OpMode.getDesc() if OpMode.getDesc() is not None else "Unused", |
|
1969 "assign_activate" : OpMode.getAssignActivate() \ |
|
1970 if OpMode.getAssignActivate() is not None else "#x0000", |
|
1971 "cycletime_sync0" : OpMode.getCycleTimeSync0().getcontent() \ |
|
1972 if OpMode.getCycleTimeSync0() is not None else None, |
|
1973 "shifttime_sync0" : OpMode.getShiftTimeSync0().getcontent() \ |
|
1974 if OpMode.getShiftTimeSync0() is not None else None, |
|
1975 "cycletime_sync1" : OpMode.getShiftTimeSync1().getcontent() \ |
|
1976 if OpMode.getShiftTimeSync1() is not None else None, |
|
1977 "shifttime_sync1" : OpMode.getShiftTimeSync1().getcontent() \ |
|
1978 if OpMode.getShiftTimeSync1() is not None else None |
|
1979 } |
|
1980 |
|
1981 if OpMode.getCycleTimeSync0() is not None: |
|
1982 temp_data["cycletime_sync0_factor"] = OpMode.getCycleTimeSync0().getFactor() |
|
1983 |
|
1984 if OpMode.getCycleTimeSync1() is not None: |
|
1985 temp_data["cycletime_sync1_factor"] = OpMode.getCycleTimeSync1().getFactor() |
|
1986 |
|
1987 return_data.append(temp_data) |
|
1988 |
|
1989 return return_data |
|
1990 |
|
1991 #------------------------------------------------------------------------------- |
1570 # Common Use Methods |
1992 # Common Use Methods |
1571 # ------------------------------------------------------------------------------- |
1993 # ------------------------------------------------------------------------------- |
1572 def CheckConnect(self, cyclic_flag): |
1994 def CheckConnect(self, cyclic_flag): |
1573 """ |
1995 """ |
1574 Check connection status (1) between Beremiz and the master (2) between the master and the slave. |
1996 Check connection status (1) between Beremiz and the master (2) between the master and the slave. |