Merge remote-tracking branch 'remotes/les_software/master'

Conflicts:
	CANLibrary/CanMessage.py
This commit is contained in:
Christian Sueltrop 2014-02-21 17:05:21 +01:00
commit 571df6a1ec
17 changed files with 360 additions and 54 deletions

46
.gitignore vendored Normal file
View 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/

View file

@ -1,12 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?> <?eclipse-pydev version="1.0"?><pydev_project>
<pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property> <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_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/CANLibrary</path> <path>/vonPhilipp.git</path>
<path>/CANLibrary/PCANBasic</path> <path>/vonPhilipp.git/PCANBasic</path>
<path>/CANLibrary/pycrc</path> <path>/vonPhilipp.git/pycrc</path>
</pydev_pathproperty> </pydev_pathproperty>
</pydev_project> </pydev_project>

View file

@ -2,5 +2,6 @@ eclipse.preferences.version=1
encoding//CANLibrary/CanMessage.py=UTF-8 encoding//CANLibrary/CanMessage.py=UTF-8
encoding//CANLibrary/CanSignal.py=UTF-8 encoding//CANLibrary/CanSignal.py=UTF-8
encoding//CANLibrary/PCan.py=UTF-8 encoding//CANLibrary/PCan.py=UTF-8
encoding//CANLibrary/Sym2Lib.py=UTF-8
encoding//CANLibrary/example.py=UTF-8 encoding//CANLibrary/example.py=UTF-8
encoding//pycrc/crc_algorithms.py=latin1 encoding//pycrc/crc_algorithms.py=latin1

View file

@ -48,6 +48,7 @@ class CanMessage(object):
self.Id = MessageId self.Id = MessageId
self.CycleTime = MessageCycleTime self.CycleTime = MessageCycleTime
self.Label = Label self.Label = Label
self.timestamp = 0
# create an initial array of message data # create an initial array of message data
for i in range(0, self.Length): for i in range(0, self.Length):

View file

@ -28,13 +28,15 @@ class CanSignal(object):
self.Length = SignalLength self.Length = SignalLength
self.Offset = SignalOffset self.Offset = SignalOffset
self.Scaling = SignalScaling self.Scaling = SignalScaling
self.Label = SignalLabel self.Label = SignalLabel
self.Data = [] self.Data = []
self.SetData(SignalData) self.Enum = None
self.SetData(SignalData)
def SetData(self, SignalData): def SetData(self, SignalData):
''' '''
Update the data of the Signal. Update the data of the Signal.
@ -47,14 +49,17 @@ class CanSignal(object):
self.Data = [] self.Data = []
for i in range(0, int(self.Length/8)+1): for i in range(0, int(self.Length/8)+1):
self.Data.append ( (tmpData >> (8*i) ) & 0xff ) self.Data.append ( (tmpData >> (8*i) ) & 0xff )
def GetData(self): def GetData(self):
''' '''
''' '''
tmpData = 0 tmpData = 0
for i in range(0, int(self.Length/8)+1): for i in range(0, int(self.Length/8)+1):
tmpData += ( self.Data[i] << (8*i) ) tmpData += ( self.Data[i] << (8*i) )
tmpData = int( (tmpData * self.Scaling) + self.Offset ) tmpData = ( (tmpData * self.Scaling) + self.Offset )
return tmpData return tmpData
def SetEnum(self, Enum):
self.Enum = Enum

View file

