James Martel
Published © LGPL

What Do I Build Next? Crickit FeatherWing Bot

Another 2-wheeled robot project using a Feather 32u4 Bluefruit and a Crickit FeatherWing carrier board.

BeginnerFull instructions provided2 hours167
What Do I Build Next? Crickit FeatherWing Bot

Things used in this project

Hardware components

Adafruit Feather 32u4 BLE
×1
Adafruit Crickit Featherwing
×1
Adafruit TT DC Motors with Bi-Metal gearbox 98:1
×1
Adafruit 6600 mAh Lipo Battery
×1
Adafruit 4 x AA Battery Holder with ON/OFF switch
×1
Adafruit D wheels Orange and Clear TT Motor Wheel for TT DC Gearbox Motor
×2
AA Batteries
AA Batteries
×4
Pololu robot expansion plate Pololu RP5/Rover 5 Expansion Plate RRC07A (Narrow) Solid Red Pololu
×1
Adafruit .8" plastic standoffs White Nylon Screw and Stand-off Set – M2.5 Thread
×1
DFRobot Brass standoffs and screws
×1
2WD Robot Smart Car Kit with Speed Encoder Battery Box for DIY
×1
Adafruit Female DC Power jack
×1
Adafruit caster wheel Supporting Swivel Caster Wheel
×1

Software apps and online services

Adafruit Crickit Make it Move

Story

Read more

Schematics

Crickit Featherwing 2 wheeled robot

Just starting with this board, battery connectors are labelled

Code

Base DC Motor Code for Featherwing Crickit-seesaw.cpp

Arduino
Arduino code supplied by Adafruit
/*!
 * @file Adafruit_seesaw.cpp
 *
 * @mainpage Adafruit seesaw arduino driver
 *
 * @section intro_sec Introduction
 *
 * This is part of Adafruit's seesaw driver for the Arduino platform.  It is
 * designed specifically to work with the Adafruit products that use seesaw technology.
 *
 * These chips use I2C to communicate, 2 pins (SCL+SDA) are required
 * to interface with the board.
 *
 * Adafruit invests time and resources providing this open source code,
 * please support Adafruit and open-source hardware by purchasing
 * products from Adafruit!
 *
 * @section author Author
 *
 * Written by Dean Miller for Adafruit Industries.
 *
 * @section license License
 *
 * BSD license, all text here must be included in any redistribution.
 *
 */

#include "Adafruit_seesaw.h"

/**
 *****************************************************************************************
 *  @brief      Create a seesaw object on a given I2C bus
 *
 *  @param      i2c_bus the I2C bus connected to the seesaw, defaults to "Wire"
 ****************************************************************************************/
Adafruit_seesaw::Adafruit_seesaw(TwoWire *i2c_bus)
{
  if (i2c_bus == NULL) {
    _i2cbus = &Wire;
  } else {
    _i2cbus = i2c_bus;
  }
}
	

/**
 *****************************************************************************************
 *  @brief      Start the seesaw
 *
 *				This should be called when your sketch is connecting to the seesaw
 * 
 *  @param      addr the I2C address of the seesaw
 *  @param      flow the flow control pin to use
 *  @param		reset pass true to reset the seesaw on startup. Defaults to true.
 *
 *  @return     true if we could connect to the seesaw, false otherwise
 ****************************************************************************************/
bool Adafruit_seesaw::begin(uint8_t addr, int8_t flow, bool reset)
{
	_i2caddr = addr;
	_flow = flow;

	if(_flow != -1) ::pinMode(_flow, INPUT);

	_i2c_init();

	if(reset){
		SWReset();
		delay(500);
	}

	uint8_t c = this->read8(SEESAW_STATUS_BASE, SEESAW_STATUS_HW_ID);
	if (c != SEESAW_HW_ID_CODE) {
	  return false;
	}
	return true;
}

/**
 *****************************************************************************************
 *  @brief      perform a software reset. This resets all seesaw registers to their default values.
 *
 *  			This is called automatically from Adafruit_seesaw.begin()
 * 
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::SWReset()
{
	this->write8(SEESAW_STATUS_BASE, SEESAW_STATUS_SWRST, 0xFF);
}

/**
 *****************************************************************************************
 *  @brief      Returns the available options compiled into the seesaw firmware.
 * 
 *
 *  @return     the available options compiled into the seesaw firmware. If the option is included, the
 *				corresponding bit is set. For example, 
 *				if the ADC module is compiled in then (ss.getOptions() & (1UL << SEESAW_ADC_BASE)) > 0
 ****************************************************************************************/
uint32_t Adafruit_seesaw::getOptions()
{
	uint8_t buf[4];
	this->read(SEESAW_STATUS_BASE, SEESAW_STATUS_OPTIONS, buf, 4);
	uint32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
	return ret;
}

/**
 *****************************************************************************************
 *  @brief      Returns the version of the seesaw
 *
 *  @return     The version code. Bits [31:16] will be a date code, [15:0] will be the product id.
 ****************************************************************************************/
uint32_t Adafruit_seesaw::getVersion()
{
	uint8_t buf[4];
	this->read(SEESAW_STATUS_BASE, SEESAW_STATUS_VERSION, buf, 4);
	uint32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
	return ret;
}

/**
 *****************************************************************************************
 *  @brief      Set the mode of a GPIO pin.
 * 
 *  @param      pin the pin number. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *  @param		mode the mode to set the pin. One of INPUT, OUTPUT, or INPUT_PULLUP.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::pinMode(uint8_t pin, uint8_t mode)
{
	if(pin >= 32)
		pinModeBulk(0, 1ul << (pin-32), mode);
	else
		pinModeBulk(1ul << pin, mode);
}

/**
 *****************************************************************************************
 *  @brief      Set the output of a GPIO pin
 * 
 *  @param      pin the pin number. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *	@param		value the value to write to the GPIO pin. This should be HIGH or LOW.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::digitalWrite(uint8_t pin, uint8_t value)
{
	if(pin >= 32)
		digitalWriteBulk(0, 1ul << (pin-32), value);
	else
		digitalWriteBulk(1ul << pin, value);	
}


/**
 *****************************************************************************************
 *  @brief      Read the current status of a GPIO pin
 * 
 *  @param      pin the pin number. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *
 *  @return     the status of the pin. HIGH or LOW (1 or 0).
 ****************************************************************************************/
