リレーモジュール にて調べました。Arduinoでシリアル通信 の "シリアル通信でリレーモジュールを操作するプログラム" をそのまま書き込んでいます。フォトレジスタで明るさを測定する での回路を使用しています。Arduinoでシリアル通信 のソフトを改造していきます。Option Explicit
Dim data(30)  As Long
Dim ptr As Integer
Private Sub Class_Initialize()
    Dim i As Integer
    For i = 0 To 30
        data(i) = -1
    Next i
End Sub
'移動平均を計算する -1は無視される
Function average(str_val As String) As Long
    Dim val As Long
    On Error GoTo err
    val = CLng(str_val)
    On Error GoTo 0
    If -1 <> val Then
        data(ptr) = val
        If 30 - 1 = ptr Then
            ptr = 0
        Else
            ptr = ptr + 1
        End If
        Dim i As Integer
        Dim pos As Long
        pos = 0
        For i = 0 To 30 - 1 Step 1
            If -1 <> data(i) Then
                pos = pos + data(i)
            Else
                Exit For
            End If
        Next i
        average = Int(pos / i)
        Exit Function
    End If
err:
    average = val
End Function
 shoumei_20230617.zip Option Explicit
Dim timer As Long
Dim power_change As Integer
Dim power_real As Integer
Private Sub Class_Initialize()
    power_change = 1
    timer = 0
End Sub
'タイマーを減算する、現実の出力が変化したらリセットする
Public Sub clock(real As Integer)
    If timer <> 0 Then
        timer = timer - 1
    Else
        timer = 0
    End If
    If power_real <> real Then
        power_real = real
        timer = 0
    End If
End Sub
'出力の変化を要請
Public Property Let Power(change As Integer)
    If power_change = 1 And change = 0 Then
        power_change = 0
        'リレーがON状態からOFFの要請
        timer = 60 / 2 '60秒のタイマーセット
    ElseIf power_change = 0 And change = 1 Then
        power_change = 1
        'リレーがOFF状態からONの要請
        timer = (10 * 60) / 2 '10分のタイマーセット
    End If
End Property
'出力の状態を取得
Public Property Get Power() As Integer
    If timer = 0 Then
        Power = power_change
    Else
        Power = power_real
    End If
End Property
'タイマーのリセット
Public Sub reset()
    timer = 0
End Sub
 'センサーの値を判定する sensor センサーの値 real_output 現在の出力 enable 有効/無効
Public Function calc(sensor As Long, real_output As Integer, enable As Integer) As Integer
    If 1 = enable Then
        If sensor > 400 Then
            calc = 0
        ElseIf sensor < 350 Then
            calc = 1
        Else
            calc = real_output
        End If
    Else
        calc = 0
    End If
End Function
 shoumei_20230620.zip auto_control_digital_pin(0) = 0 '自動制御にて関数開始状態を設定する変数 初期値:0
Public auto_control_func_next_state_setting As Integer
Public Const NONE_SETTING = 0 '何もしない
Public Const ENABLE_SETTING_1 = 1 '有効
Public Const DISABLE_SETTING_0 = -1 '無効 threshold.setThreshold(650, 0) shoumei_20230624.zip 線形補間 にて事前にVB6用のコードを作成しました。Option Explicit
Dim threshold_ As New threshold
Dim map1() As Variant
Dim map1_w As Long
Private Sub Class_Initialize()
    '数列の作成
    map1 = Array( _
    0, 900, 1100, 1300, 1500, 2400, _
    380, 380, 385, 385, 380, 380 _
    )
    '数列の幅を計算
    map1_w = (UBound(map1) + 1) / 2
End Sub
'線形補間のマクロ
Private Function INTERP(xi As Long, xi1 As Long, yi As Long, yi1 As Long, x As Long) As Long
    INTERP = (yi + (((yi1 - yi) * (x - xi)) / (xi1 - xi)))
