Skip to content

Commit e500ac8

Browse files
LTR-303 driver (openshwprojects#1970)
* LTR-303 driver * Forgot discovery --------- Co-authored-by: openshwprojects <85486843+openshwprojects@users.noreply.github.com>
1 parent aeafcb0 commit e500ac8

File tree

10 files changed

+273
-0
lines changed

10 files changed

+273
-0
lines changed

platforms/obk_main.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ set(OBKM_SRC
124124
${OBK_SRCS}driver/drv_sm16703P.c
125125
${OBK_SRCS}driver/drv_simpleEEPROM.c
126126
${OBK_SRCS}driver/drv_leds_shared.c
127+
${OBK_SRCS}driver/drv_ltr_als.c
127128
${OBK_SRCS}driver/drv_spi.c
128129
${OBK_SRCS}driver/drv_spiLED.c
129130
${OBK_SRCS}driver/drv_spi_flash.c

platforms/obk_main.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ OBKM_SRC += $(OBK_SRCS)driver/drv_sm15155e.c
140140
OBKM_SRC += $(OBK_SRCS)driver/drv_sm16703P.c
141141
OBKM_SRC += $(OBK_SRCS)driver/drv_simpleEEPROM.c
142142
OBKM_SRC += $(OBK_SRCS)driver/drv_leds_shared.c
143+
OBKM_SRC += $(OBK_SRCS)driver/drv_ltr_als.c
143144
OBKM_SRC += $(OBK_SRCS)driver/drv_sm2135.c
144145
OBKM_SRC += $(OBK_SRCS)driver/drv_sm2235.c
145146
OBKM_SRC += $(OBK_SRCS)driver/drv_soft_i2c.c

src/driver/drv_local.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,7 @@ void Bridge_driver_DeInit();
287287
void Bridge_driver_QuickFrame();
288288
void Bridge_driver_OnChannelChanged(int ch, int value);
289289
/*************************************************************/
290+
291+
void LTR_Init();
292+
void LTR_OnEverySecond();
293+
void LTR_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState);

src/driver/drv_ltr_als.c

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
#include "../obk_config.h"
2+
3+
#if ENABLE_DRIVER_LTR_ALS
4+
5+
#include "../new_pins.h"
6+
#include "../logging/logging.h"
7+
#include "drv_local.h"
8+
#include "drv_ltr_als.h"
9+
10+
static softI2C_t g_softI2C;
11+
static bool is_init = false;
12+
13+
static int ch_lux = -1;
14+
15+
static uint16_t als_ch0 = 0;
16+
static uint16_t als_ch1 = 0;
17+
static float als_lux = 0.0f;
18+
19+
static byte sec_left = 0;
20+
static byte sec_cycle = 4;
21+
22+
static void LTR_WriteReg(byte reg, byte val)
23+
{
24+
Soft_I2C_Start(&g_softI2C, LTR_I2C_ADDR);
25+
Soft_I2C_WriteByte(&g_softI2C, reg);
26+
Soft_I2C_WriteByte(&g_softI2C, val);
27+
Soft_I2C_Stop(&g_softI2C);
28+
}
29+
30+
static byte LTR_Read8(byte reg)
31+
{
32+
byte v;
33+
Soft_I2C_Start(&g_softI2C, LTR_I2C_ADDR);
34+
Soft_I2C_WriteByte(&g_softI2C, reg);
35+
Soft_I2C_Stop(&g_softI2C);
36+
Soft_I2C_Start(&g_softI2C, LTR_I2C_ADDR | 1);
37+
v = Soft_I2C_ReadByte(&g_softI2C, true);
38+
Soft_I2C_Stop(&g_softI2C);
39+
return v;
40+
}
41+
42+
static void LTR_Reset()
43+
{
44+
LTR_WriteReg(LTR_REG_ALS_CONTR, 0x02);
45+
rtos_delay_milliseconds(10);
46+
}
47+
48+
static void LTR_Setup()
49+
{
50+
LTR_Reset();
51+
byte manufac = LTR_Read8(LTR_REG_MANUFAC_ID);
52+
if(manufac != 0x05)
53+
{
54+
// retry once
55+
manufac = LTR_Read8(LTR_REG_MANUFAC_ID);
56+
if(manufac != 0x05)
57+
{
58+
ADDLOG_ERROR(LOG_FEATURE_SENSOR, "LTR unknown manufacturer %i", manufac);
59+
is_init = false;
60+
return;
61+
}
62+
}
63+
LTR_WriteReg(LTR_REG_ALS_CONTR, 0x01);
64+
rtos_delay_milliseconds(20);
65+
// dummy read
66+
LTR_Read8(LTR_REG_STATUS);
67+
is_init = true;
68+
}
69+
70+
static void LTR_ReadData()
71+
{
72+
if(!(LTR_Read8(LTR_REG_STATUS) & 0x04)) return;
73+
74+
byte c1l = LTR_Read8(LTR_REG_CH1_0);
75+
byte c1h = LTR_Read8(LTR_REG_CH1_1);
76+
byte c0l = LTR_Read8(LTR_REG_CH0_0);
77+
byte c0h = LTR_Read8(LTR_REG_CH0_1);
78+
79+
als_ch1 = ((uint16_t)c1h << 8) | c1l;
80+
als_ch0 = ((uint16_t)c0h << 8) | c0l;
81+
}
82+
83+
static void LTR_CalcLux()
84+
{
85+
if(als_ch0 == 0 && als_ch1 == 0)
86+
{
87+
als_lux = 0;
88+
return;
89+
}
90+
91+
float r = (float)als_ch1 / (float)(als_ch0 + als_ch1);
92+
93+
if(r < 0.45f) als_lux = 1.7743f * als_ch0 + 1.1059f * als_ch1;
94+
else if(r < 0.64f) als_lux = 4.2785f * als_ch0 - 1.9548f * als_ch1;
95+
else if(r < 0.85f) als_lux = 0.5926f * als_ch0 + 0.1185f * als_ch1;
96+
else als_lux = 0.0f;
97+
}
98+
99+
static void LTR_Measure()
100+
{
101+
if(!is_init) return;
102+
103+
LTR_ReadData();
104+
LTR_CalcLux();
105+
106+
if(ch_lux >= 0) CHANNEL_Set(ch_lux, (int)(als_lux * 10), 0);
107+
}
108+
109+
commandResult_t LTR_ALS(const void* ctx, const char* cmd, const char* args, int flags)
110+
{
111+
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
112+
113+
if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 3)) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
114+
115+
int gain = Tokenizer_GetArgInteger(0);
116+
int integ = Tokenizer_GetArgInteger(1);
117+
int rep = Tokenizer_GetArgInteger(2);
118+
119+
LTR_WriteReg(LTR_REG_ALS_CONTR, 0x01 | (gain << 2));
120+
LTR_WriteReg(LTR_REG_MEAS_RATE, (rep & 0x07) | ((integ & 0x07) << 3));
121+
return CMD_RES_OK;
122+
}
123+
124+
commandResult_t LTR_INT(const void* ctx, const char* cmd, const char* args, int flags)
125+
{
126+
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
127+
128+
if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 4)) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
129+
130+
int en = Tokenizer_GetArgInteger(0);
131+
int low = Tokenizer_GetArgInteger(1);
132+
int high = Tokenizer_GetArgInteger(2);
133+
int persist = Tokenizer_GetArgInteger(3);
134+
135+
LTR_WriteReg(LTR_REG_ALS_THRES_LOW_0, low & 0xFF);
136+
LTR_WriteReg(LTR_REG_ALS_THRES_LOW_1, low >> 8);
137+
LTR_WriteReg(LTR_REG_ALS_THRES_UP_0, high & 0xFF);
138+
LTR_WriteReg(LTR_REG_ALS_THRES_UP_1, high >> 8);
139+
LTR_WriteReg(LTR_REG_INTERRUPT_PERSIST, persist & 0x0F);
140+
LTR_WriteReg(LTR_REG_INTERRUPT, en ? 0x02 : 0x00);
141+
142+
return CMD_RES_OK;
143+
}
144+
145+
commandResult_t LTR_Cycle(const void* ctx, const char* cmd, const char* args, int flags)
146+
{
147+
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
148+
149+
if(Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
150+
151+
int s = Tokenizer_GetArgInteger(0);
152+
if(s < 1) return CMD_RES_BAD_ARGUMENT;
153+
154+
sec_cycle = s;
155+
sec_left = s;
156+
return CMD_RES_OK;
157+
}
158+
159+
void LTR_Init()
160+
{
161+
g_softI2C.pin_clk = Tokenizer_GetPin(1, 9);
162+
g_softI2C.pin_data = Tokenizer_GetPin(2, 14);
163+
164+
ch_lux = Tokenizer_GetArgIntegerDefault(3, -1);
165+
166+
Soft_I2C_PreInit(&g_softI2C);
167+
rtos_delay_milliseconds(100);
168+
169+
LTR_Setup();
170+
171+
//cmddetail:{"name":"LTR_ALS","args":"[gain] [integration] [repeat]",
172+
//cmddetail:"descr":"ALS configuration. Gain mappings: 0-x1 1-x2 2-x4 3-x8 6-x48 7-x96. Integration mappings (ms): 0-100 1-50 2-200 3-400 4-150 5-250 6-300 7-350. Repeat mappings (ms): 0-50 1-100 2-200 3-500 4-1000 5-2000.",
173+
//cmddetail:"fn":"LTR_ALS","file":"driver/drv_ltr_als.c","requires":"",
174+
//cmddetail:"examples":LTR_ALS 3 0 3 <br /> gain 8x, integration 100ms, repeat 500ms"}
175+
CMD_RegisterCommand("LTR_ALS", LTR_ALS, NULL);
176+
//cmddetail:{"name":"LTR_INT","args":"[enable] [als_low] [als_high] [persistance]",
177+
//cmddetail:"descr":"Interrupt configuration. Enable = 0-1, persistance (oversampling) = 0-15. als_low/als_high - raw thresholds",
178+
//cmddetail:"fn":"LTR_INT","file":"driver/drv_ltr_als.c","requires":"",
179+
//cmddetail:"examples":"LTR_INT 1 200 2000 4 <br /> enable interrupt, when measurement is lower than 200 or higher than 2000 4 times"}
180+
CMD_RegisterCommand("LTR_INT", LTR_INT, NULL);
181+
//cmddetail:{"name":"LTR_Cycle","args":"[IntervalSeconds]",
182+
//cmddetail:"descr":"This is the interval between measurements in seconds, by default 1. Max is 255.",
183+
//cmddetail:"fn":"LTR_Cycle","file":"driver/drv_ltr_als.c","requires":"",
184+
//cmddetail:"examples":"LTR_Cycle 60 <br /> measurement is taken every 60 seconds"}
185+
CMD_RegisterCommand("LTR_Cycle", LTR_Cycle, NULL);
186+
}
187+
188+
void LTR_OnEverySecond()
189+
{
190+
if(sec_left-- <= 0)
191+
{
192+
LTR_Measure();
193+
sec_left = sec_cycle;
194+
}
195+
}
196+
197+
void LTR_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState)
198+
{
199+
if(bPreState)
200+
return;
201+
202+
if(!is_init) hprintf255(request, "<b>LTR sensor not detected</b>");
203+
else hprintf255(request, "<h2>LTR Lux=%.1f</h2>", als_lux);
204+
}
205+
206+
#endif