bool Adafruit_seesaw::digitalRead(uint8_t pin)
{
	if(pin >= 32)
		return digitalReadBulkB((1ul << (pin-32))) != 0;
	else
		return digitalReadBulk((1ul << pin)) != 0;

}

/**
 *****************************************************************************************
 *  @brief      read the status of multiple pins on port A.
 * 
 *  @param      pins a bitmask of the pins to write. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				For example, passing 0b0110 will return the values of pins 2 and 3.
 *
 *  @return     the status of the passed pins. If 0b0110 was passed and pin 2 is high and pin 3 is low, 0b0010 (decimal number 2) will be returned.
 ****************************************************************************************/
uint32_t Adafruit_seesaw::digitalReadBulk(uint32_t pins)
{
	uint8_t buf[4];
	this->read(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK, buf, 4);
	uint32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
	return ret & pins;
}

/**
 *****************************************************************************************
 *  @brief      read the status of multiple pins on port B.
 * 
 *  @param      pins a bitmask of the pins to write.
 *
 *  @return     the status of the passed pins. If 0b0110 was passed and pin 2 is high and pin 3 is low, 0b0010 (decimal number 2) will be returned.
 ****************************************************************************************/
uint32_t Adafruit_seesaw::digitalReadBulkB(uint32_t pins)
{
	uint8_t buf[8];
	this->read(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK, buf, 8);
	uint32_t ret = ((uint32_t)buf[4] << 24) | ((uint32_t)buf[5] << 16) | ((uint32_t)buf[6] << 8) | (uint32_t)buf[7];
	return ret & pins;
}

/**
 *****************************************************************************************
 *  @brief      Enable or disable GPIO interrupts on the passed pins
 * 
 *  @param      pins a bitmask of the pins to write. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				For example, passing 0b0110 will enable or disable interrups on pins 2 and 3.
 *	@param		enabled pass true to enable the interrupts on the passed pins, false to disable the interrupts on the passed pins.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::setGPIOInterrupts(uint32_t pins, bool enabled)
{
	uint8_t cmd[] = { (uint8_t)(pins >> 24) , (uint8_t)(pins >> 16), (uint8_t)(pins >> 8), (uint8_t)pins };
	if(enabled)
		this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_INTENSET, cmd, 4);
	else
		this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_INTENCLR, cmd, 4);
}

/**
 *****************************************************************************************
 *  @brief      read the analog value on an ADC-enabled pin.
 * 
 *  @param      pin the number of the pin to read. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				On the default seesaw firmware on the SAMD09 breakout, pins 2, 3, and 4 are ADC-enabled.
 *
 *  @return     the analog value. This is an integer between 0 and 1023
 ****************************************************************************************/
uint16_t Adafruit_seesaw::analogRead(uint8_t pin)
{
	uint8_t buf[2];
	uint8_t p;
	switch(pin){
		case ADC_INPUT_0_PIN: p = 0; break;
		case ADC_INPUT_1_PIN: p = 1; break;
		case ADC_INPUT_2_PIN: p = 2; break;
		case ADC_INPUT_3_PIN: p = 3; break;
		default:
			return 0;
			break;
	}

	this->read(SEESAW_ADC_BASE, SEESAW_ADC_CHANNEL_OFFSET + p, buf, 2, 500);
	uint16_t ret = ((uint16_t)buf[0] << 8) | buf[1];
  	delay(1);
	return ret;
}

/**
 *****************************************************************************************
 *  @brief      read the analog value on an capacitive touch-enabled pin.
 * 
 *  @param      pin the number of the pin to read.
 *
 *  @return     the analog value. This is an integer between 0 and 1023
 ****************************************************************************************/
uint16_t Adafruit_seesaw::touchRead(uint8_t pin)
{
	uint8_t buf[2];
	uint8_t p = pin;

	this->read(SEESAW_TOUCH_BASE, SEESAW_TOUCH_CHANNEL_OFFSET + p, buf, 2, 500);
	uint16_t ret = ((uint16_t)buf[0] << 8) | buf[1];
  	delay(1);
	return ret;
}

