ツインモーターギヤーボックス+ESP32+モータードライバーBD6222HFPで遠隔操作のリモコンカー
 
リモコンカー台座。タミヤのツインモーターギヤーボックスだと思う。
 
前の記事でカメラの向きを変える為の台座?みたいなものを作っておりましたが。

首を振るだけではつまらなくなり。
リモコンカー的なものを作ってみました。
ずっと前にモーターを回す実験をやった時のモータードライバーBD6222HFPが
ありましたので、これを使います。
あと、動力部にはタミヤ 楽しい工作シリーズ No.97
 ツインモーターギヤーボックス だと思う。
 
 これらとESPを組み合わせて作っていきます。
 
■接続構成
 ESP32---BD6222HFP---ツインモーターギヤーボックス
 となっており、
 ESPのWIFI接続でESP内にWEBサーバーを開いて、
 その画面から操作することで遠隔地からリモコンカーの操作が可能になるっていうやつ。
 
■モータードライバー
 


 
俺的解釈。
 FINとRINの入力によって前に回したり後ろに回したりする事ができる。
 Fがフロント、Rがリヤとかってに解釈。
 FにHighでRにLowにすると、前に進む
 RにHighでLにLowにすると、後ろに進む
 で、
 両方Lowでなにもしない。電源OFFになるので、回っている場合は惰性で回り続ける
 急に止まりたいときは、急ブレーキの特殊コマンドFR両方Highを与える。
 という所とみました。
 上記はa~dまでの動きでだいたい思ったことはできるのであと使わないけど。
 eから下はゆっくり走るとかできるんだと思います。
 
 
■回路
 
 
 
■プログラム
 上記の通り
 モータードライバーのコマンドが
  制御信号2本でできるので、そこのGPIOを制御するだけの簡単なものです。
 また、プログラムがblogで切られるので抜粋です
 全体は
  https://drive.google.com/file/d/16r5zl1-g-W9wNNi34aSM_K4LeMp21irX/view?usp=sharing
  

wait_sec = 0.1
wait_sec2 = 0.3
m1_1=Pin(16,Pin.OUT)
m1_2=Pin(17,Pin.OUT)
m2_1=Pin(18,Pin.OUT)
m2_2=Pin(19,Pin.OUT)

def motor_stop( ) :
    m1_1.value(1)
    m1_2.value(1)
    m2_1.value(1)
    m2_2.value(1)
    time.sleep(0.2)
    m1_1.value(0)
    m1_2.value(0)
    m2_1.value(0)
    m2_2.value(0)

motor_stop()

def zenshin(flag, conn):
    #モーター制御
    m1_1.value(1)
    m1_2.value(0)
    m2_1.value(1)
    m2_2.value(0)
    time.sleep(wait_sec2)
    motor_stop()
def koutai(flag, conn):
    #モーター制御
    m1_1.value(0)
    m1_2.value(1)
    m2_1.value(0)
    m2_2.value(1)
    time.sleep(wait_sec2)
    motor_stop()
    #
def hidari(flag, conn):
    #モーター制御
    m1_1.value(1)
    m1_2.value(0)
    m2_1.value(0)
    m2_2.value(1)
    time.sleep(wait_sec)
    motor_stop()
    #
def migi(flag, conn):
    #モーター制御
    m1_1.value(0)
    m1_2.value(1)
    m2_1.value(1)
    m2_2.value(0)
    time.sleep(wait_sec)
    motor_stop()
    #

 

■動いている様子

 

 

 

 

ステッピングモーターで遠隔地からカメラを左右に向ける
 
前の記事で昔々買っておいたステッピングモーターの記事を書きました。


この仕組みを使ってカメラの撮影方向を左右に変更できる装置を作ってみました。
 
■映像
 

■回路図

 

 

 

■WEB画面操作

 

左右に45°と細かく4°ぐらい旋回するボタンを付けました。

 

■プログラム

https://drive.google.com/file/d/1IofmumkqOpXvEN2CH41RIN7VR7gZVCr_/view?usp=sharing


#
#ステッピングモーターで台を左右に振る
#  ESP32 micro python system
#
#  ESP32---ULN2003制御ボード---28BYJステッピングモーター
#
# 接続
#  ESP32 ULN2003
#   25      1
#   26      2
#   27      3
#   13      4
#   5V      5V
#   GNS     GND
#
# 仕様
#  自動的にWIFI接続して
#  webサーバーを起動する
#  webサーバー画面のボタンを押すと
#  ステッピングモーターが回転する
#

 

途中省略

 


def migi(flag, conn):
    header_send200(conn)
    #conn.send('HTTP/1.1 200 OK¥n')
    #conn.send('Content-Type: text/html¥n')
    #conn.send('Connection: close¥n¥n')
    html_form = """
        <html>
        <head>
            <title>MigiHidariSys </title>
            <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
            <meta http-equiv="refresh" content="0;URL=/">
        </head>
        <body>
            <h1>MigiHidariSys ステータス</h1>
    """
    conn.send(html_form)
    conn.send("serialno:"+serialno+"<br>¥n")
    conn.send("<br>¥n")
    conn.send("MigiHidariSys:<br>¥n")
    conn.send("<blockquote>¥n")
    conn.send("右を向きました<br>¥n")
    conn.send("</blockquote>¥n")
    html_form = """
            メニュー<br>
            <blockquote>
                <a href="/">戻る</a><br>
            </blockquote>
        </body>
        </html>
    """
    conn.send(html_form)
    #
    LED_ON()
    # ステッピングモーター制御
    if flag == True:
        log(WRN, SV, "debug migi 1")
        my_motor.step(-288)
        log(WRN, SV, "debug migi 2")
    else :
        log(WRN, SV, "debug migi 3")
        my_motor.step(-25)
        log(WRN, SV, "debug migi 4")
    #
    LED_OFF()
    log(WRN, SV, "migi kaiten.")

def hidari(flag, conn):
    header_send200(conn)
    #conn.send('HTTP/1.1 200 OK¥n')
    #conn.send('Content-Type: text/html¥n')
    #conn.send('Connection: close¥n¥n')
    html_form = """
    <html>
    <head>
        <title>MigiHidariSys </title>
        <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
        <meta http-equiv="refresh" content="0;URL=/">
    </head>
    <body>
        <h1>MigiHidariSys ステータス</h1>
    """
    conn.send(html_form)
    conn.send("serialno:"+serialno+"<br>¥n")
    conn.send("<br>¥n")
    conn.send("MigiHidariSys:<br>¥n")
    conn.send("<blockquote>¥n")
    conn.send("左を向きました<br>¥n")
    conn.send("</blockquote>¥n")
    html_form = """
        メニュー<br>
        <blockquote>
            <a href="/">戻る</a><br>
        </blockquote>
    </body>
    </html>
    """
    conn.send(html_form)
    #
    LED_ON()
    # ステッピングモーター制御
    if flag == True:
        log(WRN, SV, "debug hidari 1")
        my_motor.step(267)
        log(WRN, SV, "debug hidari 2")
    else :
        log(WRN, SV, "debug hidari 3")
        my_motor.step(25)
        log(WRN, SV, "debug hidari 4")
    #
    LED_OFF()
    log(WRN, SV, "hidari kaiten.")
 

 

