Difference between revisions of "PPOD-mini: 6-DOF Shaker"

From Mech
Jump to navigationJump to search
Line 22: Line 22:


== Code ==
== Code ==
#include <18f4520.h>
#fuses HS,NOLVP,NOWDT
#use delay (clock=40000000)
#include "key.c"
#include "flex_lcd.c" //lcd files
int32 frequency = 40;
int ii;
int32 halfperiod;
int32 delays;
int8 s_p[6]={0,0,0,0,0,0};
char k;
#INT_EXT // designates that this is the routine to call when pin RB0/INTO changes state
void INT0isr() {
int s;
int flag=1;
char speaker;
char phase;
int i, j, temp;
printf(lcd_putc,"\fChanging Phase");
delay_ms(10);
printf(lcd_putc,"\n\fSpeaker Number:");
while(flag==1){
speaker = kbd_getc(); //read speaker number
if(speaker!=0) { //determine speaker
printf(lcd_putc,"%c",speaker);
switch (speaker){
case '1':
s=0;
flag=0; //exit loop if acceptable input is entered
break;
case '2':
s=1;
flag=0;
break;
case '3':
s=2;
flag=0;
break;
case '4':
s=3;
flag=0;
break;
case '5':
s=4;
flag=0;
break;
case '6':
s=5;
flag=0;
break;
default:
printf(lcd_putc,"\n\fInvalid input.");
delay_ms(10);
printf(lcd_putc,"\n\nSpeaker Number:");
break;
}
}
}
flag=1;
printf(lcd_putc,"\nEnter Phase:");
while(flag==1){
phase = kbd_getc(); //read in phase
if(phase!=0) {
printf(lcd_putc,"%c",phase);
switch (phase){ //set phase array
case '0':
s_p[s]=0;
flag=0;
break;
case '1':
s_p[s]=1;
flag=0;
break;
case '2':
s_p[s]=2;
flag=0;
break;
case '3':
s_p[s]=3;
flag=0;
break;
case '4':
s_p[s]=4;
flag=0;
break;
case '5':
s_p[s]=5;
flag=0;
break;
default:
printf(lcd_putc,"\nInvalid input.");
delay_ms(10);
printf(lcd_putc,"\nEnter Phase:");
break;
}
}
}
}
void main (){
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
ext_int_edge(0, L_TO_H);
halfperiod = 500000/frequency;
delays = halfperiod/3;
lcd_init();
kbd_init(); //initialize keypad
printf(lcd_putc,"Starting...\n");
delay_ms(1000);
printf(lcd_putc,"\n");
while(true) {
if(s_p[0] == 0){
output_high(PIN_A0);
output_low(PIN_A1);
}
if(s_p[1] == 0){
output_high(PIN_A2);
output_low(PIN_A3);
}
if(s_p[2] == 0){
output_high(PIN_A4);
output_low(PIN_A5);
}
if(s_p[3] == 0){
output_high(PIN_C6);
output_low(PIN_E0);
}
if(s_p[4] == 0){
output_high(PIN_E1);
output_low(PIN_E2);
}
if(s_p[5] == 0){
output_high(PIN_C5);
output_low(PIN_D0);
}
if(s_p[0] == 3){
output_low(PIN_A0);
output_high(PIN_A1);
}
if(s_p[1] == 3){
output_low(PIN_A2);
output_high(PIN_A3);
}
if(s_p[2] == 3){
output_low(PIN_A4);
output_high(PIN_A5);
}
if(s_p[3] == 3){
output_low(PIN_C6);
output_high(PIN_E0);
}
if(s_p[4] == 3){
output_low(PIN_E1);
output_high(PIN_E2);
}
if(s_p[5] == 3){
output_low(PIN_C5);
output_high(PIN_D0);
}
delay_us(delays);
if(s_p[0] == 1){
output_high(PIN_A0);
output_low(PIN_A1);
}
if(s_p[1] == 1){
output_high(PIN_A2);
output_low(PIN_A3);
}
if(s_p[2] == 1){
output_high(PIN_A4);
output_low(PIN_A5);
}
if(s_p[3] == 1){
output_high(PIN_C6);
output_low(PIN_E0);
}
if(s_p[4] == 1){
output_high(PIN_E1);
output_low(PIN_E2);
}
if(s_p[5] == 1){
output_high(PIN_C5);
output_low(PIN_D0);
}
if(s_p[0] == 4){
output_low(PIN_A0);
output_high(PIN_A1);
}
if(s_p[1] == 4){
output_low(PIN_A2);
output_high(PIN_A3);
}
if(s_p[2] == 4){
output_low(PIN_A4);
output_high(PIN_A5);
}
if(s_p[3] == 4){
output_low(PIN_C6);
output_high(PIN_E0);
}
if(s_p[4] == 4){
output_low(PIN_E1);
output_high(PIN_E2);
}
if(s_p[5] == 4){
output_low(PIN_C5);
output_high(PIN_D0);
}
delay_us(delays);
if(s_p[0] == 2){
output_high(PIN_A0);
output_low(PIN_A1);
}
if(s_p[1] == 2){
output_high(PIN_A2);
output_low(PIN_A3);
}
if(s_p[2] == 2){
output_high(PIN_A4);
output_low(PIN_A5);
}
if(s_p[3] == 2){
output_high(PIN_C6);
output_low(PIN_E0);
}
if(s_p[4] == 2){
output_high(PIN_E1);
output_low(PIN_E2);
}
if(s_p[5] == 2){
output_high(PIN_C5);
output_low(PIN_D0);
}
if(s_p[0] == 5){
output_low(PIN_A0);
output_high(PIN_A1);
}
if(s_p[1] == 5){
output_low(PIN_A2);
output_high(PIN_A3);
}
if(s_p[2] == 5){
output_low(PIN_A4);
output_high(PIN_A5);
}
if(s_p[3] == 5){
output_low(PIN_C6);
output_high(PIN_E0);
}
if(s_p[4] == 5){
output_low(PIN_E1);
output_high(PIN_E2);
}
if(s_p[5] == 5){
output_low(PIN_C5);
output_high(PIN_D0);
}
delay_us(delays);
if(s_p[0] == 3){
output_high(PIN_A0);
output_low(PIN_A1);
}
if(s_p[1] == 3){
output_high(PIN_A2);
output_low(PIN_A3);
}
if(s_p[2] == 3){
output_high(PIN_A4);
output_low(PIN_A5);
}
if(s_p[3] == 3){
output_high(PIN_C6);
output_low(PIN_E0);
}
if(s_p[4] == 3){
output_high(PIN_E1);
output_low(PIN_E2);
}
if(s_p[5] == 3){
output_high(PIN_C5);
output_low(PIN_D0);
}
if(s_p[0] == 0){
output_low(PIN_A0);
output_high(PIN_A1);
}
if(s_p[1] == 0){
output_low(PIN_A2);
output_high(PIN_A3);
}
if(s_p[2] == 0){
output_low(PIN_A4);
output_high(PIN_A5);
}
if(s_p[3] == 0){
output_low(PIN_C6);
output_high(PIN_E0);
}
if(s_p[4] == 0){
output_low(PIN_E1);
output_high(PIN_E2);
}
if(s_p[5] == 0){
output_low(PIN_C5);
output_high(PIN_D0);
}
delay_us(delays);
if(s_p[0] == 4){
output_high(PIN_A0);
output_low(PIN_A1);
}
if(s_p[1] == 4){
output_high(PIN_A2);
output_low(PIN_A3);
}
if(s_p[2] == 4){
output_high(PIN_A4);
output_low(PIN_A5);
}
if(s_p[3] == 4){
output_high(PIN_C6);
output_low(PIN_E0);
}
if(s_p[4] == 4){
output_high(PIN_E1);
output_low(PIN_E2);
}
if(s_p[5] == 4){
output_high(PIN_C5);
output_low(PIN_D0);
}
if(s_p[0] == 1){
output_low(PIN_A0);
output_high(PIN_A1);
}
if(s_p[1] == 1){
output_low(PIN_A2);
output_high(PIN_A3);
}
if(s_p[2] == 1){
output_low(PIN_A4);
output_high(PIN_A5);
}
if(s_p[3] == 1){
output_low(PIN_C6);
output_high(PIN_E0);
}
if(s_p[4] == 1){
output_low(PIN_E1);
output_high(PIN_E2);
}
if(s_p[5] == 1){
output_low(PIN_C5);
output_high(PIN_D0);
}
delay_us(delays);
if(s_p[0] == 5){
output_high(PIN_A0);
output_low(PIN_A1);
}
if(s_p[1] == 5){
output_high(PIN_A2);
output_low(PIN_A3);
}
if(s_p[2] == 5){
output_high(PIN_A4);
output_low(PIN_A5);
}
if(s_p[3] == 5){
output_high(PIN_C6);
output_low(PIN_E0);
}
if(s_p[4] == 5){
output_high(PIN_E1);
output_low(PIN_E2);
}
if(s_p[5] == 5){
output_high(PIN_C5);
output_low(PIN_D0);
}
if(s_p[0] == 2){
output_low(PIN_A0);
output_high(PIN_A1);
}
if(s_p[1] == 2){
output_low(PIN_A2);
output_high(PIN_A3);
}
if(s_p[2] == 2){
output_low(PIN_A4);
output_high(PIN_A5);
}
if(s_p[3] == 2){
output_low(PIN_C6);
output_high(PIN_E0);
}
if(s_p[4] == 2){
output_low(PIN_E1);
output_high(PIN_E2);
}
if(s_p[5] == 2){
output_low(PIN_C5);
output_high(PIN_D0);
}
delay_us(delays);
printf(lcd_putc,"\n\fPhases:%i%i%i%i%i%i\n",s_p[0],s_p[1],s_p[2],s_p[3],s_p[4],s_p[5]);
}
}