End Function
'線形補間 x:補間する値 ar:数列 w:数列の横の長さ
Private Function interp1dim(x As Long, ByRef ar_() As Variant, w As Long) As Long
    Dim i As Long
    'xの値が範囲外の場合はxが最大最小値の値を返す
    If x <= ar_(0) Then
        interp1dim = ar_(w)
        Exit Function
    ElseIf x >= ar_(w - 1) Then
        interp1dim = ar_(w * 2 - 1)
        Exit Function
    End If
    For i = 0 To (w - 1) Step 1
        If ar_(i) >= x Then Exit For
    Next i
    ' y=yi + (yi+1-yi)(x-xi)/(xi+1-xi) を行い値を返す
    interp1dim = INTERP(CLng(ar_(i - 1)), CLng(ar_(i)), CLng(ar_(i + w - 1)), CLng(ar_(i + w)), x)
End Function
'センサーの値を判定する sensor センサーの値 real_output 現在の出力 enable 有効/無効
Public Function calc(sensor As Long, real_output As Integer, enable As Integer) As Integer
    Dim str As String
    str = Format(Now, "HH:MM:ss")
    Dim m, h, v, pos As Long
    m = CLng((CLng(Mid(str, 4, 2)) / 60) * 100)
    h = CLng(Mid(str, 1, 2) & "00")
    v = h + m
    pos = interp1dim(CLng(v), map1, map1_w)
'Form1.Caption = CStr(pos) + " " + CStr(350) 'デバッグのため
    Call threshold_.setThreshold(pos, 350)
    calc = threshold_.calc(sensor, real_output, enable)
End Function
 shoumei_20230713.zip Private Sub share_data_file(str As String, filename As String) version 0_14_4_1 ■ 人間の明るさの感じ方の解釈の修正 トップページ の「ご意見ご感想」からメールを送って教えていただけるとうれしいです。色々考察した結果、[2匹目の悪魔] の復帰(消灯)には作業者に気が付かれないように(ゆっくりと)消灯する必要があり、調光機能付き照明設備でないと実現できない為、あきらめました。 オッカムの剃刀 」的な物だと思っています。    '季節の変化によるオフセット値
    map1_Season = Array( _
        '1月 2月   3月   4月  5月  6月  7月  8月   9月  10月  11月 12月  全部21日基準
      0, 20,  51,  79,  110, 140, 171, 201, 232,  263,  293,  324, 354, 366, _
    -30,-30, -20, -15,   -7,   0,   0,   0,  -7,  -15,  -20,  -30, -30, -30  _
    )
 線形補間 を行い、年初からの日数により値を求めて日々の制御の閾値を動的に変更していきます。フォトレジスタで明るさを測定する  の回路を使っていますが、アナログ回路ですので同じものを複製できません。GY-30 照度センサー  を取り付けてアナログ値と明るさを表す単位のルクスの相関がわかるグラフを作成します。GY-30 照度センサー  の回路と同様に接続しました。
#include <avr/wdt.h>
#include <Wire.h>
//GY-30 接続先のアドレス
#define ADDRESS 0b00100011
unsigned char buff_gy30[10];
 