途中省略

 

#
#WEB画面
#
def s_Th():
    try :
        conn = ""
        log(INF, NO, "start s_Th()")
        
        global wifi_error_flag
        global senser_error_flag
        global network_error_flag
        
        global logBuffer
        
        #
        log(INF, NO, "s_Th socket.getaddrinfo()")
        addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
        #
        log(INF, NO, "s_Th socket.socket()")
        s = socket.socket()
        #
        log(INF, NO, "s_Th s.bind(addr)")
        s.bind(addr)
        #
        log(INF, NO, "s_Th s.listen(1)")
        s.listen(1)
        #
        log(INF, NO, "s_Th s.settimeout(600)")
        s.settimeout(600)    #acceptのタイムアウトを600秒に設定
        
    except Exception as e:
        last_log = trace_point
        log(WRN, SV, "s_Th() exception")
        log(WRN, SV, "s_Th() lastlog="+last_log)
        log(WRN, SV, "s_Th() exception string="+str(e))
        log(WRN, SV, "s_Th() I will restart now.")
        error_LED( 5 )
        machine.reset()
        
    #
    while True:
        try :
            PILOT_LED_ON( )
            log(INF, NO, "s_Th s.accept()")
            try:
                conn, addr = s.accept()
            except:
                log(INF, NO, "s_Th error s.accept")
                utime.sleep(0.1)
                continue
            #
            PILOT_LED_OFF( )
            utime.sleep(0.03)
            PILOT_LED_ON( )
            conn.settimeout(1)
            #リクエストを読み込む
            log(INF, NO, "s_Th conn.recv()")
            request = conn.recv(1000)
            request = request.decode('utf8')
            log(INF, NO, "s_Th "+request)
            log(INF, NO, "addr "+str(addr))
            #
            #リセットフラグ
            reset_flag = 0
            # / へのアクセス
            if request.find('GET / ') != -1 :
                header_send200(conn)
                #conn.send('HTTP/1.1 200 OK¥n')
                #conn.send('Content-Type: text/html¥n')
                #conn.send('Connection: close¥n¥n')
                html_form = """
                <html>
                <head>
                    <title>MigiHidariSys </title>
                    <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
                </head>
                <body>
                    <h1>MigiHidariSys </h1>
                """
                conn.send(html_form)
                conn.send("serialno:"+serialno+"<br>¥n")
                conn.send("<br>¥n")
                conn.send("MigiHidariSys:<br>¥n")
                conn.send("<blockquote>¥n")
                conn.send("<a href='/hid2'><font size='+2'>←</font></a> ¥n")
                conn.send("<a href='/hidari'>←</a> ¥n")
                conn.send("<a href='/migi'>→</a> ¥n")
                conn.send("<a href='/mig2'><font size='+2'>→</font></a><br>¥n")
                conn.send("</blockquote>¥n")
                html_form = """
                    メニュー<br>
                    <blockquote>
                        <a href="/status">ステータス</a><br>
                    </blockquote>
                </body>
                </html>
                """
                conn.send(html_form)
                
            # /migi へのアクセス
            elif request.find('GET /migi') != -1 :
                migi(False, conn)
            # /hidari へのアクセス
            elif request.find('GET /hidari') != -1 :
                hidari(False, conn)
            # /mig2 へのアクセス
            elif request.find('GET /mig2') != -1 :
                migi(True, conn)
            # /hid2 へのアクセス
            elif request.find('GET /hid2') != -1 :
                hidari(True, conn)
            # ステータス
            elif request.find('GET /status') != -1 :
                header_send200(conn)
                #conn.send('HTTP/1.1 200 OK¥n')
                #conn.send('Content-Type: text/html¥n')
                #conn.send('Connection: close¥n¥n')
                html_form = """
                    <html>
                    <head>
                        <title>MigiHidariSys ステータス画面</title>
                        <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
                    </head>
                    <body>
                        <h1>MigiHidariSys ステータス画面</h1>
                """
                conn.send("<blockquote>¥n")
                conn.send(html_form)
                
                # 状態表示
                conn.send("状態<br>¥n")
                conn.send("<blockquote>¥n")
                if wifi_error_flag == 0 :
                    conn.send("WIFI接続:正常<br>¥n")
                else :
                    conn.send("WIFI接続:異常<br>¥n")
                
                if network_error_flag == 0 :
                    conn.send("ネットワーク:正常<br>¥n")
                else :
                    conn.send("ネットワーク:異常<br>¥n")
                cpu_ondo = str(int((esp32.raw_temperature() -32 ) / 1.8))
                conn.send("CPU温度:"+cpu_ondo+"℃<br>¥n")
                #GC実行
                gc.collect()
                conn.send("メモリ状況:<br>¥n")
                conn.send("<blockquote>¥n")
                conn.send("使用中:"+str(gc.mem_alloc())+"<br>¥n")
                conn.send("空き :"+str(gc.mem_free())+"<br>¥n")
                conn.send("</blockquote>¥n")
                #MAC
                conn.send("MAC:"+ubinascii.hexlify(machine.unique_id(), '-').decode()+"<BR>¥n")
                
                conn.send("</blockquote>¥n")
                #設定情報
                conn.send("設定情報<br>¥n")
                conn.send("<blockquote>¥n")
                #設定ファイルからパラメータを読み込む
                fSetup = open("config.inf", "r")
                for f in fSetup:
                  one = f[0:1]
                  if one == '#' :
                    continue
                  f=f.replace('¥n', '')
                  f=f.replace('¥r', '')
                  conn.send(f+"<br>¥n")
                conn.send("</blockquote>¥n")
                
                conn.send("Software<br>¥n")
                conn.send("<blockquote>¥n")
                conn.send(VersionStr+"<br>¥n")
                conn.send("</blockquote>¥n")
                
                html_form = """
                        メニュー<br>
                        <blockquote>
                            <a href="/detail_log">直近ログ確認</a><br>
                            <a href="/error_log">エラーログ確認</a><br>
                            <a href="/reset">リセット</a><br>
                            <a href="/">戻る</a><br>
                        </blockquote>
                    </body>
                    </html>
                """
                conn.send(html_form)
            #直近ログ
            elif request.find('GET /detail_log') != -1 :
                header_send200(conn)
                #conn.send('HTTP/1.1 200 OK¥n')
                #conn.send('Content-Type: text/html¥n')
                #conn.send('Connection: close¥n¥n')
                html_form = """
                    <html>
                    <head>
                        <title>MigiHidariSys 直近ログ確認</title>
                        <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
                    </head>
                    <body>
                        <h1>MigiHidariSys 直近ログ確認</h1>
                        <br>
                        <a href="/status">メニューに戻る</a>
                        <br>
                        <blockquote>
                """
                conn.send(html_form)
                for log_record in logBuffer :
                    if type(log_record) is str :
                        conn.send(log_record)
                        conn.send("<br>¥n")
                html_form = """
                        </blockquote>
                    </body>
                    </html>
                """
                conn.send(html_form)
            #ファイル一覧
            elif request.find('GET /error_log') != -1 :
                header_send200(conn)
                #conn.send('HTTP/1.1 200 OK¥n')
                #conn.send('Content-Type: text/html¥n')
                #conn.send('Connection: close¥n¥n')
                html_form = """
                    <html>
                    <head>
                        <title>MigiHidariSys エラーログ確認</title>
                        <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
                    </head>
                    <body>
                        <h1>MigiHidariSys エラーログ確認(ファイル一覧)</h1>
                        <br>
                        <a href="/status">メニューに戻る</a>
                        <br>
                        <blockquote>
                """
                conn.send(html_form)
                files = os.listdir()
                for file_name in files :
                    if file_name.find('.log') != -1 :
                        conn.send("<a href=¥""+file_name+"¥">"+file_name+"</a>")
                        conn.send("<br>¥n")
                html_form = """
                        </blockquote>
                    </body>
                    </html>
                """
                conn.send(html_form)
            #ファイルログ
            elif ( request.find('GET /MH.log') != -1 or request.find('GET /MH.1.log') != -1 or request.find('GET /MH.2.log') != -1 or request.find('GET /MH.3.log') != -1 or request.find('GET /MH.4.log') != -1 or request.find('GET /MH.5.log') != -1 or request.find('GET /MH.6.log') != -1 or request.find('GET /MH.7.log') != -1 or request.find('GET /MH.8.log') != -1 or request.find('GET /MH.9.log') != -1 or request.find('GET /MH.10.log') != -1 ) :
                header_send200(conn)
                #conn.send('HTTP/1.1 200 OK¥n')
                #conn.send('Content-Type: text/html¥n')
                #conn.send('Connection: close¥n¥n')
                html_form = """
                    <html>
                    <head>
                        <title>MigiHidariSys エラーログ確認(ログ内容)</title>
                        <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
                    </head>
                    <body>
                        <h1>MigiHidariSys エラーログ確認(ログ内容)</h1>
                        <br>
                        <a href="error_log">ファイル一覧に戻る</a>
                        <br>
                        <blockquote>
                """
                conn.send(html_form)
                filename = request.replace('GET /', '').strip().split(' ', 1)[0].split('?', 1)[0]
                conn.send("----------filename=")
                conn.send(filename)
                conn.send("----------<br><br>")
                
                f = open(filename, 'r')
                with open(filename) as fh:
                    for line in fh:
                        conn.send(line.strip())
                        conn.send("<br>¥n")
                html_form = """
                        </blockquote>
                    </body>
                    </html>
                """
                conn.send(html_form)
            elif request.find('GET /reset') != -1 :
                header_send200(conn)
                #conn.send('HTTP/1.1 200 OK¥n')
                #conn.send('Content-Type: text/html¥n')
                #conn.send('Connection: close¥n¥n')
                html_form = """
                    <html>
                    <head>
                        <title>MigiHidariSys リセット</title>
                        <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
                    </head>
                    <body>
                        <h1>MigiHidariSys をリセットしました</h1>
                    </body>
                    </html>
                """
                conn.send(html_form)
                reset_flag = 1
            elif request.find('GET /favicon.ico') != -1 :
                conn.send('HTTP/1.1 404 notfound¥n')
                conn.send('Content-Type: text/html¥n')
                conn.send('Connection: close¥n¥n')
            else :
                log(INF, NO, "s_Th other")
                #try :
                #    conn.send('HTTP/1.1 500 Internal Server Error¥n')
                #    conn.send('Content-Type: text/html¥n')
                #    conn.send('Connection: close¥n¥n')
                #    utime.sleep(5)
                #except :
                #    log(INF, NO, "s_Th error con.send")
            conn.close()
            #リセット操作
            if reset_flag == 1 :
                log(INF, NO, "utime.sleep(5)")
                utime.sleep(5)
                log(INF, NO, "s_Th:machine.reset()")
                machine.reset()
            #
            utime.sleep(0.1)
            #GC実行
            gc.collect()
        except Exception as e:
            if str(e) == '[Errno 104] ECONNRESET' :
                log(INF, NO, "s_Th [Errno 104] ECONNRESET")
                conn.close()
                continue
            if str(e) == '[Errno 110] ETIMEDOUT' :
                log(INF, NO, "s_Th [Errno 110] ETIMEDOUT")
                conn.close()
                continue
            last_log = trace_point
            log(WRN, SV, "s_Th() exception")
            log(WRN, SV, "s_Th() lastlog="+last_log)
            log(WRN, SV, "s_Th() exception string="+str(e))
            log(WRN, SV, "s_Th() I will restart now.")
            error_LED( 5 )
            machine.reset()

