Legacy Forum: Preserving Nearly 20 Years of Community History - A Time Capsule of Discussions, Memories, and Shared Experiences.

libavr/libbioloid C library for CM5 released!

Bioloid robot kit from Korean company Robotis; CM5 controller block, AX12 servos..
289 postsPage 2 of 201, 2, 3, 4, 5 ... 20
289 postsPage 2 of 201, 2, 3, 4, 5 ... 20

Post by brijesh » Sat Dec 20, 2008 9:03 pm

Post by brijesh
Sat Dec 20, 2008 9:03 pm

I meant why reimplement the functionality of sprintf()?
Did you need some particular feature that was not available in sprintf()?
I meant why reimplement the functionality of sprintf()?
Did you need some particular feature that was not available in sprintf()?
brijesh
Newbie
Newbie
Posts: 4
Joined: Tue Sep 02, 2008 7:51 pm

Post by RandomMatt » Sat Dec 20, 2008 11:31 pm

Post by RandomMatt
Sat Dec 20, 2008 11:31 pm

While you can implement printf() in terms using sprintf() you end up using a lot of memory as a string buffer.

Given the exact design of the (already written) uart_*() functions, it didn't seem sensible to use the avr-libc version of printf() (which would have required faffing around with FILE *). So I just implemented printf() from scratch - which as you can see isn't that hard.

As an aside: (After the decisions above) I've removed any code dependency on avr-libc, and therefore a dependency on gcc. Basically I'd like to use a compiler other than gcc (to escape the many compiler bugs that have wasted weeks of my life).
While you can implement printf() in terms using sprintf() you end up using a lot of memory as a string buffer.

Given the exact design of the (already written) uart_*() functions, it didn't seem sensible to use the avr-libc version of printf() (which would have required faffing around with FILE *). So I just implemented printf() from scratch - which as you can see isn't that hard.

As an aside: (After the decisions above) I've removed any code dependency on avr-libc, and therefore a dependency on gcc. Basically I'd like to use a compiler other than gcc (to escape the many compiler bugs that have wasted weeks of my life).
RandomMatt
Savvy Roboteer
Savvy Roboteer
Posts: 117
Joined: Sat Dec 20, 2008 11:16 pm

Post by RandomMatt » Sun Dec 21, 2008 11:18 am

Post by RandomMatt
Sun Dec 21, 2008 11:18 am

...

On the subject of printf() and memory use, my printf() supports the non-standard %S (in addition to the standard %s). %S is used in the same way to %s, but the string is kept in flash memory rather than ram - which is very useful when you're trying to avoid excessive ram use.

Another difference between my and the standard printf() is the location of the format string. My printf() ensures the format string is in flash - which also helps minimise ram use. (You might want to look here for a description of the issue http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_flashstrings).
...

On the subject of printf() and memory use, my printf() supports the non-standard %S (in addition to the standard %s). %S is used in the same way to %s, but the string is kept in flash memory rather than ram - which is very useful when you're trying to avoid excessive ram use.

Another difference between my and the standard printf() is the location of the format string. My printf() ensures the format string is in flash - which also helps minimise ram use. (You might want to look here for a description of the issue http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_flashstrings).
RandomMatt
Savvy Roboteer
Savvy Roboteer
Posts: 117
Joined: Sat Dec 20, 2008 11:16 pm

Post by srobot » Sun Dec 21, 2008 5:54 pm

Post by srobot
Sun Dec 21, 2008 5:54 pm

Thank you Stuart and Random Matt!

Looks great, it will be cool to see some projects done with this.
Thank you Stuart and Random Matt!

Looks great, it will be cool to see some projects done with this.
Dell Latitude D520, Windows XP, 4 GB RAM, 80 GB HDD, Intel Core 2 Duo. The power that's needed!

RIBO Labs, Springing Robotic Development to a New Level
srobot
Savvy Roboteer
Savvy Roboteer
User avatar
Posts: 401
Joined: Sun Dec 10, 2006 1:00 am
Location: Deep in robot parts

Post by BillB » Mon Dec 22, 2008 12:56 am

Post by BillB
Mon Dec 22, 2008 12:56 am

I have a question that I am hoping you (StuartL/RandomMatt) could help me with. I am planning to port my Hexapod IK code to the CM5 (and finally be free of the PC tether) but am not sure how I should approach the timing to ensure a smooth gait.

I will need to update the servo positions on a regular basis (> 30 Hz), in order to calculate the positions of the servos my code will need to know how much time has elapsed since a previous milestone/reset.

