Followers

Recent Posts

Friday, January 29, 2010

Come with me - if you want to live.

I finally watched Terminator Salvation the other night.

I couldn't work out if the machines actually knew who Kyle Reese was or why they wanted to capture him - and also why they didn't just kill him when they had the chance!

There was also the matter of how lightly guarded skynet central was (despite apparently producing about 1 T800 per second), and how those motorcycle robots were supposed to get up if someone knocked them over.

What I really wanted to talk about though, was the Robopocalypse. Not so much the idea that robots will eventually rise up against their human masters, but just about how robots (or any machine) can be dangerous if people are careless around them.

I used to be vice-president of the Sydney University Mechatronics Organization, which held a yearly robot wars competition. Now, as you can imagine, robots designed to tear each other to bits would be equally (more?) effective at maiming pathetic squishy humans, so it was hard to disregard OH&S.

Despite a strong emphasis on safety, the university was in a difficult position when it came to allowing students to use their facilities. If we were injured in one of the workshops or laboratories, then the uni was liable - even if we were being properly supervised or if it was due to our own negligence. However, if we attempted to work on the robot outside of the university, we were without the appropriate tools and safety equipment and were significantly more likely to injure ourselves. This created many headaches and administrative woes, which ultimatley turned what should have been a fun and simple activity for students into a legislative nightmare.

This is why I am so much in favor of the smaller and safer robo-one style competition. I think it is a more elegant form of robot combat, for a more civilized age.





This video is from a new humanoid competition called RT Corp under 1kg Robot Fight. Like robo-one, it emphasizes lightweight robots which wrestle each other in a ring.

I think that this is a better direction for schools and universities who want to encourage students to learn about robots and mechatronics while having a bit of fun.

  1. Robot wars robots are glorified remote control cars. There, I said it. Many designs, like wedges or saws don't need any additional circuitry to control their weapons. The design is primarily in the mechanical field, and students will learn very little about the electrical or software side.
  2. It's so much safer. There are no dangerous weapons, and the weight limit is also much lower (unless you're these guys). The machining process is also much simpler (use tin-snips instead of table saws, solder instead of welding, etc).
  3. You get to keep your robot at the end. One of the most annoying things about robot wars is that if you lost, your robot was toast. Nothing gets damaged or destroyed in a wrestling match, so you are free to upgrade and modify parts for next time.
  4. The emphasis is on design and technique, not raw power. Software, real-time control, electrical systems and weight distribution are just as important as how strong your motors are.
  5. It's just as exciting. Robots can take their inspiration from boxing, tae-kwon do, ju-jitsu, MMA, akido, pancrase or any other type of martial art.

    The biggest drawback is that it can be quite expensive to build these little guys, but probably not by a huge margin. Our 13kg Robot wars Robots cost $300-500 (excluding the remote controls, which were borrowed), but I can see a under 1kg robot being build for a similar amount.

    If that doesn' convince you, just look at how much fun these guys are having!



    Wednesday, January 27, 2010

    It's not a bug, it's a feature

    Mystery solved!

    Here is a quote from the avrlibc documentation (which I probably should have looked at earlier):

    In order for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an expression that is a known constant at compile-time. If these requirements are not met, the resulting delay will be much longer (and basically unpredictable), and applications that otherwise do not use floating-point calculations will experience severe code bloat by the floating-point library routines linked into the application.

    This describes exactly the symptoms I was experiencing - if the function was passed a constant, it worked flawlessly. If I was using a value fetched from program memory, then the compiler was unable to determine how many NOPs should be performed and the delay was unpredictable.

    I don't really know why the library function requires prior knowledge of how long a delay should last. All a spin loop does is keep the processor busy for a set number of cycles. If you need longer, you can simply put another loop around the first loop to multiply it's effects. Sure, without careful calculations you can lose your nanosecond accuracy, but when you are working in the millisecond range it is usually unimportant if you are off by a few clock cycles.

    If you want the best accuracy, you should be using a timer or counter interrupt anyway...

    ..but that's a story for another night. I don't intend to be using spin loops for future versions anyway.

    Thanks to the people who emailed me and suggested that I might be accidentally passing the value of the pointer to the function, instead of the dereferenced value. That would also explain the strange behaviour, but it would also have shown up in the compiler output.

    In other news - what's up with the horrible popup?

    If you don't live in Australia (or perhaps even if you do) you might be unaware that the Australian government is considering introducing mandatory filtering of internet sites.

    Much like draconian airport security, national identity cards and racial profiling, this filter is supposed to be being put in place for our "protection". Because apparently Australians can't be trusted with unregulated free speech and freedom of information.

    I understand that some people are willing to sacrifice their personal liberties for the comforting feeling of saftey, but the problem is not with the filter as it exists now, but what it could become.

    First they came for the communists, and I did not speak out—because I was not a communist;
    Then they came for the trade unionists, and I did not speak out—because I was not a trade unionist;
    Then they came for the Jews, and I did not speak out—because I was not a Jew;
    Then they came for me—and there was no one left to speak out.

    Monday, January 25, 2010

    Byte by byte

    Here are a few things which might aid you in your detective work.

    First of all, I am still using avr-gcc and avrlibc to build the code. To achieve this, you first need to:

    compile,
    avr-gcc -mmcu=atmega128 -I. -g -Wall -Os -c *.c

    link,
    avr-gcc -o main.elf -mmcu=atmega128 *.o

    and then pack
    avr-objcopy -j .text -O ihex main.elf main.hex

    Then download the resulting .hex file using the RBCUpgradeTool. Note that you can simply switch the RBC block off and on, rather than messing around with the reset pin.

    This should help anyone who is trying to get to the bottom of the mystery I spoke about earlier. I also promised to talk a little about transferring data from the program space into working memory.

    Unlike desktop computers, embedded systems are built according to the Harvard Architecture which keeps the program instructions separate from the working memory. They even have separate buses, which means that an opcode and an operand can be fetched on a single clock cycle. In normal operation, there is no need to exchange data between the two areas of memory, since self modifying code has been all but banished to the history books.

    Sometimes, you find yourself running out of working memory especially if you are storing large tables or arrays which will eat up the free addresses very quickly. Also beware of memory leaks. Unlike a desktop with an operating system, your program won't segfault or blue-screen to let you know something is wrong - it will probably just start suddenly spewing garbage.

    However, if you absolutley must use giant arrays or matricies in your program, you can keep your RAM free by storing them in the program memory and then copy it out only when you need to use it. This is done by using the LMP (LoadProgramMemory) instruction, which enables a special register which shifts the data from the program bus onto the data bus.

    Unfortunatley, because the data bus is still only 8 bits wide, memory has to be loaded one byte at a time - so ints (which are 16 bits) need special routines to make sure that the high and low bytes are stored in adjacent locations. Also, reading a byte from flash memory (where the program is stored) takes more than a few clock cycles, during which execution needs to halt. Reading a large table could take up to a second.

    Most of the details and heavy lifting are handled by special hardware and instructions on the microcontroller, and core data types like floats have library functions in avrlibc. It is still the responsibility of the programmer to know when to load a table, and particularly to make sure that any memory loaded goes out of scope or is free()d when the operation is complete.

    The canned actions which are made using the robobuilder software suite can be exported as 16xN tables, where N is the number of poses (there are 16 servos for the basic robobuilder). For a complicated action, this could be many, many bytes - so the tables are necessarily stored in the flash memory. And of course, since only one action can be performed at a time, you can store dozens of actions in the 128kB of flash and simply swap them out when one needs to be performed.