Current section
Files
Jump to
Current section
Files
src/pmod_als.erl
% @doc Digilent Pmod_ALS module
% This component provides ambient light-to-digital
% sensing through the SPI2 interface on a 6-pin connector.
%
% For further information about the Digilent Pmod_ALS
% and its components :
% https://store.digilentinc.com/pmod-als-ambient-light-sensor/
%
% Texas Instrument's ADC081S021 analog-to-digital converter
% http://www.ti.com/lit/ds/symlink/adc081s021.pdf
%
% Vishay Semiconductor's TEMT6000X01.
% http://www.vishay.com/docs/81579/temt6000.pdf
%
% Start the driver with
% ```
% 1> grisp:add_device(spi2, pmod_als).
% '''
% @end
-module(pmod_als).
-behaviour(gen_server).
-include("grisp.hrl").
% API
-export([start_link/2]).
-export([read/0]).
-export([percentage/0]).
% gen_server callbacks
-export([init/1]).
-export([handle_call/3]).
-export([handle_cast/2]).
-export([handle_info/2]).
-export([terminate/2]).
-export([code_change/3]).
%--- Macros --------------------------------------------------------------------
-define(SPI_MODE, #{clock => {high, trailing}}).
%--- Records -------------------------------------------------------------------
-record(state , {
% options = [],
bus
}).
%--- API -----------------------------------------------------------------------
% @private
start_link(Slot, _Opts) -> gen_server:start_link(?MODULE, Slot, []).
% @doc Returns the ambient light value that is currently sensed
% by the ALS module. On success, the return value is a number
% in the 0..255 range that is proportional to the luminous
% intensity.
%
% Technically, the values are representative of the
% power perceived by the phototransistor from the light source
% incoming at an angle of ±60°. It is a model of the response
% of the human eye to the same light source that is obtained
% by calculating the luminosity function.
%
% The peak wavelength sensitivity of the module is at 570nm
% making it close to the human eye (555nm). This implies that
% return values will be the highest when the ALS is exposed to
% wavelengths of green light with a slight yellow tint.
-spec read() -> 0..255 | no_return().
read() ->
Dev = grisp_devices:default(?MODULE),
case gen_server:call(Dev#device.pid, read) of
{error, Reason} -> error(Reason);
Result -> Result
end.
% @doc Returns a the percentage of current ambient light
% based on the {@link pmod_als:read/0} function. The value
% is rounded to the closest integer.
-spec percentage() -> 0..100.
percentage() ->
Raw = read(),
round((Raw / 255) * 100).
%--- Callbacks -----------------------------------------------------------------
% @private
init(Slot) ->
ok = grisp_devices:register(Slot, ?MODULE),
{ok, #state{bus = grisp_spi:open(Slot)}}.
% @private
handle_call(read, _From, #state{bus = Bus} = State) ->
Val = get_value(Bus),
{reply, Val, State};
handle_call(Request, _From, _State) -> error({unknown_call, Request}).
% @private
handle_cast(Request, _State) -> error({unknown_cast, Request}).
% @private
handle_info(Info, _State) -> error({unknown_info, Info}).
% @private
terminate(_Reason, _State) -> ok.
% @private
code_change(_OldVsn, State, _Extra) -> {ok , State}.
%--- Internal ------------------------------------------------------------------
get_value(Bus) ->
[<<_:3, Resp:8, _Pad:5>>] = grisp_spi:transfer(Bus, [
{?SPI_MODE, <<0:8>>, 0, 1}
]),
Resp.