src/driver/drv_ltr_als.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#define LTR_I2C_ADDR (0x29 << 1)
2+
3+
#define LTR_REG_ALS_CONTR 0x80
4+
#define LTR_REG_PS_CONTR 0x81
5+
#define LTR_REG_PS_LED 0x82
6+
#define LTR_REG_PS_N_PULSES 0x83
7+
#define LTR_REG_PS_MEAS_RATE 0x84
8+
#define LTR_REG_MEAS_RATE 0x85
9+
#define LTR_REG_PART_ID 0x86
10+
#define LTR_REG_MANUFAC_ID 0x87
11+
#define LTR_REG_CH1_0 0x88
12+
#define LTR_REG_CH1_1 0x89
13+
#define LTR_REG_CH0_0 0x8A
14+
#define LTR_REG_CH0_1 0x8B
15+
#define LTR_REG_STATUS 0x8C
16+
#define LTR_REG_PS_DATA_0 0x8D
17+
#define LTR_REG_PS_DATA_1 0x8E
18+
#define LTR_REG_INTERRUPT 0x8F
19+
#define LTR_REG_PS_THRES_UP_0 0x90
20+
#define LTR_REG_PS_THRES_UP_1 0x91
21+
#define LTR_REG_PS_THRES_LOW_0 0x92
22+
#define LTR_REG_PS_THRES_LOW_1 0x93
23+
#define LTR_REG_ALS_THRES_UP_0 0x97
24+
#define LTR_REG_ALS_THRES_UP_1 0x98
25+
#define LTR_REG_ALS_THRES_LOW_0 0x99
26+
#define LTR_REG_ALS_THRES_LOW_1 0x9A
27+
#define LTR_REG_INTERRUPT_PERSIST 0x9E

