DIY chipKIT Board Using a Through-Hole SPDIP PIC32

Overview:

Certain varieties of Microchip Technology’s PIC32 Microcontrollers are available in Small Plastic Dual In-line Packages (SPDIP). This packaging makes it very easy to build up your own chipKIT board at home using common tools found in the home hobbyist/Maker workshop. Other 32-bit platforms would require specialized equipment to solder their fine pitch packaging to a custom board.

This post will demonstrate how to build up a chipKIT Platform onto a solderless breadboard using a PIC32MX250F128B 32-bit Microcontroller and some readily available components.

NOTE: This application uses a voltage provided off of the USB line. This is adequate for Low Power application such as blinking a single LED. However, most applications will require that you connect a separate power source to the Vin input of the Voltage Regulator such as a battery (shown at the end of this post). Excessive application power consumption could damage your USB port.

Components list:

The following components were used to complete this project

  • The TCHIP-USB-MX250F128B: Microchip PIC32MX250F128B in SPDIP package preprogrammed with the chipKIT USB Bootloader
  • Microchip MCP1702-3302E/TO: 3.3V LDO Voltage Regulator in TO-92 package
  • 8MHz Crystal Oscillator
  • 4 x 0.1uF Capacitors
  • 1 x 10uF Tantalum or Ceramic capacitor (note: needed for low ESR characteristics)
  • 2 x 36pF Capacitors
  • 1 x 130Ω Resistor
  • 4 x 10kΩ resistors
  • LED
  • 2 x SPST Tactile Switches
  • Some sort of way to connect a USB cable to the breadboard. I used a Sparkfun BOB-09614 USB-mini Breakout board 
COMPONENTS

Schematic:

schematic

Procedure:

Insert the PIC32MX250F128B into a solderless breadboard. Be sure to connect all of the Vdd (3.3V) and Vss (0V) signals as shown. Be sure to double check the datasheet pin diagram shown below:

VoltageBlock

power_ground

Note that some pins are not labeled as Vdd or Vss but will need to be connected to these voltages for the application to function. This includes pins related to USB and our Analog peripherals on the Microcontroller. Also note that the 3.3V Vdd signal will be coming off of our MCP1702 3.3V regulator. Connect the GND to a breadboard rail that will be dedicated to Vss and the Vout pin to a breadboard rail that will be dedicated to Vdd. Also connect a 0.1uF capacitor to the Vin and Vout pins to GND. The pin out diagram for the MCP1702 is shown below: MCP1702_pinout MCP1702

Next, the USB breakout board will be connected as follows:

  • Provide the Vin signal for the MCP1702
  • Connect the D- and D+ data lines
usb_MCP1702_Conn
usb_data

There is a Voltage Regulator on the PIC32MX250F128B Microcontroller that regulates internal voltage down to 1.8V to meet the requirement of the core. You don’t really have to worry about this other than you will need to connect a low ESR capacitor such as a Tantalum type to the Vcap pin on the Microcontroller to ground (Vss) as shown: vcap_pinout vcap

This particular version of the chipKIT Platform will use the PIC32MX250F128B’s on-chip USB peripheral instead of the standard way of doing things with the FTDI chip. Therefore, we will need to tell the PIC32 when to go into “bootloader” mode. In order to download a sketch, the PIC32 will need to be in this “bootloader.” To do this, two pushbuttons are used. One to RESET (turn on and off) the microcontroller and a second PROGRAM pushbutton that you will press down while the Microcontroller comes out of RESET. Coming out of RESET, the Microcontroller notices that the pin connected to the PROGRAM pushbutton has been driven HIGH (3.3V) and will automatically enter into “bootloader” mode.

The RESET pushbutton is connected to the MCLR (pin 1 of the Microcontroller) through a 10kΩ resistor that will limit current. The MCLR pin, when driven low, will cause the PIC32 to RESET. Therefore, another 10kΩ resistor is used to pull the line up to 3.3V that will keep the device out of RESET. One lead of the pushbutton is connected to this 3.3V signal and the other to Vss. Therefore, when the pushbutton is pressed, the Microcontroller will notice that the MCLR pin is driven LOW and will enter into RESET mode.

Similarly, the PROGRAM pushbutton is connected to the RB4 (pin 11) on the PIC32 through a current limiting 10kΩ resistor. However, this time the pin is held LOW through a 10kΩ pull down resistor since the a HIGH signal on this pin tells the Microcontroller to enter “bootloader” mode: pushbutton block pushbuttons

Finally, the USB bootloader is based off of an 8MHz external crystal oscillator. The oscillator is connected to the OSC1 and OSC2 pins on the PIC32 and 36pF capacitors are connected to each to ground as shown: oscillator_block oscillator

Next, I added a 130Ω resistor connected to pin 16 then to an LED connected to ground.

led

The final circuit should look something like this:

final circuit microB

To connect to a battery source, disconnect the Vin input to the MCP1702 from the USB connector and connect to the positive terminal of a battery as shown. Make sure that the battery’s negative terminal is connected to the Vss rail on your board.

battery_connection

Testing the Application:

To test the application, we will create a sketch to blink the LED on pin 16, connect the board through the USB, and download the sketch.

