samdcbu / nxt-python

GNU General Public License v3.0
0 stars 0 forks source link

NXT Python (Hitechnic DC motor controller/Servo Controller) #18

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
To include the Hitechnic Tetrix controller for the NXT DC and servo controller 
form Hitechnic

Why do you think it's important?

the exposure of Tetrix/NXT make the next level of robot enthusiasts, and with 
the addition of ROS and other ROS nodes will make the NXT/Tetrix a suitable 
platform to do basic research in robotics

Any ideas on how to implement it?

I don't have to much experience in this implementation that's why I'm asking 
your help

Thanks

Please provide any additional information below.

Original issue reported on code.google.com by henrya...@hotmail.com on 23 Nov 2010 at 8:29

GoogleCodeExporter commented 9 years ago
I couldn't find any mention of the Tetrix controller on HiTechnic's product 
page. Could you please link to more information about it?

Original comment by marcus@wanners.net on 23 Nov 2010 at 8:47

GoogleCodeExporter commented 9 years ago
Hi

I have few referneces to the Tetrix DC and servo controllers for the Tetrix

http://www.robotc.net
http://www.tetrixrobotics.com/MINDSTORMS_Controlled/Downloads/default.aspx?aid=8
4
http://www.legoeducation.us/store/detail.aspx?ID=1648&bhcp=1
http://www.legoeducation.us/store/detail.aspx?CategoryID=187&by=9&ID=1649&c=1&t=
0&l=0

Original comment by henrya...@hotmail.com on 24 Nov 2010 at 12:47

GoogleCodeExporter commented 9 years ago
Ah, now I know what you're talking about. I checked out those references and 
couldn't find any protocol docs for the device. Do you know whether it plugs 
into a motor port or a sensor port? If it's a sensor port thing, you'll need to 
find the I2C protocol docs for it. Once I have those, I can create a patch and 
send it to you for testing.

Thanks!

Original comment by marcus@wanners.net on 24 Nov 2010 at 7:39

GoogleCodeExporter commented 9 years ago
Alternatively, an NXC program or library which uses it would work as 
well...those are usually pretty easy to reverse-engineer.

Original comment by marcus@wanners.net on 24 Nov 2010 at 7:40

GoogleCodeExporter commented 9 years ago
Are you still interested in this? I will need the requested docs to continue.

If there is no response in the next few days, I will close this issue.

Original comment by marcus@wanners.net on 3 Jan 2011 at 7:32

GoogleCodeExporter commented 9 years ago
Hi Sorry for the delay, as the files where a bit hard to get but Hitechnic has 
provided them, 

Thanks

Original comment by henrya...@hotmail.com on 4 Jan 2011 at 1:24

Attachments:

GoogleCodeExporter commented 9 years ago
Thanks. I will work on implementing this. In the mean time, it would be most 
helpful if you could provide me with the output of a get_sensor_info() call on 
a BaseDigitalSensor object controlling the sensor. If you don't know what I'm 
talking about I can probably get you some example code.

Original comment by marcus@wanners.net on 4 Jan 2011 at 3:08

GoogleCodeExporter commented 9 years ago
well if you don't mind sending me the code I will need to rus as I'm just 
starting to learn Python

:)

Thanks

Original comment by henrya...@hotmail.com on 4 Jan 2011 at 4:55

GoogleCodeExporter commented 9 years ago
import nxt
b = nxt.find_one_brick()
s = nxt.BaseDigitalSensor(b, nxt.PORT_1)
print s.get_sensor_info()

With the sensor attached to port 1.

Original comment by marcus@wanners.net on 4 Jan 2011 at 5:03

GoogleCodeExporter commented 9 years ago
Hi I have this output, not sure but seems that I have something wrong in my 
installation

I have the DC motor controlled attached to port 1 and the NXT brick on the usb

