CAN bus status counter help

Hello,
I am a beginner and i am currently trying to modify a code line in an existing project for a CAN interface. In the code there is a status counter that cycles from 00 - FF

the coding appears like this:

void setShifterStatus(byte status_code){
  uint8_t buf[] = { 0x00, status_code, status_counter  };
  uint8_t crc = crc8(0, buf, 4);
  byte payload[4] = { 0x00, status_code, status_counter , crc };
  CAN.sendMsgBuf(0x418, 0, 4, payload);
  delay(55);

  status_counter++ ;
  if ((status_counter)) status_counter++;

As you can see in the can bus message payload there are 4 bytes (0123)
the status counter is in byte 2
i need to make the status counter operate only in the first nibble or first 4 bits of the byte from 0-F (eg 0x00 0x10 0x20 0x30 0x40 and so on) leaving the second nibble (4bits) able to be modifided by a input.

how can i re-write the status counter for this function?

Welcome

I don't really understand your question

byte = left_nibble << 4 | right_nibble;

Where left_nibble is your status_counter, and right_nibble is the modified input

sorry , yes if i was to look at the byte i need the left nibble to operate as the status counter and the right to operate as a modifiable input.

please refer table for desired message structure

A Column 1 C D E F G H I
BYTE #, NIBBLE# ==============> BYTE 0, NIBBLE 0 BYTE 0, NIBBLE 1 BYTE 1, NIBBLE 0 BYTE 1, NIBBLE 1 BYTE 2, NIBBLE 0 BYTE 2, NIBBLE 1 BYTE 3, NIBBLE 0 BYTE 3, NIBBLE 1
FUNCTION =============> MODIFIED OUTPUT MODIFIED OUTPUT MODIFIED OUTPUT MODIFIED OUTPUT STATUS COUNTER (0 TO F) MODIFIED OUTPUT CRC CRC

Yes, but here we prefer to read hex and binary numbers from right to left, so it's not bytes 0123, but 3210, same with nibbles, 0 is on the right, 1 on the left

Anyway, I think what I proposed is what you are looking for, or I still don't understand :slight_smile:

Here is an example : plgSLW - Online C++ Compiler & Debugging Tool - Ideone.com

Left-shift by 4 (moving the nibble to the left side of the byte) is the same as multiplying by 16, and (in this case) the bitwise OR is like an addition, so if you prefer you can write

left_nibble * 16 + right_nibble;
1 Like

Now im not quite understanding :rofl:

Is there any chance you could show me how i would implement this in my current code?

A bit of background probably helps,
Basically im trying to create a Bench testing module so i can plug in a electronic gear selector module from a car so I can function test them on the bench. Push the park button and it comes out of park into N, push stick forward one click it goes into R, pull it back one click it goes into N, pull it back another click it goes into D etc etc

The original coding came from someone who connected up a BMW gear shifter to a racing sim. I thought it would be a base to start.

but im new to this so i could be very wrong :upside_down_face:


#include <SPI.h>


const uint8_t crc8_lut[] = {
  0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf,
  0x9c, 0x81, 0xa6, 0xbb, 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e,
  0x25, 0x38, 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, 0x87, 0x9a, 0xbd, 0xa0,
  0xf3, 0xee, 0xc9, 0xd4, 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, 0x21, 0x3c,
  0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, 0xa2, 0xbf, 0x98, 0x85,
  0xd6, 0xcb, 0xec, 0xf1, 0x13, 0x0e, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40,
  0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, 0xde, 0xc3, 0xe4, 0xf9,
  0xaa, 0xb7, 0x90, 0x8d, 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65,
  0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, 0x7c, 0x61, 0x46, 0x5b,
  0x08, 0x15, 0x32, 0x2f, 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0x0a,
  0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, 0x26, 0x3b, 0x1c, 0x01,
  0x52, 0x4f, 0x68, 0x75, 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d,
  0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, 0x03, 0x1e, 0x39, 0x24,
  0x77, 0x6a, 0x4d, 0x50, 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2,
  0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, 0x6c, 0x71, 0x56, 0x4b,
  0x18, 0x05, 0x22, 0x3f, 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7,
  0x35, 0x28, 0x0f, 0x12, 0x41, 0x5c, 0x7b, 0x66, 0xdd, 0xc0, 0xe7, 0xfa,
  0xa9, 0xb4, 0x93, 0x8e, 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab,
  0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, 0xb2, 0xaf, 0x88, 0x95,
  0xc6, 0xdb, 0xfc, 0xe1, 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x09,
  0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, 0x31, 0x2c, 0x97, 0x8a, 0xad, 0xb0,
  0xe3, 0xfe, 0xd9, 0xc4
};


#define CAN_2515
// #define CAN_2518FD

// Set SPI CS Pin according to your hardware

#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat:
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else

// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif


#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN);  // Set CS pin
#endif

#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN);  // Set CS pin
#endif

#define CAN_ID_PID 0x401

bool shifter_init_test_done = false;

bool shifter_released = true;
bool parking_button_released = true;

char msgString[128];
char lever_position_code[128];
char parking_position_code[128];
uint8_t status_counter = 0;

// CAN message
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];

