IOT再びーーーESP32編(4)

苦労しましたが,思った動作をさせることができました。
ESP32編(3)の諸兄の,超音波センサーで距離を測る関数を,書き換えました。

// 距離測定関数
float measureDistance() {
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);
 long duration = pulseIn(echoPin, HIGH);
 float distance = (duration * 0.0343) / 2;*/
 return distance;
}

この関数を

float measureDistance() {
 while (Serial.available()) {
   char inChar = (char)Serial.read();
   inputString += inChar;
   if (inChar == '\n') {
     distance=inputString.toFloat();
     inputString="";
     return distance;
   }
 }
 return distance;
}

のように変更して,動かしてみました。本来,センサーが受け持つ部分を,シリアルコンソールからの手動入
力に変えての動作確認です。
動画の右側のシリアルコンソールから,2→→4→→6→→8→→10 と入力を繰り返してます。入力に応じて,
iphoneのドーナツグラフが変化してくれます。
これで,第一段階の難関がクリアーです。

投稿日: 2024年7月3日 IOT再びーーーESP32編(3)ーSPIFFS不可

前掲の諸兄のスケッチ眺めてみましたが,ハンドラーの部分の記述と,html の javascript の部分がいま
いちわかりません。youtbe をあれこれ検索していましたら,別の諸兄の記事がめにとまりました。この諸兄の
スケッチなら,私用に改変できそうです。諸兄は,超音波を使ってますが,超音波だと,タンクに穴を開ける
必要がある気がしますので,超音波は使わないで当初の予定のように水位センサーを使ってやります。
ひとまず,諸兄のプログラムのオリジナルをインストールしてみます。

 

ところが,ところが,インストールに必要な,プラグインをIDEに取り込めません。一日,あれこれやりまし
たがやっとできました。
原因は,arduino IDE のバージョンで,使っていたV2.**ではだめで,v1.**で,やっとできました。
これが,分かるのに丸一日,インストールしていたarduino IDE 関係のフォルダーも全削除して,何回か
インストール,つかれました。
おかげで,やっと,下記の諸兄のスケッチをesp32に書き込み,テストできました。

// 必要なライブラリのインクルード
#include <WiFi.h>
#include <WebServer.h>
#include <SPIFFS.h>

// ピンの定義
#define trigPin 5 // 超音波センサのトリガーピン
#define echoPin 18 // 超音波センサのエコーピン

// WiFi接続情報
const char* ssid = "Your SSID";
const char* password = "Your Password";

// WebServerオブジェクトの初期化
WebServer server(80);

// セットアップ関数
void setup() {
  Serial.begin(115200); // シリアル通信の開始
  pinMode(trigPin, OUTPUT); // トリガーピンを出力として設定
  pinMode(echoPin, INPUT); // エコーピンを入力として設定

  // SPIFFSの初期化
  if(!SPIFFS.begin(true)){
    Serial.println("SPIFFSのマウントに失敗しました");
    return;
  }

  // WiFi接続
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // Webサーバーのルート設定
  server.on("/", HTTP_GET, []() {
    server.send(200, "text/html", SPIFFS.open("/index.html", "r").readString());
  });

  // '/distance'で距離を返す設定
  server.on("/distance", HTTP_GET, []() {
    server.send(200, "text/plain", String(measureDistance()));
  });

  server.begin(); // サーバーの開始
}

// メインループ
void loop() {
  server.handleClient(); // クライアントのリクエストを処理
}

// 距離測定関数
float measureDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duration = pulseIn(echoPin, HIGH);
  float distance = (duration * 0.0343) / 2;
  return distance;
}

 

スケッチは簡単ですが,HP掲載用のhtmlとjavascritpがやっかいのようですが,これもあまり手を加えずに済みそうです。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>水位計</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://code.highcharts.com/highcharts-more.js"></script>
    <script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            font-family: Arial, sans-serif;
            font-size: 20px;
        }
        #container {
            width: 90%;
            height: 50%;
        }
        .settings {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 20px;
        }
        .settings > div {
            margin: 0 10px;
        }
        .alert {
            display: none;
            color: red;
            text-align: center;
            position: absolute;
            width: 100%;
            bottom: 10%;
        }
        #title {
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 50px;
        }
    </style>
