Skip to content

Instantly share code, notes, and snippets.

@ak1211

ak1211/irrec1.c

Created Jan 2, 2020
Embed
What would you like to do?
irrec プログラム(C言語とpigpioライブラリ)
/*
irremocon <https://github.com/ak1211/irremocon>
Copyright 2019 Akihiro Yamamoto
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
//
// use pigpio libraries. without pigpiod
// install libraries
// sudo apt-get install pigpio
//
// build
//
// $ gcc -Wall -pthread -o irrec1 irrec1.c -lpigpio -lrt
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <pigpio.h>
// 赤外線受信モジュール電源ピン(GPIO 24 / Physical 18)
const uint8_t GPIO_IRM_POWER_PIN = 24;
// 赤外線受信モジュール入力ピン(GPIO 25 / Physical 22)
const uint8_t GPIO_IRM_INPUT_PIN = 25;
// 赤外線受信モジュールは負論理信号
const int ASSERT_IR = 0;
const int NEGATE_IR = 1;
// キャリア周波数[kHz}
// 38kHz
const uint16_t CARRIER_FREQ_KHZ = 38;
// キャリア周期[us]
// 1/38,000 * 1,000,000 = 26us
const uint16_t CARRIER_PERIOD_MICROS = 1000 / CARRIER_FREQ_KHZ;
//
// ラズパイゼロではキャリア周期に同期できず
// タイミング違反が起きるので分周する
//
// プリスケーラの倍率
// 2分周
const uint16_t N_OF_PRESCALER = 2;
// 分周後でのクロックカウンタ増加量
const uint16_t COUNT_PACE = N_OF_PRESCALER;
// タイマー周期[us]
// キャリア周期 * プリスケーラの倍率
const uint16_t TIMER_INTERVAL_MICROS = CARRIER_PERIOD_MICROS * N_OF_PRESCALER;
// この時間信号が変化しないと, 赤外線リモコン信号を読み取るのを終了する
// 34ms
const uint16_t TIMEOUT_COUNTS = 34 * 1000 / TIMER_INTERVAL_MICROS;
//
//
//
ssize_t receive_ir_codes( uint16_t* buffer, size_t buffer_size )
{
assert( TIMEOUT_COUNTS <= buffer_size );
ssize_t ret_val = -1;
int tfd = timerfd_create( CLOCK_REALTIME, 0 );
struct itimerspec interval = {
.it_interval = { .tv_sec = 0, .tv_nsec = TIMER_INTERVAL_MICROS * 1000 },
.it_value = { .tv_sec = 0, .tv_nsec = 1000 }
};
timerfd_settime( tfd, 0, &interval, NULL );
// リモコン信号入力待ち
while (gpioRead(GPIO_IRM_INPUT_PIN) == NEGATE_IR) {
// タイマー待ち
uint64_t v;
if (read( tfd, &v, sizeof(uint64_t) ) < 0) {
goto exit;
}
}
// リモコン信号を検出したのでカウント開始
bool previous = false;
size_t buffer_counter = 0;
uint16_t count = 0;
while (count < TIMEOUT_COUNTS) {
if (previous == gpioRead(GPIO_IRM_INPUT_PIN)) {
// 信号が変化しないならカウンタを増やす
count += COUNT_PACE;
} else {
// 信号が変化したら
// カウント値をバッファに入れて
// カウンタを初期化
buffer[buffer_counter++] = count;
previous = !previous;
count = 0;
}
// タイマー待ち
uint64_t v;
if (read( tfd, &v, sizeof(uint64_t) ) < 0) {
goto exit;
}
}
// 最後のカウント値をバッファに入れる
buffer[buffer_counter++] = count;
ret_val = buffer_counter;
exit:
close(tfd);
return ret_val;
}
//
//
//
int main()
{
if (gpioInitialise() < 0) {
perror("");
return 0;
}
if (gpioSetMode(GPIO_IRM_POWER_PIN, PI_OUTPUT) != 0) {
perror("");
goto exit;
}
// 赤外線受信モジュールに電源を供給する。
if (gpioWrite(GPIO_IRM_POWER_PIN, 1) != 0) {
perror("");
goto exit;
}
fprintf( stderr, "irrec\n" );
fprintf( stderr, "This program is display infrared codes.\n" );
enum { IRCODES_SIZE = 1024 };
uint16_t ircodes[IRCODES_SIZE] = {0};
ssize_t count;
if ((count = receive_ir_codes(ircodes, IRCODES_SIZE)) < 0) {
perror("");
goto exit;
}
//
for( ssize_t c=0 ; c<count ; c++ ) {
int lo =ircodes[c] & 0x00ff;
int hi =ircodes[c] >> 8 & 0x00ff;
printf( "%02X%02X", lo, hi );
}
printf( "\n" );
// 赤外線受信モジュールの電源を切る
if (gpioWrite(GPIO_IRM_POWER_PIN, 0) != 0) {
perror("");
goto exit;
}
fprintf( stderr, "bye.\n");
exit:
gpioTerminate();
return 0;
}
@pr-body

This comment has been minimized.

Copy link

@pr-body pr-body commented Jan 2, 2020

hello!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.