Lynxmotion SES V2 Hexapod Robot

@madmax - Can you attach your code (file) and tell me which library you used ?

1 Like

@dialfonzo

Sure. The code is attached LSS_Query_modified.zip (992 Bytes) . The library is the standard Arduino library

1 Like

@madmax - Thanks, for whatever reasons i got exited but you are not on Teensy yet and the results are the same as before for me.

@kurte - I re-downloaded your library (HERE) and deleted whatever i already had. (which should have been yours)

There is a long list so i will only put the warnings:

C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:17:18: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static bool LSS::hardwareSerial;
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:18:22: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static Stream * LSS::bus;
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:19:32: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static LSS_LastCommStatus LSS::lastCommStatus = LSS_CommStatus_Idle;
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:22:53: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static char LSS::cmdBuffer[LSS_MaxTotalCommandLength];
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:23:29: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static volatile int8_t LSS::cmdBufferSize;
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:24:30: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static volatile uint8_t LSS::readID;
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:25:30: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static volatile uint8_t LSS::identSize;
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:26:26: warning: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive]
static char LSS::value[24];
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:52:31: warning: cannot declare member function ‘static int LSS::timedRead()’ to have static linkage [-fpermissive]
static int LSS::timedRead(void)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:167:58: warning: cannot declare member function ‘static void LSS::initBus(SoftwareSerial&, uint32_t)’ to have static linkage [-fpermissive]
static void LSS::initBus(SoftwareSerial &s, uint32_t baud)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:178:58: warning: cannot declare member function ‘static void LSS::initBus(HardwareSerial&, uint32_t)’ to have static linkage [-fpermissive]
static void LSS::initBus(HardwareSerial &s, uint32_t baud)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:187:31: warning: cannot declare member function ‘static void LSS::closeBus()’ to have static linkage [-fpermissive]
static void LSS::closeBus(void)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:206:53: warning: cannot declare member function ‘static bool LSS::genericWrite(uint8_t, char*)’ to have static linkage [-fpermissive]
static bool LSS::genericWrite(uint8_t id, char * cmd)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:236:68: warning: cannot declare member function ‘static bool LSS::genericWrite(uint8_t, char*, int16_t)’ to have static linkage [-fpermissive]
static bool LSS::genericWrite(uint8_t id, char * cmd, int16_t value)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:268:111: warning: cannot declare member function ‘static bool LSS::genericWrite(uint8_t, char*, int16_t, char*, int16_t)’ to have static linkage [-fpermissive]
static bool LSS::genericWrite(uint8_t id, char * cmd, int16_t value, char * parameter, int16_t parameter_value)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:302:68: warning: cannot declare member function ‘static int16_t LSS::genericRead_Blocking_s16(uint8_t, char*)’ to have static linkage [-fpermissive]
static int16_t LSS::genericRead_Blocking_s16(uint8_t id, char * cmd)
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp: In static member function ‘static int16_t LSS::genericRead_Blocking_s16(uint8_t, char*)’:
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:325:96: warning: invalid conversion from ‘const char*’ to ‘char’ [-fpermissive]
cmdBufferSize = bus->readBytesUntil(LSS_CommandEnd, cmdBuffer, (LSS_MaxTotalCommandLength - 1));
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/HardwareSerial.h:106:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:46,
from C:\Users\ENANTE~1\AppData\Local\Temp\arduino_build_383318/pch/Arduino.h:6,
from C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.h:22,
from C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:12:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/Stream.h:57:9: note: initializing argument 1 of ‘size_t Stream::readBytesUntil(char, char*, size_t)’
size_t readBytesUntil(char terminator, char buffer, size_t length);
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:339:72: warning: format ‘%u’ expects argument of type 'unsigned int
’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
cmdBufferSize = sscanf(cmdBuffer, “%3u%1s%d”, &readID, ident, &value);
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:339:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:339:72: warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:339:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:344:72: warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
cmdBufferSize = sscanf(cmdBuffer, “%3u%2s%d”, &readID, ident, &value);
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:344:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:344:72: warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:344:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:349:72: warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
cmdBufferSize = sscanf(cmdBuffer, “%3u%3s%d”, &readID, ident, &value);
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:349:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:349:72: warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:349:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:354:72: warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
cmdBufferSize = sscanf(cmdBuffer, “%3u%4s%d”, &readID, ident, &value);
^
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:354:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:354:72: warning: format ‘%u’ expects argument of type ‘unsigned int*’, but argument 3 has type ‘volatile uint8_t* {aka volatile unsigned char*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:354:72: warning: format ‘%d’ expects argument of type ‘int*’, but argument 5 has type ‘int16_t* {aka short int*}’ [-Wformat=]
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp: At global scope:
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:390:67: warning: cannot declare member function ‘static char* LSS::genericRead_Blocking_str(uint8_t, char*)’ to have static linkage [-fpermissive]
static char * LSS::genericRead_Blocking_str(uint8_t id, char * cmd)
^
In file included from C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp:12:0:
C:\Users\ENantel - RobotShop\Documents\Arduino\libraries\LSS_Library_Arduino-master\src\LSS.cpp: In static member function ‘static char* LSS::genericRead_Blocking_str(uint8_t, char*)’:

Same as before, only the Position is getting a data.
Arduino 1.8.13
Teensyduino 1.53

I have checked but didn’t found where to download the Beta for Teensyduino

I’ve run the LSSTestServos but it get stuck at “Search for all servos”
Note: i have no warnings however

image

1 Like

@dialfonzo - Good Morning,

My guess is you did not switch to my branch associated with the Pull Request (compliler_warnings), and instead used my “master” branch, which should be a duplicate of the released one.

You might try again downloading my updated branch at: https://github.com/KurtE/LSS_Library_Arduino/tree/compiler_warnings

And see if that makes a differnce… You should not hopefully then see all of those messages.

1 Like

Sorry to hear that. @kurte If I want to connect the Teensy to the adapter board where do pins 0 and pin 1 (RX1/TX1) from the Teensy connect the adapter board ?

1 Like

WORKING - Indeed it was not the “compiler_warnings” version

1 Like

:smiley:

@dialfonzo and @cbenson - I might again suggest that you maybe do a quick check for the Arduino UNO to make sure nothing has broken and then Merge in the Pull Request and release a new version of the library

1 Like

Again assuming you have their LSS Adapter board, the wiring:


Pin 0 of Teensy goes to logical Pin 0 of the Arduino adapter. Ditto for Pin 1

Sorry for the quick and dirty clipboard cut/paste here, you also need a common ground wire.

Also you need someway to power everything. When I am working in a rigged setup like this, I often wallwart it.
So have 12v plugged into the Adapter board.

Note: However it shows the +5 and 3.3v on the Arduino Shield pins, however this board does not connect those pins up to voltages from this shield… So it is not setup to power the Teensy. The V pin does however get the voltage plugged in to the shield.

So my board then has it’s own power conversion DC/DC down to 5v to connect teensy. But in startup mode I don’t worry about that and instead simply plug the Teensy into computer and use that for the logic…

Hope that helps.

@kurte would you be able to upload the latest to the BETA hexapod Github (new folder)? We can start fresh from there which would be nice.
https://github.com/lynxmotionbeta/SES-V2-Hexapod-Beta

I’ll try to do that… :wink:

I just pushed up the library plus made some edits to change from Serial to Serial1 in examples…

Actually I changed them to use LSS_SERIAL which I defined as Serial1.

Later may go back and set default different if AVR…

@kurte Nice and clean. Thanks!

Hi All,

I was playing with the LSS to see if I could stop the motion using current sensing. I just gathered a few values before I could stop the motion using current sensing.

Current Sensing.
First tried incrementing the servos in smaller (100) and larger steps(400) to see how much current it draws. I was using a modified version of my Query code. I also wanted to check how accurate the position value is feedback.
the blue trace(value) is the commanded position whereas the orange(pos) is the value read back.

Increment by 100

Positional feedback accuracy
image
Current sensing
image
Looks like the current is fairly same except when there is direction of motion change.

Increment by 400
Positional feedback accuracy
image
Current sensing
image

In both instances the position value lags by one step. The error increases as the increment size increases. May be this can be made more accurate but I am reading immediately after commanding the servo. The baud rate is 115200. Should I increase it ?

Then I thought of adding a cardboard arm and checking how can I get the motor to stop based on current sensing. Did some modifications to my sketch and I could see that. Apologies for my makeshift leg and the mess. I have no brackets at the moment.

Applied a threshold of 200mA…When the arm presses against the table I hold the servo tightly in place so it does not move. and the servo soon stops its motion
image

I really liked the voltage monitoring on the servo as it is very useful thing to not have an additional hardware/software to monitor battery voltage.

2 Likes

Wow, nice values! :slight_smile:

Well, that is probably due to the coils (being inductors) resisting change momentarily.

I think you may be misinterpreting the data here. The error increases as the increment size increases.

If you are sending a “D” command followed by a “QD” command to any LSS, you’ll get the current virtual position.
If instead you want to know the current target virtual position, you need to send QDT!

This will only make what is happening even truer… :stuck_out_tongue: (i.e.: closer to the virtual position of the LSS before motion gets to start).
You could also send a Q command to read the status. Before a move command (but after a move command already settled/not limp), the status will be 6 (holding). But while in motion (after a “D” command but before reaching the target virtual position, a status query should return 3, 4 or 5 (accel [increasing speed], travel [constant speed], decel [reducing speed]).

You should increase it to the fastest speed your board can take that is at or below 500 kBaud. This allows the LSS to respond faster, too. Of course, don’t forget to first send to your bus something like #254CB500000\r (broadcast ID + config baud + 500 kBaud)!

During the beta when when we were all hunting down electrical issues and other problems with the LSS, we eventually completed all the solutions we could manage. And then we thought: “what is the worse case scenario we want to support?”. That was a full humanoid with many DoF at a high rate. So we setup a test with 36 LSS using many of the longest cables we offer (many Y-cables, too) and LSS Power Hub to connect all of them. While saturating the bus completely (100% capacity) we found 0 packet loss. That was success! :smiley:
image

That is a cool idea! :stuck_out_tongue:

Good! :slight_smile:

Yes, our thought exactly! Especially because the voltage on the LSS bus is usually far higher than what most microcontroller boards can read anyway (without a voltage divider or something similar), so this makes it trivial to read these values quickly.

Thanks @scharette

Yes … I agree…

I probably need to understand this part a bit better. What is a virtual position ?

I don’t think the “QDT” command is supported in the current version of the library. Do you want me to add this to the library code as
getPositionTarget ?

yes :stuck_out_tongue:

Thanks for this. I will read up aa bit more and experiment with this

That is awesome… !! Really cool! When was the beta for the servos and when were these servos released ?

1 Like

Thanks for the information @kurte. Quick and dirty is still quite good and very informative. I will try the Teensy next. I was having some fun with Arduino and the motors. This is the first time I am using motors which actually talk back to me :crazy_face: I was using the MG996R Tower Pro servos on my hexapod which when they move sounds like there is sand inside. Still good for someone like me on budget constraints I guess.

Here is the video of me stopping the servo travel based on current sensing. Added some LED colour change to show when the servo has stopped.

1 Like

The beta was done before the release (of course), maybe a bit more than half a year of total active time?

The release was, hmm, in May 2019 if memory serves? :open_mouth: :thinking: @cbenson totally knows this better than I do I’m sure! :smiley:

The blog says 2019-04-30… https://community.robotshop.com/blog/show/lynxmotion-launches-their-new-smart-servo-motors
The GitHub says 2019-05-09… https://github.com/Lynxmotion/LSS_Library_Arduino/commit/485745ef716c3be88e736341a91c4448f14cf3ba

So I guess May 2019 sounds like a good estimate after all! :smiley:

1 Like

Ah! And the launch video is 2019-04-29… hehehe!
Totally posting this here because it is awesome to watch again! :slight_smile:

3 Likes

The launch vide is pretty cool. I saw it on the robotshop page recently. Really amazing! Just curios though. How do these compare to the dynamixel servos. AX-12 or whatever. Those are very expensive. I guess Phoenix code uses that but as I said earlier I have never used any of those at all.

1 Like

For obvious reasons, capability comparisons probably best answered by RobotShop :wink:
Short answer - I think they are both good servos!

Costs… Depends, AX-12 sell for about $45, or their newer versions with about same And likewise about the same price of about $45 for their newer XL430-W250, they also now have some cheaper XLs as well… But then their prices jump up quickly for higher end servos like the XM ($230-$350+), and higher…

Hookup - Their servos work in half duplex mode - So the data is only flowing one direction or the other… They have two versions. Either normal TTL or they have RS-485 versions which allow longer distances (never tried them)

Firmware capabilities - Again I have only started to play with these for a bit, so hard to say. Some of the things I wish these (LSS) servos supported, was more ability to talk to multiple servos at the same time. But some of this could probably be enhanced by whoever is currently responsible for the servo firmware.

That is for example with Dynamixels I can send out one packet that says: On the following N servos, I wish to set the a few properties like location and speed, and they all act when the final checksum is received and verified by each servo. Likewise with protocol 2 servos they have the ability ask N servos for data, and each servo in that request waits for the previous servos to respond and they add their response…

For the first part we again had that capability with the SSC32 which they LSS servo communications is based on:
That is we could do things like: #1P500#2P400#3P600T250
And in this case the SSC-32 received all of this message and updated those 3 servos to start moving to their new positions to be completed in about a quarter of a second.

Again I have not seen the LSS servos firmware, but I would think it would not be hard to have each servo looking at these messages and see that they were mentioned, save their values in some local memory and only react when they receive the final CR…

Likewise I am not sure how hard it would be to allow you to send out query requests, like what is your current position, and speed… and send out this request in our case to all 18 servos and each servo when it hears this request, will try to try to make sure there is no collisions and recover when there is? My impression is you maybe can send multiple requests for the same servo without waiting, but must wait until all responses have come back from that servo for you might try a second servo?

But maybe not a big issue if we can run the servo baud rate fast enough?
Note: I am currently running my LSS servos at 250000 baud and I run my Dynamixels at 1000000 sometimes higher

Note: I have had servo drivers for the Phoenix code to work with Dynamixel servos for many years now, including some with the newer Dynamixels.

Also the code started off with a driver for the Lyxmotion SSC-32 as the first versions of this code was setup to run with the Lynxmotion board: http://www.lynxmotion.com/p-840-botboarduino.aspx which a couple of us designed and
was more or less an Arduino UNO crossed with a Bot Board 2… And ran on the Lynxmotion Phoenix: http://www.lynxmotion.com/c-117-phoenix.aspx which was designed by @zenta which is where the code base got it’s name.

I also had versions of it running directly to PWM like servos using a modified version of Servo library. Also had version that ran on Orion Servos (Basic Micro for a short time sold some robots…) And I know a few others have adapted as well to some other servo controllers, like ones from Pololu…

Sorry message probably too long again.

2 Likes