Skip to content

Commit 453c4f4

Browse files
authored
Merge pull request #10 from atomvm/i2c-improvements
I2c improvements
2 parents 302c77d + c6e730e commit 453c4f4

File tree

7 files changed

+98
-72
lines changed

7 files changed

+98
-72
lines changed

examples/bh1750_example/rebar.config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
{plugins, [
66
atomvm_rebar3_plugin
77
]}.
8+
{atomvm_rebar3_plugin, [
9+
{packbeam, [prune]}
10+
]}.

examples/bh1750_example/src/bh1750_example.erl

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ start() ->
3737
one_time_loop(BH) ->
3838
case bh1750:take_reading(BH) of
3939
{ok, Reading} ->
40-
io:format("Luminosity: ~slx\n", [to_string(Reading)]);
40+
io:format("Luminosity: ~slx\n", [Reading]);
4141
ErrorT ->
4242
io:format("Error taking reading temperature: ~p~n", [ErrorT])
4343
end,
@@ -47,9 +47,6 @@ one_time_loop(BH) ->
4747
continuous_loop(BH) ->
4848
receive
4949
Reading ->
50-
io:format("Luminosity: ~slx\n", [to_string(Reading)])
50+
io:format("Luminosity: ~p\n", [Reading])
5151
end,
5252
continuous_loop(BH).
53-
54-
to_string({Integral, {Fractional, _}}) ->
55-
io_lib:format("~p.~p", [Integral, Fractional]).

examples/bme280_example/rebar.config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
{plugins, [
66
atomvm_rebar3_plugin
77
]}.
8+
{atomvm_rebar3_plugin, [
9+
{packbeam, [prune]}
10+
]}.

examples/sht3x_example/rebar.config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
{plugins, [
66
atomvm_rebar3_plugin
77
]}.
8+
{atomvm_rebar3_plugin, [
9+
{packbeam, [prune]}
10+
]}.

src/bh1750.erl

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,24 @@
3131

3232
-behaviour(gen_server).
3333

34-
-export([start/1, start/2, stop/1, take_reading/1, reset/1]).
35-
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
34+
-export([
35+
start/1,
36+
start/2,
37+
start_link/1,
38+
start_link/2,
39+
stop/1,
40+
take_reading/1,
41+
reset/1
42+
]).
43+
44+
-export([
45+
init/1,
46+
handle_call/3,
47+
handle_cast/2,
48+
handle_info/2,
49+
terminate/2,
50+
code_change/3]
51+
).
3652

3753
% -define(TRACE_ENABLED, true).
3854
-include_lib("atomvm_lib/include/trace.hrl").
@@ -119,6 +135,47 @@ start(I2CBus, Options) ->
119135
E -> E
120136
end.
121137

138+
%%-----------------------------------------------------------------------------
139+
%% @param SDAPin pin number for I2C SDA channel
140+
%% @param SCLPin pin number for the I2C SCL channel
141+
%% @returns {ok, BH} on success, or {error, Reason}, on failure
142+
%% @equiv start_link(SDAPin, SCLPin, [])
143+
%% @doc Start the BH1750 driver.
144+
%% @end
145+
%%-----------------------------------------------------------------------------
146+
-spec start_link(I2CBus::i2c_bus:i2c_bus()) -> {ok, BH::bh()} | {error, Reason::term()}.
147+
start_link(I2CBus) ->
148+
start_link(I2CBus, []).
149+
150+
%%-----------------------------------------------------------------------------
151+
%% @param SDAPin pin number for I2C SDA channel
152+
%% @param SCLPin pin number for the I2C SCL channel
153+
%% @param Options additional driver options
154+
%% @returns {ok, BH} on success, or {error, Reason}, on failure
155+
%% @doc Start the BH1750 driver.
156+
%%
157+
%% This operation will start the BH driver. Use the returned reference
158+
%% in subsequent operations, such as for taking a reading.
159+
%%
160+
%% The Options parameter may be used to fine-tune behavior of the sensor,
161+
%% but the default values should be sufficient for weather-station based
162+
%% scenarios.
163+
%%
164+
%% Notes: The default oversampling rates for temperature, pressure, and humidity
165+
%% is `x4'. A sampling rate of `ignore' is not tested.
166+
%%
167+
%% The default `mode' is `forced'. Other modes are not tested.
168+
%% @end
169+
%%-----------------------------------------------------------------------------
170+
-spec start_link(I2CBus::i2c_bus:i2c_bus(), Options::options()) -> {ok, BH::bh()} | {error, Reason::term()}.
171+
start_link(I2CBus, Options) ->
172+
case gen_server:start_link(?MODULE, {I2CBus, maybe_add_self(Options)}, []) of
173+
{ok, Pid} = R ->
174+
maybe_start_continuous(Pid, Options),
175+
R;
176+
E -> E
177+
end.
178+
122179
%% @private
123180
maybe_add_self(Options) ->
124181
case proplists:get_value(mode, Options) of
@@ -324,23 +381,13 @@ do_take_reading(State) ->
324381
%% @private
325382
to_reading(Bin, Mode, MtReg) ->
326383
<<Reading:16/big-unsigned>> = Bin,
327-
X = multiply({1, {2, 10}}, {69, MtReg}),
384+
X = 1.2 * (69 / MtReg),
328385
Y = case Mode of
329386
high2 ->
330-
multiply(X, 2);
387+
X * 2;
331388
_ -> X
332389
end,
333-
divide(Reading, Y).
334-
335-
%% @private
336-
multiply(A, B) ->
337-
rational:simplify(rational:reduce(rational:multiply(A, B))).
338-
339-
%% @private
340-
divide(0, _B) ->
341-
{0, {0, 1}};
342-
divide(A, B) ->
343-
rational:to_decimal(rational:reduce(rational:divide(A, B)), 2).
390+
Reading / Y.
344391