昔々amazonで衝動買いしておいたステッピングモーターと制御ボードをESP32で動かすよー(28BYJ-48+ULN2003+ESP32)
最近、夢の中でなんか作ってて、何を作っているのかわからないんだけど
うまく動かなくて、ギャーって起きるみたいな。
そんな夢を何度も見て、そして、眠れなくなって起きるみたいな。
そんな感じで起きちゃいました。
そういえば、昔amazonで買ったのがあったなーとか思い出して
丑三つ時に起きてしまったので、部屋の電気をMAXにして4時間経過しました。
ステッピングモーター的にはうまく動いたっぽいですので、記録してから寝ます。
 
■amazon
 今も同じものが手に入るみたいですね。

 2018年に購入って・・・だいぶ長い間眠らせておりましたみたいです。
 
■回路図
 
 
 
 電源は開発ボードの5Vをそのままでも動きましたけど、
 別にしたほうが安全と思います。
 
■参考ページ
    https://qiita.com/kotaproj/items/cd37c971f03fb02c97ce
 
■Movie
https://youtu.be/JO4JZjH0W3E

 

■ソース


#
#ステッピングモーター動作テスト
#
#  ESP32---ULN2003制御ボード---28BYJステッピングモーター
#
#  ESP32 ULN2003
#   25      1
#   26      2
#   27      3
#   13      4
#   5V      5V
#   GNS     GND
#


import time
from machine import Pin

