The incubator will consist of different modules that can be connected to add features. To achieve that goal I implemented the I2C protocol with one master device and several slaves. Therefore, the master device will communicate with the tilting bed module, the temperature module, etc. through the "two wire" communication protocol.
This protocol requires two pulled-up wires (using a 10kΩ resistor), one for the clock (SCL) and other for the data (SCA). That wiring process was made using a breadboard.
The first attempt to communicate two devices was done by pulling information from the master device.
In this example I implemented a Master-transmitter and a Slave-receiver architecture. The master device sends numbers to the slave with the number of times it led has to blink. That number increases each time it is sent until it reaches a value of 10.
- /********************************************************
- *
- * i2cmaster.fabduino.c
- *
- * Alejandro Escario Méndez
- * 03/05/2015
- *
- * MIT license
- *********************************************************/
- #include <avr/io.h>
- #include <util/delay.h>
- #define output(directions,pin) (directions |= pin) // set port direction for output
- #define input(directions,pin) (directions &= (~pin)) // set port direction for input
- #define set(port,pin) (port |= pin) // set port pin
- #define clear(port,pin) (port &= (~pin)) // clear port pin
- #define pin_test(pins,pin) (pins & pin) // test for port pin
- #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
- #define LED_DIRECTION DDRB
- #define LED_PORT PORTB
- #define LED_PIN (1 << PB5)
- unsigned char recipient = 0x28;
- unsigned char data = 1;
- void i2c_init_master(){
- // SCL freq = F_CPU/(16+2(TWBR)*prescalerValue)
- TWBR = 32; // Bit rate
- TWSR = (0 << TWPS1) | (0 << TWPS0); // Setting prescalar bits
- }
- void i2c_start(){
- TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // put start condition
- while(!(TWCR & (1 << TWINT))); // wait until start condition is transmitted
- while((TWSR & 0xF8)!= 0x08); // wait for ACK
- }
- void i2c_repeated_start(){
- TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // put start condition
- while(!(TWCR & (1 << TWINT))); // wait until start condition is transmitted
- while((TWSR & 0xF8)!= 0x10); // wait for ACK
- }
- void i2c_stop(){
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); // put stop condition
- while(!(TWCR & (1<<TWSTO))); // wait until stop condition is transmitted
- }
- void i2c_write_address(unsigned char addr)
- {
- TWDR = addr; // write addr to "call"
- TWCR = (1 << TWINT) | (1 << TWEN); // Enable TWI and clear interrupt flag
- while(!(TWCR & (1 << TWINT))); // Wait until TWDR byte is transmitted
- while((TWSR & 0xF8)!= 0x18); // Check for the acknowledgement
- }
- void i2c_write_data(unsigned char data)
- {
- TWDR = data; // write data in TWDR
- TWCR = (1 << TWINT) | (1 << TWEN); // Clear TWI interrupt flag,Enable TWI
- while (!(TWCR & (1 << TWINT))); // Wait till complete TWDR byte transmitted
- while((TWSR & 0xF8) != 0x28); // Check for the acknowledgement
- }
- int main() {
- output(LED_DIRECTION, LED_PIN);
- i2c_init_master();
- while (1) {
- set(LED_PORT,LED_PIN);
- _delay_ms(100);
- clear(LED_PORT,LED_PIN);
- i2c_start();
- i2c_write_address(recipient);
- i2c_write_data(data);
- i2c_stop();
- _delay_ms(1000);
- data ++;
- data %= 10;
- }
- }
- /********************************************************
- *
- * i2cslave.fabduino.c
- *
- * Alejandro Escario Méndez
- * 03/05/2015
- *
- * MIT license
- *********************************************************/
- #include <avr/io.h>
- #include <util/delay.h>
- #define output(directions,pin) (directions |= pin) // set port direction for output
- #define input(directions,pin) (directions &= (~pin)) // set port direction for input
- #define set(port,pin) (port |= pin) // set port pin
- #define clear(port,pin) (port &= (~pin)) // clear port pin
- #define pin_test(pins,pin) (pins & pin) // test for port pin
- #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
- #define LED_DIRECTION DDRB
- #define LED_PORT PORTB
- #define LED_PIN (1 << PB5)
- unsigned char my_addr = 0x28;
- void i2c_init_slave(){
- TWAR = my_addr;
- }
- void i2c_match_read_slave(){
- while((TWSR & 0xF8)!= 0x60) { // wait for ACK
- TWCR=(1<<TWEA)|(1<<TWEN)|(1<<TWINT); // get ACK, en TWI, clear int flag
- while (!(TWCR & (1<<TWINT))); // Wait for TWINT flag
- }
- }
- unsigned char i2c_read_slave(){
- TWCR=(1<<TWEA)|(1<<TWEN)|(1<<TWINT); // get ACK, en TWI, clear int flag
- while (!(TWCR & (1<<TWINT))); // Wait for TWINT flag
- while((TWSR & 0xF8)!=0x80); // Wait for acknowledgement
- return TWDR; // return received value
- }
- int main() {
- output(LED_DIRECTION, LED_PIN);
- i2c_init_slave();
- while (1) {
- i2c_match_read_slave();
- unsigned char data = i2c_read_slave();
- int i;
- for(i = 0; i < data; i++){
- _delay_ms(25);
- set(LED_PORT,LED_PIN);
- _delay_ms(25);
- clear(LED_PORT, LED_PIN);
- }
- }
- }
The preceding code is not implementing the best approach. Meanwhile the master device can divide its time between communication time and self-executing time because it decides when to communicate; the slave device has to be wasting CPU time waiting for the master device to start the communication. In order to fix that issue I decided to use interruptions in the slave device, so it can process information when not transmitting or receiving.
The incubator brain will need to send and retrieve information from the external modules. This new code enables two ways communication:
The implemented program sends a number (x) from the master device to the slave. The slave blinks the led 'x' times. The slave subtract the received number to 10 and sends it back to the master device. The master device blinks the led 10-x times. Increments the number to be sent to the slave and starts again.
- /********************************************************
- *
- * i2cmaster.fabduino.c
- *
- * Alejandro Escario Méndez
- * 03/05/2015
- * MIT license
- *********************************************************/
- #include <avr/io.h>
- #include <util/delay.h>
- #include <util/twi.h>
- #define output(directions,pin) (directions |= pin) // set port direction for output
- #define input(directions,pin) (directions &= (~pin)) // set port direction for input
- #define set(port,pin) (port |= pin) // set port pin
- #define clear(port,pin) (port &= (~pin)) // clear port pin
- #define pin_test(pins,pin) (pins & pin) // test for port pin
- #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
- #define LED_DIRECTION DDRB
- #define LED_PORT PORTB
- #define LED_PIN (1 << PB5)
- unsigned char recipient = 0x28;
- unsigned char data = 1;
- void i2c_init_master(){
- // SCL freq = F_CPU/(16+2(TWBR)*prescalerValue)
- TWBR = 32; // Bit rate
- TWSR = (0 << TWPS1) | (0 << TWPS0); // Setting prescalar bits
- }
- void i2c_start(){
- TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // put start condition
- while(!(TWCR & (1 << TWINT))); // wait until start condition is transmitted
- while((TWSR & 0xF8)!= TW_START); // wait for ACK
- }
- void i2c_repeated_start(){
- TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // put start condition
- while(!(TWCR & (1 << TWINT))); // wait until start condition is transmitted
- while((TWSR & 0xF8)!= TW_REP_START); // wait for ACK
- }
- void i2c_stop(){
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); // put stop condition
- while(!(TWCR & (1<<TWSTO))); // wait until stop condition is transmitted
- }
- void i2c_write_address(unsigned char addr)
- {
- TWDR = addr; // write addr to "call"
- TWCR = (1 << TWINT) | (1 << TWEN); // Enable TWI and clear interrupt flag
- while(!(TWCR & (1 << TWINT))); // Wait until TWDR byte is transmitted
- while((TWSR & 0xF8)!= TW_MT_SLA_ACK); // Check for the acknowledgement
- }
- void i2c_write_data(unsigned char data)
- {
- TWDR = data; // write data in TWDR
- TWCR = (1 << TWINT) | (1 << TWEN); // clc TWI interrupt flag,En TWI
- while (!(TWCR & (1 << TWINT))); // Wait until TWDR byte transmitted
- while((TWSR & 0xF8) != TW_MT_DATA_ACK); // Check for the acknowledgement
- }
- void i2c_read_address(unsigned char data)
- {
- TWDR=data; // Address and read instruction
- TWCR=(1<<TWINT)|(1<<TWEN); // clc TWI interrupt flag,En TWI
- while (!(TWCR & (1<<TWINT))); // Wait until TWDR byte transmitted
- while((TWSR & 0xF8)!= TW_MR_SLA_ACK); // Check for the acknowledgement
- }
- void i2c_read_data()
- {
- TWCR=(1<<TWINT)|(1<<TWEN); // clc TWI interrupt flag,En TWI
- while (!(TWCR & (1<<TWINT))); // Wait until TWDR byte transmitted
- while((TWSR & 0xF8) != TW_MR_DATA_NACK); // Check for the acknowledgement
- blink(TWDR);
- }
- void blink(unsigned char num){
- int i;
- for(i = 0; i < num; i++){
- _delay_ms(50);
- set(LED_PORT,LED_PIN);
- _delay_ms(50);
- clear(LED_PORT, LED_PIN);
- }
- }
- int main() {
- output(LED_DIRECTION, LED_PIN);
- i2c_init_master();
- while (1) {
- i2c_start();
- i2c_write_address(recipient);
- i2c_write_data(data);
- i2c_stop();
- _delay_ms(1000);
- i2c_start();
- i2c_read_address(recipient+1);
- i2c_read_data();
- i2c_stop();
- _delay_ms(1000);
- data ++;
- data %= 10;
- }
- }
- /********************************************************
- *
- * i2cslave.fabduino.c
- *
- * Alejandro Escario Méndez
- * 03/05/2015
- *
- * (c) Massachusetts Institute of Technology 2015
- * Permission granted for experimental and personal use;
- * license for commercial sale available from MIT.
- *********************************************************/
- #include <avr/io.h>
- #include <util/delay.h>
- #include <util/twi.h>
- #include <avr/interrupt.h>
- #define output(directions,pin) (directions |= pin) // set port direction for output
- #define input(directions,pin) (directions &= (~pin)) // set port direction for input
- #define set(port,pin) (port |= pin) // set port pin
- #define clear(port,pin) (port &= (~pin)) // clear port pin
- #define pin_test(pins,pin) (pins & pin) // test for port pin
- #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
- #define LED_DIRECTION DDRB
- #define LED_PORT PORTB
- #define LED_PIN (1 << PB5)
- unsigned char my_addr = 0x28;
- unsigned char regaddr, regdata;
- void i2c_init_slave(){
- TWAR = my_addr;
- TWDR = 0x00;
- // SCL freq = F_CPU/(16+2(TWBR)*prescalerValue)
- TWBR = 32; // Bit rate
- TWSR = (0 << TWPS1) | (0 << TWPS0); // Setting prescalar bits
- TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN) | (1<<TWIE); // get ACK, en TWI, clear int flag
- }
- void blink(unsigned char num){
- int i;
- for(i = 0; i < num; i++){
- _delay_ms(50);
- set(LED_PORT,LED_PIN);
- _delay_ms(50);
- clear(LED_PORT, LED_PIN);
- }
- }
- ISR(TWI_vect){
- static unsigned char last_val = 1;
- // Disable Global Interrupt
- cli();
- switch(TW_STATUS){
- case TW_START: // 0x08
- case TW_REP_START: // 0x10
- case TW_MT_SLA_ACK: // 0x18
- case TW_MT_SLA_NACK: // 0x20
- case TW_MT_DATA_ACK: // 0x28
- case TW_MT_DATA_NACK: // 0x30
- case TW_MR_SLA_ACK: // 0x40
- case TW_MR_SLA_NACK: // 0x48
- case TW_MR_DATA_ACK: // 0x50
- case TW_MR_DATA_NACK: // 0x58
- case TW_ST_ARB_LOST_SLA_ACK: // 0xB0
- case TW_SR_ARB_LOST_SLA_ACK: // 0x68
- case TW_SR_GCALL_ACK: //0x70
- case TW_SR_ARB_LOST_GCALL_ACK: // 0x78
- case TW_SR_GCALL_DATA_ACK: // 0x90
- case TW_SR_GCALL_DATA_NACK: // 0x98
- case TW_NO_INFO: // 0xF8
- TWCR |= (1<<TWINT); // Clear TWINT Flag
- break;
- case TW_SR_SLA_ACK: // 0x60: SLA+W received, ACK returned
- TWCR |= (1<<TWINT); // Clear TWINT Flag
- break;
- case TW_SR_DATA_ACK: // data received
- last_val = TWDR;
- blink(last_val);
- TWCR |= (1<<TWINT); // Clear TWINT Flag
- break;
- case TW_SR_STOP: // 0xA0: stop or repeated start condition received while selected
- TWCR |= (1<<TWINT); // Clear TWINT Flag
- break;
- case TW_ST_SLA_ACK: // 0xA8: SLA+R received, ACK returned
- TWDR= 10-last_val; // Fill TWDR register whith the data to be sent
- TWCR = ((1 << TWEA) | (1 << TWINT) | (1 << TWEN) | (1 << TWIE)); // Enable TWI, Clear TWI interrupt flag
- break;
- case TW_ST_DATA_ACK: // 0xB8: data transmitted, ACK received
- TWCR |= (1<<TWINT); // Clear TWINT Flag
- break;
- case TW_ST_DATA_NACK: // 0xC0: data transmitted, NACK received
- TWCR |= (1<<TWINT); // Clear TWINT Flag
- break;
- case TW_ST_LAST_DATA: // 0xC8: last data byte transmitted, ACK received
- case TW_BUS_ERROR: // 0x00: illegal start or stop condition
- default:
- TWCR |= (1<<TWINT); // Clear TWINT Flag
- break;
- }
- sei();
- }
- int main() {
- output(LED_DIRECTION, LED_PIN);
- i2c_init_slave();
- sei();
- while (1);
- }
The interaction between both FabKits can be seen in the next video.
For this example I used a breadboard to do the SDA and SCL pull-up circuit. Now that everything is working as expected, I decided to create a small PCB circuit that allows connecting 4 I2C devices. The master or any slave can be connected to any port, But I suggest connecting the master device in the independent connection.
Once welded the result should look like this:
Despite of the low cost nature of the incubator I am designing, I decided to add an "optional" module to control wirelessly the machine. In order to do that I connected a HC-05 Bluetooth module to my FabKit through the USART port and tried to send and receive/send information from/to a cellphone.
To achieve that goal I recycled the code and the design of the control panel shield but, instead of connecting the FabKit to the computer using the FTDI cable, I fed the circuit using the power supply built a few weeks ago. Doing that I could use the TX and RX ports of the FabKit to communicate with the bluetooth module at 9600 bauds.
I also had to design a board to connect the HC-05 to the FabKit (using for example a breadboard).
Once welded it looks like this:
This board has a button to pair the device, a led that indicates whether is powered on or not and a second led that blinks depending on the state of the bluetooth module. It has 6 output pins, but just 4 of them are mandatory: GND, 5V, Tx & Rx.
Learning how to communicate using a bluetooth interface, I modified the control panel code. It shows the position of the joystick in the first line of the screen and sends that information through the bluetooth as a string. If the connected device sends information to the AVR, it will be displayed in the second line of the LCD display.
In order to compile and load this code into an AVR the libraries serial.h and defitions.h must be located in the folder ../lib/. Those can be downloaded from the input devices page.
- /********************************************************
- *
- * bluetooth.fabduino.c
- *
- * 9600 baud FTDI interface
- *
- * Alejandro Escario Méndez
- * 29/04/2015
- *
- * MIT license
- *********************************************************/
- #include <avr/io.h>
- #include <util/delay.h>
- #include <stdio.h>
- #include <avr/pgmspace.h>
- #include <avr/interrupt.h>
- #include "../lib/definitions.h"
- #include "../lib/serial.h"
- #define output(directions,pin) (directions |= pin) // set port direction for output
- #define input(directions,pin) (directions &= (~pin)) // set port direction for input
- #define set(port,pin) (port |= pin) // set port pin
- #define clear(port,pin) (port &= (~pin)) // clear port pin
- #define pin_test(pins,pin) (pins & pin) // test for port pin
- #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
- #define RGB_PORT PORTB
- #define RGB_DIRECTION DDRB
- #define RGB_PIN PINB
- #define RGB_RED PB1
- #define RGB_GREEN PB0
- #define RGB_BLUE PB2
- #define BUZZER_PORT PORTD
- #define BUZZER_DIRECTION DDRD
- #define BUZZER_PIN PIND
- #define BUZZER_I PD7
- #define BUTTON_PORT PORTD
- #define BUTTON_DIRECTION DDRD
- #define BUTTON_PIN PIND
- #define BUTTON_I PD2
- #define lcd_delay() _delay_ms(10) // delay between commands
- #define strobe_delay() _delay_us(1) // delay for strobe
- #define LCD_PORT PORTC
- #define LCD_DIRECTION DDRC
- #define LCD_DB7 (1 << PC0)
- #define LCD_DB6 (1 << PC1)
- #define LCD_DB5 (1 << PC2)
- #define LCD_DB4 (1 << PC3)
- #define LCD_E (1 << PC4)
- #define LCD_RS (1 << PC5)
- #define JOY_X 7
- #define JOY_Y 6
- volatile int x = 0, y = 0, buff_idx;
- volatile char buff[16];
- void button_init(){
- set(BUTTON_PORT, (1 << BUTTON_I)); // turn on pull-up
- input(BUTTON_DIRECTION, (1 << BUTTON_I));
- }
- void button_on_click(void (*fn)()){
- if (0 == pin_test(BUTTON_PIN, (1 << BUTTON_I))){
- (*fn)();
- }
- }
- void buzzer_init(){
- clear(BUZZER_PORT, (1 << BUZZER_I));
- output(BUZZER_DIRECTION, (1 << BUZZER_I));
- }
- void buzzer_beep(){
- set(BUZZER_PORT, (1 << BUZZER_I));
- _delay_ms(10);
- clear(BUZZER_PORT, (1 << BUZZER_I));
- }
- void rgb_init(){
- clear(RGB_PORT, (1 << RGB_RED));
- output(RGB_DIRECTION, (1 << RGB_RED));
- clear(RGB_PORT, (1 << RGB_GREEN));
- output(RGB_DIRECTION, (1 << RGB_GREEN));
- clear(RGB_PORT, (1 << RGB_BLUE));
- output(RGB_DIRECTION, (1 << RGB_BLUE));
- rgb_off();
- }
- void rgb_green(){
- clear(PORTB, (1 << RGB_GREEN));
- set(PORTB, (1 << RGB_RED));
- set(PORTB, (1 << RGB_BLUE));
- }
- void rgb_off(){
- set(PORTB, (1 << RGB_GREEN));
- set(PORTB, (1 << RGB_RED));
- set(PORTB, (1 << RGB_BLUE));
- }
- void rgb_red(){
- clear(PORTB, (1 << RGB_RED));
- set(PORTB, (1 << RGB_GREEN));
- set(PORTB, (1 << RGB_BLUE));
- }
- void rgb_blue(){
- set(PORTB, (1 << RGB_RED));
- set(PORTB, (1 << RGB_GREEN));
- clear(PORTB, (1 << RGB_BLUE));
- }
- void rgb_yellow(){
- clear(PORTB, (1 << RGB_GREEN));
- clear(PORTB, (1 << RGB_RED));
- set(PORTB, (1 << RGB_BLUE));
- }
- void rgb_white(){
- clear(PORTB, (1 << RGB_GREEN));
- clear(PORTB, (1 << RGB_RED));
- clear(PORTB, (1 << RGB_BLUE));
- }
- void joystick_init(){
- ADCSRA = (1 << ADEN) // enable
- | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128
- }
- void joystick_change_port(volatile uint8_t pc){
- ADMUX = (0 << REFS1) | (0 << REFS0) // VCC ref
- | (0 << ADLAR) // right adjust for 10bit precision
- | pc;
- }
- int joystick_read_x(){
- joystick_change_port(JOY_X);
- return read_adc();
- }
- int joystick_read_y(){
- joystick_change_port(JOY_Y);
- return read_adc();
- }
- int read_adc(){
- ADCSRA |= (1 << ADSC); // conversion init
- while (ADCSRA & (1 << ADSC)); // wait for completion
- return ADC; // return value
- }
- //
- // lcd_putchar
- // put character in lcdbyte
- //
- void lcd_putchar(char lcdbyte) {
- //
- // set RS for data
- //
- set(LCD_PORT, LCD_RS);
- //
- // output high nibble
- //
- if bit_test(lcdbyte, 7)
- set(LCD_PORT, LCD_DB7);
- else
- clear(LCD_PORT, LCD_DB7);
- if bit_test(lcdbyte, 6)
- set(LCD_PORT, LCD_DB6);
- else
- clear(LCD_PORT, LCD_DB6);
- if bit_test(lcdbyte, 5)
- set(LCD_PORT, LCD_DB5);
- else
- clear(LCD_PORT, LCD_DB5);
- if bit_test(lcdbyte, 4)
- set(LCD_PORT, LCD_DB4);
- else
- clear(LCD_PORT, LCD_DB4);
- //
- // strobe E
- //
- strobe_delay();
- set(LCD_PORT, LCD_E);
- strobe_delay();
- clear(LCD_PORT, LCD_E);
- //
- // wait
- //
- lcd_delay();
- //
- // output low nibble
- //
- if bit_test(lcdbyte, 3)
- set(LCD_PORT, LCD_DB7);
- else
- clear(LCD_PORT, LCD_DB7);
- if bit_test(lcdbyte, 2)
- set(LCD_PORT, LCD_DB6);
- else
- clear(LCD_PORT, LCD_DB6);
- if bit_test(lcdbyte, 1)
- set(LCD_PORT, LCD_DB5);
- else
- clear(LCD_PORT, LCD_DB5);
- if bit_test(lcdbyte, 0)
- set(LCD_PORT, LCD_DB4);
- else
- clear(LCD_PORT, LCD_DB4);
- //
- // strobe E
- //
- strobe_delay();
- set(LCD_PORT, LCD_E);
- strobe_delay();
- clear(LCD_PORT, LCD_E);
- //
- // wait and return
- //
- lcd_delay();
- }
- //
- // lcd_putcmd
- // put command in lcdbyte
- //
- void lcd_putcmd(char lcdbyte) {
- //
- // clear RS for command
- //
- clear(LCD_PORT, LCD_RS);
- //
- // output command bits
- //
- PORTC = lcdbyte;
- //
- // strobe E
- //
- strobe_delay();
- set(LCD_PORT, LCD_E);
- strobe_delay();
- clear(LCD_PORT, LCD_E);
- //
- // wait and return
- //
- lcd_delay();
- }
- //
- // lcd_putstring
- // put a null-terminated string in flash
- //
- void lcd_putstring(char* message) {
- static uint8_t i;
- static char chr;
- i = 0;
- while (1) {
- chr = message[i];
- if (chr == 0)
- return;
- lcd_putchar(chr);
- ++i;
- }
- }
- void lcd_putline(char* message, int line){
- if(line == 1){
- lcd_putcmd(0);
- lcd_putcmd(LCD_DB5);
- }else if(line == 2){
- lcd_putcmd(LCD_DB7+LCD_DB6);
- lcd_putcmd(0);
- }
- lcd_putstring(message);
- }
- void lcd_clear(){
- lcd_putcmd(0);
- lcd_putcmd(LCD_DB4);
- }
- void lcd_cursor_off(){
- lcd_putcmd(0);
- lcd_putcmd(LCD_DB7+LCD_DB6);
- }
- //
- // lcd_init
- // initialize the LCD
- //
- void lcd_init() {
- //
- // initialize LCD pins
- //
- clear(LCD_PORT, LCD_DB7);
- output(LCD_DIRECTION, LCD_DB7);
- clear(LCD_PORT, LCD_DB6);
- output(LCD_DIRECTION, LCD_DB6);
- clear(LCD_PORT, LCD_DB5);
- output(LCD_DIRECTION, LCD_DB5);
- clear(LCD_PORT, LCD_DB4);
- output(LCD_DIRECTION, LCD_DB4);
- clear(LCD_PORT, LCD_E);
- output(LCD_DIRECTION, LCD_E);
- clear(LCD_PORT, LCD_RS);
- output(LCD_DIRECTION, LCD_RS);
- //
- // power-up delay
- //
- lcd_delay();
- //
- // initialization sequence
- //
- lcd_putcmd(LCD_DB5+LCD_DB4);
- lcd_putcmd(LCD_DB5+LCD_DB4);
- lcd_putcmd(LCD_DB5+LCD_DB4);
- //
- // 4-bit interface
- //
- lcd_putcmd(LCD_DB5);
- //
- // two lines, 5x7 font
- //
- lcd_putcmd(LCD_DB5);
- lcd_putcmd(LCD_DB7);
- //
- // display on
- //
- lcd_putcmd(0);
- lcd_putcmd(LCD_DB7+LCD_DB6+LCD_DB5);
- //
- // entry mode
- //
- lcd_putcmd(0);
- lcd_putcmd(LCD_DB6+LCD_DB5);
- }
- ISR (USART_RX_vect) {
- char line[16];
- buff[buff_idx] = UDR0;
- if(buff_idx >= 16 || buff[buff_idx] == 0){
- buff_idx = 0;
- }else{
- buff_idx++;
- }
- }
- int main(void) {
- char line[16];
- int x, y, i = 0;
- buzzer_init();
- rgb_init();
- lcd_init();
- button_init();
- joystick_init();
- lcd_init();
- lcd_clear();
- lcd_cursor_off();
- usart_init(R_UBRR);
- sei();
- while(1){
- x = joystick_read_x();
- y = joystick_read_y();
- sprintf(line, "x=%4i - y=%4i", x, y);
- printf("%s\n", line);
- lcd_putline(line, 1);
- lcd_putline(buff,2);
- button_on_click(&buzzer_beep);
- if(x > 450 && x < 550 && y > 450 && y < 550){
- rgb_green();
- }else if(x > 200 && x < 800 && y > 200 && y < 800){
- rgb_yellow();
- }else{
- rgb_red();
- }
- }
- }
The incubator has 3 different boards. This approach might seem unnecessary at first glance, but the goal of the project is building a low cost incubator and, in order to achieve that goal, I designed it as modular as possible. Therefore If you want to build your incubator without the control panel board and controle it using the bluetooth connection, you can do it.
There are 3 types of networking communication:
The boards and code of this two input devices can be found in the final project page.