Download MPIDE (a FREE download) from the Install page and install it, and then follow these instructions.

  1. Open up MPIDE and create a new sketch with the following code:
  2. /*
      Blink
      Turns on an LED on for one second, then off for one second, repeatedly.
    
      This example code is in the public domain.
     */
    
    void setup() {
      // initialize the digital pin as an output.
      // Digital pin 24 has the LED connected to it
      //For more information including a pin diagram please visit www.chipkit.net/diy-chipkit-board
      pinMode(24, OUTPUT);
    }
    
    void loop() {
      digitalWrite(24, HIGH);   // set the LED on
      delay(1000);              // wait for a second
      digitalWrite(24, LOW);    // set the LED off
      delay(1000);              // wait for a second
    }
    
  3. Connect the application through the USB connector to your computer.
  4. If the driver is not installed successfully, you will need to manually install. The driver is located in the directory where you originally installed MPIDE. On my Window® Machine, I installed MPIDE to my C drive as follows:

  5. C:\mpide-0023-windows-20130426-test\mpide-0023-windows-20130401-test\drivers

  6. Once the device drivers are successfully installed, you are now ready to program the board.The PIC32MX250F128B chip is preprogrammed with the USB bootloader. The bootloader will only define which pin is used as the PROGRAM input (Pin 11 in this case) and which pins will flash to indicate that the device is indeed in bootloader mode. In this case, the LED indicator is defined as pin 7 on the PIC32MX250F128B Microcontroller. If you were to connect an LED to this pin as you did above for pin 16, the LED would flash rapidly when in “Bootloader” mode. In order to define which pin on the PIC32 will do what, we need to select a configuration in the MPIDE. We will be using an existing board definition file for the new Fubarino Mini platform.

  7. In the MPIDE, select Tools>Board>Fubarino Mini.The PIC32 will now be set up as follows: pinout

  8. You will need to make sure that the application is in Bootloader mode. To do this, hold down the PROGRAM pushbutton connected to pin 11 while pressing on/off the pushbutton RESET connected to MCLR (pin 1).

  9. Select Tools > Serial Port > COMx (whatever serial comm has been assigned to the application)

  10. Click the upload button in MPIDE.

  11. The application USB will disconnect and then the LED connected to Digital Pin 24 should start flashing.

To view the pinout configuration and to locate some relevant tutorials, please visit the Fubarino Mini homepage at www.fubarino.org/mini.