/**
 *****************************************************************************************
 *  @brief      set the mode of multiple GPIO pins at once.
 * 
 *  @param      pins a bitmask of the pins to write. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				For example, passing 0b0110 will set the mode of pins 2 and 3.
 *	@param		mode the mode to set the pins to. One of INPUT, OUTPUT, or INPUT_PULLUP.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::pinModeBulk(uint32_t pins, uint8_t mode)
{
	uint8_t cmd[] = { (uint8_t)(pins >> 24) , (uint8_t)(pins >> 16), (uint8_t)(pins >> 8), (uint8_t)pins };
	switch (mode){
		case OUTPUT:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRSET_BULK, cmd, 4);
			break;
		case INPUT:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 4);
			break;
		case INPUT_PULLUP:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 4);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 4);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 4);
			break;
		case INPUT_PULLDOWN:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 4);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 4);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 4);
			break;
	}
		
}

/**
 *****************************************************************************************
 *  @brief      set the mode of multiple GPIO pins at once. This supports both ports A and B.
 * 
 *  @param      pinsa a bitmask of the pins to write on port A. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				For example, passing 0b0110 will set the mode of pins 2 and 3.
 *  @param      pinsb a bitmask of the pins to write on port B.
 *	@param		mode the mode to set the pins to. One of INPUT, OUTPUT, or INPUT_PULLUP.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::pinModeBulk(uint32_t pinsa, uint32_t pinsb, uint8_t mode)
{
	uint8_t cmd[] = { (uint8_t)(pinsa >> 24) , (uint8_t)(pinsa >> 16), (uint8_t)(pinsa >> 8), (uint8_t)pinsa,
				(uint8_t)(pinsb >> 24) , (uint8_t)(pinsb >> 16), (uint8_t)(pinsb >> 8), (uint8_t)pinsb };
	switch (mode){
		case OUTPUT:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRSET_BULK, cmd, 8);
			break;
		case INPUT:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 8);
			break;
		case INPUT_PULLUP:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 8);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 8);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 8);
			break;
		case INPUT_PULLDOWN:
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_DIRCLR_BULK, cmd, 8);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_PULLENSET, cmd, 8);
			this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 8);
			break;
	}
}

/**
 *****************************************************************************************
 *  @brief      write a value to multiple GPIO pins at once.
 * 
 *  @param      pins a bitmask of the pins to write. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				For example, passing 0b0110 will write the passed value to pins 2 and 3.
 *	@param		value pass HIGH to set the output on the passed pins to HIGH, low to set the output on the passed pins to LOW.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::digitalWriteBulk(uint32_t pins, uint8_t value)
{
	uint8_t cmd[] = { (uint8_t)(pins >> 24) , (uint8_t)(pins >> 16), (uint8_t)(pins >> 8), (uint8_t)pins };
	if(value)
		this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 4);
	else
		this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 4);
}

/**
 *****************************************************************************************
 *  @brief      write a value to multiple GPIO pins at once. This supports both ports A and B
 * 
 *  @param      pinsa a bitmask of the pins to write on port A. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				For example, passing 0b0110 will write the passed value to pins 2 and 3.
 *  @param      pinsb a bitmask of the pins to write on port B.
 *	@param		value pass HIGH to set the output on the passed pins to HIGH, low to set the output on the passed pins to LOW.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::digitalWriteBulk(uint32_t pinsa, uint32_t pinsb, uint8_t value)
{
	uint8_t cmd[] = { (uint8_t)(pinsa >> 24) , (uint8_t)(pinsa >> 16), (uint8_t)(pinsa >> 8), (uint8_t)pinsa,
				(uint8_t)(pinsb >> 24) , (uint8_t)(pinsb >> 16), (uint8_t)(pinsb >> 8), (uint8_t)pinsb };
	if(value)
		this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_SET, cmd, 8);
	else
		this->write(SEESAW_GPIO_BASE, SEESAW_GPIO_BULK_CLR, cmd, 8);
}

/**
 *****************************************************************************************
 *  @brief      write a PWM value to a PWM-enabled pin
 * 
 *  @param      pin the number of the pin to write. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				on the default seesaw firmware on the SAMD09 breakout, pins 5, 6, and 7 are PWM enabled.
 *	@param		value the value to write to the pin
 *	@param		width the width of the value to write. Defaults to 8. If 16 is passed a 16 bit value will be written.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::analogWrite(uint8_t pin, uint16_t value, uint8_t width)
{
	int8_t p = -1;
	switch(pin){
		case PWM_0_PIN: p = 0; break;
		case PWM_1_PIN: p = 1; break;
		case PWM_2_PIN: p = 2; break;
		case PWM_3_PIN: p = 3; break;
		default:
			break;
	}
	if(p > -1){
		if(width == 16){
			uint8_t cmd[] = {(uint8_t)p, (uint8_t)(value >> 8), (uint8_t)value};
			this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
		}
		else 
		{
			uint16_t mappedVal = map(value, 0, 255, 0, 65535);
			uint8_t cmd[] = {(uint8_t)p, (uint8_t)(mappedVal >> 8), (uint8_t)mappedVal};
			this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
		}
	}
}

/**
 *****************************************************************************************
 *  @brief      set the PWM frequency of a PWM-enabled pin. Note that on SAMD09, SAMD11 boards
 *				the frequency will be mapped to closest match fixed frequencies.
 *				Also note that PWM pins 4 and 5 share a timer, and PWM pins 6 and 7 share a timer.
 *				Changing the frequency for one pin will change the frequency for the other pin that
 *				is on the timer.
 * 
 *  @param      pin the number of the pin to change frequency of. On the SAMD09 breakout, this corresponds to the number on the silkscreen.
 *				on the default seesaw firmware on the SAMD09 breakout, pins 5, 6, and 7 are PWM enabled.
 *	@param		freq the frequency to set.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::setPWMFreq(uint8_t pin, uint16_t freq)
{
	int8_t p = -1;
	switch(pin){
		case PWM_0_PIN: p = 0; break;
		case PWM_1_PIN: p = 1; break;
		case PWM_2_PIN: p = 2; break;
		case PWM_3_PIN: p = 3; break;
		default:
			break;
	}
	if(p > -1){
		uint8_t cmd[] = {(uint8_t)p, (uint8_t)(freq >> 8), (uint8_t)freq};
		this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_FREQ, cmd, 3);
	}
}

/**
 *****************************************************************************************
 *  @brief      Enable the data ready interrupt on the passed sercom. Note that both the interrupt module and
 *				the passed sercom must be compiled into the seesaw firmware for this to function.
 *				If both of these things are true, the interrupt pin on the seesaw will fire when
 *				there is data to be read from the passed sercom. On the default seesaw firmeare
 *				on the SAMD09 breakout, no sercoms are enabled.
 * 
 *  @param      sercom the sercom to enable the interrupt on. 
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::enableSercomDataRdyInterrupt(uint8_t sercom)
{
	_sercom_inten.bit.DATA_RDY = 1;
	this->write8(SEESAW_SERCOM0_BASE + sercom, SEESAW_SERCOM_INTEN, _sercom_inten.reg);
}

/**
 *****************************************************************************************
 *  @brief      Disable the data ready interrupt on the passed sercom.
 * 
 *  @param      sercom the sercom to disable the interrupt on. 
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::disableSercomDataRdyInterrupt(uint8_t sercom)
{
	_sercom_inten.bit.DATA_RDY = 0;
	this->write8(SEESAW_SERCOM0_BASE + sercom, SEESAW_SERCOM_INTEN, _sercom_inten.reg);
}

/**
 *****************************************************************************************
 *  @brief      Reads a character from the passed sercom if one is available. Note that on
 *				the default seesaw firmware on the SAMD09 breakout no sercoms are enabled.
 * 
 *  @param      sercom the sercom to read data from.
 *
 *  @return     a character read from the sercom.
 ****************************************************************************************/
char Adafruit_seesaw::readSercomData(uint8_t sercom)
{
	return this->read8(SEESAW_SERCOM0_BASE + sercom, SEESAW_SERCOM_DATA);
}

