ChipKIT BB32

This is an implementation of a  ChipKIT platform on a Solderless Breadboard, using the Microchip PIC32MX250F128B that is now available with a Bootloader preinstalled. This implementation is based on the Digilent ChipKIT DP32, but modified to make it cheaper, flexible and cost effective for Hobbyists and Students in 3rd World Countries such as my own. (Shipping costs and import duties can be crippling). The circuit uses the Right Hand side of a Standard Solderless Breadboard and is designed for the smallest possible footprint. This means that more than half of the breadboard, on the Left Hand side, is available for conducting experiments and constructing interface modules, as the image shows.

Hardware:

Here is a closeup of the circuit itself,  it should provide sufficient information for most people to be able to build the circuit, assuming they have built circuits on a Breadboard befor.  For the wiring I suggest solid core telephone cable. Offcuts or discarded cable can often be found  on building sites or during office renovations and provide several colours of insulation. CAT5 cable could also be used.  As this is a semi permanent installation on the Breadboard I recommend that the wires be cut and bent to size for a neat and reliable construction. Some notes on the components used:
  • The Voltage Regulator is a LM1117-33, the Pin marked Adj is actually the Ground Pin.
  • The Electrolytic Capacitor is a 10uF, oriented so that Positive goes to the Center Pin of the regulator.
  • The 10uF capacitor on the PIC32MX is a Low ESR tantalum capacitor, negative to Ground.
  • The 2 Capacitors on the 8Mhz Crystal are 22pF ceramics, but any close value should do, it may even oscillate without them on a breadboard.
  • All other Capacitors are 100nF (0.1uF) ceramics, any 100nF capacitors will do.
  • All Resistors are 1K with the exception of the one on the LDR which is 22K. (it forms a voltage divider so choose one that best matches your LDR Characteristics).

Features:

USB Power is regulated down to 3.3 Volts for the benefit of the PIC32MX Device. The Breadboard may be powered via USB or the ICSP Header, but it has no protection diodes. It is advisable not to power it via the ICSP Header when plugging it into a USB port.  If it is powered via the ICSP Header,  set the voltage to 3V3 only. A 5V rail is provided as the last row on the Right, to facilitate interfacing to 5V devices such as LCD Displays. This is unregulated 5V directly from the USB Header. The layout is orientated so that the 5V Tolerant PINS are located near to the 5V rail. The majority of the ChipKIT PINS are located to the Left of the device and are readily accessible by the empty portion of the Breadboard. This block of PINS includes the Analog Pins. An ICSP Header is included and serves several roles. It may be used to Install or Replace the Bootloader, Program the board with MPLAB or to connect a PICKit Serial Analyzer / Logic Analyser or UART Tool to assist in Experiments and Debugging. It is only permanently connected to the power bus, use temporary jumper leads to connect to  the appropriate breadboard rows, depending on your application. The LED’s are connected to ChipKIT PIN# 13 and 14, so that the Standard Arduino Blink Sketch and others should compile and run without modification. When addressed in MPLAB they are RB2 and RB3 respectively. The Prog Button is available for use in Sketches (User Programs) as ChipKIT PIN# 17 or RB4 in MPLAB. ChipKIT PIN Numbers are indicated on the Device and Repeated on the Breadboard. Users may find it useful to print out the above Image as a reference whilst using the board. The Key is as follows:
  • The Numbers correspond to ChipKIT PIN# not Microchip Port or Pin Numbers i.e. digitalRead(17) would read pin 9 (RB4) of the PIC32MX package, analogRead(A0) would read pin 24 (RB13).
  • Numbers in RED are 5V tolerant Pins.
  • Numbers in GREEN are both Analog and Digital capable PINS and will work with both the digitalRead() and the analogRead() functions.
  • Analog Channel numbers are shown on the Breadboard Overlay along with the corresponding Digital PIN numbers.
  • Numbers with a ~ symbol may be connected to the OC Registers and used as Hardware PWM PINS.

Software:

Digilent have kindly supplied a Zip file that contains all the files and Instructions  needed to update your MPIDE to support the ChipKIT DP32. The same files will work with this BB32 implementation. http://www.digilentinc.com/Data/Products/CHIPKIT-DP32/DP32_variant.zip It should not, however, be necessary to modify the MPIDE if you are running a newer test version.  I have used the BB32 successfully with both mpide-0023-windows-20130602-test and mpide-0023-windows-20130609-test. If you have a blank device, Digilent also provide a copy of the Bootloader .HEX file.  http://www.digilentinc.com/Data/Products/CHIPKIT-DP32/chipKIT_Bootloader_DP32.zip You will need a PICKit3 or better to install it on the Device, but it can be done with the Breadboard in situ by connecting the ICSP Header pins to the appropriate PIC Pins as follows:
  • Mclr to PIC PIN# 1
  • Dat to PIC PIN# 4 (Chipkit PIN# 11)
  • Clk to PIC PIN# 5 (Chipkit PIN# 12)
If you have a PICKit3 then you will already be familiar with MPLAB, but in a nutshell, start a blank project, select your device as PIC32MX250F128B, File->Import the bootloader.hex file. Set Programmer->PICKit3 and then use the Program Button in the toolbar to upload. Disconnect the PICKit, Plug in the USB cable and if all is well the device will enumerate and you will get a new hardware found notification. If windows requests a driver it is located in the MPIDE directory: C:\….\mpide-0023-windows-20130609-test\drivers\chipKIT Drivers It should install as a stk500 device.

Getting started:

Run MPIDE.EXE from the folder you unziped too. select the Board:

Tools->Board->ChipKIT-> ChipKIT DP32

then

Tools->Serial Port and select the Port that was created by the stk500 driver

When in Bootloader Mode LED2 (RED) will flash at ~ 4Hz To test the Hardware run this Sketch: BB32_test.pde //_________________________________________________________________ // //  BB32_Test.pde // //  C.A.Roper – 2013/07/17 // //  Hardware confidance test Software for the CHIPKit-BB-32 //  CHIPKit compatable Breadboard circuit based on PIC32MX250F128B. // //  Tests Digital Output to LED’s //  Teats Digital Input from Prog Button //  Tests Analog Input from LDR //  Tests Serial Output Via USB //  Tests Serial Input from USB //_________________________________________________________________ // int Last; int State; int Character; void setup() { Serial.begin(19200); pinMode(17, INPUT); pinMode(13, OUTPUT); pinMode(14, OUTPUT); } void loop() { if(Serial.available()) { Character = Serial.read(); if(Character == ‘1’) State = 1; else if(Character == ‘0’) State = 0; else if(Character == ‘t’ || Character == ‘T’) State = !State; } if(digitalRead(17)) { State = !State; } if(State != Last) { digitalWrite(13, !State); digitalWrite(14, State); Serial.println(analogRead(A0)); } Last = State; delay(250); } Whilst uploading LED1 (Green) will flicker. Press the Prog Button to toggle the LED’s and open the Serial console to see the ADC Reading and to issue commands. To return to Bootloader mode and upload other Sketches:
  1. Close the Serial Monitor if open.
  2. Press and hold the Prog Button.
  3. Press and release the Reset Button.
  4. Release the Prog Button.