345392
%% @private
346393
do_start_continuous_reading(State) ->
@@ -385,13 +432,8 @@ do_powerdown(State) ->
385432

386433
%% @private
387434
send_command(I2CBus, Address, Command) ->
388-
% ok = i2c_bus:begin_transmission(I2CBus, Address),
389-
% ok = i2c_bus:write_byte(I2CBus, Command),
390-
% ok = i2c_bus:end_transmission(I2CBus).
391435
?TRACE("sending command to bus ~p using address ~p command ~p ...", [I2CBus, Address, Command]),
392-
ok = i2c_bus:enqueue(I2CBus, Address, [
393-
fun(Port, _Address) -> ok = i2c:write_byte(Port, Command) end
394-
]).
436+
i2c_bus:write_bytes(I2CBus, Address, Command).
395437

396438
%% @private
397439
get_command(one_time, high) ->
@@ -410,22 +452,10 @@ get_command(continuous, low) ->
410452
%% @private
411453
get_sleep_ms(Resolution, MtReg) ->
412454
Base = get_sleep_ms(Resolution),
413-
Sleep = multiply(Base, divide(MtReg, 69)),
414-
round_sleep(Sleep).
455+
Sleep = Base * (MtReg / 69),
456+
erlang:round(Sleep).
415457

416458
%% @private
417459
get_sleep_ms(high) -> 120;
418460
get_sleep_ms(high2) -> 120;
419461
get_sleep_ms(low) -> 16.
420-
421-
%% @private
422-
round_sleep({I, {_N, _D} = F}) ->
423-
I + round_sleep(F);
424-
round_sleep({0, _D}) ->
425-
0;
426-
round_sleep({N, D}) ->
427-
case N > (D bsr 1) of
428-
true -> 1;
429-
_ -> 0
430-
end;
431-
round_sleep(I) when is_integer(I) -> I.

