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"?>
<?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>

View file

@ -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

View file

@ -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):

View file

@ -28,13 +28,15 @@ class CanSignal(object):
self.Length = SignalLength
self.Offset = SignalOffset
self.Scaling = SignalScaling
self.Label = SignalLabel
self.Data = []
self.SetData(SignalData)
self.Enum = None
self.SetData(SignalData)
def SetData(self, SignalData):
'''
Update the data of the Signal.
@ -47,14 +49,17 @@ class CanSignal(object):
self.Data = []
for i in range(0, int(self.Length/8)+1):
self.Data.append ( (tmpData >> (8*i) ) & 0xff )
def GetData(self):
'''
'''
tmpData = 0
for i in range(0, int(self.Length/8)+1):
tmpData += ( self.Data[i] << (8*i) )
tmpData = int( (tmpData * self.Scaling) + self.Offset )
return tmpData
tmpData = ( (tmpData * self.Scaling) + self.Offset )
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 sys
from time import sleep
class PcanAdapter (object):
class PcanAdapter(object):
'''
A class for controlling a PEAK PCan adapter. Based on the PCANBasic library.
'''
# 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 }
def __init__(self, Baudrate):
'1000k': PCANBasic.PCAN_BAUD_1M
}
def __init__(self, Baudrate, debug = True):
'''
Constructor.
@param Baudrate: Baud rate from the PcanAdapter. Baud rate dictionary
'''
# Instance variables:
self.Messages = {}
# Instance variables:
self.debug = debug
self.Messages = {}
self.Channel = PCANBasic.PCAN_USBBUS1
self.Pcan = PCANBasic.PCANBasic()
self.Baudrate = Baudrate # Baud rate from PCANBasic
self.isInitialised = False
def __del__(self):
'''
Destructor.
@ -40,26 +45,40 @@ class PcanAdapter (object):
'''
print '\nDestructor:'
self.uninitialize()
def addMessage(self, CanMessage):
'''
Add a Message of type CanMessage to the list of messages.
@param CanMessage: The message to add to the list of messages.
'''
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)
except:
pass
def clearMessages(self):
self.Messages = {}
def initialize(self):
'''
Initializes the PCAN adapter.
@ -67,15 +86,17 @@ class PcanAdapter (object):
self.Pcan.Uninitialize(PCANBasic.PCAN_NONEBUS)
status = self.Pcan.Initialize(self.Channel, self.Baudrate)
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")
print("PCAN initialised")
if self.debug:
print("PCAN initialised")
self.isInitialised = True
channel, hwId = self.Pcan.GetValue( self.Channel, PCANBasic.PCAN_DEVICE_NUMBER )
print 'DeviceNumber: ', hwId
if self.debug:
print 'DeviceNumber: ', hwId
def uninitialize(self):
'''
Unitialize the PCAN adapter.
@ -83,29 +104,33 @@ class PcanAdapter (object):
if self.isInitialised:
status = self.Pcan.Uninitialize(self.Channel)
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")
print("PCAN deinitialised")
def sendMessage(self, Message):
if self.debug:
print("PCAN deinitialised")
def sendMessage(self, Message, rtr = False):
'''
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.
msg = PCANBasic.TPCANMsg() # create a new PCAN message object
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.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
#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.
@ -113,7 +138,7 @@ class PcanAdapter (object):
while True: # do this while messages are read from the bus
result, msg, timestamp = self.Pcan.Read(self.Channel)
if result == PCANBasic.PCAN_ERROR_OK:
# loop through the messages and look for one that matches the received message:
for msgKey in self.Messages:
@ -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
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 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.

Binary file not shown.