CAN Bus

11 Feb 2011

Hey, another question: I've adjusted the void send to send multiple messages after eachother using a counter. I can enter the specific data pretty easily.

void send() {
    if(counter==0) {
        //--------Global Start nodes
        data[0] = (char)(0x01); // NMT Start RemoteNode
        data[1] = (char)(0x00); // Global
        data[2] = (char)(0x00);
        data[3] = (char)(0x00);
        data[4] = (char)(0x00);
        data[5] = (char)(0x00);
        data[6] = (char)(0x00);
        data[7] = (char)(0x00);
        if(can1.write(CANMessage(0000,data,2))) {
            printf("Startup sent \n");
        }
        led1 = !led1;
        counter ++;
    }
......

Now, when I first send a message with data[0] to data[7] all 0xFF and a datalength of 8, and then after that a message with data[0] 0x01 and the rest 0x00 with a datalength of 1, the following happens. The 0x01 overwrites, but the 0xFF's in the other data stays the same, even tho I specificly put them to 0x00 before putting the data in the CANmessage... (see full code and try entering the example I gave above)

Import programCANtest

With this program you can configure and run a CAN compatible (also LSS protocol compatible) motor through the mbed\'s CANbus. Further more it gives a basic template that lets you create your own CAN messages. I\'ve implemented a configuration and a running example that the program runs through. Also there\'s 2 kinds of loops it can go into after it\'s ran through it\'s configuration and/or speed setting. It can continuously ask for the motor\'s status (node guarding kind of thing) OR it can continuously ask for the motor\'s position. Make sure you have a if, (elsif), else structure so the counter doesn\'t run out of control. I\'ve tried to put as many comments in as I could. I hope it helps you in understanding the basics of CAN and running devices. I\'m new to it myself, so any critisism is welcome. Enjoy.

So this means atleast 2 things: 1). The limited length of the second message doesn't seem to cancel out any data in the bytes that aren't used. 2). Somehow the data 0xFF is stored? Perhaps because the new data IS cancelled out after all?

Anything I did wrong in my code? Am I beeing to specific for these forums? :p

Thanks,

Melchior

11 Feb 2011

Melchior Pau wrote:

Hey,

Does anyone have an idea how to inquire the node_ID of a servomotor I have connected? http://www.faulhaber-group.com/uploadpk/EN_CANopen_FAULHABER_CAN_im_DFF.pdf I've been reading through that, I don't have the software they use.

On every manual I find they get started on how to start up nodes and put them in opperational mode. And then all of a sudden they start sending messages with Function + node_ID... and I'm like, where on earth did we somehow know what the node_ID is??

I've been trying for a while now :p need a hint in the right direction!

Thanks,

Melchior

CANOpen doesn't have a node id's as such.

Each device is assigned a series of PDO's or Process Data Objects, the CANOpen specification is available on the CAN in Automation website http://www.can-cia.org/

You will need the EDS for the device to determine the available PDO's and their default settings.

If the device is fully CANOpen certified you should be able to change these values to suit your network.

11 Feb 2011

Melchior Pau wrote:

Hey, another question: I've adjusted the void send to send multiple messages after eachother using a counter. I can enter the specific data pretty easily.

void send() {
    if(counter==0) {
        //--------Global Start nodes
        data[0] = (char)(0x01); // NMT Start RemoteNode
        data[1] = (char)(0x00); // Global
        data[2] = (char)(0x00);
        data[3] = (char)(0x00);
        data[4] = (char)(0x00);
        data[5] = (char)(0x00);
        data[6] = (char)(0x00);
        data[7] = (char)(0x00);
        if(can1.write(CANMessage(0000,data,2))) {
            printf("Startup sent \n");
        }
        led1 = !led1;
        counter ++;
    }
......

Now, when I first send a message with data[0] to data[7] all 0xFF and a datalength of 8, and then after that a message with data[0] 0x01 and the rest 0x00 with a datalength of 1, the following happens. The 0x01 overwrites, but the 0xFF's in the other data stays the same, even tho I specificly put them to 0x00 before putting the data in the CANmessage... (see full code and try entering the example I gave above)

Import programCANtest

With this program you can configure and run a CAN compatible (also LSS protocol compatible) motor through the mbed\'s CANbus. Further more it gives a basic template that lets you create your own CAN messages. I\'ve implemented a configuration and a running example that the program runs through. Also there\'s 2 kinds of loops it can go into after it\'s ran through it\'s configuration and/or speed setting. It can continuously ask for the motor\'s status (node guarding kind of thing) OR it can continuously ask for the motor\'s position. Make sure you have a if, (elsif), else structure so the counter doesn\'t run out of control. I\'ve tried to put as many comments in as I could. I hope it helps you in understanding the basics of CAN and running devices. I\'m new to it myself, so any critisism is welcome. Enjoy.

So this means atleast 2 things: 1). The limited length of the second message doesn't seem to cancel out any data in the bytes that aren't used. 2). Somehow the data 0xFF is stored? Perhaps because the new data IS cancelled out after all?

