Communicating with PM5 via VB

Post questions and issues with Concept2 PM3 SDK
dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » November 27th, 2014, 6:30 pm

Phil_M wrote:I am sorry that I haven't figured it out yet.
No worries.
Phil_M wrote:I copied your Chrome.hid example, and I got no errors but also got no results.
Did you try clicking the extension's launch link? That wasn't necessary in Chrome 38 but it might be in Chrome 39. At that point something should be logged. Either a command and response or a "No performance monitors found." message.
Phil_M wrote:Could it be anything to do with the VendorID that you reference? 6052? Citron mentioned earlier in this topic that the Vendor ID and Product ID would be different on a PM5.
The vendor ID should still be 6052. I don't have a PM5 to confirm but the PM3's product ID is 1 and the PM4's is 2 so I figured the PM5's would be 3 so the chrome.hid example supports vendor ID/product ID 6052/1, 6052/2, and 6052/3. The PyUSB example supports 6052/anything.

Can you check the PM5's vendor ID/product ID? If you don't know how off the top of your head try googling something like "Windows (Windows Version) USB Vendor ID".
Phil_M wrote:Going back to Pyusb, and the python route you were helping me with. I have definitely installed Pyusb.1.0.0a2, and done the "Python setup.py install" step (which worked after a massive amount of faffing about). I haven't tried version b2, which you suggested overnight, but I will try that tomorrow/the weekend as I have run out of time tonight. I am pretty sure that version a2 had worked though, as once I had managed to install it, it eliminated a number of errors from the PyRow application (or at least allowed it to compile).
1.0.0a2 should work. I didn't realize I linked to two different versions. :S

The error you posted earlier ("No module named 'usb'") means that Python is unable to find PyUSB so it doesn't sound like PyUSB is installed properly. Are you still getting that error? Did you install libusb or libusb-win32 before installing PyUSB?
Phil_M wrote:For some reason I decided to go back a stage to look at the Software Development Kit with all the dll's and the demo program, and realized I may have missed a crucial first step. When I downloaded Libusb, it instructed me to save the dll's down in my System32 folder. This is something I hadn't done with the SDK Dll's, so I tried to do that, and then tried to register them using "regsvr32 xxxxxx.dll" (which I found through some more googling) but this came up with the error "the dll is read but the DLLRegistryServer entry point is not found". Could my lack of registered Dll's be the root of all these problems?
Unfortunately I'm not that familiar with Windows. :(

Phil_M
Paddler
Posts: 30
Joined: November 23rd, 2014, 10:10 am

Re: Communicating with PM5 via VB

Post by Phil_M » November 27th, 2014, 6:58 pm

Thanks for the quick response dsissitka.

Yes I tried clicking launch and pretty much all the other buttons/links I could see. I'll try again tomorrow, and will have a try at writing the example chrome extension in the link you provided, to see whether I can get that one to work as this may narrow down where the problem lies.

Your thoughts on Vendor IDs seems reasonable, but I will try and find the vendor ID via the googling method you suggested. First search hit led me somewhere, but it is too close to bed time for me to go down another rabbit hole tonight.
EDIT: I changed my mind, coz I really want to sort this out.....PM5 is exactly as you surmised: VendorID: 6052, ProductID: 3. Slowly ticking off the options as to what is causing the problem.

I installed Libusb-win32 (or at least think I did). I will retrace my steps on this tomorrow with LibUsb-Win32, then PyUSB and see if that solves the error.

No worries, you have been more than helpful already. I will do some reading up on Dlls and see where that gets me.

dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » November 27th, 2014, 7:20 pm

What happens when you click launch? If it doesn't work you should see an error where the command and response are in my screenshot. Something like "chrome.hid.(function) Error: (Error)" in red. For example, this is what I get when my PM3 is unplugged:

http://i.imgur.com/hOrYai9.png

dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » November 27th, 2014, 10:07 pm

Note that I've checked "Collect Errors". I can't remember if that's the default.

Phil_M
Paddler
Posts: 30
Joined: November 23rd, 2014, 10:10 am

Re: Communicating with PM5 via VB

