Society of Robots - Robot Forum

Electronics => Electronics => Topic started by: Gertlex on June 29, 2008, 05:11:37 PM

Title: Axon with miniSSC
Post by: Gertlex on June 29, 2008, 05:11:37 PM
Hey Admin, I'm looking through the uart4.c/h files, figuring out what methods to be used for sending commands to a MiniSSC II servo controller.  I've had partial success... A few things I'm wondering about those files in particular:
-What is the significance of u08 in those files... it's everywhere ;)
-For sending bytes, should I just be sending basic integers? unsigned integers? does uart2SendByte(127) properly call that function?  You don't list Byte as an actual variable type in the C variable tutorial.
-Or should I send them to buffer and send then send them in sets of three bytes?
-Do I need to connect grounds between two UART ports if I use a loop for testing?

There's a thread of mine in the programming forum about the Axon with another question or two, as well as some workarounds I found necessary.
Title: Axon with miniSSC
Post by: Admin on June 29, 2008, 09:18:43 PM
First, the uart.h and uart.c are files from the AVRlib, so you can find a lot of info on them if you google around.

u08 is basically an int

As for the SSC, I haven't used it before, but with a quick glance through the manual it appears you can just use the rprintf function to control it.

For example:

rprintf("SSCAT #0P2000T5000;<cr>");

This is how I control the Blackfin camera.
also, I noticed you had replied to this post quoting yourself, but not saying anything else . . . so I deleted that post . . .
Title: Axon with miniSSC
Post by: Gertlex on June 29, 2008, 09:24:09 PM
Dang.  I must have hit quote instead of modify...  I had added a few notes, including my discovery of what u08 was.

General forum suggestion: send people back to the thread they just posted in, rather than the sub-forum's index. I'd have caught that mistake otherwise :)
Title: Axon with miniSSC
Post by: Gertlex on July 09, 2008, 11:20:19 AM
As for the SSC, I haven't used it before, but with a quick glance through the manual it appears you can just use the rprintf function to control it.

For example:

rprintf("SSCAT #0P2000T5000;<cr>");

This is how I control the Blackfin camera.
Guess I'd best ask after pondering for days x_x

Is it relevant for me to understand what's inside the ()s of the example line you give there?  Cause I definitely don't :/

I've been working with writing bites via serial connection from VB.Net 2005 to the Axon, and then sending that back to Hyperterminal.  I've gotten some weird results... (I'm sure there's some logic to it, but i'm a newb... And i'll elaborate in some later post) I won't be able to test sending VB output directly to hypertrm until I get home from vacation though.

Also, is there a 128 byte limit on the receiving buffers on the Axon's UART?  Seems like it *shrug*

Edit: Actually it seems like the buffer discards the first byte in an array that I send, can store up to 132 bytes, and if it receives less than 132 bytes, it appends a byte with the value of 0. (And empty buffer values are -1).  There's too much odd stuff to describe (thus the strikethrough; 'tis a situational thing)
Title: Axon with miniSSC
Post by: Admin on July 09, 2008, 01:09:23 PM
Quote
Is it relevant for me to understand what's inside the ()s of the example line you give there?  Cause I definitely don't :/
I took that line exactly from the SSC datasheet, as specified in that datasheet.

rprintf("ssc command goes here");//send command to ssc

Quote
Also, is there a 128 byte limit on the receiving buffers on the Axon's UART?  Seems like it *shrug*

