I am using MLX90366 magneto-resistive sensor to measure the rotation angle of a motor. The sensor uses SENT(SAE J2716 Protocol) signal for communication. I have no idea how to decode this signal nor can I find any libraries for it.
I will attach the frame format it uses provided in its documentation. Is there any way to decode this using any available libraries? I can integrate it with Matlab/simulink , but I cannot find any suitable libraries for decoding SENT data.
if you intend to process the data using matlab/simulink what is the UNO for?
connect the device directly to your PC?
ask for assistance on the Matlab forum
It's not because I want to process it in MATLAB, I just need a solution on how to process it so that I can get the angle value i need from the sensor. I need to process it in UNO, it is not clear to me how exactly I can do that.
looking at the timing of the SENT protocol I doubt if a UNO is fast enough - possibly a Arduino Due or a ESP32 may be
a web search for Head Automotive Interface4 Sent SAE J2716-CAN gives plenty of links, e.g. 48-automotive-interface-4
Edit: thinking again - I would probably use an FPGA to interface to this protocol
I used this code to decode the SENT signal for my mlx sensor, thanks to @Rintin . You can refer to this thread and also this thread .
// Connect data pin of sensor to D8 of the Arduino Uno/Nano/Mini
// Change based on the tick time for your component
// Time for one tick (in µs)
constexpr uint8_t tick_time = 3;
constexpr auto serial_baud = 115200;
/************************************************************/
constexpr uint8_t tick_syn = 56;
constexpr uint8_t tick_offest = 12;
constexpr uint16_t cycl_tick = F_CPU / 1000000 * tick_time; // CPU cycles per tick
// Allow +/- 20% difference
constexpr uint16_t cycl_syn_min = cycl_tick * tick_syn * 4 / 5;
constexpr uint16_t cycl_syn_max = cycl_tick * tick_syn * 6 / 5;
constexpr auto LOOKUP_SIZE = 256;
constexpr auto LOOKUP_DIV = 4;
uint16_t cycl_syn;
uint16_t cycl_offset;
int8_t cycl_lookup[LOOKUP_SIZE];
constexpr uint8_t BUFFER_SIZE = 32;
volatile uint16_t buffer[BUFFER_SIZE];
volatile uint8_t buffer_write_pointer;
volatile uint8_t buffer_read_pointer;
uint16_t last_icr = 0;
volatile bool error = false;
ISR(TIMER1_CAPT_vect) {
uint16_t value = ICR1;
buffer[buffer_write_pointer] = value - last_icr;
last_icr = value;
buffer_write_pointer++;
if (buffer_write_pointer >= BUFFER_SIZE) {
buffer_write_pointer = 0;
}
if (buffer_write_pointer == buffer_read_pointer) {
error = true;
}
}
bool buffer_available() {
return buffer_write_pointer != buffer_read_pointer;
}
uint16_t buffer_read() {
while (!buffer_available()) {
// wait for data
}
uint16_t ret = buffer[buffer_read_pointer];
auto new_p = buffer_read_pointer + 1;
if (new_p >= BUFFER_SIZE) {
new_p = 0;
}
uint8_t oldSREG = SREG;
cli();
buffer_read_pointer = new_p;
SREG = oldSREG;
return ret;
}
uint16_t get_syn_cycl() {
while (true) {
uint16_t dx = buffer_read();
if (dx >= cycl_syn_min && dx <= cycl_syn_max) {
return dx;
}
}
}
void wait_for_syn() {
while (true) {
uint16_t dx = buffer_read();
auto t = dx > cycl_syn ? dx - cycl_syn : cycl_syn - dx;
if ( t < 10) {
return;
}
}
}
void setup() {
Serial.begin(serial_baud);
Serial.print("cycl_tick = ");
Serial.println(cycl_tick);
TCCR1A = 0;
TCCR1B = 1;
TCCR1C = 0;
TIMSK1 = (1 << ICIE1);
cycl_syn = get_syn_cycl();
cycl_offset = cycl_syn * (tick_offest * 2 - 1) / tick_syn / 2; // cycl_tick * 11.5
for (uint16_t c = 0; c < LOOKUP_SIZE; c++) {
int8_t value = c * tick_syn * LOOKUP_DIV / cycl_syn;
if ( value >= 16) {
value = -1;
}
cycl_lookup[c] = value;
}
auto cycl_syn1 = get_syn_cycl();
auto dx = cycl_syn > cycl_syn1 ? cycl_syn - cycl_syn1 : cycl_syn1 - cycl_syn;
Serial.print("cycl_syn = ");
Serial.println(cycl_syn);
Serial.print("cycl_syn ok? ");
Serial.println(dx < 10 ? "yes" : "no");
Serial.print("cycl_offset = ");
Serial.println(cycl_offset);
if (LOOKUP_SIZE < (cycl_syn * 17 / tick_syn / LOOKUP_DIV)) {
Serial.println("Lookup table would exceed expected size!");
while (true) {
;
}
}
Serial.println("Lookup table:");
for (int x = 0; x < 16; x++) {
Serial.print(x * 16, HEX);
Serial.print(": ");
for (int y = 0; y < 16; y++) {
Serial.print(cycl_lookup[x * 16 + y], HEX);
Serial.print(" ");
}
Serial.println("");
}
Serial.println("************************");
Serial.flush();
error = false;
}
constexpr char toHex[] = "0123456789ABCDEF";
void loop() {
constexpr auto FRAME_SIZE = 8;
char frame[FRAME_SIZE + 1];
wait_for_syn();
for (int c = 0; c < FRAME_SIZE; c++) {
auto dx = buffer_read();
dx = (dx - cycl_offset) / LOOKUP_DIV;
if (dx > LOOKUP_SIZE || cycl_lookup[dx] < 0) {
frame[c] = '!';
} else {
frame[c] = cycl_lookup[dx];
}
}
Serial.write(frame, FRAME_SIZE);
Serial.println("");
// decimalValue is the angle, wrt the frame format for mlx90366 sensor
//int decimalValue = (frame[1] << 8) | (frame[2] << 4) | frame[3];
//Serial.println(decimalValue); // Comment the rest of serial prints to directly print the angle
if (error) {
// I commented this if condition, since it was operating properly without this.
Serial.println("Buffer overflow");
while (true) {
;
}
}
}
The output should look similar to this:
cycl_tick = 48
cycl_syn = 2699
cycl_syn ok? yes
cycl_offset = 554
Lookup table:
0: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
10: 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
20: 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3
30: 3 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5
40: 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6
50: 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 7
60: 7 8 8 8 8 8 8 8 8 8 8 8 8 9 9 9
70: 9 9 9 9 9 9 9 9 9 A A A A A A A
80: A A A A A B B B B B B B B B B B
90: B C C C C C C C C C C C C D D D
A0: D D D D D D D D D E E E E E E E
B0: E E E E E F F F F F F F F F F F
C0: F FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF