I am trying to send 29-bit EFF (Extended Frame Format) CAN messages over SocketCAN, but for some reason, it sends them with the 11-bit identifier, cutting off five bytes from the ID. Using loopback mode, through candump, I can see that messages are received as 11 bit.
I don't get any errors, nothing. That’s why I am confused.
I am using Raspberry Pi 3B+ if that makes any difference. And the Can-utils library.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include </home/pi/can-utils/lib.h>
int main(int argc, char **argv)
{
int s, loop = 1;
int nbytes;
struct sockaddr_can addr;
struct can_frame frame;
struct ifreq ifr;
// CAN interface
if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1;
}
strcpy(ifr.ifr_name, "can0");
if(ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
// Data send loop
while(loop) {
int g;
for (int e = 0; e < 1020; e++) {
if(e < 10) {
g = 0;
}
else if (e%100 == 0) {
g = 1;
}
else if (e%50 == 0) {
g = 2;
}
else if (e%20 == 0) {
g = 3;
}
if (g == 0) {
switch(e) {
case 1: // Total fuel used 5-8
frame.can_id = 0x0000FEE9;
printf("value %X", frame.can_id);
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x00;
frame.data[2] = 0x00;
frame.data[3] = 0x00;
frame.data[4] = 0xF5; // 0.5 l/bit
frame.data[5] = 0x06; // 0.5 l/bit
frame.data[6] = 0x07; // 0.5 l/bit
frame.data[7] = 0x08; // 0.5 l/bit
break;
case 2: // Fuel level 2
frame.can_id = 0x0000FEFC;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x88; // 0.4%/bit
frame.data[2] = 0x00;
frame.data[3] = 0x00;
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 3: // Total engine hours 1-4
frame.can_id = 0x0000FEE5;
frame.can_dlc = 8;
frame.data[0] = 0x11; // 0.05 h/bit
frame.data[1] = 0x22; // 0.05 h/bit
frame.data[2] = 0x33; // 0.05 h/bit
frame.data[3] = 0x44; // 0.05 h/bit
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 4: // Milleage 1-4
frame.can_id = 0x0000FEC1;
frame.can_dlc = 8;
frame.data[0] = 0x44; // 5 miles/bit
frame.data[1] = 0x33; // 5 miles/bit
frame.data[2] = 0x22; // 5 miles/bit
frame.data[3] = 0x11; // 5 miles/bit
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 5:
frame.can_id = 0x0000FEEE; // Engine temperature 1
frame.can_dlc = 8;
frame.data[0] = 0xCC; // 1 C/bit -40 C offset
frame.data[1] = 0x00;
frame.data[2] = 0x00;
frame.data[3] = 0x00;
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 6: // Ambient temperature 4-5
frame.can_id = 0x0000FEF5;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x00;
frame.data[2] = 0x00;
frame.data[3] = 0xE4; // 0.03125 C/bit -273 C offset
frame.data[4] = 0xF2; // 0.03125 C/bit -273 C offset
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 7: // High res fuel 5-8
frame.can_id = 0x0000FD09;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x00;
frame.data[2] = 0x00;
frame.data[3] = 0x00;
frame.data[4] = 0x01; // 0.001 l/bit
frame.data[5] = 0x02; // 0.001 l/bit
frame.data[6] = 0x03; // 0.001 l/bit
frame.data[7] = 0x04; // 0.001 l/bit
break;
case 8: // Vehicle weight 2-3
frame.can_id = 0x0000FEEA;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x05; // 0.5 kg/bit
frame.data[2] = 0xFF; // 0.5 kg/bit
frame.data[3] = 0x00;
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 9: // Distance before service 2-3
frame.can_id = 0x0000FEC0;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0xEF; // 5 km/bit -160 635 km offset
frame.data[2] = 0xCD; // 5 km/bit -160 635 km offset
frame.data[3] = 0x00;
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
default:
break;
}
for(int i = 0; i <1; i++) {
if ((nbytes = write(s, &frame, sizeof(struct can_frame))) != sizeof(frame)) {
}
}
}
if (g == 1) {
for(int l = 1; l < 5; l++) {
switch(l) {
case 1: // EEC 3-5
frame.can_id = 0x000CF004;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x00;
frame.data[2] = 0xEE; // Torque 1%/bit -125% offset
frame.data[3] = 0xEF; // RPM 0.125/bit
frame.data[4] = 0x12; // RPM 0.125/bit
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 2: // Fuel economy 1-4
frame.can_id = 0x0000FEF2;
frame.can_dlc = 8;
frame.data[0] = 0xEC; // Fuel rate (0.05l/h)/bit
frame.data[1] = 0xFF; // Fuel rate (0.05l/h)/bit
frame.data[2] = 0x15; // Current fuel (1/512km/l)/bit
frame.data[3] = 0xE5; // Current fuel (1/512km/l)/bit
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 3: // Wheel speed 2-3
frame.can_id = 0x0000FEF1;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x01; // (1/256 km/h)/bit
frame.data[2] = 0x99; // (1/256 km/h)/bit
frame.data[3] = 0x00;
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
case 4: // EEC2 2-3
frame.can_id = 0x0000F003;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x03; // 0.4%/bit accelerator position
frame.data[2] = 0x55; // 1%/bit engine load
frame.data[3] = 0x00;
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
break;
}
for(int i = 0; i <1; i++) {
if ((nbytes = write(s, &frame, sizeof(struct can_frame))) != sizeof(frame)) {
}
}
if(l < 5)
usleep(1000);
}
}
else if (g == 2) {
frame.can_id = 0x0000F003;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x03; // 0.4%/bit accelerator position
frame.data[2] = 0x55; // 1%/bit engine load
frame.data[3] = 0x00;
frame.data[4] = 0x00;
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
for(int i = 0; i <1; i++) {
if ((nbytes = write(s, &frame, sizeof(struct can_frame))) != sizeof(frame)) {
}
}
}
else if (g == 3) {
frame.can_id = 0x0000F004;
frame.can_dlc = 8;
frame.data[0] = 0x00;
frame.data[1] = 0x00;
frame.data[2] = 0xEE; // Torque 1%/bit -125% offset
frame.data[3] = 0xEF; // RPM 0.125/bit
frame.data[4] = 0x12; // RPM 0.125/bit
frame.data[5] = 0x00;
frame.data[6] = 0x00;
frame.data[7] = 0x00;
for(int i = 0; i <1; i++) {
if ((nbytes = write(s, &frame, sizeof(struct can_frame))) != sizeof(frame)) {
}
}
}
usleep(10000);
g = 5;
if(e == 900)
e = 0;
}
}
close(s);
return 0;
}
You need to add the correct flag after setting can_id:
frame.can_id |= CAN_EFF_FLAG;
Or for example: Instead of
frame.can_id = 0x0000FEE9
use
frame.can_id = 0x0000FEE9U | CAN_EFF_FLAG;
Here U signifies that your integer literal is unsigned. Also see can.h.