Today I had a little time to work on my recently ordered Atmel AVR XMEGA-A1 Xplained, which I need to evaluate all necessary functions used for my university project which is a humanoid robot made of a lot servos.
So I just started with some research on google because there is no material delivered with a Xplained kit, not even a hardware user’s guide which could tell what port is used for the integrated stuff like LED, switches, USART, etc. but after some time I got all informations and started coding, my goal was to get a nice looking terminal from which I’m able to toggle the LED by just pressing the corresponding numbers e.g. to lit up LED3 so press 3 in terminal window, LED3 turns on and get a response which LED was toggled.
I will just start with the code now and after some lines explain what they do.
|
1 2 3 4 5 6 7 8 9 |
/** * main.c * Xplained USART Test * © Andreas Behrend */ #include <asf.h> #include <gpio.h> #include <string.h> #include <sysclk.h> |
So here I do the first break to explain that all those includes stand for:
- asf.h – include all needed Atmel frameworks
- gpio.h – this header file includes all used stuff defined (LED0_GPIO, LED1_GPIO and so on)
- string.h – just needed to use strlen later
- sysclk.h – used to synchronize the systems clock
|
1 2 3 4 5 6 7 8 |
#define CONF_BOARD_ENABLE_USARTC0 #define USART_SERIAL_PORT &USARTC0 #define USART_SERIAL_BAUDRATE 9600 #define USART_SERIAL_CHAR_LENGTH USART_CHSIZE_8BIT_gc #define USART_SERIAL_PARITY USART_PMODE_DISABLED_gc #define USART_SERIAL_STOP_BIT false #define LED_PORT_ID 4 //PORTE #define LED_PORT_MASK 0xFF |
Just define some variables, we need them later a lot.
|
1 2 3 4 5 |
void light_single_led(uint8_t led_pin); void light_single_led(uint8_t led_pin){ gpio_set_pin_group_high(LED_PORT_ID, LED_PORT_MASK); gpio_set_pin_low(led_pin); } |
Since the Xplained board uses LED as active LOW the whole PORT (4 or PORTE) has to be set high by using gpio_set_pin_group_high(LED_PORT_ID, LED_PORT_MASK);, this function first needs to get the PORT and then a bitmask, both are defined above.
|
1 2 3 4 5 6 7 8 |
void send_uart_text(const char text[]); void send_uart_text(const char text[]){ uint8_t length = strlen(text); uint8_t i = 0; for (i = 0; i < length; i++) { usart_putchar(USART_SERIAL_PORT, text[i]); } } |
Now write some text back from the XMEGA to the terminal window. Here the strlen function is used to get the character count we hand in via const char text[] and then put every character each by each to our terminal using usart_putchar(USART_SERIAL_PORT, text[i]);. This function needs first to know to which USART it should write to and the character, in this case position i inside the text[] array.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void show_menu(void){ send_uart_text("\f"); // CLS send_uart_text("\n\r++++++++++++++++++++++++++++++++++++++++"); send_uart_text("\n\r++ Willkommen im XMEGA USART Terminal ++"); send_uart_text("\n\r++ Verfügbare Optionen: ++"); send_uart_text("\n\r++ 0 -> LED0 ON ++"); send_uart_text("\n\r++ 1 -> LED1 ON ++"); send_uart_text("\n\r++ 2 -> LED2 ON ++"); send_uart_text("\n\r++ 3 -> LED3 ON ++"); send_uart_text("\n\r++ 4 -> LED4 ON ++"); send_uart_text("\n\r++ 5 -> LED5 ON ++"); send_uart_text("\n\r++ 6 -> LED6 ON ++"); send_uart_text("\n\r++ 7 -> LED7 ON ++"); send_uart_text("\n\r++++++++++++++++++++++++++++++++++++++++\n\n\r"); } |
This function is very easy and don’t need a lot explanation, just hand the menu to pre-defined function send_uart_text(), it’s possible to write almost everything.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int main(void) { uint8_t received_byte; uint8_t i; board_init(); sysclk_init(); static usart_rs232_options_t USART_SERIAL_OPTIONS = { .baudrate = USART_SERIAL_BAUDRATE, .charlength = USART_SERIAL_CHAR_LENGTH, .paritytype = USART_SERIAL_PARITY, .stopbits = USART_SERIAL_STOP_BIT }; usart_init_rs232(USART_SERIAL_PORT, &USART_SERIAL_OPTIONS); show_menu(); // Menü anzeigen |
Almost done, first define used vars received_byte and i, then initialize the Xplain board so the compiler knows where to find PORTx, PINx, LEDx etc. with board_init(); then synchronize the systems clock sysclk_init();. After the board is ready we can start with passing the predefined USART options into USART_SERIAL_OPTIONS to use it right after.
In usart_init_rs232(USART_SERIAL_PORT, &USART_SERIAL_OPTIONS); it needs the used USART port (USART_SERIAL_PORT) and of course the whole options-set (&USART_SERIAL_OPTIONS). The following show_menu(); will just show the predesigned menu.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
while (true) { received_byte = usart_getchar(USART_SERIAL_PORT); if (received_byte == '\r') { show_menu(); } if (received_byte == '0'){ light_single_led(LED0_GPIO); send_uart_text("\n\rLED0"); } if (received_byte == '1'){ light_single_led(LED1_GPIO); send_uart_text("\n\rLED1"); } if (received_byte == '2'){ light_single_led(LED2_GPIO); send_uart_text("\n\rLED2"); } if (received_byte == '3'){ light_single_led(LED3_GPIO); send_uart_text("\n\rLED3"); } if (received_byte == '4'){ light_single_led(LED4_GPIO); send_uart_text("\n\rLED4"); } if (received_byte == '5'){ light_single_led(LED5_GPIO); send_uart_text("\n\rLED5"); } if (received_byte == '6'){ light_single_led(LED6_GPIO); send_uart_text("\n\rLED6"); } if (received_byte == '7'){ light_single_led(LED7_GPIO); send_uart_text("\n\rLED7"); } } } |
Now let’s enter the main while-loop and catch some user interactions. First use the predefined var received_byte = usart_getchar(USART_SERIAL_PORT); and use a function to get the character received from terminal. Now it’s possible to just use some “if-code” to let the XMEGA doanything. In this case I just catch die numbers from 0-7 to toggle LED and a return to show the menu again, remember to use “\r” to detect a return. light_single_led(LED7_GPIO); just uses the function made before to toggle a specified LED, send_uart_text(“\n\rLED7″); will send some text to terminal.
After I got everything to work I got this idea to send some commands from my iPhone, but since I wanted to keep it really simple I came to the point to just install XAMPP and wrote some really simple PHP code, I will not explain the PHP, it’s really simple stuff.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>XMEGA Controller</title> </head> <body> <?php function senden($comport,$zeichen){ $fp1 = fopen ("$comport", "w+"); if (!$fp1){ echo "Port zum Schreiben nicht geöffnet!"; } else { fputs ($fp1, $zeichen); fclose ($fp1); } } function lesen($comport2,$sekunden){ $buffer = ""; $fp2 = fopen ("$comport2", "r+"); if (!$fp2){ echo "Port zum lesen nicht geöffnet"; } else{ sleep($sekunden); $buffer .= fgets($fp2, 4096); } return $buffer; fclose ($fp2); } if ($_REQUEST["action"] == "LED0") { senden("COM4","0"); } elseif ($_REQUEST["action"] == "LED1") { senden("COM4","1"); } elseif ($_REQUEST["action"] == "LED2") { senden("COM4","2"); } elseif ($_REQUEST["action"] == "LED3") { senden("COM4","3"); } elseif ($_REQUEST["action"] == "LED4") { senden("COM4","4"); } elseif ($_REQUEST["action"] == "LED5") { senden("COM4","5"); } elseif ($_REQUEST["action"] == "LED6") { senden("COM4","6"); } elseif ($_REQUEST["action"] == "LED7") { senden("COM4","7"); } elseif ($_REQUEST["action"] == "LEDb1") { $seconds = 0.2; senden("COM4","0"); usleep($seconds*1000000); senden("COM4","1"); usleep($seconds*1000000); senden("COM4","2"); usleep($seconds*1000000); senden("COM4","3"); usleep($seconds*1000000); senden("COM4","4"); usleep($seconds*1000000); senden("COM4","5"); usleep($seconds*1000000); senden("COM4","6"); usleep($seconds*1000000); senden("COM4","7"); } elseif ($_REQUEST["action"] == "LEDb2") { $seconds = 0.2; senden("COM4","0"); usleep($seconds*1000000); senden("COM4","4"); usleep($seconds*1000000); senden("COM4","1"); usleep($seconds*1000000); senden("COM4","5"); usleep($seconds*1000000); senden("COM4","2"); usleep($seconds*1000000); senden("COM4","6"); usleep($seconds*1000000); senden("COM4","3"); usleep($seconds*1000000); senden("COM4","7"); } elseif ($_REQUEST["action"] == "LEDb3") { $seconds = 0.2; senden("COM4","0"); usleep($seconds*1000000); senden("COM4","1"); usleep($seconds*1000000); senden("COM4","4"); usleep($seconds*1000000); senden("COM4","5"); usleep($seconds*1000000); senden("COM4","2"); usleep($seconds*1000000); senden("COM4","3"); usleep($seconds*1000000); senden("COM4","6"); usleep($seconds*1000000); senden("COM4","7"); } ?> <h1>Toggle LED</h1> <p><a href="?action=LED0">LED0 on.</a></p> <p><a href="?action=LED1">LED1 on.</a></p> <p><a href="?action=LED2">LED2 on.</a></p> <p><a href="?action=LED3">LED3 on.</a></p> <p><a href="?action=LED4">LED4 on.</a></p> <p><a href="?action=LED5">LED5 on.</a></p> <p><a href="?action=LED6">LED6 on.</a></p> <p><a href="?action=LED7">LED7 on.</a></p> <p><a href="?action=LEDb1">LED blink mode 1</a></p> <p><a href="?action=LEDb2">LED blink mode 2</a></p> <p><a href="?action=LEDb3">LED blink mode 3</a></p> </body> </html> |
That’s it! I can open a terminal connection to my XMEGA, send any command I want and also control it from any browser available.
What else? Bluetooth! Later I will attach a BTM-222 and control it via Bluetooth.