</head>
<body>
    <div id="title">Water Level monitoring</div>
    <div class="settings">
        
        <div>
            <label for="minDistance">0% Distance (cm): </label>
            <input type="number" id="minDistance" value="2">
        </div>
        <div>
            <label for="maxDistance">100% Distance (cm): </label>
            <input type="number" id="maxDistance" value="15">
        </div>
    </div>
    <div id="container"></div>
    <div id="alert" class="alert">Alert: The value is below 20%</div>

    
    <script>
        var minDistance = parseFloat(document.getElementById('minDistance').value);
        var maxDistance = parseFloat(document.getElementById('maxDistance').value);

        document.getElementById('minDistance').addEventListener('change', function() {
            minDistance = parseFloat(this.value);
            updateChart();
        });

        document.getElementById('maxDistance').addEventListener('change', function() {
            maxDistance = parseFloat(this.value);
            updateChart();
        });


        // Highchartsのゲージオプション設定
        var gaugeOptions = {
            chart: {
                type: 'solidgauge',
            },
            title: null,
            pane: {
                startAngle: -120,
                endAngle: 120,
                background: {
                    backgroundColor: '#EEE',
                    innerRadius: '60%',
                    outerRadius: '100%',
                    shape: 'arc'
                }
            },
            tooltip: {
                enabled: false
            },
            yAxis: {
                stops: [
                    [0.1, '#DF5353'], // 高い値で青系
                    [0.5, '#DDDF0D'], // 中間値で黄色
                    [0.9, '#55BF3B']  // 低い値で赤系
                ],
                lineWidth: 0,
                minorTickInterval: null,
                tickAmount: 2,
                min: 0,
                max: 100,
                title: null,
                labels: {
                    y: 16
                }
            },
            credits: {
                enabled: false
            },
            series: [{
                name: 'Distance',
                data: [100], // 初期値
                dataLabels: {
                    format: '<div style="text-align:center"><span style="font-size:30px">{y}%</span></div>'
                }
            }]
        };

        // Highchartsのゲージを作成
        var chart = Highcharts.chart('container', Highcharts.merge(gaugeOptions, {
            series: [{
                data: [100] // シリーズにも初期値をセット
            }]
        }));

        // ゲージの値を更新する関数
        function updateGauge(value) {
            // minDistanceとmaxDistanceを使用して値を計算
            var newVal = ((maxDistance - value) / (maxDistance - minDistance)) * 100;
            
            // newValが0未満の場合は0に、100を超える場合は100に制限する
            newVal = Math.max(0, Math.min(newVal, 100));    
            newVal = Math.round(newVal); // 小数点以下を四捨五入して整数に
            chart.series[0].points[0].update(newVal);

            // 値が20以下の場合、アラートを表示
            if (newVal <= 20) {
                document.getElementById('alert').style.display = 'block';
            } else {
                document.getElementById('alert').style.display = 'none';
            }
        }

        // ESP32からデータを取得してゲージを更新する
        // HTML内のJavaScriptの一部
        // HTML内のJavaScriptの一部
        setInterval(function () {
            fetch('/distance')
                .then(response => response.text())
                .then(distance => {
                var dist = parseFloat(distance);
                updateGauge(dist); // ゲージを更新する関数に距離データを渡す
                })
                .catch(function (error) {
                console.error('Error fetching distance:', error);
                });
        }, 1000); // 1秒ごとに更新
    </script>
</body>
</html>

この諸兄のいいところは,スケッチにhtmlの部分を含めるのではなく,htmlは別途esp32にアップロードでき
るところでしょうか。そのため,デバックのために,htmlを抜き出す必要もなく,htmlをそのままデバックで
きます。

IOT再びーーーESP32編(2)

前回,とりあえず,諸兄のスケッチ動かしみました。
このスケッチのhtml部分を書き換え,下記ようにして,スケッチの方で,それぞれのLの帯を順次消していけ
ば,目的を達成できるかなと考えました。

ただ,これでは,問題があるようで,サーバー側で,新しい情報をクライアントの方に送っても,クライア
ント側で更新を行わないと,画面が新しくならないみたいなので,このままでは,つかえないかなとおもい
ました。

いろいろあさってると,「非同期処理」が必要だとのHPを見つけました。これを改変すれば,目的が達成でき
そうな気がしてきました。
このHPのスケッチをDLして,自分の環境に合わせて,動かしてみました。温度センサーは以前買った,
Sensor Kit for Aruduinoというセット

に入ってた物をつかいました。
写真の下にあるのが,写真のものを動かしている諸兄のHPにあった,スケッチです。
もっともここよりも諸兄のHPに全文がのっていますので,そちらからDLした方がいいでし
ょうか。


/*
 * File:      WiFiMeasureAsync.ino
 * Function:  計測デバイスを非同期Webサーバーにして、クライアント画面に計測値を更新表示
 *            させる。
 * Date:      2020/02/12
 * Author:    M.Ono
 * 
 * Hardware   MCU:  ESP32 (DOIT ESP32 DEVKIT V1 Board)
 *            ブレッドボードに上記開発ボードと温湿度センサー、プッシュボタン、LEDを配線
 *            温湿度センサーはDHT11 
 *            ※今回はプッシュボタンとLEDは使用しない。
 */
 
#include <arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <DHT.h>                    // DHTセンサー用


/* Function Prototype */
String getTemperature();
String getHumidity();
String processor(const String&);
void doInitialize();
void connectToWifi();

// ルーター接続情報
#define WIFI_SSID "aterm-e4b126-g"
#define WIFI_PASSWORD "3d259dac2f80e"

/* 基本属性定義  */
#define SPI_SPEED   115200          // SPI通信速度
#define DHTTYPE     DHT11           // DHTセンサーの型式

// Webサーバーオブジェクト
#define HTTP_PORT 80
AsyncWebServer server(HTTP_PORT);

/* DHTセンサー*/
const int DHTPin = 14;                  // DHTセンサーの接続ピン
DHT   dht(DHTPin, DHTTYPE);             // DHTクラスの生成(初期化?)

/* HTMLページ */
const char* strHtml = R"rawliteral(
 <!DOCTYPE HTML>
 <html>
 <head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <style>