Something like:

CurrentLegPosition = (StartingLegPosition + (ElapsedTime * Velocity)) % StrideLength

So my question is how can I obtain the ElapsedTime. What is the best way to do his - is there a register I should read? can I use the 'tick' integer in the timer.c finle of your library? Do I need to commandeer one of the Interrupt/Timers?

Please help.

I apologise again if it seems a elementary question, but I could do it with my eyes shut for a PC MFC/.Net application in 3 different programming languages, but I am finding that programming the CM5 is a whole new way of thinking.
I have a question that I am hoping you (StuartL/RandomMatt) could help me with. I am planning to port my Hexapod IK code to the CM5 (and finally be free of the PC tether) but am not sure how I should approach the timing to ensure a smooth gait.

I will need to update the servo positions on a regular basis (> 30 Hz), in order to calculate the positions of the servos my code will need to know how much time has elapsed since a previous milestone/reset.

Something like:

CurrentLegPosition = (StartingLegPosition + (ElapsedTime * Velocity)) % StrideLength

So my question is how can I obtain the ElapsedTime. What is the best way to do his - is there a register I should read? can I use the 'tick' integer in the timer.c finle of your library? Do I need to commandeer one of the Interrupt/Timers?

Please help.

I apologise again if it seems a elementary question, but I could do it with my eyes shut for a PC MFC/.Net application in 3 different programming languages, but I am finding that programming the CM5 is a whole new way of thinking.
BillB
Savvy Roboteer
Savvy Roboteer
User avatar
Posts: 232
Joined: Sun Aug 06, 2006 1:00 am
Location: Hampshire, UK

Post by RandomMatt » Mon Dec 22, 2008 9:13 am

Post by RandomMatt
Mon Dec 22, 2008 9:13 am

The way we do it is to run the main loop at exactly HZ (defaults to 40) times a second:

Code: Select all
for(;;) {
    //calculations and stance update
    dx_setstance(&s);
    timer_delay(1);
}


If you want high resolution timing (useful for profiling the code on the CM5), you can use clock_start() and clock(). clock() tells you how many ticks at 2MHz have passed, clock_start() resets that value to zeroish (the function call overhead is significant when measuring things at 2MHz).
The way we do it is to run the main loop at exactly HZ (defaults to 40) times a second:

Code: Select all
for(;;) {
    //calculations and stance update
    dx_setstance(&s);
    timer_delay(1);
}


If you want high resolution timing (useful for profiling the code on the CM5), you can use clock_start() and clock(). clock() tells you how many ticks at 2MHz have passed, clock_start() resets that value to zeroish (the function call overhead is significant when measuring things at 2MHz).
RandomMatt
Savvy Roboteer
Savvy Roboteer
Posts: 117
Joined: Sat Dec 20, 2008 11:16 pm

Post by RandomMatt » Mon Dec 22, 2008 9:33 am

Post by RandomMatt
Mon Dec 22, 2008 9:33 am

in the quadruped, the first line of calculations reads:

Code: Select all
speed = magnitude of psx controller stick;
c += speed;
c %= 400;


and then I treat c as your "(ElapsedTime * Velocity)". The advantage of doing it my way (i.e. moving the % operator towards the inside of the calculation) is that it makes it easier to avoid overflowing an integer. (The disadvantage is slightly harder to read code).
in the quadruped, the first line of calculations reads:

Code: Select all
speed = magnitude of psx controller stick;
c += speed;
c %= 400;


and then I treat c as your "(ElapsedTime * Velocity)". The advantage of doing it my way (i.e. moving the % operator towards the inside of the calculation) is that it makes it easier to avoid overflowing an integer. (The disadvantage is slightly harder to read code).
RandomMatt
Savvy Roboteer
Savvy Roboteer
Posts: 117
Joined: Sat Dec 20, 2008 11:16 pm

Post by BillB » Tue Dec 23, 2008 12:03 am

Post by BillB
Tue Dec 23, 2008 12:03 am

Thanks Matt - it all makes perfect sense.

Your code really does make programming the CM5 much easier. I get more impressed the more I use it.

I notice you have tabulated the trig tables - good move, especially since they are scaled to 255 and are in Servo Units (as opposed to degrees/Rads). I am sure that this will make life easier, but for now I will revisit my Inverse Kinematic calculations to make best use of your lookup tables (and to minimise the expensive Square rooting in the Law of Cosines calculation).

Thanks again Matt

Bill
Thanks Matt - it all makes perfect sense.