class Stepper():
    def __init__(self,  number_of_steps, motor_pin_1, motor_pin_2, motor_pin_3, motor_pin_4):
        self.step_number = 0                   # 何ステップ
        self.direction = 0                     # 方向 左回転=1、右回転=0
        self.last_step_time = 0                # 経過時間計算用に前の動作時間を保存
        self.number_of_steps = number_of_steps # 1回転のステップ数

        # ULN2003に接続するピン設定
        self.motor_pin_1 = Pin(motor_pin_1, Pin.OUT)
        self.motor_pin_2 = Pin(motor_pin_2, Pin.OUT)
        self.motor_pin_3 = Pin(motor_pin_3, Pin.OUT)
        self.motor_pin_4 = Pin(motor_pin_4, Pin.OUT)

        #スピードをデフォルトにしておく
        self.set_speed()
        return

    def set_speed(self, what_speed=10):
        #スピード設定 1~19は動くみたい
        
        #六百万を2048で割って、さらにwhat_speedで割る
        #what_speedが小さいほど計算結果が大きな数字になり、
        #結果次のステップへの動作コマンドが送られるまでが長くなるので
        #回転スピードが遅くなる
        self.step_delay = 60 * 1000 * 1000 // self.number_of_steps // what_speed
        return

    def step(self, steps_to_move, auto_stop=True):
        #指定された回転ステップ分動かすのじゃ
        
        steps_left = abs(steps_to_move)  # 整数のステップを取得
        self.direction = 1 if steps_to_move > 0 else 0  # 方向を取得

        # 上記で求めたステップだけ回る
        while steps_left > 0:
            now = time.ticks_us()
            # 現在時刻と直前に指示を送った時刻の差分がset_speedで求めた値を超えたら次の指示を送る
            if time.ticks_diff(now, self.last_step_time) >= self.step_delay:
                self.last_step_time = now  #直前に指示を送った時刻を記録
                # 方向を確認して指示するステップを求める
                if self.direction == 1:
                    self.step_number += 1
                    if self.step_number == self.number_of_steps:
                        self.step_number = 0
                else:
                    if self.step_number == 0:
                        self.step_number = self.number_of_steps
                    self.step_number -= 1

                # ループ回数
                steps_left -= 1
                # 4で割った余りを指示として出す
                self._step_motor(self.step_number % 4)

        if auto_stop:
            self.stop()
        return

    def _step_motor(self, this_step):
        # 1010
        if this_step == 0:
            self.motor_pin_1.value(True)
            self.motor_pin_2.value(False)
            self.motor_pin_3.value(True)
            self.motor_pin_4.value(False)
        # 0110
        elif this_step == 1:
            self.motor_pin_1.value(False)
            self.motor_pin_2.value(True)
            self.motor_pin_3.value(True)
            self.motor_pin_4.value(False)
        # 0101
        elif this_step == 2:
            self.motor_pin_1.value(False)
            self.motor_pin_2.value(True)
            self.motor_pin_3.value(False)
            self.motor_pin_4.value(True)
        # 1001
        elif this_step == 3:
            self.motor_pin_1.value(True)
            self.motor_pin_2.value(False)
            self.motor_pin_3.value(False)
            self.motor_pin_4.value(True)
        return

    def stop(self):
        self.motor_pin_1.value(False)
        self.motor_pin_2.value(False)
        self.motor_pin_3.value(False)
        self.motor_pin_4.value(False)
        return

MOTOR_STEPS = (2048)
PIN_MOTOR_1 = (25)
PIN_MOTOR_2 = (26)
PIN_MOTOR_3 = (27)
PIN_MOTOR_4 = (13)
my_motor = Stepper(MOTOR_STEPS, PIN_MOTOR_1, PIN_MOTOR_3, PIN_MOTOR_2, PIN_MOTOR_4)

print("speed(1)")
my_motor.set_speed(1)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(5)")
my_motor.set_speed(5)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(10)")
my_motor.set_speed(10)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(15)")
my_motor.set_speed(15)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(16)")
my_motor.set_speed(16)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(17)")
my_motor.set_speed(17)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(18)")
my_motor.set_speed(18)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(19)")
my_motor.set_speed(19)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(20)")
my_motor.set_speed(20)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(25)")
my_motor.set_speed(25)
my_motor.step(1024)
my_motor.step(-1024)

print("speed(30)")
my_motor.set_speed(30)
my_motor.step(1024)
my_motor.step(-1024)

 

ラズパイでカメラ安定化バージョン3

 

前の記事でhttps://ameblo.jp/fc2miha/entry-12833773023.html

 

新型のラズパイOSでうまく良くといいなーという取り組みだったんですが、
やっぱり1週間程度で停止してしましました。

今回はディスクのramdisk化を実施してみます。


今度はちゃんと安定して動くといいなー

 

■今回の方針

 

・Linux raspberrypi 5.10.60+ #1449をインストール。

・sshが動くように設定

・カメラが動くように設定

(ここまでは前回も同じ)

・OSのディスクに書き込まないように設定

・USBメモリ認識

・sambaが動くように設定

・カメラ関連シェルをUSBメモリ上で動くようにする

・OverlayFSの有効化

・この状態で安定しているか確認する

 

■Raspberry Pi OS(32bit)をインストール

 

    Raspberry Pi Imagerを使用してRaspberryPiOS(32bit)を選択して
    MicroSDに起動ディスクを作って
    ラズパイゼロWHにセットして
    起動する
    
    パスワードの設定、ロケーションの設定、WIFIの設定
    ソフトの最新化を実施しておく。
    1時間ぐらいかなかかります。

    ちなみに、uname -aの結果は
     Linux raspberrypi 5.10.60+ #1449

 

■sshを有効化

 

    sudo raspi-config

    interfaceing Options → SSH
    Wold you the SSH server to be enables?
    Yes
    Finish
    
    reboot

 

■カメラを使えるようにする

 

    sudo raspi-config
    
    Interfacing Options → Camera
    
    Yes
    
    Ok
    
    rebootされる

 

■一枚撮ってみる。

 

    pi@raspberrypi:~ $ python
    Python 2.7.16 (default, Oct 10 2019, 22:02:15)
    [GCC 8.3.0] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import picamera
    >>> camera = picamera.PiCamera()
    >>> camera.capture('image.jpg')
    >>> quit()
    
    pi@raspberrypi:~ $ ls
    Bookshelf  Documents  Music     Public     Videos     picamera
    Desktop    Downloads  Pictures  Templates  image.jpg
    pi@raspberrypi:~ $
    
    
