I challenged a friend to connect a micro-controller to a Raspberry Pi. I chose to use an ATMega168 programmed in C while he preferred to use a Microchip PIC programmed in ASM. Not that I don’t like ASM, but it took me only 45 minutes to get all the material together and blink some LEDs from a shell. To get thinks up very fast, I used a BugOne board. This is clearly an advantage for me since it is already assembled with an ISP connector and ready to use.
Connecting the AVR
I connected the BugOne to Raspberry Pi’s 3.3V, serial port and ground available from its GPIO (see the picture, only 4 wires).
Preparing the Raspberrry Pi
Then I removed any use of the /dev/ttyAMA0 port as mentioned in this article from [Oscar Liang]. Its pretty easy since you only need to edit two files: /boot/cmdline.txt and /etc/inittab.
The code
I used previous code from “Blinking a BugOne” and mixed various sources form Internet which I don’t remember and ATMega168 documentation to manage to do interruption driven communication. The source code below is self explanatory, but fill free to ask more details in comments if necessary :
#include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "avr_compat.h" /* Serial */ #define USART_BAUDRATE 9600 #define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL ))) - 1) /* Pinout of leds */ #define LED1 C,1 #define LED2 C,0 int main() { // --- Init UART ----------------------------------- // Turn on the transmission and reception circuitry UCSR0B = (1 << RXEN0) | (1 << TXEN0); // Use 8-bit character sizes UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); // Load upper 8-bits of the baud rate value into the high byte // of the UBRR register UBRR0H = (BAUD_PRESCALE >> 8); // Load lower 8-bits of the baud rate value into the low byte // of the UBRR register UBRR0L = BAUD_PRESCALE ; // Enable the USART Recieve Complete interrupt (USART_RXC) UCSR0B |= (1 << RXCIE0); // --- Init GPIO ---------------------------------------- drive(LED1); drive(LED2); set_output(LED1); set_output(LED2); _delay_ms(500); clr_output(LED1); clr_output(LED2); // --- Interrupts ---------------------------------------- sei(); while (1) { toggle_output(LED1); _delay_ms(500); } } ISR(USART_RX_vect) { uint8_t received; // Fetch the received byte value into the variable "ByteReceived" received = UDR0; if (received & 0x01) { set_output(LED2); } else { clr_output(LED2); } // Wait for USART to be ready to send // while (!(UCSR0A & (1 << UDRE0))); // Echo back the received byte back to the computer UDR0 = received; }
Putting it all together
After compiling and flashing the BugOne, I connected to the BugOne through SSH and I used screen to connect to the BugOne.
screen /dev/ttyAMA0 9600
Then you can press any key. It will be echoed to the terminal and depending on the last bit of the char it will toggle LED2.