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

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

View file

@ -8,25 +8,30 @@ 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 }
'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,14 +86,16 @@ 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):
'''
@ -83,12 +104,13 @@ 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")
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.
@ -98,14 +120,17 @@ class PcanAdapter (object):
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.
@ -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.