2024年3月1日金曜日

Raspberry Pi ロボットカー WebIOPiブラウザ操作

 
2018年に製作したRaspberry Pi ロボットカーをスマホのWebブラウザからカメラ画像受信・走行操作について記事にしました。



同ブログ関連記事:【Raspberry Pi ロボットカー回路図






動画



スマホ画面

http://192.168.1.11:8000(個人環境)

パソコン・スマホのWebブラウザからカメラ画像表示と走行・移動式カメラコントロールボタン。

移動式カメラコントロールボタン
上[^^^] 下[vvv] 左[<<<] 右[>>>]





























■WebIOPi起動
sudo systemctl start webiopi

http://192.168.1.11:8000(個人環境)
ログイン ID : webiopi
パスワード :raspberry

■動画ストリーミングソフトウェアの起動
cd mjpg-streamer
sudo ./mjpg_streamer -i "./input_uvc.so -f 10 -r 320x240 -d /dev/video0 -y -n" -o "./output_http.so -w ./www -p 8080"

■WebIOPi停止
sudo systemctl stop webiopi


プログラム
WebIOPi サービスの設定の変更
sudo nano /etc/webiopi/config
#myscript = /home/pi/webiopi/examples/scripts/macros/script.py
myscript = /home/pi/webiopi/wcar4.py
#doc-root = /home/pi/webiopi/examples/scripts/macros
doc-root = /home/pi/webiopi/
#welcome-file = index.html
welcome-file = wcar4.html
pwm0 = PCA9685

wcar4.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import webiopi
from webiopi import deviceInstance

webiopi.setDebug()
GPIO = webiopi.GPIO
pwm0 = deviceInstance("pwm0")

v = -45
h = -45

pwm0.pwmWriteAngle(0,h )
pwm0.pwmWriteAngle(1,v)
        
class DCMotor:
    _pin1 = 0
    _pin2 = 0

    def __init__(self, pin1, pin2):
        self._pin1 = pin1
        self._pin2 = pin2
        GPIO.setFunction( self._pin1, GPIO.PWM )
        GPIO.setFunction( self._pin2, GPIO.PWM )

    def __del__(self):
        self.write(0.0) # stop

    def write(self, ratio):
        if 1.0 < ratio: # saturation
            ratio = 1.0
        if -1.0 > ratio:    # saturation
            ratio = -1.0
        if 0.01 > ratio and -0.01 < ratio:  # stop
            GPIO.pwmWrite(self._pin1, 0.0)
            GPIO.pwmWrite(self._pin2, 0.0)
        elif 0 < ratio: # Normal rotation
            GPIO.pwmWrite(self._pin1, ratio)
            GPIO.pwmWrite(self._pin2, 0.0)
        else:   # Reverse rotation
            GPIO.pwmWrite(self._pin1, 0.0)
            GPIO.pwmWrite(self._pin2, -ratio)

g_motorL = DCMotor( 5, 12)      # Left motor
g_motorR = DCMotor( 6, 13)  # Right motor

g_strMode = "0"     # Drive mode. GUI default mode = "0"(stop)
g_fRatio = int("5") * 0.05  # PWM Ratio. GUI default level = "5"

@webiopi.macro
def ChangeDriveMode( strMode ):
    webiopi.debug("ChangeDriveMode( %s )" % (strMode))
    global g_strMode
    g_strMode = strMode
    iMode = int(strMode)
    if 0 == iMode:
        webiopi.debug("Mode : Stop")
        g_motorL.write(0.0)
        g_motorR.write(0.0)
    elif 1 == iMode:
        webiopi.debug("Mode : Forward")
        g_motorL.write(g_fRatio)
        g_motorR.write(g_fRatio)
    elif 2 == iMode:
        webiopi.debug("Mode : Backward")
        g_motorL.write(-g_fRatio)
        g_motorR.write(-g_fRatio)
    elif 3 == iMode:
        webiopi.debug("Mode : CW")
        g_motorL.write( g_fRatio)
        g_motorR.write(-g_fRatio)
    elif 4 == iMode:
        webiopi.debug("Mode : CCW")
        g_motorL.write(-g_fRatio)
        g_motorR.write( g_fRatio)
    elif 5== iMode:     
        webiopi.debug("Mode : U")
        global v
        if v > -85:
            v -=  5
            pwm0.pwmWriteAngle(1, v)            
    elif 6 == iMode:
        webiopi.debug("Mode : D")
        global v
        if v <  0:
            v +=  5
            pwm0.pwmWriteAngle(1, v)                     
    elif 7== iMode:
        webiopi.debug("Mode : L")
        global h
        if h > -85:
            h -= 5
            pwm0.pwmWriteAngle(0, h)        
    elif 8 == iMode:
        webiopi.debug("Mode : R")
        global h
        if h < 0:
            h += 5
            pwm0.pwmWriteAngle(0,h)  
            
@webiopi.macro
def ChangeVoltageLevel( strLevel ):
    webiopi.debug("ChangeVoltageLevel( %s )" % (strLevel))
    global g_fRatio
    g_fRatio = int(strLevel) * 0.05
    # ratio = level * 0.05 : level=10 -> ratio=0.5 -> InputVoltage=2.5[V](When VM=5[V]).
    webiopi.debug("Ratio : %f" % (g_fRatio))
    ChangeDriveMode( g_strMode )



wcar4.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>tank controller</title>
<script type="text/javascript" src="/webiopi.js"></script>
<script type="text/javascript">
webiopi().ready( function()
{ // Initialize
drive( 0 );
vlevel( 5 );
} );

function drive(mode)
{ // Change drive mode. 0 : Stop, 1 : Forward, 2 : Backward, 3 : CW, 4 : CCW , 5 : U , 6 : D , 7 : L , 8 : R 
webiopi().callMacro( "ChangeDriveMode", mode );
}

function vlevel(level)
{ // Change Voltage Level.
webiopi().callMacro( "ChangeVoltageLevel", level);
}
</script>
</head>
<body>
<div align="center">
    <img src="http://192.168.1.11:8080/?action=stream" />
    <table border="1">
        <tbody>
            <tr>
<td align="center" width="100" height="100">
                <form><input type="button" value="^^^" onclick="drive(5)" data-role="none"></form>
                </td>                
                <td align="center" width="100" height="100">
                <form><input type="button" value="GoGo" onclick="drive(1)" data-role="none"></form>
                </td>               
                <td align="center" width="100" height="100">
                <form><input type="button" value="vvv" onclick="drive(6)" data-role="none"></form>
                </td>
            </tr>
            <tr>
                <td align="center" width="100" height="100">
                <form><input type="button" value="Left" onclick="drive(4)" data-role="none"></form>
                </td>
                <td align="center" width="100" height="100">
                <form><input type="button" value="Stop" onclick="drive(0)" data-role="none"></form>
                </td>
                <td align="center" width="100" height="100">
                <form><input type="button" value="Right" onclick="drive(3)" data-role="none"></form>
                </td>
            </tr>
            <tr><td align="center" width="100" height="100">
                <form><input type="button" value="<<<" onclick="drive(7)" data-role="none"></form>
                </td>                
                <td align="center" width="100" height="100">
                <form><input type="button" value="Back" onclick="drive(2)" data-role="none"></form>
                </td>               
                 <td align="center" width="100" height="100">
                <form><input type="button" value=">>>" onclick="drive(8)" data-role="none"></form>
                </td>
            </tr>
        </tbody>
    </table>
</div>
<p align="center">voltage level</p>
<div align="center">
<form>1 
<input type="radio" name="vl" onclick="vlevel(1)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(2)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(3)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(4)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(5)" data-role="none" checked> 
<input type="radio" name="vl" onclick="vlevel(6)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(7)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(8)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(9)" data-role="none"> 
<input type="radio" name="vl" onclick="vlevel(10)" data-role="none"> 
10</form>
</div>
</body>
</html


0 件のコメント:

コメントを投稿

Raspberry Pi Donkey Car スマートカー

  2020年に製作したDonkey Car スマートカー について記事にしました。 Donkey CarはRaspberry Pi のカメラからコースを ディープラーニングさせ自動走行を行います。(動画は白線上を自動走行)   動画