Cant send commands to PM3 using C#. Please help me

Post questions and issues with Concept2 PM3 SDK
Daren
1k Poster
Posts: 144
Joined: March 16th, 2006, 1:49 pm

Post by Daren » September 19th, 2006, 3:57 pm

onyak wrote:soares, can I get copy of your source code? I want to build my own tools for the Concept2 in C# and have no idea where to start.
This won't copy&paste, compile and run, but should give you a leg up. It was written quite a while ago, and I'm not really a C# programmer, nor have I learnt much of the .Net framework, so I make no claims as to its quality.

Code: Select all

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Runtime.InteropServices; // this is for DllImport
using System.Timers;

namespace PM3App
{
	enum CSAFE : uint
	{ 
		CSAFE_GETSTATUS_CMD					= 0x80,
		CSAFE_RESET_CMD                     = 0x81,
		CSAFE_GOIDLE_CMD                    = 0x82,
		CSAFE_GOHAVEID_CMD                  = 0x83,
		CSAFE_GOINUSE_CMD                   = 0x85,
		CSAFE_GOFINISHED_CMD                = 0x86,
		CSAFE_GOREADY_CMD                   = 0x87,
		CSAFE_BADID_CMD                     = 0x88,
		CSAFE_GETVERSION_CMD                = 0x91,
		CSAFE_GETID_CMD                     = 0x92,
		CSAFE_GETUNITS_CMD                  = 0x93,
		CSAFE_GETSERIAL_CMD                 = 0x94,
		CSAFE_GETLIST_CMD                   = 0x98,
		CSAFE_GETUTILIZATION_CMD            = 0x99,
		CSAFE_GETMOTORCURRENT_CMD           = 0x9A,
		CSAFE_GETODOMETER_CMD               = 0x9B,
		CSAFE_GETERRORCODE_CMD              = 0x9C,
		CSAFE_GETSERVICECODE_CMD            = 0x9D,
		CSAFE_GETUSERCFG1_CMD               = 0x9E,
		CSAFE_GETUSERCFG2_CMD               = 0x9F,
		CSAFE_GETTWORK_CMD                  = 0xA0,
		CSAFE_GETHORIZONTAL_CMD             = 0xA1,
		CSAFE_GETVERTICAL_CMD               = 0xA2,
		CSAFE_GETCALORIES_CMD               = 0xA3,
		CSAFE_GETPROGRAM_CMD                = 0xA4,
		CSAFE_GETSPEED_CMD                  = 0xA5,
		CSAFE_GETPACE_CMD                   = 0xA6,
		CSAFE_GETCADENCE_CMD                = 0xA7,
		CSAFE_GETGRADE_CMD                  = 0xA8,
		CSAFE_GETGEAR_CMD                   = 0xA9,
		CSAFE_GETUPLIST_CMD                 = 0xAA,
		CSAFE_GETUSERINFO_CMD               = 0xAB,
		CSAFE_GETTORQUE_CMD                 = 0xAC,
		CSAFE_GETHRCUR_CMD                  = 0xB0,
		CSAFE_GETHRTZONE_CMD                = 0xB2,
		CSAFE_GETMETS_CMD                   = 0xB3,
		CSAFE_GETPOWER_CMD                  = 0xB4,
		CSAFE_GETHRAVG_CMD                  = 0xB5,
		CSAFE_GETHRMAX_CMD                  = 0xB6,
		CSAFE_GETUSERDATA1_CMD              = 0xBE,
		CSAFE_GETUSERDATA2_CMD              = 0xBF,
		CSAFE_SETUSERCFG1_CMD               = 0x1A,
		CSAFE_SETTWORK_CMD                  = 0x20,
		CSAFE_SETHORIZONTAL_CMD             = 0x21,
		CSAFE_SETPROGRAM_CMD                = 0x24,
		CSAFE_SETTARGETHR_CMD               = 0x30,
		CSAFE_PM_GET_WORKDISTANCE			= 0xA3,
		CSAFE_PM_GET_WORKTIME				= 0xA0,
		CSAFE_PM_SET_SPLITDURATION			= 0x05,
		CSAFE_PM_GET_FORCEPLOTDATA			= 0x6B,
		CSAFE_PM_GET_DRAGFACTOR				= 0xC1,
		CSAFE_PM_GET_STROKESTATE			= 0xBF,
		CSAFE_UNITS_METER					= 0x24
	}