html { font-family: Helvetica; display: inline-block; margin: 0px auto;text-align: center;}
h1 {font-size:28px;}
body {text-align: center;}
table { border-collapse: collapse; margin-left:auto; margin-right:auto;}
th { padding: 12px; background-color: #0000cd; color: white; border: solid 2px #c0c0c0;}
tr { border: solid 2px #c0c0c0; padding: 12px;}
td { border: solid 2px #c0c0c0; padding: 12px;}
.value { color:blue; font-weight: bold; padding: 1px;}
 </style>
 </head>
 <body>
 <h1>Asynchronous Server </h1>
 <p style='color:brown; font-weight: bold'>計測値は 10 秒ごとに自動更新されます! </p>
 <p> <table>
 <tr> <th>ELEMENT </th> <th>VALUE </th> </tr>
 <tr> <td>Temperature </td> <td> <span id="temperature" class="value">%TEMPERATURE%
 </span> <tr> <td>Humidity </td> <td> <span id="humidity" class="value">%HUMIDITY% </span>
 </td> </tr>
 </table> </p>
 </body>
 <script>
var getTemperature = function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
};
xhr.open("GET", "/temperature", true);
xhr.send(null);
}
var getHumidity = function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("humidity").innerHTML = this.responseText;
}
};
xhr.open("GET", "/humidity", true);
xhr.send(null);
}
setInterval(getTemperature, 10000);
setInterval(getHumidity, 10000);
 </script>
 </html>)rawliteral";

/*****************************************************************************
 *                          Predetermined Sequence                           *
 *****************************************************************************/
void setup(){
    doInitialize();             // 初期化処理をして
    connectToWifi();            // Wi-Fiルーターに接続する

    // GETリクエストに対するハンドラーを登録して
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/html", strHtml, editPlaceHolder);
    });
    server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/plain", getTemperature().c_str());
    });
    server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/plain", getHumidity().c_str());
    });
    // サーバーを開始する
    server.begin();
}
 
void loop(){
}

/* 計測処理ロジック */
String getTemperature() {
    float t = dht.readTemperature();
    if (isnan(t)) {    
        Serial.println("Failed to get temperature!");
        return "--";
    }
    else {
        Serial.println(t);
        return String(t) + " ℃";
    }
}

String getHumidity() {
    float h = dht.readHumidity();
    if (isnan(h)) {
        Serial.println("Failed to get humidity!");
        return "--";
    }
    else {
        Serial.println(h);
        return String(h) + " %";
    }
}

/* プレースホルダー処理 */
String editPlaceHolder(const String& var){
    if(var == "TEMPERATURE"){
        return getTemperature();
    }
    else if(var == "HUMIDITY"){
        return getHumidity();
    }
    return "??";
}

/* 初期化処理 */
void doInitialize() {
    Serial.begin(SPI_SPEED);
    dht.begin();                       // DHTセンサーを起動
}

/****************************< Connect functions >****************************/
/* Wi-Fiルーターに接続する */
void connectToWifi() {
    Serial.print("Connecting to Wi-Fi ");
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    // モニターにローカル IPアドレスを表示する
    Serial.println("WiFi connected.");
    Serial.print("  *IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();
}

  }
}

IOT再びーーーESP32編

何年か前に,raspberry Pi を使って,スマホから,LED の制御を実験しました。

このと時は,raspberry Pi のプログラムが良く分からないところもあったので,結構手間がかかりました。
あることがやりたくで,再びIOTに挑戦することにしました。

手始めに,ESP32を使って,wify経由でのLチカです。

諸兄のスケッチをESP32に書き込み,ESP32にLEDをつけると,それほど手間がかからずにできます。
arduino・IDEのシリアル通信の画面に表示される,IPアドレスを,スマホのブラウザに打ち込むと,動画の
制御画面に入れます。
ブレッドボードには,ジャンパー線が多数見られますが,これは,前回までの作業の名残で,片付けていま
せん。


