diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9435d6 --- /dev/null +++ b/.gitignore @@ -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/ diff --git a/.pydevproject b/.pydevproject index 546e447..2f1c7f7 100644 --- a/.pydevproject +++ b/.pydevproject @@ -1,12 +1,10 @@ - - - + Default python 2.7 -/CANLibrary -/CANLibrary/PCANBasic -/CANLibrary/pycrc +/vonPhilipp.git +/vonPhilipp.git/PCANBasic +/vonPhilipp.git/pycrc diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index 77d664b..24ecbd3 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -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 diff --git a/CANLibrary/CanMessage.py b/CANLibrary/CanMessage.py index 2ae64fe..6ce83d9 100644 --- a/CANLibrary/CanMessage.py +++ b/CANLibrary/CanMessage.py @@ -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): diff --git a/CANLibrary/CanSignal.py b/CANLibrary/CanSignal.py index fe932d1..a98f5e9 100644 --- a/CANLibrary/CanSignal.py +++ b/CANLibrary/CanSignal.py @@ -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 \ No newline at end of file + + tmpData = ( (tmpData * self.Scaling) + self.Offset ) + + return tmpData + + def SetEnum(self, Enum): + self.Enum = Enum diff --git a/CANLibrary/PCan.py b/CANLibrary/PCan.py index 1fa0148..4e3c734 100644 --- a/CANLibrary/PCan.py +++ b/CANLibrary/PCan.py @@ -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) diff --git a/CANLibrary/Sym2Lib.py b/CANLibrary/Sym2Lib.py new file mode 100644 index 0000000..2aae65e --- /dev/null +++ b/CANLibrary/Sym2Lib.py @@ -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") diff --git a/CANLibrary/Test.sym b/CANLibrary/Test.sym new file mode 100644 index 0000000..a0e346d --- /dev/null +++ b/CANLibrary/Test.sym @@ -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 + diff --git a/CANLibrary/example.py b/CANLibrary/example.py index 3debfd4..91a9dfa 100644 --- a/CANLibrary/example.py +++ b/CANLibrary/example.py @@ -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' diff --git a/PCANBasic/PCANBasic.pyc b/PCANBasic/PCANBasic.pyc deleted file mode 100644 index 1057119..0000000 Binary files a/PCANBasic/PCANBasic.pyc and /dev/null differ diff --git a/pycrc/crc_algorithms.pyc b/pycrc/crc_algorithms.pyc deleted file mode 100644 index 0ef825c..0000000 Binary files a/pycrc/crc_algorithms.pyc and /dev/null differ diff --git a/pycrc/crc_lexer.pyc b/pycrc/crc_lexer.pyc deleted file mode 100644 index b8d15f8..0000000 Binary files a/pycrc/crc_lexer.pyc and /dev/null differ diff --git a/pycrc/crc_models.pyc b/pycrc/crc_models.pyc deleted file mode 100644 index f373a09..0000000 Binary files a/pycrc/crc_models.pyc and /dev/null differ diff --git a/pycrc/crc_opt.pyc b/pycrc/crc_opt.pyc deleted file mode 100644 index 20e375b..0000000 Binary files a/pycrc/crc_opt.pyc and /dev/null differ diff --git a/pycrc/crc_parser.pyc b/pycrc/crc_parser.pyc deleted file mode 100644 index fc1547b..0000000 Binary files a/pycrc/crc_parser.pyc and /dev/null differ diff --git a/pycrc/crc_symtable.pyc b/pycrc/crc_symtable.pyc deleted file mode 100644 index 8c2c13d..0000000 Binary files a/pycrc/crc_symtable.pyc and /dev/null differ diff --git a/pycrc/pycrc.pyc b/pycrc/pycrc.pyc deleted file mode 100644 index 6706699..0000000 Binary files a/pycrc/pycrc.pyc and /dev/null differ