Skip to main content

Overview

This product provides sample programs that let you verify features available in the MicroPeckerX CAN FD application development library, such as transmit, receive, and slot transmission.

Sample Program Environment Setup

Copy the static library for your CPU/OS into the 02_sample directory and run make.
Alternatively, copy the dynamic library to a path where your OS can load libraries and run the program.

Communication Settings

The communication settings (baud rate and sample point) for the sample programs are as follows.

CategoryItemSetting Value
Arbitration SectionBaud Rate500kbps
Sample Point80%
Payload SectionBaud Rate2Mbps
Sample Point80%

Python Sample Program

This is a Python 3 wrapper and sample Python application that supports transmit and receive operations.
Use it for developing custom Python wrappers and Python applications for MPX.

How to Run

After completing the user write-permission setup, build and install the Python wrapper sample in the following order.

python setup.py build
sudo python setup.py install

After installation, run mpx_adl_sample.py to execute the sample.

Features You Can Verify

  • Monitoring function
  • Transmission (simulation) function

Sample Behavior

  • CH1
    Transmits 10,000 messages while incrementing the CAN ID and the first byte of the payload.
    Displays messages on CH1 in the console.
  • CH2
    Unused

Sample Source Code

import MPX_ADL_WR
import threading

#read thread
def read_exec():
while True:
ret = MPX_ADL_WR.DispMonitor(serial,1)
if not ret is None:
for i in range(ret[0]):
print('time:' +
str(ret[1 + i][0]) +'[ms] , ' +
str(ret[1 + i][1]) +'[us] , CAN-ID:' +
hex(ret[1 + i][2]) +
' DL:' + str(ret[1 + i][3]) +
' DIR:' + ret[1 + i][4] +
' DATA:' + str(ret[1 + i][5]))
global stop_threads
if stop_threads:
break

ret=MPX_ADL_WR.MPXOpen()
if ret[0] != 0:
print('MPXOpen Error:' + str(ret[0]))

print('Serial No.')
for i in range(ret[1]):
print(' ' + str(ret[2][i]))

serial = ret[2][0]

print('MPX INIT.')
ret=MPX_ADL_WR.MPXSampleInit(serial)
if ret != 0:
print('INIT error:' + str(ret))

print('MPX MonitorStart.')
ret=MPX_ADL_WR.MPXMonitorStart(serial)

print('Start ReadThread...')
stop_threads = False
read_thread = threading.Thread(target=read_exec)
read_thread.start()