Your code really does make programming the CM5 much easier. I get more impressed the more I use it.

I notice you have tabulated the trig tables - good move, especially since they are scaled to 255 and are in Servo Units (as opposed to degrees/Rads). I am sure that this will make life easier, but for now I will revisit my Inverse Kinematic calculations to make best use of your lookup tables (and to minimise the expensive Square rooting in the Law of Cosines calculation).

Thanks again Matt

Bill
BillB
Savvy Roboteer
Savvy Roboteer
User avatar
Posts: 232
Joined: Sun Aug 06, 2006 1:00 am
Location: Hampshire, UK

Post by BillB » Tue Dec 23, 2008 12:16 am

Post by BillB
Tue Dec 23, 2008 12:16 am

Is there a streamlined way to transfer the compiled .Hex file to the CM5.?

Ideally a command line utility that can connect and transfer .Hex files to the CM5. At the moment I transfer the .Hex file using a terminal emulator, which can get very tedious. I can't help thinking that it is probably the same set of bytes being sent to the CM5 to prepare it for the download followed by the .Hex file followed by a checksum.

If I find the time I will setup a port sniffer and verify that this is the case (and capture byte sequence)- but do not want to reinvent the wheel if someone has done it already.
Is there a streamlined way to transfer the compiled .Hex file to the CM5.?

Ideally a command line utility that can connect and transfer .Hex files to the CM5. At the moment I transfer the .Hex file using a terminal emulator, which can get very tedious. I can't help thinking that it is probably the same set of bytes being sent to the CM5 to prepare it for the download followed by the .Hex file followed by a checksum.

If I find the time I will setup a port sniffer and verify that this is the case (and capture byte sequence)- but do not want to reinvent the wheel if someone has done it already.
BillB
Savvy Roboteer
Savvy Roboteer
User avatar
Posts: 232
Joined: Sun Aug 06, 2006 1:00 am
Location: Hampshire, UK

Post by RandomMatt » Tue Dec 23, 2008 8:36 am

Post by RandomMatt
Tue Dec 23, 2008 8:36 am

To automatically program the cm5 you need to a program that:

sends "#" characters until it receives a "#" back
send an "l"
send the bytes from the .bin file - not the .hex file
send the checksum* byte
wait a bit (this signals to the cm5 the end of the image)
read the "Checksum:" line and determine success of failure

* the checksum byte is an extra byte no included in the .bin (or .hex) file and is simply the lower 8 bits of the sum of all the bytes in the .bin file.

(all from memory - so sorry if i have made a mistake)
To automatically program the cm5 you need to a program that:

sends "#" characters until it receives a "#" back
send an "l"
send the bytes from the .bin file - not the .hex file
send the checksum* byte
wait a bit (this signals to the cm5 the end of the image)
read the "Checksum:" line and determine success of failure

* the checksum byte is an extra byte no included in the .bin (or .hex) file and is simply the lower 8 bits of the sum of all the bytes in the .bin file.

(all from memory - so sorry if i have made a mistake)
RandomMatt
Savvy Roboteer
Savvy Roboteer
Posts: 117
Joined: Sat Dec 20, 2008 11:16 pm

Post by RandomMatt » Tue Dec 23, 2008 8:42 am

Post by RandomMatt
Tue Dec 23, 2008 8:42 am

whoops...

step 2: you need to send an "l" followed by a <CR>

(although when flashing an AX12 you must not send that <CR>)
whoops...

step 2: you need to send an "l" followed by a <CR>

(although when flashing an AX12 you must not send that <CR>)
RandomMatt
Savvy Roboteer
Savvy Roboteer
Posts: 117
Joined: Sat Dec 20, 2008 11:16 pm

Post by StuartL » Tue Dec 23, 2008 8:44 am

Post by StuartL
Tue Dec 23, 2008 8:44 am

Feel safe in the knowledge that Matt's programming habits mirror his forum posting habits.

One 'post' with useful, usually genius, content. A second 'post' to correct all the mistakes in the first...

*runs and hides from Matt*
Feel safe in the knowledge that Matt's programming habits mirror his forum posting habits.

One 'post' with useful, usually genius, content. A second 'post' to correct all the mistakes in the first...

*runs and hides from Matt*
StuartL
Savvy Roboteer
Savvy Roboteer
Posts: 350
Joined: Mon Jun 04, 2007 3:46 pm
Location: Thatcham, Berkshire, UK

Post by RandomMatt » Tue Dec 23, 2008 7:26 pm

