Pan_Tilt lib for C/C++


#1

I am searching for how to access C/C++ libraries for the Pimoroni Pan-Tilt HAT. I have found the python libs but I do not think that that is enough to use the HAT from C/C++.
If the C/C++ lib is not available, is there documentation on the I2C commands that need to be sent to the HAT to gain control of the servos?


#2

Presently there is no documentation on the i2c interface, since the firmware that drives Pan Tilt HAT is completely custom, however briefly:

0x00 = Config
0x01 = Servo 1 (two bytes, most significant first)
0x03 = Servo 2 (ditto)
0x05 = ws2812 pixel data, this goes from register 0x05 to 0x4c
0x4d = update register, trigger an update for the ws2812 pixels

The 2 byte unsigned integers for Servo 1 and Servo 2 represent the time, in microseconds, of the servo high pulse. A pulse is typically something like 500 to 2500 (0.5ms to 2.5ms) microseconds which is repeated every 20 milliseconds.

The config register is as follows, from LSB to MSB:

0 - Enable Servo 1
1 - Enable Servo 2
2 - Enable lights
3 - Light mode - 1 = ws2812, 0 = regular on/off toggle
4 - Light polarity - 1 = active low, 0 = active high

The ws2812 pixel data is 72 bytes long- it doesn’t care if you send 18 sets of RGBW data or 24 sets of RGB data. It also doesn’t care what order the pixels are sent in, but will forward the data you give it directly on to the attached ws2812 or sk6812 pixels. So, use the pixel order and format suitable for whatever you have connected.

Hopefully that should get you started! I should probably codify this in a brief datasheet.


#3

Thank you very much for the info.
I also purchased an Automation HAT. Is there any way that you could provide information on that piece of hardware?


#4

All the information on which pin connects to what is here: https://pinout.xyz/pinout/automation_hat

The Automation HAT then has an ADS1015 ADC on board, plus an SN3218 LED driver.

The former is documented here: http://www.ti.com.cn/cn/lit/ds/symlink/ads1015.pdf and should have a whole bunch of C-like embedded example code floating around on the internet that you could draw on for inspiration.

The SN3218 is documented here: https://github.com/pimoroni/sn3218/blob/master/datasheets/sn3218-datasheet.pdf

Our own Arduino library might help you better understand how it works (it’s really, really simple as far as i2c devices go anyway)- https://github.com/pimoroni/pimoroni_arduino_sn3218/blob/master/sn3218.cpp


#5

I am searching for how to access C/C++ libraries for the Pimoroni Pan-Tilt HAT

Presently there is no documentation on the i2c interface, since the firmware that drives Pan Tilt HAT is completely custom

That’s likely to be a stupid question, but how did you create a Python library then? What’s different with C/C++?

And I double the request for C/C++ library, that would be quite handy.
Or at least a bit more detailed guidance for how to control pan/tilt with C/C++ via I2C.


#6

Well, since I wrote said firmware I knew exactly how to interact with it, and Python is the one language we - at least try very hard to - support across all our Pi products.

