-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
max44009.c
104 lines (94 loc) · 2.81 KB
/
max44009.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//
// MAX44009 ambient light sensor
// prototyping code to enable the sensor and read the current value
//
// Written by Larry Bank - 11/30/2017
// Copyright (c) 2017 BitBank Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
static int file_i2c = 0;
//
// Opens a file system handle to the I2C device
// Sets the device into continuous sampling mode
// returns 0 for success, 1 for failure
//
int max44009Init(int iChannel, int iAddr)
{
int rc;
char filename[32];
unsigned char ucTemp[2];
sprintf(filename, "/dev/i2c-%d", iChannel);
if ((file_i2c = open(filename, O_RDWR)) < 0)
{
fprintf(stderr, "Failed to open the i2c bus; not running as root?\n");
file_i2c = 0;
return 1;
}
if (ioctl(file_i2c, I2C_SLAVE, iAddr) < 0)
{
fprintf(stderr, "Failed to acquire bus access or talk to slave\n");
file_i2c = 0;
return 1;
}
ucTemp[0] = 0x02; // configuration register
ucTemp[1] = 0x80; // continuous, automatic mode
rc = write(file_i2c, ucTemp, 2);
if (rc != 2)
{
printf("Error configuring sensor\n");
return 1;
}
return 0;
} /* max44009Init() */
//
// Read the ambient light value in Lux
//
float max44009ReadValue(void)
{
unsigned char ucTemp[4];
int i,rc;
int iMantissa, iExponent;
float fLux;
//
// We need to read registers 0x3 and 0x4 for the LUX value
// On most systems, a 2-byte read from 0x3 succeeds, but on RPI boards
// there is something wrong with their I2C hardware and it doesn't work
// so we split the operation into 2 separate reads
//
ucTemp[0] = 0x3; // start of data registers we want
rc = write(file_i2c, ucTemp, 1); // write address of register to read
i = read(file_i2c, &ucTemp[1], 1);
ucTemp[0] = 0x4; // read second byte
rc = write(file_i2c, ucTemp, 1);
i = read(file_i2c, &ucTemp[2], 1);
if (rc != 1 || i != 1)
{
return 0.0f; // something went wrong
}
iMantissa = ((ucTemp[1] & 0xf)<< 4); // upper bits of mantissa
iMantissa |= (ucTemp[2] & 0xf); // lower bits of mantissa
iExponent = ucTemp[1] >> 4;
iMantissa = (iMantissa << iExponent);
fLux = (float)iMantissa * 0.72f;
return fLux;
} /* max44009ReadValue() */