Final prototype for Grounded, an electromechanical coffee machine.

Grounded

Electromechanical Design
Programming
Prototyping

Design and prototype an electromechanical coffee machine, incorporating an AeroPress device

KeyShot rendering of design proposal, showing the moving carousel.
KeyShot rendering of design proposal, showing the moving Aeropress device.
Schematic diagram of the electronic components used.

/** C O N F I G U R A T I O N _ B I T S **/

#pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF
#pragma config PWRT = OFF, BOREN = OFF, BORV = 30
#pragma config WDTEN = OFF, WDTPS = 32768
#pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC
#pragma config STVREN = ON, LVP = OFF, XINST = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF
#pragma config EBTRB = OFF

/** I N C L U D E S **/

#include "p18f45k20.h"
#include "GROUNDED ADC.h"
#include "delays.h"

#define PLUNGE_1 LATBbits.LATB0
#define PLUNGE_2 LATBbits.LATB1
#define LIMITING_SWITCH LATBbits.LATB2

#define CLEAR_SCREEN 0b00000001
#define FOUR_BIT 0b00101100
#define LINES_5X7 0b00111000
#define CURSOR_BLINK 0b00001111
#define CURSOR_RIGHT 0b00000110

#define DATA_PORT LATD
#define RS_PIN PORTDbits.RD6
#define E_PIN PORTDbits.RD7

#define IN1 LATBbits.LATB3
#define IN2 LATBbits.LATB4

/** F U N C T I O N S **/

/** L I N E A R _ A C T U A T O R **/

void PLUNGE_UP ()
{
LATB=0b11111111;
PLUNGE_1=1;
PLUNGE_2=0;
}

void PLUNGE_DOWN ()
{
LATB=0b11111111;
PLUNGE_1=0;
PLUNGE_2=1;
}

void PLUNGE_STOP ()
{
LATB=0b11111111;
PLUNGE_1=1;
PLUNGE_2=1;
}

/** D C _ M O T O R **/

void CLOCKWISE ()
{
IN1=1;
IN2=0;
}

void ANTICLOCKWISE ()
{
IN1=0;
IN2=1;
}

void ROTATE_STOP ()
{
IN1=1;
IN2=1;
}

/** L C D **/

void Delay5milli(void)
{
Delay1KTCYx(2);
}

void SetAddr(unsigned char DDaddr)
{
DATA_PORT &= 0xf0;
DATA_PORT |= (((DDaddr | 0b10000000)>>4) & 0x0f);

RS_PIN = 0;
Delay5milli();
E_PIN = 1;
Delay5milli();
E_PIN = 0;

DATA_PORT &= 0xf0;
DATA_PORT |= (DDaddr&0x0f);

Delay5milli();
E_PIN = 1;
Delay5milli();
E_PIN = 0;
}

void WriteCmd(unsigned char cmd)
{
DATA_PORT &= 0xf0;
DATA_PORT |= (cmd>>4)&0x0f;
RS_PIN = 0;
Delay5milli();
E_PIN = 1;
Delay5milli();
E_PIN = 0;

    DATA_PORT &= 0xf0;
DATA_PORT |= cmd&0x0f;
Delay5milli();
E_PIN = 1;
Delay5milli();
E_PIN = 0;
}

void WriteChar(char data)
{
DATA_PORT &= 0xf0;
DATA_PORT |= ((data>>4)&0x0f);

RS_PIN = 1;
Delay5milli();
E_PIN = 1;
Delay5milli();
E_PIN = 0;

  DATA_PORT &= 0xf0;
DATA_PORT |= (data&0x0f);

       Delay5milli();
E_PIN = 1;
Delay5milli();
E_PIN = 0;
}

void WriteString(const rom char *buffer)
{
while(*buffer)
{
Delay5milli();
WriteChar( *buffer);
buffer++;
}
return;
}

void ADC_Init0(void)
{
ANSEL = 0;
ANSELH = 0;
ANSELbits.ANS0 = 1;

  ADCON1 = 0;
ADCON2 = 0b00111000;
    ADCON0 = 0b00000001;
}