Anything I did wrong in my code? Am I beeing to specific for these forums? :p

Thanks,

Melchior

How are you monitoring it?

14 Feb 2011

I'm using moserial, a terminal program on Ubuntu.

In the send void I've placed:

if(counter==0) {
        //--------8 bytes of data
        data[0] = (char)(0xFF);
        data[1] = (char)(0xFF);
        data[2] = (char)(0xFF);
        data[3] = (char)(0xFF);
        data[4] = (char)(0xFF);
        data[5] = (char)(0x00);
        data[6] = (char)(0x00);
        data[7] = (char)(0x00);
        if(can1.write(CANMessage(2021,data,8))) {
            printf("8bytes test sent \n");
        }
        led1 = !led1;
        counter ++;
    }
    else {
        //--------2 bytes of data
        data[0] = (char)(0x00);
        data[1] = (char)(0xAA);
        data[2] = (char)(0x00);
        data[3] = (char)(0x00);
        data[4] = (char)(0x00);
        data[5] = (char)(0x00);
        data[6] = (char)(0x00);
        data[7] = (char)(0x00);
        if(can1.write(CANMessage(2021,data,2))) {
            printf("2bytes test sent \n");
        }
        led1 = !led1;
        counter = 10;
    }

Which gives the output:

  • 8bytes test sent
  • Message read with ID: 2021
  • Data: ff ff ff ff ff 0 0 0
  • Length: 8, Type: 0, Format: 0
  • 2bytes test sent
  • Message read with ID: 2021
  • Data: 0 aa ff ff ff 0 0 0
  • Length: 2, Type: 0, Format: 0

So, the data isn't overwritten, even tho I changed it?

Cheers,

Melchior

14 Feb 2011

I got the principle to work now btw. Make sure to check the latest version :p perhaps it helps other people to get started with CANbus. The output still doesn't overwrite unused databytes somehow, but... care.

Import programCANtest

With this program you can configure and run a CAN compatible (also LSS protocol compatible) motor through the mbed\'s CANbus. Further more it gives a basic template that lets you create your own CAN messages. I\'ve implemented a configuration and a running example that the program runs through. Also there\'s 2 kinds of loops it can go into after it\'s ran through it\'s configuration and/or speed setting. It can continuously ask for the motor\'s status (node guarding kind of thing) OR it can continuously ask for the motor\'s position. Make sure you have a if, (elsif), else structure so the counter doesn\'t run out of control. I\'ve tried to put as many comments in as I could. I hope it helps you in understanding the basics of CAN and running devices. I\'m new to it myself, so any critisism is welcome. Enjoy.

18 Feb 2011

I want to make a procedure like:

char data[8]
int d0,d1,d2,d3,d4,d5,d6,d7;

void setdata (d0,d1,d2,d3,d4,d5,d6,d7) {
    data[0] = (char) (d0);
    data[1] = (char) (d1);
    data[2] = (char) (d2);
    data[3] = (char) (d3);
    data[4] = (char) (d4);
    data[5] = (char) (d5);
    data[6] = (char) (d6);
    data[7] = (char) (d7);
}

So I can just write

setdata(0xB6,0x00,0xF0,0xFF,0xFF,0x00,0x00,0x00); and my array of data is filled.

But it just says "imcomplete type is not allowed". Where do I fail?

void setdata(int d0, int d1, int d2, int d3, int d4, int d5, int d6, int d7) {
    data[0] = (char) (d0);
    data[1] = (char) (d1);
    data[2] = (char) (d2);
    data[3] = (char) (d3);
    data[4] = (char) (d4);
    data[5] = (char) (d5);
    data[6] = (char) (d6);
    data[7] = (char) (d7);
}

works... nvm.

28 Mar 2017

I know this is rather old topic, but I am facing problems while filtering IDs.

The way I am currently doing is using a switch case structure to select the messages I want to read and to save the data in the appropriate variables, however whenever I try filtering a big number of IDs I start noticing a loss of data.

I am using an ST board to communicate with a motor controller which is programmed to send certain data, such as speed, torque and temperatures, but I noticed the variables where the parameters are stored are updating very slowly. I imagined it has something to do with buffers not being cleared in time.

Can anyone explain this? Whats the proper way to filter multiple IDs without losing data?

29 Mar 2017

Rather then doing it by software you should let the built-in CAN controller perform the filtering without disturbing the MCU. Use the filter(...) member function of CAN class to set up filters.