Raspberry Pi 2 Model B (以下RPi)
Raspbian Jessie
Python 2.7.9
処理予定と状況
- I2Cセンサーから測定値を読取る
- 組込みCでの実装予定
- Pythonでの動作チェックは完了
- GitHubにあったコードで確認
- ハードウェアは問題ない
GPIOのポート出力(OUT, IN)とレベル(High, Low)操作でのI2Cセンサー測定値の読取を実装する。
/dev/i2c-1
を使わずに/sys/class/gpio/
使用での実装とする。
(組込みでsoftware I2Cとして実装するため)。
こういう実装を作っておくことで、将来、別のセンサーの実装が必要な時に短時間で最終形(組込みC)の実装に到達するだろう。
参考
-
- echoを使った
/sys/class/gpio/
の書換え
- echoを使った
-
- Linuxの流儀でGPIOを監視する @ 電脳伝説さん
-
/sys/class/gpio/
のCでの制御
-
- マクロのみのI2C通信実装 (low level実装なし)
code v0.1 > GPIO24をHレベル出力
i2c_send_command_180227.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <stdbool.h>
#include <string.h>
/*
v0.1 Feb. 27, 2018
- test > set High for [GPIO_SCL]
- add gpio_setDirection()
- add gpio_setHigh()
- add gpio_setExport()
*/
#define GPIO_SDA (25) // Pin# 22
#define GPIO_SCL (24) // Pin# 18
void gpio_setExport(int index, bool bfOn)
{
int wfd;
static char zbuf[10];
if (bfOn) {
wfd = open("/sys/class/gpio/export", O_WRONLY);
} else {
wfd = open("/sys/class/gpio/unexport", O_WRONLY);
}
sprintf(zbuf, "%d", index);
write(wfd, zbuf, (int)strlen(zbuf));
close(wfd);
}
void gpio_setHigh(int index, bool bfTrue)
{
int wfd;
static char zbuf[30];
// 1234567890123456789012345678
// /sys/class/gpio/gpioxx/value
sprintf(zbuf, "/sys/class/gpio/gpio%d/value", index);
wfd = open(zbuf, O_WRONLY);
if (bfTrue) {
write(wfd, "1", 1);
} else {
write(wfd, "0", 1);
}
close(wfd);
}
void gpio_setDirection(int index, bool bfOut)
{
int wfd;
static char zbuf[33];
// 12345678901234567890123456789012
// /sys/class/gpio/gpioxx/direction
sprintf(zbuf, "/sys/class/gpio/gpio%d/direction", index);
wfd = open(zbuf, O_WRONLY);
if (bfOut) {
write(wfd, "out", 3);
} else {
write(wfd, "in", 2);
}
close(wfd);
}
int main(){
gpio_setExport(GPIO_SCL, /* bfOn=*/true);
gpio_setDirection(GPIO_SCL, /* bfOut=*/true);
gpio_setHigh(GPIO_SCL, /* bfTrue=*/true);
//gpio_setHigh(GPIO_SCL, /* bfTrue=*/false);
//gpio_setExport(GPIO_SDA, /* bfOn=*/false);
}
$ gcc i2c_send_command_180227.c -o i2c_send_command
$ sudo ./i2c_send_command
GPIO24のHレベルがassert状態になる。
v0.1では手じまいは手動で行うこと。
$ echo "24" > /sys/class/gpio/unexport
v0.1のコードはリソース消費の観点からは良くない。ポーティング前の実装まで済んだ段階で再考する予定。
link
code v0.2
(追記 2018/03/01)
i2c_send_command_180227.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <stdbool.h>
#include <string.h>
/*
v0.2 Mar. 01, 2018
- add s_zbuf[]
- add [GPIO_HIGH], [GPIO_LOW]
- refactor > change gpio_setHigh() to gpio_setLevel()
v0.1 Feb. 27, 2018
- test > set High for [GPIO_SCL]
- add gpio_setDirection()
- add gpio_setHigh()
- add gpio_setExport()
*/
#define GPIO_SDA (19) // Pin# 35
#define GPIO_SCL (26) // Pin# 37
#define GPIO_HIGH (true)
#define GPIO_LOW (false)
// 12345678901234567890123456789012
// /sys/class/gpio/gpioxx/direction
static char s_zbuf[40]; // buffer for sprintf()
void gpio_setExport(int index, bool bfOn)
{
int wfd;
if (bfOn) {
wfd = open("/sys/class/gpio/export", O_WRONLY);
} else {
wfd = open("/sys/class/gpio/unexport", O_WRONLY);
}
sprintf(s_zbuf, "%d", index);
write(wfd, s_zbuf, (int)strlen(s_zbuf));
close(wfd);
}
void gpio_setLevel(int index, bool bfHigh)
{
int wfd;
sprintf(s_zbuf, "/sys/class/gpio/gpio%d/value", index);
wfd = open(s_zbuf, O_WRONLY);
if (bfHigh) {
write(wfd, "1", 1);
} else {
write(wfd, "0", 1);
}
close(wfd);
}
void gpio_setDirection(int index, bool bfOut)
{
int wfd;
sprintf(s_zbuf, "/sys/class/gpio/gpio%d/direction", index);
wfd = open(s_zbuf, O_WRONLY);
if (bfOut) {
write(wfd, "out", 3);
} else {
write(wfd, "in", 2);
}
close(wfd);
}
int main(){
gpio_setExport(GPIO_SCL, /* bfOn=*/true);
gpio_setDirection(GPIO_SCL, /* bfOut=*/true);
gpio_setLevel(GPIO_SCL, GPIO_HIGH);
// delay() or some other delay function
gpio_setLevel(GPIO_SCL, GPIO_LOW);
// to unexport GPIO
//gpio_setExport(GPIO_SDA, /* bfOn=*/false);
return 0;
}