== Issues with Design ==
== Issues with Design ==

Revision as of 19:04, 19 March 2009

Team Members

  • Ankur Bakshi (Biomedical Engineering, Class of 2009)
  • Donald Redding (Mechanical Engineering, Class of 2009)
  • Ben Tollberg (Mechanical Engineering, Class of 2009)

Introduction

The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device {PPOD} found in the Laboratory for Intelligent Mechanical Systems (LIMS) at Northwestern. The PPOD-mini utilizes six speakers that act like actuators. The speakers are connected to a PVC plate via flexures of tygon and iron. In its current implementation, the phase of the speakers can be controlled independently, giving the device six degrees of freedom. The movement of objects placed on the PVC plate can be controlled by changing the phases of the speakers.

The PPOD mini measures about 12" x 12" x 8" and can be plugged into a wall outlet for power. It utilizes a switch to start the changing algorithm, a keypad for input to change the speaker phases, and an 16x2 line LCD for user interfacing and to output the speaker phases. A PIC 18f4520 provides the computing power. Each speaker is driven by an H-bridge, which is powered by a 10W power supply from Marlin Jones ([1]). The speakers are 1W, 16 ohm speakers from Jameco.

Operation

When first plugging in the PPOD-mini, the switch is triggered and the text on the LCD is garbled. By pressing the reset button on the PIC board or by pressing buttons on the keypad until clear text appears. To change the phase of a speaker, the switch must be pressed. Then following the instructions on the LCD, press the a number between one and six to select the speaker. Next, press a number between zero and five to choose a phase from 0-300 degrees in 60 degree increments. The increments can be changed by uploading a new program to the PIC. The speakers should then be running.