/**
 *****************************************************************************************
 *  @brief      Set the seesaw I2C address. This will automatically call Adafruit_seesaw.begin()
 *				with the new address.
 * 
 *  @param      addr the new address for the seesaw. This must be a valid 7 bit I2C address.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::setI2CAddr(uint8_t addr)
{
  this->EEPROMWrite8(SEESAW_EEPROM_I2C_ADDR, addr);
  delay(250);
  this->begin(addr); //restart w/ the new addr
}


/**
 *****************************************************************************************
 *  @brief      Read the I2C address of the seesaw
 *
 *  @return     the 7 bit I2C address of the seesaw... which you probably already know because you
 *				just read data from it.
 ****************************************************************************************/
uint8_t Adafruit_seesaw::getI2CAddr()
{
  return this->read8(SEESAW_EEPROM_BASE, SEESAW_EEPROM_I2C_ADDR);
}

/**
 *****************************************************************************************
 *  @brief      Write a 1 byte to an EEPROM address
 * 
 *  @param      addr the address to write to. On the default seesaw firmware on the SAMD09
 *				breakout this is between 0 and 63.
 *	@param		val to write between 0 and 255
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::EEPROMWrite8(uint8_t addr, uint8_t val)
{
  this->EEPROMWrite(addr, &val, 1);
}

/**
 *****************************************************************************************
 *  @brief      write a string of bytes to EEPROM starting at the passed address
 * 
 *  @param      addr the starting address to write the first byte. This will be automatically
 *				incremented with each byte written.
 *	@param		buf the buffer of bytes to be written.
 *	@param		size the number of bytes to write. Writing past the end of available EEPROM
 *				may result in undefined behavior.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::EEPROMWrite(uint8_t addr, uint8_t *buf, uint8_t size)
{
  this->write(SEESAW_EEPROM_BASE, addr, buf, size);
}

/**
 *****************************************************************************************
 *  @brief      Read 1 byte from the specified EEPROM address.
 * 
 *  @param      addr the address to read from. One the default seesaw firmware on the SAMD09
 *				breakout this is between 0 and 63.
 *
 *  @return     the value between 0 and 255 that was read from the passed address.
 ****************************************************************************************/
uint8_t Adafruit_seesaw::EEPROMRead8(uint8_t addr)
{
  return this->read8(SEESAW_EEPROM_BASE, addr);
}

/**
 *****************************************************************************************
 *  @brief      Set the baud rate on SERCOM0.
 * 
 *  @param      baud the baud rate to set. This is an integer value. Baud rates up to 115200 are supported.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::UARTSetBaud(uint32_t baud)
{
	uint8_t cmd[] = { (uint8_t)(baud >> 24), (uint8_t)(baud >> 16), (uint8_t)(baud >> 8), (uint8_t)baud };
	this->write(SEESAW_SERCOM0_BASE, SEESAW_SERCOM_BAUD, cmd, 4);
}

/**
 *****************************************************************************************
 *  @brief      activate or deactivate a key and edge on the keypad module
 * 
 *  @param      key the key number to activate
 *  @param		edge the edge to trigger on
 *  @param		enable passing true will enable the passed event, passing false will disable it.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::setKeypadEvent(uint8_t key, uint8_t edge, bool enable)
{
	keyState ks;
	ks.bit.STATE = enable;
	ks.bit.ACTIVE = (1 << edge);
	uint8_t cmd[] = {key, ks.reg};
	this->write(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_EVENT, cmd, 2);
}

/**
 *****************************************************************************************
 *  @brief      enable the keypad interrupt that fires when events are in the fifo.
 ****************************************************************************************/
void Adafruit_seesaw::enableKeypadInterrupt()
{
	this->write8(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_INTENSET, 0x01);
}

/**
 *****************************************************************************************
 *  @brief      disable the keypad interrupt that fires when events are in the fifo.
 ****************************************************************************************/
void Adafruit_seesaw::disableKeypadInterrupt()
{
	this->write8(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_INTENCLR, 0x01);
}

/**
 *****************************************************************************************
 *  @brief      Get the number of events currently in the fifo
 *  @return     the number of events in the fifo
 ****************************************************************************************/
uint8_t Adafruit_seesaw::getKeypadCount()
{
	return this->read8(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_COUNT, 500);
}

/**
 *****************************************************************************************
 *  @brief      Read all keyEvents into the passed buffer
 * 
 *  @param      buf pointer to where the keyEvents should be stored
 *  @param		count the number of events to read
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::readKeypad(keyEventRaw *buf, uint8_t count)
{
	return this->read(SEESAW_KEYPAD_BASE, SEESAW_KEYPAD_FIFO, (uint8_t *)buf, count, 1000);
}

/**
 *****************************************************************************************
 *  @brief      Read the temperature of the seesaw board in degrees Celsius. NOTE: not all
 * 				seesaw firmwares have the temperature sensor enabled.
 *  @return     Temperature in degrees Celsius as a floating point value.
 ****************************************************************************************/
float Adafruit_seesaw::getTemp()
{
	uint8_t buf[4];
	this->read(SEESAW_STATUS_BASE, SEESAW_STATUS_TEMP, buf, 4, 1000);
	int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
	return (1.0/(1UL << 16)) * ret;
}

/**
 *****************************************************************************************
 *  @brief      Read the current position of the encoder
 *  @return     The encoder position as a 32 bit signed integer.
 ****************************************************************************************/
int32_t Adafruit_seesaw::getEncoderPosition()
{
	uint8_t buf[4];
	this->read(SEESAW_ENCODER_BASE, SEESAW_ENCODER_POSITION, buf, 4);
	int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];

	return ret;
}

/**
 *****************************************************************************************
 *  @brief      Set the current position of the encoder
 *  @param     pos the position to set the encoder to.
 ****************************************************************************************/
void Adafruit_seesaw::setEncoderPosition(int32_t pos)
{
	uint8_t buf[] = { (uint8_t)(pos >> 24), (uint8_t)(pos >> 16), (uint8_t)(pos >> 8), (uint8_t)(pos & 0xFF) };
	this->write(SEESAW_ENCODER_BASE, SEESAW_ENCODER_POSITION, buf, 4);
}

/**
 *****************************************************************************************
 *  @brief      Read the change in encoder position since it was last read.
 *  @return     The encoder change as a 32 bit signed integer.
 ****************************************************************************************/