反応が鈍いようですが,多分,ルーターのためだと思います。
この,動画のスケッチをいじって,あれこれやる予定です。

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/
// Load Wi-Fi library
#include <WiFi.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";
// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}
void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected() && currentTime - previousTime <= timeoutTime) {  // loop while the client's connected
      currentTime = millis();
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>GPIO 26 - State " + output26State + "</p>");
            // If the output26State is off, it displays the ON button       
            if (output26State=="off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            // Display current state, and ON/OFF buttons for GPIO 27  
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button       
            if (output27State=="off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

このスケッチを改変するにあたって,これまた,丁寧に解説なさってる諸兄がいらっしゃいました。
おかげで,スケッチの構造がやっとおぼろげながら分かってきました。

チャタリング防止

PICやarduinoで,タクトスイッチ等の安物を使うと,話題に上るのがチャタリングです。チャタリングのこと
を考えないと思った動作をしなくなります。
通常は,シュミットトリガー回路に代表されるハードを使って取り除く方法や,ソフトで取り除くこと等が必
要のようです。ソフトでは,間をあけて何回か測定して判別する方法等があるようですが,あるHPで,ビット
シフトを使った方法がでていました。

#define MAXPIN 13

int checkbutton(int i){
   static byte val[MAXPIN];
   static byte state[MAXPIN];

   if(digitalRead(PIN[i]) == 1){
      val[i] = val[i]<<1;
      val[i] += digitalRead(PIN[i]);
   }else{
      val[i] = 0;
   }

   if(val[i] == B01111111){
      state[i] = 1 - state[i];
   }

   return state[i];
}

やはり,先達はすごい。い くつか変数を用意しておいて,古いデータと比べるということは考えつきますが,
ビットシフトを使うとは,すごいなと思いました。ただ,このプログラム,IDEでコンパイルすると

 B01111111→→0b01111111

と怒られます。ちょっとした勘違いなんでしょうね。「弘法も筆の誤り」ですね。

追記
 あと,シフトビットのいいところは,オーバーフローを気にしなくていいことでしょうか。シフトで
はみでた部分は,破棄されるようですので。ここを,int等の変数で足し算すると,オーバーフローの処置をいれないとPGが暴走しますので。

併せて,変数のスコープ等について,調べていたら,大きな勘違いをしていることに気がつきました。IDE
では,Loopの中にmainのプログラムを書きますが,一回だけ実施したい処理を次のように書きました。


loop(){
   int flag;
   if(flag==0){
      syori;//動作させたい処理
      flag=1;
   }
}

みたいな記述をしていましたが,思った動作はしませんでした。それもそのはず,loopの中で,
最後の「 }」の前で,変数が初期化されてしまうとのこと。これでは,思った動作をしませんね。
保持するには,

  int flag;→→static int flag;

のように,静的変数の宣言をしないとだめということが分かりました。これ,IDEの癖みたいなものでしょう
か。知らないとこまりますね。今まで,loopのなかの冒頭で,変数の宣言をしていましたが,これ,何回も
宣言することになって,なんだろうと,疑問にも思っていたところなので,この疑問も解決ですね。

赤外線リモコンリピーター(中継器)(3)

ESP32のリピーターですが,難航してます。とりあえず,信号を送ることはできるようですが,まず取り組ん
だのは,38kHzの変調をすることです。下記のようなスケッチで,波長を探りました。

 startTime = millis();
  for(unsigned long k=0;k<38000;k++){
    digitalWrite(IR_TRANS_PIN, HIGH);
    delayMicroseconds(11);   // キャリア周波数38kHzでON/OFFするよう時間調整
    digitalWrite(IR_TRANS_PIN, LOW);
    delayMicroseconds(14);   // キャリア周波数38kHzでON/OFFするよう時間調整
  }
  endTime=millis();


  Serial.println(endTime-startTime);

出力をハイにするための  delayMicroseconds(**); の括弧のなかの数値を調整して,計測時間が
1000msに近くなるように調整しました。その際,ピンの出力をHIGHにしたときと,LOWにしたときの
時間が,1:3(デュティ比1/3)になるようにしました。その後,実際に動かしてみて,リモコンで
機器が反応するように調整をしました。結果,デュティ比1/3では,反応せす,11:14 ぐらいで反応
しました。
リピーターとして動かすスケッチは至ってシンプルで,受光部からの信号が-の出力があるときだけ赤外
線をだせばいいので,

void loop() {
  while(digitalRead(IR_RECIVE_PIN) == 0 ) {   // 赤外線を検知=0, 検知していない=1
      digitalWrite(IR_TRANS_PIN, HIGH);
      delayMicroseconds(11);   // キャリア周波数38kHzでON/OFFするよう時間調整
      digitalWrite(IR_TRANS_PIN, LOW);
      delayMicroseconds(14);   // キャリア周波数38kHzでON/OFFするよう時間調整
  }
}

初期設定を除いたLOOPはこれだけです。
下記のようなPWMを発生するコマンドもあって,

ledcWriteTone(LEDC_CHANNEL,CARRIER_FREQ);

簡単に38Khzの信号がだせるのですが,このコマンドの後に何かをすると,うまく動かなくなります。
間に,delay(5) ぐらいの間をとらないとだめみたいなので,あまり好きではないのですが,使うのを
やめて

delayMicroseconds(**);

を使って,38kHzの信号を作成しました。

赤外線リモコンリピーター(中継器)(2)

ESP32を使った回路と,既存のレピーターを使った回路であれこれやっています。ESP32を使った回路はなか
なかうまくいきませんが,既存のレピーターを使った回路の改造は,比較的うまくいってます。

写真のように既存のものに,トランジスターをいれて,赤外線LEDをセットしました。この構成で,オリジ
ナルででは,コントロールできなかった,台所のLEDライトのコントロールができました。

回路図では,上記のようになります。手持ちの部品でいろいろやりましたが,2SA1015と2SC1815のトラン
ジスタを使ったものが比較的成績がいいです。この既存のレピーターの受信部は,多分オープンコレクタ
ーの構成になってるのかなと想像してます。できれば,このまま使いたいので,受信部の分解はしていま
せんが,どんな回路なのか興味のあるところです。
ESP32を使った方は,手こずっています。何とか,コントロールするところまで,はこぎ着けたのですが,
送信の赤外線LEDと コントロール する機器の距離がとれません。2SC1815で,増幅して使っているので
すが,うまくいきません。GPIO 端子の出力電流が足りないのか,そのためトランジスタのベースに十分
流せないのか,無い頭をなやませています。

ESP32 リセットを繰り返す 問題

ちまたで結構話題のある表題の問題にぶち当たりました。使い始めた頃は,何の疑問も持ちませんでしたが,
シリアルモニターで確認すると,リセットを繰り返す症状に我慢ができなくなりました。
同じ問題で,悩んでいらっる方も結構いるようで,その対処方については,いろいろのっていました。その
全部をやりましたが,結局それらの方法では,だめでした。やったのは,次のような方法です。

1--Flash Frequency を 80Hz から 40Hz に下げて書き込む。
2--Flash Mode を QIO から DIO に変更する。
3--USBケーブルを太い物に変える。
4--フラッシュメモリーをクリアーする。
5--別なESP32で実行する

結果どれも効果がありませんでした。ただ,4番目のフラッシュメモリ-のクリアーについては,多少苦労し
しましたので,ちょっと補足。下記の命令を WINDOWS のコマンドプロンプトから打つのですが,

esptool.exe –chip esp32 –port COM6 –baud 921600 erase_flash

コマンドプロンプトを開いて,そのままでは,エラーが帰ってきます。このままでは,esptool.exe のおい
てあるるフォルダーへのパスが通ってないので,エラーになります。こうならないように,
カレントディレクトリーを移動してやらないとだめです。私の環境では,

\Users\*******\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\4.5.1

という深い位置に,esptool.exe はありますので,

cd \Users\*******\AppData\Local\Arduino15\packages\esp32\tools\esptool_py\4.5.1

というように cd (チェンジディレクトリー)のコマンドで,移動した後に,上記の esptool.exe を
実行します。比較的最近始められた方は、コマンドプロンプトの使い方なれてないでしょうから、苦労する
かなと思います。詳しいわけではないのですが、大昔に、MS-DOS を経験していますので、それほど苦労せ
ずに、実行できました。ただ、ディレクトリー(フォルダー)を移動するにあたって、階層が深いので、
全部打ち込むのは間違いも多く面倒なので、esptool.exe のプロパティを開いて、場所 から、
ディレクトリーをコピーしたものをテキストエディターにはりつけておいて、それをされにコピーして、
コマンドプロンプトにペーストするという方法で、やりました。

しかし、このいずれもだめでしたが、ふとしたことで、ある方のHPをみて、変更してみるとあっけなく解消
できました。

Event Run On Core0 →→ Core1
Arduino Run On Core0 →→ Core1

に変更したところ、あっけなく解消しました。デフォルトの設定はわかりませんし、どの設定で使うのが正解
なのかはわかりませんが、取り合えず解消しました。あとで、分かったことなのですが、ESP32はデュアルコ
アなので、高性能な反面、設定等、私みたいな、新参者には難しいのかなと感じました。

ESP32 MAX7219 DS1307 時計表示

ESP32をいじってます。MAX7219のドライブの8桁7セグLEDを時計風にしてみました。マトリックスのLED
ではNETより時刻を取得して表示していましたが,今回は,DS1307のRTCのモジュールを使ってみました。

このモジュールについては,諸兄が詳しくHPに掲載していますので,そちらが参考になりますので,覚え
書きに記録します。使うにあたって,諸兄のHPを参考に,基板上のダイオードと抵抗をはずしました。
このモジュールは,バックアップ用に,充電式のボタン電池を使う仕様になっているので,非充電用の
ボタン電池を使うと不具合が起こるようなので,通常のボタン電池で,使えるようにしました。また,
このモジュールをESP32に使うのに〇ZON購入のレベルシフターを使いました。

SWITCHSIENCEで以前に購入したものは保持していたのですが,1つしかなかったので,購入しましたが,
6個中2個が不良でした。安いので,こんなもんでしょうかね。RTCのモジュールは,3.3Vでも動き
ましたが,シフターをはさみました。

動画のような表示ですが,シリアルコンソールから,’y’の入力で,西暦と月を,’m’の入力で,月と
日にちと曜日を表示するようにしました。もっとも,曜日は,数字のままで,今日は,日曜日なので,
0の表示です。
RTCもモジュールは,はじめに初期設定の時刻を書き込みますが,ネットより時刻を取得して,それを
書き込むようにしてあります。下記のようなスケッチですが,使ってない関数もあります。

#include <SPI.h>
#include <Wire.h>
#include <time.h>
#include <WiFi.h>


//時刻設定
#define JST     3600* 9
#define RTC_address 0x68


//DS1307設定
//const char *week[] = {"日","月","火","水","木","金","土"};
const char *week[] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};

uint8_t REG_table[8];

// MAX7219 Command address
#define MAX7219_TEST 0x0f
#define MAX7219_BRIGHTNESS 0x0a
#define MAX7219_SCAN_LIMIT 0x0b
#define MAX7219_DECODE_MODE 0x09
#define MAX7219_SHUTDOWN 0x0C

//SPI設定
#define CS_PIN 5//CLK 18 DIN 23
#define LED_CLK 18
#define LED_DIN 23

//Wifys接続設定

const char* ssid = "***************";
const char* password = "**************";
//const char* ssid = "*****************";
//const char* password = "**************";

struct tm timeInfo;//時刻を格納するオブジェクト
char s[30];//時刻文字格納用

/***********************************************************
*SPIデータ送信--SPIライブラリー使用
*
************************************************************/
void maxTransfer(uint8_t address, uint8_t value) {
   digitalWrite(CS_PIN, LOW);  // Start transfer.
   SPI.transfer(address);      // Send address.
   SPI.transfer(value);        // Send the value.
   //digitalWrite(CS_PIN, HIGH); // Finish transfer.
}

/**********************************************************
*MAX7219初期設定
*
***********************************************************/
void MAX7219_INI(){
   maxTransfer(MAX7219_DECODE_MODE, 0b11011011);// 3.4はデコードしない
      digitalWrite(CS_PIN, HIGH);  
   maxTransfer(MAX7219_BRIGHTNESS, 0x01); // Use lowest intensity.
      digitalWrite(CS_PIN, HIGH);  
   maxTransfer(MAX7219_SCAN_LIMIT, 0x07); // Display digits 01234567
      digitalWrite(CS_PIN, HIGH);

   maxTransfer(MAX7219_SHUTDOWN, 0x01);    // Normal Operation
      digitalWrite(CS_PIN, HIGH);  
   maxTransfer(MAX7219_TEST, 0x00);        // Normal Operation
      digitalWrite(CS_PIN, HIGH);  
}

/******************************************************************
*今回使った書き込み関数
*
*******************************************************************/
void LED_OUT(uint8_t addr, uint8_t dat){
  digitalWrite(CS_PIN, LOW);
  shiftOut(LED_DIN, LED_CLK, MSBFIRST, addr);
  shiftOut(LED_DIN, LED_CLK, MSBFIRST, dat);
  digitalWrite(CS_PIN, HIGH);
}

/********************************************************************
*int ch_to_int(char,char)
*
*********************************************************************/
int ch_to_int(char a,char b){

  int buff;
  int c=a-'0';//charをintに変換
  int d=b-'0';//charをintに変換
  buff=(c<<4) | d;
  return buff;  
}


/********************************************************************
*7セグ初期化
*
*********************************************************************/
void sevn_seg_init(){
  LED_OUT(0x9, 0b11011011);   //7セグでデコードするビットに1を立てる:
  LED_OUT(0xA, 5);   //輝度を設定, 0-15:
  LED_OUT(0xB, 7);    //使用する桁数を指定, 桁数-1:
  LED_OUT(0xC, 1);    //特にいじる必要なし:
  LED_OUT(0xF, 0);    //同上:
}
/************************************************************************************************************************************
*Set up
*
**********************************************************************/
void setup() {
 
  Wire.begin();
  Serial.begin(115200);


  pinMode(CS_PIN,  OUTPUT);
  pinMode(LED_CLK, OUTPUT);
  pinMode(LED_DIN, OUTPUT);
 
  digitalWrite(CS_PIN,  HIGH);
  digitalWrite(LED_CLK, LOW);
  digitalWrite(LED_DIN, LOW);


//Wify接続
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.println();
  Serial.printf("Connected, IP address: ");
  Serial.println(WiFi.localIP());


 //Netより時刻を取得
  configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
  getLocalTime(&timeInfo);//tmオブジェクトのtimeInfoに現在時刻を入れ込む
  sprintf(s, " %04d/%02d/%02d %02d:%02d:%02d:%02d",
          timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
          timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec,timeInfo.tm_wday);//人間が読める形式に変換
  delay(800);


Serial.print(s[1]);//西暦
Serial.print(s[2]);
Serial.print(s[3]);
Serial.print(s[4]);
Serial.print("-");
Serial.print(s[6]);//月
Serial.print(s[7]);
Serial.print("-");
Serial.print(s[9]);//日
Serial.print(s[10]);
Serial.print("-");
Serial.print(s[12]);//時
Serial.print(s[13]);
Serial.print("-");
Serial.print(s[15]);//分
Serial.print(s[16]);
Serial.print("-");
Serial.print(s[18]);//秒
Serial.print(s[19]);
Serial.print(s[20]);
Serial.print(s[21]);
Serial.println(s[22]);
//Serial.println(s[23]);

//RTCに現在時刻データを書き込む
  Wire.beginTransmission(RTC_address);
  Wire.write(0x00);//Register 先頭アドレス
  Wire.write(ch_to_int(s[18],s[19]));//second
  Wire.write(ch_to_int(s[15],s[16]));//minute
  Wire.write(ch_to_int(s[12],s[13]));//hour
  Wire.write(s[22]-'0');//week  
  Wire.write(ch_to_int(s[9],s[10]));//day
  Wire.write(ch_to_int(s[6],s[7]));//month
  Wire.write(ch_to_int(s[3],s[4]));//year
  Wire.endTransmission();

  digitalWrite(CS_PIN,  HIGH);
  digitalWrite(LED_CLK, LOW);
  digitalWrite(LED_DIN, LOW);
 
  LED_OUT(0x9, 0b11011011);   //7セグでデコードするビットに1を立てる:
  LED_OUT(0xA, 5);   //輝度を設定, 0-15:
  LED_OUT(0xB, 7);    //使用する桁数を指定, 桁数-1:
  LED_OUT(0xC, 1);    //特にいじる必要なし:
  LED_OUT(0xF, 0);  
 
 //7セグ初期設定
  //sevn_seg_init();


//7セグに表示
  LED_OUT(0x3, 1);            //3ケタ目'-'
  LED_OUT(0x6, 1);            //6ケタ目'-'
}


char h_on=1;
char y_on=0;
char m_on=0;

/*****************************************************************
*メインループ
*
******************************************************************
void loop() {


  char inkey;


  Wire.beginTransmission(RTC_address);
  Wire.write(0x00);//Register 先頭アドレス
  Wire.endTransmission();


//RTCデータの読み込み
  Wire.requestFrom(RTC_address,7);


  for(int i=0;i<=7;i++){
    REG_table[i]=Wire.read();
  }


if( Serial.available() > 0  ) {
    inkey = Serial.read();
    switch (inkey){
      case 'h':h_on=1;
               y_on=0;
               m_on=0;
               break;
      case 'y':h_on=0;
               y_on=1;
               m_on=0;
               break;
      case 'm':h_on=0;
               y_on=0;
               m_on=1;
               break;    
    }
  }



if(h_on==1){//時分秒を表示
  LED_OUT(0x9, 0b11011011);


  LED_OUT(0x1, REG_table[0]); //秒を表示
  LED_OUT(0x2, REG_table[0]>>4);//10秒を表示


  LED_OUT(0x3, 1);


  LED_OUT(0x4, REG_table[1]);//分を表示
  LED_OUT(0x5, REG_table[1]>>4);//分を表示


  LED_OUT(0x6, 1);


  LED_OUT(0x7, REG_table[2]);//時を表示
  LED_OUT(0x8, REG_table[2]>>4);//時を表示
}


if(y_on==1){//年号月の表示
    LED_OUT(0x9, 0b11111111);
    LED_OUT(0x8,2);
    LED_OUT(0x7,0);
    LED_OUT(0x6,REG_table[6]>>4);
    LED_OUT(0x5,REG_table[6]);
    LED_OUT(0x4,0xF);
    LED_OUT(0x3,0xF);
    LED_OUT(0x2,REG_table[5]>>4);
    LED_OUT(0x1,REG_table[5]);
}
if(m_on==1){//月日曜日の表示
    LED_OUT(0x9, 0b11111111);
    LED_OUT(0x8,REG_table[5]>>4);//月
    LED_OUT(0x7,REG_table[5]);
    LED_OUT(0x6,0xF);
    LED_OUT(0x5,REG_table[4]>>4);//日
    LED_OUT(0x4,REG_table[4]);
    LED_OUT(0x3,0xF);
    LED_OUT(0x2,REG_table[3]);//曜日
    LED_OUT(0x1,0xF);
}


}

MAX7219の使い方8×8LCD無ライブラリー(9)ESP32編

この4日~5日の間,頭をさんざん悩ませていました。何のことはない,数字のを上から落ちてくるようにし
たくて,あれこれなやんでしました。特に,この二日間は,散歩しながらも,うまくいかない原因を考えては
,手直しを考える。散歩が終わってからは実際に修正してみる,の繰り返しをしてました。今日,やっと思っ
た動作ができるよいうになりました。スケッチのアルゴリズム(手順)は,ほぼ間違いなかったのですが,
順番を間違っていました。本来ならば,

  保持しているメモリの移動→→新しい書き込み

の順でしなければならないのに,

  書き込み→メモリーの移動

の順にしてました。完成したときは,思わず,やった,と叫びそうになりました。

動画のような動作になりますが,一秒の表示のところが,時々,数字が飛びます。これは,処理の関係で仕方
ないのかなと思います。スケッチは,ほとんどが,bit の操作で,今回は,備え付けの関数を使わないで,
or と and で処理しました。冗長なスケッチですが,次のものが,数字をセットする部分のスケッ
チです。

/**************************************************************
*number_set_V_T(int y,int x,string num)
*
***************************************************************/
void number_set_V_T(int y,int x,char ch){
 
  int num;
  unsigned char buff;
  unsigned char buff_suji;


  if(ch=='0'){num=0;}
  if(ch=='1'){num=1;}
  if(ch=='2'){num=2;}
  if(ch=='3'){num=3;}
  if(ch=='4'){num=4;}
  if(ch=='5'){num=5;}
  if(ch=='6'){num=6;}
  if(ch=='7'){num=7;}
  if(ch=='8'){num=8;}
  if(ch=='9'){num=9;}
  if(ch=='A'){num=10;}


  int u_num=(x-1)/8+1;
  if((x % 8)==0){
     x=8;
  }
  else{
     x=x % 8;
  }


  switch (x){    
      case 8:
        for(int n=7;n>=0;n--){
          v_shift_T(u_num,x);


          buff_suji=suuji[num][n];
          buff_suji=buff_suji<<2;//数字を2ビットシフト
          dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b00011111;
          dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
          dummy[8-n]=dot_hoji[u_num][1];


          dot_hyouji(u_num);
          delay(TM);
         
        }
        break;
      case 7:
        for(int n=7;n>=0;n--){
           v_shift_T(u_num,x);


          buff_suji=suuji[num][n];
          buff_suji=buff_suji<<1;//数字を2ビットシフト
          dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b10001111;
          dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
         
          dot_hyouji(u_num);
          delay(TM);
         
        }
        break;      
      case 6:
        for(int n=7;n>=0;n--){
           v_shift_T(u_num,x);


          buff_suji=suuji[num][n];
          dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11000111;
          dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
         
          dot_hyouji(u_num);
          delay(TM);
        }
        break;
      case 5:
       for(int n=7;n>=0;n--){
          v_shift_T(u_num,x);


          buff_suji=suuji[num][n];
          buff_suji=buff_suji>>1;//数字を右に1ビットシフト
          dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11100011;
          dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
         
          dot_hyouji(u_num);
          delay(TM);
        }
        break;      
      case 4:
        for(int n=7;n>=0;n--){
          v_shift_T(u_num,x);


          buff_suji=suuji[num][n];
          buff_suji=buff_suji>>2;//数字を右に2ビットシフト
          dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11110000;
          dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;


          dot_hyouji(u_num);
          delay(TM);
        }
        break;  
      case 3:
        for(int n=7;n>=0;n--){
          v_shift_T(u_num,x);


          buff_suji=suuji[num][n];
          buff_suji=buff_suji>>3;//数字を右に3ビットシフト
          dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11111000;
          dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
         
          dot_hyouji(u_num);
          delay(TM);
        }
        break;
      case 2:
        if(u_num>1){
          for(int n=7;n>=0;n--){
            v_shift_T(u_num,x);


            buff_suji=suuji[num][n];
            buff_suji=buff_suji>>4;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11111100;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
           
            buff_suji=suuji[num][n];
            buff_suji=buff_suji<<4;
            dot_hoji[u_num-1][1]=dot_hoji[u_num-1][1] & 0b01111111;
            dot_hoji[u_num-1][1]=dot_hoji[u_num-1][1] | buff_suji;


            dot_hyouji(u_num);
            delay(TM);
          }
        }
        else{
          for(int n=7;n>=0;n--){
            v_shift_T(u_num,x);


            buff_suji=suuji[num][n];


            buff_suji=buff_suji>>4;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11111100;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
            buff_suji=suuji[num][n];


            dot_hyouji(u_num);
            delay(TM);
          }
        }
        break;
      case 1:
        if(u_num>1){
          for(int n=7;n>=0;n--){
            v_shift_T(u_num,x);


            buff_suji=suuji[num][n];
           
            buff_suji=buff_suji>>5;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11111110;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
           
            buff_suji=suuji[num][n];
            buff_suji=buff_suji<<3;
            dot_hoji[u_num-1][1]=dot_hoji[u_num-1][1] & 0b00111111;
            dot_hoji[u_num-1][1]=dot_hoji[u_num-1][1] | buff_suji;


            dot_hyouji(u_num);
            delay(TM);
          }
        }
        else{
          for(int n=7;n>=0;n--){
             v_shift_T(u_num,x);


            buff_suji=suuji[num][n];
            buff_suji=buff_suji>>5;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] & 0b11111110;
            dot_hoji[u_num][1]=dot_hoji[u_num][1] | buff_suji;
           
            dot_hyouji(u_num);
            delay(TM);
          }
        }
        break;      
  }
}