Mechanical Design

Circuit Diagram

Circuit schematic for PPOD mini project

To the right is the complete circuit schematic for our project. The +5V and GND for the L293D chips were supplied by the external power supply. The LCD was powered by the PIC +5V and GND in order to avoid some overheating issues that occurred when they were connected to the external supply. Each L293D chip controlled two speakers, with one full H-bridge for each speaker. The direction that voltage is applied to each speaker is controlled by the high or low signals that are output from the PIC to the H-bridges.

Code

#include <18f4520.h>
#fuses HS,NOLVP,NOWDT
#use delay (clock=40000000)
#include "key.c"
#include "flex_lcd.c" //lcd files

int32 frequency = 40;
int ii;
int32 halfperiod;
int32 delays;
int8 s_p[6]={0,0,0,0,0,0};
char k;

#INT_EXT             // designates that this is the routine to call when pin RB0/INTO changes state
void INT0isr() {
    
    int s;
    int flag=1;
    char speaker;
    char phase;
    
    int i, j, temp;
    
    printf(lcd_putc,"\fChanging Phase");
    delay_ms(10);
    printf(lcd_putc,"\n\fSpeaker Number:");
    while(flag==1){
        speaker = kbd_getc();               //read speaker number
        if(speaker!=0) {                    //determine speaker
            printf(lcd_putc,"%c",speaker);
            switch (speaker){
                case '1':
                    s=0;
                    flag=0;                 //exit loop if acceptable input is entered
                    break;       
                case '2':
                    s=1;
                    flag=0;
                    break;
                case '3':
                    s=2;
                    flag=0;
                    break;
                case '4':
                    s=3;
                    flag=0;
                    break;
                case '5':
                    s=4;
                    flag=0;
                    break;
                case '6':
                    s=5;
                    flag=0;
                    break;
                default:
                    printf(lcd_putc,"\n\fInvalid input.");
                    delay_ms(10);
                    printf(lcd_putc,"\n\nSpeaker Number:");
                    break;
            }
        }
    }
    
    flag=1;
    printf(lcd_putc,"\nEnter Phase:");
    while(flag==1){
        phase = kbd_getc();            //read in phase
        if(phase!=0) {
            printf(lcd_putc,"%c",phase);
            switch (phase){            //set phase array
                case '0':
                    s_p[s]=0;
                    flag=0;
                    break;
                case '1':
                    s_p[s]=1;
                    flag=0;
                    break;
                case '2':
                    s_p[s]=2;
                    flag=0;
                    break;
                case '3':
                    s_p[s]=3; 
                    flag=0;
                    break;
                case '4':
                    s_p[s]=4;
                    flag=0;
                    break;
                case '5':
                    s_p[s]=5;
                    flag=0;
                    break;
                default:
                    printf(lcd_putc,"\nInvalid input.");
                    delay_ms(10);
                    printf(lcd_putc,"\nEnter Phase:");
                    break;
            }
        }
    }
}