int32_t Adafruit_seesaw::getEncoderDelta()
{
	uint8_t buf[4];
	this->read(SEESAW_ENCODER_BASE, SEESAW_ENCODER_DELTA, buf, 4);
	int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];

	return ret;
}

/**
 *****************************************************************************************
 *  @brief      Enable the interrupt to fire when the encoder changes position.
 ****************************************************************************************/
void Adafruit_seesaw::enableEncoderInterrupt()
{
	this->write8(SEESAW_ENCODER_BASE, SEESAW_ENCODER_INTENSET, 0x01);	
}

/**
 *****************************************************************************************
 *  @brief      Disable the interrupt from firing when the encoder changes position.
 ****************************************************************************************/
void Adafruit_seesaw::disableEncoderInterrupt()
{
	this->write8(SEESAW_ENCODER_BASE, SEESAW_ENCODER_INTENCLR, 0x01);	
}

/**
 *****************************************************************************************
 *  @brief      Write 1 byte to the specified seesaw register.
 * 
 *  @param      regHigh the module address register (ex. SEESAW_NEOPIXEL_BASE)
 *	@param		regLow the function address register (ex. SEESAW_NEOPIXEL_PIN)
 *	@param		value the value between 0 and 255 to write
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::write8(byte regHigh, byte regLow, byte value)
{
	this->write(regHigh, regLow, &value, 1);
}

/**
 *****************************************************************************************
 *  @brief      read 1 byte from the specified seesaw register.
 * 
 *  @param      regHigh the module address register (ex. SEESAW_STATUS_BASE)
 *	@param		regLow the function address register (ex. SEESAW_STATUS_VERSION)
 *	@param		delay a number of microseconds to delay before reading out the data.
 *				Different delay values may be necessary to ensure the seesaw chip has
 *				time to process the requested data. Defaults to 125.
 *
 *  @return     the value between 0 and 255 read from the passed register
 ****************************************************************************************/
uint8_t Adafruit_seesaw::read8(byte regHigh, byte regLow, uint16_t delay)
{
	uint8_t ret;
	this->read(regHigh, regLow, &ret, 1, delay);
	
	return ret;
}

/**
 *****************************************************************************************
 *  @brief      Initialize I2C. On arduino this just calls i2c->begin()
 * 
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::_i2c_init()
{
  _i2cbus->begin();
}

/**
 *****************************************************************************************
 *  @brief      Read a specified number of bytes into a buffer from the seesaw.
 * 
 *  @param      regHigh the module address register (ex. SEESAW_STATUS_BASE)
 *	@param		regLow the function address register (ex. SEESAW_STATUS_VERSION)
 *	@param		buf the buffer to read the bytes into
 *	@param		num the number of bytes to read.
 *	@param		delay an optional delay in between setting the read register and reading
 *				out the data. This is required for some seesaw functions (ex. reading ADC data)
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::read(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num, uint16_t delay)
{
	uint8_t pos = 0;
	
	//on arduino we need to read in 32 byte chunks
	while(pos < num){
		
		uint8_t read_now = min(32, num - pos);
		_i2cbus->beginTransmission((uint8_t)_i2caddr);
		_i2cbus->write((uint8_t)regHigh);
		_i2cbus->write((uint8_t)regLow);
		if(_flow != -1) while(!::digitalRead(_flow));
		_i2cbus->endTransmission();

		//TODO: tune this
		delayMicroseconds(delay);

		if(_flow != -1) while(!::digitalRead(_flow));
		_i2cbus->requestFrom((uint8_t)_i2caddr, read_now);
		
		for(int i=0; i<read_now; i++){
			buf[pos] = _i2cbus->read();
			pos++;
		}
	}
}

/**
 *****************************************************************************************
 *  @brief      Write a specified number of bytes to the seesaw from the passed buffer.
 * 
 *  @param      regHigh the module address register (ex. SEESAW_GPIO_BASE)
 *	@param		regLow the function address register (ex. SEESAW_GPIO_BULK_SET)
 *	@param		buf the buffer the the bytes from
 *	@param		num the number of bytes to write.
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::write(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num)
{ 
	_i2cbus->beginTransmission((uint8_t)_i2caddr);
	_i2cbus->write((uint8_t)regHigh);
	_i2cbus->write((uint8_t)regLow);
	_i2cbus->write((uint8_t *)buf, num);
	if(_flow != -1) while(!::digitalRead(_flow));
	_i2cbus->endTransmission();
}

/**
 *****************************************************************************************
 *  @brief      The print wrapper for the seesaw class. Calling this allows you to use
 *				ss.print() or ss.println() and write to the UART on SERCOM0 of the seesaw.
 *				Note that this functionality is only available when the UART (sercom) module
 *				is compiled into the seesaw firmware. On the default seesaw firmware on the
 *				SAMD09 breakout this functionality is not available.
 * 
 *  @param      character the character to write.
 *
 *  @return     none
 ****************************************************************************************/
size_t Adafruit_seesaw::write(uint8_t character) {
	//TODO: add support for multiple sercoms
	this->write8(SEESAW_SERCOM0_BASE, SEESAW_SERCOM_DATA, character);
	delay(1); //TODO: this can be optimized... it's only needed for longer writes
	return 1;
}

/**
 *****************************************************************************************
 *  @brief      The print wrapper for the seesaw class allowing the user to print a string. 
 *				Calling this allows you to use
 *				ss.print() or ss.println() and write to the UART on SERCOM0 of the seesaw.
 *				Note that this functionality is only available when the UART (sercom) module
 *				is compiled into the seesaw firmware. On the default seesaw firmware on the
 *				SAMD09 breakout this functionality is not available.
 * 
 *  @param      str the string to write
 *
 *  @return     none
 ****************************************************************************************/
size_t Adafruit_seesaw::write(const char *str) {
	uint8_t buf[32];
	uint8_t len = 0;
	while(*str){
		buf[len] = *str;
		str++;
		len++;
	}
	this->write(SEESAW_SERCOM0_BASE, SEESAW_SERCOM_DATA, buf, len);
	return len;
}

/**
 *****************************************************************************************
 *  @brief      Write only the module base address register and the function address register.
 * 
 *  @param      regHigh the module address register (ex. SEESAW_STATUS_BASE)
 *	@param		regLow the function address register (ex. SEESAW_STATUS_SWRST)
 *
 *  @return     none
 ****************************************************************************************/
