Commit f88d705d authored by Martin Horauer's avatar Martin Horauer
Browse files

added I2C example

parent b30aa796
data/ADJDs311.cpp.i
data/ADJDs311.h.i
0
pull
https://mbed.org/users/CheeseW/code/ADJDs311
#include "ADJDs311.h"
#include "mbed.h"
#include <algorithm>
ADJDs311::ADJDs311(PinName sda, PinName scl, PinName led):
_i2c(sda, scl), _led(led) {
// hard coded value for number of capacitors
colorCap.red = 12;
colorCap.green = 9;
colorCap.blue = 2;
colorCap.clear = 9;
// hard coded value for number of integration time slot
colorInt.red = 16;
colorInt.green = 16;
colorInt.blue = 16;
colorInt.clear = 16;
colorOffset.red = readRegister(OFFSET_RED);
colorOffset.green = readRegister(OFFSET_GREEN);
colorOffset.blue = readRegister(OFFSET_BLUE);
colorOffset.clear = readRegister(OFFSET_CLEAR);
// write number of capacitors to registers
writeRegister(colorCap.red & 0xF, CAP_RED);
writeRegister(colorCap.green & 0xF, CAP_GREEN);
writeRegister(colorCap.blue & 0xF, CAP_BLUE);
writeRegister(colorCap.clear & 0xF, CAP_CLEAR);
// write number of integration time slot to registers
writeInt(colorInt.red & 0xFFF, INT_RED_LO);
writeInt(colorInt.green & 0xFFF, INT_GREEN_LO);
writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO);
writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO);
}
// Read data regeisters and return a RGBC var
RGBC ADJDs311::read(){
RGBC color = RGBC();
performMeasurement();
color.red = readInt(DATA_RED_LO);
color.green = readInt(DATA_GREEN_LO);
color.blue = readInt(DATA_BLUE_LO);
color.clear = readInt(DATA_CLEAR_LO);
return color;
}
// get number of capacitor
RGBC ADJDs311::getColorCap()
{
return colorCap;
}
// get number of intetgration time slot
RGBC ADJDs311::getColorInt()
{
return colorInt;
}
// set number of capacitor
void ADJDs311::setColorCap(int red, int green, int blue, int clear) {
colorCap.red = red;
colorCap.green = green;
colorCap.blue = blue;
colorCap.clear = clear;
// write number of capacitors to registers
writeRegister(colorCap.red & 0xF, CAP_RED);
writeRegister(colorCap.green & 0xF, CAP_GREEN);
writeRegister(colorCap.blue & 0xF, CAP_BLUE);
writeRegister(colorCap.clear & 0xF, CAP_CLEAR);
}
// set number of integration time slot
void ADJDs311::setColorInt(int red, int green, int blue, int clear) {
colorInt.red = red;
colorInt.green = green;
colorInt.blue = blue;
colorInt.clear = clear;
// write number of integration time slot to registers
writeInt(colorInt.red & 0xFFF, INT_RED_LO);
writeInt(colorInt.green & 0xFFF, INT_GREEN_LO);
writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO);
writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO);
}
// Perform measurement and save the result to registers
void ADJDs311::performMeasurement(){
writeRegister(0x01, 0x00); // start sensing
while(readRegister(0x00) != 0)
; // waiting for a result
}
// Write a byte of data to a specific ADJD-S311 address
void ADJDs311::writeRegister(char data, char regAddr){
char temp[2];
temp[0] = regAddr; // register addresss
temp[1] = data;
_i2c.write(WRITE_ADDRESS, temp, 2, false);
}
// Read a byte of data from ADJD-S311 address
char ADJDs311::readRegister(char regAddr){
char data;
_i2c.write(WRITE_ADDRESS, &regAddr, 1, true);
_i2c.read(READ_ADDRESS, &data, 1, false);
return data;
}
// Read two bytes of data from ADJD-S311 address and addres+1
int ADJDs311::readInt(char loRegAddr)
{
return (unsigned char)readRegister(loRegAddr) + (((unsigned char)readRegister(loRegAddr+1))<<8);
}
// Write two bytes of data to ADJD-S311 address and addres+1
void ADJDs311::writeInt(int data, char loRegAddr)
{
char lobyte = data;
char hibyte = data >> 8;
writeRegister(lobyte, loRegAddr);
writeRegister(hibyte, loRegAddr+1);
}
/* calibrateClear() - This function calibrates the clear integration registers
of the ADJD-S311.
*/
void ADJDs311::calibrateClearInt(){
bool gainFound = false;
int upperBox=4096;
int lowerBox = 0;
int half;
while (!gainFound){
half = ((upperBox-lowerBox)/2)+lowerBox;
//no further halfing possbile
if (half==lowerBox){
gainFound=true;
}else{
colorInt.clear = half;
writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO);
performMeasurement();
int halfValue = readInt(DATA_CLEAR_LO);
if (halfValue>800){
upperBox=half;
}else if (halfValue<800){
lowerBox=half;
}else{
gainFound=true;
}
}
}
}
/* calibrateColor() - This function clalibrates the RG and B
integration registers.
*/
void ADJDs311::calibrateColorInt(){
bool gainFound = false;
int upperBox=4096;
int lowerBox = 0;
int half;
int halfValue;
while (!gainFound)
{
half = ((upperBox-lowerBox)/2)+lowerBox;
//no further halfing possbile
if (half==lowerBox)
{
gainFound=true;
}
else {
colorInt.red = half;
colorInt.green = half;
colorInt.blue = half;
// write number of integration time slot to registers
writeInt(colorInt.red & 0xFFF, INT_RED_LO);
writeInt(colorInt.green & 0xFFF, INT_GREEN_LO);
writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO);
performMeasurement();
halfValue = 0;
halfValue=std::max(halfValue, readInt(DATA_RED_LO));
halfValue=std::max(halfValue, readInt(DATA_GREEN_LO));
halfValue=std::max(halfValue, readInt(DATA_BLUE_LO));
if (halfValue>800) {
upperBox=half;
}
else if (halfValue<800) {
lowerBox=half;
}
else {
gainFound=true;
}
}
}
}
/* calibrateCapacitors() - This function calibrates each of the RGB and C
capacitor registers.
*/
void ADJDs311::calibrateCapacitors(){
bool calibrated = false;
//need to store detect better calibration
int diff;
int oldDiff = 1024;
while (!calibrated){
// sensor gain setting (Avago app note 5330)
// CAPs are 4bit (higher value will result in lower output)
writeRegister(colorCap.red & 0xF, CAP_RED);
writeRegister(colorCap.green & 0xF, CAP_GREEN);
writeRegister(colorCap.blue & 0xF, CAP_BLUE);
int maxRead = 0;
int minRead = 1024;
int red = 0;
int green = 0;
int blue = 0;
for (int i=0; i<4 ;i ++)
{
performMeasurement();
red += readInt(DATA_RED_LO);
green += readInt(DATA_GREEN_LO);
blue += readInt(DATA_BLUE_LO);
}
red /= 4;
green /= 4;
blue /= 4;
maxRead = std::max(maxRead, red);
maxRead = std::max(maxRead, green);
maxRead = std::max(maxRead, blue);
minRead = std::min(minRead, red);
minRead = std::min(minRead, green);
minRead = std::min(minRead, blue);
diff = maxRead - minRead;
if (oldDiff != diff)
{
if ((maxRead==red) && (colorCap.red<15))
colorCap.red++;
else if ((maxRead == green) && (colorCap.green<15))
colorCap.green++;
else if ((maxRead == blue) && (colorCap.blue<15))
colorCap.blue++;
}
else
calibrated = true;
oldDiff=diff;
}
}
void ADJDs311::calibrate(){
setColorCap(0, 0, 0, 8);
calibrateColorInt(); // This calibrates R, G, and B int registers
calibrateClearInt(); // This calibrates the C int registers
calibrateCapacitors(); // This calibrates the RGB, and C cap registers
calibrateColorInt();
}
void ADJDs311::ledMode(bool ledOn)
{
_led = ledOn;
}
void ADJDs311::offsetMode(bool useOffset)
{
if (useOffset)
{
writeRegister(0x01, CONFIG);
} else
{
writeRegister(0x00, CONFIG);
}
}
RGBC ADJDs311::getOffset()
{
return colorOffset;
}
RGBC ADJDs311::setOffset(bool useOffset)
{
_led = 0;
writeRegister(0x02, CTRL);
while(readRegister(CTRL));
colorOffset.red = readRegister(OFFSET_RED);
colorOffset.green = readRegister(OFFSET_GREEN);
colorOffset.blue = readRegister(OFFSET_BLUE);
colorOffset.clear = readRegister(OFFSET_CLEAR);
offsetMode(useOffset);
return colorOffset;
}
#ifndef ADJDs311_h
#define ADJDs311_h
//Includes
#include "mbed.h"
// ADJD-S311's I2C address, don't change
#define WRITE_ADDRESS 0xE8 // Address for write
#define READ_ADDRESS 0xE9 // Address for read
// ADJD-S311's register list
#define CTRL 0x00
#define CONFIG 0x01
#define CAP_RED 0x06
#define CAP_GREEN 0x07
#define CAP_BLUE 0x08
#define CAP_CLEAR 0x09
#define INT_RED_LO 0xA
#define INT_RED_HI 0xB
#define INT_GREEN_LO 0xC
#define INT_GREEN_HI 0xD
#define INT_BLUE_LO 0xE
#define INT_BLUE_HI 0xF
#define INT_CLEAR_LO 0x10
#define INT_CLEAR_HI 0x11
#define DATA_RED_LO 0x40
#define DATA_RED_HI 0x41
#define DATA_GREEN_LO 0x42
#define DATA_GREEN_HI 0x43
#define DATA_BLUE_LO 0x44
#define DATA_BLUE_HI 0x45
#define DATA_CLEAR_LO 0x46
#define DATA_CLEAR_HI 0x47
#define OFFSET_RED 0x48
#define OFFSET_GREEN 0x49
#define OFFSET_BLUE 0x4A
#define OFFSET_CLEAR 0x4B
/**
* A structure contain info about the red, green, blue and clear channel
*/
struct RGBC{
int red;
int blue;
int green;
int clear;
};
/**
* A ADJD-S311 color sensor class
*/
class ADJDs311{
public:
/**
* Create a color sensor interface
*
* @param sda Pin connected to sda of color sensor
* @param scl Pin connected to scl of color sensor
* @param led Pin connected to on board led of the sensor
*/
ADJDs311(PinName sda, PinName scl, PinName led);
/**
* Calibrate the capacitance and integration time slot so that the current
* readings are as close to 1000 as possible and the difference between RGB
* readings are as small as possible
*/
void calibrate();
/**
* Turn the on board LED on/off.
*
* @param ledOn Whether to turn the LED on.
*/
void ledMode(bool ledOn);
/**
* Get the current offset stored in offset registers
*
* @return Current offset stored in offset registers
*/
RGBC getOffset();
/**
* Use the current light condition to set the offset
*
* @param useOffset Wether to use the offset
* @return The offset set
*/
RGBC setOffset(bool useOffset = true);
/**
* Use the offset registers to automatically subtract offset from the readings
*
* @param useOffset Wether to use the offset
*/
void offsetMode(bool useOffset);
/**
* Read in the color value from the sensor
*
* @return Structure containing the value of red, green, blue and clear
*/
RGBC read();
/**
* Get the gain of number of capacitor for each channel, in the range of 0 to
* 15. Less capacitor will give higher sensitivity.
*
* @return Structure containing the gain of number of capacitor for each
* channel.
*/
RGBC getColorCap();
/**
* Get the gain of number of integration time slot, in the range of 0 to 4095.
* More integration time slot will give higher sensitivity.
*
* @return Structure containing the gain of number of integration time
* slot for each channel.
*/
RGBC getColorInt();
/**
* Set the gain of number of capacitor for each channel, in the range of 0 to
* 15. Less capacitor will give higher sensitivity.
*
* @param red gain value for red
* @param green gain value for green
* @param blue gain value for blue
* @param clear gain value for clear
*/
void setColorCap(int red, int green, int blue, int clear);
/**
* Set the gain of number of integration time slot, in the range of 0 to 4095.
* More integration time slot will give higher sensitivity.
*
* @param red gain value for red
* @param green gain value for green
* @param blue gain value for blue
* @param clear gain value for clear
*/
void setColorInt(int red, int green, int blue, int clear);
private:
// fields
I2C _i2c;
DigitalOut _led;
RGBC colorCap;
RGBC colorInt;
RGBC colorOffset;
// private memeber functions
/** Write a byte of data to ADJD-S311 register
*
* @param data byte data to write to the register
* @param regAddr address of the register to write
*/
void writeRegister(char data, char regAddr);
/** Read a byte of data from ADJD-S311 register
*
* @param regAddr address of the register to write
* @retrun byte data read from the register
*/
char readRegister(char regAddr);
/** Read 2 bytes of data from ADJD-S311 registers and return as an integer
*
* @param loRegAddr low register address
* @return value from registers as an int
*/
int readInt(char loRegAddr);
/** Write an integer data of 2 bytes to ADJD-S311 registers
*
* @param loRegAddr low register address
* @param data integer value to write
*/
void writeInt(int data, char loRegAddr);
/**
* Tell the color sensor to perform measurement and store data to the color and
* clear registers. Must be called before reading
* color values
*/
void performMeasurement();
/**
* Calibrate the clear integration time slot so that current reading of the
* clear channel will be as close to 1000 as possible
*/
void calibrateClearInt();
/**
* Calibrate the color integration time slots so that the max current reading
* of the RGB channels will be as close to 1000 as possible
*/
void calibrateColorInt();
/**
* Calibrate the color capacitors so the difference of reading of different
* channels are as small as possible
*/
void calibrateCapacitors();
};
#endif
\ No newline at end of file
################################################################################
# Makefile for XMC4500 RelaxKit using uCOS-III
# v1, 02/2018
# Martin Horauer, UAS Technikum Wien
#
# Supported: Windows, Linux, OSX
# Requirements:
# * GCC ARM https://launchpad.net/gcc-arm-embedded/+download
# * SEGGER JLINK https://www.segger.com/jlink-software.html
# * DOXYGEN http://www.stack.nl/~dimitri/doxygen/
################################################################################
# USAGE
# -----
# make .... build the program image
# make debug .... build the program image and invoke gdb
# make flash .... build an flash the application
# make erase .... erase the target device
# make doc .... run doxygen - output will be in > doc
# make clean .... remove intermediate and generated files
################################################################################
# define the name of the generated output file
#
TARGET = main
################################################################################
# below only edit with care
#
VENDOR = Infineon
################################################################################
# define the following symbol -D JLINK_RTT to enable JLINK_RTT tracing
# -D SEMI_HOSTING to enable