void ADC_Init1(void)
{
ANSEL = 0;
ANSELH = 0;
ANSELbits.ANS1 = 1;

ADCON1 = 0;
ADCON2 = 0b00111000;
ADCON0 = 0b00000001;
}

unsigned char ADC_Convert(void)
{
ADCON0bits.GO_DONE = 1;
while (ADCON0bits.GO_DONE == 1);
return ADRESH;
}

/** M A I N **/

void main(void)
{
while(1)
{

/** P I N S _ S E T  UP **/

ANSEL = 0;
ANSELH = 0;

TRISA = 0b11111111;
TRISB = 0b00000100;
TRISC = 0b00000000;
TRISD = 0b00000000;

/** S T A R T _ U S E R _ P R O C E S S **/

/** L C D _ D I S P L A Y **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Welcome to");
SetAddr (0xC0);
WriteString("Base HQ");
Delay10KTCYx(120);

/** D C _ M O T O R **/

do
{
ANTICLOCKWISE ();
}

while(PORTAbits.RA3 == 1);

ROTATE_STOP ();

do
{
CLOCKWISE ();
}

while(PORTAbits.RA2 == 1);
ROTATE_STOP ();

Delay10KTCYx(20);

/** L I N E A R _ A C T U A T O R **/

do
{
PLUNGE_UP ();
}

while(PORTBbits.RB2 == 1);

PLUNGE_STOP ();

/** L C D _ D I S P L A Y **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Place vessel in");
SetAddr (0xC0);
WriteString("launch pad");
Delay10KTCYx(120);

/** L D R _ S E N S O R **/

do
{
ADC_Init0();
ADC_Convert();
SetAddr (0x80);
}

while (ADRESH < 80);

/** L C D _ D I S P L A Y **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Add rocket fuel");
SetAddr (0xC0);
WriteString("to chamber");

Delay10KTCYx(255);
WriteCmd ( CLEAR_SCREEN);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Americano or");
SetAddr (0xC0);
WriteString("Espresso?");
Delay10KTCYx(60);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Press and hold");
SetAddr (0xC0);
WriteString("selection");
Delay10KTCYx(60);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("1_ Americano");
SetAddr (0xC0);
WriteString("2_ Espresso");
Delay10KTCYx(60);

if (PORTAbits.RA4 == 0)
{
WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr  (0x80);
WriteString("Fill water to");
SetAddr (0xC0);
WriteString("level 3");
Delay10KTCYx(255);
}

else
{
WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Fill water to");
SetAddr (0xC0);
WriteString("level 2");
Delay10KTCYx(255);
}

do
{
WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Press and hold");
SetAddr (0xC0);
WriteString("if water added");
}

while(PORTAbits.RA4 == 1);

do
{
ADC_Init1();
ADC_Convert();
}

while (ADRESH < 120);

/** L I N E A R _ A C T U A T O R **/

PLUNGE_DOWN ();
Delay10KTCYx(245);

PLUNGE_STOP ();

/** L C D _ D I S P L A Y _ A N I M A T I O N **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);

SetAddr ( 0x80 );
WriteChar ( 0x00 );
WriteChar ( 0x01 );
WriteChar ( 0x02 );
WriteChar ( 0x03 );
SetAddr ( 0xC0 );
WriteString ("Initialising...");
WriteCmd ( 0x40 );

/** D E F I N E _ C H A R A C T E R S **/

WriteChar ( 0b00000000 );
WriteChar ( 0b00001010 );
WriteChar ( 0b00010101 );
WriteChar ( 0b00000000 );
WriteChar ( 0b00000000 );
WriteChar ( 0b00010101 );
WriteChar ( 0b00001010 );
WriteChar ( 0b00000000 );

WriteChar ( 0b00000000 );
WriteChar ( 0b00010101 );
WriteChar ( 0b00001010 );
WriteChar ( 0b00000000 );
WriteChar ( 0b00000000 );
WriteChar ( 0b00001010 );
WriteChar ( 0b00010101 );
WriteChar ( 0b00000000 );

WriteChar ( 0b00011000 );
WriteChar ( 0b00011100 );
WriteChar ( 0b00000111 );
WriteChar ( 0b00001111 );
WriteChar ( 0b00001111 );
WriteChar ( 0b00000111 );
WriteChar ( 0b00011100 );
WriteChar ( 0b00011000 );

WriteChar ( 0b00000000 );
WriteChar ( 0b00000000 );
WriteChar ( 0b00011100 );
WriteChar ( 0b00010111 );
WriteChar ( 0b00010111 );
WriteChar ( 0b00011100 );
WriteChar ( 0b00000000 );
WriteChar ( 0b00000000 );

SetAddr ( 0xC0 );
WriteString ("Initialising...");

WriteCmd ( CLEAR_SCREEN);

/** S T A R T _ A N I M A T I O N **/

SetAddr ( 0x81 );
WriteChar ( 0x00 );
WriteChar ( 0x01 );
WriteChar ( 0x02 );
WriteChar ( 0x03 );
SetAddr ( 0xC0 );
WriteString ("Initialising...");
Delay1KTCYx(400);
WriteCmd ( CLEAR_SCREEN);

/* repetitive strings omitted */

SetAddr ( 0x90 );
WriteChar ( 0x01 );
WriteChar ( 0x00 );
WriteChar ( 0x02 );
WriteChar ( 0x03 );
SetAddr ( 0xC0 );
WriteString ("Initialising...");
Delay1KTCYx(400);
WriteCmd ( CLEAR_SCREEN);

/** L C D _ D I S P L A Y **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("B L A S T  O F F");
Delay10KTCYx(150);

/** L I N E A R _ A C T U A T O R **/

PLUNGE_DOWN ();
Delay10KTCYx(255);
Delay10KTCYx(255);
Delay10KTCYx(100);

PLUNGE_STOP ();

/** L C D _ D I S P L A Y **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Remove vessel");
SetAddr (0xC0);
WriteString("from dock");
Delay10KTCYx(60);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Resetting...");
Delay10KTCYx(60);

/** L D R _ S E N S O R **/

do
{
ADC_Init0();
ADC_Convert();
SetAddr (0x80);
}

while (ADRESH > 80);

Delay10KTCYx(1);

/** L I N E A R _ A C T U A T O R **/

do
{
PLUNGE_UP ();
}

while(PORTBbits.RB2 == 1);

PLUNGE_STOP ();
Delay10KTCYx(10);

/** D C _ M O T O R **/

do
{
ANTICLOCKWISE ();
}

while(PORTAbits.RA3 == 1);

ROTATE_STOP ();

/** L C D _ D I S P L A Y **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Carefully remove");
SetAddr (0xC0);
WriteString("valve cap");
Delay10KTCYx(200);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Dispose of rocket");
SetAddr (0xC0);
WriteString("fuel and clean");
Delay10KTCYx(200);

/** D C _ M O T O R **/

do
{
CLOCKWISE ();
}

while(PORTAbits.RA2 == 1);

ROTATE_STOP ();

/** L C D _ D I S P L A Y **/

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Please replace");
SetAddr (0xC0);
WriteString("cap");
Delay10KTCYx(200);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("BACK YO SELF");
Delay10KTCYx(200);

WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Would you");
SetAddr (0xC0);
WriteString("like another?");
Delay10KTCYx(60);

do
{
WriteCmd ( 0x02 );
WriteCmd ( CLEAR_SCREEN);
SetAddr (0x80);
WriteString("Press 1");
SetAddr (0xC0);
WriteString("to continue");
Delay10KTCYx(60);
}

while(PORTAbits.RA4 == 1);

}

}

Wide view showcasing the full prototype.
Detailed view of the design elements of the prototype.
Close up view of the finished electronics.
Front view of the finished prototype.