The code is developed for the hardware NUCLEO-L432KC or any other board with SPI communication and the Digilent Pmod ALS1 ambient light sensor module. The purpose is to make students to understand the development process. They need to study the original analog to digital converter documentation to understand how the converter 16 bit output is converted to an illuminance value.
main.cpp@1:d1f1c7d9fbba, 2022-01-09 (annotated)
- Committer:
- timo_k2
- Date:
- Sun Jan 09 19:55:59 2022 +0000
- Revision:
- 1:d1f1c7d9fbba
- Parent:
- 0:f8565ce9a7ca
2 MHz SPI clock frequency for the ADC chip.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
timo_k2 | 0:f8565ce9a7ca | 1 | /* mbed Microcontroller Library |
timo_k2 | 0:f8565ce9a7ca | 2 | * Copyright (c) 2019 ARM Limited |
timo_k2 | 0:f8565ce9a7ca | 3 | * SPDX-License-Identifier: Apache-2.0 |
timo_k2 | 0:f8565ce9a7ca | 4 | ************************************************************************ |
timo_k2 | 0:f8565ce9a7ca | 5 | * |
timo_k2 | 0:f8565ce9a7ca | 6 | * Test of the Pmod ambient light sensor |
timo_k2 | 0:f8565ce9a7ca | 7 | * |
timo_k2 | 0:f8565ce9a7ca | 8 | ************************************************************************* |
timo_k2 | 0:f8565ce9a7ca | 9 | * Description: McLab13_Sensor_SPI_PmodALS_OS6 |
timo_k2 | 0:f8565ce9a7ca | 10 | * The ambient light value will be read and converted to LUX. |
timo_k2 | 0:f8565ce9a7ca | 11 | * |
timo_k2 | 0:f8565ce9a7ca | 12 | * Material |
timo_k2 | 0:f8565ce9a7ca | 13 | * 1. ST NUCLEO L432KC or NXP FRDM-K64F |
timo_k2 | 0:f8565ce9a7ca | 14 | * or some other micro controller board with SPI communication |
timo_k2 | 0:f8565ce9a7ca | 15 | * 2. Digilent Pmod ALS ambient light sensor |
timo_k2 | 0:f8565ce9a7ca | 16 | * Please connect L432KC or FRDM-K64F - PmodALS with lines: |
timo_k2 | 0:f8565ce9a7ca | 17 | * L432KC D13 - ALS 4 SCK hardware defined for the SPI |
timo_k2 | 0:f8565ce9a7ca | 18 | * L432KC D12 - ALS 3 MISO hardware defined for the SPI |
timo_k2 | 0:f8565ce9a7ca | 19 | * L432KC A6 - ALS 1 CS or any other free |
timo_k2 | 0:f8565ce9a7ca | 20 | * GND - ALS 5 GND |
timo_k2 | 0:f8565ce9a7ca | 21 | * Vcc - ALS 6 Vcc |
timo_k2 | 0:f8565ce9a7ca | 22 | |
timo_k2 | 0:f8565ce9a7ca | 23 | * ALS data on the SPI |
timo_k2 | 0:f8565ce9a7ca | 24 | * D15 ... D12 - four zeros |
timo_k2 | 0:f8565ce9a7ca | 25 | * D11 ... D04 - 8 bits of ambient light data |
timo_k2 | 0:f8565ce9a7ca | 26 | * D03 ... D00 - four zeros |
timo_k2 | 0:f8565ce9a7ca | 27 | * |
timo_k2 | 0:f8565ce9a7ca | 28 | * Details on the ADC IC on ALS board are given at |
timo_k2 | 0:f8565ce9a7ca | 29 | * http://www.ti.com/lit/ds/symlink/adc081s021.pdf |
timo_k2 | 0:f8565ce9a7ca | 30 | * The Pmod ALS |
timo_k2 | 0:f8565ce9a7ca | 31 | * https://reference.digilentinc.com/reference/pmod/pmodals/start |
timo_k2 | 0:f8565ce9a7ca | 32 | * |
timo_k2 | 0:f8565ce9a7ca | 33 | *************************************************************************** |
timo_k2 | 0:f8565ce9a7ca | 34 | * 3. Option A for task 2: Photo Diode BPW34 and amplifier circuit on HAMK McBoard. |
timo_k2 | 0:f8565ce9a7ca | 35 | * 3. Option B for task 2: Photo Diode BPW34, OpAmp TLC721, 330k, 12 pF. Detailed |
timo_k2 | 0:f8565ce9a7ca | 36 | * circuit diagram in the instruction sheet. |
timo_k2 | 0:f8565ce9a7ca | 37 | * |
timo_k2 | 0:f8565ce9a7ca | 38 | * Timo Karppinen 16.04.2021 copyright Apache-2.0 |
timo_k2 | 0:f8565ce9a7ca | 39 | *************************************************************************/ |
timo_k2 | 0:f8565ce9a7ca | 40 | #include "mbed.h" |
timo_k2 | 0:f8565ce9a7ca | 41 | |
timo_k2 | 0:f8565ce9a7ca | 42 | DigitalOut LED(D2); // LD1 to LD4 pin names are linked to D13 in L432KC. |
timo_k2 | 0:f8565ce9a7ca | 43 | // The L432KC board "LD3" is connected the D13. Do not use! It is the SPI SCK. |
timo_k2 | 0:f8565ce9a7ca | 44 | // PmodALS |
timo_k2 | 0:f8565ce9a7ca | 45 | SPI spi(D11, D12, D13); // mosi, miso, sck |
timo_k2 | 0:f8565ce9a7ca | 46 | |
timo_k2 | 0:f8565ce9a7ca | 47 | DigitalOut alsCS(A6); // chip select for sensor SPI communication |
timo_k2 | 0:f8565ce9a7ca | 48 | //DigitalIn sw2(A2); // input from switch2 on the HAMK McBoard |
timo_k2 | 0:f8565ce9a7ca | 49 | // Any pin can be used with internal pull down |
timo_k2 | 0:f8565ce9a7ca | 50 | DigitalIn sw2(A2, PullDown); // works OK if nothing connected to this pin. |
timo_k2 | 0:f8565ce9a7ca | 51 | |
timo_k2 | 0:f8565ce9a7ca | 52 | int alsScaledI = 0; // 32 bit integer |
timo_k2 | 0:f8565ce9a7ca | 53 | int getALS(); // function for the Digilent PmodALS sensor |
timo_k2 | 0:f8565ce9a7ca | 54 | int getPhotoDiode(); // function for the photo diode circuit |
timo_k2 | 0:f8565ce9a7ca | 55 | |
timo_k2 | 0:f8565ce9a7ca | 56 | int main(){ |
timo_k2 | 0:f8565ce9a7ca | 57 | // SPI for the ALS |
timo_k2 | 0:f8565ce9a7ca | 58 | // Setup the spi for 8 bit data, high steady state clock, |
timo_k2 | 0:f8565ce9a7ca | 59 | // second edge capture, with a 12MHz clock rate |
timo_k2 | 0:f8565ce9a7ca | 60 | spi.format(8,0); |
timo_k2 | 1:d1f1c7d9fbba | 61 | spi.frequency(2000000); // 1 to 4 MHz recommend for the adc081s021 |
timo_k2 | 0:f8565ce9a7ca | 62 | // ready to wait the conversion start |
timo_k2 | 0:f8565ce9a7ca | 63 | alsCS.write(1); |
timo_k2 | 1:d1f1c7d9fbba | 64 | ThisThread::sleep_for(1ms); |
timo_k2 | 0:f8565ce9a7ca | 65 | |
timo_k2 | 0:f8565ce9a7ca | 66 | while (true) { |
timo_k2 | 0:f8565ce9a7ca | 67 | if(sw2.read() == 0){ |
timo_k2 | 0:f8565ce9a7ca | 68 | alsScaledI = getALS(); |
timo_k2 | 0:f8565ce9a7ca | 69 | } |
timo_k2 | 0:f8565ce9a7ca | 70 | else{ |
timo_k2 | 0:f8565ce9a7ca | 71 | alsScaledI = getPhotoDiode(); |
timo_k2 | 0:f8565ce9a7ca | 72 | } |
timo_k2 | 0:f8565ce9a7ca | 73 | |
timo_k2 | 0:f8565ce9a7ca | 74 | printf("Ambient light scaled to LUX = %0d\r\n",alsScaledI); |
timo_k2 | 0:f8565ce9a7ca | 75 | |
timo_k2 | 0:f8565ce9a7ca | 76 | if (alsScaledI > 100){ |
timo_k2 | 0:f8565ce9a7ca | 77 | LED.write(1); |
timo_k2 | 0:f8565ce9a7ca | 78 | printf("Light enough for working \n\n"); |
timo_k2 | 0:f8565ce9a7ca | 79 | } |
timo_k2 | 0:f8565ce9a7ca | 80 | else{ |
timo_k2 | 0:f8565ce9a7ca | 81 | LED.write(0); |
timo_k2 | 0:f8565ce9a7ca | 82 | printf("Too low light for working \n\n"); |
timo_k2 | 0:f8565ce9a7ca | 83 | } |
timo_k2 | 0:f8565ce9a7ca | 84 | |
timo_k2 | 0:f8565ce9a7ca | 85 | ThisThread::sleep_for(3000ms); |
timo_k2 | 0:f8565ce9a7ca | 86 | } |
timo_k2 | 0:f8565ce9a7ca | 87 | } |
timo_k2 | 0:f8565ce9a7ca | 88 | |
timo_k2 | 0:f8565ce9a7ca | 89 | int getALS(){ |
timo_k2 | 0:f8565ce9a7ca | 90 | char alsByte0 = 0; //8bit data from sensor board, char is the unsigned 8bit |
timo_k2 | 0:f8565ce9a7ca | 91 | char alsByte1 = 0; // 8bit data from sensor board |
timo_k2 | 0:f8565ce9a7ca | 92 | char alsByteSh0 = 0; |
timo_k2 | 0:f8565ce9a7ca | 93 | char alsByteSh1 = 0; |
timo_k2 | 0:f8565ce9a7ca | 94 | char als8bit = 0; // unsigned 8 bit integer value |
timo_k2 | 0:f8565ce9a7ca | 95 | float alsScaledF = 0; // 32 bit floating point |
timo_k2 | 0:f8565ce9a7ca | 96 | |
timo_k2 | 0:f8565ce9a7ca | 97 | // Begin the conversion process and serial data output |
timo_k2 | 0:f8565ce9a7ca | 98 | alsCS.write(0); |
timo_k2 | 1:d1f1c7d9fbba | 99 | ThisThread::sleep_for(1ms); |
timo_k2 | 0:f8565ce9a7ca | 100 | // Reading two 8bit bytes by writing two dymmy 8bit bytes |
timo_k2 | 0:f8565ce9a7ca | 101 | alsByte0 = spi.write(0x00); |
timo_k2 | 0:f8565ce9a7ca | 102 | alsByte1 = spi.write(0x00); |
timo_k2 | 0:f8565ce9a7ca | 103 | // End of serial data output and back to tracking mode |
timo_k2 | 0:f8565ce9a7ca | 104 | alsCS.write(1); |
timo_k2 | 1:d1f1c7d9fbba | 105 | ThisThread::sleep_for(1ms); |
timo_k2 | 0:f8565ce9a7ca | 106 | // Check the http://www.ti.com/lit/ds/symlink/adc081s021.pdf |
timo_k2 | 0:f8565ce9a7ca | 107 | // The data looks like 0000AAAA AAAA0000 on the alsByte0 alsByte1 |
timo_k2 | 0:f8565ce9a7ca | 108 | printf("alsByte0 alsByte1 in hexadecimal %X %X\r\n",alsByte0, alsByte1); |
timo_k2 | 0:f8565ce9a7ca | 109 | // shifting bits to get the number out |
timo_k2 | 0:f8565ce9a7ca | 110 | alsByteSh0 = alsByte0 << 4; |
timo_k2 | 0:f8565ce9a7ca | 111 | alsByteSh1 = alsByte1 >> 4; |
timo_k2 | 0:f8565ce9a7ca | 112 | |
timo_k2 | 0:f8565ce9a7ca | 113 | als8bit =( alsByteSh0 | alsByteSh1 ); |
timo_k2 | 0:f8565ce9a7ca | 114 | alsScaledF = (float(als8bit))*(float(6.68)); |
timo_k2 | 0:f8565ce9a7ca | 115 | // The value 6.68 is 64 bit double precision floating point of type double. |
timo_k2 | 0:f8565ce9a7ca | 116 | // Conversions to 32 bit floating point of type float. |
timo_k2 | 0:f8565ce9a7ca | 117 | |
timo_k2 | 0:f8565ce9a7ca | 118 | printf("Ambient light ALS sensor 8 bit 0...255 = '%d' \r\n",als8bit); |
timo_k2 | 0:f8565ce9a7ca | 119 | //printf("Ambient light scaled to LUX = '%0.1f' \r\n",alsScaledF); |
timo_k2 | 0:f8565ce9a7ca | 120 | //Sorry, no more float printing in OS6 ! |
timo_k2 | 0:f8565ce9a7ca | 121 | // But if you really need the floating point printing: |
timo_k2 | 0:f8565ce9a7ca | 122 | // https://forums.mbed.com/t/hitchhikers-guide-to-printf-in-mbed-6/12492 |
timo_k2 | 0:f8565ce9a7ca | 123 | return (int)alsScaledF; |
timo_k2 | 0:f8565ce9a7ca | 124 | } |
timo_k2 | 0:f8565ce9a7ca | 125 | |
timo_k2 | 0:f8565ce9a7ca | 126 | int getPhotoDiode() { |
timo_k2 | 0:f8565ce9a7ca | 127 | // The function for reading the analog input value from |
timo_k2 | 0:f8565ce9a7ca | 128 | // the Photo Diode amplifier and scaling it to Lux value. |
timo_k2 | 0:f8565ce9a7ca | 129 | AnalogIn ainPD(A0); |
timo_k2 | 0:f8565ce9a7ca | 130 | unsigned short pd12bit = 0; |
timo_k2 | 0:f8565ce9a7ca | 131 | float pdScaledF = 0.0; |
timo_k2 | 0:f8565ce9a7ca | 132 | pd12bit = ainPD.read_u16() >>4; // leftmost 12 bits moved 4 bits to right. |
timo_k2 | 0:f8565ce9a7ca | 133 | printf("Ambient light PD sensor 12 bit 0...4095 = '%d' \r\n", pd12bit); |
timo_k2 | 0:f8565ce9a7ca | 134 | pdScaledF = (float(pd12bit))*(float(0.1)); |
timo_k2 | 0:f8565ce9a7ca | 135 | return (int)pdScaledF; |
timo_k2 | 0:f8565ce9a7ca | 136 | } |