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

Post questions and issues with Concept2 PM3 SDK
soares
Paddler
Posts: 17
Joined: April 18th, 2006, 6:30 pm
Location: Portugal

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

Post by soares » July 12th, 2006, 8:35 pm

Hi, i'm making a program in .NET C# and i have the folowing code:

Code: Select all

public class Ligacao
	{
		public Int16 num_units = 0;
		public string ver_ptr;
        public ushort ecode = 0;
        public ushort ecode0 = 0;
        
        public ushort ecode3 = 10;  
        public ushort rsp_size = new ushort();
        public ulong[] rsp_data = new ulong[3];

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

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

		[ DllImport("RPPM3DDI.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern ushort tkcmdsetDDI_fw_version(ushort unit_address, ref string ver_ptr);
		
		[ DllImport("RPPM3Csafe.dll", CallingConvention=CallingConvention.Cdecl) ]
		public static extern ushort tkcmdsetCSAFE_command(ushort unit_address, ushort cmd_data_size, ulong[] cmd_data, ushort rsp_data_size, ulong[] rsp_data);
	
		public Ligacao()
		{
			//
			// TODO: Add constructor logic here
			//
		}


		
		public short teste()
		{

            tkcmdsetDDI_init();
			
			this.ecode = tkcmdsetDDI_discover_pm3s("Concept2 Performance Monitor 3 (PM3)", 0, ref num_units);
			
					
			return num_units;

		}


		public string fw()
		{
			ushort ecode1 = 111;			
			
				ecode1 = tkcmdsetDDI_fw_version(0, ref ver_ptr);
                
				if (ecode1 == 0)
				{
					return ver_ptr;
				}
				else
					return ecode1.ToString();			

		}		

	}
This is the Class where i do the pm3 discover fine with no errors.

But when i try sending a comand to the pm3 (any comand), instead of returnig 0 wich means there was no error, it returns the error 55382.
This happens always and i cant find the problem.

This is the class where i send the comand:

Code: Select all

  public class Ligacao2
	{			
		ushort ecode2 = 0;
		Int16 num_units = 12;

		public Ligacao2()
		{
			//
			// TODO: Add constructor logic here
			//
		}		

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



		public ulong teste()
		{				
					ushort rsp_size = new ushort();
					ulong[] rsp_data = new ulong[1];
					ulong[] cmd_data = {0x80};

					ushort ecode3 = tkcmdsetCSAFE_command(0, 1, cmd_data, rsp_size, rsp_data);

					if (ecode3 == 0)
					{
						return rsp_data[0];
					}
					else
						return ecode3;


}  
Can someone help me with this??
I´m probabily sending the comand the wrong way but i really dont know.

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Post by haboustak » July 13th, 2006, 10:40 am

It looks like your missing the call to init the CSAFE protocol. I believe the process for sending commands to the PM3 is:

Code: Select all

   1: Init DDI
   2: Discover Devices
   3: Init CSafe
   4: Send Commands
I think there's also a DDI shutdown command that needs to be called per-port as step 5.

You seem to be mixing the C# integer types with reckless abandon! :lol:
ushort/UInt16, ulong/UInt32, short/Int16, etc are all aliases for the same thing. Once you pick which one you like you can stick with it everywhere.

That being said, C2 SDK error codes are signed shorts (Int16) and you're assigning it to an unsigned short value. Doing a little 2s-complement to your value of 55382 yields -10154. Peeking inside of RPecodesPM3DDI.ini seems to coincide with the Csafe Init problem.

Code: Select all

[-10154]
Name=TKDDI_PROTOCOL_NOT_DEFINED_ERR
Text=Protocol not initialized.
In reviewing your code, I'm reminded by how annoying it is to use a UInt32 for CSafe commands and responses when we could be using UInt8 and consuming 25% of the space.

Let me know if that helps,
Mike

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

Post by soares » July 14th, 2006, 6:49 pm

Thanks a lot haboustak :D
i think that my problem was the init CSAFE protocol being missing.

about mixing the integer values, lol, i knew that but this is only a test program so that i learn how to comunicate with the pm3 so i was being reckless with the naming and some other stuff. In test programs i normally dont pay much attention to details. :? i´m a noob.

I changed the the SDK errors to Int16, i dont kow why i put it in Unsigned :?:

I still couldnt make a successefull command because i´m having an error somewhere in the command line.

Code: Select all

tkcmdsetCSAFE_init_protocol(1000);

					UInt16 rsp_size = new UInt16();
                    UInt32[] rsp_data = new UInt32[1];
					UInt32[] cmd_data = {0x80};
                    UInt16 cmd_data_size = 1;
					ecode3 = tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, rsp_size, rsp_data);

                   
                    tkcmdsetDDI_shutdown(0);

                    return rsp_data[0];             
It´s giving me a NullPointerException: not set to an instance of an object.
Debugging it, the only object with null reference is the cmd_data but i still dont know why.
I´ve tried different ways and could get it not to be with null reference but error was the same and in the same line

Code: Select all

ecode3 = tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, rsp_size, rsp_data);

This project is for my school, the thing is that i cant spend enough time with the Concept 2 rowing machine, so, this is going to take a while :cry:

Any hints on this would be apreciated.

Thanks

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Post by haboustak » July 14th, 2006, 9:59 pm

I think the problem might be with your import of the DLL function. I don't write much C#, and when I do I don't use much unmanaged code. I think that you need some 'ref' or 'in/out' input type declarations for the parameters in the Csafe_command() function.

Anything marked with a * in the C header file will need a 'ref' declaration. C arrays will probably need an '[in, out]' or maybe a 'ref'. Good news is, once you have it all set up it will work forever.

I might try this:

Code: Select all

[ DllImport("RPPM3Csafe.dll", CallingConvention=CallingConvention.Cdecl) ] 
      public static extern ushort tkcmdsetCSAFE_command(ushort unit_address, ushort cmd_data_size, [in, out] ulong[] cmd_data, [ref] ushort rsp_data_size, [in, out] ulong[] rsp_data);
The other thing to try is allocating more memory than the bare minimum. I think your length 1 arrays should work, but if all else fails it doesn't hurt to test it out with about 100 bytes of space.

Code: Select all

               UInt16 rsp_size=100, cmd_size=0; 
               UInt32[] rsp_data[100], cmd_data[100]; 
               cmd_data[cmd_size++] = 0x80;

               ecode3 = tkcmdsetCSAFE_command(0, cmd_size, cmd_data, rsp_size, rsp_data);
I changed the way you wrote the initalizers, but for no other reason than it's my personal style. What you had before should work just fine.

It's too bad you don't have more access to the rower. It's a lot of fun writing code once you get started. But at least you have a lot of time to think up good ideas between sessions.

Mike

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

Post by soares » July 25th, 2006, 3:10 pm

Well the error is gone, it seems it was because i was missing the ref parameter int the rsp_data_size. I dont know why i keep letting errors like this appear, this is just lack of attention.

The status command was executed with no problem, though the result was 128 and i dont know what that means yet.

The thing is that any other command i try to execute returns the error -10107, wich is:

Code: Select all

[-10107]
Name=TKUSB_READ_TIMEOUT_ERR
Text=The USB read operation did not complete within the timeout period
I tried with some commands, like the CSAFE_GETTWORK_CMD

Code: Select all

UInt16 rsp_size = new UInt16();
UInt32[] rsp_data = new UInt32[10];
UInt32[] cmd_data = {0xA1};
UInt16 cmd_data_size = 1;
ecode3 = tkcmdsetCSAFE_command(0, cmd_data_size, cmd_data, ref rsp_size, rsp_data);
I really dont know why the USB timeout error.

I think it might be because of the command:

Code: Select all

Int16 ecode1 = tkcmdsetCSAFE_init_protocol(1000);
which has timeout = 1000 ms = 1 second, but i´m lost, i cant find anything on the documentation refering to this.

This is really dificult to comunicate with the PM3.

Thanks for all the help Mike, i´m lost without your help.

Rui

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Post by haboustak » July 25th, 2006, 4:07 pm

A status of 128 or 0x80 hex is the correct value for a PM3 in the 'Ready' state. You can get a description of the fields of the Status byte at the CSAFE homepage: http://www.fitlinxx.com/CSAFE/Framework.htm (Section 2.5) You should also see the status toggle between 0x80 and 0x81 as the PM3 sends frames.

Glancing at your code it looks to me like you've neglected to set the value of rsp_size. It should be 10 as it's an input to the command.

Code: Select all

UInt16 rsp_size = 10;
If the PM3 is timing out, it probably means you're not sending it proper information. Sounds like for the most part you have it working.

Mike

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

Post by soares » July 27th, 2006, 9:40 am

Hey Mike, do you have a Concept2 at hand? Could You test my program to see what is wrong?

I sent a mail to Concept2 to see if they can help me, i´m waiting their answer.

By the way, i read the framework of the CSAFE protocol, and i kow the status command i wanted is the State of Slave of the Status byte, wich is the first 3 bits of the frame. What i still couldnt figure is how to associate the value 128 to the Ready state.

I dont have much practice with this kind of things. :(

Thanks for everything.

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Post by haboustak » July 27th, 2006, 10:29 am

Sure, I'll check it out. You can email it to the address in my profile.

Mike

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

Post by soares » July 27th, 2006, 11:57 am

I´ve sent you may program.

One you start, it does the discovery, then when you click onthe Teste2 button it will try to send a command to the PM3 and display the response or the error.

Thanks a lot

Rui

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

Post by soares » July 28th, 2006, 6:08 am

Hey Mike, thanks a lot for the program you sent me, i´ve learned a lot with it.
The thing is that your program returns the same error that mine (-10107).

I added your class to the solution and deleted my classes and left only yours like you said.

The device discovery is working ok, but the GetHorizontal and the GetWork are returning the same error (-10107).

This is weird.

Does your program works without errors in your computer?

:?: :?: :?: :cry:

Thanks again

Rui

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Post by haboustak » July 28th, 2006, 10:26 am

Rui,

The program works here, this is what I see:
Image


Have you checked your monitor's firmware? You need at least version 88 in order to communicate using CSAFE. From the main menu: More Options > Utilities > Product ID > PM3 Firmware Version.

Mike

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

Post by soares » July 28th, 2006, 12:05 pm

I figured the program worked there, it´s very well done, i´ll check the firmware on monday.

Thanks.

Rui

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

Post by soares » July 31st, 2006, 1:35 pm

Hey Mike, the problem was the firmware, it had the vers. 61 and now has the latest ant it works fine.

I just dont understand why the status command always returns 0x00.

Again thanks a lot for the help.

Rui

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

Post by onyak » September 19th, 2006, 1:08 pm

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.

User avatar
Citroen
SpamTeam
Posts: 8011
Joined: March 16th, 2006, 3:28 pm
Location: A small cave in deepest darkest Basingstoke, UK

Post by Citroen » September 19th, 2006, 1:56 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.
Chris,

You may be interested in this: http://homepages.isunet.net/smichael/rowit/ it was the winner of a Concept2 software design competition.

There's also: http://sourceforge.net/projects/pm2erglib/ but it's probably past it's sell-by/use-by date by now (since next to no one has a PM2+ on a model C).

And, of course, http://www.fitlinxx.com/CSAFE/

Post Reply