Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hitechnic SuperPro Board #187

Closed
jrddunbr opened this issue Jul 14, 2022 · 7 comments
Closed

Hitechnic SuperPro Board #187

jrddunbr opened this issue Jul 14, 2022 · 7 comments

Comments

@jrddunbr
Copy link
Contributor

  • OS: Arch Linux
  • Python version: 3.10.5
  • NXT-Python version: 3.1.0
  • Connection method: USB

I saw that the HiTechnic NXT SuperPro API notes that the board was only written from the specification, but I actually have one of these things! It suggested to report back findings, so here you go :)

Unfortunately, it didn't work out of the box. I tried to use it, but this is what I got:

>>> import nxt.locator
>>> import nxt.sensor.hitechnic
>>> brick = nxt.locator.find()
>>> pro = nxt.sensor.hitechnic.Prototype(brick, nxt.sensor.Port.S1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jared/.local/lib/python3.10/site-packages/nxt/sensor/digital.py", line 76, in __init__
    sensor = self.get_sensor_info()
  File "/home/jared/.local/lib/python3.10/site-packages/nxt/sensor/digital.py", line 165, in get_sensor_info
    version = self.read_value('version')[0].decode('windows-1252').split('\0')[0]
  File "/home/jared/.local/lib/python3.10/site-packages/nxt/sensor/digital.py", line 152, in read_value
    raise I2CError("read_value timeout")
nxt.error.I2CError: read_value timeout

I've never used/programmed the thing because at the time I bought it years ago, I did not know how to write C yet. But, I'd be interested in making it work if it's something of interest. It's basically never been used and should be fully functional.

PS. This is a really cool project! Definitely going to make good use of it now that I know it exists.

@jrddunbr
Copy link
Contributor Author

jrddunbr commented Jul 14, 2022

Did some experimenting with this..

Wrote this program. Got "16" back with some data!

import nxt.locator
import nxt.sensor.generic

brick = nxt.locator.find()
sensor = brick.get_sensor(nxt.sensor.Port.S1, nxt.sensor.generic.BaseDigitalSensor)
# sensor.I2C_DEV = 0x10
# sensor._i2c_query(0x00, '<8B')

for x in range(0, 255):
    print(x)
    try:
        sensor.I2C_DEV = x
        print(sensor._i2c_query(0x00, '<8B'))
    except Exception as e:
        pass # print(e)

Returns:

16
(86, 50, 46, 50, 65, 32, 32, 32)

So then the next logical conclusion:

import nxt.locator
import nxt.sensor.generic
brick = nxt.locator.find()
sensor = brick.get_sensor(nxt.sensor.Port.S1, nxt.sensor.generic.BaseDigitalSensor)
sensor.I2C_DEV = 0x10
sensor._i2c_query(0x00, '<8B')

That returns the same array as above. Wohoo!

So I determined after a lot of testing that there were 2 issues:

  1. Longer wires do not work for the SuperPro. It has a bunch of signal problems that I eventually was able to isolate by removing the extra cabling I was using. This could have also been the fault of the breadboard connection I was using to interface with the NXT ports and the scope I was using for I2C protocol hacking.
  2. The I2C address is not 0x02 as it is in the existing code, but 0x10.
>>> print(sensor.get_sensor_info())
Version: `V2.2A   `
0x56, 0x32, 0x2e, 0x32, 0x41, 0x20, 0x20, 0x20, 
Product ID: `HiTechnc`
0x48, 0x69, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x63, 
Type: `SuperPro`
0x53, 0x75, 0x70, 0x65, 0x72, 0x50, 0x72, 0x6f, 

@schodet
Copy link
Owner

schodet commented Jul 15, 2022

Thank, this is great findings!

It’s strange that they changed the I2C address, this means that the autodetect can not work with this device.

It looks like SuperPro and Prototype are different boards:

https://web.archive.org/web/20110424022758/http://www.hitechnic.com/cgi-bin/commerce.cgi?preadd=action&key=NPA1058

Would you like to make a new sensor class for the SuperPro?

@jrddunbr
Copy link
Contributor Author

Would you like to make a new sensor class for the SuperPro?

Sure. I'd be happy to.

It looks like SuperPro and Prototype are different boards:

Huh. Funny you share that link with that picture because it looks identical to a board that I have that's identified by nothing other than (c) DSI 2007 that I've been trying to determine what/how it works.. It even has the same pinout. I'll try to make both devices work.

@jrddunbr
Copy link
Contributor Author

I just tested the Prototype board and it literally works out of the box. Was able to get analog readings and do digital reads/writes.

I'd say that the interface could probably be improved a little from passing the class instance (it feels kinda clunky), but it does work at a minimum.

I did find some .. odd? behavior with the digital mode setting; it could be an issue with the device itself but it seems like digital reads or writes is an all or nothing thing for the whole digital bus. I'm not certain if it's the Python doing that or if it's the device firmware running on the chip on the Prototype board itself. More testing to be done there.

@jrddunbr
Copy link
Contributor Author

See #188

schodet added a commit that referenced this issue Jul 18, 2022
Thanks to Jared Dunbar for the test!

Also fix an obviously wrong registers definition.

See #187
@schodet
Copy link
Owner

schodet commented Jul 18, 2022

Nice to resurrect some old hardware :)

I'd say that the interface could probably be improved a little from passing the class instance (it feels kinda clunky), but it does work at a minimum.

Could you clarify this?

I did find some .. odd? behavior with the digital mode setting; it could be an issue with the device itself but it seems like digital reads or writes is an all or nothing thing for the whole digital bus. I'm not certain if it's the Python doing that or if it's the device firmware running on the chip on the Prototype board itself. More testing to be done there.

I would say it is done in the board firmware, it’s a classic way to handle it. If you want to only change a port, you need a Read-Modify-Write cycle.

@jrddunbr
Copy link
Contributor Author

I'd say that the interface could probably be improved a little from passing the class instance (it feels kinda clunky), but it does work at a minimum.

Could you clarify this?

Mostly, I find it odd that this project instantiates sensors by going brick.get_sensor(<sensor port>, <optional sensor class>) instead of SensorClass(brick, port), but I see how you're using that for automatic sensor detection (for some sensors).

I would say it is done in the board firmware, it’s a classic way to handle it. If you want to only change a port, you need a Read-Modify-Write cycle.

The reason it's frustrating is because if you do it that way, that means that you have to set the state of the pin (meaning it's always going to be a bi-state input rather than a tri-state input). I suppose that the device we're using in this case might not support that, but I wanted to test to see if you lost access to a tri-state input by setting the device to output and configuring an output signal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants