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);
}
}