■OSのディスクに書き込まないように設定


    https://ameblo.jp/fc2miha/entry-12833772931.html


    これをやると、落っこちにくくなる。
    でも、ジェシー用なので今も同じかはわからない

 

    free -h


    sudo swapoff --all


    free -h


    sudo vi /etc/fstab


    以下を追加
    tmpfs           /tmp            tmpfs   defaults,size=200m 0       0
    tmpfs           /var/tmp        tmpfs   defaults,size=20m 0       0
    tmpfs           /var/log        tmpfs   defaults,size=200m 0       0
    書き込んでviを終了 
    :wq

 

    sudo reboot


    df -h


    上記で追加したのを確認


    sudo vi /etc/rc.local


    以下を追加


    mkdir -p /var/log/apt
    mkdir -p /var/log/fsck
    mkdir -p /var/log/ntpstats
    mkdir -p /var/log/samba
 

    chmod 750 /var/log/samba
    chown ntp:ntp /var/log/ntpstats
    chown root:adm /var/log/samba

    touch /var/log/btmp
    touch /var/log/lastlog
    touch /var/log/wtmp

    chmod 600 /var/log/btmp
    chmod 664 /var/log/lastlog
    chmod 664 /var/log/wtmp

    chown root:utmp /var/log/btmp
    chown root:utmp /var/log/lastlog
    chown root:utmp /var/log/wtmp

    exit 0
    :wq

 

    sudo vi /etc/rsyslog.conf


    以下の行をコメントにする

    #daemon.*                       -/var/log/daemon.log
    #kern.*                         -/var/log/kern.log
    #lpr.*                          -/var/log/lpr.log
    #mail.*                         -/var/log/mail.log
    #user.*                         -/var/log/user.log

    #mail.info                      -/var/log/mail.info
    #mail.warn                      -/var/log/mail.warn
    #mail.err                       /var/log/mail.err

    #*.=debug;¥
    #       auth,authpriv.none;¥
    #       news.none;mail.none     -/var/log/debug
    :wq
    
    以下のumountコマンドでエラーになるので少し遠回りだけど
    別のSDで起動してUSBで接続した/dev/mmcblk0p2に対して
    ジャーナルを取り除くコマンドを入れる
    #sudo umount /dev/mmcblk0p2
    #sudo tune2fs -O ^has_journal /dev/mmcblk0p2
    #sudo tune2fs -l /dev/mmcblk0p2 | grep features
    #Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file dir_nlink extra_isize
    #has_journalが含まれていなければOK
    
    sudo shutdown -h now
    
    別のSDで起動して、今までインストールしたSDはUSB接続する
    下記では/dev/sdc2で認識されている
    
    pi@raspberrypi:~ $ df -h


    ファイルシス   サイズ  使用  残り 使用% マウント位置
    /dev/root        118G   41G   72G   37% /
    devtmpfs         181M     0  181M    0% /dev
    tmpfs            185M     0  185M    0% /dev/shm
    tmpfs            185M  5.4M  180M    3% /run
    tmpfs            5.0M  4.0K  5.0M    1% /run/lock
    tmpfs            185M     0  185M    0% /sys/fs/cgroup
    /dev/mmcblk0p1    44M   23M   21M   52% /boot
    tmpfs             37M     0   37M    0% /run/user/1000
    /dev/sdc2         14G  1.2G   13G    9% /media/pi/rootfs
    /dev/sdc1        253M   48M  205M   19% /media/pi/boot
    /dev/sda1        1.9G  236M  1.7G   13% /media/pi/BUFFALO
    
    sudo umount /dev/sdc2
    
    sudo tune2fs -O ^has_journal /dev/sdc2


    tune2fs 1.43.4 (31-Jan-2017)
    
    sudo tune2fs -l /dev/sdc2 | grep features
    Filesystem features:      ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file dir_nlink extra_isize
    
    sudo shutdown -h now
    
    元のSDで起動してジャーナルがなくなっていることを確認する
    
    sudo tune2fs -l /dev/mmcblk0p2 | grep features
    
    has_journalが含まれていなければOK


■USBメモリ認識
    
    USBメモリを接続
    
    df -h
    
    ファイルシス   サイズ  使用  残り 使用% マウント位置
    /dev/root         14G  3.4G   10G   26% /
    devtmpfs         152M     0  152M    0% /dev
    tmpfs            184M     0  184M    0% /dev/shm
    tmpfs            184M  2.9M  181M    2% /run
    tmpfs            5.0M  4.0K  5.0M    1% /run/lock
    tmpfs            184M     0  184M    0% /sys/fs/cgroup
    tmpfs            200M  4.0K  200M    1% /tmp
    tmpfs             20M     0   20M    0% /var/tmp
    tmpfs            200M  172K  200M    1% /var/log
    /dev/mmcblk0p1   253M   49M  204M   20% /boot
    tmpfs             37M  4.0K   37M    1% /run/user/1000
    /dev/sda1        1.9G  236M  1.7G   13% /media/pi/BUFFALO
    
    BUFFALOで認識された
    
    sudo vi /etc/fstab
    
    /dev/sda1       /media/pi/BUFFALO auto defaults 0 0
    
    sudo reboot

 

■カメラ関連シェルをUSBメモリ上で動くようにする
    
    cd /media/pi/BUFFALO/picamera
    
    sudo chmod +x camera.sh file_del.sh
    
    sudo vi  camera.sh file_del.sh
    
    ディレクトリパスを調整
    
    sudo crontab -e
    
    * * * * * for i in `seq 0 5 59`;do (sleep ${i}; /media/pi/BUFFALO/picamera/camera.sh) & done;
    0 * * * * /media/pi/BUFFALO/picamera/file_del.sh    

   :wq
    
■sambaが動くように設定
    
    sudo apt-get install -y samba
    
    設定
    
        sudo vi /etc/samba/smb.conf
        [pi]
           comment = Welcome to pi Server
           path = /media/pi/BUFFALO/picamera/data
           browseable = yes
           wriable = yes
           guest ok = no
           force create mode = 0666
           force directory mode = 0777
           read only = no
           create mask =0777
           directory mask = 0777
       
       sudo smbpasswd -a pi
       
       sudo service smbd restart
       
    
    
■OverlayFSの有効化


    これをやると、bootパーティションが書き込み禁止になります。
    
    sudo raspi-config

    Performance Options → Overlay File System
    はい
    Finish
    
    reboot

 

■camera.sh

 

python /media/pi/BUFFALO/picamera/camera.py

 

■file_del.sh

 

