Merge remote-tracking branch 'remotes/les_software/master'
Conflicts: CANLibrary/CanMessage.py
This commit is contained in:
commit
571df6a1ec
17 changed files with 360 additions and 54 deletions
46
.gitignore
vendored
Normal file
46
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Ignore-Datei selbst ausschließen
|
||||
#.gitignore
|
||||
.gitmodules
|
||||
Thumbs.db
|
||||
|
||||
# Bestimmte Dateien ausschließen
|
||||
cache.dat
|
||||
|
||||
# Es können Wildcards (*,?) verwendet werden:
|
||||
*.exe
|
||||
*.dll
|
||||
*.dsbackup
|
||||
*.avrsln
|
||||
*.avrsuo
|
||||
*.avrgccproj
|
||||
*.aps
|
||||
*.atsln
|
||||
*.atsuo
|
||||
*.cproj
|
||||
*.aws
|
||||
*.xml
|
||||
*.xslt
|
||||
*.aux
|
||||
*.dvi
|
||||
*.lof
|
||||
*.log
|
||||
*.lot
|
||||
*.out
|
||||
*.synctex.gz
|
||||
*.toc
|
||||
*.pyc
|
||||
*.patch
|
||||
*.csv
|
||||
.project
|
||||
.pydevproject
|
||||
tmp?.dat
|
||||
|
||||
# Auch Verzeichnisse kann man ausschießen:
|
||||
*default/
|
||||
*Debug/
|
||||
*bin/
|
||||
*ADC/
|
||||
*CAN/
|
||||
*UART/
|
||||
.*/
|
||||
CANLibrary/
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?>
|
||||
|
||||
<pydev_project>
|
||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/CANLibrary</path>
|
||||
<path>/CANLibrary/PCANBasic</path>
|
||||
<path>/CANLibrary/pycrc</path>
|
||||
<path>/vonPhilipp.git</path>
|
||||
<path>/vonPhilipp.git/PCANBasic</path>
|
||||
<path>/vonPhilipp.git/pycrc</path>
|
||||
</pydev_pathproperty>
|
||||
</pydev_project>
|
||||
|
|
|
|||
|
|
@ -2,5 +2,6 @@ eclipse.preferences.version=1
|
|||
encoding//CANLibrary/CanMessage.py=UTF-8
|
||||
encoding//CANLibrary/CanSignal.py=UTF-8
|
||||
encoding//CANLibrary/PCan.py=UTF-8
|
||||
encoding//CANLibrary/Sym2Lib.py=UTF-8
|
||||
encoding//CANLibrary/example.py=UTF-8
|
||||
encoding//pycrc/crc_algorithms.py=latin1
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class CanMessage(object):
|
|||
self.Id = MessageId
|
||||
self.CycleTime = MessageCycleTime
|
||||
self.Label = Label
|
||||
self.timestamp = 0
|
||||
|
||||
# create an initial array of message data
|
||||
for i in range(0, self.Length):
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class CanSignal(object):
|
|||
self.Label = SignalLabel
|
||||
self.Data = []
|
||||
|
||||
self.Enum = None
|
||||
|
||||
self.SetData(SignalData)
|
||||
|
||||
|
||||
|
|
@ -55,6 +57,9 @@ class CanSignal(object):
|
|||
for i in range(0, int(self.Length/8)+1):
|
||||
tmpData += ( self.Data[i] << (8*i) )
|
||||
|
||||
tmpData = int( (tmpData * self.Scaling) + self.Offset )
|
||||
tmpData = ( (tmpData * self.Scaling) + self.Offset )
|
||||
|
||||
return tmpData
|
||||
|
||||
def SetEnum(self, Enum):
|
||||
self.Enum = Enum
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Created on 06.07.2012
|
|||
|
||||
import PCANBasic # PCANBasic wrapper library provided by PEAK
|
||||
import sys
|
||||
from time import sleep
|
||||
|
||||
|
||||
class PcanAdapter(object):
|
||||
|
|
@ -16,17 +17,21 @@ class PcanAdapter (object):
|
|||
'''
|
||||
|
||||
# Class variables:
|
||||
Baudrate = { '125k' : PCANBasic.PCAN_BAUD_125K,
|
||||
Baudrate = { '100k' : PCANBasic.PCAN_BAUD_100K,
|
||||
'125k' : PCANBasic.PCAN_BAUD_125K,
|
||||
'250k' : PCANBasic.PCAN_BAUD_250K,
|
||||
'500k' : PCANBasic.PCAN_BAUD_500K,
|
||||
'1000k' : PCANBasic.PCAN_BAUD_1M }
|
||||
'1000k': PCANBasic.PCAN_BAUD_1M
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, Baudrate):
|
||||
def __init__(self, Baudrate, debug = True):
|
||||
'''
|
||||
Constructor.
|
||||
@param Baudrate: Baud rate from the PcanAdapter. Baud rate dictionary
|
||||
'''
|
||||
# Instance variables:
|
||||
self.debug = debug
|
||||
self.Messages = {}
|
||||
self.Channel = PCANBasic.PCAN_USBBUS1
|
||||
self.Pcan = PCANBasic.PCANBasic()
|
||||
|
|
@ -50,6 +55,20 @@ class PcanAdapter (object):
|
|||
|
||||
self.Messages.update({CanMessage.Label: CanMessage})
|
||||
|
||||
def _getIDs_(self):
|
||||
_ids_ = {}
|
||||
for key in self.Messages.keys():
|
||||
_ids_.update( { self.Messages[key].Id : key } )
|
||||
return _ids_
|
||||
|
||||
def getMessageName(self, ID):
|
||||
_ids_ = self._getIDs_()
|
||||
if ID in _ids_.keys():
|
||||
return _ids_[ID]
|
||||
else:
|
||||
print 'ERROR: Message ID %s not defined' % ID
|
||||
return False
|
||||
|
||||
def removeMessage(self, CanMessageLabel):
|
||||
try:
|
||||
self.Messages.pop(CanMessageLabel)
|
||||
|
|
@ -67,13 +86,15 @@ class PcanAdapter (object):
|
|||
self.Pcan.Uninitialize(PCANBasic.PCAN_NONEBUS)
|
||||
status = self.Pcan.Initialize(self.Channel, self.Baudrate)
|
||||
if status != PCANBasic.PCAN_ERROR_OK:
|
||||
if self.debug:
|
||||
print 'Error: ', self.Pcan.GetErrorText(status, 0)[1]
|
||||
sys.exit("PCAN initialisation error")
|
||||
|
||||
if self.debug:
|
||||
print("PCAN initialised")
|
||||
self.isInitialised = True
|
||||
|
||||
channel, hwId = self.Pcan.GetValue( self.Channel, PCANBasic.PCAN_DEVICE_NUMBER )
|
||||
if self.debug:
|
||||
print 'DeviceNumber: ', hwId
|
||||
|
||||
def uninitialize(self):
|
||||
|
|
@ -83,12 +104,13 @@ class PcanAdapter (object):
|
|||
if self.isInitialised:
|
||||
status = self.Pcan.Uninitialize(self.Channel)
|
||||
if status != PCANBasic.PCAN_ERROR_OK:
|
||||
if self.debug:
|
||||
print 'Error: ', self.Pcan.GetErrorText(status, 0)[1]
|
||||
sys.exit("PCAN deinitialisation error")
|
||||
|
||||
if self.debug:
|
||||
print("PCAN deinitialised")
|
||||
|
||||
def sendMessage(self, Message):
|
||||
def sendMessage(self, Message, rtr = False):
|
||||
'''
|
||||
Sends the CanMessage object Message onto the CAN bus.
|
||||
|
||||
|
|
@ -98,6 +120,9 @@ class PcanAdapter (object):
|
|||
|
||||
msg = PCANBasic.TPCANMsg() # create a new PCAN message object
|
||||
msg.ID = Message.Id # copy the ID
|
||||
if rtr:
|
||||
msg.MSGTYPE = PCANBasic.PCAN_MESSAGE_RTR # Message type is Remote-Transfer-Request
|
||||
else:
|
||||
msg.MSGTYPE = PCANBasic.PCAN_MESSAGE_STANDARD # Message type is standard (not extended)
|
||||
msg.LEN = Message.Length # copy the length
|
||||
msg.DATA[0:Message.Length] = Message.Data # copy the message data into the PCAN message object
|
||||
|
|
@ -105,7 +130,7 @@ class PcanAdapter (object):
|
|||
self.Pcan.Write(self.Channel, msg) # write it onto the Bus
|
||||
#print ('Message ' + Message.Label + ' written.')
|
||||
|
||||
def receiveMessage(self):
|
||||
def receiveMessage(self, block = False):
|
||||
'''
|
||||
Tries to receive a CAN message and puts its data into the according CanMessage object's Data field.
|
||||
This method should be called frequently.
|
||||
|
|
@ -127,5 +152,8 @@ class PcanAdapter (object):
|
|||
for i in range(0, self.Messages[msgKey].Length):
|
||||
self.Messages[msgKey].Data[i] = msg.DATA[i]
|
||||
self.Messages[msgKey].decomposeData()
|
||||
elif result == PCANBasic.PCAN_ERROR_QRCVEMPTY:
|
||||
break
|
||||
self.Messages[msgKey].timestamp = timestamp.micros + 1000 * timestamp.millis + 0xFFFFFFFF * 1000 * timestamp.millis_overflow
|
||||
return msgKey
|
||||
elif result == PCANBasic.PCAN_ERROR_QRCVEMPTY and block == False:
|
||||
return None
|
||||
sleep(0.01)
|
||||
|
|
|
|||
202
CANLibrary/Sym2Lib.py
Normal file
202
CANLibrary/Sym2Lib.py
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
|
||||
'''
|
||||
Created on 12.12.2013
|
||||
|
||||
@author: Philipp Rauch
|
||||
@version: 1.0
|
||||
@attention: No support for multiplex; until now no motorola support
|
||||
'''
|
||||
from CanMessage import CanMessage
|
||||
from CanSignal import CanSignal
|
||||
from pprint import pprint
|
||||
|
||||
def readSym(symfile):
|
||||
'''
|
||||
Read in a .sym-file created with PEAK PCAN Symbol Editor containing CAN message and signal definitions.
|
||||
'''
|
||||
sym = open(symfile, "r") # File handle to the .sym-file
|
||||
|
||||
message = {} # Decoded message descriptions
|
||||
tmp = {} #
|
||||
enums = {} #
|
||||
ignore = True # temporary ignore flag for message types
|
||||
enums_bool = False #
|
||||
name = "" #
|
||||
|
||||
for line in sym:
|
||||
line = line.split("//")[0].strip()
|
||||
#print line
|
||||
|
||||
if line == "":
|
||||
if ignore:
|
||||
continue
|
||||
if name == "":
|
||||
continue
|
||||
if not tmp.has_key("CycleTime"):
|
||||
tmp["CycleTime"] = 0
|
||||
message[name] = tmp
|
||||
tmp = {}
|
||||
name = ""
|
||||
continue
|
||||
|
||||
if ignore and not line[0] == "{":
|
||||
continue
|
||||
elif enums_bool and not line[0] == "{":
|
||||
arg = line.strip()
|
||||
if arg.find("enum") == 0:
|
||||
arg = line.split("(")
|
||||
ident =arg[0].split(" ")[1]
|
||||
enums[ident] = {}
|
||||
arg = arg[1]
|
||||
if ")" in arg:
|
||||
arg = (arg.split(")"))[0]
|
||||
tm = arg.split(",")
|
||||
else:
|
||||
tm = arg.split(",")
|
||||
del tm[-1]
|
||||
for i in range(len(tm)):
|
||||
tm[i] = tm[i].split("=")
|
||||
tm[i][0] = int(tm[i][0].strip())
|
||||
tm[i][1] = tm[i][1].strip("\"")
|
||||
for i in tm:
|
||||
enums[ident][i[0]] = i[1]
|
||||
|
||||
if line[0] == "{":
|
||||
ignore = False
|
||||
enums_bool = False
|
||||
modus = line.strip("{} \n")
|
||||
if modus == "ENUMS":
|
||||
enums_bool = True
|
||||
ignore = False # do not ignore ENUM definitions
|
||||
elif modus == "SEND":
|
||||
ignore = False # do not ignore SEND type message definitions
|
||||
elif modus == "RECEIVE":
|
||||
ignore = False # do not ignore RECEIVE type message definitions
|
||||
elif modus == "SENDRECEIVE":
|
||||
ignore = False # do not ignore SENDRECEIVE type message definitions
|
||||
elif modus == "VIRTUALVARS":
|
||||
ignore = True # ignore VIRTUALVARS definitions
|
||||
|
||||
elif line[0] == "[":
|
||||
name = line.strip("[] \n")
|
||||
|
||||
elif line.find("ID") == 0:
|
||||
msg_id = line.split("=")[1].strip().rstrip("h")
|
||||
tmp["ID"] = int(msg_id, 16) # convert hex to int
|
||||
|
||||
elif line.find("DLC") == 0:
|
||||
tmp["DLC"] = int(line.split("=")[1].strip())
|
||||
|
||||
elif line.find("CycleTime") == 0:
|
||||
tmp["CycleTime"] = int(line.split("=")[1].strip())
|
||||
|
||||
elif line.find("Var") == 0:
|
||||
arg = line.split("=")[1].strip().split(" ")
|
||||
signal = {}
|
||||
signal["factor"] = 1
|
||||
signal["data"] = 0
|
||||
signal["offset"] = 0
|
||||
|
||||
titel = arg[0]
|
||||
del arg[0]
|
||||
|
||||
signal["type"] = arg[0]
|
||||
del arg[0]
|
||||
|
||||
signal["begin"] = int(arg[0].split(",")[0])
|
||||
signal["length"] = int(arg[0].split(",")[1])
|
||||
del arg[0]
|
||||
|
||||
if "-m" in arg:
|
||||
signal["format"] = "motorola"
|
||||
arg.remove("-m")
|
||||
else:
|
||||
signal["format"] = "intel"
|
||||
|
||||
if "-b" in arg:
|
||||
signal["output"] = "binary"
|
||||
arg.remove("-b")
|
||||
elif "-h" in arg:
|
||||
signal["output"] = "hexadecimal"
|
||||
arg.remove("-h")
|
||||
else:
|
||||
signal["output"] = "decimal"
|
||||
|
||||
for i in arg:
|
||||
a = i.split(":")
|
||||
if a[0] == "/u":
|
||||
signal["unit"] = a[1]
|
||||
elif a[0] == "/f":
|
||||
signal["factor"] = float(a[1])
|
||||
elif a[0] == "/o":
|
||||
signal["offset"] = float(a[1])
|
||||
elif a[0] == "/d":
|
||||
signal["data"] = float(a[1])
|
||||
elif a[0] == "/e":
|
||||
signal["enum"] = enums[a[1]]
|
||||
|
||||
tmp[titel] = signal
|
||||
return message
|
||||
|
||||
def Sym2Code(symfile, adapter):
|
||||
'''
|
||||
Create code for message configuration.
|
||||
The code created can be used for static message defintions where the .sym-file shall not be included into the project.
|
||||
'''
|
||||
mes = readSym(symfile)
|
||||
for i in mes.keys():
|
||||
if i == "ENUMS":
|
||||
print { i : mes[i] }
|
||||
continue
|
||||
print "%s.addMessage(CanMessage(%s, %s, %s, \'%s\')" % (adapter, hex(mes[i]["ID"]), mes[i]["DLC"], mes[i]["CycleTime"], i)
|
||||
for sig in mes[i]:
|
||||
if isinstance(mes[i].get(sig), dict):
|
||||
print "%s.Messages[\'%s\'].addSignal(CanSignal(%s, %s, %s, %s, %s, \'%s\')" % (adapter, i, mes[i][sig]["begin"], mes[i][sig]["length"], mes[i][sig]["offset"], mes[i][sig]["factor"], mes[i][sig]["data"], sig)
|
||||
if "enum" in mes[i][sig].keys():
|
||||
pprint({ "enum" : mes[i][sig]["enum"]})
|
||||
print ""
|
||||
|
||||
def Add2Adapter(pcan, symfile):
|
||||
'''
|
||||
Add message configuration to a pcan adapter instance.
|
||||
'''
|
||||
mes = readSym(symfile)
|
||||
print ""
|
||||
for i in mes.keys():
|
||||
if i == "ENUMS":
|
||||
continue
|
||||
pcan.addMessage(CanMessage(mes[i]["ID"],
|
||||
mes[i]["DLC"],
|
||||
mes[i]["CycleTime"],
|
||||
i))
|
||||
|
||||
print "adding message to pcan: ID \'%s\', Name \'%s\'" % (hex(mes[i]["ID"]), i)
|
||||
signals = []
|
||||
for sig in mes[i]:
|
||||
if isinstance(mes[i].get(sig), dict):
|
||||
pcan.Messages[i].addSignal(CanSignal(mes[i][sig]["begin"],
|
||||
mes[i][sig]["length"],
|
||||
mes[i][sig]["offset"],
|
||||
mes[i][sig]["factor"],
|
||||
mes[i][sig]["data"],
|
||||
sig))
|
||||
if "enum" in mes[i][sig].keys():
|
||||
pcan.Messages[i].Signals[sig].SetEnum(mes[i][sig]["enum"])
|
||||
signals.append(sig)
|
||||
print ' signals: %s\n' % ', '.join(signals)
|
||||
return pcan
|
||||
|
||||
def _get_easy_Dict_(mes):
|
||||
symDict = {}
|
||||
for i in mes.keys():
|
||||
symDict[i] = []
|
||||
for sig in mes[i]:
|
||||
if isinstance(mes[i].get(sig), dict):
|
||||
symDict[i].append(sig)
|
||||
return symDict
|
||||
|
||||
|
||||
|
||||
|
||||
Sym2Code("Test.sym", "pcan")
|
||||
13
CANLibrary/Test.sym
Normal file
13
CANLibrary/Test.sym
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
FormatVersion=5.0 // Do not edit!
|
||||
Title="Test"
|
||||
|
||||
{SEND}
|
||||
|
||||
[Test]
|
||||
ID=123h
|
||||
DLC=8
|
||||
CycleTime=100
|
||||
Var=Var1 unsigned 0,8 /u:Volt /f:2
|
||||
Var=Var2 signed 8,21 /u:Ampere
|
||||
Var=Var4 float 32,32
|
||||
|
||||
|
|
@ -9,6 +9,8 @@ Example for creating and sending CAN messages via PCAN using the CanMessage, Can
|
|||
from CanMessage import CanMessage
|
||||
from CanSignal import CanSignal
|
||||
from PCan import PcanAdapter
|
||||
#from Sym2Lib import addtoPCAN, printCode
|
||||
from Sym2Lib import Add2Adapter
|
||||
import time
|
||||
|
||||
print '\nCreate a PCAN adapter'
|
||||
|
|
@ -58,6 +60,16 @@ pcan.Messages['mMotor_2'].composeData()
|
|||
print 'mMotor_2.Data', pcan.Messages['mMotor_2'].Data
|
||||
pcan.sendMessage(pcan.Messages['mMotor_2'])
|
||||
|
||||
# Test Sym2Lib
|
||||
Add2Adapter(pcan, "Test.sym")
|
||||
|
||||
pcan.Messages['Test'].Signals['Var1'].SetData( 30 )
|
||||
pcan.Messages['Test'].composeData()
|
||||
|
||||
pcan.sendMessage(pcan.Messages['Test'])
|
||||
|
||||
|
||||
|
||||
# receive messages, if the signal MO1_Drehzahl has changed, print the new value
|
||||
while True:
|
||||
#print 'send'
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
pycrc/pycrc.pyc
BIN
pycrc/pycrc.pyc
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue