ScriptName "1 Byte I/O with CO V4" ScriptAuthor "(dA) " ScriptVersion "V 1.0" // 03.03.05 V 1.0 create for UNIGATE CO V4 // 12.04.05 in house Conformance Test with SCSlaveExample.eds SetErrorHandler( :ErrorHandler ) ; // Initialize ErrorHandler SetSystemErrorHandler( :SystemErrorHandler ) ; // Initialize SystemErrorHandler // Now we create CANopen objects used by application // For example we make a easy application. Data from serial interface will send // to CANopen, and data from CANopen will be send to serial interface. // So we use 2 object: RxObjectValue and TxObjectValue. Each Object needs 1 Byte. // Rx means data from CANopen, Tx means data to CANopen // Every Script MUST have the following ObjectTable, and length MUST be: // ((number of objects) + 2) * 12 // If length is not correct, there will be big problems by running the script! var a_ObjectTable : buffer[48]; // (2 Objects + 2) * 12 = 48 // Now we will send the information about number of objects and buffer to firmware // This line MUST done befor CANopen-objects will be created InitObjectTable ( 2 , a_ObjectTable[0] ) ; // 2=number of objects // Variables used from CANopen objects var bRxObjectValue : byte; var bTxObjectValue : byte; // CreateObject(Index, SubIndex, Attribut, DataType, Length, Variable) // Attribut: 0000xx0x // || +- Mappable to PDO // |+--- Read-Only // +---- Write-Only // i.E: if object may mappable to PDO and Read/Write: => 00001101 = 13(dec) // // DataType (like DS301): // BOOLEAN_k 1 // INTEGER8 2 // INTEGER16 3 // INTEGER32 4 // UNSIGNED8 5 // UNSIGNED16 6 // UNSIGNED32 7 // FLOAT 8 // REAL32 8 // VISIBLE_STRING 9 // OCTET_STRING 10 // DOMAIN 15 // // Idx 2000H, SubIdx 0, RW-Map, Unsigned8, 1Byte-Len CreateObject (0x2000, 0, 13, 5, 1, bRxObjectValue) ; // Idx 2001H, SubIdx 0, RW-Map, Unsigned8, 1Byte-Len CreateObject (0x2001, 0, 13, 5, 1, bTxObjectValue) ; // Now we create PDO's. It's possible to create up to 16 Rx- and 16 Tx-PDO's // SetPDOCommunication(direction,PDOnumber,COBId,InhibitTime,TransmissionType); // direction: Rx = 0, Tx = 1 // PDO-number: 1 - LastPDO // COB-ID = yy000ccccccccccc // || +++++++++++- 11-Bit COB-ID // |+--------------- 0 = add Node-ID, 1 = use ID direct // +---------------- 0 = PDO Enabled, 1 = PDO Disabled // InhibitTime like DS301. On Rx-PDO use dummy 0 // Transmission Typs like DS301. Normally 255 = PDO send on event asynchron //Rx-PDO 1: COB-ID=200H + nodeID, Inhibittime=Dummy, azycl.event SetPDOCommunication(0, 1, 0x0200, 0x0000, 255); //Tx-PDO 1: COB-ID=180H + nodeID, Inhibittime=0, azycl.event //Tx-PDO 2: COB-ID=280H + nodeID, Inhibittime=0, azycl.event SetPDOCommunication(1, 1, 0x0180, 0x0000, 255); SetPDOCommunication(1, 2, 0x0280, 0x0000, 255); // Now we make PDO-Mappings // SetPDOMapping(direction,PDOnumber,obj1,...obj8) // direction: Rx = 0, Tx = 1 // PDO-number: 1 - LastPDO // obj1..8 = iiiiiiiiiiiiiiiissssssssllllllll (like DS301) // ||||||||||||||||||||||||++++++++- Lenght of bits // ||||||||||||||||++++++++--------- Sub-Index // ++++++++++++++++----------------- Index // Rx-PDO1 = Obj. 2000, SubIdx = 0, Len = 8 Bit = 1 Byte SetPDOMapping(0, 1, 0x20000008, 0, 0, 0, 0, 0, 0, 0); // Tx-PDO1 = Obj.2001, SubIdx = 0, Len = 8 Bit = 1 Byte // Tx-PDO2 = Obj.2001, SubIdx = 0, Len = 8 Bit = 1 Byte + Obj. 2001, SubIdx = 0 SetPDOMapping(1, 1, 0x20010008, 0, 0, 0, 0, 0, 0, 0); SetPDOMapping(1, 2, 0x20010008, 0x20010008, 0, 0, 0, 0, 0, 0); // The following Object-Informaiton (1000H, 1008H, 1009H, 100AH) may only be // used if necessary for application. Otherwise clear these lines. // Object 1000h: Device Type (s. DS301) // Contains information about the device type. The object at index 1000h describes the type of device // and its functionality. It is composed of a 16-bit field which describes the device profile that is used and // a second 16-bit field which gives additional information about optional functionality of the device. The // Additional Information parameter is device profile specific. Its specification does not fall within the // scope of this document, it is defined in the appropriate device profile. The value 0000h indicates a // device that does not follow a standardised device profile. // [1000] // ParameterName=Device Type // DefaultValue=0 Set ( DeviceType , 0x00000000 ) ; // [1008] // ParameterName=Manufacturer Device Name (max. 15 Character terminated by 0) // DefaultValue=UNIGATE RSCO-SC var DeviceNameBuf : buffer[19]; moveconst ( DeviceNameBuf[0], "UNIGATE CANopen SC"#0x00); SetByVar ( DeviceName , DeviceNameBuf[0] ) ; // [1009] // ParameterName=Manufacturer Hardware Version // DefaultValue=G // [100a] // ParameterName=Manufacturer Software Version // DefaultValue=V1.0 // DeviceRevision: MSB=Hard-Rev, LSB=Softrev(Hex) => 0x4710 = Hard-Rev.G, Soft-Rev. V1.0 Set ( DeviceRevision , 0x4710 ) ; // Initilize serial interface Set ( Baudrate , 9600 ) ; Set ( Databits , 8 ) ; Set ( Startbits , 1 ) ; Set ( Parity , none ) ; // Variables need for endless-loop var b_0: byte; moveConst(b_0, 0); var w_0: word; moveConst(w_0, 0); var w_1: word; moveConst(w_1, 1); var bReturnCode : byte; var wAnzInChar : word; var w_Timeout : word; moveConst (w_Timeout, 10); var b_ReceiveData : byte; var w_NumberCharToReceive : word; moveConst (w_NumberCharToReceive, 1); var b_SendObjLen : byte; moveConst ( b_SendObjLen, 1); var b_NewBusData : byte; var b_LastRxObj: byte; var w_Index: word; var b_SubIndex: byte; var w_2000H: word; moveConst (w_2000H, 0x2000); var b_NoNewData: byte; moveConst(b_NoNewData, 3); var b_E: byte; moveConst(b_E, "E"); var a_EmergencyMessage: buffer[8]; // This buffer will be used to read data from all objects. So size of this // buffer MUST as long as the biggest object data! // i.e. if you use byte and long data in objects, length of buffer must be // 4 byte. In this example we use only byte data, so length is 1 byte. var a_CANInputDataBuffer: buffer[1]; // Now we make a connection to CANopen BusStart ; Wait ( Bus_Active ) ; Set (RS_State_LED, GreenFlashing) ; :start ; //---- Get ( RSInputCharacter16 , wAnzInChar ) ; if wAnzInChar equal w_0 then :check_new_object; // No serial input ReceiveSomeCharRS( w_Timeout, b_ReceiveData, w_NumberCharToReceive);// rd 1 char if b_ReceiveData equal b_E then :SendEmergency; // simulate emergencymessage WriteObject(bTxObjectValue, b_ReceiveData, b_SendObjLen);// copy value to object Set (RS_State_LED, StaticGreen) ; :check_new_object ; //--------------- ReadNewCANObjectData(w_Index, b_SubIndex, a_CANInputDataBuffer[0]); Get ( ErrorCode , bReturnCode ) ; if bReturnCode equal b_NoNewData then :start; // No canges // The following line is here normally not necessary, because only 1 obj. used if w_index notequal w_2000H then :start; // Check if Obj. 2000H SendRS( a_CANInputDataBuffer[0], w_1 ) ; jump :start; :SendEmergency; //------------- // a_EmergencyMessage MUST be used like DS301 // Errorcode_H, Errorcode_L, ErrorRegister, Usercode[5] // Errorcode = 0x6201 (User Software Error) // ErrorRegister = 0x80 (Bit 7 = manufactor specific) // Usercode = 12345 (user specific) moveConst(a_EmergencyMessage[0], #0x62#0x01#0x80#1#2#3#4#5); CO_WriteEmergency ( a_EmergencyMessage[0] ) ; jump :start; : ErrorHandler ; //------------ Get ( ErrorCode , bReturnCode ) ; SetByVar ( Errorcode , bReturnCode ) ; // ErrorCode display on yellow LED's return ; :SystemErrorHandler; //------------------ Get ( systemError , bReturnCode ) ; // Systemerrorcode will be displayed on yellow LED's by Firmware. // Other action by user will be here possible return;