目的:
WEB画面から raspberry pi に 接続した LED の PWM制御による 調光 を行う。
php から Cプログラム へ メッセージキュー を使用したプロセス間通信を使用する。
環境/構成:
環境/構成は、
WEB から LED ON/OFF
と同じ。
プロセス間通信については、WEB から LED ON/OFF ( php - C言語 間通信 ) を参照。
PWM制御については、C言語で LED 調光 (PWM 制御) を参照。
phpファイル(WEB画面):
WEB画面は、ESP32/arduino:LED調光_スライダーで明るさを調整
、2
と同じ画面。
<?php
$QKEY = 1111;
$QUEUE = msg_get_queue($QKEY, 0666);
session_start() ;
if ($_SESSION['led_val'] == NULL ) $_SESSION['led_val'] = 0 ;
if ($_GET['led_v'] != NULL) {
$_SESSION['led_val'] = $_GET['led_v'] ;
msg_send($QUEUE, "1111", "set_ledval " . $_SESSION['led_val'] . "\0" , FALSE) ;
}
if ($_GET['led_s'] != NULL) {
$_SESSION['led_val'] = $_GET['led_v'] ;
msg_send($QUEUE, "1111", "set_ledval " . $_SESSION['led_val'] . "\0" , FALSE) ;
}
if ($_GET['on'] == "ON") {
$_SESSION['led_val'] = "255" ;
msg_send($QUEUE, "1111", "led_on\0" , FALSE) ;
}
if ($_GET['off'] == "OFF") {
$_SESSION['led_val'] = "0" ;
msg_send($QUEUE, "1111", "led_off\0" , FALSE) ;
}
$led_brightness = $_SESSION['led_val'] ;
?>
<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>
<style>input.button {margin:8px;width:100px;}
input.button2 {margin-left:8px; width:40px;}
input.text {margin-left:8px; width:25px;}
input.slid {width:230px;}
div {font-size:16pt;text-align:center;width:250px;border:solid 4px #93ff93;}
</style>
<title>Color LED Controller</title></head>
<body>
<div><p>LED ON/OFF</p>
<form method='get' style='text-align:left' >
<span style='padding-left:15pt; font-size:8pt ;text-align:left'> LED brightness (0-255)</span>
<input class='text' type='text' name='led_v' id='led_v' value=<?=$led_brightness?> >
<input class='button2' type='submit' name='set' value='SET'>
</form>
<form name='slidform' method='get' style='text-align:left'>
<input class='slid' type='range' name='led_s' value=<?=$led_brightness?> min='0' max='255' step='1' onchange='setval(this.value)' oninput='setval(this.value)' >
</form>
<form method='get'>
<input class='button' type='submit' name='on' value='ON'><input class='button' type='submit' name='off' value='OFF'><br>
</form>
</div>
<script>
function setval(ledval){
var xhr = new XMLHttpRequest();
xhr.open('get', 'pwm_resp.php?slid='+ledval );
xhr.timeout = 1000 ;
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('If-Modified-Since', 'Thu, 01 Jun 1970 00:00:00 GMT');
xhr.responseType = 'document' ;
xhr.onreadystatechange = function() {
if( (xhr.readyState == 4) && (xhr.status == 200) ) {
document.getElementById('led_v').value = xhr.response.getElementById('output1').innerHTML;
}
}
xhr.ontimeout = function(e) {
xhr.abort() ;
}
xhr.send();
}
</script>
</body>
</html>
<?php $led_brightness = $_GET['slid'] ; $QKEY = 1111; $QUEUE = msg_get_queue($QKEY, 0666); msg_send($QUEUE, "1111", "set_slidval " . $led_brightness . "\0" , FALSE) ; ?> <!DOCTYPE html><html lang='ja'> <head> <title>Color LED Controller</title></head> <body> <output id='output1'> <?=$led_brightness?> </output> </body> </html>
処理の流れ:
- php 本体では、各 GET 要求を受けたとき、メッセージキューに LED 操作のコマンドを送信する。また、HTML 中の変数($led_brightness) に値を設定する。
- HTML中の変数($led_brightness) は、php のショートタグ( <?=*** ?> ) を使用して値に置き換える。
- スライダー操作時は、javascript で XHRを使用して 値を XHRレスポンス用 php に送信する。
- XHR レスポンス用 php では、送信された値を受け、メッセージキューに LED 操作のコマンドを送信し、受信した値をそのままレスポンスとして返す。ここでは、HTML(テキスト) でレスポンスを返している。
各処理の内容については、上述の参照ページを参照。
Cプログラム(LED調光):
Cプログラムは、
WEB から LED ON/OFF ( php - C言語 間通信 )
の LED ON, OFF を PWM制御 (
C言語で LED 調光 (PWM 制御)
) に置き換えたものとなる。
プログラムを以下に示す。
プログラムを以下に示す。
#include <wiringPi.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>
// *****************************************************************************
// * 定義等 *
// *****************************************************************************
// メッセージキュー 用 定義 ----------------------------------------------------
#define BUFFSIZE 256 // バッファサイズ
#define QKEY (key_t)1111 // メッセージキューの key
//
struct msgbuf{ // メッセージの構造体
long int type; // type は long int であること。
char data[BUFFSIZE]; //
}; //
//
// LED ON/OFF 用 定義 ----------------------------------------------------------
#define led_pin 12 // LED を接続する GPIO #
//
// *****************************************************************************
// * キーイベントの取得 *
// *****************************************************************************
//
int kbhit(void) { //
struct termios oldt, newt; //
int ch; //
int oldf; //
//
tcgetattr(STDIN_FILENO, &oldt); //
newt = oldt; //
newt.c_lflag &= ~(ICANON | ECHO); //
tcsetattr(STDIN_FILENO, TCSANOW, &newt); //
oldf = fcntl(STDIN_FILENO, F_GETFL, 0); //
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); //
//
ch = getchar(); //
//
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); //
fcntl(STDIN_FILENO, F_SETFL, oldf); //
//
if (ch != EOF) { //
ungetc(ch, stdin); //
return 1; //
} //
//
return 0; //
} //
//
// *****************************************************************************
// * メイン 関数 *
// *****************************************************************************
int main() { //
int msqid; // メッセージキュー ID
struct msgbuf message; // メッセージ
long int read_type = 0 ; // リードするメッセージタイプ
char c ; // 1文字入力用
char buf[128] ; // キーボード入力用のバッファ
int p_buf = 0 ; // 入力位置
char *cmd ; // コマンド用バッファ
char *prm1 ; // パラメータ1用バッファ
int val = 0 ; // 設定値
//
// メッセージキューの作成,取得 -----------------------------------------------
// 誰でも読み書き可能なキューを作成して、ID を取得する --
errno = 0; //
if( ( //
msqid = msgget(QKEY, 0666 | IPC_CREAT) // 0666:アクセス許可パラメータ
) == -1 ) { //
perror("msgget failure"); // 作成失敗時の処理
exit(EXIT_FAILURE); //
} //
//
// wiringpi の設定 -----------------------------------------------------------
wiringPiSetupGpio() ; //
pinMode (led_pin, PWM_OUTPUT) ; // LED 調光
pwmSetMode(PWM_MODE_MS) ; // PWM モード設定
pwmSetClock(40) ; // PWM 分周比設定(レンジ当たりのクロック数)
pwmSetRange(255) ; // PWM 分解能設定(1周期当たりのレンジ数)
//
// メッセージを受信して LED の ON/OFF を行う ---------------------------------
while(1){
errno = 0 ; //
if (!(msgrcv( msqid, &message, BUFFSIZE, // メッセージの受信
read_type, IPC_NOWAIT) == -1) //
) //
{ // メッセージ受信時の処理
// メッセージをコマンドとパラメータに分割 -//
cmd = strtok(message.data, " ") ; // 最初の文字列(" "まで) をコマンド
prm1 = strtok(NULL, " ") ; // 次の文字列を パラメータ1
printf("command : %s %s\n",cmd,prm1); // 表示
//
if (strcmp(cmd,"led_on") == 0) { // LED ON
pwmWrite(led_pin, 256) ; // LED 調光値設定(ON : 256)
} //
if (strcmp(cmd,"led_off") == 0) { // LED OFF
pwmWrite(led_pin, 0 ) ; // LED 調光値設定(OFF : 0)
} //
if (strcmp(cmd,"set_ledval") == 0) { // LED 調光値設定
val = atoi (prm1) ; // パラメータ1 を数値に変換
pwmWrite(led_pin, val) ; // LED 調光値設定
} //
if (strcmp(cmd,"set_slidval") == 0) { // LED スライダー値設定
val = atoi (prm1) ; // パラメータ1 を数値に変換
pwmWrite(led_pin, val) ; // LED 調光値設定
} //
}else{ // 受信失敗時
if (errno != ENOMSG) { // メッセージ無し以外は終了
printf("msgrcv : errno = %x\n",errno) ; //
break ; //
} //
} //
// キーイベントを取得し、入力文字列が "exit" ならループを終了する。----------
if (kbhit()) { //
c = getchar() ; // 入力された文字を表示
printf("%c",c) ; //
if ( c == '\n' ) { // リターン入力時
if ( strcmp(buf,"exit") == 0 ) { // "exit" を入力ならループ終了
break ; //
} else { // "exit" でなければ、先頭に戻る
p_buf = 0 ; //
buf[p_buf] = '\0' ; //
} //
} else { // リターンでなければ、
if (p_buf == 255) p_buf = 0 ; // バッファサイズを超える時は先頭へ
buf[p_buf] = c ; // バッファに入力文字を追加
buf[p_buf + 1] = '\0' ; //
p_buf++ ; // 入力位置を +1
} //
} //
} //
//
// メッセージキューを削除して終了 ----------------------------------------------
errno = 0; //
if(msgctl(msqid, IPC_RMID, NULL) == -1){ //
perror("msgctl failure"); //
exit(EXIT_FAILURE); //
} //
//
exit(EXIT_SUCCESS); //
//
} //
//
//
メッセージキューに送信されたコマンドに従い、LED の値 を設定する。
本プログラムを sudo 付きで実行し、WEB から 上述のphp(html) を開いて 操作すると、スライダーに応じて LED の明るさが変わる。
端末から "exit(rtn)" を入力すると プログラムは停止する。

0 件のコメント:
コメントを投稿