VN:F [1.9.22_1171]
Rating: 8.4/10 (23 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Arduino-style Maze Solving Robot using Sparkfun Ardumoto

OVERVIEW:

Here is a robot application that implements a very simple maze solving algorithm. This application uses off the shelf components along with a very basic chassis built from common materials. This could be a good weekend project. The robot chassis for this Demo was constructed with 2½” wide by ¼” thick poplar project wood purchased at a local home improvement center. Note that a box was also created to house the battery holder. mazebot

HARDWARE USED

CONSTRUCTION

The Ardumoto Shield is mounted to a chipKIT Uno32 Development Platform with all component connections made to the shield as indicated in labels next to component. mazebot_construction

LOGIC OVERVIEW

The maze solving theory used here is based on the following: Say you enter a maze or room, close your eyes, place your right hand on the wall, and start walking while keeping your hand on the wall. You will eventually find your way out of the room or maze. Not the fastest route, but it works! This assumes that all the walls are connected of course. Here is the basic software algorithm in flowchart form. A graphical representation of the robot and the sensors is on the right of the chart for reference.   Robot starts by checking its sensors. If it detects a wall on its side sensor, it checks to see if the wall is in its “Sweet Spot”. If so, the robot will adjust its wheel speeds to move in a straight line (supposedly parallel to the wall). If either the front or side sensor detects a wall that is too close, then the robot turns off its left wheel so that it veers to the left (hopefully avoiding a collision). Otherwise, the robot will move in a wide circle to the right with the hopes that an object will come into view of at least one of the sensors.   Note: You can also use the left side to do this.   mazebot_overview  

 SKETCH

 
/*
 9/10/2012
 Marc McComb

This code runs a maze solving routine based on the following:
Say you enter a maze or room, close your eyes, place your right hand on the wall, and start walking while keeping your hand on the wall. 
You will eventually find your way out of the room or maze. Not the fastest route, but it works! This assumes that all the walls are connected of course

So the robot starts by checking its sensors. If it detects a wall on its side sensor, it checks to see if the wall is in its “Sweet Spot”. If so, the robot
will adjust its wheel speeds to move in a straight line (supposedly parallel to the wall). If either the front or side sensor detects a wall that is too close,
then the robot turns off its left wheel so that it veers to the left (hopefully avoiding a collision). Otherwise, the robot will move in a wide circle to the
right with the hopes that an object will come into view of at least one of the sensors. 

This application uses the following hardware:
chipKITâ„¢ Uno32 available at http://www.digilentinc.com/chipkit 
Sparkfun Ardumoto - Motor Driver shield: https://www.sparkfun.com/products/9815
Some Sharp GP2Y0A21YK0F IR Sensors - Available at Adafruit with wires already attached: https://www.adafruit.com/products/164

Software used:
The Ardumoto board is designed for a PWM on pin 11. Since the Uno32 doesn't have a hardware PWM on that pin, no worries, we just
use Brian Schmaltzs SoftPWMServo library:
http://www.chipkit.org/wiki/index.php?title=Library_Status#SoftPWMServo_library 

You will need to make sure that you add the library. To do this:
1) Make sure that you have a folder in your Documents:/MPIDE folder called Libraries
2) Copy the SoftPWMServo library folder from C:\mpide-0023-windows-20120903\hardware\pic32\libraries to the Libraries folder above
3) If MPIDE is open, close and reopen. 
4) Now all you have to do is go to the MPIDE toolbar and select Sketch>Import Library>SoftPWMServo

More info on libraries at:
http://arduino.cc/en/Reference/Libraries

*/

//Need to use this library instead of just analogWrite() since there pin 11 isn't a PWM pin on the chipKIT UNO32 board.
//No big deal. This library works great on almost any pin. 
#include <SoftPWMServo.h>

//MOTOR SETUP
const int pwm_a = 3;   //PWM control for motor outputs 1 and 2 is on digital pin 3
const int pwm_b = 11;  //PWM control for motor outputs 3 and 4 is on digital pin 11
const int dir_a = 12;  //direction control for motor outputs 1 and 2 is on digital pin 12
const int dir_b = 13;  //direction control for motor outputs 3 and 4 is on digital pin 13
const char motor_speed = 200; //set the motor speed (between 0 and 255)

//IR SENSOR SETUP
const int rSensor_pin = 0; //right sensor will be read on ANO
const int fSensor_pin = 5; //front sensor will be read on AN5

//Let's set up some variable that we'll use in the code
int rSensor_val = 0;  //this will be the right sensor value ADC reading (between 0 and 1023)
int fSensor_val = 0;  //this will be the front sensor value ADC reading (between 0 and 1023)
boolean sweetspot = false;  //boolean value initialized to false. When its true, it means the wall on the right of the robot is the "sweet spot"
boolean rSensorHit = false; //boolean value initialized to false. When its true, it means the wall on the robot's right is too close
boolean fSensorHit = false; //boolean value initialized to false. When its true, it means the wall in front of the robot is too close 
int sensor_state = 0;

void setup()
{
  pinMode(dir_a, OUTPUT); //Set the dir_a pin as an output
  pinMode(dir_b, OUTPUT); //Set dir_b pin as an output
  digitalWrite(dir_a,  HIGH);  //Reverse motor direction, 1 high, 2 low
  digitalWrite(dir_b, HIGH);  //Reverse motor direction, 3 low, 4 high  

}

void loop()
{ 

  //This is how I usually do things but you may wish to change it up a bit

  //First get all you inputs
  read_sensors();
  //Then make some decisions based on these inputs
  parse_inputs();
  //Then do all your outputs at the same time. In this case, determine motor speeds
  run_motors();
  //I always have a loop timing function
  loop_timing();
}

//this function reads the IR value on the analog input pins
void read_sensors()
{

  rSensor_val = analogRead(rSensor_pin);
  fSensor_val = analogRead(fSensor_pin);
}

//this function then makes decisions based on those inputs
void parse_inputs()
{

  if (fSensor_val > 850) fSensorHit = true; //if the front sensor sees a wall set the fSensorHit variable TRUE

  //Otherwise, check if the robot is in the "sweet spot"
  else if ((rSensor_val > 750)&&(rSensor_val <850)&&(fSensor_val < 850)) sweetspot = true;      //If not, then is the wall on the right side of the robot too close?   //If so, set the rSensorHit variable TRUE   else if (rSensor_val > 850) rSensorHit = true;

  //Otherwise make sure all of the sensor flags are set to FALSE
  else{
    fSensorHit = false;
    rSensorHit = false;
    sweetspot = false;
  }

  //reinitialize your sensor variable to a known state
  rSensor_val = 0;
  fSensor_val = 0;

}

//This routine runs the two motors based on the flags in the previous funciton
void run_motors()
{

  //If the wall on the right is too close, turn left away from the wall
  if (rSensorHit)left(); 

  //Otherwise, if the wall is in the "sweet spot", then try and stay parallel with the wall
  //keeping both wheel speeds the same
  else if (sweetspot)forward();

  //If the front sensor sees a wall, turn left 
  else if (fSensorHit)left();

  //If neither sensor sees a wall, then move in a really big arc to the right. 
  //Hopefully, the bot wil be able to pick up a wall
  else right();

  //Always set your flags to a know value. In this case, FALSE
    fSensorHit = false;
    rSensorHit = false;
    sweetspot = false; 

}

void loop_timing()
{
  delay(50);

}

//Motor routines called by the run_motors()

void forward() //full speed forward
{ 

  //both wheels spin at the same speed 
  SoftPWMServoPWMWrite(pwm_a, motor_speed); 
  SoftPWMServoPWMWrite(pwm_b, motor_speed);
}

void stopped() //stop
{ 

  //turn off both motors
  SoftPWMServoPWMWrite(pwm_a, 0);
  SoftPWMServoPWMWrite(pwm_b, 0);
}

void left()                   //stop motor A
{

  //turn of the left motor so that the robot vears to the left
  SoftPWMServoPWMWrite(pwm_a, motor_speed);
  SoftPWMServoPWMWrite(pwm_b, 0);

}

void right()                   //stop motor B
{ 

  //Here we're running the right motor at a slower speed than the left motor
  //Therefore, the bot will travel in a large circle to the right
  SoftPWMServoPWMWrite(pwm_a, 50);
  SoftPWMServoPWMWrite(pwm_b, motor_speed+50);  
}
 
VN:F [1.9.22_1171]
Rating: 8.8/10 (8 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Line Following Robot with Arduino Shield

OVERVIEW:

Here is a fairly basic robot application that implements a line following algorithm. This application uses off the shelf components along with a very basic chassis built from common materials. This could be a good weekend project. The Line-Follower chassis for this Demo was constructed with 2½” wide by ¼” thick poplar project wood purchased at a local home improvement center. Note that a box was also created to house the battery holder.

HARDWARE USED

CONSTRUCTION

The Arduino Motor Shield is mounted to a chipKIT Uno32 Development Platform with all component connections made to the shield as indicated in labels next to component.  

LOGIC OVERVIEW

The line following robot is programmed to basically avoid the color black. If both sensors see black, then the robot will back up until it no longer sees black. If one sensor sees black, then the robot will turn in the direction of that sensor until it no longer sees black. Other than that, if the robot doesn’t see black on either sensor, it will simply move for- ward. In this application, the black line is created using common electrical tape. The logic for this algorithm is shown below along with a graphical representation of the front of the line following bot for reference.  

 SKETCH

 
/*
 9/10/2012
 Marc McComb

The line following robot is programmed to basically avoid the color black. If both sensors see black, 
then the robot will back up until it no longer sees black. If one sensor sees black, then the robot will
turn in the direction of that sensor until it no longer see black. Other than that, if the robot doesn’t 
see black on either sensor, it will simply move forward. In this application, the black line is created 
using common electrical tape. 

This application uses the following hardware:
chipKITâ„¢ Uno32 available at http://www.digilentinc.com/chipkit 
Arduino Motor Shield available at: http://arduino.cc/en/Main/ArduinoMotorShieldR3 
Sparkfun QRE1113 Line Sensor Board- Analog(Item #: ROB-09453) https://www.sparkfun.com/products/9453 

Software used:
The Aruino Motor shield is designed for a PWM on pin 11. Since the Uno32 doesn't have a hardware PWM 
on that pin, no worries, we just use Brian Schmaltzs SoftPWMServo library:
http://www.chipkit.org/wiki/index.php?title=Library_Status#SoftPWMServo_library 

You will need to make sure that you add the library. To do this:
1) Make sure that you have a folder in your Documents:/MPIDE folder called Libraries
2) Copy the SoftPWMServo library folder from C:\mpide-0023-windows-20120903\hardware\pic32\libraries 
    to the Libraries folder above
3) If MPIDE is open, close and reopen. 
4) Now all you have to do is go to the MPIDE toolbar and select Sketch>Import Library>SoftPWMServo

More info on libraries at:
http://arduino.cc/en/Reference/Libraries

*/

#include <SoftPWMServo.h>

//Setting up the Hardware pins
// First the line following (IR) sensors
const int irLeft = 2; //Left line sensor is on pin A2
const int irRight = 3; //Right line sensor is on pin A3

//Setting up the Arduino Motor Shield
const int leftDIR = 12; 
const int rightDIR = 13;
const int leftPWM = 3;
const int rightPWM = 11;
const int leftBrake = 9;
const int rightBrake = 8;
const char bothSpeed = 100; //sets how fast the motors will spin (0 to 255)

//Here we set up variable that will hold the ADC value representing the line sensor values
int leftSees = 0; //A2 ADC value (0 to 1023)
int rightSees = 0; //A3 ADC value (0 to 1023)

void setup() 
{ 

  //Make sure to set all of our control signal pins as output
  pinMode(leftDIR, OUTPUT); 
  pinMode(rightDIR, OUTPUT); 
  pinMode(leftBrake, OUTPUT); 
  pinMode(rightBrake, OUTPUT); 

  //Next we make sure our brake signals are set LOW
  digitalWrite(leftBrake, LOW);
  digitalWrite(rightBrake, LOW);
} 

void loop() 
{ 
    //Start by reading the left sensor on A2
  int leftEye = analogRead(irLeft);

  //delay a little bit
  delay(5);

  //next read the right sensor connected A3
  int rightEye = analogRead(irRight);

  //Next, we run the motors based on the sensor reading

  //If both sensors see black (ADC value greater than 1000), then back up
  if ((leftEye >= 1000)&&(rightEye >= 1000)) reverse();

  //Otherwise, if only the left sensor sees black, then turn off the left motor
  //so the robot veer to the left
  else if ((leftEye >= 1000)&&(rightEye < 1000)) turnLeft();

  //Otherwise, if only the right sensor sees black, then turn off the right motor
  //so the robot veer to the right
  else if ((leftEye < 1000)&&(rightEye >= 1000)) turnRight();

  //Otherwise, move forward
  else forward();

}

//Turn right by turning off the right motor 
//i.e disable the PWM to that wheel
void turnRight(void)
{
  digitalWrite(leftDIR, HIGH); 
  digitalWrite(rightDIR, HIGH);
  SoftPWMServoPWMWrite(leftPWM, bothSpeed);
  SoftPWMServoPWMWrite(rightPWM, 0);
}

//Turn left by turning off the left motor
//i.e disable the PWM to that wheel
void turnLeft(void)
{
  digitalWrite(leftDIR, HIGH); 
  digitalWrite(rightDIR, HIGH);
  SoftPWMServoPWMWrite(leftPWM, 0);
  SoftPWMServoPWMWrite(rightPWM, bothSpeed);
}

//Move forward by enabling both wheels
void forward(void)
{
  digitalWrite(leftDIR, HIGH); 
  digitalWrite(rightDIR, HIGH);
  SoftPWMServoPWMWrite(leftPWM, bothSpeed);
  SoftPWMServoPWMWrite(rightPWM, bothSpeed);
}

//Reverse by enabling both wheels 
void reverse(void)
{
  digitalWrite(leftDIR, LOW); 
  digitalWrite(rightDIR, LOW);
  SoftPWMServoPWMWrite(leftPWM, bothSpeed);
  SoftPWMServoPWMWrite(rightPWM, bothSpeed);
}
 
VN:F [1.9.22_1171]
Rating: 6.9/10 (27 votes cast)
VN:F [1.9.22_1171]
Rating: +2 (from 2 votes)

chipKIT Software SPI Library

This article on chipKIT software SPI library is written by Gene Apperson, Digilent Inc.

At Digilent we have been working to extend the chipKIT software framework beyond its original Arduino-inspired roots. Recent enhancements enable the framework to be used with many different systems based on PIC32 MCUs. In order to support arbitrary hardware configurations, we implemented a general-purpose Serial Peripheral Interface (SPI) library that does not rely on dedicated hardware peripherals. The Software SPI (SoftSPI) library allows the creation of any number of software based (bit-banged) SPI ports.

Serial Peripheral Interface (SPI) is a four wire synchronous serial interface used by many integrated circuits and electronic devices. SPI devices can operate as either master slave devices. The four SPI signals are generally referred to as Slave Select (SS), Master Out, Slave In (MOSI), Master In, Slave Out (MISO), and Serial Clock (SCK). A master device generates SS, MOSI and SCK, and receives MISO. A slave device receives SS, MOSI, and SCK and generates MISO. The SS signal is used to enable the slave device, and this signal is only significant for slave devices. A master device can use any general purpose I/O pin to generate SS to enable a slave.

The SoftSPI library only supports operation as an SPI master device.

An SPI transaction begins with the master device bringing SS low. When the slave sees SS go low it becomes enabled and waits for the master to send data. The master shifts data out on MOSI and simultaneously shifts data in on MISO. The slave device receives data from the master on its MOSI pin and simultaneously sends data to the master on its MISO pin. Each time the master sends a byte to the slave, it simultaneously receives a byte from the slave. The master generates the clock signal (SCK) that is used to control the shifting of the data in both the master and the slave.

SPI devices can operate using one of four data transfer modes, and one of two shift directions. The transfer modes specify the idle state of the clock signal (idles high or idles low) the active edge of the clock, and the phase relationship between the active edge of the clock signal and the data. The modes are generally called mode 0 through mode 3. The shift direction specifies whether the data is shifted most significant bit first (shift left), or least significant bit first (shift right). The SoftSPI library header file defines symbols used to specify the transfer mode and shift direction. Refer to documentation for the SPI slave device being used to determine the transfer mode and shift direction to use. Most SPI devices use mode 0 with shift left.

The SoftSPI library defines an object class (SoftSPI) that is used to create a separate object instance for each desired SPI port. Each instance of the SoftSPI object class uses four specified digital pins for the SPI signals. The SoftSPI object class supports all four transfer modes, both shift directions, and setting the frequency of the clock signal.

To use the SoftSPI library, an object instance variable of the SoftSPI object class must be created:

/* Declare an instance of the SPI interface object */
SoftSPI    spi;

The object instance is initialized using functions to set mode, shift direction and clock speed. In this example, a 6uS delay between bytes is specified to accommodate a joystick peripheral:

/* Define digital pins for the SoftSPI port to use*/
#define  pinSS    24
#define  pinMOSI  25
#define  pinMISO  26
#define  pinSCK   27

/* Initialize the SPI port */
spi.begin(pinSS, pinMOSI, pinMISO, pinSCK);
spi.setSpeed(250000);
spi.setMode(SSPI_MODE0);
spi.setDirection(SSPI_SHIFT_LEFT);
spi.setDelay(6);  /* delay 6uS between bytes */

Data can then be transferred to a slave device by calling the various data transfer functions. This example communicates with Digilent’s PmodJSTK peripheral:

{
uint8_t    rgbSnd[5];
uint8_t    rgbRcv[5];
int      ib;
/* Initialize the transmit buffer */
for (ib = 0; ib < 5; ib++) {
rgbSnd[ib] = 0x50 + ib;
}
rgbSnd[0] = fbLedPmod + 0x80;  // First byte sets the LEDs

/* Bring SS low to begin the transaction */
spi.setSelect(LOW);

/* Wait 10us for Pmod to become ready */
Delay10us();

/* Send the data to the Pmod and get the response */
spi.transfer(5, rgbSnd, rgbRcv);

/* Bring SS high to end the transaction */
spi.setSelect(HIGH);
}
The SoftSPI Library is included with versions of the Multi-Platform IDE (MPIDE) dated 12/15/2011 or later. Complete documentation is available here.
VN:F [1.9.22_1171]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Debouncing a Pushbutton

Overview:

A pushbutton is a Mechanical Switch. Switches play an important and extensive role in practically every computer, microprocessor and microcontroller application. Mechanical switches are inexpensive, simple and reliable. However, switches can be very noisy electrically. When a switch, such as a pushbutton is pressed, the connection actually makes and breaks several, perhaps even hundreds, of times before the final switch state settles. The problem is known as switch bounce.

The consequences of uncorrected switch bounce can range from being just annoying to catastrophic.

A software technique called “Debouncing” is one way to solve this problem. Here’s how it works:

Usually, the switch is connected to a pin on the Microcontroller so that it maintains either a HIGH or LOW condition when the switch is open (not pressed). If the switch closes (is pressed) then that condition will change. The Microcontroller detects that change. Instead of reacting right away, the Microcontroller will wait a period of time, say 5 mS, to give the switch a chance to stop bouncing and then checks that pin again. If the pin still reads that the switch is closed, then the Microcontroller will do something about it.

In this tutorial, a pushbutton press (BTN1) will trigger LD1 to light. Otherwise, LD1 will be OFF.

 

Reference:

This tutorial introduces the if/else statement. This type of statement gives your sketch the ability to make decisions based on conditions occurring outside of the Microcontroller or as a result of some sort of internal condition such as the result of some mathematical operation.

We recommend you read the following before proceeding:

 

Hardware Used:

The hardware used in this tutorial will be the chipKIT uC32 along with a chipKIT Basic I/O Shield both manufactured by Digilent Inc. The reference guide for each board, schematics and other resources are available on their individual homepages:

 

Procedure:

  1. Create a new sketch in MPIDE.
  2. Save the sketch with a meaningful name.
  3. Add the following code to your new sketch:
    int ledPin = 26;   // LED connected to digital pin 26
    int pbPin = 4;   //pushbutton BTN1 connected to digital pin 4
    int pbState = LOW; //this variable will hold the value or state of BTN1
                       // i.e. if not pressed, pbState = LOW, if pressed, pbState = HIGH
    
    void setup()
    {
      pinMode(ledPin, OUTPUT);   // sets the digital pin 26 as output
      pinMode(pbPin, INPUT); //sets digital pin 4 as input
      digitalWrite(ledPin, LOW); //make sure LD1 is OFF
    }
    
    void loop()
    {
    
      pbState = digitalRead(pbPin); //read the value, HIGH or LOW, on the pushbutton pin
    
      if (pbState == HIGH) //is pbState HIGH indicating BTN1 is pressed??
      //if yes, do the code inside the curly braces. This is the debounce section
      {
        delay(5); //wait 5 mS for any pushbutton bounce to disappear
        pbState = digitalRead(pbPin); //read the value on the pushbutton pin again
    
        if(pbState == HIGH) //is it still HIGH (pressed)
        {
          digitalWrite(ledPin, HIGH); //Light LD1>
        }
      }
    
      //otherwise
      else
      {
          digitalWrite(ledPin, LOW); //keep LD1 OFF
      }
    
    }
     
  4. In the MPIDE, verify that the chipKIT uC32 and the associated communication port are selected.
  5. Upload the code to the chipKIT Board.
   

Verifying Operation

After the sketch is sent to the chipKIT uC32 board’s Microcontroller, LED 1 (LD1) on the chipKIT Basic I/O Shield should light when pushbutton BTN1 is pressed.

   
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Changing PWM frequency and bit resolution

Overview

You have to bypass the analogWrite function in the abstraction layer and talk directly to the hardware to do this. You will need to program one of the timers, and one or more of the output compares to do this. The Output Compare units in the PIC32 can work from either Timer2 or Timer3. The analogWrite code uses Timer2. If you don’t need analogWrite to work, I would use Timer2. If you need analogWrite to work as well, use Timer3. The Output Compare sets the pin when the timer resets. The timer then counts up from 0. The Output Compare resets the pin when the the value in the timer matches the value in the ouput compare register. The counter continues to count up until the count value matches the value in the period register. The timer then resets and it all starts over again. Also at the end of a period the contents of the duty cycle buffer register(OCxRS) is loaded into the duty cycle register(OCxR). The frequency of the resulting PWM signal is determined by the clock speed of the timer, and the value in the period register. The clock speed of the timer is determined by the peripheral bus frequency and the prescaler selected. The peripheral bus frequency is 80 MHz (at least this is the default set by the boot loader). The prescaler can be selected to be 1:1, 1:2, 1:4, up to 1:256. So for example, with a 1:8 prescaler selected, the 80 MHz would be divided down to 10 MHz and that is the timer clock frequency (i.e. the timer counts up 1 every 100ns). The value in the period register determines when the counter resets. So, for example if you set the period register to 10000, you would get a reset at 10000*100ns, or every 1 ms. This is a frequency of 1 kHz. To get a 12-bit PWM, you could load the period register with 4096 (2^12). With the 1:8 prescaler, this would give a frequency of about 2.4 kHz.

Code

The following code will initialize Timer2 with the 1:8 prescaler and a period value of 4096
T2CONCLR = T2_ON          // Turn the timer off
T2CON = T2_PS_1_8;        // Set prescaler
TMR2 = 0;                 // Clear the counter
PR2 = 4096;               // Set the period
T2CONSET = T2_ON;         // Turn the timer on
The following code will set output compare 1 to use Timer2 and a PWM value that would give a 50% duty cycle.
OC1R = 2048;              // Load initial value into duty cycle register
OC1RS = 2048;             // When a period finishes the contents of OC1RS is loaded to OC1R
OC1CON = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE; // Set Timer2 as source | enable pwm mode without fault protection
OC1CONSET = OC_ON;
This example code is taken (and slightly modified) from the code for analogWrite. This is in the file wiring_analog.c in the core files. These statements are all writing directly to the peripheral registers for Timer2 and Output Compare 1. For more complete details, you should refer to the Timer and Output Compare sections of the PIC32 Family Reference Manual that can be downloaded from the Microchip web site.
VN:F [1.9.22_1171]
Rating: 6.6/10 (9 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Debugging with ejtagproxy and GDB

Debugging without MPLAB is possible through ejtagproxy. You need a compatible ICSP adapter, like PICkit2 or PICkit3 (full list of compatible adapters is available on project homepage). Note that you can’t use PICkit2 with MPLAB, but it works with ejtagproxy. Obtain source, build. Obtain stock GDB source. Configure with –target=mipsel-elf32 . Build. Start ejtagproxy:
$ ejtagproxy
GDB proxy for Microchip PIC32 processors, Version 1.0.25
Copyright (C) 2012 Serge Vakulenko

EJTAGproxy comes with ABSOLUTELY NO WARRANTY; for details
use `--warranty' option. This is Open Source software. You are
welcome to redistribute it under certain conditions. Use the
'--copying' option for details.
ejtagproxy: waiting on TCP port 2000
Start GDB and point it to ELF file of your application:
$ pic32-gdb ~/repos/chipKIT-minimal-application/src/main.elf
(gdb)
Set the target to ejtagproxy:
(gdb) target remote localhost:2000
You should notice that ICSP adapter is now connected to target board. On my chipKIT Max32 this also results in board reset. The ejtagproxy willl print something like:
adapter: PICkit2 Version 2.32.0
processor: Microchip PIC32MX795F512L
processor: reset occured
hardware: 6 breakpoints, 2 watchpoints
oscillator: internal Fast RC
And GDB will connect to target:
Remote debugging using localhost:2000
0xbfc00000 in ?? ()
(gdb)
Now you can set breakpoints, watchpoints, etc. and run the application.
(gdb) break main
Breakpoint 1 at 0x9d00136c: file main.c, line 12.
(gdb) c
Continuing.
Unfortunately, when ejtagproxy is connected to target board everything is much slower than normally, so you have to wait a moment…
Breakpoint 1, main () at main.c:12

12			loop();
As you can see breakpoint was successfully activated in main() function. Now it’s possible to do further analysis:
(gdb) i reg
         zero       at       v0       v1       a0       a1       a2       a3
R0   00000000 ffbfffff ffffffff ffffffff 00000000 00000000 a000001c bf800000 
           t0       t1       t2       t3       t4       t5       t6       t7
R8   9d0011f0 00000000 00000020 04000000 00000000 00000000 00000000 00000000 
           s0       s1       s2       s3       s4       s5       s6       s7
R16  00000000 00100000 00000000 00000000 00000000 00000002 00000000 00000000 
           t8       t9       k0       k1       gp       sp       s8       ra
R24  00000000 00000000 00000000 00000000 a00081f0 a001ffe8 a001ffe8 9d001208 
           sr       lo       hi      bad    cause       pc
     00100000 00000019 00000001 cc37facd a0800034 9d00136c 
          fsr      fir
     can't read register 160 (fsr)
(gdb) disassemble 
Dump of assembler code for function main:
  0x9d00135c <+0>:	addiu	sp,sp,-24
  0x9d001360 <+4>:	sw	ra,20(sp)
  0x9d001364 <+8>:	sw	s8,16(sp)
  0x9d001368 <+12>:	move	s8,sp
=> 0x9d00136c <+16>:	jal	0x9d001328 <loop>
  0x9d001370 <+20>:	nop
  0x9d001374 <+24>:	j	0x9d00136c <main+16>
  0x9d001378 <+28>:	nop
End of assembler dump.
(gdb) stepi
loop () at main.c:1
1	void loop(void) {
(gdb) disassemble 
Dump of assembler code for function loop:
=> 0x9d001328 <+0>:	addiu	sp,sp,-16
  0x9d00132c <+4>:	sw	s8,12(sp)
  0x9d001330 <+8>:	move	s8,sp
  0x9d001334 <+12>:	li	v0,1
  0x9d001338 <+16>:	sw	v0,0(s8)
  0x9d00133c <+20>:	lw	v0,4(s8)
  0x9d001340 <+24>:	addiu	v0,v0,2
  0x9d001344 <+28>:	sw	v0,4(s8)
  0x9d001348 <+32>:	move	sp,s8
  0x9d00134c <+36>:	lw	s8,12(sp)
  0x9d001350 <+40>:	addiu	sp,sp,16
  0x9d001354 <+44>:	jr	ra
  0x9d001358 <+48>:	nop
End of assembler dump.
(gdb)
VN:F [1.9.22_1171]
Rating: 8.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Programming Microchip starter kits from MPIDE

Running on Microchip Starter Kits

MPIDE has been expanded explicitly to support all of the Microchip starter kits such as:
  • PIC32 Starter Kit
  • PIC32 USB Starter Kit
  • PIC32 Ethernet Starter Kit
  • Explorer 16 Starter Kit
Currently for all of these boards you will need some sort of USB to serial adapter. For all but the Exp-16 I use an FTDI cable that breaks out to pins. I connect those to pins on the expansion board for uart1. The PIC32 USB Starter Kit and PIC32 Ethernet Starter Kits are also compatible with the USB PIC32 bootloader. The Explorer-16 has an on-board DB-9 RS-232 connector. This is connected to UART2. The bootloader is configured to use UART2 for the Explorer-16 and the Serial ports for Arduino are remapped so that Serial.print goes to uart2 and Serial1.print goes to uart1. This is all done automatically so the user does not have to worry about it at all. In order to install the bootloader on any of these boards, you have to have one of the Microchip compatible programmers such as the MPLAB ICD 3 or PICkit 3. Ideally you should download MPLAB X IDE from microchip (http://www.microchip.com/mplabx) and use that to compile and burn the bootloader. The bootloader source and pre-compiled hex files are all on github. (https://github.com/chipKIT32/pic32-Arduino-Bootloader)

Using other PIC32 boards

As far as using MPIDE with other boards, the answer is YES, it should work with ANY PIC32 there is. The only limit might be it won’t work on chips smaller than 32K, And that’s because it hasn’t been tried on anything smaller. To get it to work on other boards, a few things have be be done.
  • First, the bootloader has to be burned onto the target board. The source is on github and MPLAB is used to compile and burn the bootloader. The multi-platform MPLAB-X was used on a Mac, but other versions should work as well.
  • If you using a chip that has not already been added to avrdude.conf, that has to be done.
  • You need to add a new entry to boards.txt and then you will be able to program the board directly from MPIDE.
VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Running StickOS BASIC on a chipKIT board

Have you ever wished you could examine and manipulate the pins and peripherals of your MCU *interactively*, while it was live and connected to your embedded circuit, rather than using just “reset and run” debugging? If so, StickOS BASIC may be for you! With StickOS BASIC, you can log in to your MCU using nothing but a terminal emulator, and then take full control of the MCU from a command-line, just as if you had an In-Circuit Emulator. StickOS can run either in “slave” mode, tethered to and controlled by a host computer as a glorified intelligent I/O port, or it can run in “master” mode, programmed in BASIC, interactively debugged, and even configured to autorun its BASIC program autonomously. In StickOS BASIC, it is trivial to examine and manipulate I/O pins. I/O pins can be configured for digital input or output, analog input or output, servo output, or frequency output. Once a pin is configured, it can be bound to a BASIC variable, and from then on, examining or manipulating the pin is as simple as examining or manipulating the bound variable. For example, to configure pin 3 for servo output, bind it to the variable “motor1”, and then set it up for a 1ms (1000us) PWM pulse width is as easy as (interactively, at the command-line, or in a program):
    > dim motor1 as pin 3 for servo output
    > let motor1=1000
    > _
In StickOS BASIC, it is equally trivial to use timers, UARTs, advanced I2C or SPI peripherals, as well as HD44780-compatible LCDs and simple scanned keypads. And most importantly, it can all be done interactively — no more guessing what your MCU is up to! The StickOS debugger supports command-line program interruption, breakpoints, assertions, watchpoints, live variable (and pin) manipulation and examination, execution tracing and single-stepping, sampling profiling, and even edit-and-continue! When you’re ready to move up, you can then port your BASIC program to C using the MPLAB X StickOS Skeleton project, and take advantage of all the same pin/peripheral configuration, flash manipulation, etc., used by StickOS BASIC. A detailed introduction to StickOS on the chipKIT boards is here: http://www.cpustick.com/chipkit.htm An overview of the StickOS BASIC language features is in the Quick Reference guide, here: http://www.cpustick.com/downloads/quickref.v1.82.pdf More information and downloads for the chipKIT boards are available here: http://www.cpustick.com/downloads.htm
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)