Raspberry PiでErlang使ってADコンバータでアナログ値取得してみた

  • 6
    Like
  • 0
    Comment
More than 1 year has passed since last update.

モチベーション

関数型言語ってどんなもの?と思い戦闘機本を勉強中
で、Rapberry Pi使って何か面白いことできないかなと考え中

Raspberry PiとErlangでアナログ値取得

手始めに講談社ブルーバックス「Raspberry Piで学ぶ電子工作」6章のSPI通信によるADコンバータを用いたアナログ値取得を、Erlangで書いてみた。
上記の本には電子回路(フォトレジスタ、ADコンバータ、LEDなど)の構成、Pythonのコードと、その説明が書かれているのでそれと照らし合わせていただければ。

print.erl
-module(print).
-compile(export_all).

-define(SPICLK, "11"). %% GPIOピン番号
-define(SPIMOSI, "10").
-define(SPIMISO, "9").
-define(SPICS, "8").
-define(LED, "25").

main() ->
 io:format("initializing...~n"),
 pi_gpio:set_pin_direction(?SPICLK, "out"),
 pi_gpio:set_pin_direction(?SPIMOSI, "out"),
 pi_gpio:set_pin_direction(?SPIMISO, "in"),
 pi_gpio:set_pin_direction(?SPICS, "out"),
 pi_gpio:set_pin_direction(?LED, "out"),
 mainloop().

mainloop() ->
 Val = readadc(0),
 io:format("~w~n", [Val]),
 case Val > 2500 of %% 取得値が一定値以上でLED点灯
  true -> pi_gpio:set_pin_value(?LED, "1");
  false -> pi_gpio:set_pin_value(?LED, "0")
 end,
 timer:sleep(500), 
 mainloop().

readadc(Adcnum) ->
 pi_gpio:set_pin_value(?SPICS, "1"),
 pi_gpio:set_pin_value(?SPICLK, "0"),
 pi_gpio:set_pin_value(?SPICS, "0"),
 ComOut = (Adcnum bor 16#18) bsl 3, %% スタートビット+シングルエンドビットとのor, 左3ビットシフト
 loop1(ComOut, 5), %% 5ビット送信
 Adcout = 0,
 loop2(Adcout, 13). %% 13ビット読み込み


loop1(ComO, 0) -> ok;

loop1(ComO, N) ->
 case ComO band 16#80 of %% 8ビット目が1?
  16#80 -> pi_gpio:set_pin_value(?SPIMOSI, "1");
  16#0 -> pi_gpio:set_pin_value(?SPIMOSI, "0")
 end,
 ComO1 = ComO bsl 1,
 %%io:format("loop1:clockpin:High,Low~n"),
 pi_gpio:set_pin_value(?SPICLK, "1"),
 pi_gpio:set_pin_value(?SPICLK, "0"),
 loop1(ComO1, N-1).


loop2(AdcO, 0) ->
 pi_gpio:set_pin_value(?SPICS, "1"),
 %%io:format("cspin:High~n"),
 AdcO;

loop2(AdcO, K) ->
 %%io:format("loop2:clockpin:High,Low~n"),
 pi_gpio:set_pin_value(?SPICLK, "1"),
 pi_gpio:set_pin_value(?SPICLK, "0"),
 AdcO1 = AdcO bsl 1,
 H = pi_gpio:get_pin_value(?SPIMISO), %% GPIO9番ピンから値を読み込む
 %%io:format("misopin value: ~w~n", [H]),
 case K < 13 andalso H =:= 1 of %% 値が1?
  true ->
   %%io:format("adcout bor 0x1~n"),
   AdcO2 = AdcO1 bor 16#1;
  false ->
   %%io:format("adcout bor 0x0~n"),
   AdcO2 = AdcO1
 end,
 loop2(AdcO2, K-1).

%% ctrl-g
%% i
%% c
%% pi_gpio:release_pin("11"),
%% pi_gpio:release_pin("10"),
%% pi_gpio:release_pin("9"),
%% pi_gpio:release_pin("8"),
%% pi_gpio:release_pin("25").

Raspberry PiへのErlangインストール、GPIO制御

Raspberry PiへのErlangのインストール、GPIO制御は下記を参照して、ちょっとだけ修正
Raspberry Pi and Erlang - Part1
Raspberry Pi and Erlang - Part2

pi_gpio
-module(pi_gpio).

-compile(export_all).

-define(GPIO_PATH, "/sys/class/gpio/").
-define(GPIO, "gpio").

reserve_pin(Pin) ->
   ExportFile = string:concat(?GPIO_PATH, "export"),
   file:write_file(ExportFile, Pin, [append]).

release_pin(Pin) ->
   UnexportFile = string:concat(?GPIO_PATH, "unexport"),
   file:write_file(UnexportFile, Pin, [append]).

set_pin_direction(Pin, Direction) ->
   reserve_pin(Pin),
   file:write_file(direction_file(Pin), Direction, [append]).

set_pin_value(Pin, Value) ->
   file:write_file(value_file(Pin), Value, [append]).

get_pin_value(Pin) ->
   {ok, Value} = file:read_file(value_file(Pin)),
   {H, _} = string:to_integer(binary_to_list(Value)),
   H.

direction_file(Pin) ->
   string:concat(pin_path(Pin), "direction").

value_file(Pin) ->
   string:concat(pin_path(Pin), "value").

pin_path(Pin) ->
   PinFolder = string:concat(string:concat(?GPIO, Pin), "/"),
   string:concat(?GPIO_PATH, PinFolder).

実行

構成は上記のブルーバックスを参照ください。

実行後、フォトレジスタに指を近づけて暗くすると、出力値が2500を切ってLEDが消灯、再び指を離すとLED点灯。。。