src/i2c_bus.erl

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
-define(DEFAULT_OPTIONS, #{freq_hz => 400000}).
4747

4848
-record(state, {
49-
port
49+
i2c
5050
}).
5151

5252
%%-----------------------------------------------------------------------------
@@ -137,39 +137,38 @@ read_bytes(Bus, Address, Register, Count) ->
137137

138138
%% @hidden
139139
init(Options) ->
140-
Port = i2c:open([
141-
{sda, maps:get(sda, Options)},
142-
{scl, maps:get(scl, Options)},
140+
I2C = i2c:open([
143141
{clock_speed_hz, maps:get(freq_hz, Options)}
142+
| maps:to_list(Options)
144143
]),
145-
?TRACE("Port opened. Options: ~p Port: ~p", [Options, Port]),
144+
?TRACE("I2C opened. Options: ~p I2C: ~p", [Options, I2C]),
146145
State = #state{
147-
port = Port
146+
i2c = I2C
148147
},
149148
{ok, State}.
150149

151150
%% @hidden
152151
handle_call({enqueue, Address, Operations}, _From, State) ->
153-
Reply = try_enqueue_operations(State#state.port, Address, Operations),
152+
Reply = try_enqueue_operations(State#state.i2c, Address, Operations),
154153
{reply, Reply, State};
155154
handle_call({write_bytes, Address, Bytes}, _From, State) ->
156-
?TRACE("Writing bytes ~p to address ~p i2c ~p", [Bytes, Address, State#state.port]),
157-
Reply = i2c:write_bytes(State#state.port, Address, Bytes),
155+
?TRACE("Writing bytes ~p to address ~p i2c ~p", [Bytes, Address, State#state.i2c]),
156+
Reply = i2c:write_bytes(State#state.i2c, Address, Bytes),
158157
?TRACE("Reply: ~p", [Reply]),
159158
{reply, Reply, State};
160159
handle_call({write_bytes, Address, Register, Bytes}, _From, State) ->
161-
?TRACE("Writing bytes ~p to address ~p register ~p i2c ~p", [Bytes, Address, Register, State#state.port]),
162-
Reply = i2c:write_bytes(State#state.port, Address, Register, Bytes),
160+
?TRACE("Writing bytes ~p to address ~p register ~p i2c ~p", [Bytes, Address, Register, State#state.i2c]),
161+
Reply = i2c:write_bytes(State#state.i2c, Address, Register, Bytes),
163162
?TRACE("Reply: ~p", [Reply]),
164163
{reply, Reply, State};
165164
handle_call({read_bytes, Address, Count}, _From, State) ->
166-
?TRACE("Reading bytes off address ~p count ~p i2c ~p", [Address, Count, State#state.port]),
167-
Reply = i2c:read_bytes(State#state.port, Address, Count),
165+
?TRACE("Reading bytes off address ~p count ~p i2c ~p", [Address, Count, State#state.i2c]),
166+
Reply = i2c:read_bytes(State#state.i2c, Address, Count),
168167
?TRACE("Reply: ~p", [Reply]),
169168
{reply, Reply, State};
170169
handle_call({read_bytes, Address, Register, Count}, _From, State) ->
171-
?TRACE("Reading bytes off address ~p register ~p count ~p i2c ~p", [Address, Register, Count, State#state.port]),
172-
Reply = i2c:read_bytes(State#state.port, Address, Register, Count),
170+
?TRACE("Reading bytes off address ~p register ~p count ~p i2c ~p", [Address, Register, Count, State#state.i2c]),
171+
Reply = i2c:read_bytes(State#state.i2c, Address, Register, Count),
173172
?TRACE("Reply: ~p", [Reply]),
174173
{reply, Reply, State};
175174
handle_call(Request, _From, State) ->
@@ -186,7 +185,7 @@ handle_info(_Info, State) ->
186185
%% @hidden
187186
terminate(_Reason, State) ->
188187
io:format("Closing I2C ... ~n"),
189-
i2c:close(State#state.port),
188+
i2c:close(State#state.i2c),
190189
ok.
191190

192191
%% @hidden
@@ -203,21 +202,23 @@ maybe_add_defaults(Options) ->
203202
maps:merge(?DEFAULT_OPTIONS, Options).
204203

205204
%% @private
206-
try_enqueue_operations(Port, Address, Operations) ->
207-
case i2c:begin_transmission(Port, Address) of
205+
try_enqueue_operations(I2C, Address, Operations) ->
206+
?TRACE("Enqueing on I2C ~p at address ~p", [I2C, Address]),
207+
case i2c:begin_transmission(I2C, Address) of
208208
ok ->
209209
try
210210
lists:foreach(
211211
fun(Operation) ->
212-
Operation(Port, Address)
212+
?TRACE("Executing on I2C ~p at address ~p", [I2C, Address]),
213+
Operation(I2C, Address)
213214
end,
214215
Operations
215216
)
216217
catch
217218
_:E ->
218219
{error, E}
219220
after
220-
i2c:end_transmission(Port)
221+
i2c:end_transmission(I2C)
221222
end;
222223
E ->
223224
{error, E}

src/sht3x.erl

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,18 +248,7 @@ do_take_reading(State) ->
248248
%%
249249
{MSB, LSB} = create_measurement_command(State#state.options),
250250
?TRACE("measurement_command: ~p", [{MSB, LSB}]),
251-
ok = i2c_bus:enqueue(
252-
I2CBus, ?SHT31_BASE_ADDR, [
253-
fun(Port, _Address) ->
254-
?TRACE("writing ~p", [MSB]),
255-
ok = i2c:write_byte(Port, MSB)
256-
end,
257-
fun(Port, _Address) ->
258-
?TRACE("writing ~p", [LSB]),
259-
ok = i2c:write_byte(Port, LSB)
260-
end
261-
]
262-
),
251+
ok = i2c_bus:write_bytes(I2CBus, ?SHT31_BASE_ADDR, <<MSB:8, LSB:8>>),
263252
timer:sleep(20),
264253
%%
265254
%% Read the data in memory.

0 commit comments

Comments
 (0)