CN0397 (Smart Visible Light Detection)

Dependencies:   AD7798

Dependents:   cn0397-helloworld

For additional information check out the mbed page of the Analog Devices wiki: https://wiki.analog.com/resources/tools-software/mbed-drivers-all

Committer:
adisuciu
Date:
Tue Nov 08 09:56:25 2016 +0000
Revision:
1:77eb0888c15a
Parent:
0:61b289f9bab0
Fixed for mbed online compiler (array initialization not allowed within class declaration)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
adisuciu 0:61b289f9bab0 1 /**
adisuciu 0:61b289f9bab0 2 * @file CN0397.cpp
adisuciu 0:61b289f9bab0 3 * @brief Source file for the CN0397
adisuciu 0:61b289f9bab0 4 * @author Analog Devices Inc.
adisuciu 0:61b289f9bab0 5 *
adisuciu 0:61b289f9bab0 6 * For support please go to:
adisuciu 0:61b289f9bab0 7 * Github: https://github.com/analogdevicesinc/mbed-adi
adisuciu 0:61b289f9bab0 8 * Support: https://ez.analog.com/community/linux-device-drivers/microcontroller-no-os-drivers
adisuciu 0:61b289f9bab0 9 * Product: www.analog.com/EVAL-CN0397-ARDZ
adisuciu 0:61b289f9bab0 10 * More: https://wiki.analog.com/resources/tools-software/mbed-drivers-all
adisuciu 0:61b289f9bab0 11
adisuciu 0:61b289f9bab0 12 ********************************************************************************
adisuciu 0:61b289f9bab0 13 * Copyright 2016(c) Analog Devices, Inc.
adisuciu 0:61b289f9bab0 14 *
adisuciu 0:61b289f9bab0 15 * All rights reserved.
adisuciu 0:61b289f9bab0 16 *
adisuciu 0:61b289f9bab0 17 * Redistribution and use in source and binary forms, with or without
adisuciu 0:61b289f9bab0 18 * modification, are permitted provided that the following conditions are met:
adisuciu 0:61b289f9bab0 19 * - Redistributions of source code must retain the above copyright
adisuciu 0:61b289f9bab0 20 * notice, this list of conditions and the following disclaimer.
adisuciu 0:61b289f9bab0 21 * - Redistributions in binary form must reproduce the above copyright
adisuciu 0:61b289f9bab0 22 * notice, this list of conditions and the following disclaimer in
adisuciu 0:61b289f9bab0 23 * the documentation and/or other materials provided with the
adisuciu 0:61b289f9bab0 24 * distribution.
adisuciu 0:61b289f9bab0 25 * - Neither the name of Analog Devices, Inc. nor the names of its
adisuciu 0:61b289f9bab0 26 * contributors may be used to endorse or promote products derived
adisuciu 0:61b289f9bab0 27 * from this software without specific prior written permission.
adisuciu 0:61b289f9bab0 28 * - The use of this software may or may not infringe the patent rights
adisuciu 0:61b289f9bab0 29 * of one or more patent holders. This license does not release you
adisuciu 0:61b289f9bab0 30 * from the requirement that you obtain separate licenses from these
adisuciu 0:61b289f9bab0 31 * patent holders to use this software.
adisuciu 0:61b289f9bab0 32 * - Use of the software either in source or binary form, must be run
adisuciu 0:61b289f9bab0 33 * on or directly connected to an Analog Devices Inc. component.
adisuciu 0:61b289f9bab0 34 *
adisuciu 0:61b289f9bab0 35 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
adisuciu 0:61b289f9bab0 36 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
adisuciu 0:61b289f9bab0 37 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
adisuciu 0:61b289f9bab0 38 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
adisuciu 0:61b289f9bab0 39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
adisuciu 0:61b289f9bab0 40 * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
adisuciu 0:61b289f9bab0 41 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
adisuciu 0:61b289f9bab0 42 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
adisuciu 0:61b289f9bab0 43 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
adisuciu 0:61b289f9bab0 44 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
adisuciu 0:61b289f9bab0 45 *
adisuciu 0:61b289f9bab0 46 ********************************************************************************/
adisuciu 0:61b289f9bab0 47
adisuciu 0:61b289f9bab0 48 #include "CN0397.h"
adisuciu 0:61b289f9bab0 49 #include "AD7798.h"
adisuciu 0:61b289f9bab0 50 #include "Timer.h"
adisuciu 0:61b289f9bab0 51 #include <stdio.h>
adisuciu 0:61b289f9bab0 52 #include <math.h>
adisuciu 0:61b289f9bab0 53 #include <mbed.h>
adisuciu 0:61b289f9bab0 54
adisuciu 0:61b289f9bab0 55 extern Serial pc;
adisuciu 0:61b289f9bab0 56
adisuciu 0:61b289f9bab0 57
adisuciu 0:61b289f9bab0 58 void flush_serial()
adisuciu 0:61b289f9bab0 59 {
adisuciu 0:61b289f9bab0 60 wait_ms(10); // wait for all data to come through
adisuciu 0:61b289f9bab0 61 while (pc.readable()) pc.getc();
adisuciu 0:61b289f9bab0 62 }
adisuciu 0:61b289f9bab0 63
adisuciu 1:77eb0888c15a 64 const uint8_t CN0397::Channels[3] = { 1, 0, 2};
adisuciu 1:77eb0888c15a 65 const char CN0397::colour[3][6] = { "RED", "GREEN", "BLUE" };
adisuciu 1:77eb0888c15a 66 const uint8_t CN0397::ColorPrint[3] = { 31, 32, 34 };
adisuciu 1:77eb0888c15a 67 const uint8_t CN0397::Gain[8] = { 1, 2, 4, 8, 16, 32, 64, 128};
adisuciu 1:77eb0888c15a 68 const float CN0397::Lux_LSB[3] = {2.122, 2.124, 2.113};
adisuciu 1:77eb0888c15a 69 const float CN0397::Optimal_Levels[3] = {26909.0, 8880.0, 26909.0};
adisuciu 0:61b289f9bab0 70
adisuciu 0:61b289f9bab0 71 CN0397::CN0397(PinName cs) : ad7798(cs)
adisuciu 1:77eb0888c15a 72 {
adisuciu 0:61b289f9bab0 73 }
adisuciu 0:61b289f9bab0 74 void CN0397::display_data(void)
adisuciu 0:61b289f9bab0 75 {
adisuciu 0:61b289f9bab0 76
adisuciu 0:61b289f9bab0 77 uint8_t channel = 0, i;
adisuciu 0:61b289f9bab0 78
adisuciu 0:61b289f9bab0 79 /* for(channel = 0; channel < CHANNELS; channel++){
adisuciu 0:61b289f9bab0 80
adisuciu 0:61b289f9bab0 81 pc.printf("%s (channel %d):\n", colour[channel], (channel + 1));
adisuciu 0:61b289f9bab0 82 pc.printf("\tADC output = %u (%#06x)\n", adcValue[channel], adcValue[channel]);
adisuciu 0:61b289f9bab0 83 pc.printf("\tVoltage = %f mV\n", voltageValue[channel]);
adisuciu 0:61b289f9bab0 84 pc.printf("\tLight Intensity = %.2f lux\n", intensityValue[channel]);
adisuciu 0:61b289f9bab0 85 pc.printf("\tLight Concentration = %.2f%c\n", lightConcentration[channel], 37);
adisuciu 0:61b289f9bab0 86
adisuciu 0:61b289f9bab0 87 }*/
adisuciu 0:61b289f9bab0 88
adisuciu 0:61b289f9bab0 89
adisuciu 0:61b289f9bab0 90 for(channel = 0; channel < CHANNELS; channel++) {
adisuciu 0:61b289f9bab0 91
adisuciu 0:61b289f9bab0 92 pc.printf("\t\t\033[2;%dm%s\033[0m channel:\t\t", ColorPrint[channel], colour[channel]);
adisuciu 0:61b289f9bab0 93 }
adisuciu 0:61b289f9bab0 94
adisuciu 0:61b289f9bab0 95 pc.printf("\n");
adisuciu 0:61b289f9bab0 96 pc.printf("\t");
adisuciu 0:61b289f9bab0 97
adisuciu 0:61b289f9bab0 98 /*
adisuciu 0:61b289f9bab0 99 for(channel = 0; channel < CHANNELS; channel++) {
adisuciu 0:61b289f9bab0 100
adisuciu 0:61b289f9bab0 101 pc.printf("\t\t\tADC output = %u (%#06x)", adcValue[channel], adcValue[channel]);
adisuciu 0:61b289f9bab0 102 }
adisuciu 0:61b289f9bab0 103
adisuciu 0:61b289f9bab0 104 pc.printf("\n");
adisuciu 0:61b289f9bab0 105 pc.printf("\t");
adisuciu 0:61b289f9bab0 106
adisuciu 0:61b289f9bab0 107 */
adisuciu 0:61b289f9bab0 108 for(channel = 0; channel < CHANNELS; channel++) {
adisuciu 0:61b289f9bab0 109
adisuciu 0:61b289f9bab0 110 pc.printf("\t\tLight Intensity = %.2f lux", intensityValue[channel]);
adisuciu 0:61b289f9bab0 111 }
adisuciu 0:61b289f9bab0 112
adisuciu 0:61b289f9bab0 113 pc.printf("\n");
adisuciu 0:61b289f9bab0 114 pc.printf("\t");
adisuciu 0:61b289f9bab0 115
adisuciu 0:61b289f9bab0 116
adisuciu 0:61b289f9bab0 117 for(channel = 0; channel < CHANNELS; channel++) {
adisuciu 0:61b289f9bab0 118
adisuciu 0:61b289f9bab0 119 pc.printf("\t\tLight Concentration = %.2f%c", lightConcentration[channel], 37);
adisuciu 0:61b289f9bab0 120 }
adisuciu 0:61b289f9bab0 121
adisuciu 0:61b289f9bab0 122 pc.printf("\n");/*pc.printf("\t");
adisuciu 0:61b289f9bab0 123
adisuciu 0:61b289f9bab0 124 for(channel = 0; channel < CHANNELS; channel++) {
adisuciu 0:61b289f9bab0 125
adisuciu 0:61b289f9bab0 126 pc.printf("\t\t\tLight Concentration = %.2f%c", lightConcentration[channel], 37);
adisuciu 0:61b289f9bab0 127 }
adisuciu 0:61b289f9bab0 128
adisuciu 0:61b289f9bab0 129 pc.printf("\n");pc.printf("\t");
adisuciu 0:61b289f9bab0 130
adisuciu 0:61b289f9bab0 131 /* for(channel = 0; channel < CHANNELS; channel++){
adisuciu 0:61b289f9bab0 132
adisuciu 0:61b289f9bab0 133 pc.printf("\t\t\t\033[2;%dm|\033[0m\t", ColorPrint[channel]);
adisuciu 0:61b289f9bab0 134
adisuciu 0:61b289f9bab0 135 }*/
adisuciu 0:61b289f9bab0 136
adisuciu 0:61b289f9bab0 137 for(channel = 0; channel < 5; channel++) {
adisuciu 0:61b289f9bab0 138 pc.printf("\n");
adisuciu 0:61b289f9bab0 139 }
adisuciu 0:61b289f9bab0 140
adisuciu 0:61b289f9bab0 141 // pc.printf("\n");
adisuciu 0:61b289f9bab0 142 // pc.printf("\n");
adisuciu 0:61b289f9bab0 143 pc.printf("\n");
adisuciu 0:61b289f9bab0 144 }
adisuciu 0:61b289f9bab0 145
adisuciu 0:61b289f9bab0 146
adisuciu 0:61b289f9bab0 147 void CN0397::data_to_voltage(uint16_t adcValue, float *voltage)
adisuciu 0:61b289f9bab0 148 {
adisuciu 0:61b289f9bab0 149
adisuciu 0:61b289f9bab0 150 *voltage = (float)(adcValue * V_REF) / (float)(_2_16 * gainAdc);
adisuciu 0:61b289f9bab0 151
adisuciu 0:61b289f9bab0 152 }
adisuciu 0:61b289f9bab0 153
adisuciu 0:61b289f9bab0 154 void CN0397::init(void)
adisuciu 0:61b289f9bab0 155 {
adisuciu 0:61b289f9bab0 156 ad7798.reset();
adisuciu 0:61b289f9bab0 157 uint8_t channel;
adisuciu 0:61b289f9bab0 158
adisuciu 0:61b289f9bab0 159 if(ad7798.init()) {
adisuciu 0:61b289f9bab0 160
adisuciu 0:61b289f9bab0 161 ad7798.set_coding_mode(AD7798_UNIPOLAR);
adisuciu 0:61b289f9bab0 162 ad7798.set_mode(AD7798_MODE_SINGLE);
adisuciu 0:61b289f9bab0 163 ad7798.set_gain(ADC_GAIN);
adisuciu 0:61b289f9bab0 164 ad7798.set_filter(ADC_SPS);
adisuciu 0:61b289f9bab0 165 ad7798.set_reference(AD7798_REFDET_ENA);
adisuciu 0:61b289f9bab0 166
adisuciu 0:61b289f9bab0 167 }
adisuciu 0:61b289f9bab0 168
adisuciu 0:61b289f9bab0 169 gainAdc = Gain[ADC_GAIN];
adisuciu 0:61b289f9bab0 170 #ifdef USE_CALIBRATION
adisuciu 0:61b289f9bab0 171 pc.printf("Calibrate the system:\n");
adisuciu 0:61b289f9bab0 172 pc.printf("\n");
adisuciu 0:61b289f9bab0 173
adisuciu 0:61b289f9bab0 174 for(channel = 0; channel < CHANNELS; channel++) {
adisuciu 0:61b289f9bab0 175
adisuciu 0:61b289f9bab0 176 pc.printf("\tCalibrate channel %d: be sure that %s photodiode is cover and press <ENTER>.\n", (Channels[channel] + 1), colour[channel]);
adisuciu 0:61b289f9bab0 177 pc.getc();
adisuciu 0:61b289f9bab0 178 flush_serial();
adisuciu 0:61b289f9bab0 179 calibration(Channels[channel]);
adisuciu 0:61b289f9bab0 180 pc.printf("\t\tChannel %d is calibrated!\n", (Channels[channel] + 1));
adisuciu 0:61b289f9bab0 181 pc.printf("\n");
adisuciu 0:61b289f9bab0 182
adisuciu 0:61b289f9bab0 183 }
adisuciu 0:61b289f9bab0 184
adisuciu 0:61b289f9bab0 185 printf("System calibration complete!\n");
adisuciu 0:61b289f9bab0 186 printf("\n");
adisuciu 0:61b289f9bab0 187 printf("\n");
adisuciu 0:61b289f9bab0 188
adisuciu 0:61b289f9bab0 189 #endif
adisuciu 0:61b289f9bab0 190 }
adisuciu 0:61b289f9bab0 191
adisuciu 0:61b289f9bab0 192 void CN0397::calc_light_intensity(uint8_t channel, uint16_t adcValue, float *intensity)
adisuciu 0:61b289f9bab0 193 {
adisuciu 0:61b289f9bab0 194
adisuciu 0:61b289f9bab0 195 *intensity = adcValue * Lux_LSB[channel];
adisuciu 0:61b289f9bab0 196
adisuciu 0:61b289f9bab0 197 }
adisuciu 0:61b289f9bab0 198
adisuciu 0:61b289f9bab0 199 void CN0397::calc_light_concentration(uint8_t channel, float intensity, float *conc)
adisuciu 0:61b289f9bab0 200 {
adisuciu 0:61b289f9bab0 201
adisuciu 0:61b289f9bab0 202 *conc = (intensity * 100) / Optimal_Levels[channel];
adisuciu 0:61b289f9bab0 203
adisuciu 0:61b289f9bab0 204 }
adisuciu 0:61b289f9bab0 205
adisuciu 0:61b289f9bab0 206 void CN0397::set_app_data(void)
adisuciu 0:61b289f9bab0 207 {
adisuciu 0:61b289f9bab0 208 uint8_t channel, rgbChannel;
adisuciu 0:61b289f9bab0 209 uint16_t *adcData = &adcValue[0];
adisuciu 0:61b289f9bab0 210 float *voltageData = &voltageValue[0], *intensityData = &intensityValue[0];
adisuciu 0:61b289f9bab0 211 float *concData = &lightConcentration[0];
adisuciu 0:61b289f9bab0 212
adisuciu 0:61b289f9bab0 213 for(channel = 0; channel < CHANNELS; channel++) {
adisuciu 0:61b289f9bab0 214
adisuciu 0:61b289f9bab0 215 rgbChannel = Channels[channel];
adisuciu 0:61b289f9bab0 216
adisuciu 0:61b289f9bab0 217 ad7798.set_channel(channel);
adisuciu 0:61b289f9bab0 218
adisuciu 0:61b289f9bab0 219 adcData = &adcValue[rgbChannel];
adisuciu 0:61b289f9bab0 220 voltageData = &voltageValue[rgbChannel];
adisuciu 0:61b289f9bab0 221 intensityData = &intensityValue[rgbChannel];
adisuciu 0:61b289f9bab0 222 concData = &lightConcentration[rgbChannel];
adisuciu 0:61b289f9bab0 223 ad7798.read_data(channel, adcData);
adisuciu 0:61b289f9bab0 224 data_to_voltage(*adcData, voltageData);
adisuciu 0:61b289f9bab0 225 calc_light_intensity(rgbChannel, *adcData, intensityData);
adisuciu 0:61b289f9bab0 226 calc_light_concentration(rgbChannel, *intensityData, concData);
adisuciu 0:61b289f9bab0 227
adisuciu 0:61b289f9bab0 228 /* adcData++;
adisuciu 0:61b289f9bab0 229 voltageData++;
adisuciu 0:61b289f9bab0 230 intensityData++;
adisuciu 0:61b289f9bab0 231 concData++;*/
adisuciu 0:61b289f9bab0 232
adisuciu 0:61b289f9bab0 233 }
adisuciu 0:61b289f9bab0 234 }
adisuciu 0:61b289f9bab0 235
adisuciu 0:61b289f9bab0 236 void CN0397::calibration(uint8_t channel)
adisuciu 0:61b289f9bab0 237 {
adisuciu 0:61b289f9bab0 238
adisuciu 0:61b289f9bab0 239 uint16_t setValue;
adisuciu 0:61b289f9bab0 240
adisuciu 0:61b289f9bab0 241 ad7798.set_channel(channel); //select channel to calibrate
adisuciu 0:61b289f9bab0 242
adisuciu 0:61b289f9bab0 243 // Perform system zero-scale calibration
adisuciu 0:61b289f9bab0 244 setValue = ad7798.get_register_value(AD7798_REG_MODE, 2);
adisuciu 0:61b289f9bab0 245 setValue &= ~(AD7798_MODE_SEL(0x07));
adisuciu 0:61b289f9bab0 246 setValue |= AD7798_MODE_SEL(AD7798_MODE_CAL_SYS_ZERO);
adisuciu 0:61b289f9bab0 247 ad7798.set_register_value(AD7798_REG_MODE, setValue, 2);
adisuciu 0:61b289f9bab0 248
adisuciu 0:61b289f9bab0 249 while((ad7798.get_register_value( AD7798_REG_STAT, 1) & channel) != channel); // wait for RDY bit to go low
adisuciu 0:61b289f9bab0 250
adisuciu 0:61b289f9bab0 251 while(ad7798.get_register_value(AD7798_REG_MODE, 2) != 0x4005); // wait for ADC to go in idle mode
adisuciu 0:61b289f9bab0 252
adisuciu 0:61b289f9bab0 253
adisuciu 0:61b289f9bab0 254 }
adisuciu 0:61b289f9bab0 255
adisuciu 0:61b289f9bab0 256
adisuciu 0:61b289f9bab0 257
adisuciu 0:61b289f9bab0 258