import nxt
>>> b = nxt.find_one_brick()
>>> s = nxt.BaseDigitalSensor(b, nxt.PORT_1)
>>> print s.get_sensor_info()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "nxt/sensor/digital.py", line 140, in get_sensor_info
    version = self.read_value('version')[0].split('\0')[0]
  File "nxt/sensor/digital.py", line 127, in read_value
    return self._i2c_query(address, fmt)
  File "nxt/sensor/digital.py", line 112, in _i2c_query
    self._ls_get_status(n_bytes)
  File "nxt/sensor/digital.py", line 85, in _ls_get_status
    b = self.brick.ls_get_status(self.port)
  File "nxt/brick.py", line 26, in poll
    return parse_func(igram)
  File "nxt/direct.py", line 149, in _parse_ls_get_status
    tgram.check_status()
  File "nxt/telegram.py", line 112, in check_status
    nxt.error.check_status(self.parse_u8())
  File "nxt/error.py", line 85, in check_status
    raise ex
nxt.error.DirProtError: Communication bus error

Original comment by henrya...@hotmail.com on 9 Jan 2011 at 4:59

GoogleCodeExporter commented 9 years ago
and this is output with the servo controller at port 1 on the nxt

 print s.get_sensor_info()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "nxt/sensor/digital.py", line 140, in get_sensor_info
    version = self.read_value('version')[0].split('\0')[0]
  File "nxt/sensor/digital.py", line 127, in read_value
    return self._i2c_query(address, fmt)
  File "nxt/sensor/digital.py", line 111, in _i2c_query
    self.brick.ls_write(self.port, msg, n_bytes)
  File "nxt/brick.py", line 24, in poll
    self.sock.send(str(ogram))
  File "nxt/usbsock.py", line 65, in send
    self.handle.bulkWrite(self.blk_out.address, data)
usb.USBError: error submitting URB: No such device

Original comment by henrya...@hotmail.com on 9 Jan 2011 at 5:01

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
with the DC motor controller connected in port 1

>>> import nxt
>>> b = nxt.find_one_brick()
>>> s = nxt.BaseDigitalSensor(b, nxt.PORT_1)
>>> print s.get_sensor_info()
Version: `�V2.0   `
0xfd, 0x56, 0x32, 0x2e, 0x30, 0x20, 0x20, 0x20, 
Product ID: `HiTechnc`
0x48, 0x69, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x63, 
Type: `MotorCon`
0x4d, 0x6f, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 

and with the servo controller i got 

>>> import nxt
>>> b = nxt.find_one_brick()
>>> s = nxt.BaseDigitalSensor(b, nxt.PORT_1)
>>> print s.get_sensor_info()
Version: `�V1.4   `
0xfd, 0x56, 0x31, 0x2e, 0x34, 0x20, 0x20, 0x20, 
Product ID: `HiTechnc`
0x48, 0x69, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x63, 
Type: `ServoCon`
0x53, 0x65, 0x72, 0x76, 0x6f, 0x43, 0x6f, 0x6e, 

Original comment by henrya...@hotmail.com on 9 Jan 2011 at 5:13

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
OK, I will ask them if they can provide me with the most recent spec

Thanks

Original comment by henrya...@hotmail.com on 9 Jan 2011 at 6:12

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Hi 

I've been told that the document is the latest version and the version number 
of the document does not correspond to the firmware version.

Which is a good news :)

one thing, could you please let me know how can I patch it, and do you mind 
send me some testing code to test the encoders

Thanks :)

Original comment by henrya...@hotmail.com on 13 Jan 2011 at 4:38

GoogleCodeExporter commented 9 years ago
If you're on windows, would use TortoiseSVN's Patch feature. If you're on 
linux, you use the patch command. The syntax is tricky, google can help. As for 
code, I'm not sure exactly how one would use the motors. Look at the other 
sensor examples and the comments in the patch to see how the syntax should go.

If you can post your testing code, I will add it as an example.

Original comment by marcus@wanners.net on 14 Jan 2011 at 3:20

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I have applied the patch and then I did reinstall nxt-python

when building I got this error