find /media/pi/BUFFALO/picamera/data/* -name '*.jpg'  -cmin +150 -exec rm -f {} ¥;
find /media/pi/BUFFALO/picamera/data/* -type d  -ctime +0 -exec rm -rf {} ¥;


■camera.py

 

import picamera
import datetime
import os
import shutil

now = datetime.datetime.now()
base_directory = '/media/pi/BUFFALO/picamera/data/'
YYYYMMDD = now.strftime('%Y%m%d')
output_directory = base_directory + YYYYMMDD
if not os.path.exists(output_directory):
  os.makedirs(output_directory)
  os.chmod(output_directory, 0777)
filename = now.strftime('%H%M%S')
filename_fullpath = output_directory + '/' + filename + '.jpg'

camera=picamera.PiCamera()
camera.hflip = True
camera.vflip = True
#camera.resolution = (640,480)
camera.resolution = (1024,768)
camera.capture(filename_fullpath)
shutil.copyfile(filename_fullpath, base_directory + '/now.jpg')

 

■10日後・・・(2021.10.25)

 動かなくなった。

 症状としては

  sambaの反応がなくなった。

  sshの反応がなくなった。

  pingの反応がなくなった。

 暫定対処

 →電源切り→電源入り

 sambaが動作

  写真の中身をみると、直近までカメラデータが残っていたので、

  単純にNWが落っこちて、その他は動いていたっぽい。

 本格対処。

  crobtabに以下の一行を追加

  0 0 * * * sudo reboot

  0時に再起動します。

ラズパイでカメラ安定化バージョン2 安定化試験中

 

前に作ったラズパイカメラを使ったカメラなんですが、何日かで止まってしまうので
安定化するための措置を行います。

 

前の記事でジェシーのままやりたかったんですが、ダメだったみたいなので

新しいやつを使います。


新しいのはラズパイをインストールするシキタリが変わっていて、
OSの名前もRaspbianではなくて
SDに書き込むツールが本家の財団から出ていて、
インストールするOSの名前もRaspberry Pi OS(32-bit)とかになってたりします。


ツールをインストールしたら起動して
入れるOSはドロップダウンリストから選ぶだけで、簡単に
SDカード作ってくれたりします。

 

普通のデスクトップ向けのraspberryPi用のOSを選んでみたところ、
初回の起動でWIFIのSSIDとかパスワード、国の名前や言語とか選べば
普通にネットにつながってくれましたので、その状態からやります。

 

ちなみに、unameの結果は
 Linux raspberrypi 5.10.60+ #1449
ってなっておりました。

 

■今回の方針。

 

OSがVersionUPしているので、
これで、安定するかも!!

と甘い期待を抱きまして、今回は最新バージョンのまま小細工しないで
カメラ撮影して保存する部分だけを実装したいと思います。

カメラ画像(静止画)を日付と時刻で保存するプログラムを
crontabで一定周期で呼び出す。
画像の解像度と保存先の容量を計算して
ctontabに設定する周期を調整。
ディスクがいっぱいにならないように一定期間経過したファイルを削除する
sshでログインしてメンテナンス可能にする
sambaで取得した画像を確認可能にする

 

■まずはなにはともあれ、sshが使えないと・・・なので、sshを有効化

 

    sudo raspi-config

    interfaceing Options → SSH
    Wold you the SSH server to be enables?
    Yes
    Finish
    
    reboot


→前回躓いたpythonにカメラモジュールを入れるところから始めます。

 

■カメラを使えるようにする

 

    sudo raspi-config
    
    Interfacing Options → Camera
    
    Yes
    
    Ok
    
    rebootされる

 

■カメラ関連のモジュールを入れる

 

    sudo apt-get install python-picamera
    
    python-picamera はすでに最新バージョン (1.13) です。
    
    最初から入っている。うーんなんもすることないね。
    
■一枚撮ってみる。

 

    pi@raspberrypi:~ $ python
    Python 2.7.16 (default, Oct 10 2019, 22:02:15)
    [GCC 8.3.0] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import picamera
    >>> camera = picamera.PiCamera()
    >>> camera.capture('image.jpg')
    >>> quit()
    
    pi@raspberrypi:~ $ ls
    Bookshelf  Documents  Music     Public     Videos     picamera
    Desktop    Downloads  Pictures  Templates  image.jpg
    pi@raspberrypi:~ $
    
    image.jpgができている。
    画像を表示すると普通に撮れて要るっぽい
    
    もうね、何にもしなくても普通につないてプログラムちょいちょいでカメラが動くって
    おもしろ。
    
■動画

 

    ラズパイカメラの場合?(パイソンの場合かも)、
    動画は拡張子h264形式で保存されるので
    mp4にするためにgpacってのがいるみたいです。
    
    sudo apt-get install -y gpac

 

■動画撮影

 

    import picamera
    import time
    
    camera=picamera.PiCamera()
    camera.hflip = True
    #camera.vflip = True
    camera.resolution = (640,480)
    camera.start_recording('record.h264')
    time.sleep(10)
    camera.stop_recording()
    camera.close()

 

    MP4Box -fps 30 -add record.h264 record.mp4

    ちなみに、ラズパイに入っている再生ソフトVLCプレイヤーではh264のままでも再生できる

 

■cronに設定を入れて定期的に画像を保存する

 

    sudo crontab -e
    * * * * * for i in `seq 0 5 59`;do (sleep ${i}; /home/pi/picamera/camera.sh) & done;
    0 * * * * /home/pi/picamera/file_del.sh
    #0 0 * * * sudo reboot

    1行目は5秒に一回camera.shを起動
    2行目はfile_del.shを毎時0分に起動
    3行目は1日一回00:00にrebootする
    
    3行目はコメントしといたほうが良いと思うのでコメント
    ま、やっぱ安定しないときはこれをやる

    シェルに実行権を付ける
    
        chmod +x camera.sh file_del.sh

 

→シェルとプログラムの中身

 

■file_del.sh

 

find /home/pi/picamera/data/* -name '*.jpg' -ctime +7 -exec rm -f {} ¥;
find /home/pi/picamera/data/* -type d -ctime +7 -exec rm -rf {} ¥;

 

■camera.sh

 

python /home/pi/picamera/camera.py

 

■camera.py

 

import picamera
import datetime
import os

now = datetime.datetime.now()
base_directory = '/home/pi/picamera/data/'
YYYYMMDD = now.strftime('%Y%m%d')
output_directory = base_directory + YYYYMMDD
if not os.path.exists(output_directory):
  os.makedirs(output_directory)
  os.chmod(output_directory, 0777)
filename = now.strftime('%H%M%S')
filename_fullpath = output_directory + '/' + filename + '.jpg'

camera=picamera.PiCamera()
camera.hflip = True
camera.vflip = True
#camera.resolution = (640,480)
camera.resolution = (1024,768)
camera.capture(filename_fullpath)

 

■file_del.shの調整

 

    画像の1ファイルが500㌔バイト。

    ディスクの空きが残り11GB
    
    半分の5ギガをこのシステムで使うとして
    (5 × 1000 × 1000 × 1000 ) / 500000
    = 10000枚
    
    1万枚の写真を保存するとして、
    5秒間隔とすれば
    期間は
    5万秒
    ってことは、時間(H)にすると
    50000 ÷ 3600
    = 13.88888889
    って、それしか撮れないのかよ。
    みたいな。
    crontabを10秒間隔として
    削除までの期間を1日で調整。っと。
    
■smabaでwindowsから見えるようにする

 

    sudo apt-get install -y samba
    
    設定
    
        sudo vi /etc/samba/smb.conf
        [pi]
           comment = Welcome to pi Server
           path = /home/pi/picamera/data
           browseable = yes
           wriable = yes
           guest ok = no
           force create mode = 0666
           force directory mode = 0777
           read only = no
           create mask =0777
           directory mask = 0777
       
       sudo smbpasswd -a pi

 

       sudo service smbd restart

 

■完成

 

    この状態で2か月ぐらい動くかテストすることにする。


 

1週間経過しないぐらいで動かなくなった。ログを見るとpsの結果が連続して出ているように見える。なぜ?

前に作ったラズパイカメラを使ったカメラなんですが、何日かで止まってしまうので
安定化するための措置を行います。

 

古いですが、じぇしーを使います。

 

■使用するもの
    SDカードフォーマッター
  https://www.sdcard.org/ja/downloads-2/formatter-2/

    WIN32DiskImager
        https://win32diskimager.download/download-win32-disk-imager/
    ラズパイイメージファイル
        http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian_lite/images/
    ラズパイzeroWH
        https://akizukidenshi.com/catalog/g/gM-12961/


■イメージファイルをmicroSDに焼いて起動

    初期IDとパスワードはpi/raspberry
    すぐ忘れちゃうからねメモメモ

 

■ラズパイのSD書き込みを極力なくする方法

    https://ameblo.jp/fc2miha/entry-12833772931.html

    これをやると、落っこちにくくなる。

    順番にコマンドを書いとく
    free -h
    sudo swapoff --all
    free -h
    sudo vi /etc/fstab
    以下を追加
    tmpfs           /tmp            tmpfs   defaults,size=200m 0       0
    tmpfs           /var/tmp        tmpfs   defaults,size=20m 0       0
    tmpfs           /var/log        tmpfs   defaults,size=200m 0       0
    書き込んでviを終了 
    :wq

    sudo reboot
    df -h
    上記で追加したのを確認
    sudo vi /etc/rc.local
    以下を追加
    mkdir -p /var/log/apt
    mkdir -p /var/log/fsck
    mkdir -p /var/log/ntpstats
    mkdir -p /var/log/samba
 

    chmod 750 /var/log/samba
    chown ntp:ntp /var/log/ntpstats
    chown root:adm /var/log/samba

    touch /var/log/btmp
    touch /var/log/lastlog
    touch /var/log/wtmp

    chmod 600 /var/log/btmp
    chmod 664 /var/log/lastlog
    chmod 664 /var/log/wtmp

    chown root:utmp /var/log/btmp
    chown root:utmp /var/log/lastlog
    chown root:utmp /var/log/wtmp

    exit 0
    :wq

    sudo vi /etc/rsyslog.conf
    以下の行をコメントにする

    #daemon.*                       -/var/log/daemon.log
    #kern.*                         -/var/log/kern.log
    #lpr.*                          -/var/log/lpr.log
    #mail.*                         -/var/log/mail.log
    #user.*                         -/var/log/user.log

    #mail.info                      -/var/log/mail.info
    #mail.warn                      -/var/log/mail.warn
    #mail.err                       /var/log/mail.err

    #news.crit                      /var/log/news/news.crit
    #news.err                       /var/log/news/news.err
    #news.notice                    -/var/log/news/news.notice

    #*.=debug;¥
    #       auth,authpriv.none;¥
    #       news.none;mail.none     -/var/log/debug
    :wq
    
    sudo umount /dev/mmcblk0p2
    sudo tune2fs -O ^has_journal /dev/mmcblk0p2

    ※ここから先コマンドが複雑なのでPCからコピペしたいのでteratermで操作

    crontab -e
    以下を追加
    sudo tar cvzf /home/pi/log`date '+%Y%m%d%H%M'`.tgz /var/log/*
    sudo find /home/pi/log* -mtime +31  -exec rm -f {} ¥;
    :wq
    
■WIFIに接続
    
    sudo vi /etc/wpa_supplicant/wpa_supplicant.conf
    とやって
    country=JP
    etwork={
        ssid="Free001"
        psk="password"
    }
    wqで書き込みするけどpermissionエラーになる。
    
    どうやら、rootのパスワードを先につけてあげないとだめっぽ
    
    sudo passwd root
    new password:
    
■sshを有効化

    sudo raspi-config

    interfaceing Options → SSH
    Wold you the SSH server to be enables?
    Yes
    Finish
    
    reboot


■USBメモリ認識

    USBメモリをセットする

    sudo fdisk -l

    Disk /dev/mmcblk0: 14.4 GiB, 15476981760 bytes, 30228480 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0x543cc39b

    Device         Boot Start      End  Sectors  Size Id Type
    /dev/mmcblk0p1       8192    93596    85405 41.7M  c W95 FAT32 (LBA)
    /dev/mmcblk0p2      94208 30228479 30134272 14.4G 83 Linux

    Disk /dev/sda: 1.9 GiB, 2004877312 bytes, 3915776 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0xc3072e18

    Device     Boot Start     End Sectors  Size Id Type
    /dev/sda1  *       32 3915775 3915744  1.9G  6 FAT16


    上記のBooTが*のやつ/dev/sda1がUSBメモリっぽい

    cd /media
    sudo mkdir usbmem
    sudo chmod 777 usbmem
    sudo mount /dev/sda1 /media/usbmem

    df
    
    Filesystem     1K-blocks   Used Available Use% Mounted on
    /dev/sda1        1957600 241024   1716576  13% /media/usbmem
    
    ls -l /media/usbmem
    
    フォルダーの中身を見て正しいか確認
    
    sudo umount /media/usbmem
    
    sudo vi /etc/fstab
    
■ラズパイカメラを使えるようにする

    sudo raspi-config
    
    Interfacing Options → Camera
    
    Yes
    
    Ok
    
    rebootされる

■カメラ関連のモジュールを入れる

    sudo apt-get install python-picamera
    
    エラーになる。
    
    いろいろ試行錯誤・・・・・
    
    ガーン
    
    ジェシーちゃん古すぎてaptコマンド使えないっす。
    
    って事で。
    
    失敗

遠隔操作でPCの電源をON/OFF/RESETする回路とか。
 
リモートワークが流行っております。
自分もリモートワークだったんですが、さらに拡張して
実家でリモートワークしてたりします。
 
自宅PCがデスクトップなので、VNCを使って
リモート接続してメール等やファイルを見れるようにしておりましたが、
ある日突然接続不能に陥り、ギャーってなっておりました。
会社であれば、電話して電源入れなおしてもらうとかすれば良いんですけど。
結局、2週間経過後に謎の自然復旧を遂げたのですが、
今度こんなことが発生したときに大丈夫なように
電源ボタンを操作する装置を作ってみました。
 
原理
 デスクトップパソコンにはフロントパネルの電源スイッチと
リセットスイッチに接続されるピンが出ております。
これをハイジャックして、遠隔操作できるようにします。
 
写真
 

 
回路
 

 
搭載する機能
 パソコンの電源ボタンを押す。
 パソコンの電源ボタンを長押しする。
 パソコンのリセットボタンを押す。
 
そんで完成。
写真
 

 

 
動作
 

 
回路
 

 
プログラム
 
 
https://drive.google.com/file/d/1ZbtXihSVUc9jNszct-V2ex5Z7XvxxcxF/view?usp=sharing
 
 
 

ESP32+micropythonでのメモリ節約コーディング
 
ESP32でプログラムをしていると
いつも、メモリーが足りなくなってしまい・・・・
メモリー確保エラーとの戦いになるので。
自分なりに整理してみたい
 
今回試してみたこと。
 
何か指標がないと効果があったのか
なかったのかわからないので。以下を指標値にする。
 gc.mem_alloc() → 使用中
 gc.mem_free() → 空き
 単位はバイト。
 
として、実際に動かしてみながら試してみております。
 
とりあえず、動作しないとどうしようもないので不要なコード削除から始めてみた。
 

■不要なコードを削除

 使用中:63328
 空き :54896

 

-----

 

■毎回GCを入れる

 →ループの先頭にgc.collect()を入れた
 使用中:60544
 空き :57680

 

-----

 

■余計な表示文字列の削除

 →http送信用バッファーのスペースを削除してみる 
 使用中:58528
 空き :59696

 

-----

 

■同一処理のサブルーチン化

 →HTTP/1.1 200 OKの3行の応答をひとつにまとめてみる 
 使用中:54928
 空き :63168

 

やろうと思えば、もっと多くの部分をサブルーチン化できるんですけど、

今回は目立つ部分だけに止めた。

結局基本に立ち戻ってサブルーチン化が一番効果があるかも、という結論だけど、

あんまりやり過ぎるとプログラムの見通しが悪くなったりして・・・

いろんな意見があると思うのでこのぐらいで止めておくが

メモリ削減を優先する場合はまだ改善の余地ありってことです。

 

で、空きが63168ぐらいあれば良いみたいですね。

単位はバイト。

空きと、使用中を足しても120㌔バイトしかない。

秋月のページで

     ESP32-DevKitC ESP-WROOM-32開発ボード

を見るとSRAM512㌔ってなっていて。なんか少ないねーと思ったりしますが。

Micropython入れた状態だと

ユーザーは120㌔バイトしか使えないっぽい。です。

ちなみに、Micropython入れて、main.pyを空にして起動した直後は

--------------------------

MicroPython v1.11-288-gfb73bdae6 on 2019-09-06; ESP32 module with ESP32
Type "help()" for more information.
>>> gc.mem_alloc()
4880
>>> gc.mem_free()
113344
>>>

ってなっておりまして、113㌔バイト使える状態なので、

自分が作成したプログラムがだいたい50㌔バイトを占めていることになるようです。

ちなみに、プログラムはコメント込みで1500Lineぐらいですので

そんなに大したことはしていない感じですが、機能としては

 WIFIでAPを開いて設定用のWEB画面を表示して

 設定内容を消えないメモリ(micropythonのディスク?)へ格納

 設定内容に接続先のWIFIのSSIDとか、パスワードとか

 他パラメーター11種類が書いてあるのでそれを読みだし

 自宅WIFIへ接続

 制御用にWEBサーバーをネット上で開いて

 ログイン等、全部で11画面

 画面からの制御でGPIOを制御して外部装置を制御

 後から何かエラーがわかるようにlog出力&ログローテーション

 ログに時間を記録しないと何が何だかわからないのでntpと時刻同期

 セキュリティー認証機能 暗号化はない

 LEDによる状態通知

 アクセスのないときに時々再起動

といった所です。

結構機能満載でしょう。


 
 

IEでも動作する最近のトレンドにマッチしているかっこいいページ?
 
なんか、IEを今でも使い続けている会社さんとかいっぱいあったりして。
IEは11で終了で、来年6月にサポート終了なんだけど、
そういった会社さんはそれでも使い続けるんだろうなーみたいな。悪い予感しかしない。
 
その当時IE8ぐらいかなーから9にアップすると社内システムがいろいろ動かなくなったりして。
IE8から上げるの禁止とか・・・
IEの互換モード使うと動くとか。
いろいろあって、今でもEdgeに移行できていない人たちみたいな。
 
新人にIEで動くようにするのに会社の都合でね・・・みたいなのを説明したり。
そして、絶対命令を下すと新人さんのモチベーションを一気に奪っていったり。
chrome標準なんですよね。とお客さんに言うと、
社長のところにchromeインストールに行くのめんどくさいとか言われるという。
 
この世界でおそらく最強の影響力を保っているというブラウザーである
IEことInternetExplorer。
 
もっと昔はVersion4ぐらいのときにNetscapeNavigatorと戦いを繰り広げ。
同じjavascriptなのに双方で互換性がないとか、
それなのにお客さんには両方で同じように
動くようにしてほしいというリクエストが来るという。
 
そんなんブラウザー側の責任でしょ。の責任がプログラマーに来るという
恐ろしい世の中ですよね。
 
という世の中で
「IEでも動作する最近のトレンドにマッチしているかっこいいページ」の要望をもらいました。
 
で世の中に出回っているページを色々見ながら、
かっこいい要素はおそらくは、背景画像だったり、トップページの画像だったりとかしたりして、
自分みたいなプログラマー的な人間の領域ではないので
ま、画像は後から張り付けるとして、
メニューがプルダウンとか、ハンバーガーメニューとか、そういったものがかっこ良さの要素かなと
理解して、ハンバーガーメニューとログイン画面のかっこいい要素を考えてみた。
 
login.htmlとindex.htmlがメインでのこりはcssとjsの集まりで
少し古いバージョンのライブラリを使っております。
な感じのになっております。
 
template1 メニュー上部表示、右上にハンバーガーメニュー
template2 右上にハンバーガーメニュー
template3 左上にハンバーガーメニュー
 
ってことで。
 
template1 ログイン

 
template1 メイン

 
カッコ良いかかどうかなんて おれにわ わからね
https://drive.google.com/file/d/1nsnowOc5_dJ0kUMwR5jU71J9FFLW5wfn/view?usp=sharing

 

KENWOOD修理
 
仕事場用のスピーカーというかなにか音が鳴るものが欲しくて
近くのハードオフに行ってみたところ、だいぶ古い、MDとCDとラジオが付いている
ミニコンポ?と言うのだろうか?大きめのラジカセサイズのステレオという感じですが。
が、全部セット(上記本体にリモコン、AMーFM用アンテナ、スピーカー、電源ケーブル)で2200円。
という価格で並んでおりました。説明には音出ました。と書いてあったので、
これは安いーと、店員を呼んで確認すると、全部セットで2200との事だったので、
即購入。
 
家に戻り、
 
ラジオを鳴らしてみると結構いい音で鳴る。
 
パソコンの音声出力の音も鳴る。
 
CDも鳴る。
MDは持ち合わせがないので確認していないけど。
音出ますね。
 
しかし、故障もありまして。
故障箇所を一覧にする。
 ・リモコンが効かない。
 ・ボリュームが効かない。
という状況。
 
ハードオフの説明に偽りなし。
 でも壊れているところも書いておいてほしい。
  そんな気もします。
 
リモコンを調べてみると、赤外線が光っている様子がないので
 (これは、スマホをビデオ代わりにして赤外線の発射口を撮影しながら
  リモコン操作を行えば判る。赤外線が発射されるとピカーと光ります。)
電池切れと判断。
 
近くの電気屋に行ってボタン電池CR2025を買って取り付け。
KENWOODに向けて電源ボタンをON、ON、おん
効かない・・・
 
リモコンが治ればボリューム操作はこっちで出来るのでは?
と目論んでいたが残念。
 
ちなみに、スマホで撮影するとピカーと光るのでリモコン自体は動いている。
 
残るは本体。
さーてと、分解分解ー
 側面と後ろのネジを外して、カバーを開けて、
 さらに内部のネジを外して、
 前面パネルを外すと、前面パネルの裏に基盤がくっついていて、
 この基盤を外して確認。
ぎゃー、基盤が割れている。
写真

 
しかーし、これなら、電線追加して直せばいいと言うことで
ハンダゴテ、半田、半田コテ台、AWG24の電線、ワイヤーストリッパーを揃えて
修理。
 
 基板の割れは瞬間接着剤で固定して。
 電線を8本ほど追加して切れている回路を繋いで行く。
 30分ぐらいかな。
 ・
 ・
 ・
で、
 元通り組み立てて、どうだ。
リモコン電源ON、やったー電源入った。
 
本体のボリュームの操作も、リモコンからのいろいろな操作も出来るようになった。
 
成功だ。
 

後日、MDへの録音と再生も成功して、一通り動くことを確認。
Rakutenで中古価格を調べるとRDーESA5mdは13445円(税込)との事で
いい買い物と楽しい一日が過ごせました。