Post by Phil_M » November 29th, 2014, 8:03 am

This is a lot like hard work =(,

I am going to park the Chrome Extension option because it is going nowhere fast. In my version I dont have a "Collect Errors" checkbox, even after ticking the developer mode button. After some googling this may or may not be to do with the fact that extensions in windows are blocked for the purposes of avoiding viruses, unless they are posted on the official extension shopfront. I tried the simple "one-click-kittens" example extension that you linked earlier, and its so simple, even I cant have messed it up, but it still doesnt work properly. It creates a button in Chrome, but there are no pictures of kittens, which is a shame coz that would have cheered me up. Either way, I am just ending up down another rabbit hole, so I am going to leave chrome for now.

The answer I want is the Python method you proposed, so I am going to go back to square one and start again to try and get either your example code working by reinstalling PyUSB, or get the PyRow code working which also needs PyUsb. Once I can get that working I think I will be away. One of the PyRow example files is half way to what I wanted to achieve anyway, which is logging rows by stroke in text files. Once I get to that stage, I will just need to work on a way to compare the live row with the row from a text file to give me my "Ghost" race.

Thank you for all your help so far dsissitka. I will report back once I have had a go at uninstalling then reinstalling everything again in the right order.

Can you confirm which version out of Python 2.x and Python 3.x you are using? As in another thread (possibly the one about PyRow), Citreon said it made a difference. Currently I have both installed, but I am at a loss to work out which is compiling my code.

dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » November 29th, 2014, 8:39 am

Phil_M wrote:I am going to park the Chrome Extension option because it is going nowhere fast.
I just upgraded to Chrome 39. On Chrome 39 you have to click the extension's background page link to see the output:

https://imgur.com/YiWOQ74


Phil_M wrote:The answer I want is the Python method you proposed, so I am going to go back to square one and start again to try and get either your example code working by reinstalling PyUSB, or get the PyRow code working which also needs PyUsb.
Start with mine. The PyRow examples need to be modified to work with current versions of Python.
Phil_M wrote:Can you confirm which version out of Python 2.x and Python 3.x you are using?
I'm using Python 2.7.6.

Phil_M
Paddler
Posts: 30
Joined: November 23rd, 2014, 10:10 am

Re: Communicating with PM5 via VB

Post by Phil_M » December 2nd, 2014, 6:52 am

Hi Dsissitka,

I haven't replied for a couple of days because I have been trying a new tactic, but first in response to the below. Thank you for the image, I managed to find that in my version too, and on Saturday I managed to get Chrome to find the monitor, and it replaced the "No monitors can be found text" with the command line as in your screenshot, but the Response line was not there. The error was a "Chrome.hid.send Error: [object Object] handleError".

Shortly after this half success, I found a libusb installer for windows, and thought I was onto something, so I tried that. I have no idea what it did, but basically it broke everything that was previously working, C2 Utility and Tijmen's web application both stopped working. Luckily installing an update of the C2 Utility fixed them again. This minor disaster then lucky recovery prompted me to move off in a new direction.

I have now partitioned my laptop harddrive, and installed Ubuntu 14.04 as a dual boot. Experimenting with Linux has been on my to do list for a while anyway.

Here is what I have done in order: (Just in case you spot I have missed anything)
Installed Ubuntu 14.04
Downloaded and installed Libusb1.0.9 using "Sudo apt-get install libusb-dev"
Downloaded Python 2.7.8
(From some instructions on how to install Python 2.7.8) - Installed Build-Essentials, Installed a load of libraries (I can find the list if necessary)
Installed Python 2.7.8 using ./Configure, Make, sudo Make Install
Downloaded and installed PyUSB1.0.0b2 using Python setup.py install

I then tried to run your simple Python example and got the following error (before even trying to attach to the Concept2)

Code: Select all

Line 5: configuration = device[0]
TypeError: 'NoneType' object has no attribute '____getitem____'
I also installed Chrome 39 on Ubuntu, but when running the extension, I am stuck on the "No PM monitors can be found" error when I try connecting to the ergo.

I have also downloaded PyRow, but I am getting all sorts of compiling errors in the code, and have slowly been working my way though them, but since the code is working for other people, I dont get why I am getting basic compile errors like the indentation blocks aren't right. I will follow this up in the PyRow forum topic though.

dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » December 2nd, 2014, 8:05 am

Ubuntu requires a little extra work. You need to:

- Create a file named /etc/udev/rules.d/concept2.rules with the following content:

Code: Select all

SUBSYSTEM=="usb", ATTR{idVendor}=="17a4", MODE="0664", GROUP="plugdev"
- Execute "sudo service udev restart".
- Reconnect your PM5 if it's plugged in.

chrome.hid on Ubuntu requires a little extra work. chrome.hid on Ubuntu doesn't detect USB device disconnects so any time you disconnect your PM5 you'll need to restart Chrome before chrome.hid is able to detect it again.

Can you paste the output of "lsusb"?

I've made a small modification to the Python example. Try this instead:

Code: Select all

import os
import usb

device        = usb.core.find(idVendor=6052)
configuration = device[0]
interface     = configuration[(0, 0)]
inEndpoint    = interface[0]
outEndpoint   = interface[1]

if device.is_kernel_driver_active(0):
    device.detach_kernel_driver(0)

data = [
    1,   # Report ID
    241, # Standard Frame Start Flag

    # Command
    #
    # 128 is 0x80 in hexidecimal. If you check Appendix A you'll find that 0x80
    # is CSAFE_GETSTATUS_CMD's command ID.
    128,

    128, # Checksum
    242, # Frame Stop Flag

    # Padding. Standard frames are 21 bytes.
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]

device.write(outEndpoint.bEndpointAddress, data)

response = device.read(inEndpoint.bEndpointAddress, inEndpoint.wMaxPacketSize)

print "%s" % response

# Prints:
#
#     array('B', [
#         1,   # Report ID
#         241, # Standard Frame Start Flag
#
#         # Command Response
#         #
#         # If you search for "CSAFE machine states" you'll find that 1 means
#         # ready. I'm not sure why but if I execute CSAFE_GETSTATUS_CMD
#         # multiple times its return value alternatives between 1 and 129. 129
#         # doesn' appear to be documented.
#         1,
#
#         1,   # Checksum
#         242, # Frame Stop Flag
#
#         # Padding
#         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#    ])

Phil_M
Paddler
Posts: 30
Joined: November 23rd, 2014, 10:10 am

Re: Communicating with PM5 via VB

Post by Phil_M » December 2nd, 2014, 9:21 am

Ubuntu requires a little extra work.
Of course :D.

Where should I save the Concept2.rules file? or does it not matter?

I dont think I tried restarting Chrome so that may explain that one. Where will I find the output of lsusb?

I will try the new Python one tonight.

Thank you again dsissitka

dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » December 2nd, 2014, 9:59 am

No problem.
Phil_M wrote:Where should I save the Concept2.rules file? or does it not matter?
Save it in the /etc/udev/rules.d directory.
Phil_M wrote:Where will I find the output of lsusb?
Open a terminal (press the Windows key then start typing "terminal") and execute it:

http://i.imgur.com/5Tvz0tq.png

Can you paste the output of "lsusb -v" instead? That'll give us a little more information to work with.

Phil_M
Paddler
Posts: 30
Joined: November 23rd, 2014, 10:10 am

Re: Communicating with PM5 via VB

Post by Phil_M » December 2nd, 2014, 3:47 pm

:D :D :D :D

Your new Python example is working. I got the response as per your instructions, and got my missus to do a few strokes while I spammed F5, and got several different Machine States as a result.

I then tried to mess with it to get some different data out, and promptly broke it, but nevermind :D, I now need to get my reading hat on, and get to grips with Appendix A. I now have the anchor I was after at the start of this long quest.

Thank you very much for your persistence dsissitka.

In other news I still cant get the Chrome one to work, but I am going to focus on Python for now. I did the lsusb, and it recognised the Concept2, I then tried lsusb -v and there was too much data, and the usb slot with the concept2 in it was pushed off the terminal. I don't know if there is a way to do lsusb -v for a specific usb slot, but given the python code above is working, I imagine its all a bit academic now.

Thank you again.
Phil

dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » December 2nd, 2014, 4:03 pm

Glad to hear it!
Phil_M wrote:In other news I still cant get the Chrome one to work...
Just curious, what's the error now?

Edit: And what version of Chrome are you using?

The nice thing about chrome.hid is that it should work everywhere that the desktop version of Chrome works. Some day I'd like to create a RowPro lite of sorts and run it on a cheap Chromebook.

Phil_M
Paddler
Posts: 30
Joined: November 23rd, 2014, 10:10 am

Re: Communicating with PM5 via VB

Post by Phil_M » December 2nd, 2014, 4:21 pm

There isn't an error as such, it just cant find the ergo, so just has the "Cant find PM" line instead of command and response.

Using version 39 of Chrome. On windows I managed to get half way there as per an earlier post, but on Ubuntu its being stubborn.

dsissitka
Paddler
Posts: 29
Joined: June 29th, 2014, 4:48 am

Re: Communicating with PM5 via VB

Post by dsissitka » December 2nd, 2014, 4:38 pm

I suspect you're getting bit by Issue 347758: HID device enumeration doesn't pick up removal on Linux. If that's the case and you'd like to give chrome.hid another shot you can usually work around the problem by:

- Exiting Chrome.
- Reconnecting your PM5.
- Starting Chrome.

Sometimes you have to do that a couple of times before it will work.

Either way I can't wait to see what you come up with!

Phil_M
Paddler
Posts: 30
Joined: November 23rd, 2014, 10:10 am

Re: Communicating with PM5 via VB

Post by Phil_M » December 31st, 2014, 6:25 pm

Dsissitka, I need your assistance again.

It has been about a month since you got a base program working for me, and I haven't had too much time to play since then. Ironically because I have been spending all my time on the ergo. Gave myself a silly 310km in December challenge which I have thankfully finished tonight. I have however spent some time learning python via "Learn Python the hard way".

Anyway....I managed to get somewhere with my program. It looks pretty awful, and is still super simple, but at least it is doing something. It takes 1 reading a second and outputs it to a text file, hurrah. I am planning on putting more readings into the text file, and changing it from once a second to once a stroke, but I haven't had the time to experiment on the ergo to find out what readings I need to take, what with all the ergo-ing I have been doing.

My hugely untidy code so far :D. The business end is at the bottom. There are a couple of sections in there not being used yet, because it is a work in progress.

Code: Select all

import os
import usb
import sys
import time

device = usb.core.find(idVendor=6052)

if not device:
	print "No rowing machine found."
	sys.exit(1)

try:
	configuration = device[0]
	interface     = configuration[(0, 0)]
	inEndpoint    = interface[0]
	outEndpoint   = interface[1]
	if device.is_kernel_driver_active(0):
		device.detach_kernel_driver(0)

except:
	print "Unknown error."
	sys.exit(1)

def metres():
	data = [
	1,   # Report ID
	241, # Standard Frame Start Flag
	161, # Command
	161, # Checksum
	242, # Frame Stop Flag
	# Padding. Standard frames are 21 bytes.
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	]

	device.write(outEndpoint.bEndpointAddress, data)
	response = device.read(inEndpoint.bEndpointAddress, inEndpoint.wMaxPacketSize)
	return response[5]+response[6]*255

def rowTime_Arr():
	data = [
	1,   # Report ID
	241, # Standard Frame Start Flag
	160, # Command
	160, # Checksum
	242, # Frame Stop Flag
	# Padding. Standard frames are 21 bytes.
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	]

	device.write(outEndpoint.bEndpointAddress, data)
	response = device.read(inEndpoint.bEndpointAddress, inEndpoint.wMaxPacketSize)
	return response

def rowTime_Sec():
	Time_Arr = rowTime_Arr()
	return Time_Arr[5]*3600.0+Time_Arr[6]*60.0+Time_Arr[7]+Time_Arr[8]/255.0

def Workout_Start():
	Time_Arr = rowTime_Arr()
	if Time_Arr[2] == 9:
		return "Start"
	else:
		return "wait"

def Machine_State():
	data = [
	1,   # Report ID
	241, # Standard Frame Start Flag
	128, # Command
	128, # Checksum
	242, # Frame Stop Flag
	# Padding. Standard frames are 21 bytes.
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	]

	device.write(outEndpoint.bEndpointAddress, data)
	response = device.read(inEndpoint.bEndpointAddress, inEndpoint.wMaxPacketSize)
	return response	


def workoutType():

	if device.is_kernel_driver_active(0):
		device.detach_kernel_driver(0)

	data = [
	1,   # Report ID
	241, # Standard Frame Start Flag
	137, # Command
	137, # Checksum
	242, # Frame Stop Flag

	# Padding. Standard frames are 21 bytes.
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	]

	device.write(outEndpoint.bEndpointAddress, data)

	return device.read(inEndpoint.bEndpointAddress, inEndpoint.wMaxPacketSize)

def Create_File():
	
	Date_Time = (time.strftime("%Y%m%d_%H%M%S"))
	File_Name = "RowLog_%s.txt" % Date_Time
	file = open(File_Name, 'w')
	file.write('Loop,Distance,Time\n')

def rowstats():
	
	# Create_File()

	Date_Time = (time.strftime("%Y%m%d_%H%M%S"))
	File_Name = "RowLog_%s.txt" % Date_Time
	file = open(File_Name, 'w')
	file.write('Loop,Distance,Time\n')

	print "File Created. Waiting to Start"
	
	while Workout_Start() == "wait":
		pass	
	
	for i in xrange(120):
		Workout_info = str(i) + ',' + str(metres()) + ',' + str(rowTime_Sec())
		print Workout_info
		file.write(Workout_info + '\n') 
		time.sleep(1)

	file.close()
Incidentally, have I missed something obvious. In the SDK there is a breakdown of all the commands you can ask, but there doesn't seem to be a breakdown of all the replies that can be given. I.e. In your first example to me, you showed machine state, and when playing with that I got various numbers back, but had to guess what they meant depending on what I happened to be doing on the rowing machine at the time, or in the case of horizontal distance, it says one of the numbers is the units, but what specific number represents metres, or Km, or miles or whatever? I presume even if it is trial and error to find these answers, everyone else here must have already been through it, so is there a library somewhere of responses for each command?

If not, I can do it myself manually hopefully, now I have some time to experiment.

Anyway, my master plan at the start of all this, was to write the output to a text file (check), and then display that output on a graph (still outstanding). This is where I am currently stuck, and it is more of a python/ubuntu problem than a Concept2 problem so if I need to head off to a python forum please tell me, but having googled for a bit, I am going to need some serious dumbing down of answers if I try my luck there. I found a youtube video of how to display a graph from a csv file using matplotlib. This is the code:

Code: Select all

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

def graph():
    Row_Count, Distance, Time = np.loadtxt('RowLog_20141224_151056.txt', delimiter=',', unpack=True)
    fig = plt.figure()
    ax1 = fig.add_subplot(1,1,1, axisbg='white')
    plt.plot(x=Time, y = Distance, fmt='-')
    plt.title('title')
    plt.ylabel('Distance')
    plt.xlabel('Time')
    plt.show

graph()
Which all looks pretty simple, but when running it fails on the import of numpy.

I think the problem is due to numpy being installed on Python2.7.8, but my program using the default python which came with ubuntu (at a guess). When I try to install numpy it says it is already installed. When I ran "dpkg -L python-numpy" it printed a whole load of files stored in "/usr/lib/python2.7/xxxxxx" which looks right. But when I run "type python" the response is "/usr/local/bin/python". Do you think that the problem that python is defaulting to "/usr/local/bin" rather than "/usr/lib/" ?

And as a secondary question, do you think this is the best way to attack the problem, given I will ultimately want a csv of my previous row, and the stats from my current row in real time to be plotted on the same graph? Matplotlib looks to be the way to do it, if I could get it working.

Thank you again for getting me the leg up I needed to get this far.

Happy new year.

Phil

Post Reply