TI 2MTR-DYNO load motor CCS control

The TI 2MTR-DYNO is a back-to-back permanent magnet synchronous motor system, with the two motors coupled together. The motors are driven by two inverters (Ti offers evaluation boards) and is controlled by a Delfino microcontroller. I have used TI's TMS320F28379D Launchpad to drive one of the two motors, while I was developing the hardware and software for the main motor. The load motor (controlled by the TI software) is in speed control mode, so it keeps a constant speed (positive, negative or zero), which is set by the Code Composer Studio code variables. The TI application note SPRACB8A explains how to get the code, connect the inverter and run the system in various different modes. I will focus in how to setup the system to have a single motor, operating in speed control mode, in order to act as a load during motor control development for the coupled motor.

The characteristics of the 2MTR-DYNO motors are detailed in a previous post. I am using the BOOSTXL-3PhGaNInv module, which consists of a three-phase GaN inverter, together with phase current sensors and a small level of protection circuits. I am have connected the inverter to the lower side BOOSTXL connectors of the Delfino board (J5-J8), as it was easier in terms of assembly. This means that the encoder of the motor, needs to be connected to the QEPB connector (with the triangle on pin1 of the connector). On the BOOSTXL inverter board, the DC supply and the motor phases need to be connected.

On the application code, following the Application Note, I set the 'MOTOR2_DRV' to 'GaN_BP', which is the default and set the 'BUILDLEVEL' to 'FCL_LEVEL5', which is the one for speed control. I have tested all previous build levels beforehand, to ensure the correct operation of the setup and see the voltage/current waveforms of the system and would recommend building on the previous levels as well. However, this post is about using a single motor as a load for the testbech. As soon as I set these parameters in the configuration file (FCL_SFRA_XL_DualServo-Settings.h), I built the project.

I then started the CCS debugger and loaded the key expressions, as shown below. To run the motor as a load for the testbench, the steps are the following:

  1. Hit 'Resume' on the debugger, to start the application code on the processor core
  2. Enable 'Continuous Refresh' on the expressions, to have a live update on the values
  3. Switch on the DC power I usually set it to 30V.  The GaN inverter is compatible with up to 48V
  4. Set 'EnableFlag' to '1'. Monitor the 'IsrTicker' that it's constantly updated
  5. Set 'QepCalFlag' to '1'. Set 'QepCalibSm' to 'Qep2'. This will rotate the motor to find the encoder index
  6. Wait for the encoder index learn. The 'QepCalibSm' will change to 'Done' after that
  7. Set 'Motor2.RunMotor' to 'RUN'. The inverter will start switching
  8. Set 'motor2.pid_spd.param.Umax' to '1.0' and 'motor2.pid_spd.param.Umin' to '-1.0'. This will give maximum capability to the inverter, in order to have the speed follow the reference value, under any torque on the axle.
  9. Set the reference speed by setting the parameter 'motor2.SpeedRef'. The value can be either positive or negative, and it is a ratio of the maximum speed.

TI 2MTR-DYNO motor characteristics

Texas Instruments provides an evaluation kit for Permanent Magnet Motor control. The kit provides two three-phase motors, which are coupled together (motor+load), two inverters and a single microcontroller launchpad, to drive the two inverters. TI also provides software for Field Oriented Control (FOC) with Space Vector Modulation (SVM). Although the TI documentation for the inverter, the microcontroller and the included software. However, there is almost no information about the motors, so I had to search the internet, to see pictures on how to connect the motors to the boards for example, or read the TI code for the ratings of the motor.

The motor is the M-2310P-LN-04K Brushless Three-Phase permanent magnet motor. The datasheet of this motor can be found on the Teknic website. The motor has an internal encoder of 4000counts per revolution. It also has a 120degree commutator, which is less preferable for Field Oriented Sensored Control.

The motor comes with the Molex Mini-Fit connector. It is then output to two low-power connectors (encoder and commutator) and has the high power cables available as well.

Encoder connector (J6)

The encoder connector is a standard 5-way single row 2.54 spacing connector. The pinout is shown below:

1 - Blue: Encoder A pulse

2 - Orange: Encoder B pulse

3 - Brown: Encoder I pulse

4 - Red: 5V power supply (125mA at idle)

5 - Black: Ground

Pin 1 is considered as the the pin with the ^ symbol. The encoder count is 4000 per mechanical revolution.

Power connections

All the wires are AWG16.

Black: Phase A

Red: Phase B

White: Phase C

Motor Characteristics

The motor has a sinusoidal Back-EMF. The back-EMF factor is 4.64Vp/krpm (line to line) [based on the datasheet]

The motor has 4 pole-pairs [based on the datasheet]. The resolver offset needs to be learned by applying fixed vectors to the windings.

The Maximum Continuous torque is 0.2754Nm [based on the datasheet, converting from oz-in]

Based on the above, the torque constant 0383725Nm/Ap, whereas the maximum Iq current is 7A.

On the motor label, the rated speed is mentioned, which is 6000rpm (mechanical). The label also states that the rated continuous current is 7.1A.

Concerning electrical characteristics, I have done the following measurements to determine the inductance and resistance:

Phase resistance: Measured with a DMM (4-wire measurement) the phase to phase resistance, when the TI kit molex connector was connected. The average phase to phase resistance was 777mΩ (at 20degC), leading to an average phase to neutral resistance of 389mΩ. The value mentioned on the datasheet is 720mΩ (phase to phase), which perhaps doesn't considers the extra harness.

Concerning inductance, the datasheet states 400uH (phase too phase), which doesn't say much about the motor characteristics. NXP has a good application note, which explains how to align the rotor, to measure the Ld and Lq value, applying step voltage changes on the windings. I did follow the application note to align the rotors (applying fixed vectors), but then used a network analyzer to determine the inductance for different frequencies. The results of these measurements are shown in the figure below.

Characterizing a device with LXI equipment

Usually, to measure the characteristic curve of a component, a Source Measure Unit (SMU) is needed, which sources a voltage and measures the current it provides with great accuracy. A similar task can be done with a power supply, together with a multimeter to have better accuracy. What is important about those measurements is automation. SMUs can be easily automated through scripts (TSP scripts for example for the Keithley SMUs) and can generate the characteristic curve autonomously, by sourcing different voltages/current and measuring the results.

To conduct similar tests with equipment of different manufacturers, a master controller is needed. With the use of LXI (LAN eXtensions for Instrumentation), this can be done with a computer as the master, commanding the test equipment and logging the results. MATLAB can be used to control the test equipment, log the results and present them in graphs.

All of the LXI compatible equipment use an Ethernet port, the easiest way is to connect them directly to the router, so that they are available to all of the other machines in the network. However, if the router is not close to the test equipment, a raspberry pi can be used to bridge the wireless network with the ethernet network, if all of the test equipment are connected to the raspberry pi. The lnxrouter can be used to setup the connection of the two networks. The routing table on the router or on the controller machine needs to be updated as well.

MATLAB does have an Instrument Control toolbox with some test equipment libraries, but I selected to write my own libraries for the power supply that I am using (Aim TTI MX100TP) and the multimeter (Keithley DMM6500). All of the functions I wrote for the LXI test equipment can be found in the github page. From MATLAB, the procedure is common to any other communication. The connection is opened, and the user writes to the device with an fprintf function call, and gets from the device with a query function call.

A simple example to control the power supply and log measurements from the power supply, as well as from the multimeter. The power supply has overcurrent and overvoltage protection, which can be set manually in the instrument to ensure that an erroneous code would not supply more than the load would handle. A loop is formed which increases the power supply output voltage by 0.2V step on every iteration and gets the voltage measurement from the power supply as well as the current measurement from the multimeter. The measurements are logged and plotted in real time. The multimeter is setup to get 10 measurements and report back the average.


%%% Defines %%%%
clear all;
MX100TP_ip = '';
DMM6500_ip = '';
CurrentLimit = 0.5;

