> For the complete documentation index, see [llms.txt](https://drcl.mju.ac.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://drcl.mju.ac.kr/research/project/mj-vesc/mjvesc-framework.md).

# MJ-VESCuino

{% hint style="info" %}
If you have any question on MJ-VESC, please leave a topic on 'Board' or send a email to <dongilc@mju.ac.kr>.&#x20;
{% endhint %}

## 1. What is MJ-VESC?

#### The MJ-VESC Project was launched to apply the VESC, which is commonly used in electric-skating board, to *"the Robotics area"*.&#x20;

#### The unique thing of MJ-VESC is stack-able design. The board form factor is Arduino Shield Type. So, it can be stacked on the Arduino.

<div align="center"><img src="/files/-LYqH4dgPHVFfbliFklL" alt="MJ-VESC ver0.1"></div>

![Stacked three MJ-VESCs with 3D printed Case.](/files/-LYqHwKfCEGJbuijVFQK)

![Stacked four MJ-VESCs on Arduino Due with 3D printed Case.](/files/-LYqJNSGoAIQA7MJXYSJ)

#### The hardware improvements from the existing VESC are as follows:

1. In **FOC** control, we provide **high torque** control even at **low speed**.&#x20;
2. **Position control** is possible at **Hall sensor** commutation with AB encoder (without index).
3. Hall & Encoder **Hybrid Commutation** for more precise position control.
4. More **accurate current control** by changing shunt resistor from 0.5mohm to 2mohm.
5. **Improved CAN** Communication Noise Filter using split terminal resistor and EMI filter.

#### The software improvements from the existing VESC are as follows:

1. High accuracy position control using "**DPS speed control**" (Degree Per Second).
2. VESC - **Arduino** high speed communication using **SPI communication**.
3. **Debugging terminal** using extra serial communication.

## 2. MJ-VESC Firmware Github Page

### 2.1. Firmware for MJ-VESC VER0.1

{% hint style="info" %}
The **MJ-VESC Firmware** version is based on **vesc bldc firmware 3.40** and compatible **VESC-TOOL** version is **0.95** at this moment.
{% endhint %}

{% embed url="<https://github.com/dongilc/bldc-mjvesc_v01_3.40>" %}

### 2.2. Original Firmware of VESC

{% embed url="<https://github.com/vedderb/bldc>" %}

### 2.3. VESC-TOOL 0.95

{% embed url="<https://github.com/vedderb/vesc_tool>" %}

## 3. ROS Control Framework for MJ-VESC

In this page, I will explain how to setup MJ-VESC when the high-level controller is based on **ROS** and communication method is **USB**.

1\. First, run VESC-TOOL (I assume that the motor setup of all the MJ-VESC is already finished)

```
./vesc_tool_0.95
```

Connect MJ-VESC ID=0.

```
Go to App Settings -> General -> APP to USE : Custom User App 
Go to App Settings -> General -> Send CAN Status : False.
```

2\. Connect MJ-VESC ID=1\~ using CAN-FORWARD (Setup all the other MJ-VESCs as below in case of ID>=1)

```
Go to App Settings -> General -> APP to USE : UART
Go to App Settings -> General -> Send CAN Status : True
```

The VESC-TOOL setup is finished.

3\. Download attached source code named 'vesc\_control\_ex1.zip'. You also need vesc library for ROS. Download 'vesc.zip' which is ros driver for MJ-VESC.

4\. Unzip and put those folders at your catkin workspace and then build. When you build, you may need dependencies as follows:

```
serial
ackermann-msgs
```

You can install above packages like this (when you use 'ros-melodic' then replace 'kinetic' to 'melodic').&#x20;

```
sudo apt-get install ros-kinetic-ackermann-msgs ros-kinetic-serial
```

5\. Run the ROS example using launch file below. Change argument 'port' depend on your condition.

```
roslaunch vesc_control_ex1 vesc_control_ex1_teleop.launch port:=/dev/ttyACM1
```

The main function of 'vesc\_control\_ex1\_node.cpp' is as below.

```
/*
 * Main Function
 * 
 */
int main(int argc, char **argv)            
{
  ros::init(argc, argv, "vesc_control_node");

  // loop freq
  int rate_hz = 50;	//hz

  // TeleopVesc Class
  const int num_of_vesc = VESC_ID_END+1;//4;
  TeleopVesc *teleop_vesc = new TeleopVesc(num_of_vesc);
  teleop_vesc->enable.data = false;

  // ROS Loop
  int cnt_lp = 0;
  ros::Rate loop_rate(rate_hz); //Hz
  ROS_INFO("Start Tele-operation");
  while (ros::ok())
  {
		teleop_vesc->enable.data = true;

		// read encoder data.
		//teleop_vesc->requestCustoms();
		//ROS_INFO("rps_0:%.2f(dps_0:%.2f), rad_0:%.2f", teleop_vesc->rps[0], teleop_vesc->rps[0]*RPS2DPS, teleop_vesc->rad[0]);
		//ROS_INFO("rps_1:%.2f(dps_1:%.2f), rad_1:%.2f", teleop_vesc->rps[1], teleop_vesc->rps[1]*RPS2DPS, teleop_vesc->rad[1]);
		//ROS_INFO("rps_2:%.2f(dps_2:%.2f), rad_2:%.2f", teleop_vesc->rps[2], teleop_vesc->rps[2]*RPS2DPS, teleop_vesc->rad[2]);
		//ROS_INFO("rps_3:%.2f(dps_3:%.2f), rad_3:%.2f", teleop_vesc->rps[3], teleop_vesc->rps[3]*RPS2DPS, teleop_vesc->rad[3]);

		// // current example (A)
		//teleop_vesc->current[0] = 4.0;
		//teleop_vesc->current[1] = 4.0;
		//teleop_vesc->current[2] = -1.0;
		//teleop_vesc->current[3] = 1.0;
		//teleop_vesc->setCurrentOut();

		// // brake example (A)
		//teleop_vesc->brake[0] = 10.0;
		//teleop_vesc->brake[1] = 10.0;
		//teleop_vesc->brake[2] = 5.0;
		//teleop_vesc->brake[3] = 8.0;
		//teleop_vesc->setBrakeOut();

		// // speed example (erpm = rev/min*polepair, polepair=Encoder Ratio@vesc_tool)
		//teleop_vesc->speed[0] = 0.//-(15000.0 - 5000.0);
		//teleop_vesc->speed[1] = 1000.//(15000.0 + 5000.0);
		//teleop_vesc->speed[2] = -1000.0;
		//teleop_vesc->speed[3] = 5000.0;
		//teleop_vesc->setSpeedOut();

		// // duty example (0.005~0.95)
		//teleop_vesc->duty[0] = 0.1;
		//teleop_vesc->duty[1] = 0.1;
		//teleop_vesc->duty[2] = 0.1;
		//teleop_vesc->duty[3] = 0.5;
		//teleop_vesc->setDutyCycleOut();

		// // position example (0~360 deg)
		//teleop_vesc->position[0] = 0.;
		//teleop_vesc->position[1] = 15.;
		//teleop_vesc->position[2] = 270.;
		//teleop_vesc->position[3] = -45.;
		//teleop_vesc->setPositionOut();

		// Custom example
		teleop_vesc->custom_cmd_type[0] = COMM_SET_DUTY;
		teleop_vesc->custom_cmd_value[0] = 0.6;
		teleop_vesc->custom_cmd_type[1] = COMM_SET_DPS;
		teleop_vesc->custom_cmd_value[1] = 1000.;
		//teleop_vesc->custom_cmd_type[2] = COMM_SET_DPS;
		//teleop_vesc->custom_cmd_value[2] = -1000.;
		//teleop_vesc->custom_cmd_type[3] = COMM_SET_DPS;
		//teleop_vesc->custom_cmd_value[3] = 1000.;
		//teleop_vesc->custom_cmd_type[1] = COMM_SET_DPS;
		//teleop_vesc->custom_cmd_value[1] = 0.;
		teleop_vesc->setCustomOut();

		ros::spinOnce();
		loop_rate.sleep();
  }

  return 0;
}
```

You can test 'SetCurrent', 'SetDutyCycle', 'SetSpeed', 'SetPosition', 'SetBrake', 'SetDPS' by un-commenting each functions. "COMM\_SET\_DPS" is only valid when you use 'teleop\_vesc->custom\_cmd\_type'.

{% hint style="info" %}
All the encoder data are stored at 'teleop\_vesc->rps\[id]' and 'teleop\_vesc->rad\[id]'. The 'rps' is rad/sec' and The 'rad' is Radian. You can easily use these variables at main function.
{% endhint %}

### Attachment

{% file src="/files/-LYqLpciwrCe2HfhBHEQ" %}
VESC ROS Driver
{% endfile %}

{% file src="/files/-LYqLslDC-JhKGCFUGaT" %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://drcl.mju.ac.kr/research/project/mj-vesc/mjvesc-framework.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