	enum StrokeState { Idle	= 0, Catch	= 1, Drive	= 2, Dwell = 3, Recovery = 4 }

	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		[ DllImport("RPPM3DDI.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern ushort tkcmdsetDDI_init();

		[ DllImport("RPPM3DDI.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern ushort tkcmdsetDDI_discover_pm3s( 
			string product_name, 
			ushort starting_address,
			ref ushort num_units);

		[ DllImport("RPPM3Csafe.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern ushort tkcmdsetCSAFE_init_protocol(ushort timeout);

		[ DllImport("RPPM3Csafe.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern ushort tkcmdsetCSAFE_command(
			ushort		unit_address,
			ushort		cmd_data_size, 
			uint []	cmd_data,
			ref ushort	rsp_data_size, 
			uint []	rsp_data);

		void PM3GetStatusThread()
		{
			StrokeState PreviousStrokeState = StrokeState.Idle;
			bool	bNewStroke = false;
			bool	bEndOfDrive = false;
			double	dWorkTime = 0;
			double	dWorkDistanceRowed = 0;

			DateTime timeStart = DateTime.Now;
			DateTime timeStop = DateTime.Now;
			long timeDrive = 0;
			long timeRecovery = 0;

			while (!bTerminate)
			{
				if (!bPause && bConnected && !bRaceFinished)
				{
					StrokeState CurrentStrokeState = StrokeState.Idle;
					ushort ecode = 0;
					uint CurrentSPM = 0;
					uint CurrentHR = 0;

					bNewStroke = false;
					bEndOfDrive = false;

					uint [] cmd_data = new uint [64];
					ushort cmd_data_size;
					uint [] rsp_data = new uint [1024];
					ushort rsp_data_size = 0;

					cmd_data_size = 0;

					// PM3 extension commands wrapped up
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_SETUSERCFG1_CMD;

					cmd_data[cmd_data_size++] = 0x04; //4 commands -- REMEMBER to make this match
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_PM_GET_STROKESTATE;
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_PM_GET_DRAGFACTOR;
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_PM_GET_WORKDISTANCE;
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_PM_GET_WORKTIME;

					// standard commands follow
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GETPACE_CMD;
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GETPOWER_CMD;
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GETCADENCE_CMD;
					cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GETHRCUR_CMD;

					// CSAFE_GETHRCUR_CMD				

					ecode = tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data);

					if (0 == ecode)
					{
						uint currentbyte = 0;
						uint datalength = 0;

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_SETUSERCFG1_CMD)
						{
							currentbyte+=2;	
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_PM_GET_STROKESTATE)
						{						
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;

							switch (rsp_data[currentbyte])
							{
								case 0:
								case 1:
									CurrentStrokeState = StrokeState.Catch;
									break;
								case 2:
									CurrentStrokeState = StrokeState.Drive;
									break;
								case 3:
									CurrentStrokeState = StrokeState.Dwell;
									break;
								case 4:
									CurrentStrokeState = StrokeState.Recovery;
									break;
							}
							currentbyte+=datalength;
						}

						if (!bRaceStarted && CurrentStrokeState != StrokeState.Catch)
						{
							bFalseStart = true;
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_PM_GET_DRAGFACTOR)
						{
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;

							uint DF = rsp_data[currentbyte];

							currentbyte+=datalength;
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_PM_GET_WORKDISTANCE)
						{
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;

							uint Distance = (rsp_data[currentbyte] + (rsp_data[currentbyte+1] << 8) + (rsp_data[currentbyte+2] << 16) + (rsp_data[currentbyte+3] << 24)) / 10;
							uint fraction = rsp_data[currentbyte+4];
					
							dWorkDistance = Distance + (fraction/10.0);

							dCurrentDistance = dWorkDistance - dWorkDistancePreviousStage;

							currentbyte+=datalength;
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_PM_GET_WORKTIME)
						{
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;

							if (datalength == 5)
							{
								uint TimeInSeconds = (rsp_data[currentbyte] + (rsp_data[currentbyte+1] << 8) + (rsp_data[currentbyte+2] << 16) + (rsp_data[currentbyte+3] << 24)) / 100;
								uint fraction = rsp_data[currentbyte+4];

								uint SS = TimeInSeconds % 60;
								uint MM = (TimeInSeconds / 60) % 60;
								uint HH = (TimeInSeconds / 3600);

								dWorkTime = TimeInSeconds + (fraction/100.0);
							}
							currentbyte+=datalength;
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_GETPACE_CMD)
						{
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;
							
							// Pace is in seconds/Km
							uint Pace = rsp_data[currentbyte] + (rsp_data[currentbyte+1] << 8);
							// get pace in seconds / 500m
							double fPace = Pace / 2.0;
							// convert it to mins/500m
							double minutes = Math.Floor(fPace / 60);
							double seconds = fPace - (minutes * 60);													

							currentbyte+=datalength;
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_GETPOWER_CMD)
						{
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;
													
							uint Power = rsp_data[currentbyte] + (rsp_data[currentbyte+1] << 8);
							
							currentbyte+=datalength;
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_GETCADENCE_CMD)
						{
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;

							CurrentSPM = rsp_data[currentbyte];

							if (0 < CurrentSPM)
							{
								nSPM += CurrentSPM;
								nSPMReads++;

								avgSPM = (nSPM * 1.0) / (nSPMReads * 1.0);								
							}
							currentbyte+=datalength;
						}

						if (rsp_data[currentbyte] == (uint)CSAFE.CSAFE_GETHRCUR_CMD)
						{
							currentbyte++;
							datalength = rsp_data[currentbyte];
							currentbyte++;

							CurrentHR = rsp_data[currentbyte];							
							
							if (0 < CurrentHR)
							{								
								nHR += CurrentHR;
								nHRReads++;

								avgHR = (nHR * 1.0) / (nHRReads * 1.0);								
							}
							currentbyte+=datalength;
						}
						
						// END OF REQUESTED DATA 

					} // didn't get the data... (ecode != 0)

					PreviousStrokeState = CurrentStrokeState;
				}
				// Sleep for 50ms as that's the minimum inter-frame gap, so let's be sure
				//Thread.Sleep(50);
			}
		}

		void PM3GetStatusThreadStart()
		{
			PM3GetStatusThread();
		}

		void UIUpdateThread()
		{
			while (!bTerminate)
			{
				if (!bPause && bConnected)
				{
					if (bUpdateUI)
					{
						// update UI
						bUpdateUI = false;
					}
				}
				Thread.Sleep(50);
			}
		}

		void UIUpdateThreadStart()
		{
			UIUpdateThread();
		}

		public Form1()
		{
			InitializeComponent();

			ushort ecode = 0;

			ecode = tkcmdsetDDI_init();

			if (0 == ecode)
			{
				// Init CSAFE protocol
				ecode = tkcmdsetCSAFE_init_protocol(1000);

				if (0 == ecode)
				{
					String sname = "Concept2 Performance Monitor 3 (PM3)";													

					ecode = tkcmdsetDDI_discover_pm3s(sname, 0, ref num_units);

					if (0 == ecode)
					{
						if (num_units > 0)
						{
							bConnected = true;

							labelPM3.BackColor = System.Drawing.Color.Green;

							// start a thread to check the PM3(s)
							Thread thread_PM3GetStatus = new Thread (new ThreadStart(PM3GetStatusThreadStart));
							thread_PM3GetStatus.Start();

							// start a thread to update the display(s)
							Thread thread_UIUpdate = new Thread (new ThreadStart(UIUpdateThreadStart));
							thread_UIUpdate.Start();
						}
						else
						{
							labelPM3.BackColor = System.Drawing.Color.Red;
						}
					}
					else
					{
						labelPM3.BackColor = System.Drawing.Color.Red;
					}
				}
			}		
		}


		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void Form1_Load(object sender, System.EventArgs e)
		{
		
		}

		private void buttonReset_Click(object sender, System.EventArgs e)
		{
			uint [] cmd_data = new uint [64];
			ushort cmd_data_size;
			uint [] rsp_data = new uint [64];
			ushort rsp_data_size = 0;

			Level = 0;
			Stage = 0;
			StageSecondsLeft = 0;
			nFailures = 0;

			bRaceStarted = false;
			bRaceFinished = false;
			bFalseStart = false;

			cmd_data_size = 0;

			// re-set
			cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GOFINISHED_CMD;
			cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GOIDLE_CMD;

			// go, go, go
			cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GOHAVEID_CMD;
			cmd_data[cmd_data_size++] = (uint)CSAFE.CSAFE_GOINUSE_CMD;

			tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, ref rsp_data_size, rsp_data);					
		}

		private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			bPause = true;
			bTerminate = true;		
		}
	}
}
[b]Daren[/b]
37, short, borderline LWT.
[i]Taff Attack Racing[/i]

onyak
Paddler
Posts: 3
Joined: September 19th, 2006, 1:03 pm

Post by onyak » September 19th, 2006, 3:59 pm

Thanks Citroen. But Rowit doesn't come with source. I was hoping to get a copy of the C# code or even VB (can easily convert vb to c#) that everyone has been working on to save some time.

I've started the converstion (but would love some help if anyone can provide source). Once complete... I'll post on these forums and maybe Scott will add it to the SDK as well.

onyak
Paddler
Posts: 3
Joined: September 19th, 2006, 1:03 pm

Post by onyak » September 19th, 2006, 4:01 pm

Daren.... your a LIFE SAVER! THANK YOU!

soares
Paddler
Posts: 17
Joined: April 18th, 2006, 6:30 pm
Location: Portugal

Post by soares » September 19th, 2006, 6:17 pm

Hello, this is a test class that Mike Haboustak sent me when i wasn´t understanding how it works, it´s great to start understanding:

Code: Select all

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

namespace Remo1
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.TextBox textBox1;
		private System.Windows.Forms.TextBox textBox2;
		private System.Windows.Forms.TextBox textBox3;
		private System.Windows.Forms.TextBox textBox4;
		private System.Windows.Forms.TextBox textBox5;
		private System.Windows.Forms.TextBox txtLog;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.Label label4;


		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;
		private System.Windows.Forms.Button button1;
        