void Adafruit_seesaw::writeEmpty(uint8_t regHigh, uint8_t regLow)
{
    _i2cbus->beginTransmission((uint8_t)_i2caddr);
    _i2cbus->write((uint8_t)regHigh);
    _i2cbus->write((uint8_t)regLow);
    if(_flow != -1) while(!::digitalRead(_flow));
    _i2cbus->endTransmission();
}

Base DC Motor Code for Featherwing Crickit-seesaw.h

Arduino
Adafruit supplied base code
/*!
 * @file Adafruit_seesaw.h
 *
 * This is part of Adafruit's seesaw driver for the Arduino platform.  It is
 * designed specifically to work with the Adafruit products that use seesaw technology.
 *
 * These chips use I2C to communicate, 2 pins (SCL+SDA) are required
 * to interface with the board.
 *
 * Adafruit invests time and resources providing this open source code,
 * please support Adafruit and open-source hardware by purchasing
 * products from Adafruit!
 *
 * Written by Dean Miller for Adafruit Industries.
 *
 * BSD license, all text here must be included in any redistribution.
 *
 */

#ifndef LIB_SEESAW_H
#define LIB_SEESAW_H

#if (ARDUINO >= 100)
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#include <Wire.h>

/*=========================================================================
    I2C ADDRESS/BITS
    -----------------------------------------------------------------------*/
    #define SEESAW_ADDRESS                (0x49) ///< Default Seesaw I2C address
/*=========================================================================*/

/*=========================================================================
    REGISTERS
    -----------------------------------------------------------------------*/

    /** Module Base Addreses
     *  The module base addresses for different seesaw modules.
     */
    enum
    {
        SEESAW_STATUS_BASE = 0x00,
        SEESAW_GPIO_BASE = 0x01,
        SEESAW_SERCOM0_BASE = 0x02,

        SEESAW_TIMER_BASE = 0x08,
        SEESAW_ADC_BASE = 0x09,
        SEESAW_DAC_BASE = 0x0A,
        SEESAW_INTERRUPT_BASE = 0x0B,
        SEESAW_DAP_BASE = 0x0C,
        SEESAW_EEPROM_BASE = 0x0D,
        SEESAW_NEOPIXEL_BASE = 0x0E,
        SEESAW_TOUCH_BASE = 0x0F,
        SEESAW_KEYPAD_BASE = 0x10,
        SEESAW_ENCODER_BASE = 0x11,
    };

    /** GPIO module function addres registers
     */
    enum
    {
        SEESAW_GPIO_DIRSET_BULK = 0x02,
        SEESAW_GPIO_DIRCLR_BULK = 0x03,
        SEESAW_GPIO_BULK = 0x04,
        SEESAW_GPIO_BULK_SET = 0x05,
        SEESAW_GPIO_BULK_CLR = 0x06,
        SEESAW_GPIO_BULK_TOGGLE = 0x07,
        SEESAW_GPIO_INTENSET = 0x08,
        SEESAW_GPIO_INTENCLR = 0x09,
        SEESAW_GPIO_INTFLAG = 0x0A,
        SEESAW_GPIO_PULLENSET = 0x0B,
        SEESAW_GPIO_PULLENCLR = 0x0C,
    };

    /** status module function addres registers
     */
    enum
    {
        SEESAW_STATUS_HW_ID = 0x01,
        SEESAW_STATUS_VERSION = 0x02,
        SEESAW_STATUS_OPTIONS = 0x03,
        SEESAW_STATUS_TEMP = 0x04,
        SEESAW_STATUS_SWRST = 0x7F,
    };

    /** timer module function addres registers
     */
    enum
    {
        SEESAW_TIMER_STATUS = 0x00,
        SEESAW_TIMER_PWM = 0x01,
        SEESAW_TIMER_FREQ = 0x02,
    };
	
    /** ADC module function addres registers
     */
    enum
    {
        SEESAW_ADC_STATUS = 0x00,
        SEESAW_ADC_INTEN = 0x02,
        SEESAW_ADC_INTENCLR = 0x03,
        SEESAW_ADC_WINMODE = 0x04,
        SEESAW_ADC_WINTHRESH = 0x05,
        SEESAW_ADC_CHANNEL_OFFSET = 0x07,
    };

    /** Sercom module function addres registers
     */
    enum
    {
        SEESAW_SERCOM_STATUS = 0x00,
        SEESAW_SERCOM_INTEN = 0x02,
        SEESAW_SERCOM_INTENCLR = 0x03,
        SEESAW_SERCOM_BAUD = 0x04,
        SEESAW_SERCOM_DATA = 0x05,
    };

    /** neopixel module function addres registers
     */
    enum
    {
        SEESAW_NEOPIXEL_STATUS = 0x00,
        SEESAW_NEOPIXEL_PIN = 0x01,
        SEESAW_NEOPIXEL_SPEED = 0x02,
        SEESAW_NEOPIXEL_BUF_LENGTH = 0x03,
        SEESAW_NEOPIXEL_BUF = 0x04,
        SEESAW_NEOPIXEL_SHOW = 0x05,
    };

    /** touch module function addres registers
     */
    enum
    {
        SEESAW_TOUCH_CHANNEL_OFFSET = 0x10,
    };

    /** keypad module function addres registers
     */
    enum
    {
        SEESAW_KEYPAD_STATUS = 0x00,
        SEESAW_KEYPAD_EVENT = 0x01,
        SEESAW_KEYPAD_INTENSET = 0x02,
        SEESAW_KEYPAD_INTENCLR = 0x03,
        SEESAW_KEYPAD_COUNT = 0x04,
        SEESAW_KEYPAD_FIFO = 0x10,
    };

    /** keypad module edge definitions
     */
    enum 
    {
        SEESAW_KEYPAD_EDGE_HIGH = 0,
        SEESAW_KEYPAD_EDGE_LOW,
        SEESAW_KEYPAD_EDGE_FALLING,
        SEESAW_KEYPAD_EDGE_RISING,
    };

    /** encoder module edge definitions
     */
    enum
    {
        SEESAW_ENCODER_STATUS = 0x00,
        SEESAW_ENCODER_INTENSET = 0x02,
        SEESAW_ENCODER_INTENCLR = 0x03,
        SEESAW_ENCODER_POSITION = 0x04,
        SEESAW_ENCODER_DELTA = 0x05,
    };