Post by RandomMatt
Tue Dec 23, 2008 7:26 pm

Bill: for what it is worth... I do have some (c) code that does the CM5 flashing - but it isn't yet cross-platform. When I get around-to-it I'll publish it as part of the libbioloid distribution (although it'll probably end up depending on libcompat, which I'll publish at the same time).

Also, as you may (or may not) have noticed I've been making small improvements to both libavr and libbioloid - so you may want to download the newer ones. The biggest new feature is the absence of bugs (particularly noticable in the 'm' command from the supervisor), and secondly the ability to easily change a few constants (like HZ).

For example, if you add -DHZ=30 to the (right of the) CFLAGS_AVR line (with a more recent libbioloid than 920) you'll get ticks that run at 30Hz. And therefore a tick_delay(1) that'll delay you until the start of the next 30Hz 'frame'.

Stuart: you are wrong... I commit a barely working bit of code and then at least 10-20 minor patches (not 1).
Bill: for what it is worth... I do have some (c) code that does the CM5 flashing - but it isn't yet cross-platform. When I get around-to-it I'll publish it as part of the libbioloid distribution (although it'll probably end up depending on libcompat, which I'll publish at the same time).

Also, as you may (or may not) have noticed I've been making small improvements to both libavr and libbioloid - so you may want to download the newer ones. The biggest new feature is the absence of bugs (particularly noticable in the 'm' command from the supervisor), and secondly the ability to easily change a few constants (like HZ).

For example, if you add -DHZ=30 to the (right of the) CFLAGS_AVR line (with a more recent libbioloid than 920) you'll get ticks that run at 30Hz. And therefore a tick_delay(1) that'll delay you until the start of the next 30Hz 'frame'.

Stuart: you are wrong... I commit a barely working bit of code and then at least 10-20 minor patches (not 1).
RandomMatt
Savvy Roboteer
Savvy Roboteer
Posts: 117
Joined: Sat Dec 20, 2008 11:16 pm

Post by billyzelsnack » Tue Dec 23, 2008 8:37 pm

Post by billyzelsnack
Tue Dec 23, 2008 8:37 pm

RandomMatt wrote:Stuart: you are wrong... I commit a barely working bit of code and then at least 10-20 minor patches (not 1).


Release early, release often. FTW!
RandomMatt wrote:Stuart: you are wrong... I commit a barely working bit of code and then at least 10-20 minor patches (not 1).


Release early, release often. FTW!
billyzelsnack
Savvy Roboteer
Savvy Roboteer
User avatar
Posts: 618
Joined: Sat Dec 30, 2006 1:00 am

Post by BillB » Wed Dec 24, 2008 12:16 am

Post by BillB
Wed Dec 24, 2008 12:16 am

After a session of debugging a modified version of the example.c code here are 2 quick tips for anyone using the LibBioloid.

Tip 1: The servo units are in the range -512 to +511 and not 0 to 1023 (as used in the BCP & Motion Editor).

The servo range can be adjusted back to the 0 to 1023 range by modifying the SERVO_MIN, SERVO_CENTRE and SERVO_MAX constants in dynamixel.h to 0,0,1023 respectively.

Tip 2: If you have built your code on the Example.c and your servos are not reaching the intended position then it may because the line beginning "const robot_t FLASH robot" is limiting the servo angles.

Matt - it may be worth setting the range in lines 21 & 22 to SERVO_MIN and SERVO_MAX in the example.c file.
After a session of debugging a modified version of the example.c code here are 2 quick tips for anyone using the LibBioloid.

Tip 1: The servo units are in the range -512 to +511 and not 0 to 1023 (as used in the BCP & Motion Editor).

The servo range can be adjusted back to the 0 to 1023 range by modifying the SERVO_MIN, SERVO_CENTRE and SERVO_MAX constants in dynamixel.h to 0,0,1023 respectively.

Tip 2: If you have built your code on the Example.c and your servos are not reaching the intended position then it may because the line beginning "const robot_t FLASH robot" is limiting the servo angles.

Matt - it may be worth setting the range in lines 21 & 22 to SERVO_MIN and SERVO_MAX in the example.c file.
BillB
Savvy Roboteer
Savvy Roboteer
User avatar
Posts: 232
Joined: Sun Aug 06, 2006 1:00 am
Location: Hampshire, UK

PreviousNext
289 postsPage 2 of 201, 2, 3, 4, 5 ... 20
289 postsPage 2 of 201, 2, 3, 4, 5 ... 20