The reason we don’t ship C/C++ drivers for anything is, briefly:

  • Python is by far the more widely pushed and accessible language on the Pi
  • I’m the only one doing software support
  • So I don’t have time :(
  • I’m a terrible C/C++ programmer

It’s a shame, because I’d love the time to explore this stuff!


#7

I see. Well, I’ll try to create a C/C++ implementation of my own then, and in case I succeed I’ll share the results here, of course.

But I’ll need some help from you. I have no experience working with I2C, so please bear with me.

Here’s the output of i2c-tools:

$ i2cdetect -y 1

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- 15 -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

So device has a 0x15 address. Here’s its dump as a word data:

$ i2cdump -y 1 0x15 w

     0,8  1,9  2,a  3,b  4,c  5,d  6,e  7,f
00: 0000 c800 00c8 c800 50c8 4950 4d49 4f4d
08: 524f 4f52 4e4f 494e 0049 0000 0000 0000
10: 0000 0000 0000 0000 5700 4157 5341 0053
18: 0000 0000 0000 0000 0000 0000 0000 0000
20: 0000 0000 0000 0000 0000 4800 4548 5245
28: 4552 0045 0000 0000 0000 0000 0000 0000
30: 0000 0000 0000 0000 0000 0000 0000 0000
38: 0000 0000 0000 0000 0000 0000 0000 0000
40: 0000 0000 0000 0000 0000 0000 0000 0000
48: 0000 0000 0000 0000 0000 4e00 004e c800
50: 00c8 c800 50c8 4950 4d49 4f4d 524f 4f52
58: 4e4f 494e 0049 0000 0000 0000 0000 0000
60: 0000 0000 5700 4157 5341 0053 0000 0000
68: 0000 0000 0000 0000 0000 0000 0000 0000
70: 0000 0000 0000 4800 4548 5245 4552 0045
78: 0000 0000 0000 0000 0000 0000 0000 0000
80: 0000 0000 0000 0000 0000 0000 0000 0000
88: 0000 0000 0000 0000 0000 0000 0000 0000
90: 0000 0000 0000 0000 0000 0000 0000 0000
98: 0000 0000 0000 4e00 004e c800 00c8 c8ff
a0: 506f 4902 4d10 4fff 5220 4f86 4e00 49c8
a8: 0000 0000 0002 0000 00ff 0000 0000 00f8
b0: 571c 4100 5300 0086 0000 0000 0089 0000
b8: 00c0 002f 0000 000f 0000 0000 0001 0000
c0: 0000 4800 45ff 5214 4516 0000 007a 0011
c8: 0000 0020 0000 0000 0000 0000 00c8 0000
d0: 00c8 0000 00c8 0000 0000 0000 0088 00d7
d8: 002b 002b 0000 0000 0000 00ff 0051 00ff
e0: 0066 00ff 0000 00ff 0000 0042 00bb 0000
e8: 00fe 4ea8 007f c884 ffff 6f00 0200 1000
f0: ff00 2000 8600 0000 c800 0000 0000 0200
f8: 0000 ff00 0000 0000 f800 1c00 0000 0000

Just in case, here’s its dump as a byte data:

$ i2cdump -y 1 0x15

No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 c8 00 c8 50 49 4d 4f 52 4f 4e 49 00 00 00    ..?.?PIMORONI...
10: 00 00 00 00 00 57 41 53 00 00 00 00 00 00 00 00    .....WAS........
20: 00 00 00 00 00 00 48 45 52 45 00 00 00 00 00 00    ......HERE......
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4e 00    ..............N.
50: c8 00 c8 50 49 4d 4f 52 4f 4e 49 00 00 00 00 00    ?.?PIMORONI.....
60: 00 00 00 57 41 53 00 00 00 00 00 00 00 00 00 00    ...WAS..........
70: 00 00 00 00 48 45 52 45 00 00 00 00 00 00 00 00    ....HERE........
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 4e 00 c8 ff    ............N.?.
a0: 6f 02 10 ff 20 86 00 c8 00 00 02 00 ff 00 00 f8    o??. ?.?..?....?
b0: 1c 00 00 86 00 00 89 00 c0 2f 00 0f 00 00 01 00    ?..?..?.?/.?..?.
c0: 00 00 ff 14 16 00 7a 11 00 20 00 00 00 00 c8 00    ...??.z?. ....?.
d0: c8 00 c8 00 00 00 88 d7 2b 2b 00 00 00 ff 51 ff    ?.?...??++....Q.
e0: 66 ff 00 ff 00 42 bb 00 fe a8 7f 84 ff 00 00 00    f....B?.????....
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

According to what you wrote above, servos are 0x01 and 0x03 (both currently storing 0x00 values, as I can see), so writing to these registers will make them move - is that so? If not, how can I find correct registers/addresses?


#8

That is more or less so- although:

Firstly you will most likely want to write the config register first since - IIRC - the servos are disabled-by-default.

You can do this with i2c-tools by setting the two LSBs of the config register (the enable servo bits):

i2cset -y 1 0x15 0x00 0x03

Secondly writing 0x01 and 0x03 will be slightly trickier since they aren’t - at least not on their own - the full value you need to work with. The unsigned 16bit values are actually stored in two pairs of 8bit registers.

You need to use i2cset's “word” mode to write both bytes:

i2cset -y 1 0x15 0x01 0xFFFF w

IE: to set servo 1 to a 500us pulse:

i2cset -y 1 0x15 0x01 500 w

This will translate through to C differently depending on what library you use for i2c access- some have a write_word method which handles the conversion for you. Others? Not so much! :D


#9

go program

Not sure if this will be of interest to anyone, but it’s there if you need it.
Now there is a Go Package: With example…

pantilt package


#10

Good evening fellows,

I’ve been able to write a C++ class named pantilthat (made of pantilthat.h and pantilthat.ccp) designed for offering a pure C++ interface to i2c Pimoroni Pantilt-Hat device for Raspberry Pi 3 B+.

Give me a couple of days to test it so I can assert it is safe and functional. Then I’ll publish here a link to the source code.

Regards,

RC


#11

Here we go ! At https://github.com/corbelr/cpppth you’ll find the promised C++ class for controlling a PTH, along with a demo program.

Regards.


#12

Handy! Nice work!!!