% Connect to MX100TP %
MX100TP = instrfind('Type', 'tcpip', 'RemoteHost', MX100TP_ip, 'RemotePort', 9221, 'Tag', '');

if isempty(MX100TP)
    MX100TP = tcpip(MX100TP_ip, 9221);
    MX100TP = MX100TP(1);

% Connect to DMM6500%
DMM6500 = instrfind('Type', 'tcpip', 'RemoteHost', DMM6500_ip, 'RemotePort', 9221, 'Tag', '');
if isempty(DMM6500)
    DMM6500 = tcpip(DMM6500_ip, 5025);
    DMM6500 = DMM6500(1);

%%%%% Setup DMM6500 %%%%%%
DMM6500_Setup(DMM6500, 'FUNC_DC_CURRENT', 1, 10, 10);
%%%%%%% End of Setup %%%%%

voltage = 0;
current_MX100 = 0;
current_DMM6500 = 0;
disp('Start of Measurements');
M100TP_SetOutputValues(MX100TP, 1, 0, CurrentLimit); % Set current limit for Channel 1

close all;
f1 = subplot(2,1,1);
h1 = plot(voltage,current_MX100, '-o');
hold on;
h2 = plot(voltage,current_DMM6500, '-*');
xlabel('Voltage [V]'); ylabel('Current [mA]'); grid on; legend('MX100 Current','DMM6500 Current', 'location', 'southeast');
f2 = subplot(2,1,2);
h3 = plot(voltage,voltage*current_MX100, '-o');
hold on;
h4 = plot(voltage,voltage*current_DMM6500, '-*');
xlabel('Voltage [V]'); ylabel('Power [mW]'); grid on; legend('MX100 Power','DMM6500 Power', 'location', 'southeast');

for Voltage=0:0.2:35
    M100TP_SetOutputVoltage(MX100TP, 1, Voltage);
    fprintf('Voltage setpoint: %.1fV\n', Voltage);
    measvoltage = MX100TP_GetVoltage(MX100TP, 1);
    meascurrent_MX100 = MX100TP_GetCurrent(MX100TP, 1);
    meascurrent_DMM6500 = DMM6500_Read(DMM6500);
    voltage = [voltage measvoltage];
    current_MX100 = [current_MX100 meascurrent_MX100];
    current_DMM6500 = [current_DMM6500 meascurrent_DMM6500];
    set(h1, 'XData', voltage);
    set(h1, 'YData', current_MX100*1000);
    set(h2, 'XData', voltage);
    set(h2, 'YData', current_DMM6500*1000);
    set(h3, 'XData', voltage);
    set(h3, 'YData', voltage.*current_MX100*1000);
    set(h4, 'XData', voltage);
    set(h4, 'YData', voltage.*current_DMM6500*1000);

disp('End of Measurements');
M100TP_SetOutputValues(MX100TP, 1, 0, 0);

I used the code above to measure two resistors. One was a 100R resistor with the result shown below. As expected, the characteristic is linear.

The second resistor was a 10k one. Because of the much smaller current, the quantization error on the current measurement of the power supply is evident. Even if it has a 0.1mA resolution, still this is not enough. Whereas with the multimetre which has 6.5digits and a 10mA scale, the quantization noise is significantly lower.



Di2 Electronic shifting bike groupset upgrade

My road bike is a 2013 Merida Scultura Comp 905, with an electronic shifting compatible carbon frame and the 10-speed Shimano Ultegra 6700 groupset and rim brakes. I recently purchased the Ultegra 8050 groupset and, in this post, I describe the steps that were needed to install on the frame and some observations based on the experience.

But first of all, since I have changed already some components from the stock Scultura 905, the before-after components for the changes from mechanical groupset to electronic groupset are shown in the table below