@ -8,31 +8,36 @@ Created on 06.07.2012
import PCANBasic # PCANBasic wrapper library provided by PEAK import PCANBasic # PCANBasic wrapper library provided by PEAK
import sys import sys
from time import sleep
class PcanAdapter (object): class PcanAdapter(object):
''' '''
A class for controlling a PEAK PCan adapter. Based on the PCANBasic library. A class for controlling a PEAK PCan adapter. Based on the PCANBasic library.
''' '''
# Class variables: # 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, '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. Constructor.
@param Baudrate: Baud rate from the PcanAdapter. Baud rate dictionary @param Baudrate: Baud rate from the PcanAdapter. Baud rate dictionary
''' '''
# Instance variables: # Instance variables:
self.Messages = {} self.debug = debug
self.Messages = {}
self.Channel = PCANBasic.PCAN_USBBUS1 self.Channel = PCANBasic.PCAN_USBBUS1
self.Pcan = PCANBasic.PCANBasic() self.Pcan = PCANBasic.PCANBasic()
self.Baudrate = Baudrate # Baud rate from PCANBasic self.Baudrate = Baudrate # Baud rate from PCANBasic
self.isInitialised = False self.isInitialised = False
def __del__(self): def __del__(self):
''' '''
Destructor. Destructor.
@ -40,26 +45,40 @@ class PcanAdapter (object):
''' '''
print '\nDestructor:' print '\nDestructor:'
self.uninitialize() self.uninitialize()
def addMessage(self, CanMessage): def addMessage(self, CanMessage):
''' '''
Add a Message of type CanMessage to the list of messages. Add a Message of type CanMessage to the list of messages.
@param CanMessage: The message to add to the list of messages. @param CanMessage: The message to add to the list of messages.
''' '''
self.Messages.update({CanMessage.Label: CanMessage}) 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): def removeMessage(self, CanMessageLabel):
try: try:
self.Messages.pop(CanMessageLabel) self.Messages.pop(CanMessageLabel)
except: except:
pass pass
def clearMessages(self): def clearMessages(self):
self.Messages = {} self.Messages = {}
def initialize(self): def initialize(self):
''' '''
Initializes the PCAN adapter. Initializes the PCAN adapter.
@ -67,15 +86,17 @@ class PcanAdapter (object):
self.Pcan.Uninitialize(PCANBasic.PCAN_NONEBUS) self.Pcan.Uninitialize(PCANBasic.PCAN_NONEBUS)
status = self.Pcan.Initialize(self.Channel, self.Baudrate) status = self.Pcan.Initialize(self.Channel, self.Baudrate)
if status != PCANBasic.PCAN_ERROR_OK: if status != PCANBasic.PCAN_ERROR_OK:
print 'Error: ', self.Pcan.GetErrorText(status, 0)[1] if self.debug:
print 'Error: ', self.Pcan.GetErrorText(status, 0)[1]
sys.exit("PCAN initialisation error") sys.exit("PCAN initialisation error")
if self.debug:
print("PCAN initialised") print("PCAN initialised")
self.isInitialised = True self.isInitialised = True
channel, hwId = self.Pcan.GetValue( self.Channel, PCANBasic.PCAN_DEVICE_NUMBER ) channel, hwId = self.Pcan.GetValue( self.Channel, PCANBasic.PCAN_DEVICE_NUMBER )
print 'DeviceNumber: ', hwId if self.debug:
print 'DeviceNumber: ', hwId
def uninitialize(self): def uninitialize(self):
''' '''
Unitialize the PCAN adapter. Unitialize the PCAN adapter.
@ -83,29 +104,33 @@ class PcanAdapter (object):
if self.isInitialised: if self.isInitialised:
status = self.Pcan.Uninitialize(self.Channel) status = self.Pcan.Uninitialize(self.Channel)
if status != PCANBasic.PCAN_ERROR_OK: if status != PCANBasic.PCAN_ERROR_OK:
print 'Error: ', self.Pcan.GetErrorText(status, 0)[1] if self.debug:
print 'Error: ', self.Pcan.GetErrorText(status, 0)[1]
sys.exit("PCAN deinitialisation error") sys.exit("PCAN deinitialisation error")
if self.debug:
print("PCAN deinitialised") print("PCAN deinitialised")
def sendMessage(self, Message): def sendMessage(self, Message, rtr = False):
''' '''
Sends the CanMessage object Message onto the CAN bus. Sends the CanMessage object Message onto the CAN bus.
@param Messge: The CanMessage object that is to be sent. @param Messge: The CanMessage object that is to be sent.
''' '''
Message.composeData() # compose message data array from the signals in Message.Signals. Message.composeData() # compose message data array from the signals in Message.Signals.
msg = PCANBasic.TPCANMsg() # create a new PCAN message object msg = PCANBasic.TPCANMsg() # create a new PCAN message object
msg.ID = Message.Id # copy the ID msg.ID = Message.Id # copy the ID
msg.MSGTYPE = PCANBasic.PCAN_MESSAGE_STANDARD # Message type is standard (not extended) 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.LEN = Message.Length # copy the length
msg.DATA[0:Message.Length] = Message.Data # copy the message data into the PCAN message object msg.DATA[0:Message.Length] = Message.Data # copy the message data into the PCAN message object
self.Pcan.Write(self.Channel, msg) # write it onto the Bus self.Pcan.Write(self.Channel, msg) # write it onto the Bus
#print ('Message ' + Message.Label + ' written.') #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. Tries to receive a CAN message and puts its data into the according CanMessage object's Data field.
This method should be called frequently. This method should be called frequently.
@ -113,7 +138,7 @@ class PcanAdapter (object):
while True: # do this while messages are read from the bus while True: # do this while messages are read from the bus
result, msg, timestamp = self.Pcan.Read(self.Channel) result, msg, timestamp = self.Pcan.Read(self.Channel)
if result == PCANBasic.PCAN_ERROR_OK: if result == PCANBasic.PCAN_ERROR_OK:
# loop through the messages and look for one that matches the received message: # loop through the messages and look for one that matches the received message:
for msgKey in self.Messages: for msgKey in self.Messages:
@ -127,5 +152,8 @@ class PcanAdapter (object):
for i in range(0, self.Messages[msgKey].Length): for i in range(0, self.Messages[msgKey].Length):
self.Messages[msgKey].Data[i] = msg.DATA[i] self.Messages[msgKey].Data[i] = msg.DATA[i]
self.Messages[msgKey].decomposeData() self.Messages[msgKey].decomposeData()
elif result == PCANBasic.PCAN_ERROR_QRCVEMPTY: self.Messages[msgKey].timestamp = timestamp.micros + 1000 * timestamp.millis + 0xFFFFFFFF * 1000 * timestamp.millis_overflow
break return msgKey
elif result == PCANBasic.PCAN_ERROR_QRCVEMPTY and block == False:
return None
sleep(0.01)

202
CANLibrary/Sym2Lib.py Normal file
View 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
View 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

View file

@ -9,6 +9,8 @@ Example for creating and sending CAN messages via PCAN using the CanMessage, Can
from CanMessage import CanMessage from CanMessage import CanMessage
from CanSignal import CanSignal from CanSignal import CanSignal
from PCan import PcanAdapter from PCan import PcanAdapter
#from Sym2Lib import addtoPCAN, printCode
from Sym2Lib import Add2Adapter
import time import time
print '\nCreate a PCAN adapter' print '\nCreate a PCAN adapter'
@ -58,6 +60,16 @@ pcan.Messages['mMotor_2'].composeData()
print 'mMotor_2.Data', pcan.Messages['mMotor_2'].Data print 'mMotor_2.Data', pcan.Messages['mMotor_2'].Data
pcan.sendMessage(pcan.Messages['mMotor_2']) 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 # receive messages, if the signal MO1_Drehzahl has changed, print the new value
while True: while True:
#print 'send' #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.

Binary file not shown.