This project is intended to make the Pixy2 interface with the MSP432P401R microcontroller. I created this driver for an REU project, and demonstrated the driver by using the Pixy2 in combination with the TI-RSLK Maze Edition robot.
I will continue to keep this driver updated as I have time, so if you have any questions about the driver or would like to notify me of any issues that exist in the driver, please email me at: zachary.holloway@gmail.com
Please be sure to take a look at the README located in "Schematics" for important notes about how to utilize this driver.
pixy2_uart_header.h
C/C++Include this file along with pixy2_uart_driver.c in your project to utilize the functions described in the header.
/*
* pixy2_uart_header.h
*
* Created on: Mar 3, 2019
* Author: Zachary Holloway
*/
#ifndef PIXY2_UART_HEADER_H_
#define PIXY2_UART_HEADER_H_
//*****************************************************************************
//
// If building with a C++ compiler, make all of the definitions in this header
// have a C binding.
//
//*****************************************************************************
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#define ON (1)
#define OFF (0)
#define PIXY2_CHECKSUM_SYNC (0xC1AF)
#define PIXY2_NO_CHECKSUM_SYNC (0xC1AE)
#define PIXY2_TYPE_REQUEST_CHANGE_PROGRAM (0x02)
#define PIXY2_TYPE_REQUEST_RESOLUTION (0x0C)
#define PIXY2_TYPE_RESPONSE_RESOLUTION (0x0D)
#define PIXY2_TYPE_REQUEST_VERSION (0x0E)
#define PIXY2_TYPE_RESPONSE_VERSION (0x0F)
#define PIXY2_TYPE_RESPONSE_RESULT (0x01)
#define PIXY2_TYPE_RESPONSE_ERROR (0x03)
#define PIXY2_TYPE_REQUEST_BRIGHTNESS (0x10)
#define PIXY2_TYPE_REQUEST_SERVO (0x12)
#define PIXY2_TYPE_REQUEST_LED (0x14)
#define PIXY2_TYPE_REQUEST_LAMP (0x16)
#define PIXY2_TYPE_REQUEST_FPS (0x18)
#define PIXY2_TYPE_REQUEST_BLOCKS (0x20)
#define PIXY2_TYPE_REQUEST_MAIN_FEATURES (0x30)
#define PIXY2_TYPE_REQUEST_MODE (0x54)
#define PIXY2_TYPE_REQUEST_NEXT_TURN (0x58)
#define PIXY2_TYPE_REQUEST_DEFAULT_TURN (0x60)
#define PIXY2_TYPE_REQUEST_REVERSE_VECTOR (0x62)
#define PIXY2_TYPE_REQUEST_RGB (0x70)
#define PIXY2_RESULT_OK (0)
#define PIXY2_RESULT_ERROR (-1)
#define PIXY2_RESULT_BUSY (-2)
#define PIXY2_RESULT_CHECKSUM_ERROR (-3)
#define PIXY2_RESULT_TIMEOUT (-4)
#define PIXY2_RESULT_BUTTON_OVERRISE (-5)
#define PIXY2_RESULT_PROGRAM_CHANGING (-6)
#define PIXY2_SERVO_MIN_POSITION (0)
#define PIXY2_SERVO_MAX_POSITION (1000L)
#define PIXY2_SERVO_CENTER_POSITION ((PIXY2_SERVO_MAX_POSITION-PIXY2_SERVO_MIN_POSITION)/2)
//*************************************************************************************
extern void configUART(void);
//*************************************************************************************
//
// @brief: This function configures all the necessary settings for UART A2.
//
// @return: None.
//
//*************************************************************************************
extern void sendPacket(void);
//*************************************************************************************
//
// @brief: This function is used to send all data packets to the Pixy2 by assigning
// values to an integer array and filling the TX buffer with data to be sent.
//
// @return: None.
//
//*************************************************************************************
extern void receivePacket(int responseLength);
//*************************************************************************************
//
// @brief: This function is used to receive all data from the Pixy2 in response to
// a command from the RX buffer and store them in an array.
//
// @return: None.
//
//*************************************************************************************
extern void setCameraBrightness(uint_fast8_t valueBrightness);
//*************************************************************************************
//
// @brief: This function is used to set the level of the camera brightness for the
// Pixy2.
//
// @param: valueBrightness is the level of camera brightness.
// Valid values are between 0-255 inclusive.
//
// @return: None.
//*************************************************************************************
extern void setLED(uint_fast8_t valueRed,
uint_fast8_t valueGreen,
uint_fast8_t valueBlue);
//*************************************************************************************
//
// @brief: This function is used to set the color of the RGB LED on the front Pixy2.
//
// @param: valueRed is the control of the red color level for the RGB LED.
// Valid values are between 0-255 inclusive.
//
// @param: valueGreen is the control of the green color level for the RGB LED.
// Valid values are Valid values are between 0-255 inclusive.
//
// @param: valueBlue is the control of the blue color level for the RGB LED.
// Valid values are Valid values are between 0-255 inclusive.
//
// @return: None.
//
//*************************************************************************************
extern void setLamp(uint_fast8_t upperLamp,
uint_fast8_t lowerLamp);
//*************************************************************************************
//
// @brief: This function is used to turn the lamps of the Pixy2 for additional lighting.
//
// @param: upperLamp is the control for the two white LEDs along the top of the
// Pixy2.
// Valid values are:
// - 0 (Turn lamp off)
// - 1 (Turn lamp on)
//
// @param: lowerLamp is the control for turning on all channels of the bottom RGB LED of
// the Pixy2.
// Valid values are:
// - 0 (Turn lamp off)
// - 1 (Turn lamp on)
//
// @return: None.
//
//*************************************************************************************
extern void setServos(uint_fast16_t panValue,
uint_fast16_t tiltValue);
//*************************************************************************************
//
// @brief: This function is used to set the pan and tilt servos to a desired position.
//
// @param: panValue is the position of the pan servo (looking around).
// Valid values are between 0-1000 inclusive.
//
// @param: panValue is the position of the tilt servo (looking up and down).
// Valid values are between 0-1000 inclusive.
//
// @return: None.
//
//*************************************************************************************
extern void setMode(uint_fast8_t mode);
//*************************************************************************************
//
// @brief: This function is used to set the mode of line-tracking while running the
// line-tracking API.
//
// @param: mode is a variable which is a bitwise ORing of the following bits:
// - LINE_MODE_TURN_DELAYED (1, LSB)
// - LINE_MODE_MANUAL_SELECT_VECTOR (2)
// - LINE_MODE_WHITE_LINE (4, MSB)
// The resulting value will be between 0-7 inclusive.
//
// @return: None.
//
//*************************************************************************************
extern int getMainFeatures(uint_fast8_t features, int featuresData[]);
//*************************************************************************************
//
// @brief: This function is used to get data of main features in view of the Pixy2.
//
// @param: features is the type of feature to return data from. It is a bitwise ORing
// of the following bits:
// - VECTORS (1, LSB)
// - INTERSECTIONS (2)
// - BARCODES (4, MSB)
// The resulting value will be between 0-7 inclusive.
//
// @param: featuresData is the array in which the feature data will be stored.
//
// @return: featuresData array.
// featuresData[0] is the first type of main feature.
// featuresData[1] is the length of data from the type of first feature.
// featuresData[2] through featuresData[2+featuresData[1]] is the data from
// the first feature.
// NOTE: This format will continue for each of the types of main features
// visible when this function is called.
//
//
//*************************************************************************************
extern void setNextTurn(uint_fast8_t nextTurnAngle);
//*************************************************************************************
//
// @brief: This function is used to set the angle of the next turn while running the
// line-tracking API.
//
// @param: nextTurnAngle is the angle which the next turn will have.
// Valid values are between -180 and 180 inclusive.
// NOTE: Pixy2 interprets 90 degrees as a left turn and -90 degrees as a right
// turn.
//
// @return: None.
//
//*************************************************************************************
extern void setDefaultTurn(uint_fast8_t defaultTurnAngle);
//*************************************************************************************
//
// @brief: This function is used to set the angle of the default turn while running the
// line-tracking API.
//
// @param: defaultTurnAngle is the angle which the next turn will have.
// Valid values are between -180 and 180 inclusive.
// NOTE: Pixy2 interprets 90 degrees as a left turn and -90 degrees as a right
// turn.
//
// @return: None.
//
//*************************************************************************************
extern void reverseVector(void);
//*************************************************************************************
//
// @brief: This function is used to reverse the current direction of travel.
//
// @param: None.
//
// @return: None.
//
//*************************************************************************************
extern int getResolution(int resolutionData[]);
//*************************************************************************************
//
// @brief: This function retrieves the resolution from the Pixy2.
//
// @param: resolutionData is an array in which the frame width and height will be
// stored.
//
// @return: resolutionData array.
// resolutionData[0] is the frame width.
// resolutionData[1] is the frame height.
//
//*************************************************************************************
extern int getFPS(void);
//*************************************************************************************
//
// @brief: This function retrieves the current FPS from the Pixy2.
//
// @param: None.
//
// @return: FPS (32 bit integer)
//
//*************************************************************************************
//
//*************************************************************************************
extern int getBlocks(int sigmap, int maxBlocks);
//*************************************************************************************
//
// @brief: This function retrieves data regarding blocks of color signature sigmap
// while in color connected components mode.
//
// @param: sigmap indicates what signature to receive data from.
// Valid values are between 0-255 inclusive. 255 is a special case where
// all color signatures are available.
//
// @param: maxBlocks indicates the maximum number of blocks to return.
// Valid values are between 0-255 inclusive.
//
// @return: blocksData array. (n indicates the number of blocks detected)
// blocksData[0+8n] is the color signature of the block.
// blocksData[1+8n] is the X center of the block in pixels.
// blocksData[2+8n] is the Y center of the block in pixels.
// blocksData[3+8n] is the width of the blocks in pixels.
// blocksData[4+8n] is the height of the blocks in pixels.
// blocksData[5+8n] is the angle of the color code in degrees.
// blocksData[6+8n] is the tracking index of the block.
// blocksData[7+8n] is the age of the block (number of frames it has been
// tracked).
//
//*************************************************************************************
//
#ifdef __cplusplus
}
#endif
#endif /* PIXY2_UART_HEADER_H_ */
pixy2_uart_driver.c
C/C++Include this along with pixy2_uart_header.h in your project to utilize the functions described in the header.
#include "ti/devices/msp432p4xx/inc/msp.h"
#include "pixy2_uart_header.h"
#include "stdio.h"
int commandBuffer[20];
int responseBuffer[20];
int resolutionData[2];
uint8_t rxBuffer[1024];
uint16_t bufferIndex = 0;
void sendPacket (void) {
int i;
int length = sizeof(commandBuffer);
for (i = 0; i < length; i++){
while (!(EUSCI_A2->IFG & EUSCI_A_IFG_TXIFG));
EUSCI_A2->TXBUF = commandBuffer[i];
}
memset(commandBuffer, 0, sizeof(commandBuffer));
}
void receivePacket (int responseLength) {
int i;
memset(responseBuffer, 0, sizeof(responseBuffer));
for (i = 0; i < responseLength; i++){
while (!(EUSCI_A2->IFG & EUSCI_A_IFG_RXIFG));
responseBuffer[i] = EUSCI_A2->RXBUF;
}
}
void setCameraBrightness (uint_fast8_t valueBrightness) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_BRIGHTNESS;
commandBuffer[3] = 1;
commandBuffer[4] = valueBrightness;
sendPacket();
}
void setLED (uint_fast8_t valueRed, uint_fast8_t valueGreen, uint_fast8_t valueBlue) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_LED;
commandBuffer[3] = 3;
commandBuffer[4] = valueRed;
commandBuffer[5] = valueGreen;
commandBuffer[6] = valueBlue;
sendPacket();
}
void setLamp (uint_fast8_t lowerLamp, uint_fast8_t upperLamp) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_LAMP;
commandBuffer[3] = 2;
commandBuffer[4] = lowerLamp;
commandBuffer[5] = upperLamp;
sendPacket();
}
void setServos (uint_fast16_t panValue, uint_fast16_t tiltValue) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_SERVO;
commandBuffer[3] = 4;
commandBuffer[4] = panValue & 0xFF;
commandBuffer[5] = panValue >> 8;
commandBuffer[6] = tiltValue & 0xFF;
commandBuffer[7] = tiltValue >> 8;
sendPacket();
}
void setMode (uint_fast8_t mode) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_MODE;
commandBuffer[3] = 1;
commandBuffer[4] = mode;
sendPacket();
}
int getMainFeatures (uint_fast8_t features, int featuresData[]) {
int i, count;
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_MAIN_FEATURES;
commandBuffer[3] = 2;
commandBuffer[4] = 1;
commandBuffer[5] = features;
sendPacket();
featuresData[0] = rxBuffer[6];
featuresData[1] = rxBuffer[7];
for (i = 0; i < featuresData[1]; i++){
featuresData[2+i] = rxBuffer[8+i];
}
count = count + i;
featuresData[3+count] = rxBuffer[9+count];
featuresData[4+count] = rxBuffer[10+count];
for (i = 0; i < featuresData[4+count]; i++){
featuresData[5+count+i] = rxBuffer[11+count+i];
}
count = count + i;
featuresData[6+count] = rxBuffer[12+count];
featuresData[7+count] = rxBuffer[13+count];
for (i = 0; i < featuresData[7+count]; i++){
featuresData[8+count+i] = rxBuffer[14+count+i];
}
return featuresData;
}
void setNextTurn (uint_fast16_t nextTurnAngle) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_NEXT_TURN;
commandBuffer[3] = 2;
commandBuffer[4] = nextTurnAngle & 0xFF;
commandBuffer[5] = nextTurnAngle >> 8;
sendPacket();
}
void setDefaultTurn (uint_fast16_t defaultTurnAngle) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_DEFAULT_TURN;
commandBuffer[3] = 2;
commandBuffer[4] = defaultTurnAngle & 0xFF;
commandBuffer[5] = defaultTurnAngle >> 8;
sendPacket();
}
void reverseVector (void) {
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_REVERSE_VECTOR;
commandBuffer[3] = 0;
sendPacket();
}
int getResolution (int resolutionData[]){
memset(rxBuffer, 0, sizeof(rxBuffer));
bufferIndex = 0;
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_RESOLUTION;
commandBuffer[3] = 1;
commandBuffer[4] = 69; // Value does not matter, as long as it is an 8-bit integer
sendPacket();
resolutionData[0] = rxBuffer[6] | rxBuffer[7] << 8;
resolutionData[1] = rxBuffer[8] | rxBuffer[9] << 8;
return resolutionData;
}
int getFPS (void){
int FPS;
memset(rxBuffer, 0, sizeof(rxBuffer));
bufferIndex = 0;
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_FPS;
commandBuffer[3] = 0;
sendPacket();
FPS = rxBuffer[6] | rxBuffer[7] << 8 | rxBuffer[8] << 16 | rxBuffer[9] << 24;
return FPS;
}
int getBlocks (int sigmap, int maxBlocks){
int blockCount;
int i;
int blocksData[1024];
memset(rxBuffer, 0, sizeof(rxBuffer));
bufferIndex = 0;
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_BLOCKS;
commandBuffer[3] = 2;
commandBuffer[4] = sigmap;
commandBuffer[5] = maxBlocks;
sendPacket();
blockCount = rxBuffer[3]/14;
for (i = 0; i < blockCount; i++){
blocksData[(i*8)] = rxBuffer[(i*14+6)] | rxBuffer[(i*14+7)] << 8;
blocksData[(i*8)+1] = rxBuffer[(i*14+8)] | rxBuffer[(i*14+9)] << 8;
blocksData[(i*8)+2] = rxBuffer[(i*14+10)] | rxBuffer[(i*14+11)] << 8;
blocksData[(i*8)+3] = rxBuffer[(i*14+12)] | rxBuffer[(i*14+13)] << 8;
blocksData[(i*8)+4] = rxBuffer[(i*14+14)] | rxBuffer[(i*14+15)] << 8;
blocksData[(i*8)+5] = rxBuffer[(i*14+16)] | rxBuffer[(i*14+17)] << 8;
blocksData[(i*8)+6] = rxBuffer[(i*14+18)];
blocksData[(i*8)+7] = rxBuffer[(i*14+19)];
}
return blocksData;
}
int getRGB (int xValue, int yValue, int saturate, int RGBData[]){
memset(rxBuffer, 0, sizeof(rxBuffer));
bufferIndex = 0;
commandBuffer[0] = PIXY2_NO_CHECKSUM_SYNC & 0xFF;
commandBuffer[1] = PIXY2_NO_CHECKSUM_SYNC >> 8;
commandBuffer[2] = PIXY2_TYPE_REQUEST_RGB;
commandBuffer[3] = 5;
commandBuffer[4] = xValue & 0xFF;
commandBuffer[5] = xValue >> 8;
commandBuffer[6] = yValue & 0xFF;
commandBuffer[7] = yValue >> 8;
commandBuffer[8] = saturate;
sendPacket();
RGBData[0] = rxBuffer[6];
RGBData[1] = rxBuffer[7];
RGBData[2] = rxBuffer[8];
return RGBData;
}
void EUSCIA2_IRQHandler(void)
{
if (EUSCI_A2->IFG & EUSCI_A_IFG_RXIFG)
{
rxBuffer[bufferIndex] = EUSCI_A2->RXBUF;
bufferIndex++;
EUSCI_A2->IFG &= ~EUSCI_A_IFG_RXIFG;
}
}
Thanks to University of Texas at Arlington and Texas Instruments.
Comments