running install_lib
copying build/lib.linux-i686-2.6/nxt/sensor/hitechnic.py -> 
/usr/local/lib/python2.6/dist-packages/nxt/sensor
byte-compiling /usr/local/lib/python2.6/dist-packages/nxt/sensor/hitechnic.py 
to hitechnic.pyc
SyntaxError: ('invalid syntax', 
('/usr/local/lib/python2.6/dist-packages/nxt/sensor/hitechnic.py', 567, 7, '    
def get_pid(self, mot):\n'))

could you please advice

Thanks

Original comment by henrya...@hotmail.com on 18 Jan 2011 at 9:15

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Running into problems here with the Communication bus error.

I have run the code 
>>> import nxt
>>> b = nxt.find_one_brick()
>>> s = nxt.BaseDigitalSensor(b, nxt.PORT_1)
>>> print s.get_sensor_info()

on two different machines with no success. My error is:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py", line 140, in get_sensor_info
    version = self.read_value('version')[0].split('\0')[0]
  File "/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py", line 127, in read_value
    return self._i2c_query(address, fmt)
  File "/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py", line 112, in _i2c_query
    self._ls_get_status(n_bytes)
  File "/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py", line 85, in _ls_get_status
    b = self.brick.ls_get_status(self.port)
  File "/usr/local/lib/python2.6/dist-packages/nxt/brick.py", line 26, in poll
    return parse_func(igram)
  File "/usr/local/lib/python2.6/dist-packages/nxt/direct.py", line 149, in _parse_ls_get_status
    tgram.check_status()
  File "/usr/local/lib/python2.6/dist-packages/nxt/telegram.py", line 112, in check_status
    nxt.error.check_status(self.parse_u8())
  File "/usr/local/lib/python2.6/dist-packages/nxt/error.py", line 85, in check_status
    raise ex
nxt.error.DirProtError: Communication bus error

Any advice? Simply running the last command twice does not appear to be a 
viable solution as suggested.

Original comment by forrest....@gmail.com on 18 Jan 2011 at 10:46

GoogleCodeExporter commented 9 years ago
henry:
That's exactly the error I'm looking for, and good job patching the source! 
I'll have an updated patch for you to test as soon as I can. Thanks.

fmc:
I don't know what causes this error, but for me it only happens occasionally. 
Could you test with a v1.x release and with the 0.7 NXT_Python package please? 
The method for get_sensor_info() may be different or nonexistant on some of 
these, just try reading a value if you can't do that specific one.

Original comment by marcus@wanners.net on 19 Jan 2011 at 2:01

GoogleCodeExporter commented 9 years ago
Here's the updated patch file. Sorry about that, simple missing parentheses. My 
bad; probably should have at least parsed the code before sending it.

Original comment by marcus@wanners.net on 19 Jan 2011 at 2:32

Attachments:

GoogleCodeExporter commented 9 years ago
:)  the patch has been successfully applied.

could you please advice which simple code can I use to test them

Thanks

Original comment by henrya...@hotmail.com on 19 Jan 2011 at 8:32

GoogleCodeExporter commented 9 years ago
Here is a recent log from ipython (this is the same error as before, but with a 
traceback):

In [1]: import nxt

In [2]: b = nxt.find_one_brick()

In [3]: s = nxt.Base
nxt.BaseAnalogSensor   nxt.BaseDigitalSensor  nxt.BaseMotor

In [3]: s = nxt.BaseDigitalSensor(b, nxt.PORT_4)

In [4]: s.get_sensor_info()
---------------------------------------------------------------------------
DirProtError                              Traceback (most recent call last)

/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py in 
get_sensor_info(self)
    138 
    139     def get_sensor_info(self):
--> 140         version = self.read_value('version')[0].split('\0')[0]
    141         product_id = self.read_value('product_id')[0].split('\0')[0]
    142         sensor_type = self.read_value('sensor_type')[0].split('\0')[0]

/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py in 
read_value(self, name)
    125         """
    126         address, fmt = self.I2C_ADDRESS[name]
--> 127         return self._i2c_query(address, fmt)
    128 
    129     def write_value(self, name, value):

/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py in 
_i2c_query(self, address, format)
    110             sleep(0.02 - diff)
    111         self.brick.ls_write(self.port, msg, n_bytes)
--> 112         self._ls_get_status(n_bytes)
    113         data = self.brick.ls_read(self.port)
    114         self.lastpoll = time()

/usr/local/lib/python2.6/dist-packages/nxt/sensor/digital.py in 
_ls_get_status(self, n_bytes)
     83         for n in range(3):
     84             try:
---> 85                 b = self.brick.ls_get_status(self.port)
     86                 if b >= n_bytes:
     87                     return b

/usr/local/lib/python2.6/dist-packages/nxt/brick.pyc in poll(self, *args, 
**kwargs)
     24         self.sock.send(str(ogram))
     25         igram = Telegram(opcode=opcode, pkt=self.sock.recv())
---> 26         return parse_func(igram)
     27     return poll
     28 

/usr/local/lib/python2.6/dist-packages/nxt/direct.pyc in 
_parse_ls_get_status(tgram)
    147 
    148 def _parse_ls_get_status(tgram):
--> 149     tgram.check_status()
    150     n_bytes = tgram.parse_u8()
    151     return n_bytes

/usr/local/lib/python2.6/dist-packages/nxt/telegram.pyc in check_status(self)
    110 
    111     def check_status(self):
--> 112         nxt.error.check_status(self.parse_u8())
    113 
    114 import nxt.direct

/usr/local/lib/python2.6/dist-packages/nxt/error.pyc in check_status(status)
     83         ex = CODES.get(status)
     84         if ex:
---> 85             raise ex
     86         else:
     87             raise ProtocolError, status

DirProtError: Communication bus error
____________________________________________________________-

I am, however, able to communicate with a touch sensor I have connected in 
PORT_1 by the small script:
#!/usr/bin/env python

import nxt

b = nxt.find_one_brick()
t = nxt.Touch(b, nxt.PORT_1)
print t.get_sample() #'TRUE' or 'FALSE' depending on touch state
# end script

I could also communicate with the touch sensor in a similar way in version 1.2 
through this script:
#!/usr/bin/env python

import time
import nxt.locator
from nxt.sensor import *

sock = nxt.locator.find_one_brick()
if sock:
    b = test_sensors(sock.connect())
    t = TouchSensor(b, PORT_1)
        print t.get_sample()
    sock.close()
else:
    print 'No NXT bricks found'
# end script

I could find no similar method call like get_sensor_info() in 1.2. I have not 
looked at version .7, but I'm not sure that is relevant.

Also, some more information, maybe it's helpful 

In [1]: import nxt
In [2]: b = nxt.find_one_brick()
In [3]: b.get_device_info()
Out[3]: 
('NXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
 '00:16:53:0C:02:FF',
 0,
 82516)
In [4]: b.get_firmware_version()
Out[4]: ((1, 124), (1, 28))

Still, I cannot solve the Communication bus error.

Original comment by forrest....@gmail.com on 20 Jan 2011 at 9:52

GoogleCodeExporter commented 9 years ago
Protocol error guy: This seems to be a problem with some optimization code we 
implemented a while back. It was designed to reduce effect of bt/usb latency on 
the performance of nxt-python. Please open a new ticket with details on the 
versions you see this problem with. In the mean time, you can try tweaking the 
value in lines 108 and 110 of sensor/digital.py and seeing if that fixes it. 
The one chosen was thought to be conservative and worked in most cases, but it 
may not be working with your configuration. This can be easily fixed with your 
cooperation, and thanks for that neat traceback format.

Need examples guy: That's really dependent on how the sensor is meant to be 
used. In general, apply the patch, install the package (you seem to have got 
this right) and then do something like this:
#with a brick as b
from nxt.sensor import *
from nxt.sensor.hitechnic import ServoCon, MotorCon #needed because the aliases 
aren't set up in sensor/__init__.py yet
cur = mot.get_enc_current(1)
print cur #should be 0 if the motor hasn't moved since being powered on
mot.set_encoder_target(cur+360) #should move the motor one rotation...
mot.set_power(70) #...at 70% power
at this point, you can do a print dir(mot) to see what other methods are 
available. check out the comments in the patch to see how to use them
srv = ServoCon(b, PORT_2)
print srv.get_status() #should be 0
srv.set_pos(1, 60) #set servo 1 to position 60
print srv.get_status() #should be 1
while srv.get_status() != 0:
    print "running..." #print running... as long as the motor is moving
print "stopped." #should print stopped as soon as the motor isn't moving anymore
again, play with the other methods and report any weird stuff. I will warn you 
that set_get_ratio on motors isn't implemented yet by HiTechnic, so it won't 
work.

Thanks!

Original comment by marcus@wanners.net on 20 Jan 2011 at 10:27

GoogleCodeExporter commented 9 years ago
Alright, reporting back here, still having issues.

I took a look at lines 108 and 110 in digital.py and my first attempt was too 
change the two occurrences of value .02 to something greater like you 
suggested. I tried values like .04, .08 and then eventually something huge like 
5. Nothing worked. I then realized that in the step-by-step debugger things 
were screwy because I was taking excessive time between time() calls while 
stepping, so I modified the code further...

Here are my changes:

    def _i2c_query(self, address, format):
        """Reads an i2c value from given address, and returns a value unpacked
        according to the given format. Format is the same as in the struct
        module. See http://docs.python.org/library/struct.html#format-strings
        """
        n_bytes = struct.calcsize(format)
        msg = chr(self.I2C_DEV) + chr(address)
    t = time()
        if not self.lastpoll: self.lastpoll = t
    #import pdb; pdb.set_trace()
        if self.lastpoll+5 > t:
            diff = t - self.lastpoll
            sleep(4 - diff)
        self.brick.ls_write(self.port, msg, n_bytes)
        self._ls_get_status(n_bytes)
        data = self.brick.ls_read(self.port)
        self.lastpoll = t
        if len(data) < n_bytes:
            raise I2CError, 'Read failure'
        return struct.unpack(format, data[-n_bytes:]) # TODO: why could there be more than

This basically involves setting t to time() near the top and using this same 
value throughout the function call.

Anyways, I'm still getting the communication bus error. One thing to note 
however, the first time I run 
"import nxt
b = nxt.find_one_brick()
s = nxt.BaseDigitalSensor(b, nxt.PORT_4)
s.get_sensor_info()"

the code posted DOES enter the if statement at line 110 and sleeps for some 
amount of time, eventually resulting in the error. Subsequent calls to 
s.get_sensor_info() result in the error immediately without sleeping. If I 
re-initialize s by saying s = nxt.BaseDigitalSensor(b, nxt.PORT_4) again and 
then call s.get_sensor_info(), the code will sleep again, but subsequent calls 
to s.get_sensor_info() error immediately.

Not sure what to do at this point. 

Any more suggestions?

Thanks!

Original comment by forrest....@gmail.com on 25 Jan 2011 at 6:51

GoogleCodeExporter commented 9 years ago
I will take a good look at that code as soon as I get a bit of time with my dev 
box. In the mean time, are you using USB or bluetooth? Does switching from one 
to the other change things at all?

As I said, if you wouldn't mind, start a new issue for this as it's obviously 
separate from the one this issue is about.

Original comment by marcus@wanners.net on 25 Jan 2011 at 9:05

GoogleCodeExporter commented 9 years ago
All right. I can't reproduce your error and actually haven't gotten ANY errors 
at all using either USB or Bluetooth (with the latest SVN). If you can't find a 
way to fix the issue, please open a new issue which details exactly what you're 
doing including:
OS
Python version
NXT hardware/software/protocol version numbers
NXT-python release version number or SVN revision
USB or BT? (test with both if possible)
PyUSB/pybluez version number

Until I have this information, I'm really at a loss as far as what's going on 
here. If you're on Ubuntu, you can use wireshark to watch exactly what's going 
on with the USB ports in real time. Might help with debugging.

Sorry I couldn't figure out why this is happening to you.

Original comment by marcus@wanners.net on 27 Jan 2011 at 9:27

GoogleCodeExporter commented 9 years ago
Any word from the OP on this?

Original comment by marcus@wanners.net on 1 Feb 2011 at 10:17

GoogleCodeExporter commented 9 years ago
I'm going to add this code but mark it as untested. If you test it at some 
point, let me know how things go.

Original comment by marcus@wanners.net on 6 Feb 2011 at 1:18

GoogleCodeExporter commented 9 years ago
http://www.education.rec.ri.cmu.edu/products/getting_started_tetrix/nxtg/softwar
e/software_index.html

Original comment by humberto...@gmail.com on 20 Nov 2014 at 3:35