Edit: Actually it seems like the buffer discards the first byte in an array that I send, can store up to 132 bytes, and if it receives less than 132 bytes, it appends a byte with the value of 0. (And empty buffer values are -1)
hmmm to be honest, I do not know. I looked over the ATmega640 datasheet (http://www.atmel.com/dyn/products/product_card.asp?PN=ATmega640) but couldn't find buffer size. Anyone know?


I recommend looking at the rough draft Blackfin Camera source code that I included in the last source version release. At the very top is a function I use to parse data I get from the Blackfin Cam. Also notice the buffer flushing that it does - I'd occasionally get weird data results if I didn't flush after ever use . . . errr no pun intended . . . The comments should roughly explain how it works. Basically, using your SSC and using the Blackfin require very similar code on the Axon.
Title: Axon with miniSSC
Post by: dunk on July 09, 2008, 03:54:20 PM
Quote
Also, is there a 128 byte limit on the receiving buffers on the Axon's UART?  Seems like it *shrug*
there is only a one byte buffer on AVR UARTs.
the buffer is implemented in firmware.
as such you can make the buffer as big as your free memory stack.

dunk.
Title: Axon with miniSSC
Post by: Gertlex on July 11, 2008, 08:34:43 AM
Just a clarification: the buffer limit isn't any problem for me, it's just something I encountered while experimenting with UART funsies.  I won't run into said problem with any actual robot code :)
Title: Axon with miniSSC
Post by: Gertlex on July 21, 2008, 07:58:11 PM
Quote
Is it relevant for me to understand what's inside the ()s of the example line you give there?  Cause I definitely don't :/
I took that line exactly from the SSC datasheet, as specified in that datasheet.

rprintf("ssc command goes here");//send command to ssc

(Avoided further testing with Mini SSC for week and a half to avoid true frustration :P)

I can't find either of the lines you reference in any SSC datasheet I know of; certainly nothing in the official datasheet/manual files (at http://seetron.com/ssc.htm )

I've tried various methods of sending data with no success (BAUD rate is set correctly, of course).  The following are one line examples of attempts to send data:
Code: [Select]
v1 = 0xFF; //255 in hex (v1 is a char, and compiler doesn't complain)
rprintf("%x",v1);
rprintf("255");
rprintf("%c",v1);
rprintfChar(0xFF);

I admit to not being certain how to use the hex %x variable (or even %c, I suppose; I know what they're for, but not how)

I'm thinking maybe I ought to do the Solidworks version of the Axon for you, and in exchange mail you the MiniSSC and let you apply your skills :)
Title: Re: Axon with miniSSC
Post by: Admin on July 21, 2008, 09:17:09 PM
[I split your topic to a new thread]

oooohhhh I thought you were using this:
http://www.lynxmotion.com/Product.aspx?productID=395
(next time link us over sooner :P)


Ok starting from the top . . . whats your baud rate? Using 9600bps, right?

Now try this code:

Code: [Select]
rprintfInit(uart0SendByte);//set to use uart0
uartSetBaudRate(0, 9600); //set baud rate

//<255 (sync)> <servo#> <position>
rprintf("255,5,200"); //moves servo number 5 to position 200

if you want to send a number by using a variable, just do this:
Code: [Select]
axon=1;
rprintf("I love my Axon: %d",axon);
rprintf("Look! %d Two variables! %d", axon, squirrel);

let me know how that goes . . .
Title: Re: Axon with miniSSC
Post by: Gertlex on July 22, 2008, 09:59:21 AM
Heh...  the new thread threw me off for a bit.  But I certainly don't object.

Your code didn't succeed in communicating with the MiniSSC.

One thing from the MiniSSC manual that seems relevant here is the following:
Quote
"[The bytes] must be sent as individual byte values, not as text representations of numbers as y ou might type at a terminal." (page 4 of manual)
Title: Re: Axon with miniSSC
Post by: Admin on July 22, 2008, 10:28:20 AM
hmmm I'm not entirely sure what they mean by that . . .

try this:
Code: [Select]
rprintf("%c %c %c",255, 5, 200);
if that doesn't work, try:
Code: [Select]
//&0x0F strips ascii off to use in char strings
rprintf("%c %c %c",255 & 0x0F, 5 & 0x0F, 200 & 0x0F);


If neither works, I'd suspect perhaps you have a hardware issue. Are your grounds common? What does the oscope say on both the UART line and servo signal line? Sure you used the correct battery voltages?

Failing that, do they have customer support?

I'm sure a professional programmer can figure this out (hint hint, anyone!)
Title: Re: Axon with miniSSC
Post by: pomprocker on July 22, 2008, 11:04:39 AM
at 2400 or 9600 baud it wants byte values sent one at a time serially, not TTL

"unsigned char" is 8-bits/1-byte ranges from 0 to 255

unsigned char SyncUp = 255;
unsigned char ServoNum = 0;
unsigned char ServoPos = 0;

or you could use u08 data type which makes it take up a byte of space

u08 SyncUp = 255;
u08 ServoNum = 0;
u08 ServoPos = 0;

rprintf(SyncUp, ServoNum, ServoPos);


or try this:

u08 SyncUp = 11111111;
u08 ServoNum = 00000000;
u08 ServoPos = 00000000;
rprintf(SyncUp);
delay_us(2);
rprintf(ServoNum);
delay_us(2);
rprintf(ServoPos);




Title: Re: Axon with miniSSC
Post by: Gertlex on July 22, 2008, 03:01:35 PM
Nothing working so far.

I know the MiniSSC is fine, as it still works when controlled with VB.Net using actual serial communication.

I don't own an oscilloscope, alas.

pomprocker, your suggestions don't quite work.  The compiler didn't like setting the u08 vars with individual bit values, or your method of using rprintf.  rprintf has to have the format
Code: [Select]
rprintf("blah", var1, var2, etc);
Tricky little beast...
Title: Re: Axon with miniSSC
Post by: pomprocker on July 22, 2008, 03:18:26 PM
try quoting your values

u08 SyncUp;
SyncUp = "255";

rprintf("%c", SyncUp);
Title: Re: Axon with miniSSC
Post by: Gertlex on July 22, 2008, 03:24:18 PM
u08 SyncUp;
SyncUp = 255;

rprintf("%c", SyncUp);


Had done that modification prior to my last post; doesn't work :/
Title: Re: Axon with miniSSC
Post by: pomprocker on July 22, 2008, 03:25:37 PM
just modified my above post....try quotes

or theres a function you can call from uart.h

uartSendByte('255');


 void uartSendByte(u08 txData)
 {
     // wait for the transmitter to be ready
     while(!uartReadyTx);
     // send byte
     outb(UDR, txData);
     // set ready state to FALSE
     uartReadyTx = FALSE;
 }


edit: pffff rprintf is setup to use that function

rprintf('255');
Title: Re: Axon with miniSSC
Post by: pomprocker on July 22, 2008, 03:52:20 PM
"[The bytes] must be sent as individual byte values, not as text representations of numbers as y ou might type at a terminal." (page 4 of manual)


i think this has to do with endianess, i think it wants
2
5
5

0

0




When endianness affects code

Endianness doesn't apply to everything. If you do bitwise or bitshift operations on an int, you don't notice the endianness. The machine arranges the multiple bytes, so the least significant byte is still the least significant byte, and the most significant byte is still the most significant byte.

Similarly, it's natural to wonder whether strings might be saved in some sort of strange order, depending on the machine. To understand this, let's go back to the basics of an array. A C-style string, after all, is still an array of characters. Each character requires one byte of memory, since characters are represented in ASCII. In an array, the address of consecutive array elements increases. Thus, &arr is less than &arr[i+1]. Though it isn't obvious, if something is stored with increasing addresses in memory, it's going to be stored with increasing "addresses" in a file. When you write to a file, you usually specify an address in memory and the number of bytes you wish to write to the file starting at that address.

For example, suppose you have a C-style string in memory called man. Assume that m is stored at address 1000, a at address 1001, and n at address 1002. The null character \0 is at address 1003. Since C-style strings are arrays of characters, they follow the rules of characters. Unlike int or long, you can easily see the individual bytes of a C-style string, one byte at a time. You use array indexing to access the bytes (characters) of a string. But you can't easily index the bytes of an int or long without playing some pointer tricks. The individual bytes of an int are more or less hidden from you.

Now imagine writing out this string to a file using some sort of write() method. You specify a pointer to m and the number of bytes you wish to print (in this case four). The write() method proceeds byte by byte in the character string and writes it to the file, starting with m and working to the null character.

Given this explanation, it's clear that endianness doesn't matter with C-style strings.

Endianness does matter when you use a type cast that depends on a certain endian being in use. One example is shown in Listing 4, but keep in mind that there are many different type casts that can cause problems.

Listing 4. Forcing a byte order

               
unsigned char endian[2] = {1, 0};
short x;
 
x = *(short *) endian;


What would be the value of x? Let's look at what this code is doing. You're creating an array of two bytes, and then casting that array of two bytes into a single short. By using an array, you basically forced a certain byte order, and you're going to see how the system treats those two bytes.

If this is a little-endian system, the 0 and 1 is interpreted backwards and seen as if it is 0,1. Since the high byte is 0, it doesn't matter and the low byte is 1, so x is equal to 1.

On the other hand, if it's a big-endian system, the high byte is 1 and the value of x is 256.

Determine endianness at run time

One way to determine endiannes is to test the memory layout of a predefined constant. For example, you know that the layout of a 32-bit integer variable with a value of 1 is 00 00 00 01 for big-endian and 01 00 00 00 for little-endian. By looking at the first byte of the constant, you can tell the endianness of the running platform and then take the appropriate action.

Listing 5 tests the first byte of the multi-byte integer i to determine if it is 0 or 1. If it is 1, the running platform is assumed to be little-endian. If it is 0, it is assumed to be big-endian.

Listing 5. Determine endianness

               
const int i = 1;
#define is_bigendian() ( (*(char*)&i) == 0 )

int main(void) {
    int val;
    char *ptr;
    ptr = (char*) &val;
    val = 0x12345678;
    if (is_bigendian()) {
        printf(“%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
    } else {
        printf(“%X.%X.%X.%X\n", u.c[3], u.c[2], u.c[1], u.c[0]);
    }
    exit(0);
}




Title: Re: Axon with miniSSC
Post by: pomprocker on July 22, 2008, 04:03:14 PM
that being said try stuff like this:


unsigned char SyncUp[3] = {2, 5, 5};
rprintf('%c', SyncUp);


or try
rprintf('%d, %d, %d', 2, 5, 5);

or

rprintf('%d', 2);
rprintf('%d', 5);
rprintf('%d', 5);

since rprintf uses uartSendByte, even though its only an integer it sends it as a byte.
Title: Re: Axon with miniSSC
Post by: pomprocker on July 22, 2008, 04:26:44 PM
a byte is 8 bits, you can convert a number into a byte using the _BV() macro provided in io.h/sfr_defs.h


u08 a = _BV(2);

would make a equal the byte '00000010'
5 would be '00000101'

or

255 is '11111111'

etc...
Title: Re: Axon with miniSSC
Post by: Gertlex on July 22, 2008, 07:03:41 PM
_BV() doesn't like it if I give it more than a one digit number. It gives a warning:
Axon.c:107: warning: left shift count >= width of type

Doing the u08 blah = "255" and similar yields a warning as well:
Axon.c:115: warning: initialization makes integer from pointer without a cast
And this latter approach doesn't work.

_BV() is sending some sort of signal that the MiniSSC is interpretting.  Catch is, it's not quite acting properly either.

The program is set up with three possible results when the button is pressed, controlled by a simple counter and if statements.
On the first click, LED flashes once, and the following code is run:
Code: [Select]
u08 aa = _BV(255);
u08 bb = _BV(2);
u08 cc = _BV(100);
rprintf("%c",aa);
delay_us(2);
rprintf("%c",bb);
delay_us(2);
rprintf("%c",cc);
counter ++;
LED_flash(1);
The MiniSSC's LED does a quick flash on and off, indicating that it has received a sync byte, servo address, and position byte.  However, it doesn't move servo 2 (really the third servo). Rather, a servo connected to 0 is moved to it's maximum position counter clockwise, and the servo then continues to vibrate slightly.  This would seem to indicate that the mini SSC is telling the servo to go beyond it's limit (i.e. a PWM length greater than 1200, maybe?)

Clicks two and three send "aa," and "bb" & "cc" respectively. (was testing to see if the number of bytes sent at once made a difference... sort of does)

This is pretty much identical behavior to what I was getting when I first tried this, using uart2sendByte().  In both cases, I have the Mini SSC's LED flashing on random button presses.  The MiniSSC's LED flashes on every first button press, and randomly on second and third (were it to flash with every set of 3, starting with a 255 byte, it would flash on every first and third button press... thus my calling it's contrary behaviour "random")

I'm tempted to go back to trying to interpret the bytes that the Axon receives from my working VB.NET program.  (That didn't go well the previous time, either)