Component Original Upgraded
Front Derailleur FD-6700 FD-R8050
Rear Derailleur RD-6700 RD-R8050-SS
Chainset 6750 50/34 R8000 50/34
Cassette CS-6700 11/28 CS-R8000 11/28
Shifters ST-6700 ST-R8050
Brakes Merida Pro BB-R8000
Seatpost Deda Elementi Superleggero 27.2mm [same]
Wheelset Fulcrum Racing Comp Fulcrum Racing Zero Black
Chain Ultegra 6700 10-speed CN-HG601
Bottom bracket Ultegra 6800 [same]
Battery - BT-DN110-A
Junction boxes - SM-EW90-A (frame) and SM-JC41 (internal)
Wireless unit - EW-WU111

The components already changed aided the electronic shifting upgrade:

  • The original seatpost (Merida Carbon) was broken in 2018 and replaced with the Deda Elementi one. It supports the internal battery using seatpost battery holder 
  • The chainset (FSA Energy Mega 50/34) was broken in 2018 and replaced with the Ultegra compact equivalent. I changed the bottom bracket at the same time from the FSA Mega Exo to the Shimano 6800 one. This ensures compatiblity with the updated chainset.

Some more components to consider, which were used for the installation and operation:

  • Deda seatpost battery holder: Needed to mount the battery inside the seatpost. You could make something custom, but this is pretty neat.
  • EW-SD50 wires: Various lengths, depending on the frame size and location of each of the components.
  • SM-GM01 and SM-GM02 grommets: Used to secure the wires when entering the frame.
  • SM-AD91 band adapter: Needed if the frame doesn't have a front derailleur hanger
  • EW-SD501 wire holders: Place on the wires that are routed inside the frame. Prevents rattling noise and helps you keep your sanity.
  • Concerning the wheels, the hub was only 10-speed compatible, so an upgrade was needed :)
  • The wireless unit is not mandatory, but it allows to connect the di2 mechanism to the GPS head unit. This function is used to check the current battery and gear combination, as well as to control the head unit from the shifters.

 Here is the bike at its mechanical shifting state, together with all of the components. Logistics to get all the compatible parts is not the easiest part in the world.

Before starting to route cables through the frame, it is a good idea to check that all of the components are working with the intended connections, on the bench (or table). I connected the wireless transceiver between the top and bottom junction box and upgraded the firmware of all the components.

There is a junction box that goes next the bottom bracket. I also placed the wireless transceiver next to it and packaged it to avoid any rattling inside the frame. Although Shimano does not recommend placing the transceiver inside the frame, I haven't had any connection issue with the head unit or phone. Because of all the various connections inside this tight space, I labeled all the cables, in case modifications/troubleshooting are need in the future.

The rear derailleur is easy to fit. However, it is difficult to make the grommet stay in place. It needs some patience. The high and low screws need to be setup (as is the case with a mechanical derailleur). However, the "cable tension" is setup electronically.

