Team,
I found sample code in the RMP Help files for using a PROBE input on a Panasonic Drive. Is there anything available showing how to configure and use the PROBE input on a Mitsubishi MR-J5 Drive using C#?
Hi @JadeMonro,
Welcome to Community and thank you for your post! We are working on getting some code snippets together to share with you shortly. Then we will post a sample app once we can fully test it on hardware.
Stay tuned!
Hi @JadeMonro,
We have created a MitsubishiTouchProbe Demo Application that I’ll send over to you shortly via email because I can’t upload it to community. Eventually we will publish the app on our sample apps page.
The application demonstrates how to configure, arm, check status, and retrieve latched position for Touch probes 1 2, and 3.
Thank You
Hi @jonathan
It’ll be great if you could share this sample app with me.
I’m too working on configuring the touch probe on a Mitsubishi servo drive.
Thanks
Here is some code that was tested with TP1 and TP2, with some untested code for TP3:
using RSI.RapidCode.dotNET; // Import the RapidCode Library.
using NUnit.Framework;
using System.Collections;
class TouchProbeMitsubishi
{
const RSINodeType NODE_TYPE = RSINodeType.RSINodeTypeMITSUBISHI_MR_J5_TM; // which node type to use for this demo
const int AXIS_NUMBER = 0; // which Axis to use for this demo
const TouchProbe TOUCH_PROBE = TouchProbe.TP1; // which TouchProbe function to use for this demo
const TouchProbeEdge EDGE = TouchProbeEdge.Rising; // which TouchProbe edge to use for this demo
const int MITSUBISHI_TOUCH_PROBE_SUB_INDEX = 0; // all the touch probe SDOs use sub-index 0
const int MITSUBISHI_TP2_BITS_OFFSET = 8; // TP2 bits are in the upper 8 bits of the function index and status index
// touch probe function indexes
const int MITSUBISHI_TOUCH_PROBE_FUNCTION_BYTE_SIZE = 2; // all function SDO are 2 bytes
//Touch Probe Function (1 & 2)
//Write 0x60B8 Sub 0 Size 2 bytes.
// TPR1
//Bit 0 Enable (0 - Disabled, 1 - Enabled) [Set to 1]
//Bit 1 Type (0 for single trigger, 1 for Continuous) [Set to 0]
//Bit 2 Source (Triggered by inputting Touch Probe 1, 1 Triggered at the zero point of the encoder) [Set to 0]
//Bit 3 Reserved [Set to 0]
//Bit 4 (0 Ignore Rising, 1 Record Rising) [Set to 1]
//Bit 5 (0 Ignore Falling, 1 Record Falling) [Set to 1]
// TPR2
//Bit 8 Enable (0 - Disabled, 1 - Enabled) [Set to 1]
//Bit 9 Type (0 for single trigger, 1 for Continuous) [Set to 0]
//Bit 10 Source (Triggered by inputting Touch Probe 1, 1 Triggered at the zero point of the encoder) [Set to 0]
//Bit 11 Reserved [Set to 0]
//Bit 12 (0 Ignore Rising, 1 Record Rising) [Set to 1]
//Bit 13 (0 Ignore Falling, 1 Record Falling) [Set to 1]
const int MITSUBISHI_TP1_TP2_FUNCTION_INDEX = 0x60B8;
//Touch Probe Function (3)
//Write 0x2DE8 Sub 0 Size 2 bytes.
// TPR3
//Bit 0 Enable (0 - Disabled, 1 - Enabled) [Set to 1]
//Bit 1 Type (0 for single trigger, 1 for Continuous) [Set to 0]
//Bit 2 Source (Triggered by inputting Touch Probe 1, 1 Triggered at the zero point of the encoder) [Set to 0]
//Bit 3 Reserved [Set to 0]
//Bit 4 (0 Ignore Rising, 1 Record Rising) [Set to 1]
//Bit 5 (0 Ignore Falling, 1 Record Falling) [Set to 1]
const int MITSUBISHI_TP3_FUNCTION_INDEX = 0x2DE8;
// status indexes
const int MITSUBISHI_TOUCH_PROBE_STATUS_BYTE_SIZE = 2;
// Touch Probe Status (1&2)
//Read 60b9 sub 0 size 2 bytes.
// TPR1
//Bit 0 Touch Probe 1 (0 - Disabled, 1 - Enabled)
//Bit 1 Touch Probe 1 (0 - No Rising Edge Data, 1 - Data Stored)
//Bit 2 Touch Probe 1 (0 - No Falling Edge Data, 1 - Data Stored)
// TPR2
//Bit 8 Touch Probe 2 (0 - Disabled, 1 - Enabled)
//Bit 9 Touch Probe 2 (0 - No Rising Edge Data, 1 - Data Stored)
//Bit 10 Touch Probe 2 (0 - No Falling Edge Data, 1 - Data Stored)
const int MITSUBISHI_TOUCH_PROBE_STATUS_INDEX = 0x60B9;
// Touch Probe Status (3)
//Read 0x2de9 sub 0 size 2 bytes.
// TPR3
//Bit 0 Touch Probe 3 (0 - Disabled, 1 - Enabled)
//Bit 1 Touch Probe 3 (0 - No Rising Edge Data, 1 - Data Stored)
//Bit 2 Touch Probe 3 (0 - No Falling Edge Data, 1 - Data Stored)
const int MITSUBISHI_ATL_TOUCH_PROBE_STATUS_INDEX = 0x2de9;
// SDO indexes to read the positions
const int MITSUBISHI_TP1_POSITION_RISING_INDEX = 0x60BA;
const int MITSUBISHI_TP1_POSITION_FALLING_INDEX = 0x60BB;
const int MITSUBISHI_TP2_POSITION_RISING_INDEX = 0x60BC;
const int MITSUBISHI_TP2_POSITION_FALLING_INDEX = 0x60BD;
const int MITSUBISHI_TP3_POSITION_RISING_INDEX = 0x2DEA;
const int MITSUBISHI_TP3_POSITION_FALLING_INDEX = 0x2DEB;
const int MITSUBISHI_TOUCH_PROBE_POSITION_BYTE_SIZE = 4;
const int TIMEOUT_IN_MS = 1000;
MotionController controller;
Axis axis;
public enum TouchProbe
{
TP1,
TP2,
TP3,
};
public enum TouchProbeEdge
{
Rising,
Falling,
};
public TouchProbeMitsubishi()
{
// Initialize RapidCode Objects
controller = MotionController.CreateFromSoftware("C:/RSI/10.6.7/"); // Insert the path location of the RMP.rta (usually the RapidSetup folder)
HelperFunctions.CheckErrors(controller); // [Helper Function] Check that the controller has been initialized correctly.
HelperFunctions.StartTheNetwork(controller); // [Helper Function] Initialize the network.
axis = controller.AxisGet(AXIS_NUMBER);
HelperFunctions.CheckErrors(axis);
}
public void ArmTouchProbe()
{
const int ARM_TOUCH_PROBE_BIT_INDEX = 3;
const int RISING_EDGE_BIT_INDEX = 4;
const int FALLING_EDGE_BIT_INDEX = 5;
int functionIndex = 0;
int functionConfigurationBits = 0;
const int enable = 1 << 0; // bit 0 is enable
functionConfigurationBits |= enable;
if (EDGE == TouchProbeEdge.Rising)
{
const int recordRising = 1 << RISING_EDGE_BIT_INDEX; // bit 4 is to arm rising
functionConfigurationBits |= recordRising;
}
else if (EDGE == TouchProbeEdge.Falling)
{
const int recordFalling = 1 << FALLING_EDGE_BIT_INDEX; // bit 5 is to arm falling
functionConfigurationBits |= recordFalling;
}
// TP2 is special, its bits are the same, just in the upper 8 bits
if (TOUCH_PROBE == TouchProbe.TP2)
{
// shift them up 8 bits
functionConfigurationBits <<= MITSUBISHI_TP2_BITS_OFFSET;
}
switch (TOUCH_PROBE)
{
case TouchProbe.TP1:
case TouchProbe.TP2:
{
functionIndex = MITSUBISHI_TP1_TP2_FUNCTION_INDEX;
}
break;
case TouchProbe.TP3:
{
functionIndex = MITSUBISHI_TP3_FUNCTION_INDEX;
}
break;
default:
break;
}
axis.NetworkNode.ServiceChannelWrite(
functionIndex,
MITSUBISHI_TOUCH_PROBE_SUB_INDEX,
MITSUBISHI_TOUCH_PROBE_FUNCTION_BYTE_SIZE,
functionConfigurationBits,
TIMEOUT_IN_MS);
// print what we wrote, and to what index, subindex, size, etc in the preceding SDO
Console.WriteLine($"Armed SDO 0x{functionIndex:X} with {functionConfigurationBits:X}");
}
public void DisarmTouchProbe()
{
int functionIndex = 0;
int functionConfigurationBits = 0; // write zero to disarm
switch (TOUCH_PROBE)
{
case TouchProbe.TP1:
case TouchProbe.TP2:
{
functionIndex = MITSUBISHI_TP1_TP2_FUNCTION_INDEX;
}
break;
case TouchProbe.TP3:
{
functionIndex = MITSUBISHI_TP3_FUNCTION_INDEX;
}
break;
default:
break;
}
axis.NetworkNode.ServiceChannelWrite(
functionIndex,
MITSUBISHI_TOUCH_PROBE_SUB_INDEX,
MITSUBISHI_TOUCH_PROBE_FUNCTION_BYTE_SIZE,
functionConfigurationBits,
TIMEOUT_IN_MS);
// print what we wrote, and to what index, subindex, size, etc in the preceding SDO
Console.WriteLine($"Disarmed SDO 0x{functionIndex:X} with {functionConfigurationBits:X}");
}
public bool GetCaptureStatus()
{
const int RISING_EDGE_BIT_INDEX = 1;
const int FALLING_EDGE_BIT_INDEX = 2;
int statusIndex = MITSUBISHI_TOUCH_PROBE_STATUS_INDEX; // this one is valid for TP1 and TP2
int expectedStatusMask = 0;
if (EDGE == TouchProbeEdge.Rising)
{
expectedStatusMask = 1 << RISING_EDGE_BIT_INDEX;
}
else if (EDGE == TouchProbeEdge.Falling)
{
expectedStatusMask = 1 << FALLING_EDGE_BIT_INDEX;
}
if (TOUCH_PROBE == TouchProbe.TP2)
{
// shift up 8 bits
expectedStatusMask <<= MITSUBISHI_TP2_BITS_OFFSET; // TP2 status bits are in the upper 8 bits
}
if (TOUCH_PROBE == TouchProbe.TP3)
{
statusIndex = MITSUBISHI_ATL_TOUCH_PROBE_STATUS_INDEX;
}
int result = axis.NetworkNode.ServiceChannelRead(
statusIndex,
MITSUBISHI_TOUCH_PROBE_SUB_INDEX,
MITSUBISHI_TOUCH_PROBE_STATUS_BYTE_SIZE,
TIMEOUT_IN_MS);
// print result in hex
//Console.WriteLine("TouchProbe Status: 0x" + result.ToString("X"));
//also read and print all 32-bits of digital inputs from 0x60FD
//int digitalInputs = axis.NetworkNode.ServiceChannelRead(0x60FD, 0, 4, TIMEOUT_IN_MS);
//Console.WriteLine("Digital Inputs: 0x" + digitalInputs.ToString("X"));
// check if the expected status bit mask is set
if ((result & expectedStatusMask) == expectedStatusMask)
{
return true;
}
return false;
}
public int GetLatchedPosition()
{
int result = 0;
int latchedPositionIndex = 0;
switch (TOUCH_PROBE)
{
case TouchProbe.TP1:
latchedPositionIndex = (EDGE == TouchProbeEdge.Rising) ?
MITSUBISHI_TP1_POSITION_RISING_INDEX : MITSUBISHI_TP1_POSITION_FALLING_INDEX;
break;
case TouchProbe.TP2:
latchedPositionIndex = (EDGE == TouchProbeEdge.Rising) ?
MITSUBISHI_TP2_POSITION_RISING_INDEX : MITSUBISHI_TP2_POSITION_FALLING_INDEX;
break;
case TouchProbe.TP3:
latchedPositionIndex = (EDGE == TouchProbeEdge.Rising) ?
MITSUBISHI_TP3_POSITION_RISING_INDEX : MITSUBISHI_TP3_POSITION_FALLING_INDEX;
break;
default:
throw new Exception("Unknown Touch Probe Source");
}
result = axis.NetworkNode.ServiceChannelRead(
latchedPositionIndex,
MITSUBISHI_TOUCH_PROBE_SUB_INDEX,
MITSUBISHI_TOUCH_PROBE_POSITION_BYTE_SIZE,
TIMEOUT_IN_MS);
return result;
}
void ConfigureTP3()
{
//This only needs to happen once as a Configuration call.
const int MITSUBISHI_TPR3_CONFIGURATION_INDEX = 0x2185;
const int MITSUBISHI_TPR3_SUB_INDEX = 0;
const int MITSUBISHI_TPR3_BYTE_SIZE = 2;
const int DESIRED_CONFIGURATION = 0x63;
const int MITSUBISHI_SAVE_SETTINGS_INDEX = 0x1010;
const int MITSUBISHI_SAVE_SETTINGS_SUB_INDEX = 1;
const int MITSUBISHI_SAVE_SETTINGS_BYTE_SIZE = 4;
const int MITSUBISHI_SAVE_SETTINGS_VALUE = 0x65766173;
int result = axis.NetworkNode.ServiceChannelRead(
MITSUBISHI_TPR3_CONFIGURATION_INDEX,
MITSUBISHI_TPR3_SUB_INDEX,
MITSUBISHI_TPR3_BYTE_SIZE,
TIMEOUT_IN_MS);
if (result == DESIRED_CONFIGURATION)
{ // Properly configured for TPR3
return; //success
}
else
{
Console.WriteLine("Setting TPR3 Configuration");
axis.NetworkNode.ServiceChannelWrite(
MITSUBISHI_TPR3_CONFIGURATION_INDEX,
MITSUBISHI_TPR3_SUB_INDEX,
MITSUBISHI_TPR3_BYTE_SIZE,
DESIRED_CONFIGURATION,
TIMEOUT_IN_MS);
axis.NetworkNode.ServiceChannelWrite(
MITSUBISHI_SAVE_SETTINGS_INDEX,
MITSUBISHI_SAVE_SETTINGS_SUB_INDEX,
MITSUBISHI_SAVE_SETTINGS_BYTE_SIZE,
MITSUBISHI_SAVE_SETTINGS_VALUE,
TIMEOUT_IN_MS);
Console.WriteLine("Configured! Drive needs to be power cycled. Only needs to happen once per drive firmware update.");
}
}
public void Run()
{
if (axis.NetworkNode.TypeGet() != NODE_TYPE)
{
throw new Exception("This example is only for Mitsubishi J5 so we expect node type of " + NODE_TYPE.ToString());
}
// if you are using Home input for TP3, you probably need to call this once
//ConfigureTP3(); // and you need to reboot the drive after this one
ArmTouchProbe();
while (true)
{
Console.WriteLine("Waiting for TouchProbe " + TOUCH_PROBE + " on edge: " + EDGE + "... press ESC to exit.");
while (!GetCaptureStatus())
{
System.Threading.Thread.Sleep(1000); // sleep a little bit
if (Console.KeyAvailable)
{
if (Console.ReadKey(true).Key == ConsoleKey.Escape)
{
Console.WriteLine("Escape pressed, exiting.");
return;
}
else
{
Console.WriteLine("Key pressed, re-arming.");
break; // Break the inner loop to re-arm
}
}
}
if (!GetCaptureStatus())
{
continue; // Skip the position print and re-arming
}
Console.WriteLine("TouchProbe " + TOUCH_PROBE + " Captured!");
Console.WriteLine("TouchProbe " + TOUCH_PROBE + " Position: " + GetLatchedPosition());
DisarmTouchProbe();
ArmTouchProbe(); // re-arm
}
}
}
class TouchProbeMitsubishiProgram
{
static void Main(string[] args)
{
try
{
TouchProbeMitsubishi touchProbeMitsubishi = new TouchProbeMitsubishi();
touchProbeMitsubishi.Run();
}
catch (Exception e)
{
Console.WriteLine("FAILURE: " + e.Message);
}
}
}