Difference between revisions of "ProcessingPIC32Communication"
NickMarchuk (talk | contribs) |
NickMarchuk (talk | contribs) |
||
(19 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== Tutorial: Communication between a PIC32 and Processing == |
== Tutorial: Communication between a PIC32 and Processing == |
||
This tutorial will demonstrate how to use Processing to communicate with a |
This tutorial will demonstrate how to use Processing to communicate with a microcontroller, specifically the UBW32, a PIC32MX460F512L device. |
||
An FTDI Serial to USB cable will be used to communicate over USB. |
An FTDI Serial to USB cable will be used to communicate over USB. |
||
Line 7: | Line 7: | ||
Download and install the latest version of MPLAB (v8.53) [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002#P175_5158 here]. |
Download and install the latest version of MPLAB (v8.53) [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002#P175_5158 here]. |
||
Also download and install the C compiler [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en536656 here] and Microchip Applications Library (4/28/2010) [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en547784 here] if you have never installed MPLAB on your computer. |
|||
Also download and install these if you haven't in previous installations of MPLAB. |
|||
Download this zip |
Download this [[Media:ubw32_tutorial.zip]] that has code specific to the UBW32. Unzip it into the directory you will work in today. |
||
Start a new project in MPLAB and include the files specific to the UBW32 |
Start a new project in MPLAB and include the files from ubw32_tutorial.zip. Note that this procdefs.ld file is specific to the UBW32, if you use the one for the NU32, you will overwrite your bootloader! Your project should look like: |
||
[[Image:ubw32_objectwindow.jpg]] |
|||
Don't forget to tell the compiler where to find some source files: |
|||
[[Image:ubw32_buildoptionswindow.jpg]] |
|||
We will program the UBW32 to: |
We will program the UBW32 to: |
||
* Interrupt when it receives a character over RS232 |
|||
* Read an analog value and send it over RS232 to the PC |
|||
* Change how often it outputs data according to the character it receives |
|||
Specifically: |
Specifically: |
||
* Initially output at 5Hz |
|||
* Output at 10Hz if a "b" is received |
|||
* Output at 100Hz if a "c" is received |
|||
* Output at 5Hz if a "a" is received |
|||
* Stop outputting if a "p" is received |
|||
* Start outputting if a "t" is received |
|||
* Toggle an LED on the UBW32 board if a "w" is received |
|||
The following code achieves this: |
The following code achieves this: |
||
<code> |
|||
<pre> |
|||
Code |
|||
</code> |
|||
#include "GenericTypeDefs.h" |
|||
#include "Compiler.h" |
|||
#include "HardwareProfile.h" |
|||
// NOTE THAT BECAUSE WE USE THE BOOTLOADER, NO CONFIGURATION IS NECESSARY |
|||
// THE BOOTLOADER PROJECT ACTUALLY CONTROLS ALL OF OUR CONFIG BITS |
|||
#define SYS_FREQ (80000000L) |
|||
#define DESIRED_BAUDRATE (115200) // The desired rs232 BaudRate |
|||
unsigned short int channel4; // conversion result as read from result buffer |
|||
char UART1_out_buffer[64]; |
|||
int hz5 = 62500; // 80000000/256/5 |
|||
int hz10 = 31250; // 80000000/256/10 |
|||
int hz100 = 3125; // 80000000/256/100 |
|||
// functions |
|||
void init_serial(); |
|||
void init_analog(); |
|||
void init_timer(int freq); |
|||
int main(void) |
|||
{ |
|||
// Configure the proper PB frequency and the number of wait states |
|||
SYSTEMConfigPerformance(80000000L); |
|||
// Turn off JTAG so we get the pins back |
|||
mJTAGPortEnable(0); |
|||
//Initialize all of the LED pins |
|||
mInitAllLEDs(); |
|||
// enable multi-vector interrupts |
|||
INTEnableSystemMultiVectoredInt(); |
|||
init_serial(); |
|||
init_timer(hz10); |
|||
init_analog(); |
|||
while(1) |
|||
{ |
|||
// empty, interrupt driven code |
|||
} |
|||
} |
|||
// UART 1 interrupt handler, gets info from processing |
|||
// it is set at priority level 1 |
|||
void __ISR(_UART1_VECTOR, ipl1) IntUart1Handler(void) |
|||
{ |
|||
char data; |
|||
// Is this an RX interrupt? |
|||
if(mU1RXGetIntFlag()) |
|||
{ |
|||
// Clear the RX interrupt Flag |
|||
mU1RXClearIntFlag(); |
|||
data = (char) ReadUART1(); |
|||
// Echo what we just received. |
|||
//putcUART1(data); |
|||
if (data == 'a'){ |
|||
init_timer(hz5); |
|||
} |
|||
else if (data == 'b'){ |
|||
init_timer(hz10); |
|||
} |
|||
else if (data == 'c'){ |
|||
init_timer(hz100); |
|||
} |
|||
else if (data == 'p'){ |
|||
mT3IntEnable(0); |
|||
} |
|||
else if (data == 't'){ |
|||
init_timer(hz5); |
|||
} |
|||
else if (data == 'w'){ |
|||
mLED_3_Toggle(); |
|||
} |
|||
} |
|||
// We don't care about TX interrupt |
|||
if ( mU1TXGetIntFlag() ) |
|||
{ |
|||
mU1TXClearIntFlag(); |
|||
} |
|||
} // end UART1 interrupt |
|||
// interrput code for the timer 3, priority level 2 |
|||
void __ISR( _TIMER_3_VECTOR, ipl2) T3Interrupt( void) |
|||
{ |
|||
// read analog |
|||
channel4 = ReadADC10(0); // read the result of channel 4 |
|||
sprintf(UART1_out_buffer,"a %d\r\n",channel4); |
|||
putsUART1(UART1_out_buffer); |
|||
// clear interrupt flag and exit |
|||
mT3ClearIntFlag(); |
|||
} // end T3 Interrupt |
|||
void init_serial() { |
|||
int pbClk; |
|||
// Configure the system performance |
|||
pbClk = SYSTEMConfigPerformance(SYS_FREQ); |
|||
// define setup Configuration 1 for OpenUARTx |
|||
#define config1 UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN |
|||
// define setup Configuration 2 for OpenUARTx |
|||
#define config2 UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR |
|||
// Open UART1 with config1 and config2 |
|||
OpenUART1( config1, config2, pbClk/16/DESIRED_BAUDRATE-1); //U1RX=F2, U1TX=F8 |
|||
// Configure UART1 RX Interrupt with priority 1 |
|||
ConfigIntUART1(UART_INT_PR1 | UART_RX_INT_EN); |
|||
} // end init serial |
|||
void init_analog() { |
|||
// configure and enable the ADC |
|||
CloseADC10(); // ensure the ADC is off before setting the configuration |
|||
// define setup parameters for OpenADC10 |
|||
// Turn module on | output in integer | trigger mode auto | enable autosample |
|||
#define PARAM1 ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON |
|||
// define setup parameters for OpenADC10 |
|||
// ADC ref external | disable offset test | enable scan mode | perform 2 samples | use one buffer | use MUXA mode |
|||
#define PARAM2 ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_2 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF |
|||
// define setup parameters for OpenADC10 |
|||
// use ADC internal clock | set sample time |
|||
#define PARAM3 ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15 |
|||
// define setup parameters for OpenADC10 |
|||
// set AN4 |
|||
#define PARAM4 ENABLE_AN4_ANA |
|||
// define setup parameters for OpenADC10 |
|||
// do not assign channels to scan |
|||
#define PARAM5 SKIP_SCAN_AN0 | SKIP_SCAN_AN1 | SKIP_SCAN_AN2 | SKIP_SCAN_AN3 | SKIP_SCAN_AN6 | SKIP_SCAN_AN7 | SKIP_SCAN_AN8 | SKIP_SCAN_AN9 | SKIP_SCAN_AN10 | SKIP_SCAN_AN11 | SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15 |
|||
// use ground as neg ref for A | use AN4 (B4) and AN5(B5) for input A |
|||
// configure to sample AN4 |
|||
SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF); // configure to sample AN4 |
|||
OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above |
|||
EnableADC10(); // Enable the ADC |
|||
while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers |
|||
} // end init_analog |
|||
void init_timer(int freq) { |
|||
// init Timer3 mode and period (PR3) |
|||
OpenTimer3( T3_ON | T3_PS_1_256 | T3_SOURCE_INT, freq); // 30Hz |
|||
mT3SetIntPriority( 2); // set Timer3 Interrupt Priority |
|||
mT3ClearIntFlag(); // clear interrupt flag |
|||
mT3IntEnable( 1); // enable timer3 interrupts |
|||
} |
|||
</pre> |
|||
== Test the UBW32 code == |
== Test the UBW32 code == |
||
Line 43: | Line 211: | ||
Open Processing and save the blank sketch. This will create a folder for all the files the sketch will use. |
Open Processing and save the blank sketch. This will create a folder for all the files the sketch will use. |
||
Download and extract the [http://www.sojamo.de/libraries/controlP5/ controlP5] GUI library for Processing. Put it a folder called |
Download and extract the [http://www.sojamo.de/libraries/controlP5/ controlP5] GUI library for Processing. Put it a folder called "libraries" in the Processing folder of My Documents (the same root directory as the folder that was made when you saved your blank sketch). |
||
The sketch we will make will open the UBW32's virtual serial port and communicate with the UBW32. It will plot the analog values the UBW32 sends and have buttons to stop and start the data, and change the data rate. |
|||
The following code achieves this: |
The following code achieves this: |
||
<code> |
|||
<pre> |
|||
code |
|||
</code> |
|||
// serial variables |
|||
import processing.serial.*; // serial library |
|||
Serial[] myPorts = new Serial[1]; // lets only use one port in this sketch |
|||
// GUI variables |
|||
import controlP5.*; // controlP5 library |
|||
ControlP5 controlP5; // create the handler to allow for controlP5 items |
|||
Textlabel txtlblWhichcom; // text label displaying which comm port is being used |
|||
ListBox commListbox; // list of available com ports |
|||
// globals |
|||
int num_x = 200; |
|||
int num_y = 200; |
|||
int buffer_index = 0; |
|||
int[] rolling_buffer = new int[num_x]; |
|||
int draw_x_offset = 200; |
|||
int draw_y_offset = 100; |
|||
// setup |
|||
void setup() { |
|||
size(600,400); |
|||
frameRate(30); |
|||
controlP5 = new ControlP5(this); // initialize the GUI controls |
|||
println(Serial.list()); // print the comm ports to the debug window for debugging purposes |
|||
// make a listbox and populate it with the available comm ports |
|||
commListbox = controlP5.addListBox("myList",5,25,120,120); //addListBox(name,x,y,width,height) |
|||
commListbox.captionLabel().toUpperCase(false); |
|||
commListbox.captionLabel().set("Listbox label"); |
|||
for(int i=0;i<Serial.list().length;i++) { |
|||
commListbox.addItem("port: "+Serial.list()[i],i); // addItem(name,value) |
|||
} |
|||
// text label for which comm port selected |
|||
txtlblWhichcom = controlP5.addTextlabel("txtlblWhichcom","No Port Selected",150,25); // textlabel(name,text,x,y) |
|||
// a button to send the letter a |
|||
controlP5.addButton("Send_5Hz",1,5,210,80,19); // buton(name,value,x,y,width,height) |
|||
// a button to send the letter b |
|||
controlP5.addButton("Send_10Hz",1,5,230,80,19); // buton(name,value,x,y,width,height) |
|||
// a button to send the letter c |
|||
controlP5.addButton("Send_100Hz",1,5,250,80,19); // buton(name,value,x,y,width,height) |
|||
// a button to send the letter p |
|||
controlP5.addButton("Send_Stop",1,5,270,80,19); // buton(name,value,x,y,width,height) |
|||
// a button to send the letter t |
|||
controlP5.addButton("Send_Start",1,5,290,80,19); // buton(name,value,x,y,width,height) |
|||
// a button to send the letter w |
|||
controlP5.addButton("Send_Toggle",1,5,310,80,19); // buton(name,value,x,y,width,height) |
|||
// initialize the rolling buffer |
|||
for(int i = 0; i < num_x; i++) { |
|||
rolling_buffer[i] = 200; |
|||
} |
|||
} |
|||
// infinite loop |
|||
void draw() { |
|||
background(0,0,0); |
|||
// draw the data in the buffer |
|||
strokeWeight(4); // weight of lines between data pnts |
|||
stroke(0,255,0); // green line |
|||
for(int i = 0; i < num_x-1; i++) { |
|||
line(i+draw_x_offset,rolling_buffer[i]+draw_y_offset,i+1+draw_x_offset,rolling_buffer[i+1]+draw_y_offset); |
|||
} |
|||
} |
|||
// print the name of the control being triggered (for debugging) and see if it was a Listbox event |
|||
public void controlEvent(ControlEvent theEvent) { |
|||
// ListBox is if type ControlGroup, you need to check the Event with if (theEvent.isGroup())to avoid an error message from controlP5 |
|||
if (theEvent.isGroup()) { |
|||
// an event from a group |
|||
if (theEvent.name()=="myList") { |
|||
InitSerial(theEvent.group().value()); // initialize the serial port selected |
|||
//println("got myList"+" value = "+theEvent.group().value()); // for debugging |
|||
} |
|||
} |
|||
else { |
|||
//println(theEvent.controller().name()); // for debugging |
|||
} |
|||
} |
|||
// run this when button is triggered, send a char |
|||
public void Send_5Hz(int theValue) { |
|||
myPorts[0].write("a"); // write an a |
|||
println("sent a"); // print it to the debug screen as well |
|||
} |
|||
// run this when button is triggered, send a char |
|||
public void Send_10Hz(int theValue) { |
|||
myPorts[0].write("b"); // write an a |
|||
println("sent b"); // print it to the debug screen as well |
|||
} |
|||
// run this when button is triggered, send a char |
|||
public void Send_100Hz(int theValue) { |
|||
myPorts[0].write("c"); // write an a |
|||
println("sent c"); // print it to the debug screen as well |
|||
} |
|||
// run this when button is triggered, send a char |
|||
public void Send_Stop(int theValue) { |
|||
myPorts[0].write("p"); // write an a |
|||
println("sent p"); // print it to the debug screen as well |
|||
} |
|||
// run this when button is triggered, send a char |
|||
public void Send_Start(int theValue) { |
|||
myPorts[0].write("t"); // write an a |
|||
println("sent t"); // print it to the debug screen as well |
|||
} |
|||
// run this when button is triggered, send a char |
|||
public void Send_Toggle(int theValue) { |
|||
myPorts[0].write("w"); // write an a |
|||
println("sent w"); // print it to the debug screen as well |
|||
} |
|||
// initialize the serial port selected in the listBox |
|||
void InitSerial(float portValue) { |
|||
println("initializing serial " + int(portValue) + " in serial.list()"); // for debugging |
|||
String portPos = Serial.list()[int(portValue)]; // grab the name of the serial port |
|||
txtlblWhichcom.setValue("COM Initialized = " + portPos); |
|||
myPorts[0] = new Serial(this, portPos, 115200); // initialize the port |
|||
// read bytes into a buffer until you get a linefeed (ASCII 10): |
|||
myPorts[0].bufferUntil('\n'); |
|||
println("done init serial"); |
|||
} |
|||
// serial event, check which port generated the event |
|||
// just in case there are more than 1 ports open |
|||
void serialEvent(Serial thisPort) { |
|||
// variable to hold the number of the port: |
|||
int portNumber = -1; |
|||
// iterate over the list of ports opened, and match the |
|||
// one that generated this event: |
|||
for (int p = 0; p < myPorts.length; p++) { |
|||
if (thisPort == myPorts[p]) { |
|||
portNumber = p; |
|||
} |
|||
} |
|||
// read the serial buffer until a newline appears |
|||
String myString = thisPort.readStringUntil('\n'); |
|||
// the following is for streaming packets of data that need to be parsed |
|||
// if you got any bytes other than the newline |
|||
if (myString != null) { |
|||
String[] match_a = match(myString, "a"); |
|||
if (match_a != null) { // data starting with an a |
|||
myString = trim(myString); // ditch the newline |
|||
int[] sensor = int(split(myString.substring(2), ' ')); |
|||
//println(sensor[0]); |
|||
rolling_buffer[buffer_index] = int(map(sensor[0],0,1023,num_y,0)); // map(current number,min current number, max current number, min new number, max new number) |
|||
//println(int(map(sensor[0],0,1023,num_y,0))); |
|||
buffer_index++; |
|||
if (buffer_index >= num_y) { |
|||
buffer_index = 0; |
|||
} |
|||
} |
|||
} |
|||
} // end serialEvent |
|||
</pre> |
Latest revision as of 09:29, 16 July 2010
Tutorial: Communication between a PIC32 and Processing
This tutorial will demonstrate how to use Processing to communicate with a microcontroller, specifically the UBW32, a PIC32MX460F512L device. An FTDI Serial to USB cable will be used to communicate over USB.
UBW32 Setup
Download and install the latest version of MPLAB (v8.53) here.
Also download and install the C compiler here and Microchip Applications Library (4/28/2010) here if you have never installed MPLAB on your computer.
Download this Media:ubw32_tutorial.zip that has code specific to the UBW32. Unzip it into the directory you will work in today.
Start a new project in MPLAB and include the files from ubw32_tutorial.zip. Note that this procdefs.ld file is specific to the UBW32, if you use the one for the NU32, you will overwrite your bootloader! Your project should look like:
Don't forget to tell the compiler where to find some source files:
We will program the UBW32 to:
- Interrupt when it receives a character over RS232
- Read an analog value and send it over RS232 to the PC
- Change how often it outputs data according to the character it receives
Specifically:
- Initially output at 5Hz
- Output at 10Hz if a "b" is received
- Output at 100Hz if a "c" is received
- Output at 5Hz if a "a" is received
- Stop outputting if a "p" is received
- Start outputting if a "t" is received
- Toggle an LED on the UBW32 board if a "w" is received
The following code achieves this:
#include "GenericTypeDefs.h" #include "Compiler.h" #include "HardwareProfile.h" // NOTE THAT BECAUSE WE USE THE BOOTLOADER, NO CONFIGURATION IS NECESSARY // THE BOOTLOADER PROJECT ACTUALLY CONTROLS ALL OF OUR CONFIG BITS #define SYS_FREQ (80000000L) #define DESIRED_BAUDRATE (115200) // The desired rs232 BaudRate unsigned short int channel4; // conversion result as read from result buffer char UART1_out_buffer[64]; int hz5 = 62500; // 80000000/256/5 int hz10 = 31250; // 80000000/256/10 int hz100 = 3125; // 80000000/256/100 // functions void init_serial(); void init_analog(); void init_timer(int freq); int main(void) { // Configure the proper PB frequency and the number of wait states SYSTEMConfigPerformance(80000000L); // Turn off JTAG so we get the pins back mJTAGPortEnable(0); //Initialize all of the LED pins mInitAllLEDs(); // enable multi-vector interrupts INTEnableSystemMultiVectoredInt(); init_serial(); init_timer(hz10); init_analog(); while(1) { // empty, interrupt driven code } } // UART 1 interrupt handler, gets info from processing // it is set at priority level 1 void __ISR(_UART1_VECTOR, ipl1) IntUart1Handler(void) { char data; // Is this an RX interrupt? if(mU1RXGetIntFlag()) { // Clear the RX interrupt Flag mU1RXClearIntFlag(); data = (char) ReadUART1(); // Echo what we just received. //putcUART1(data); if (data == 'a'){ init_timer(hz5); } else if (data == 'b'){ init_timer(hz10); } else if (data == 'c'){ init_timer(hz100); } else if (data == 'p'){ mT3IntEnable(0); } else if (data == 't'){ init_timer(hz5); } else if (data == 'w'){ mLED_3_Toggle(); } } // We don't care about TX interrupt if ( mU1TXGetIntFlag() ) { mU1TXClearIntFlag(); } } // end UART1 interrupt // interrput code for the timer 3, priority level 2 void __ISR( _TIMER_3_VECTOR, ipl2) T3Interrupt( void) { // read analog channel4 = ReadADC10(0); // read the result of channel 4 sprintf(UART1_out_buffer,"a %d\r\n",channel4); putsUART1(UART1_out_buffer); // clear interrupt flag and exit mT3ClearIntFlag(); } // end T3 Interrupt void init_serial() { int pbClk; // Configure the system performance pbClk = SYSTEMConfigPerformance(SYS_FREQ); // define setup Configuration 1 for OpenUARTx #define config1 UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN // define setup Configuration 2 for OpenUARTx #define config2 UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR // Open UART1 with config1 and config2 OpenUART1( config1, config2, pbClk/16/DESIRED_BAUDRATE-1); //U1RX=F2, U1TX=F8 // Configure UART1 RX Interrupt with priority 1 ConfigIntUART1(UART_INT_PR1 | UART_RX_INT_EN); } // end init serial void init_analog() { // configure and enable the ADC CloseADC10(); // ensure the ADC is off before setting the configuration // define setup parameters for OpenADC10 // Turn module on | output in integer | trigger mode auto | enable autosample #define PARAM1 ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON // define setup parameters for OpenADC10 // ADC ref external | disable offset test | enable scan mode | perform 2 samples | use one buffer | use MUXA mode #define PARAM2 ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_2 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF // define setup parameters for OpenADC10 // use ADC internal clock | set sample time #define PARAM3 ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15 // define setup parameters for OpenADC10 // set AN4 #define PARAM4 ENABLE_AN4_ANA // define setup parameters for OpenADC10 // do not assign channels to scan #define PARAM5 SKIP_SCAN_AN0 | SKIP_SCAN_AN1 | SKIP_SCAN_AN2 | SKIP_SCAN_AN3 | SKIP_SCAN_AN6 | SKIP_SCAN_AN7 | SKIP_SCAN_AN8 | SKIP_SCAN_AN9 | SKIP_SCAN_AN10 | SKIP_SCAN_AN11 | SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15 // use ground as neg ref for A | use AN4 (B4) and AN5(B5) for input A // configure to sample AN4 SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF); // configure to sample AN4 OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above EnableADC10(); // Enable the ADC while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers } // end init_analog void init_timer(int freq) { // init Timer3 mode and period (PR3) OpenTimer3( T3_ON | T3_PS_1_256 | T3_SOURCE_INT, freq); // 30Hz mT3SetIntPriority( 2); // set Timer3 Interrupt Priority mT3ClearIntFlag(); // clear interrupt flag mT3IntEnable( 1); // enable timer3 interrupts }
Test the UBW32 code
Plug your FTDI cable into your computer and determine its port number (ex COM3). Run HyperTerminal (in XP only) or PuTTY. Open the correct com port and set the baud. Turn on the UBW32. Data should start to stream to the terminal. Type each character programmed and see the effect.
Processing Setup
Download Processing (v1.2.1).
Open Processing and save the blank sketch. This will create a folder for all the files the sketch will use.
Download and extract the controlP5 GUI library for Processing. Put it a folder called "libraries" in the Processing folder of My Documents (the same root directory as the folder that was made when you saved your blank sketch).
The sketch we will make will open the UBW32's virtual serial port and communicate with the UBW32. It will plot the analog values the UBW32 sends and have buttons to stop and start the data, and change the data rate.
The following code achieves this:
// serial variables import processing.serial.*; // serial library Serial[] myPorts = new Serial[1]; // lets only use one port in this sketch // GUI variables import controlP5.*; // controlP5 library ControlP5 controlP5; // create the handler to allow for controlP5 items Textlabel txtlblWhichcom; // text label displaying which comm port is being used ListBox commListbox; // list of available com ports // globals int num_x = 200; int num_y = 200; int buffer_index = 0; int[] rolling_buffer = new int[num_x]; int draw_x_offset = 200; int draw_y_offset = 100; // setup void setup() { size(600,400); frameRate(30); controlP5 = new ControlP5(this); // initialize the GUI controls println(Serial.list()); // print the comm ports to the debug window for debugging purposes // make a listbox and populate it with the available comm ports commListbox = controlP5.addListBox("myList",5,25,120,120); //addListBox(name,x,y,width,height) commListbox.captionLabel().toUpperCase(false); commListbox.captionLabel().set("Listbox label"); for(int i=0;i<Serial.list().length;i++) { commListbox.addItem("port: "+Serial.list()[i],i); // addItem(name,value) } // text label for which comm port selected txtlblWhichcom = controlP5.addTextlabel("txtlblWhichcom","No Port Selected",150,25); // textlabel(name,text,x,y) // a button to send the letter a controlP5.addButton("Send_5Hz",1,5,210,80,19); // buton(name,value,x,y,width,height) // a button to send the letter b controlP5.addButton("Send_10Hz",1,5,230,80,19); // buton(name,value,x,y,width,height) // a button to send the letter c controlP5.addButton("Send_100Hz",1,5,250,80,19); // buton(name,value,x,y,width,height) // a button to send the letter p controlP5.addButton("Send_Stop",1,5,270,80,19); // buton(name,value,x,y,width,height) // a button to send the letter t controlP5.addButton("Send_Start",1,5,290,80,19); // buton(name,value,x,y,width,height) // a button to send the letter w controlP5.addButton("Send_Toggle",1,5,310,80,19); // buton(name,value,x,y,width,height) // initialize the rolling buffer for(int i = 0; i < num_x; i++) { rolling_buffer[i] = 200; } } // infinite loop void draw() { background(0,0,0); // draw the data in the buffer strokeWeight(4); // weight of lines between data pnts stroke(0,255,0); // green line for(int i = 0; i < num_x-1; i++) { line(i+draw_x_offset,rolling_buffer[i]+draw_y_offset,i+1+draw_x_offset,rolling_buffer[i+1]+draw_y_offset); } } // print the name of the control being triggered (for debugging) and see if it was a Listbox event public void controlEvent(ControlEvent theEvent) { // ListBox is if type ControlGroup, you need to check the Event with if (theEvent.isGroup())to avoid an error message from controlP5 if (theEvent.isGroup()) { // an event from a group if (theEvent.name()=="myList") { InitSerial(theEvent.group().value()); // initialize the serial port selected //println("got myList"+" value = "+theEvent.group().value()); // for debugging } } else { //println(theEvent.controller().name()); // for debugging } } // run this when button is triggered, send a char public void Send_5Hz(int theValue) { myPorts[0].write("a"); // write an a println("sent a"); // print it to the debug screen as well } // run this when button is triggered, send a char public void Send_10Hz(int theValue) { myPorts[0].write("b"); // write an a println("sent b"); // print it to the debug screen as well } // run this when button is triggered, send a char public void Send_100Hz(int theValue) { myPorts[0].write("c"); // write an a println("sent c"); // print it to the debug screen as well } // run this when button is triggered, send a char public void Send_Stop(int theValue) { myPorts[0].write("p"); // write an a println("sent p"); // print it to the debug screen as well } // run this when button is triggered, send a char public void Send_Start(int theValue) { myPorts[0].write("t"); // write an a println("sent t"); // print it to the debug screen as well } // run this when button is triggered, send a char public void Send_Toggle(int theValue) { myPorts[0].write("w"); // write an a println("sent w"); // print it to the debug screen as well } // initialize the serial port selected in the listBox void InitSerial(float portValue) { println("initializing serial " + int(portValue) + " in serial.list()"); // for debugging String portPos = Serial.list()[int(portValue)]; // grab the name of the serial port txtlblWhichcom.setValue("COM Initialized = " + portPos); myPorts[0] = new Serial(this, portPos, 115200); // initialize the port // read bytes into a buffer until you get a linefeed (ASCII 10): myPorts[0].bufferUntil('\n'); println("done init serial"); } // serial event, check which port generated the event // just in case there are more than 1 ports open void serialEvent(Serial thisPort) { // variable to hold the number of the port: int portNumber = -1; // iterate over the list of ports opened, and match the // one that generated this event: for (int p = 0; p < myPorts.length; p++) { if (thisPort == myPorts[p]) { portNumber = p; } } // read the serial buffer until a newline appears String myString = thisPort.readStringUntil('\n'); // the following is for streaming packets of data that need to be parsed // if you got any bytes other than the newline if (myString != null) { String[] match_a = match(myString, "a"); if (match_a != null) { // data starting with an a myString = trim(myString); // ditch the newline int[] sensor = int(split(myString.substring(2), ' ')); //println(sensor[0]); rolling_buffer[buffer_index] = int(map(sensor[0],0,1023,num_y,0)); // map(current number,min current number, max current number, min new number, max new number) //println(int(map(sensor[0],0,1023,num_y,0))); buffer_index++; if (buffer_index >= num_y) { buffer_index = 0; } } } } // end serialEvent