/*********************************************************** * hello.piezo.c * * based on hello.mag.45.c by Neil Gershenfeld * and http://www.protostack.com/blog/2011/02/analogue-to-digital-conversion-on-an-atmega168/ * and button44 by Rob Hart * set lfuse to 0x5E for 20 MHz xtal * * Adds ADC conversion to the hello piezo * * Brian Plancher * 11/02/16 * ***********************************************************/ #include #include #include // helper defs #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 // input and output devices // Piezo PA5 // Button1 PA6 // Button1 PA7 // LED1 PA2 // LED2 PA3 // LED3 PA4 #define input_port PORTA // The button is on port A #define input_direction DDRA // DDRA defines input/output for port A #define piezo_pin (1 << PA6) // The button is on pin 5 of port A #define button1_pin (1 << PA6) // The button is on pin 6 of port A #define button2_pin (1 << PA7) // The button is on pin 7 of port A #define input_pins PINA // PINA is the register that is read to detect input high or low. #define LED_port PORTA // port A will be used for the LED #define LED_direction DDRA #define LED1_pin (1 << PA2) #define LED2_pin (1 << PA3) #define LED3_pin (1 << PA4) int main(void) { // set clock divider to /1 CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // initialize pins output(LED_direction, LED1_pin|LED2_pin|LED3_pin); // sed LEDs for output set(input_port, button1_pin|button2_pin); // turn on pull-up for the buttons input(input_direction, button1_pin|button2_pin|piezo_pin); // make buttons and piezos input // init A/D for the piezo ADMUX = (0 << REFS2) | (0 << REFS1) | (0 << REFS0) // Vcc ref | (0 << ADLAR) // right adjust | (0 << MUX3) | (1 << MUX2) | (0 << MUX1) | (1 << MUX0); // ADC5 is PA 5 ADCSRA = (1 << ADEN) // enable | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128 // main loop while (1) { // use LED 2 and 3 for the piezo level piezo_flag = ADCSRA & (1 << ADSC); // tests if in an active ADC conversion // ADC done or not started if (~piezo_flag){ ADCSRA |= (1 << ADSC); // run it again int piezo_val = ADC; // 16 bit val // 16 bit means 65536 so if >3000 then both lights // if >1500 then second lights // if >500 then first light else none if (piezo_val > 3000){ set(LED_port,LED1_pin); set(LED_port,LED2_pin); } else if(piezo_val > 1500){ set(LED_port,LED2_pin); } else if(piezo_val > 500){ set(LED_port,LED1_pin); } else{ clear(LED_port,LED2_pin); clear(LED_port,LED3_pin); } } // combine the buttons on one LED int btn1_flag = pin_test(input_pins,button1_pin); int btn2_flag = pin_test(input_pins,button2_pin); if (btn1_flag & btn2_flag){ clear(LED_port,LED1_pin); } else{ set(LED_port,LED1_pin); } } return 0; }