		//  DLL Functions
		[DllImport("RPPM3DDI.dll", CallingConvention = CallingConvention.Cdecl)]
		public static extern Int16 tkcmdsetDDI_init();

		[DllImport("RPPM3DDI.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern Int16 tkcmdsetDDI_discover_pm3s(String product_name, UInt16 starting_address, ref UInt16 num_units);

		[DllImport("RPPM3DDI.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern Int16 tkcmdsetDDI_fw_version(UInt16 unit_address, ref string ver_ptr);

		[ DllImport("RPPM3DDI.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern void tkcmdsetDDI_shutdown(UInt16 port);

		[ DllImport("RPPM3Csafe.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern Int16 tkcmdsetCSAFE_init_protocol(UInt16 timeout); 

		[ DllImport("RPPM3Csafe.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern Int16 tkcmdsetCSAFE_command(UInt16 unit_address, 
			UInt16 cmd_data_size, UInt32[] cmd_data, ref UInt16 rsp_data_size,
			UInt32[] rsp_data);


		//  Error Code constants
		protected   const Int16 NO_ERR=0;

		//   Class variables
		protected	Int16	device_error=NO_ERR;
		protected	UInt16	device_count=0;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.textBox1 = new System.Windows.Forms.TextBox();
			this.textBox2 = new System.Windows.Forms.TextBox();
			this.textBox3 = new System.Windows.Forms.TextBox();
			this.label1 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.button1 = new System.Windows.Forms.Button();
			this.textBox4 = new System.Windows.Forms.TextBox();
			this.label4 = new System.Windows.Forms.Label();
			this.textBox5 = new System.Windows.Forms.TextBox();
			this.txtLog = new System.Windows.Forms.TextBox();
			this.SuspendLayout();
			// 
			// textBox1
			// 
			this.textBox1.Location = new System.Drawing.Point(168, 20);
			this.textBox1.Name = "textBox1";
			this.textBox1.Size = new System.Drawing.Size(344, 20);
			this.textBox1.TabIndex = 0;
			this.textBox1.Text = "";
			// 
			// textBox2
			// 
			this.textBox2.Location = new System.Drawing.Point(168, 48);
			this.textBox2.Name = "textBox2";
			this.textBox2.Size = new System.Drawing.Size(344, 20);
			this.textBox2.TabIndex = 1;
			this.textBox2.Text = "";
			// 
			// textBox3
			// 
			this.textBox3.Location = new System.Drawing.Point(168, 179);
			this.textBox3.Name = "textBox3";
			this.textBox3.Size = new System.Drawing.Size(344, 20);
			this.textBox3.TabIndex = 2;
			this.textBox3.Text = "";
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(96, 20);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(64, 14);
			this.label1.TabIndex = 3;
			this.label1.Text = "Numero";
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(96, 48);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(64, 14);
			this.label2.TabIndex = 4;
			this.label2.Text = "FW Version";
			// 
			// label3
			// 
			this.label3.Location = new System.Drawing.Point(96, 179);
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size(64, 14);
			this.label3.TabIndex = 5;
			this.label3.Text = "Comando";
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(224, 128);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(120, 28);
			this.button1.TabIndex = 6;
			this.button1.Text = "teste 2";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// textBox4
			// 
			this.textBox4.Location = new System.Drawing.Point(168, 79);
			this.textBox4.Name = "textBox4";
			this.textBox4.Size = new System.Drawing.Size(175, 20);
			this.textBox4.TabIndex = 7;
			this.textBox4.Text = "";
			// 
			// label4
			// 
			this.label4.Location = new System.Drawing.Point(96, 82);
			this.label4.Name = "label4";
			this.label4.Size = new System.Drawing.Size(44, 18);
			this.label4.TabIndex = 8;
			this.label4.Text = "Erro";
			// 
			// textBox5
			// 
			this.textBox5.Location = new System.Drawing.Point(168, 205);
			this.textBox5.Name = "textBox5";
			this.textBox5.Size = new System.Drawing.Size(175, 20);
			this.textBox5.TabIndex = 9;
			this.textBox5.Text = "";
			// 
			// txtLog
			// 
			this.txtLog.Location = new System.Drawing.Point(168, 232);
			this.txtLog.Multiline = true;
			this.txtLog.Name = "txtLog";
			this.txtLog.Size = new System.Drawing.Size(344, 104);
			this.txtLog.TabIndex = 10;
			this.txtLog.Text = "";
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(632, 342);
			this.Controls.Add(this.txtLog);
			this.Controls.Add(this.textBox5);
			this.Controls.Add(this.textBox4);
			this.Controls.Add(this.textBox3);
			this.Controls.Add(this.textBox2);
			this.Controls.Add(this.textBox1);
			this.Controls.Add(this.label4);
			this.Controls.Add(this.button1);
			this.Controls.Add(this.label3);
			this.Controls.Add(this.label2);
			this.Controls.Add(this.label1);
			this.Name = "Form1";
			this.Load += new System.EventHandler(this.Form1_Load);
			this.Closed += new System.EventHandler(this.Form1_Closed);
			this.ResumeLayout(false);

		}

		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{			
			Application.Run(new Form1());
		}

		

		private void Form1_Load(object sender, System.EventArgs e)
		{			

			//  Initialize the DDI Interface
			device_error = tkcmdsetDDI_init();
			if (device_error == NO_ERR) 
			{
				//  Look for PM3 devices
				device_error = tkcmdsetDDI_discover_pm3s("Concept2 Performance Monitor 3 (PM3)", 0, ref device_count);
				if (device_error == NO_ERR) 
				{
					//  Initialize CSAFE communication
					device_error = tkcmdsetCSAFE_init_protocol(1000);
					if (device_error == NO_ERR) 
					{
						//  Let the user know about success
						txtLog.AppendText("Form1_Load: PM3 Communication Established\r\n");
						txtLog.AppendText("Form1_Load: Found "+device_count.ToString()+" Device(s)\r\n");
					}
					else 
					{
						txtLog.AppendText("Form1_Load: tkcmdsetDDI_discover_pm3s() Failed\r\n");
					}
				}
				else 
				{
					txtLog.AppendText("Form1_Load: tkcmdsetDDI_discover_pm3s() Failed\r\n");
				}
			}
			else { 
				txtLog.AppendText("Form1_Load: tkcmdsetDDI_init() Failed\r\n");
			}
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			Byte status=0x00,hrs=0x00, mins=0x00, secs=0x00;
			UInt16 distance=0x00;

			//  This is the device port (first device is 0 if you start numbering at 0)
			UInt16 device = 0;

			//  Get the Status byte
			device_error = GetDeviceStatus(device, ref status);
			if (device_error!=NO_ERR) 
			{
				txtLog.AppendText("button1_Click: GetDeviceStatus() Failed\r\n");
				return;
			}

			//  Get the time displayed on the monitor
			device_error = GetWorkTime(device, ref hrs, ref mins, ref secs);
			if (device_error!=NO_ERR) 
			{	
				txtLog.AppendText("button1_Click: GetWorkTime() Failed\r\n");
				return;
			}

			//  Get the distance displayed on the monitor
			device_error = GetWorkDistance(device, ref distance);
			if (device_error!=NO_ERR) 
			{	
				txtLog.AppendText("button1_Click: GetDistance() Failed\r\n");
				return;
			}

			//  Send the data values to the log window
			txtLog.AppendText("button1_Click: GetDeviceStatus() = 0x"+status.ToString("X02")+"\r\n");
			txtLog.AppendText("button1_Click: GetWorkTime() = "+hrs.ToString("D02")+":"+mins.ToString("D02")+":"+secs.ToString("D02")+"\r\n");
			txtLog.AppendText("button1_Click: GetWorkDistance() = "+distance.ToString()+"m\r\n");

		}

		protected Int16 GetDeviceStatus(UInt16 port, ref Byte status)
		{
			Int16 err=NO_ERR;

			UInt16 cmd_size=0, rsp_size=64;
			UInt32[] cmd_data = new UInt32[64];
			UInt32[] rsp_data = new UInt32[64];

			//  Send a 0x80 command
			cmd_data[cmd_size++] = 0x80;
			err=tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

			if (err==NO_ERR) 
			{
				//  Status is returned in Byte 0
				status = (Byte)rsp_data[0];
			}

			return (err);
		}

		protected Int16 GetWorkDistance(UInt16 port, ref UInt16 distance)
		{
			Int16 err=NO_ERR;

			UInt16 cmd_size=0, rsp_size=64;
			UInt32[] cmd_data = new UInt32[64];
			UInt32[] rsp_data = new UInt32[64];

			//  Send a 0xA1 (CSAFE_GETHORIZONTAL_CMD) command
			cmd_data[cmd_size++] = 0xA1;
			err=tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

			if (err==NO_ERR) 
			{
				//  First two bytes (0&1) are CommandId and number of data bytes
				//  Next 2 bytes (2/3) are distance
				distance = (UInt16)((rsp_data[3]<<8) | (rsp_data[2]));
			}

			return (err);
		}

		protected Int16 GetWorkTime(UInt16 port, ref Byte hours, ref Byte minutes, ref Byte seconds)
		{
			Int16 err=NO_ERR;

			UInt16 cmd_size=0, rsp_size=64;
			UInt32[] cmd_data = new UInt32[64];
			UInt32[] rsp_data = new UInt32[64];

			//  Send a 0xA1 (CSAFE_GETTWORK_CMD) command
			cmd_data[cmd_size++] = 0xA0;
			err=tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

			if (err==NO_ERR) 
			{
				//  First two bytes (0&1) are CommandId and number of data bytes
				//  Next 3 bytes (2/3/4) are hours, mins, seconds
				hours	= (Byte)rsp_data[2];
				minutes	= (Byte)rsp_data[3];
				seconds	= (Byte)rsp_data[4];
			}

			return (err);
		}

		private void Form1_Closed(object sender, System.EventArgs e)
		{
			UInt16 port;

			//  Shutdown the DDI layer
			for (port=0; port<device_count; port++) 
			{
				tkcmdsetDDI_shutdown(port);
			}
		}
	}
}
Just create a class with this code and save it. Then test it.

With this code i started to understand a bit how it works.

But i thinks Daren's code is excelent and has more for you to work with.

I could send you my project but it requires a fingerprint reader and uses SQL Database, and it´s all in portuguese.

The trick here is to understand how the CSAFE frame works, once you understand the csafe frame, you will understand the Concept2 PM3 Communication Interface Definition 010.pdf a lot better, because you will know witch bytes of the frame you need and how they can help you.

An example is that when i installed a new firmware on the PM3, the GetStatus command stopped working (always returned 0x00), but you can get the status everytime the PM3 sends you a response to a command by getting the first byte of the frame.

Rui
Last edited by soares on September 19th, 2006, 7:11 pm, edited 1 time in total.

soares
Paddler
Posts: 17
Joined: April 18th, 2006, 6:30 pm
Location: Portugal

Post by soares » September 19th, 2006, 7:00 pm

Here is some code from my project. All in the same class:

Code: Select all

//  Funções DLL 
        [DllImport("RPPM3DDI.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int16 tkcmdsetDDI_init();

        [DllImport("RPPM3DDI.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int16 tkcmdsetDDI_discover_pm3s(String product_name, UInt16 starting_address, ref UInt16 num_units);

        [DllImport("RPPM3DDI.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int16 tkcmdsetDDI_fw_version(UInt16 unit_address, ref string ver_ptr);

        [DllImport("RPPM3DDI.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void tkcmdsetDDI_shutdown(UInt16 port);

        [DllImport("RPPM3Csafe.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int16 tkcmdsetCSAFE_init_protocol(UInt16 timeout);

        [DllImport("RPPM3Csafe.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int16 tkcmdsetCSAFE_command(UInt16 unit_address,
            UInt16 cmd_data_size, UInt32[] cmd_data, ref UInt16 rsp_data_size,
            UInt32[] rsp_data);



        //  Constantes de codigo de erro
        protected const Int16 NO_ERR = 0;

 // This delegate enables asynchronous calls for setting
        // the text property on a TextBox control.
        delegate void SetTextCallback(string text);
        
        // This BackgroundWorker is used because is the 
        // preferred way of performing asynchronous operations.
        private BackgroundWorker backgroundWorker1 = new BackgroundWorker();

Code: Select all

//Aqui ele vai iniciar o contacto com o PM3
        //Begin training
        private void Treino_Load()
        {

            //  Inicializar a DDI Interface
            // Initialize DDI Interface
            device_error = tkcmdsetDDI_init();
            if (device_error == NO_ERR)
            {
                //  Procurar PM3
                // Discover PM3
                device_error = tkcmdsetDDI_discover_pm3s("Concept2 Performance Monitor 3 (PM3)", 0, ref device_count);
                if (device_error == NO_ERR)
                {
                    //  Inicializar a comunicação CSAFE
                    // Initialize CSAFE protocol
                    device_error = tkcmdsetCSAFE_init_protocol(1000);
                    if (device_error == NO_ERR)
                    {
                        //  Mostrar o estado da conexão e quantas maquinas detectou
                        // Show the state of the conection and how many PM3 it has found
                        Console.WriteLine("Form1_Load: PM3 Communication Established\r\n");
                        Console.WriteLine("Form1_Load: Found " + device_count.ToString() + " Device(s)\r\n");


                        this.iniciaTreino();


                        // This event handler starts the form's 
                        // BackgroundWorker by calling RunWorkerAsync.
                        //
                        // The Text property of the TextBox control is set
                        // when the BackgroundWorker raises the RunWorkerCompleted
                        // event.
                        this.backgroundWorker1.RunWorkerAsync();

                        //inicia um novo thread com o método getAcabaTreino
                        // starts a new thread with the method getAcabaTreino -> in English - getEndsTraining
                        newthread = new Thread(new ThreadStart(this.getAcabaTreino));

                        newthread.Start();
                        newthread.Priority = ThreadPriority.Highest;                        
                        

                    }
                    else
                    {
                        Console.WriteLine("Form1_Load: tkcmdsetDDI_discover_pm3s() Failed\r\n");
                        MessageBox.Show("Erro ao iniciar protocolo de comunicação.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        this.Close();
                    }
                }
                else
                {
                    Console.WriteLine("Form1_Load: tkcmdsetDDI_discover_pm3s() Failed\r\n");
                    MessageBox.Show("Não foram encontrados dispositivos Concept2 com PM3.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    this.Close();
                }
            }
            else
            {
                Console.WriteLine("Form1_Load: tkcmdsetDDI_init() Failed\r\n");
                MessageBox.Show("Erro ao iniciar a interface de comunicação.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Information);
                this.Close();
            }       
           
        }

Code: Select all

//Aqui ele envia as configurações necessárias do treino para o PM3
        //O PM3 fica preparado para treinar
//Here it sends the requiered configurations to the PM3
        public void iniciaTreino()
        {

            Int16 status = 0x00;            

            //  This is the device port (first device is 0 if you start numbering at 0)
            UInt16 device = 0;           

            //  Returns o Status byte
            device_error = GetDeviceStatus(device, ref status);
            if (device_error != NO_ERR)
            {
                Console.WriteLine("button1_Click: GetDeviceStatus() Failed\r\n");
                MessageBox.Show("Erro ao enviar comando GetDeviceStatus.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            Console.WriteLine("button1_Click: GetDeviceStatus() = 0x" + status.ToString("X02") + "\r\n");



            //  goReady
            device_error = goReady(device);
            if (device_error != NO_ERR)
            {
                Console.WriteLine("button1_Click: goReady() Failed\r\n");
                MessageBox.Show("Erro ao envia comando GoReady.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            Console.WriteLine("button1_Click: goReady() = OK m\r\n");
            Console.WriteLine("button1_Click: GetDeviceStatus() = 0x" + status.ToString("X02") + "\r\n");


            if (this.distancia != 0)
            {

                //  Set Distance
                device_error = setDistance(device, this.cmd_distance_lsb, this.cmd_distance_msb);
                if (device_error != NO_ERR)
                {
                    Console.WriteLine("button1_Click: SetDistance() Failed\r\n");
                    MessageBox.Show("Erro ao enviar comando SetDistance", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                Console.WriteLine("button1_Click: setDistance() = " + this.distancia.ToString() + "m\r\n");
            }
            else
            {

                // Set Work Time                
               device_error = setWorkTime(device, this.cmd_h, this.cmd_m, this.cmd_s);
               if (device_error != NO_ERR)
               {
                   Console.WriteLine("button1_Click: SetDistance() Failed\r\n");
                   return;
               }
               Console.WriteLine("button1_Click: setWorkTime() = " + this.cmd_h + ":" + this.cmd_m + ":" + this.cmd_s + "m\r\n");

            }
                       
            
            //  Set Program
            device_error = setProgram(device);
            if (device_error != NO_ERR)
            {
                Console.WriteLine("button1_Click: SetProgram() Failed\r\n");
                return;
            }

            device_error = goInUse(device);
            if (device_error != NO_ERR)
            {
                Console.WriteLine("button1_Click: goInUse() Failed\r\n");
                return;
            }
            Console.WriteLine("button1_Click: goInUse() = OK m\r\n");

        }

Code: Select all

//Este método é lançado numa nova thread pois vai estar a pedir informação
        //ao PM3 a cada segundo para mostrar no ecrã o estado do treino e para 
        //verificar quando o utilizador termina o treino
//This method is started in a new thread because it will be retrieving data from the PM3 every second to show on the monitor the time and distance in real time.
//It also verifies when the training is complete, not by knowing the status has it should, but by comparing the current training values with the training objective (time or distance). And saves all in a database for the user to consult later.
        public void getAcabaTreino()
        {
            Byte status = 0x00, hrs = 0x00, mins = 0x00, secs = 0x00;
            UInt16 distance = 0x00;              


            if (this.time == true)
            {
                int dsb = 0;                
               
                while(dsb == 0)
                {

                    Console.WriteLine("*** Hora ***");
                    Thread.Sleep(1000);
                    Thread.BeginThreadAffinity();

                    //  Get the time displayed on the monitor
                    device_error = GetWorkTime(device, ref hrs, ref mins, ref secs);
                    if (device_error != NO_ERR)
                    {
                        Console.WriteLine("button1_Click: GetWorkTime() Failed\r\n");
                        return;
                    }
                    Console.WriteLine("button1_Click: GetWorkTime() = " + hrs.ToString("D02") + ":" + mins.ToString("D02") + ":" + secs.ToString("D02") + "\r\n");
                    this.h = hrs.ToString("D02");
                    this.m = mins.ToString("D02");
                    this.s = secs.ToString("D02");
                    this.hf = hrs;
                    this.mf = mins;
                    this.sf = secs;

                    this.SetTextT(hrs.ToString("D02") + ":" + mins.ToString("D02")
                        + ":" + secs.ToString("D02"));                   


                    //  Get the distance displayed on the monitor
                    device_error = GetWorkDistance(device, ref distance);
                    if (device_error != NO_ERR)
                    {
                        Console.WriteLine("button1_Click: GetDistance() Failed\r\n");
                        return;
                    }
                    Console.WriteLine("button1_Click: GetWorkDistance() = " + distance.ToString() + "m\r\n");
                    this.d = distance.ToString();
                    this.df = distance;

                    this.SetTextD(this.d + " m");
                    

                    if ((this.hf.ToString() == this.hora.ToString()) && (this.mf.ToString() == this.minuto.ToString()) && (this.sf.ToString() == this.segundo.ToString()))
                    {
                        goto Next;
                    }

                }

                MessageBox.Show("Ocorreu durante o treino. \nTem de reiniciar o treino.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                goto Seguinte;

            }
            else if (this.time == false)
            {
                int dsa = 0;
                
                while(dsa == 0)
                {
                    Console.WriteLine("*** Distancia ***");
                    Thread.Sleep(1000);
                    
                    // Retorna o tempo mostrado no PM3 
//returns the time on the PM3
                    device_error = GetWorkTime(device, ref hrs, ref mins, ref secs);
                    if (device_error != NO_ERR)
                    {
                        Console.WriteLine("button1_Click: GetWorkTime() Failed\r\n");
                        return;
                    }
                    Console.WriteLine("button1_Click: GetWorkTime() = " + hrs.ToString("D02") + ":" + mins.ToString("D02") + ":" + secs.ToString("D02") + "\r\n");
                    this.h = hrs.ToString("D02");
                    this.m = mins.ToString("D02");
                    this.s = secs.ToString("D02");
                    this.hf = hrs;
                    this.mf = mins;
                    this.sf = secs;

                    this.SetTextT(hrs.ToString("D02") + ":" + mins.ToString("D02")
                        + ":" + secs.ToString("D02"));
                    
                                        
                    // Retorna a distancia mostrada no PM3
//returns the distance on the PM3
                    device_error = GetWorkDistance(device, ref distance);
                    if (device_error != NO_ERR)
                    {
                        Console.WriteLine("button1_Click: GetDistance() Failed\r\n");
                        return;
                    }
                    Console.WriteLine("button1_Click: GetWorkDistance() = " + distance.ToString() + "m\r\n");
                    this.d = distance.ToString();
                    this.df = distance;
                                        
                    this.SetTextD(this.d + " m");                   

                    if (this.d == this.d2.ToString())
                    {
                        goto Next;
                    }
                       

                }
           
                MessageBox.Show("Ocorreu durante o treino. \nTem de reiniciar o treino.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                goto Seguinte;
            }

        Next: //training ends

            Console.WriteLine("Terminou");

            this.SetTextTermin("Treino Terminado");
            this.SetTextTDFinal("Fez " + this.d.ToString() + " m em " + this.h + ":" + this.m + ":" + this.s);

            //Vai guardar os dados do treino no historial e alterar o Efectuado para True
            try
            {
                his = new RemoBDDataSet.HistorialDataTable();
                this.historialTableAdapter1.Fill(his);

                this.historialTableAdapter1.Insert(this.posTM, System.DateTime.Today
                    , this.hf, this.mf, this.sf, this.df, this.userID);

                for (int g = 0; g < this.tm.Rows.Count; g++)
                {
                    if (this.tm[g].ID_Treino_Marcado == this.posTM)
                    {                        
                        tm[g].Efectuado = true;
                        
                        this.treinos_MarcadosTableAdapter1.Update(this.tm[g]);

                        goto Seguinte;
                    }
                }

            }
            catch (Exception erro)
            {
                MessageBox.Show("Erro -> "+erro, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            Seguinte:            
             
              Console.WriteLine("Seguinte:");            

        }

Code: Select all

 //pede ao PM3 a distância em que vai o treino
// GetDistance
        protected Int16 GetWorkDistance(UInt16 port, ref UInt16 distance)
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0xA1 (CSAFE_GETHORIZONTAL_CMD) command
            cmd_data[cmd_size++] = 0xA1;
            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

            if (err == NO_ERR)
            {
                //  First two bytes (0&1) are CommandId and number of data bytes
                //  Next 2 bytes (2/3) are distance
                distance = (UInt16)((rsp_data[3] << 8) | (rsp_data[2]));
            }

            return (err);
        }

Code: Select all

//pede ao PM3 o tempo em que vai o treino
// GetTime
        protected Int16 GetWorkTime(UInt16 port, ref Byte hours, ref Byte minutes, ref Byte seconds)
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0xA1 (CSAFE_GETTWORK_CMD) command
            cmd_data[cmd_size++] = 0xA0;
            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

            if (err == NO_ERR)
            {
                //  First two bytes (0&1) are CommandId and number of data bytes
                //  Next 3 bytes (2/3/4) are hours, mins, seconds
                hours = (Byte)rsp_data[2];
                minutes = (Byte)rsp_data[3];
                seconds = (Byte)rsp_data[4];
            }

            return (err);
        }

Code: Select all

//Configura o PM3 para determinada distancia
//SetDistance
        protected Int16 setDistance(UInt16 port, UInt32 dist_lsb, UInt32 dist_msb)
        {
            Int16 err = NO_ERR;
         
            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0x21 (CSAFE_SETHORIZONTAL_CMD) command
            cmd_data[cmd_size++] = 0x21;
            cmd_data[cmd_size++] = 0x03;
            cmd_data[cmd_size++] = dist_lsb;   //0x90     \ 400 meters
            cmd_data[cmd_size++] = dist_msb;   //0x01     /
            cmd_data[cmd_size++] = 0x24;   //0x21 Kilometers | 0x24 Meters         

            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

            return (err);

        }

Code: Select all

//Configura o PM3 para determinado tempo de treino
//SetWorkTime
        protected Int16 setWorkTime(UInt16 port, UInt32 hours, UInt32 minutes, UInt32 seconds)
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0x20 (CSAFE_SETTWORK_CMD) command
            cmd_data[cmd_size++] = 0x20;
            cmd_data[cmd_size++] = 0x03;
            cmd_data[cmd_size++] = hours;
            cmd_data[cmd_size++] = minutes;
            cmd_data[cmd_size++] = seconds;
            cmd_data[cmd_size++] = 0x3A;


            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

            return (err);

        }
Rui

soares
Paddler
Posts: 17
Joined: April 18th, 2006, 6:30 pm
Location: Portugal

Post by soares » September 19th, 2006, 7:05 pm

Code: Select all

 //Serve para escolher o programa de treino, Pré-programado ou não
//This is to choose from a pre-programmed training or to configure a new one
//It´s set to be configured a new one 
        protected Int16 setProgram(UInt16 port)
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //Send a 0x24 (CSAFE_SETPROGRAM_CMD) command
            cmd_data[cmd_size++] = 0x24;
            cmd_data[cmd_size++] = 0x02;
            cmd_data[cmd_size++] = 0x00;
            cmd_data[cmd_size++] = 0x00;

            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

            return (err);

        }

Code: Select all

//diz ao PM3 para ir para o status Ready
//Set status GoReady
        protected Int16 goReady(UInt16 port) 
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0x87 (CSAFE_GOREADY_CMD) command
            cmd_data[cmd_size++] = 0x87;


            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);
                    

            return (err);

        }

Code: Select all

    //diz ao PM3 para ir para o status InUse
//set status GoInUse
        protected Int16 goInUse(UInt16 port) 
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0x85 (CSAFE_GOINUSE_CMD) command
            cmd_data[cmd_size++] = 0x85;

            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);
                       

            return (err);

        }

Code: Select all

 //diz ao PM3 para ir para o status Idle
//set status GoIdle
        protected Int16 goIdle(UInt16 port) 
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0x86 (CSAFE_GOIDLE_CMD) command
            cmd_data[cmd_size++] = 0x82;

            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);


            return (err);

        }

Code: Select all

   //diz ao PM3 para ir para o status HaveId
//set status GoHaveId
        protected Int16 goHaveId(UInt16 port) 
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0x86 (CSAFE_GOHAVEID_CMD) command
            cmd_data[cmd_size++] = 0x83;

            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);


            return (err);

        }

Code: Select all

//diz ao PM3 para ir para o status Finished
//set status GoFinished
        protected Int16 goFinished(UInt16 port) 
        {
            Int16 err = NO_ERR;

            UInt16 cmd_size = 0, rsp_size = 64;
            UInt32[] cmd_data = new UInt32[64];
            UInt32[] rsp_data = new UInt32[64];

            //  Send a 0x86 (CSAFE_GOFINISHED_CMD) command
            cmd_data[cmd_size++] = 0x86;

            err = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, ref rsp_size, rsp_data);

           
            return (err);

        }

Code: Select all

 //transforma a distancia para o formato certo para o comando a enviar 
        //para o PM3
//Transforms a distance value to a a way that the PM3 undestands, (Low significant byte and Most sifnificant byte)
        public void tranformaDistHexa(int dist)
        {
            string dt = "";
            dt = dist.ToString();
          

            UInt32 numDist = UInt32.Parse(dt);           

            //  split up for the CSAFE frame 
            //  CSAFE_SETHORIZONTAL_CMD needs two bytes LSB and MSB 
            this.cmd_distance_lsb = (numDist & 0xFF); // LSB: 0xD0 
            this.cmd_distance_msb = ((numDist >> 8) & 0xFF); // MSB: 0x07            
            
        }

soares
Paddler
Posts: 17
Joined: April 18th, 2006, 6:30 pm
Location: Portugal

Post by soares » September 19th, 2006, 7:13 pm

If it wasn´t for Mike Haboustak i wouln´t be able to do my project.
Thanks again for all your help Mike.
I also thanked you in my project paper.

Rui

Post Reply