// Shifter status codes for GWS
byte shifter_status_park     = 0x00; 
byte shifter_status_reverse  = 0x00;
byte shifter_status_neutral  = 0x00; 
byte shifter_status_drive    = 0x00;
byte shifter_status_manual   = 0x00;

// Lever position/movement codes
String shifter_centred           = "0x00";
String shifter_middle_move_down1 = "0x00";
String shifter_middle_move_down2 = "0x00";
String shifter_middle_move_up1   = "0x00";
String shifter_middle_move_up2   = "0x00";
String shifter_park_select       = "0x00";
String shifter_manual_select     = "0x00";

// Shifter pattern and entry shifter position/gear
const byte shifter_schema[5] = { shifter_status_park, shifter_status_reverse, shifter_status_neutral, 
shifter_status_drive, shifter_status_manual,};
uint8_t shifter_schema_position = 1;

bool shifter_mode_auto = true;

byte shifter_status_initial = shifter_status_park;
byte shifter_status_current = shifter_status_initial;

uint8_t crc8(uint8_t crc, uint8_t const *buf, uint32_t len) {
  for (uint32_t i = 0; i < len; i++) {
    uint8_t data = buf[i] ^ crc;
    crc = crc8_lut[data] ^ (crc << 8);
  }
  return crc ^ 0x00;
}

//void turnBacklight() {
  // 0x202 code is backlight turning code
  //byte payload[5] = { 0xFF, 0xFF, 0x00 };
  //CAN.sendMsgBuf(0x000, 0, 4, payload);
//}

void setShifterStatus(byte status_code){
  uint8_t buf[] = { 0x00, 0x00, status_counter, 0x00 };
  uint8_t crc = crc8(0, buf, 4);
  byte payload[5] = { 0x00, 0x00, status_counter, crc };

  CAN.sendMsgBuf(0x401, 0, 4, payload);
  delay(9);

  status_counter++;
  if ((status_counter)) status_counter++;
}



//---------------------------------------------------------------------------------------------------------------------------------//
void setup() {
  SERIAL_PORT_MONITOR.begin(115200);
  while (!Serial) {};

  while (CAN_OK != CAN.begin(CAN_500KBPS)) {  // init can bus : baudrate = 500k
    SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
    delay(100);
  }
  SERIAL_PORT_MONITOR.println("CAN init ok!");
  //turnBacklight();
}


void loop() {
// put your main code here, to run repeatedly:

  // delay(100);
  unsigned char len = 0;
  unsigned char buf[8];
  if (CAN_MSGAVAIL == CAN.checkReceive()) {  // check if data coming
    {
      // Read CAN message
      if (CAN_MSGAVAIL == CAN.checkReceive()) {  // check if data coming
        CAN.readMsgBuf(&len, buf);               // read data,  len: data length, buf: data buf
       sprintf(lever_position_code, "0x%.2X", rxBuf[2]);
       sprintf(parking_position_code, "0x%.2X", rxBuf[3]);


        unsigned long canId = CAN.getCanId();

        SERIAL_PORT_MONITOR.println("-----------------------------");
        SERIAL_PORT_MONITOR.print("Get data from ID: 0x");
        SERIAL_PORT_MONITOR.println(canId, HEX);

        for (int i = 0; i < len; i++) {  // print the data
          SERIAL_PORT_MONITOR.print(buf[i], HEX);
          SERIAL_PORT_MONITOR.print("\t");
        }
        SERIAL_PORT_MONITOR.println();
        
       }
       // Set and update Shifter status continously
       setShifterStatus(shifter_status_current);
       
       //}
       // REPEATING 0X202 FOR DIAGNOSTICS
       //byte payload[5] = { 0xFF, 0xFF, 0x00 };
       //CAN.sendMsgBuf(0x000, 0, 4, payload);
       //delay(30);
      //}


    }
  }

}   




// END FILE

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.