<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://hades.mech.northwestern.edu//index.php?action=history&amp;feed=atom&amp;title=AP_KS_GM-control_panel_code.c</id>
	<title>AP KS GM-control panel code.c - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://hades.mech.northwestern.edu//index.php?action=history&amp;feed=atom&amp;title=AP_KS_GM-control_panel_code.c"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=AP_KS_GM-control_panel_code.c&amp;action=history"/>
	<updated>2026-04-11T04:23:19Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=AP_KS_GM-control_panel_code.c&amp;diff=11757&amp;oldid=prev</id>
		<title>Kwang Sim at 06:06, 19 March 2009</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=AP_KS_GM-control_panel_code.c&amp;diff=11757&amp;oldid=prev"/>
		<updated>2009-03-19T06:06:55Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 06:06, 19 March 2009&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 48:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 48:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;//constants controlling sensitivity of controls&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;//constants controlling sensitivity of controls&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;#define POT_CHANGE_WINDOW 5&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;#define POT_CHANGE_WINDOW 5&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-deletedline diff-side-deleted&quot;&gt;&lt;div&gt;#define SCROLL_DEADBAND 40&lt;/div&gt;&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-added&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;div&gt;#define MESSAGE_BUTTON_COOLDOWN 500&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;div&gt;#define MESSAGE_BUTTON_COOLDOWN 500&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-deleted&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-context diff-side-added&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Kwang Sim</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=AP_KS_GM-control_panel_code.c&amp;diff=11745&amp;oldid=prev</id>
		<title>Kwang Sim at 05:19, 19 March 2009</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=AP_KS_GM-control_panel_code.c&amp;diff=11745&amp;oldid=prev"/>
		<updated>2009-03-19T05:19:17Z</updated>

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