void main (){
    
    enable_interrupts(INT_EXT);
    enable_interrupts(GLOBAL); 
    ext_int_edge(0, L_TO_H); 
    
    halfperiod = 500000/frequency;
    
    delays = halfperiod/3;
    
    lcd_init();
    kbd_init(); //initialize keypad
    
    printf(lcd_putc,"Starting...\n");
    delay_ms(1000);
    printf(lcd_putc,"\n");
    
    while(true) {
        if(s_p[0] == 0){
               output_high(PIN_A0);
               output_low(PIN_A1);
        }
        if(s_p[1] == 0){
               output_high(PIN_A2);
               output_low(PIN_A3);
        }
        if(s_p[2] == 0){
               output_high(PIN_A4);
               output_low(PIN_A5);
        }
        if(s_p[3] == 0){
               output_high(PIN_C6);
               output_low(PIN_E0);
        }
        if(s_p[4] == 0){
               output_high(PIN_E1);
               output_low(PIN_E2);
        }
        if(s_p[5] == 0){
               output_high(PIN_C5);
               output_low(PIN_D0);
        }
        if(s_p[0] == 3){
               output_low(PIN_A0);
               output_high(PIN_A1);
        }
        if(s_p[1] == 3){
               output_low(PIN_A2);
               output_high(PIN_A3);
        }
        if(s_p[2] == 3){
               output_low(PIN_A4);
               output_high(PIN_A5);
        }
        if(s_p[3] == 3){
               output_low(PIN_C6);
               output_high(PIN_E0);
        }
        if(s_p[4] == 3){
               output_low(PIN_E1);
               output_high(PIN_E2);
        }
        if(s_p[5] == 3){
               output_low(PIN_C5);
               output_high(PIN_D0);
        }
        
        delay_us(delays);
        
        if(s_p[0] == 1){
               output_high(PIN_A0);
               output_low(PIN_A1);
        }
        if(s_p[1] == 1){
               output_high(PIN_A2);
               output_low(PIN_A3);
        }
        if(s_p[2] == 1){
               output_high(PIN_A4);
               output_low(PIN_A5);
        }
        if(s_p[3] == 1){
               output_high(PIN_C6);
               output_low(PIN_E0);
        }
        if(s_p[4] == 1){
               output_high(PIN_E1);
               output_low(PIN_E2);
        }
        if(s_p[5] == 1){
               output_high(PIN_C5);
               output_low(PIN_D0);
        }
        if(s_p[0] == 4){
               output_low(PIN_A0);
               output_high(PIN_A1);
        }
        if(s_p[1] == 4){
               output_low(PIN_A2);
               output_high(PIN_A3);
        }
        if(s_p[2] == 4){
               output_low(PIN_A4);
               output_high(PIN_A5);
        }
        if(s_p[3] == 4){
               output_low(PIN_C6);
               output_high(PIN_E0);
        }
        if(s_p[4] == 4){
               output_low(PIN_E1);
               output_high(PIN_E2);
        }
        if(s_p[5] == 4){
               output_low(PIN_C5);
               output_high(PIN_D0);
        }
        
        delay_us(delays);
        
        if(s_p[0] == 2){
               output_high(PIN_A0);
               output_low(PIN_A1);
        }
        if(s_p[1] == 2){
               output_high(PIN_A2);
               output_low(PIN_A3);
        }
        if(s_p[2] == 2){
               output_high(PIN_A4);
               output_low(PIN_A5);
        }
        if(s_p[3] == 2){
               output_high(PIN_C6);
               output_low(PIN_E0);
        }
        if(s_p[4] == 2){
               output_high(PIN_E1);
               output_low(PIN_E2);
        }
        if(s_p[5] == 2){
               output_high(PIN_C5);
               output_low(PIN_D0);
        }
        if(s_p[0] == 5){
               output_low(PIN_A0);
               output_high(PIN_A1);
        }
        if(s_p[1] == 5){
               output_low(PIN_A2);
               output_high(PIN_A3);
        }
        if(s_p[2] == 5){
               output_low(PIN_A4);
               output_high(PIN_A5);
        }
        if(s_p[3] == 5){
               output_low(PIN_C6);
               output_high(PIN_E0);
        }
        if(s_p[4] == 5){
               output_low(PIN_E1);
               output_high(PIN_E2); 
        }
        if(s_p[5] == 5){
               output_low(PIN_C5);
               output_high(PIN_D0);
        }
        
        delay_us(delays);
        
        if(s_p[0] == 3){
               output_high(PIN_A0);
               output_low(PIN_A1);
        }
        if(s_p[1] == 3){
               output_high(PIN_A2);
               output_low(PIN_A3);
        }
        if(s_p[2] == 3){
               output_high(PIN_A4);
               output_low(PIN_A5);
        }
        if(s_p[3] == 3){
               output_high(PIN_C6);
               output_low(PIN_E0);
        }
        if(s_p[4] == 3){
               output_high(PIN_E1);
               output_low(PIN_E2);
        }
        if(s_p[5] == 3){
               output_high(PIN_C5);
               output_low(PIN_D0);
        }
        if(s_p[0] == 0){
               output_low(PIN_A0);
               output_high(PIN_A1);
        }
        if(s_p[1] == 0){
               output_low(PIN_A2);
               output_high(PIN_A3);
        }
        if(s_p[2] == 0){
               output_low(PIN_A4);
               output_high(PIN_A5);
        }
        if(s_p[3] == 0){
               output_low(PIN_C6);
               output_high(PIN_E0);
        }
        if(s_p[4] == 0){
               output_low(PIN_E1);
               output_high(PIN_E2);
        }
        if(s_p[5] == 0){
               output_low(PIN_C5);
               output_high(PIN_D0);
        }
        
        delay_us(delays);
        
        if(s_p[0] == 4){
               output_high(PIN_A0);
               output_low(PIN_A1);
        }
        if(s_p[1] == 4){
               output_high(PIN_A2);
               output_low(PIN_A3);
        }
        if(s_p[2] == 4){
               output_high(PIN_A4);
               output_low(PIN_A5);
        }
        if(s_p[3] == 4){
               output_high(PIN_C6);
               output_low(PIN_E0);
        }
        if(s_p[4] == 4){
               output_high(PIN_E1);
               output_low(PIN_E2);
        }
        if(s_p[5] == 4){
               output_high(PIN_C5);
               output_low(PIN_D0);
        }
        if(s_p[0] == 1){
               output_low(PIN_A0);
               output_high(PIN_A1);
        }
        if(s_p[1] == 1){
               output_low(PIN_A2);
               output_high(PIN_A3);
        }
        if(s_p[2] == 1){
               output_low(PIN_A4);
               output_high(PIN_A5);
        }
        if(s_p[3] == 1){
               output_low(PIN_C6);
               output_high(PIN_E0);
        }
        if(s_p[4] == 1){
               output_low(PIN_E1);
               output_high(PIN_E2);
        }
        if(s_p[5] == 1){
               output_low(PIN_C5);
               output_high(PIN_D0);
        }
        
        delay_us(delays);
        
        if(s_p[0] == 5){
               output_high(PIN_A0);
               output_low(PIN_A1);
        }
        if(s_p[1] == 5){
               output_high(PIN_A2);
               output_low(PIN_A3);
        }
        if(s_p[2] == 5){
               output_high(PIN_A4);
               output_low(PIN_A5);
        }
        if(s_p[3] == 5){
               output_high(PIN_C6);
               output_low(PIN_E0); 
        }
        if(s_p[4] == 5){
               output_high(PIN_E1);
               output_low(PIN_E2);
        }
        if(s_p[5] == 5){
               output_high(PIN_C5);
               output_low(PIN_D0);
        }
        if(s_p[0] == 2){
               output_low(PIN_A0);
               output_high(PIN_A1);
        }
        if(s_p[1] == 2){
               output_low(PIN_A2);
               output_high(PIN_A3);
        }
        if(s_p[2] == 2){
               output_low(PIN_A4);
               output_high(PIN_A5);
        }
        if(s_p[3] == 2){
               output_low(PIN_C6);
               output_high(PIN_E0);
        }
        if(s_p[4] == 2){
               output_low(PIN_E1);
               output_high(PIN_E2);
        }
        if(s_p[5] == 2){
               output_low(PIN_C5);
               output_high(PIN_D0);
        }
        
        delay_us(delays);
        
        
        printf(lcd_putc,"\n\fPhases:%i%i%i%i%i%i\n",s_p[0],s_p[1],s_p[2],s_p[3],s_p[4],s_p[5]);
    }

}