Shimano has very detailed diagrams on how to assemble the front derailleur with a band adapter (my frame doesn't have a derailleur hanger). I didn't need to do any adjustment after that.

I placed the junction box underneath the stem, with some velcro tape. Though I haven't needed to remove the junction box yet and don't think I will anytime soon. However, I didn't like Shimano's solution with the elastic band (I find it ugly). However, if you were to ride on cobblestones, perhaps this would be the only solution. I used heatshrink to increase a bit the the width of the Di2 cable and fit it between the junction box and the frame.

As I wanted to get extra buttons to shift the rear derailleur from the top instead of the hoods, I modified some buttons from eBay with the Di2 connector (cut a Di2 cable in half and soldered it to the end of the flexi of the button, and then applied hot glue). This can be connected to sprint shifter port of the Di2 shifters.

Finished result:

Not needing to adjust the cable tension every now and then is nice. As you lose the feedback on the shifter to understand at which point of the cassette you are, it is beneficial to have the current value on the head unit. It also provides audible feedback when you reach either limit of your gearing. Concerning battery, you forget to charge it (although it alerts you when the Di2 battery is getting low). Concerning traveling, I'd argue that it is easier to disassemble the bike (I leave the battery inside the seatpost and disconnect the cable, I also disconnect the two cables from the shifters to the junction box).


Desk clock based on an STM32 microcontroller

Based on my initial tests of Dot Matrix displays using either an FPGA or an STM32F4 microcontroller, I wanted to build a desk clock with the following features:

  • Low drift using an external crystal
  • Automatic setup using an NTP server via WiFi
  • Support for daylight saving
  • Temperature and Humidity measurement
  • Periodic update using an NTP server
  • Adjustable brightness
  • Single 5V supply
  • Minimum external components and wire connections
  • Support for WiFi credentials reconfiguration

The Dot Matrix display I selected was a 64x32 RGB display which has a 5V supply input. The microcontroller I used was an STM32F767 which has a maximum clock frequency of 216MHz (important, since, as analyzed in previous articles, to achieve a high refresh rate, a high clock frequency is needed, especially as a microcontroller would be used instead of an FPGA, to keep the cost low).

The F767 is mounted on a Nucelo144 board. I selected the specific board because it had an on board 32.768kHz crystal as well as the necessary 3.3V regulator. A lower cost F4 Nucleo could also be used, but I also wanted to check some other features of the specific board (especially the hardware double precision FPU and the Ethernet PHY).

To get the time from an NTP server, I used a Wemos D1 mini board, which uses the well known ESP8266 chip. Again, the D1 mini board has a 3.3V regulator, a UART to USB converter, a USB port as well as the necessary pull up resistors for the ESP8266. I have used the ESP8266 before, when I built WiFi Power switch. The chip can be programmed through Arduino (using all the available Arduino libraries as well).

Concerning the temperature and humidity measurement (which was a late request), I selected the DHT21 (AM2301) single wire temperature and humidity sensor, which I have also used before when building the Raspberry Pi Meteo Station. It has a very good accuracy for the application, and, because of its popularity, many libraries are already available.

The connection diagram of the different components is shown below. The external 5V power supply (4A maximum current, <1A expected during operation), powers both the Dot Matrix Display as well as the Nucleo board, via the external 5V Vin pin. Through the Nucleo connectors, the 5V rail is also supplied to the Wemos D1 mini board, and is stepped down to 3.3V through the onboard regulator. 3.3V is also supplied to the DHT21 sensor via another Nucleo header connector.

Concerning data transmission, the microcontroller and the ESP8266 will communicate via UART using a predefined protocol. In case of connection loss, the STM32 microcontroller will be able to reset the ESP8266 chip via the external reset pin, which is connected to an STM32 GPIO. The temperature sensor is also connected to the ESP8266 board, to decrease any processor load of the main STM32 microcontroller (which could result in display flickering if not taken into account). What is more, the matrix display data is sent through the GPIO peripheral of the microcontroller (13 pins in total) based on code analyzed previously.

The algorithm of the microcontroller also features

  • 1 second interrupts (via the WakeUp RTC function) to update the display
  • RTC alarm interrupt to get new NTP date and time
  • Reset of the WiFi chip if no data is sent back
  • Adjustable display brightness using the Nucleo User button
  • UART interrupts for received data and error checking

The ESP8266 handles the WiFi connection (and update of credentials), temperature and humidity data from the DHT21 sensor, NTP time requests as well as daylight savings settings. To implement all of the above, the following libraries were used:

The data display format was based on a Bluetooth FPGA Dot matrix clock. In that case, each frame was constructed through a Matlab script and sent via Bluetooth to a Xilinx FPGA. As shown previously, the FPGA, because of its parallel data processing, can achieve higher color resolution (or higher FPS). However to operate, it would always need to be connected to a computer. The display features greek font support, hour and minute vertical bars (left and right side of the display respectively), a seconds bar on the bottom edge of the display as well as color animations.

The mounting on the clock was also based on the above FPGA clock. The aim of the assembly was to eliminate any wires which would interconnect the four main components. All the wires are sandwiched between the Nucleo board on one side and the dot matrix display on the other side of the mount. The user button is accessible from the backside to change the display brightness, as well as the reset button. The micro-USB ports of the Nucleo board as well as the Wemos D1 mini board are also accessible for future firmware updates.