CAN bus - seed can shield V2 .0

I using arduino uno - seed can shield to send data to my CAN.

{

unsigned char stmp0[14] = {current_I1, Temp1, Temp2, Voltage_U1, Voltage_U2, Current_I1_red, OCP_flag, OVP_flag, UVP_flag}; 

  byte sndStat0 = CAN0.sendMsgBuf(txID0, 0, lenTx0, stmp0);
  if(sndStat0 == CAN_OK){
    Serial.println("Message Sent Successfully!");
  } else {
    Serial.println("Error Sending Message...");
  }

using this example from the can library. My question is, I want to use my 64bit length of the CAN message to the fullest as i want to send 14 data items .Since only for some of it i need 8 bits and for the rest it just need to be high or low (i.e 1 or 0 ) is there a way that i can send all of this in one message?
Since my message is a unsigned char array will it allow for some of my elements to be of a different data type

i have attached my full code too

Thanks in advance for your help :slight_smile:

test_run.ino (4.34 KB)

Had a look at your code and to able to package all the data you want to transmit into 8 data bytes of ONE CAN messages I would do the following:

  1. use 'uint16_t' instead of 'float' for your analog reads.
  2. use 'uint8_t' intead of 'bool' for your flags.

on arduino, the analogRead typically is 10 bit resolution.

considering all the data you have, this is how I would package it:
Capture_1.PNG

if code is would something like this:

uint8_t data_bytes[8];
uint16_t temp;

data_bytes[0] = (uint8_t)current_I1;

temp = (Current_I1_red<<2)|(current_I1>>8);

data_bytes[1] =  (uint8_t) temp;

temp =(Temp1<<4) | (Current_I1_red>>6);

data_bytes[2] = (uint8_t) temp;

temp = (Temp2<<6)|(Temp1>>4);

data_bytes[3] = (uint8_t) temp;

temp = (Temp2>>2);

data_bytes[4] = (uint8_t) temp;

data_bytes[5] = (uint8_t) Voltage_U1;

temp = (Voltage_U2<<2) | (Voltage_U1>>8);

data_bytes[6] = (uint8_t) temp;

temp = (OCP_flag<<7)|(OVP_flag<<6)|(UVP_flag<<5)|(Voltage_U2>>6);

data_bytes[7] = (uint8_t) temp;

I let you figure out the decoding! :slight_smile:

Good Luck

Capture_1.PNG

There is another (my be simpler) way to pack your 6 analog values and 3 boolean values into the 8-byte CAN message: use a bitfield on both sides of the CAN (sender and receiver):

  • As shown by sherzaad, each analog value needs 10 bit and each boolean needs 1 bit
  • The sum is 63 bit - one in reserve

The bitfield declaration looks like:

struct CANmessage
{
  unsigned int Temp1:10;
  unsigned int Temp2:10;
  unsigned int Volt1:10;
  unsigned int Volt2:10;
  unsigned int Curr1:10;
  unsigned int Curr2:10;
  bool OCP_flag:1;
  bool OVP_flag:1;
  bool UVP_flag:1;
  bool fillup:1;
};

struct CANmessage stmp; // This is the real bitfield to send

stmp.Temp1 = analogRead(A1); // So you must fill the bitfield-elements

Another question: why did you use 4 arrays with the same elements inside? And your sktch do'nt fill the araay it only fills the variables!

Thank you so much for the help. It works the way i wanted now :slight_smile: .

sherzaad:
Had a look at your code and to able to package all the data you want to transmit into 8 data bytes of ONE CAN messages I would do the following:

  1. use 'uint16_t' instead of 'float' for your analog reads.
  2. use 'uint8_t' intead of 'bool' for your flags.

on arduino, the analogRead typically is 10 bit resolution.

considering all the data you have, this is how I would package it:
Capture_1.PNG

if code is would something like this:

uint8_t data_bytes[8];

uint16_t temp;

data_bytes[0] = (uint8_t)current_I1;

temp = (Current_I1_red<<2)|(current_I1>>8);

data_bytes[1] =  (uint8_t) temp;

temp =(Temp1<<4) | (Current_I1_red>>6);

data_bytes[2] = (uint8_t) temp;

temp = (Temp2<<6)|(Temp1>>4);

data_bytes[3] = (uint8_t) temp;

temp = (Temp2>>2);

data_bytes[4] = (uint8_t) temp;

data_bytes[5] = (uint8_t) Voltage_U1;

temp = (Voltage_U2<<2) | (Voltage_U1>>8);

data_bytes[6] = (uint8_t) temp;

temp = (OCP_flag<<7)|(OVP_flag<<6)|(UVP_flag<<5)|(Voltage_U2>>6);

data_bytes[7] = (uint8_t) temp;





I let you figure out the decoding! :)

Good Luck

I just filled them for a reference, so that i could check their functionality. I intended to change it later :slight_smile: . Thanks for your help

RudolfAtRTC:
There is another (my be simpler) way to pack your 6 analog values and 3 boolean values into the 8-byte CAN message: use a bitfield on both sides of the CAN (sender and receiver):

  • As shown by sherzaad, each analog value needs 10 bit and each boolean needs 1 bit
  • The sum is 63 bit - one in reserve

The bitfield declaration looks like:

struct CANmessage

{
  unsigned int Temp1:10;
  unsigned int Temp2:10;
  unsigned int Volt1:10;
  unsigned int Volt2:10;
  unsigned int Curr1:10;
  unsigned int Curr2:10;
  bool OCP_flag:1;
  bool OVP_flag:1;
  bool UVP_flag:1;
  bool fillup:1;
};

struct CANmessage stmp; // This is the real bitfield to send

stmp.Temp1 = analogRead(A1); // So you must fill the bitfield-elements




Another question: why did you use 4 arrays with the same elements inside? And your sktch do'nt fill the araay ~~it only fills the variables!~~
~~[/quote]~~