#define ADC_INPUT_0_PIN 2 ///< default ADC input pin 
#define ADC_INPUT_1_PIN 3 ///< default ADC input pin
#define ADC_INPUT_2_PIN 4 ///< default ADC input pin
#define ADC_INPUT_3_PIN 5 ///< default ADC input pin

#define PWM_0_PIN 4 ///< default PWM output pin
#define PWM_1_PIN 5 ///< default PWM output pin
#define PWM_2_PIN 6 ///< default PWM output pin
#define PWM_3_PIN 7 ///< default PWM output pin

#ifndef INPUT_PULLDOWN
#define INPUT_PULLDOWN 0x03 ///< for compatibility with platforms that do not already define INPUT_PULLDOWN
#endif

/*=========================================================================*/

#define SEESAW_HW_ID_CODE			0x55 ///< seesaw HW ID code
#define SEESAW_EEPROM_I2C_ADDR 0x3F ///< EEPROM address of i2c address to start up with (for devices that support this feature)

/** raw key event stucture for keypad module */
union keyEventRaw {
    struct {
        uint8_t EDGE: 2; ///< the edge that was triggered
        uint8_t NUM: 6; ///< the event number
    } bit; ///< bitfield format
    uint8_t reg; ///< register format
};


/** extended key event stucture for keypad module */
union keyEvent {
    struct {
        uint8_t EDGE: 2; ///< the edge that was triggered
        uint16_t NUM: 14; ///< the event number
    } bit; ///< bitfield format
    uint16_t reg; ///< register format
};

/** key state struct that will be written to seesaw chip keypad module */
union keyState {
    struct {
        uint8_t STATE: 1; ///< the current state of the key
        uint8_t ACTIVE: 4; ///< the registered events for that key
    } bit; ///< bitfield format
    uint8_t reg; ///< register format
};

/**************************************************************************/
/*! 
    @brief  Class that stores state and functions for interacting with seesaw helper IC
*/
/**************************************************************************/
class Adafruit_seesaw : public Print {
	public:
	// constructors
        Adafruit_seesaw(TwoWire *Wi=NULL);
        ~Adafruit_seesaw(void) {};
		
	bool begin(uint8_t addr = SEESAW_ADDRESS, int8_t flow=-1, bool reset=true);
        uint32_t getOptions();
        uint32_t getVersion();
	void SWReset();

        void pinMode(uint8_t pin, uint8_t mode);
        void pinModeBulk(uint32_t pins, uint8_t mode);
        void pinModeBulk(uint32_t pinsa, uint32_t pinsb, uint8_t mode);
        virtual void analogWrite(uint8_t pin, uint16_t value, uint8_t width = 8);
        void digitalWrite(uint8_t pin, uint8_t value);
        void digitalWriteBulk(uint32_t pins, uint8_t value);
        void digitalWriteBulk(uint32_t pinsa, uint32_t pinsb, uint8_t value);

        bool digitalRead(uint8_t pin);
        uint32_t digitalReadBulk(uint32_t pins);
        uint32_t digitalReadBulkB(uint32_t pins);

        void setGPIOInterrupts(uint32_t pins, bool enabled);

        virtual uint16_t analogRead(uint8_t pin);

        uint16_t touchRead(uint8_t pin);

        virtual void setPWMFreq(uint8_t pin, uint16_t freq);

        void enableSercomDataRdyInterrupt(uint8_t sercom = 0);
        void disableSercomDataRdyInterrupt(uint8_t sercom = 0);

        char readSercomData(uint8_t sercom = 0);

        void EEPROMWrite8(uint8_t addr, uint8_t val);
        void EEPROMWrite(uint8_t addr, uint8_t *buf, uint8_t size);
        uint8_t EEPROMRead8(uint8_t addr);

        void setI2CAddr(uint8_t addr);
        uint8_t getI2CAddr();

        void UARTSetBaud(uint32_t baud);

        void setKeypadEvent(uint8_t key, uint8_t edge, bool enable=true);
        void enableKeypadInterrupt();
        void disableKeypadInterrupt();
        uint8_t getKeypadCount();
        void readKeypad(keyEventRaw *buf, uint8_t count);

        float getTemp();

        int32_t getEncoderPosition();
        int32_t getEncoderDelta();
        void enableEncoderInterrupt();
        void disableEncoderInterrupt();
        void setEncoderPosition(int32_t pos);

        virtual size_t write(uint8_t);
        virtual size_t write(const char *str);

	protected:
		uint8_t _i2caddr; /*!< The I2C address used to communicate with the seesaw */
		TwoWire *_i2cbus; /*!< The I2C Bus used to communicate with the seesaw */
		int8_t _flow; /*!< The flow control pin to use */

		void      write8(byte regHigh, byte regLow, byte value);
		uint8_t   read8(byte regHigh, byte regLow, uint16_t delay = 125);
		
		void read(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num, uint16_t delay = 125);
		void write(uint8_t regHigh, uint8_t regLow, uint8_t *buf, uint8_t num);
		void writeEmpty(uint8_t regHigh, uint8_t regLow);
		void _i2c_init();

/*=========================================================================
	REGISTER BITFIELDS
    -----------------------------------------------------------------------*/

        /** Sercom interrupt enable register
        */
        union sercom_inten {
            struct {
                uint8_t DATA_RDY : 1; ///< this bit is set when data becomes available
            } bit; ///< bitfields
            uint8_t reg; ///< full register
        };
        sercom_inten _sercom_inten; ///< sercom interrupt enable register instance

/*=========================================================================*/
};

#endif

Base DC Motor Code for Featherwing Crickit-crickit.h

Arduino
Adafruit supplied code
#ifndef _CRICKIT_TERSTER_H
#define _CRICKIT_TERSTER_H

#include "Adafruit_seesaw.h"

#define CRICKIT_SIGNAL1 2
#define CRICKIT_SIGNAL2 3
#define CRICKIT_SIGNAL3 40
#define CRICKIT_SIGNAL4 41
#define CRICKIT_SIGNAL5 11
#define CRICKIT_SIGNAL6 10
#define CRICKIT_SIGNAL7 9
#define CRICKIT_SIGNAL8 8

