Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Problem reading Raw CAN values

rmoudy
2017-02-15
2017-02-21
  • rmoudy - 2017-02-15

    I am brand new to codesys programming and am working on a project where I am trying to read raw CAN values off of a CAN network.

    I believe my code is correct since I used a referenced codesys program from v2.3 that reads CAN values as well. The problem is that the code I was referencing used functions from an IFM library and I am programming a DI4 Display from Bosch/Rexroth. I don't believe this is the library I want. Although I did try to import the library into my v3.5 program but I get an error.

    Which library should I use to get my program working? Or is there a way to make the IFM libraries work with my new device?

    I have a CANbus J1939 Manager configured and I'll paste the code below in my CAN_READ program if that helps.

    EDIT: I just remembered that this controller uses CAN2.0B? I am not entirely sure what that is or where I can download it. Google hasn't been very helpful so far.

    EDITT: Apparently CAN2.0B is an industry standard but I don't understand how that helps with implementation since I haven't been able to find useful literature so far.

    PROGRAM CAN_Read
    VAR
       rx_Message1: CAN_RX;
       abMessage1: ARRAY [0..7] OF BYTE;
       rx_Message2: CAN_RX;
       abMessage2: ARRAY [0..7] OF BYTE;
       nFPMNeedleAngle : INT;
       rx_Message3: CAN_RX;
       abMessage3: ARRAY [0..7] OF BYTE;
       rx_Message4: CAN_RX;
       abMessage4: ARRAY [0..7] OF BYTE;
       rx_Message5: CAN_RX;
       abMessage5: ARRAY [0..7] OF BYTE;
       rx_Message6: CAN_RX;
       abMessage6: ARRAY [0..7] OF BYTE;
       rx_Message7: CAN_RX;
       abMessage7: ARRAY [0..7] OF BYTE;
       rx_Message8: CAN_RX;
       abMessage8: ARRAY [0..7] OF BYTE;
       rx_Message9: CAN_RX;
       abMessage9: ARRAY [0..7] OF BYTE;
       rx_Message10: CAN_RX;
       abMessage10: ARRAY [0..7] OF BYTE;
       rx_Message11: CAN_RX;
       abMessage11: ARRAY [0..7] OF BYTE;
       
       //Addresses of PDO-IDs
       PDO1: INT:=16#2FA;
       PDO2: INT:=16#2FB;
       PDO3: INT:=16#2FC;
       PDO4: INT:=16#2FD;
       PDO5: INT:=16#2FE;
       PDO6: INT:=16#2FF;
       PDO7: INT:=16#3FA;
       PDO8: INT:=16#3FB;
       PDO9: INT:=16#3FC;
       PDO10: INT:=16#3FD;
       PDO11: INT:=16#3FE;
       
       //Create one instane and only have to change it once if wrong.
       Chan: INT:=1;
       
       //Variable names moved to Global Variable List
       
       Unpack1: UNPACK;
       Unpack2: UNPACK;
    END_VAR
    
    //Recieve CAN Data
    rx_Message1(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO1);
    rx_Message2(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO2);
    rx_Message3(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO3);
    rx_Message4(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO4);
    rx_Message5(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO5);
    rx_Message6(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO6);
    rx_Message7(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO7);
    rx_Message8(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO8);
    rx_Message9(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO9);
    rx_Message10(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO10);
    rx_Message11(ENABLE:= TRUE,CHANNEL:= Chan,ID:= PDO11);
       IF rx_message1.RESULT = 1 THEN
          abMessage1 := rx_Message1.DATA;
       ELSE
          abMessage1 := abMessage1;
       END_IF
       IF rx_message2.RESULT = 1 THEN
          abMessage2 := rx_Message2.DATA;
       ELSE
          abMessage2 := abMessage2;
       END_IF
       IF rx_message3.RESULT = 1 THEN
          abMessage3 := rx_Message3.DATA;
       ELSE
          abMessage3 := abMessage3;
       END_IF
       IF rx_message4.RESULT = 1 THEN
          abMessage4 := rx_Message4.DATA;
       ELSE
          abMessage4 := abMessage4;
       END_IF
       IF rx_message5.RESULT = 1 THEN
          abMessage5 := rx_Message5.DATA;
       ELSE
          abMessage5 := abMessage5;
       END_IF
       IF rx_message6.RESULT = 1 THEN
          abMessage6 := rx_Message6.DATA;
       ELSE
          abMessage6 := abMessage6;
       END_IF
       IF rx_message7.RESULT = 1 THEN
          abMessage7 := rx_Message7.DATA;
       ELSE
          abMessage7 := abMessage7;
       END_IF
       IF rx_message8.RESULT = 1 THEN
          abMessage8 := rx_Message8.DATA;
       ELSE
          abMessage8 := abMessage8;
       END_IF
       
       IF rx_message9.RESULT = 1 THEN
          abMessage9 := rx_Message9.DATA;
       ELSE
          abMessage9 := abMessage9;
       END_IF
       IF rx_message10.RESULT = 1 THEN
          abMessage10 := rx_Message10.DATA;
       ELSE
          abMessage10 := abMessage10;
       END_IF
       IF rx_message11.RESULT = 1 THEN
          abMessage11 := rx_Message11.DATA;
       ELSE
          abMessage11 := abMessage11;
       END_IF
    Engine_Speed:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage1[0], MS_BYTE:=abMessage1[1]);
    Hyd_Oil_Psi:= TWOBYTES_TO_WORD(LS_BYTE:=abMessage1[2], MS_BYTE:=abMessage1[3]);
    Fuel_Level:=BYTE_TO_INT(abMessage1[4]);
    Machine_Speed:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage1[5], MS_BYTE:=abMessage1[6]);
    Left_Gate_Pot:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage2[0], MS_BYTE:=abMessage2[1]);
    Right_Gate_Pot:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage2[2], MS_BYTE:=abMessage2[3]);
    Left_Gate_Volt:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage2[4], MS_BYTE:=abMessage2[5]);
    Right_Gate_Volt:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage2[6], MS_BYTE:=abMessage2[7]);
    Joystick_Volt:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage3[0], MS_BYTE:=abMessage3[1]);
    Motor_Freq:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage3[2], MS_BYTE:=abMessage3[3]);
    Pump_Fwd:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage3[4], MS_BYTE:=abMessage3[5]);
    Pump_Rev:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage3[6], MS_BYTE:=abMessage3[7]);
    Motor_Front:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage4[0], MS_BYTE:=abMessage4[1]);
    Motor_Rear:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage4[2], MS_BYTE:=abMessage4[3]);
    Left_Gate_Open:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage4[4], MS_BYTE:=abMessage4[5]);
    Left_Gate_Close:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage4[6], MS_BYTE:=abMessage4[7]);
    Right_Gate_Open:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage5[0], MS_BYTE:=abMessage5[1]);
    Right_Gate_Close:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage5[2], MS_BYTE:=abMessage5[3]);
    Hyd_Oil_Temp:=BYTE_TO_INT(abMessage5[4]);
    Engine_Coolant_Temp:=BYTE_TO_INT(abMessage5[5]);
    Machine_Speed2:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage5[6], MS_BYTE:=abMessage5[7]);
    Agg_Dist_Rate:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage6[0], MS_BYTE:=abMessage6[1]);
    Agg_Density_Right:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage6[2], MS_BYTE:=abMessage6[3]);
    Agg_Density_Left:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage6[4], MS_BYTE:=abMessage6[5]);
    Battery_Volt:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage6[6], MS_BYTE:=abMessage6[7]);
    Agg_Size:=BYTE_TO_INT(abMessage7[0]);
    Left_Auger_Percent:=BYTE_TO_INT(abMessage7[1]);
    Right_Auger_Percent:=BYTE_TO_INT(abMessage7[2]);
    Left_Conv_Percent:=BYTE_TO_INT(abMessage7[3]);
    Right_Conv_Percent:=BYTE_TO_INT(abMessage7[4]);
    Joystick_Percent:=BYTE_TO_INT(abMessage7[5]);
    Right_Gate_Close_Current:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage8[0], MS_BYTE:=abMessage8[1]);
    Right_Gate_Open_Current:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage8[2], MS_BYTE:=abMessage8[3]);
    Left_Gate_Close_Current:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage8[4], MS_BYTE:=abMessage8[5]);
    Left_Gate_Open_Current:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage8[6], MS_BYTE:=abMessage8[7]);
    Pump_Fwd_Min:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage9[0], MS_BYTE:=abMessage9[1]);
    Pump_Rev_Min:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage9[2], MS_BYTE:=abMessage9[3]);
    Front_Motor_Min:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage9[4], MS_BYTE:=abMessage9[5]);
    Rear_Motor_Min:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage9[6], MS_BYTE:=abMessage9[7]);
    Right_Screen_Rate:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage10[0], MS_BYTE:=abMessage10[1]);
    Left_Screen_Rate:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage10[2], MS_BYTE:=abMessage10[3]);
    Gate_Open_Hold:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage10[4], MS_BYTE:=abMessage10[5]);
    Gate_Shut_Hold:=TWOBYTES_TO_WORD(LS_BYTE:=abMessage10[6], MS_BYTE:=abMessage10[7]);
    Engine_Hours:=FOURBYTES_TO_DWORD(BYTE1:=abMessage11[0], BYTE2:=abMessage11[1], BYTE3:=abMessage11[2], BYTE4:=abMessage11[3]);
    Distance_Chipped:=FOURBYTES_TO_DWORD(BYTE1:=abMessage11[4], BYTE2:=abMessage11[5], BYTE3:=abMessage11[6], BYTE4:=abMessage11[7]);
    
     

    Related

    Talk.ru: 1
    Talk.ru: 2
    Talk.ru: 3
    Talk.ru: 5
    Talk.ru: 7

  • eschwellinger

    eschwellinger - 2017-02-17

    Hi,
    for me the questions are:
    1. which plc are you using now
    2. in which Version
    and
    3. you want to use J1939 is that right?

    BR
    Edwin

     
  • rmoudy - 2017-02-17

    Hello Edwin,

    1) We are not using a PLC per say but using a BODAS controller RC28 14-30.

    2) The version I am using is CODESYS V3.5 SP4 Patch1

    3) Yes that is correct.

    From the time I originally posted this question, I have since realized that the code I posted above is incorrect for trying to read CAN data with this DI4 Bodas Display. I have re-written it as of now using the CAN API package.

    I have another question though, what does the "red triangle" mean next to the device?

    IMG: redTriangle.JPG

     
  • eschwellinger

    eschwellinger - 2017-02-19

    Hi,
    do not use the Simulation mode with Control Win,
    Control Win is installed on the same machine where your CODESYS instance is running so why not login to the real plc.
    It does not really make sense to use the Simulation with all the restirctions it have.
    By the way if you want to use Control Win for CAN communication, please use a Peak-USB CAN Interface,
    this will work with Control Win.
    (So your pc could be the CANopen Master / CANopen Device or J1939 or even CAN raw sending/receive machine)

    Br
    Edwin

    IMG: startControlWinplc.jpg

     
  • rmoudy - 2017-02-21

    Well the controller is currently sititing in one of our products right now waiting for field testing (it's brand new software for this controller). I do have a Peak-USB CAN interface but the plug-in is only usefull for uploading software from a labtop to the controller. The adapter doesn't fit the DI4 Display and thus am waiting for one to ship here from Rexroth/Bosch.

    What I would like to do is verify that my code works before trying it on our new computer that's sitting in our product right now. What I'm getting away from this conversation right now is that I can having my computer set-up as a CANMaster to send messages to the "slave" (i.e. my codesys program) correct? How should I set-up my CAN devices then?

    My current set-up right now is shown in the attached picture. I'm confused on the structure of the parent/child devices.

    I have my CANbus device added, then I have my J1939_Manager device below that one as a child, and finally the J1939_ECU as the child to the manager. Does this device tree mean that the J1939-Manager is a 'slave' device to the CANbus and the J1939_ECU is a 'slave' to it's master the J1939-Manager? I really don't understand the heirarchy here and I can't find a good explanation on the internet. Could you explain the significance of each device or at least point me to a source that I can read?

    IMG: childDevices.JPG

     

Log in to post a comment.