#define SYSTEM_TIMEOUT 60  //通信途絶後60秒で初期化
#define BUF_SIZE 255
void setup() {
  wdt_enable(WDTO_4S);  //WDTを4秒で設定し有効化
  //デジタルピン2番から11番まで出力に設定
  for (int i = 2; i < 12; i++) {
    pinMode(i, OUTPUT);
  }
  Serial.begin(9600, SERIAL_8E1);  //偶数パリティ
  Wire.begin();
  Wire.beginTransmission(ADDRESS);
  Wire.write(0b00010000);
  Wire.endTransmission();
 
  serial_wdt_reset();
}
char buff[BUF_SIZE];
char buff_old[BUF_SIZE];
char pin_status[11] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '\0' };  //デジタルピン2番から11番の状態を保持し一度に転送
unsigned int str_pt;
unsigned long int timeout_timer;
//ピンの状態をまとめて転送
void trans_pin_status() {
  int j = 0;
  for (int i = 2; i < 12; i++) {
    if (pin_status[j] == '1') {
      digitalWrite(i, LOW);  //出力先がアクティブローのため反転
    } else {
      digitalWrite(i, HIGH);
    }
    j++;
  }
}
//ピンに転送前の元データを初期化する
void reset_pin_status() {
  for (int i = 0; i < 10; i++) {
    pin_status[i] = '0';
  }
  pin_status[10] = '\0';
}
unsigned long serial_wdt_counter;
//シリアル通信がSYSTEM_TIMEOUT秒停止した場合に出力をリセットする
void serial_wdt() {
  unsigned long pos = ((unsigned long)millis()) - serial_wdt_counter;
  if (pos > ((unsigned long)((unsigned long)SYSTEM_TIMEOUT * 1000))) {
    reset_pin_status();  //タイムアウトしているため初期化
  }
}
//リセットタイマーをリセットする
void serial_wdt_reset() {
  serial_wdt_counter = millis();
}
void loop() {
  wdt_reset();  //WDTのリセット
  serial_wdt();
  if (Serial.available()) {
    char c = char(Serial.read());
    timeout_timer = millis();  //msを取得
    buff[str_pt] = c;
    str_pt++;
    if (c == '\n') {  //LFを終端文字とする
      buff[str_pt] = '\0';
      if (strcmp(buff_old, buff)) {
        //比較文字列と違うため保存
        strcpy(buff_old, buff);
        Serial.println("NG");
      } else {
        //比較文字列と同じため命令を実行
        if (buff[0] == 'w') {
          int j = 0;
          for (int i = 1; i <= 10; i++) {
            if (buff[i] == '1') {
              pin_status[j] = '1';
            } else {
              pin_status[j] = '0';
            }
            j++;
          }
          Serial.println("OK");
          serial_wdt_reset();
        } else if (buff[0] == 'r') {
          //2回出力
          Serial.print("r,");
          Serial.println(pin_status);
          Serial.print("r,");
          Serial.println(pin_status);
          serial_wdt_reset();
        } else if (buff[0] == 'a') {
          static unsigned long c;
          int _ar[6];
          _ar[0] = analogRead(A0);
          _ar[1] = analogRead(A1);
          _ar[2] = analogRead(A2);
          _ar[3] = analogRead(A3);
          _ar[4] = analogRead(A4);
          _ar[5] = analogRead(A5);
          Serial.print("a,");
          for (int i = 0; i < 6; i++) {
            Serial.print(_ar[i]);
            Serial.print(',');
          }
          Serial.println(c);
          Serial.print("a,");
          for (int i = 0; i < 6; i++) {
            Serial.print(_ar[i]);
            Serial.print(',');
          }
          Serial.println(c++);
          serial_wdt_reset();
        } else if (buff[0] == 'x') {
          unsigned char*buf_pt;
          buf_pt = buff_gy30;
          Wire.requestFrom(ADDRESS, 2); //接続し2byte取得する
          while (Wire.available()) {
            *buf_pt++ = (unsigned char)Wire.read();
          }
          if ((buf_pt - buff_gy30) >= 2) {
            unsigned short pos;
            pos = buff_gy30[0] << 8;
            pos = pos + buff_gy30[1];
            pos = pos / 1.2;
            Serial.print("x,");
            Serial.println(pos);
            Serial.print("x,");
            Serial.println(pos);
          } else {
            Serial.println("NG");
          }
          serial_wdt_reset(); 
        } else if (buff[0] == 't') {
          Serial.println("NG");
        }
        buff_old[0] = '\0';  //命令が終了したため旧命令は破棄
      }
      str_pt = 0;
    }
    //バッファサイズを超えないようにする
    if (str_pt >= BUF_SIZE) {
      str_pt = 0;
    }
  } else {
    //データを受信せずに500ms経過した場合にはタイムアウトで初期化
    if (str_pt) {
      if ((millis() - timeout_timer) > 500) {
        str_pt = 0;
      }
    }
  }
  trans_pin_status();
}
 Private Sub Timer1_Timer()
    If sleep_timer1 > 0 Then 'timer1を一時的に停止する
        sleep_timer1 = sleep_timer1 - 1
        Exit Sub
    End If
On Error GoTo Err1
    Do
        MSComm1.Output = "r" & vbCr & vbLf
    Loop While MSComm1.OutBufferCount >= 1
    Do
        MSComm1.Output = "r" & vbCr & vbLf
    Loop While MSComm1.OutBufferCount >= 1
    Do
        MSComm1.Output = "a" & vbCr & vbLf
    Loop While MSComm1.OutBufferCount >= 1
    Do
        MSComm1.Output = "a" & vbCr & vbLf
    Loop While MSComm1.OutBufferCount >= 1
    
    Do
        MSComm1.Output = "x" & vbCr & vbLf
    Loop While MSComm1.OutBufferCount >= 1
    Do
        MSComm1.Output = "x" & vbCr & vbLf
    Loop While MSComm1.OutBufferCount >= 1 
