AP KS GM-control panel code.c
From Mech
Jump to navigationJump to search/********************************************** * controlpanel.c * Author:Greg McGlynn * Persistence-of-Vision Display project * Alexander Park, Kwang Xiong Sim, Grag McGlynn * ME 333 Mechatronics - Winter 2008 * Northwestern University * * This code runs on the control panel PIC. It polls the potentiomemters * and pushbutton for significant changes; when one of the inputs changes (i.e., * when the button is pressed or a potentiometer is turned), it sends a * command to the display PIC informing the display of the change. * * Simultaneously, the PIC is listening for RS232 signals coming in on * pin B1. If the USB cable is plugged in this is connected to PC transmit. The * PC will send commands along this line intended for the display PIC. The * control panel PIC's job is to accept these commands and relay them verbatim * to the display PIC through the XBee. **********************************************/ #include <18f4520.h> #device adc=8 #fuses EC,NOLVP,NOWDT,NOPROTECT #use delay(clock=40000000) //We use software RS232 //Signals are sent out to the XBee on pin B3 and signals come from PC //on pin B1. #use rs232(baud=9600, xmit=PIN_B3, rcv=PIN_B1) //image angle is a number 0-192 that gives the home column of the POV int16 image_angle = 0; //the current image angle setting // - scroll speed is a number 0-255 // - 128 is stationary; higher numbers scroll one way; lower numbers the other // - (scroll speed) - 128 is proportional change in image angle per second int16 scroll_speed = 128; //the current scroll speed setting int button_state = 0; //the current button state (1 = pressed, 0 = not) int16 button_cooldown_counter = 0; //a debouncing measure //the adc channels of the four inputs: #define IMAGE_ANGLE_CHAN 3 #define SCROLL_SPEED_CHAN 2 #define MESSAGE_NUM_CHAN 1 #define MESSAGE_BUTTON_CHAN 0 //constants controlling sensitivity of controls #define POT_CHANGE_WINDOW 5 #define MESSAGE_BUTTON_COOLDOWN 500 int ignore = true; //ignore the first interrupt on B1; it's a false alarm //this is called when we start to receive a 4-byte message from the PC #int_ext1 void incoming_rs232() { int byte1, byte2, byte3, byte4; //this interupt fires on startup even though there's no message. so //ignore this first message if(ignore) { ignore = false; return; } //get the four bytes byte1 = getc(); byte2 = getc(); byte3 = getc(); byte4 = getc(); //relay them to the xbee putc(byte1); putc(byte2); putc(byte3); putc(byte4); } //read from a specified ADC channel int pot_read(int chan) { set_adc_channel(chan); delay_us(10); return read_adc(); } //the absolute value of the difference between two int16's: int16 diff(int16 a, int16 b) { if(a > b) return a - b; else return b - a; } //send a command to the display PIC //commands are four bytes: //byte 1: 0xff //byte 2: 0xff //byte 3: command type //byte 4: command argument void send_command(int type, int argument) { //we disable interrupts while we send commands so that we don't get //interrupted by an incoming command from the PC disable_interrupts(INT_EXT1); putc(0xff); putc(0xff); putc(type); putc(argument); enable_interrupts(INT_EXT1); } //a forumula for converting the reading from the message # pot to a number //from 0 to 10 int interpret_message_reading(int16 message_reading) { if(message_reading == 0) return 0; if(message_reading == 255) return 10; else return (int)((int16)message_reading*(int16)9/(int16)254+(int16)1); } void main() { //readings from each pot: int16 angle_reading; int16 scroll_reading; int button_reading; int16 message_reading; //setup an interrupt on high-to-low transistions on pin B1. This means //that an interrupt is triggered when we start to receive an RS232 signal //from the PC, so we can read the incoming message. enable_interrupts(INT_EXT1); enable_interrupts(GLOBAL); ext_int_edge(1, H_TO_L); setup_adc_ports(AN0_TO_AN3); setup_adc(ADC_CLOCK_INTERNAL); set_adc_channel(3); //main loop: poll the controls while(true) { //read the image angle pot and convert it to an image angle; if there's //been a significant change send a command to the display angle_reading = pot_read(IMAGE_ANGLE_CHAN); angle_reading = angle_reading * 192 / 255; angle_reading = 192 - angle_reading; if(diff(angle_reading, image_angle) > POT_CHANGE_WINDOW) { image_angle = angle_reading; send_command(0x01, image_angle); } //read the scroll speed pot; if there's //been a significant change send a command to the display scroll_reading = pot_read(SCROLL_SPEED_CHAN); if(diff(scroll_reading, scroll_speed) > POT_CHANGE_WINDOW) { scroll_speed = scroll_reading; send_command(0x02, scroll_speed); } //check the button state; if it's been pressed read the message number //pot and send a command to the display to show the corresponding //builtin message button_reading = (pot_read(MESSAGE_BUTTON_CHAN) > 128 ? 1 : 0); if(button_reading == 1 && button_state == 0) { if(button_cooldown_counter == 0) { message_reading = pot_read(MESSAGE_NUM_CHAN); message_reading = interpret_message_reading(message_reading); output_d(message_reading); send_command(0x03, message_reading); button_cooldown_counter = MESSAGE_BUTTON_COOLDOWN; } } button_state = button_reading; if(button_cooldown_counter != 0) button_cooldown_counter -= 1; delay_ms(1); } }