Issues with Design

Future Steps

As mentioned in the previous section, the all the speakers do not vibrate with the same force. There are several ways to deal with this issue. First, a little experimentation may need to be done with the flexures. The flexures may be too stiff, preventing the diaphragm of the speakers from fully vibrating. The next thing to do is to check the level of the plate and the geometry of the speakers and insertion points. If the mass of the plate is unevenly distributed, some speakers may have to apply more force than others. Since the speakers will inevitably output unequal forces, amplitude control will most likely be necessary. This can be achieved by place a potentiometer between a line from the H-bridge and the speaker. Given the weak output of some speakers at 5V, reducing amplitude may not be sufficient. Raising the power source to 7V and getting higher power speakers (for example [2]) will resolve this issue.

The original PPOD used feedback from six accelerometers to independently control the amplitude of each of the speakers. One possible method to implement a simpler system would be to use one accelerometer in the middle of the plate. When all the speakers are set in phase, there should be Y acceleration without X acceleration. However, if not all of the speakers are firing equally, there will be X acceleration. Based on the X acceleration, the node that is misfiring can be calculated.

During testing, it was noted that holding down a speaker diaphragm (effectively turning it off) caused distinct movements. If the speakers are not strong enough to cause movement, adding the ability to turn of individual speakers may be necessary.