src/driver/drv_main.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,22 @@ static driver_t g_drivers[] = {
14011401
NULL, // onHassDiscovery
14021402
false, // loaded
14031403
},
1404+
#endif
1405+
#if ENABLE_DRIVER_LTR_ALS
1406+
//drvdetail:{"name":"LTR_ALS",
1407+
//drvdetail:"title":"TODO",
1408+
//drvdetail:"descr":"LTR-303/329 ambient light sensor driver.",
1409+
//drvdetail:"requires":""}
1410+
{ "LTR_ALS", // Driver Name
1411+
LTR_Init, // Init
1412+
LTR_OnEverySecond, // onEverySecond
1413+
LTR_AppendInformationToHTTPIndexPage, // appendInformationToHTTPIndexPage
1414+
NULL, // runQuickTick
1415+
NULL, // stopFunction
1416+
NULL, // onChannelChanged
1417+
NULL, // onHassDiscovery
1418+
false, // loaded
1419+
},
14041420
#endif
14051421
//{ "", NULL, NULL, NULL, NULL, NULL, NULL, NULL, false },
14061422
};

src/httpserver/http_fns.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,6 +2386,11 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
23862386
dev_info = hass_createEnumChannelInfo(i);
23872387
}
23882388
break;
2389+
case ChType_Illuminance_div10:
2390+
{
2391+
dev_info = hass_init_sensor_device_info(ILLUMINANCE_SENSOR, i, 2, 1, 1);
2392+
}
2393+
break;
23892394
default:
23902395
{
23912396
int numOptions;

src/new_pins.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,7 @@ int ChannelType_GetDivider(int type) {
13841384
case ChType_Frequency_div10:
13851385
case ChType_ReadOnly_div10:
13861386
case ChType_Current_div10:
1387+
case ChType_Illuminance_div10:
13871388
return 10;
13881389
case ChType_Frequency_div100:
13891390
case ChType_Current_div100:
@@ -1453,6 +1454,7 @@ const char *ChannelType_GetUnit(int type) {
14531454
case ChType_ReactivePower:
14541455
return "vAr";
14551456
case ChType_Illuminance:
1457+
case ChType_Illuminance_div10:
14561458
return "Lux";
14571459
case ChType_Ph:
14581460
return "Ph";
@@ -1510,6 +1512,7 @@ const char *ChannelType_GetTitle(int type) {
15101512
case ChType_ReactivePower:
15111513
return "ReactivePower";
15121514
case ChType_Illuminance:
1515+
case ChType_Illuminance_div10:
15131516
return "Illuminance";
15141517
case ChType_Ph:
15151518
return "Ph Water Quality";
@@ -2422,6 +2425,7 @@ const char* g_channelTypeNames[] = {
24222425
"Enum",
24232426
"ReadOnlyEnum",
24242427
"Current_div10",
2428+
"Illuminance_div10",
24252429
"error",
24262430
"error",
24272431
"error",

src/new_pins.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,13 @@ typedef enum channelType_e {
11271127
//chandetail:"file":"new_pins.h",
11281128
//chandetail:"driver":""}
11291129
ChType_Current_div10,
1130+
//chandetail:{"name":"Illuminance_div10",
1131+
//chandetail:"title":"Illuminance_div10",
1132+
//chandetail:"descr":"Illuminance in Lux",
1133+
//chandetail:"enum":"ChType_Illuminance_div10",
1134+
//chandetail:"file":"new_pins.h",
1135+
//chandetail:"driver":""}
1136+
ChType_Illuminance_div10,
11301137
//chandetail:{"name":"Max",
11311138
//chandetail:"title":"TODO",
11321139
//chandetail:"descr":"This is the current total number of available channel types.",

src/obk_config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@
114114
#define ENABLE_DRIVER_NEO6M 1
115115
#define ENABLE_TIME_SUNRISE_SUNSET 1
116116
#define ENABLE_TIME_DST 1
117+
118+
#define ENABLE_DRIVER_LTR_ALS 1
117119
#define ENABLE_DRIVER_SM16703P 1
118120
#define ENABLE_DRIVER_PIXELANIM 1
119121

0 commit comments

Comments
 (0)