次が,メモリーをシフトする部分のスケッチです。

/**************************************************************
*void v_shift_T(int u_num,x)
*
****************************************************************/
void v_shift_T(int u_num,int x){
  unsigned char buff=0;
  unsigned char buff1=0;
 
 switch (x){
    case 8:
       for(int n=8;n>1;n--){
        buff=dot_hoji[u_num][n-1] & 0b11100000;
        buff1=dot_hoji[u_num][n] & 0b00011111;
        dot_hoji[u_num][n]=buff | buff1;
      }
      break;
    case 7:
      for(int n=8;n>1;n--){
        buff=dot_hoji[u_num][n-1] & 0b01110000;
        buff1=dot_hoji[u_num][n] & 0b10001111;
        dot_hoji[u_num][n]=buff | buff1;
      }
      break;    
    case 6:
      for(int n=8;n>1;n--){
        buff=dot_hoji[u_num][n-1] & 0b00111000;
        buff1=dot_hoji[u_num][n] & 0b11000111;
        dot_hoji[u_num][n]=buff | buff1;
      }
      break;
    case 5:
      for(int n=8;n>1;n--){
        buff=dot_hoji[u_num][n-1] & 0b00011100;
        buff1=dot_hoji[u_num][n] & 0b11100011;
        dot_hoji[u_num][n]=buff | buff1;
      }
      break;
    case 4:
      for(int n=8;n>1;n--){
        buff=dot_hoji[u_num][n-1] & 0b00001110;
        buff1=dot_hoji[u_num][n] & 0b11110001;
        dot_hoji[u_num][n]=buff | buff1;
      }
      break;
    case 3:
        for(int n=8;n>1;n--){
          buff=dot_hoji[u_num][n-1] & 0b00000111;
          buff1=dot_hoji[u_num][n] & 0b11111000;
          dot_hoji[u_num][n]=buff | buff1;
        }
        break;
    case 2:
        if(u_num>1){


          for(int n=8;n>1;n--){
            buff=dot_hoji[u_num][n-1] & 0b00000011;
            buff1=dot_hoji[u_num][n] & 0b11111100;
            dot_hoji[u_num][n]=buff | buff1;


            buff=0;
            buff1=0;


            buff=dot_hoji[u_num-1][n-1] & 0b10000000;          
            buff1=dot_hoji[u_num-1][n] & 0b01111111;
            dot_hoji[u_num-1][n]=buff | buff1;
          }
        }
        else{
          for(int n=8;n>1;n--){
            buff=dot_hoji[u_num][n-1] & 0b00000011;
            buff1=dot_hoji[u_num][n] & 0b11111100;
            dot_hoji[u_num][n]=buff | buff1;
          }
        }
        break;
    case 1:
      if(u_num>1){
          for(int n=8;n>1;n--){
            buff=dot_hoji[u_num][n-1] & 0b00000001;
            buff1=dot_hoji[u_num][n] & 0b11111110;
            dot_hoji[u_num][n]=buff | buff1;


            buff=dot_hoji[u_num-1][n-1] & 0b11000000;          
            buff1=dot_hoji[u_num-1][n] & 0b00111111;
            dot_hoji[u_num-1][n]=buff | buff1;
          }
        }
        else{
          for(int n=8;n>1;n--){
            buff=dot_hoji[u_num][n-1] & 0b00000001;
            buff1=dot_hoji[u_num][n] & 0b11111110;
            dot_hoji[u_num][n]=buff | buff1;
          }
        }
      break;            
  }
}

かなり頭を悩ませましたが,やっとできて,ほっとしてます。こうやって,ああでもないこうでもないとあれ
これ考えることはとってもいいぼけ防止になってるるかなと思います。