print('CAN_SEND...')
senddata=bytearray(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B')
for i in range(10000):
ret=MPX_ADL_WR.MPXDirectSend(serial,1,i,8,senddata)
senddata[0] = (senddata[0] + 1) % 256
if ret != 0:
print('SendError:' + str(ret))

stop_threads = True
read_thread.join()

ret=MPX_ADL_WR.MPXMonitorStop(serial)
if ret[0] != 0:
print('MonitorStop :Error' + str(ret[0]))
else:
print('MonitorStop :Time'+str(ret[1])+'[ms]'+ str(ret[2])+'[ns]')

ret=MPX_ADL_WR.MPXClose()
  1. Open and initialize device
  • MPXOpen() Searches for MicroPeckerX devices and obtains the serial number.
  • Initializes serial (MPXSampleInit) and starts monitoring (MPXMonitorStart).
  1. Start monitoring thread
  • Runs read_exec() in a separate thread.
    • Continuously monitors CAN reception and displays received data in real time.
    • Calls MPX_ADL_WR.DispMonitor and outputs returned values (received frame list).
  1. Generate and transmit CAN data
  • Prepares a 12-byte array (senddata) as initial data.
  • Transmits CAN frames 10,000 times in a loop using MPXDirectSend.
    • The third argument i is the CAN ID (incremented each loop).
    • The fourth argument 8 is the data length (8 bytes).
    • The fifth argument senddata is the payload to transmit.

The first byte of the transmitted payload (data field) is incremented each time.
The CAN ID uses loop variable i, so each transmission uses a different ID.

  1. Shutdown processing
  • After transmission, sets stop_threads = True to stop the receive thread.
  • Stops monitoring and closes the device.

C++ Sample Program

Features You Can Verify

  • Monitoring function
  • Transmission (simulation) function
  • Slot transmission function
  • Baud rate function
  • Termination resistor on/off switching function

Sample Behavior

  • CH1
    Operates in monitor mode and displays messages on CH1 in the console.
  • CH2
    Transmits ID:300 and ID:400 using slot transmission.
    Also transmits ID:350 using direct transmission.
Slot Transmission and Direct Transmission
  • Slot transmission configures transmission on MicroPeckerX and lets MicroPeckerX transmit autonomously.
    It supports strict transmission cycles, as required in actual vehicles.
  • Direct transmission sends frames each time under PC control.
    It is useful when changing data dynamically on the PC while transmitting.

Sample Source Code

#include "MPXCANFDCtrlLinuxFree.h"
#include "stdio.h"
#include "unistd.h"
#include <deque>
#include <pthread.h>
#include <sstream>
#include <string.h>
#include <iostream>
#include <stdint.h>

// global
unsigned int serial;
StMPXCANSlot MPXCANSlot[2];

// display string
std::deque<std::string> print_que;

void DispMonitor(void);

pthread_mutex_t que_mutex;
std::string strbuf;

void * thread_routine(void *data) {
while (1) {
usleep(1000 * 5); //wait1ms
pthread_mutex_lock(&que_mutex);
if(!print_que.empty()) {
strbuf = print_que.front();
print_que.pop_front(); // remove first element
std::cout << strbuf; // display buffer
}
pthread_mutex_unlock(&que_mutex);
pthread_testcancel();
}
return 0;
}


int main() {
ER ret;
unsigned int MSec;
unsigned short USec;

pthread_t print_thread;

printf("Sample Start\n");
/* Open MicroPeckerX */
StMPXDeviceInfo devices[4];
unsigned char count;

ret = MPXOpen(devices, &count);
if (ret != E_OK)
{
printf("MPXOpen : error");
return 1;
}
else if (count == 0)
{
printf("MPXOpen : no devices");
return 1;
}
else
{
/* Serial number */
serial = devices[0].Serial;
/* Turn off LEDs */
MPXSetLED(serial, MPX_LED_OFF, MPX_LED_OFF, MPX_LED_OFF, MPX_LED_OFF, MPX_LED_OFF);
}

for (int i = 0; i < count; i++) {
printf("Serial : [%d]\n" , devices[0].Serial );
}


/* API version information */
StMPXAPIVersion version;
MPXGetAPIVersion(&version);
printf("API Version : [%s]\n" , version.APIVersion );

/* CAN FD communication parameter settings */
StMPXCANParam param1, param2;
param1.Mode = MPX_MODE_MONITOR;
param1.ArbitrationBaudrate = MPX_CAN_PARAM_ABR_500K;
param1.ArbitrationSamplepoint = MPX_CAN_PARAM_SP_80P;
param1.DataBaudrate = MPX_CAN_PARAM_DBR_2M;
param1.DataSamplepoint = MPX_CAN_PARAM_SP_80P;
param1.EnableTerminate = MPX_CAN_TERMINATE_ENABLE; // termination enabled

param2 = param1;
param2.Mode = MPX_MODE_CAN_SIM; /* CH2: simulator (with transmission) */

ret = MPXSetCANParam(serial, 1, &param1);
if (ret != E_OK)
{
printf("\n MPXSetCANParam 1 : error\n");
return -1;
}
ret = MPXSetCANParam(serial, 2, &param2);
if (ret != E_OK)
{
printf("\n MPXSetCANParam 2 : error\n");
return -1;
}


/* Simulation data settings (slot transmission function) */
for (int i = 0; i < 2; i++)
{
MPXCANSlot[i].SlotNo = i;
MPXCANSlot[i].FrameType.Enabled = MPX_CAN_SLOT_ENABLE; /* Enable slot */
MPXCANSlot[i].FrameType.Option.Protocol = MPX_CAN_PROTOCOL_CANFD;
MPXCANSlot[i].FrameType.Option.BRS = MPX_CAN_BRS_ENABLE;
MPXCANSlot[i].Frame.ID.IDE = MPX_CAN_IDE_STD;
MPXCANSlot[i].Frame.ID.RTR = MPX_CAN_RTR_DATA;
MPXCANSlot[i].msSendCycle = 35U;
MPXCANSlot[i].SendCounter = 0; /* 0 means unlimited */
MPXCANSlot[i].Frame.DL = 20;
for (int j = 0; j < 20; j++)
{
MPXCANSlot[i].Frame.Data[j] = (i + 1) * 0x10 + j;
MPXCANSlot[i].Increment[j] = MPX_CAN_SIM_INC_TRUE;
}
}
/* Per-frame settings */
MPXCANSlot[0].Frame.ID.ID = 0x300U;
MPXCANSlot[1].Frame.ID.ID = 0x400U;
MPXCANSlot[1].msSendCycle = 2U;
MPXCANSlot[0].FrameType.FrameType = MPX_CAN_FRAME_TYPE_PERIODIC;
MPXCANSlot[1].FrameType.FrameType = MPX_CAN_FRAME_TYPE_PERIODIC;

/* Slot settings (2CH) */
ret = MPXSetSlot(serial, 2, &MPXCANSlot[0], 2);
if (ret != E_OK)
{
printf("\n MPXSetSlot 2 : error[%d]\n",ret);
return -1;
}

/* Set log acquisition mode Ch1 */
MPXSetGetLogMode(serial, 1, MPX_GETLOGMODE_GETLOGAPI);

/* Set log acquisition mode Ch1 */
MPXSetGetLogMode(serial, 2, MPX_GETLOGMODE_GETLOGAPI);

printf("\n Monitor Start ...\n");
/* Start monitoring */
ret = MPXMonitorStart(serial, MPX_SYNC_MASTER);
if (ret != E_OK)
{
printf("\n Monitor Start : error");
return -1;
}

int pth_arg;
// start display thread
pthread_mutex_init(&que_mutex, NULL);
if (pthread_create(&print_thread, NULL, thread_routine, (void *)&pth_arg) != 0) {
perror("pthread_create");
return 1;
}

/* Monitoring */
for(int i = 0; i < 10000 ;i++){
/* usleep (commented out):
software control cannot maintain periodic transmission intervals accurately
((scheduling may wait longer than the configured sleep time)) */
//usleep(50)
/* Direct transmission function */
StMPXCANDirect directFrame;
/* Transmission data settings (CAN-FD data) */
directFrame.FrameType.Option.Protocol = MPX_CAN_PROTOCOL_CANFD;
directFrame.FrameType.Option.BRS = MPX_CAN_BRS_ENABLE;

directFrame.Frame.ID.IDE = MPX_CAN_IDE_STD;
directFrame.Frame.ID.RTR = MPX_CAN_RTR_DATA;
directFrame.Frame.ID.ID = 0x350;
directFrame.Frame.DL = 64;
/* Assign counter value to first 4 bytes (CPU-endian dependent) */
memcpy(&directFrame.Frame.Data[0], &i, 4);
for (int i = 4; i < 64; i++)
{
directFrame.Frame.Data[i] = 0x30;
}

MPXDirectSend(serial,2,&directFrame);
DispMonitor();
}

ret = MPXMonitorStop(serial, &MSec, &USec);
if (ret != E_OK)
{
printf("MPXMonitorStop : error");
return -1;
}
pthread_mutex_lock(&que_mutex);
print_que.clear();
pthread_mutex_unlock(&que_mutex);


usleep(100 * 1000); //wait100ms

pthread_cancel(print_thread);
pthread_join(print_thread, NULL);

// clear display queue
if(!print_que.empty())
print_que.clear();

MPXClose();
return 0;
}

void DispMonitor(void)
{
/* Acquire monitor logs */
uint16_t Count;
uint8_t BufferOver;

ER ret;
StMPXCANLog *CANLog;
std::stringstream dispTmp;

// discard CH2 logs
ret = MPXGetLog(serial, 2, &CANLog, &Count, &BufferOver);
ret = MPXGetLog(serial, 1, &CANLog, &Count, &BufferOver);

if (ret != E_OK)
{
printf("MPXGetLog: error\n");
return;
}
/* Display logs */
for (int i = 0; i < (int)Count; i++)
{


// ignore empty logs
if(CANLog[i].Protocol == MPX_LOG_TYPE_EMPTY){
continue;
}
/* Error check */
if (CANLog[i].Error == CAN_ERRFLG_FALSE)
{
/* Time */
dispTmp << "time : " << std::dec << (int)CANLog[i].mSec << "[ms]," << (int)CANLog[i].uSec << "[us] ,";

/* ID format */
if (CANLog[i].IDE == MPX_CAN_IDE_STD)
{
//printf("Std ,");
dispTmp << "Std ,";
}
else
{
dispTmp << "Ext ,";
}

/* ID */
dispTmp << "CAN-ID:" << std::hex << (int)CANLog[i].ID << " ,";

dispTmp << "DL:" << std::dec <<(int)CANLog[i].DL << " ,";

/* Direction */
dispTmp << "DIR : ";
if (CANLog[i].Dir == MPX_LOG_DIR_RX)
{
dispTmp << "Rx ,";
}
else
{
dispTmp << "Tx ,";
}

dispTmp << "DATA : ";
/* Data */
for (int j = 0; j < CANLog[i].DL; j++)
{
dispTmp << std::hex << (int)CANLog[i].Data[j] << " ";
}
dispTmp << "\n";
}
else
{
if (CANLog[i].ErrorInfo & CAN_ERR_ACK)
{
dispTmp << "ERROR : Ack E.\n";
}
else if (CANLog[i].ErrorInfo == CAN_ERR_OVERLOAD)
{
dispTmp << "ERROR : OLF E.\n";
}
}
}
pthread_mutex_lock(&que_mutex);
print_que.push_back(dispTmp.str());
pthread_mutex_unlock(&que_mutex);

}