On Error GoTo 0
    Dim str As String
    Dim st_arry() As String 
    Do While data_ptr <> 0
        str = pop()
        
        If Mid(str, 1, 1) = "x" Then
            com_x_data_old = com_x_data
            com_x_data = str
            If com_x_data = com_x_data_old Then
                st_arry = Split(com_x_data, ",")
                Text5.Text = Replace(st_arry(1), vbCrLf, "") '最後のCRLFを取り除く
            End If
        End If 
        
        If Mid(str, 1, 1) = "r" Then
            com_r_data_old = com_r_data
            com_r_data = str
            If com_r_data = com_r_data_old Then
                digital_pin(0) = CInt(Mid(str, 3, 1))
                digital_pin(1) = CInt(Mid(str, 4, 1))
                digital_pin(2) = CInt(Mid(str, 5, 1))
                digital_pin(3) = CInt(Mid(str, 6, 1))
                digital_pin(4) = CInt(Mid(str, 7, 1))
                digital_pin(5) = CInt(Mid(str, 8, 1))
                digital_pin(6) = CInt(Mid(str, 9, 1))
                digital_pin(7) = CInt(Mid(str, 10, 1))
                digital_pin(8) = CInt(Mid(str, 11, 1))
                digital_pin(9) = CInt(Mid(str, 12, 1))
            End If
        End If
    
        If Mid(str, 1, 1) = "a" Then
            com_a_data_old = com_a_data
            com_a_data = str
            If com_a_data = com_a_data_old Then
                'Dim st_arry() As String	変数宣言を削除 
                st_arry = Split(com_a_data, ",")
                Text1(0).Text = st_arry(1)
                Text1(1).Text = st_arry(2)
                Text1(2).Text = st_arry(3)
	以下続くため省略
 '現在の状態をログに書き出す
Private Sub condition_log_write()
    str = ""
    str = "," + Text1(0).Text + "," + Text5.Text
    
    Call logWrite(str, Format(Now, "yyyymmdd") + ".csv")
End Sub
 
    
       フォトレジスタの値  
       ルクス値  
     
    
      530 
      7259 
     
    
      324 
      35386 
     
    
      292 
      48560 
     
  
これらの数値を使ってマップを作成しグラフを描画しました。const int ar[]={
/* x */  288,   292,   309,   324,   335,   351,   372,   402,   431,   460,   496,  530,
/* y */  54106, 48560, 39350, 35386, 31376, 26847, 21485, 16316, 12685, 10038, 8250, 7259
};
 GL5528  を使用しています。シリアル通信を光ファイバー経由する 北側45°の角度でセットされたCDSセル、このセンサーが制御の生命線です。     map_ver = "2025/07/11"
    '数列の作成 ONになる側の閾値
    map1_H = Array( _
    0,   600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2400, _
    320, 330, 340, 340, 341, 343,  345,  360,  360,  360,  350,  345,  340,  330,  320,  320,  320 _
    )
    'ONからOFFにする閾値を引く数(マップを設定するのが面倒で簡略化のため)
    map1_OFF = Array( _
    300, 365, 370, 375, 400, 450, _
     10,  10,  20,  30,  40,  80 _
    )
    '季節の変化によるオフセット値
    map1_Season = Array( _
      0,  20,  51, 65,  79,  94, 110,125, 140,155, 171,186, 201,216, 232,247, 263, 278,  293, 308,  324,  354, 366, _
      0,   0,   0,  0,   0,   0,   0,  0,   0,  0,   5, 10,  20, 20,  10,  5 ,   0,   0,    0,   0,    0,    0,   0  )
    '  ,1/21,2/21,3/7,3/21, 4/5,4/21,5/6,5/21,6/5,6/21,7/6,7/21,8/5,8/21,9/5 ,9/21,10/6,10/21,11/5,11/21,12/21,
 version 1_5_6 Arduinoでシリアル通信 ▲トップページ