#define CRICKIT_SERVO4 14
#define CRICKIT_SERVO3 15
#define CRICKIT_SERVO2 16
#define CRICKIT_SERVO1 17

#define CRICKIT_MOTOR_A1 22
#define CRICKIT_MOTOR_A2 23
#define CRICKIT_MOTOR_B1 19
#define CRICKIT_MOTOR_B2 18
#define CRICKIT_DRIVE1 13
#define CRICKIT_DRIVE2 12
#define CRICKIT_DRIVE3 43
#define CRICKIT_DRIVE4 42

#define CRICKIT_TOUCH1 0
#define CRICKIT_TOUCH2 1
#define CRICKIT_TOUCH3 2
#define CRICKIT_TOUCH4 3

#define CRICKIT_DUTY_CYCLE_OFF 0
#define CRICKIT_DUTY_CYCLE_MAX 65535

/**************************************************************************/
/*! 
    @brief  Class that stores state and functions for interacting with Crickit variant of seesaw helper IC
*/
/**************************************************************************/
class Adafruit_Crickit : public Adafruit_seesaw {
public:
	Adafruit_Crickit() {};
	~Adafruit_Crickit() {};

	void analogWrite(uint8_t pin, uint16_t value, uint8_t width = 8);
	uint16_t analogRead(uint8_t pin);
	void setPWMFreq(uint8_t pin, uint16_t freq);
};

#endif

Base DC Motor Code for Featherwing Crickit-crickit.cpp

Arduino
Adafruit supplied code
#include "Adafruit_Crickit.h"

//the pwm pins
#define CRICKIT_NUM_PWM 12
static const uint8_t CRICKIT_pwms[CRICKIT_NUM_PWM] = {CRICKIT_SERVO4, CRICKIT_SERVO3, CRICKIT_SERVO2, CRICKIT_SERVO1,
													CRICKIT_MOTOR_B1, CRICKIT_MOTOR_B2, CRICKIT_MOTOR_A1, CRICKIT_MOTOR_A2, 
													CRICKIT_DRIVE4, CRICKIT_DRIVE3, CRICKIT_DRIVE2, CRICKIT_DRIVE1};

//the adc pin
#define CRICKIT_NUM_ADC 8
static const uint8_t CRICKIT_adc[CRICKIT_NUM_ADC] = { CRICKIT_SIGNAL1, CRICKIT_SIGNAL2, CRICKIT_SIGNAL3, CRICKIT_SIGNAL4,
													CRICKIT_SIGNAL5, CRICKIT_SIGNAL6, CRICKIT_SIGNAL7, CRICKIT_SIGNAL8 };

void Adafruit_Crickit::analogWrite(uint8_t pin, uint16_t value, uint8_t width)
{
	(void)width;

	int8_t p = -1;
	for(int i=0; i<CRICKIT_NUM_PWM; i++){
		if(CRICKIT_pwms[i] == pin){
			p = i;
			break;
		}
	}

	if(p > -1){
		uint8_t cmd[] = {(uint8_t)p, (uint8_t)(value >> 8), (uint8_t)value};
		this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_PWM, cmd, 3);
	}
}

uint16_t Adafruit_Crickit::analogRead(uint8_t pin)
{
	uint8_t buf[2];
	int8_t p = -1;
	for(int i=0; i<CRICKIT_NUM_ADC; i++){
		if(CRICKIT_adc[i] == pin){
			p = i;
			break;
		}
	}

	if(p > -1){
		this->read(SEESAW_ADC_BASE, SEESAW_ADC_CHANNEL_OFFSET + p, buf, 2, 500);
		uint16_t ret = ((uint16_t)buf[0] << 8) | buf[1];
	  	delay(1);
		return ret;
	}
	else return 0;
}

void Adafruit_Crickit::setPWMFreq(uint8_t pin, uint16_t freq)
{
	int8_t p = -1;
	for(int i=0; i<CRICKIT_NUM_PWM; i++){
		if(CRICKIT_pwms[i] == pin){
			p = i;
			break;
		}
	}

	if(p > -1){
		uint8_t cmd[] = {(uint8_t)p, (uint8_t)(freq >> 8), (uint8_t)freq};
		this->write(SEESAW_TIMER_BASE, SEESAW_TIMER_FREQ, cmd, 3);
	}
}

Base DC Motor Code for Featherwing Crickit-DC Motor

Arduino
Adafruit supplied code with longer drive times
#include "Adafruit_Crickit.h"
#include "seesaw_motor.h"

Adafruit_Crickit crickit;

seesaw_Motor motor_a(&crickit);
seesaw_Motor motor_b(&crickit);

void setup() {
  Serial.begin(115200);
  Serial.println("Dual motor demo!");
  
  if(!crickit.begin()){
    Serial.println("ERROR!");
    while(1);
  }
  else Serial.println("Crickit started");

  //attach motor a
  motor_a.attach(CRICKIT_MOTOR_A1, CRICKIT_MOTOR_A2);

  //attach motor b
  motor_b.attach(CRICKIT_MOTOR_B1, CRICKIT_MOTOR_B2);
}

void loop() {
  motor_a.throttle(1);
  motor_b.throttle(-1);
  delay(5000);

  motor_a.throttle(.5);
  motor_b.throttle(-.5);
  delay(5000);

  motor_a.throttle(0);
  motor_b.throttle(0);
  delay(5000);

  motor_a.throttle(-.5);
  motor_b.throttle(.5);
  delay(5000);

  motor_a.throttle(-1);
  motor_b.throttle(1);
  delay(5000);

  motor_a.throttle(0);
  motor_b.throttle(0);
  delay(5000);
  
  motor_a.throttle(.5);
  motor_b.throttle(.5);
  delay(5000);
  
  motor_a.throttle(-.5);
  motor_b.throttle(-.5);
  delay(5000);
  
  motor_a.throttle(1);
  motor_b.throttle(1);
  delay(5000);
  
  motor_a.throttle(-1);
  motor_b.throttle(-1);
  delay(5000);
  
  motor_a.throttle(0);
  motor_b.throttle(0);
  delay(5000);
}

Credits

James Martel

James Martel

28 projects • 28 followers
Self taught Robotics platform developer with electronics background

Comments