The Green LED will go out and the RED LED will Flash. Thats it, all that remains is to have fun with your shiny new ChipKIT. Don’t forget to Join the ChipKIT community and  read about new ChipKIT developments and uses. Cheers Chris http://caroper.blogspot.com/
VN:F [1.9.22_1171]
Rating: 10.0/10 (3 votes cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

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 (22 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)

Efficient Use of C++ in Embedded Systems

Those of you planning to begin a project in using C++, hopefully using the MPLAB XC32++ compiler or the chipKIT platform, already know about the object-oriented programming concept of polymorphism. Essential to polymorphism is the concept of a virtual method, a method whose behavior can be overridden within an inheriting class by a method with the same signature.

Virtual methods are implemented using a virtual method table (vtable). The compiler creates a vtable for each class. When an object is created, a pointer to this table is added as a hidden member of the object. The compiler also generates code to initialize the vpointers of its objects to the address of the corresponding vtable. When designing your classes for your embedded application, you will want to keep the extra overhead of the vtable in mind.

Along the same lines, as an embedded-systems developer, you may be surprised by the overhead required by a pure virtual method, since it has no implementation and can therefore never be called directly. Well, the compiler generates error-handling code to handle the case where a pure virtual function is called. In the current XC32 v1.20 compiler release, when a pure virtual method is called, an error message is printed and a C++ exception is thrown, bringing in a fairly large amount of code that should never be executed. While the error handling is useful, we plan to look into simplifying it in future compiler releases to reduce the overhead. For now, you will find that avoiding a pure virtual method will help keep your code size down.

A pure virtual method assigns the function the value 0 rather than providing an implementation. For example:

class Base
{
public:
const char* SayHi() { return "Hi"; } // a normal non-virtual method
virtual const char* GetName() { return "Base"; } // a normal virtual method
virtual int GetValue() = 0; // a pure virtual method
};

To avoid the extra overhead, provide a default implementation like this:

class Base
{
public:
const char* SayHi() { return "Hi"; } // a normal non-virtual method
virtual const char* GetName() { return "Base"; } // a normal virtual method
virtual int GetValue() { while(1); /* Error */ } // a normal virtual method
};

Another hidden consumer of Flash space to look out for is Run-Time Type Information (RTTI). This C++ mechanism exposes information about an object’s data type at runtime. The dynamic_cast<> operation and typeid operator are part of RTTI. When this feature is enabled, additional the type information gets stored in Flash and can consume space even when the application does not use it. When you’re not using RTTI, be sure to disable it in your project settings (-fno-rtti). This compiler option can be added to the chipKIT IDE (MPIDE) default compiler option in <install_dir>/hardware/pic32/platforms.txt

C++ exception handling also causes additional code to be generated. Although exceptions provide a way to react to exceptional circumstances (like runtime errors) in an application, they come at a fairly substantial code and data memory cost. When your application doesn’t require exception support, you can disable it in your project settings (-fno-exceptions). This option is specified by default when the chipKIT IDE (MPIDE) invokes the chipKIT compiler.

[ Thanks to Jason Kajita for this helpful information ]
VN:F [1.9.22_1171]
Rating: 9.3/10 (4 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

NKC ProtoShield Kit for chipKIT Uno32

This article describes an expansion board kit available from NKC Electronics for the chipKIT Uno32 Development Board.

What is a Proto Shield? We all know that the Shields are from the Arduino world and they are named after the little boards that sits on top of the Arduino and compatible boards. A Proto Shield is a combination of a ProtoBoard with a Shield. You usually use a Bread Board to build a prototype, to test the design. Once you have it working and want to house it in a more permanent board, is where a Proto Shield shows its benefits.

The ProtoShield for the chipKIT Uno32 is an exclusive design of NKC Electronics, and it has many nice features:

NKC_protoshield_image_1

The fully assembled ProtoShield board looks like this:

NKC_protoshield_image_2

The kit includes the board and many extra components. What you finally end up installing on the ProtoShield will be based on your requirements. But in general, I recommend soldering all the female headers, as they are needed to bring all the signals and POWER from the chipKIT Uno32 board to the ProtoShield.

NKC_protoshield_image_3

The LED with the associated resistor and filtering capacitor is to add a POWER indicator, meaning you have 5V power from the chipKIT Uno32 board to the ProtoShield.

NKC_protoshield_image_4

The RESET switch is necessary if you want to reset the chipKIT Uno32 board from the top.

NKC_protoshield_image_5

The little 6-pin male header with the 2 jumpers are used to configure how you want to use the 2 power BUSES in the middle of the board. You can send +5V to one of them, GND to the other, or +5 or GND to both of them at the same time.

NKC_protoshield_image_6

If you use the 6-pin male header jumpers to power the BUS, then you can only have +5V.

If you need the full ProtoShield to be 3.3V, then you can select one of the jumpers to GND and the other one open and connect +3.3V directly to the positive BUS. Take a look at the diagram below:

NKC_protoshield_image_7

For more information, visit NKC Electronics Protoshield Kit for chipKIT Uno32

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

Serial Communication – I2C EEPROM using MPLAB X IDE

Overview:

In this project you will learn to use a basic functionality of chipKIT board, which is to use serial communication I2C bus to read and write values from EEPROM memory. I2C bus is a master slave bus, which communicates data from the processor on chipKIT board to other peripherals. More description on I2C communication can be found on the Wikipedia website and on EEPROM can be found here. The configuration is done though MPLAB X IDE.

Hardware Used:

To do the serial communication project, you require the following hardware devices.
  • chipKIT Uno 32
  • chipKIT Basic IO shield
  • PICkit® 3 In-Circuit Debugger/Programmer
  • USB cable
  • 6 pin header to connect chipKIT board and PICkit® 3

Reference:

The reference guide for each board, schematics and other resources are available on their individual homepages:

Procedure:

  1. Connect the hardware devices. The PICkit® 3 should be connected to the chipKIT Uno32 board through a suitable header and use the USB cable to connect the PICkit® 3 to your PC.
  2. Make sure that the jumper settings for JP4 on chipKIT Uno32 board is configured as SPI Slave Select input mode. You can find the jumper settings in chipKIT Uno32 board reference manual from the Digilent website. Also, ensure that the jumpers JP6/JP8 are configured to be used as I2C communication lines.
  3. Place the IO shield on top of the Uno32 board with a bit of a firm press.
  4. Once the hardware setup is made and the device drivers are updated for PICkit® 3 on your computer, launch MPLAB X (Start>All Programs>Microchip>MPLAB X IDE>MPLAB X IDE vx.xx on Window® Machines).
  5. Create a new project through File>New Project. In the pop up new project window, select Standalone Project  under Projects  and click Next. Under Family scroll and select 32-bit MCUs (PIC32). Note the processor number from the chipKIT board’s reference manual and enter it under the Device  option. Click Next.
  6. Select PICkit3 in the Hardware Tools, click Next. Select XC32 (v1.20) under Compiler Toolchains, click Next. Give a project name to create the project.
  7. In the Project tab on the left side of the MPLAB X IDE, right click on Source Files > New > C Main File.. and give a file name for main source code. Once the dot c file opens, select all the codes in the file and replace it with the codes below.
    #include 
    
    #pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
    #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
    #define SYS_FREQ (80000000L)
    
    #define GetSystemClock()           (SYS_FREQ)
    #define GetPeripheralClock()       (SYS_FREQ/1)
    #define GetInstructionClock()      (SYS_FREQ)
    #define I2C_CLOCK_FREQ             5000
    
    // EEPROM Constants
    #define EEPROM_I2C_BUS              I2C1
    #define EEPROM_ADDRESS              0x50        // 0b1010000 Serial EEPROM address
    
    /*******************************************************************************
      Function:
        BOOL StartTransfer( BOOL restart )
    
      Summary:
        Starts (or restarts) a transfer to/from the EEPROM.
    
      Description:
        This routine starts (or restarts) a transfer to/from the EEPROM, waiting (in
        a blocking loop) until the start (or re-start) condition has completed.
    
      Precondition:
        The I2C module must have been initialized.
    
      Parameters:
        restart - If FALSE, send a "Start" condition
                - If TRUE, send a "Restart" condition
    
      Returns:
        TRUE    - If successful
        FALSE   - If a collision occured during Start signaling
    
      Example:
        
        StartTransfer(FALSE);
        
    
      Remarks:
        This is a blocking routine that waits for the bus to be idle and the Start
        (or Restart) signal to complete.
      *****************************************************************************/
    
    BOOL StartTransfer( BOOL restart )
    {
        I2C_STATUS  status;
    
        // Send the Start (or Restart) signal
        if(restart)
        {
            I2CRepeatStart(EEPROM_I2C_BUS);
        }
        else
        {
            // Wait for the bus to be idle, then start the transfer
            while( !I2CBusIsIdle(EEPROM_I2C_BUS) );
    
            if(I2CStart(EEPROM_I2C_BUS) != I2C_SUCCESS)
            {
                DBPRINTF("Error: Bus collision during transfer Start\n");
                return FALSE;
            }
        }
    
        // Wait for the signal to complete
        do
        {
            status = I2CGetStatus(EEPROM_I2C_BUS);
    
        } while ( !(status & I2C_START) );
    
        return TRUE;
    }
    
    /*******************************************************************************
      Function:
        BOOL TransmitOneByte( UINT8 data )
    
      Summary:
        This transmits one byte to the EEPROM.
    
      Description:
        This transmits one byte to the EEPROM, and reports errors for any bus
        collisions.
    
      Precondition:
        The transfer must have been previously started.
    
      Parameters:
        data    - Data byte to transmit
    
      Returns:
        TRUE    - Data was sent successfully
        FALSE   - A bus collision occured
    
      Example:
        
        TransmitOneByte(0xAA);
        
    
      Remarks:
        This is a blocking routine that waits for the transmission to complete.
      *****************************************************************************/
    
    BOOL TransmitOneByte( UINT8 data )
    {
        // Wait for the transmitter to be ready
        while(!I2CTransmitterIsReady(EEPROM_I2C_BUS));
    
        // Transmit the byte
        if(I2CSendByte(EEPROM_I2C_BUS, data) == I2C_MASTER_BUS_COLLISION)
        {
            DBPRINTF("Error: I2C Master Bus Collision\n");
            return FALSE;
        }
    
        // Wait for the transmission to finish
        while(!I2CTransmissionHasCompleted(EEPROM_I2C_BUS));
    
        return TRUE;
    }
    
    /*******************************************************************************
      Function:
        void StopTransfer( void )
    
      Summary:
        Stops a transfer to/from the EEPROM.
    
      Description:
        This routine Stops a transfer to/from the EEPROM, waiting (in a
        blocking loop) until the Stop condition has completed.
    
      Precondition:
        The I2C module must have been initialized & a transfer started.
    
      Parameters:
        None.
    
      Returns:
        None.
    
      Example:
        
        StopTransfer();
        
    
      Remarks:
        This is a blocking routine that waits for the Stop signal to complete.
      *****************************************************************************/
    
    void StopTransfer( void )
    {
        I2C_STATUS  status;
    
        // Send the Stop signal
        I2CStop(EEPROM_I2C_BUS);
    
        // Wait for the signal to complete
        do
        {
            status = I2CGetStatus(EEPROM_I2C_BUS);
    
        } while ( !(status & I2C_STOP) );
    }
    
    // ****************************************************************************
    // ****************************************************************************
    // Application Main Entry Point
    // ****************************************************************************
    // ****************************************************************************
    
    int main(void)
    {
        UINT8               i2cData[10];
        I2C_7_BIT_ADDRESS   SlaveAddress;
        int                 Index;
        int                 DataSz;
        UINT32              actualClock;
        BOOL                Acknowledged;
        BOOL                Success = TRUE;
        UINT8               i2cbyte;
    
        // Initialize debug messages (when supported)
        DBINIT();
    
        // Set the I2C baudrate
        actualClock = I2CSetFrequency(EEPROM_I2C_BUS, GetPeripheralClock(), I2C_CLOCK_FREQ);
        if ( abs(actualClock-I2C_CLOCK_FREQ) > I2C_CLOCK_FREQ/10 )
        {
            DBPRINTF("Error: I2C1 clock frequency (%u) error exceeds 10%%.\n", (unsigned)actualClock);
        }
    
        // Enable the I2C bus
        I2CEnable(EEPROM_I2C_BUS, TRUE);
    
        //
        // Send the data to EEPROM to program one location
        //
    
        // Initialize the data buffer
        I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_ADDRESS, I2C_WRITE);
        i2cData[0] = SlaveAddress.byte;
        i2cData[1] = 0x05;              // EEPROM location to program (high address byte)
        i2cData[2] = 0x40;              // EEPROM location to program (low address byte)
        i2cData[3] = 0xAA;              // Data to write
        DataSz = 4;
    
        // Start the transfer to write data to the EEPROM
        if( !StartTransfer(FALSE) )
        {
            while(1);
        }
    
        // Transmit all data
        Index = 0;
        while( Success && (Index < DataSz) )
        {
            // Transmit a byte
            if (TransmitOneByte(i2cData[Index]))
            {
                // Advance to the next byte
                Index++;
    
                // Verify that the byte was acknowledged
                if(!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
                {
                    DBPRINTF("Error: Sent byte was not acknowledged\n");
                    Success = FALSE;
                }
            }
            else
            {
                Success = FALSE;
            }
        }
    
        // End the transfer (hang here if an error occured)
        StopTransfer();
        if(!Success)
        {
            while(1);
        }
    
        // Wait for EEPROM to complete write process, by polling the ack status.
        Acknowledged = FALSE;
        do
        {
            // Start the transfer to address the EEPROM
            if( !StartTransfer(FALSE) )
            {
                while(1);
            }
    
            // Transmit just the EEPROM's address
            if (TransmitOneByte(SlaveAddress.byte))
            {
                // Check to see if the byte was acknowledged
                Acknowledged = I2CByteWasAcknowledged(EEPROM_I2C_BUS);
            }
            else
            {
                Success = FALSE;
            }
    
            // End the transfer (stop here if an error occured)
            StopTransfer();
            if(!Success)
            {
                while(1);
            }
    
        } while (Acknowledged != TRUE);
    
        //
        // Read the data back from the EEPROM.
        //
    
        // Initialize the data buffer
        I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_ADDRESS, I2C_WRITE);
        i2cData[0] = SlaveAddress.byte;
        i2cData[1] = 0x05;              // EEPROM location to read (high address byte)
        i2cData[2] = 0x40;              // EEPROM location to read (low address byte)
        DataSz = 3;
    
        // Start the transfer to read the EEPROM.
        if( !StartTransfer(FALSE) )
        {
            while(1);
        }
    
        // Address the EEPROM.
        Index = 0;
        while( Success & (Index < DataSz) )
        {
            // Transmit a byte
            if (TransmitOneByte(i2cData[Index]))
            {
                // Advance to the next byte
                Index++;
            }
            else
            {
                Success = FALSE;
            }
    
            // Verify that the byte was acknowledged
            if(!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
            {
                DBPRINTF("Error: Sent byte was not acknowledged\n");
                Success = FALSE;
            }
        }
    
        // Restart and send the EEPROM's internal address to switch to a read transfer
        if(Success)
        {
            // Send a Repeated Started condition
            if( !StartTransfer(TRUE) )
            {
                while(1);
            }
    
            // Transmit the address with the READ bit set
            I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_ADDRESS, I2C_READ);
            if (TransmitOneByte(SlaveAddress.byte))
            {
                // Verify that the byte was acknowledged
                if(!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
                {
                    DBPRINTF("Error: Sent byte was not acknowledged\n");
                    Success = FALSE;
                }
            }
            else
            {
                Success = FALSE;
            }
        }
    
        // Read the data from the desired address
        if(Success)
        {
            if(I2CReceiverEnable(EEPROM_I2C_BUS, TRUE) == I2C_RECEIVE_OVERFLOW)
            {
                DBPRINTF("Error: I2C Receive Overflow\n");
                Success = FALSE;
            }
            else
            {
                while(!I2CReceivedDataIsAvailable(EEPROM_I2C_BUS));
                i2cbyte = I2CGetByte(EEPROM_I2C_BUS);
            }
    
        }
    
        // End the transfer (stop here if an error occured)
        StopTransfer();
        if(!Success)
        {
            while(1);
        }
    
        // Validate the data read
        if( i2cbyte != 0xAA )
        {
            DBPRINTF("Error: Verify failed\n");
        }
        else
        {
            DBPRINTF("Success\n");
        }
    
        // Example complete
        while(1);
    }
  8. In the above program, the EEPROM is being written with a value AA and read from the memory to verify if it written correctly. To verify the result access the watch window from Window > Debugging > Watches or you can use the shortcut key Alt+Shift+2. In the watch window panel that opens on the MPLAB X IDE, enter the new watch as i2cbyte, in the blank <Enter new watch> area.
  9. In the program editor window, put a breakpoint by clicking on the line number  on the while statement near the end of the program.
  10. Click on Debug Project icon shown below,                                                 analogread mplab3
  11. Once the program halts its execution at the line with the breakpoint, click on Watches window below the code area. You can observe the output value being reflected in the i2cbyte variable as shown below.serialcomm1
This verifies the operation of writing into and reading from EEPROM memory through the I2C serial communication. To get more information on working of I2C serial communication visit the wikipedia website by clicking here. In our application EEPROM on the IOshield is the slave device and PIC controller on chipKIT Uno32 board acts as the master device. 
VN:F [1.9.22_1171]
Rating: 3.6/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 (26 votes cast)
VN:F [1.9.22_1171]
Rating: +2 (from 2 votes)