顯示具有 PIR 標籤的文章。 顯示所有文章
顯示具有 PIR 標籤的文章。 顯示所有文章

2023年10月19日 星期四

ESP32CAM Four-in-one function

Purpose:

結合之前利用ESP32CAM所做的一些功能, 如Line notify, PIR detect, MQTT, Web Stream等等. 把這些ESP32CAM的code寫在一起方便以後maintain.

Combined with some functions previously project done using ESP32CAM, such as Line notify, PIR detect, MQTT, Web Stream, etc. Write these ESP32CAM codes together for easy maintenance in the future.

之前的文章列表(previously project list):

ESP32CAM PIR DETECTION WITH LINE Notify

ESP32-CAM video streaming with Node Red

ESP32 MQTT Publish/Subscribe DS18B20 Temperature to Node-Red

ESP32-CAM Video Stream by C#

Fundamental:

ESP32CAM circuit




Arduino IDE2

MQTT

請參照之前文章ESP32 MQTT Publish/Subscribe DS18B20 Temperature to Node-Red



Web-Stream Function:

請參照之前文章 ESP32-CAM Video Stream by C#

PIR Detect to Linenotify:

請參照之前文章ESP32CAM PIR DETECTION WITH LINE Notify

YouTubeDemo:


ESP32CAM Code:

#include <PubSubClient.h>
#include <HTTPClient.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "soc/soc.h"             //用於電源不穩不重開機
#include "soc/rtc_cntl_reg.h"    //用於電源不穩不重開機
#include "esp_camera.h"          //視訊函式

//ESP32-CAM 安信可模組腳位設定
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22
// Enter your WiFi ssid and password
const char* ssid     = "your network SSID";   //your network SSID
const char* password = "your network password";   //your network password

String lineNotifyToken = "Your Totken";    //Line Notify Token
//----MQTT--------
//------ 以下修改成你MQTT設定 ------
char* MQTTServer = "mqttgo.io";
int MQTTPort = 1883;//MQTT Port
char* MQTTUser = "";//
char* MQTTPassword = "";//
//-----publish-----
char* MQTTTopicPic1  = "yourpublish/pic";  
//subscribe燈號
char* MQTTSubTopic1 = "yoursubscribe/led";
char* MQTTSubTopic2 = "yoursubscribe/flash";
long MQTTLastPublishTime;//此變數用來記錄推播時間
long MQTTPublishInterval = 300;//每0.5秒推撥一次

WiFiClient WifiClient;
PubSubClient MQTTClient(WifiClient);
//--------------------------------------------------------------------------
#define LED_IN 33
const int Led_Flash = 4;
const int Led_run = 13;
int PIR_Sensor = 12;
boolean startTimer = false;
unsigned long time_now=0;
int time_capture=0;
int wifi_Flag=0;
int wifi_cnt=0;
int MqttFlag=0;
int LinenotifyFlag=0;

#define CAMERA_MODEL_AI_THINKER // Has PSRAM
void startCameraServer();

void setup()
{
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);  //關閉電源不穩就重開機的設定
   
  Serial.begin(9600);
  Serial.setDebugOutput(true);  //開啟診斷輸出
  Serial.println();
  setupCam();

  pinMode(Led_Flash, OUTPUT);
  pinMode(Led_run, OUTPUT);
  pinMode(LED_IN, OUTPUT);
  pinMode(PIR_Sensor, INPUT_PULLDOWN);

  //閃光燈(GPIO4)
  ledcAttachPin(Led_Flash, 4);  
  ledcSetup(Led_Flash, 5000, 8);
 
  WiFi.mode(WIFI_AP_STA);  //其他模式 WiFi.mode(WIFI_AP); WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
    wifi_cnt++;
    Serial.println(wifi_cnt);
    if(wifi_cnt==20)
    {
      //change another AP
      WiFi.begin("ras_2.4", "181415181415");
      while (WiFi.status() != WL_CONNECTED)
      {
        delay(500);
        Serial.print(".");
      }
    }
    if (WiFi.status() == WL_CONNECTED) {    //若連線成功
      Serial.println("");
      Serial.println("STAIP address: ");
      Serial.println(WiFi.localIP());
      Serial.println("");

      wifi_Flag=1;
      startCameraServer();
      break;
    }
  }
 
  digitalWrite(Led_Flash, LOW);
 
}

void loop()
{
  int v = digitalRead(PIR_Sensor);
  if (v == 1) {
    //傳照片
    String result = SendImageMQTT();
    Serial.println(result);
    ledcWrite(4,10);
    delay(1000);
    Serial.println("starting to Line");
    sendCapturedImage2LineNotify(lineNotifyToken);
    ledcWrite(4,0);
  }
  if(wifi_Flag==1)
  {
    digitalWrite(LED_IN, LOW);
    delay(200);
    digitalWrite(LED_IN, HIGH);
    delay(200);
  }
  if (!MQTTClient.connected())
  {
    MQTTConnecte();
  }
  if ((millis() - MQTTLastPublishTime) >= MQTTPublishInterval )
  {
    //String result = SendImageMQTT();
    //Serial.println(result);
    MQTTLastPublishTime = millis(); //更新最後傳輸時間
  }
  MQTTClient.loop();//更新訂閱狀態
  delay(100);  //You could only send up to 50 images to Line Notify in one hour.
}

//鏡頭設定
void setupCam() {  
  // #define CAMERA_MODEL_AI_THINKER
  //視訊組態設定  https://github.com/espressif/esp32-camera/blob/master/driver/include/esp_camera.h
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  if(psramFound()){  //是否有PSRAM(Psuedo SRAM)記憶體IC
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  //視訊初始化
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    ESP.restart();
  }

  //可自訂視訊框架預設大小(解析度大小)
  sensor_t * s = esp_camera_sensor_get();
  // initial sensors are flipped vertically and colors are a bit saturated
  if (s->id.PID == OV3660_PID) {
    s->set_vflip(s, 1); // flip it back
    s->set_brightness(s, 1); // up the brightness just a bit
    s->set_saturation(s, -2); // lower the saturation
  }
  // drop down frame size for higher initial frame rate
  s->set_framesize(s, FRAMESIZE_SVGA);    //解析度 UXGA(1600x1200), SXGA(1280x1024), XGA(1024x768), SVGA(800x600), VGA(640x480), CIF(400x296), QVGA(320x240), HQVGA(240x176), QQVGA(160x120), QXGA(2048x1564 for OV3660)

  //s->set_vflip(s, 1);  //垂直翻轉
  //s->set_hmirror(s, 1);  //水平鏡像
  //s->set_pRotation(s, 1);  //0=不旋轉 1-轉90度 2- 轉180度 3-轉270
}

String sendCapturedImage2LineNotify(String token) {
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();  
  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
    return "Camera capture failed";
  }
   
  WiFiClientSecure client_tcp;  //啟動SSL wificlient
  client_tcp.setInsecure();   //run version 1.0.5 or above
  Serial.println("Connect to notify-api.line.me");
  if (client_tcp.connect("notify-api.line.me", 443)) {
    Serial.println("Connection successful");
   
    String message = "ESP32-CAM";
    String head = "--Taiwan\r\nContent-Disposition: form-data; name=\"message\"; \r\n\r\n" + message + "\r\n--Taiwan\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String tail = "\r\n--Taiwan--\r\n";

    uint16_t imageLen = fb->len;
    uint16_t extraLen = head.length() + tail.length();
    uint16_t totalLen = imageLen + extraLen;
    //開始POST傳送訊息
    client_tcp.println("POST /api/notify HTTP/1.1");
    client_tcp.println("Connection: close");
    client_tcp.println("Host: notify-api.line.me");
    client_tcp.println("Authorization: Bearer " + token);
    client_tcp.println("Content-Length: " + String(totalLen));
    client_tcp.println("Content-Type: multipart/form-data; boundary=Taiwan");
    client_tcp.println();
    client_tcp.print(head);
   
    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    Serial.println("Data Sending....");
    //檔案太大,分段傳送
    for (size_t n=0;n<fbLen;n=n+1024) {
      if (n+1024<fbLen) {
        client_tcp.write(fbBuf, 1024);
        fbBuf += 1024;
      }
      else if (fbLen%1024>0) {
        size_t remainder = fbLen%1024;
        client_tcp.write(fbBuf, remainder);
      }
    }  
   
    client_tcp.print(tail);
    client_tcp.println();
    esp_camera_fb_return(fb);

    String getResponse="",Feedback="";
    int waitTime = 10000;   // timeout 10 seconds
    long startTime = millis();
    boolean state = false;
   
    while ((startTime + waitTime) > millis()) {
      Serial.print(".");
      delay(100);      
      while (client_tcp.available()) {  //當有收到回覆資料時
          char c = client_tcp.read();
          if (state==true) Feedback += String(c);        
          if (c == '\n') {
            if (getResponse.length()==0) state=true;
            getResponse = "";
          }
          else if (c != '\r')
            getResponse += String(c);
          startTime = millis();
       }
       if (Feedback.length()>0) break;
    }
    Serial.println();
    client_tcp.stop();
    return Feedback;
  }
  else {
    return "Connected to notify-api.line.me failed.";
  }
}

String sendRequest2LineNotify(String token, String request) {
  request.replace("%","%25");
  request.replace(" ","%20");
  //request.replace("&","%20");
  request.replace("#","%20");
  //request.replace("\'","%27");
  request.replace("\"","%22");
  request.replace("\n","%0D%0A");
  request.replace("%3Cbr%3E","%0D%0A");
  request.replace("%3Cbr/%3E","%0D%0A");
  request.replace("%3Cbr%20/%3E","%0D%0A");
  request.replace("%3CBR%3E","%0D%0A");
  request.replace("%3CBR/%3E","%0D%0A");
  request.replace("%3CBR%20/%3E","%0D%0A");
  request.replace("%20stickerPackageId","&stickerPackageId");
  request.replace("%20stickerId","&stickerId");    

  WiFiClientSecure client_tcp;
  client_tcp.setInsecure();   //run version 1.0.5 or above
 
  Serial.println("Connect to notify-api.line.me");  
 
  if (client_tcp.connect("notify-api.line.me", 443)) {
    Serial.println("Connection successful");
       
    Serial.println(request);    
    client_tcp.println("POST /api/notify HTTP/1.1");
    client_tcp.println("Connection: close");
    client_tcp.println("Host: notify-api.line.me");
    client_tcp.println("User-Agent: ESP8266/1.0");
    client_tcp.println("Authorization: Bearer " + token);
    client_tcp.println("Content-Type: application/x-www-form-urlencoded");
    client_tcp.println("Content-Length: " + String(request.length()));
    client_tcp.println();
    client_tcp.println(request);
    client_tcp.println();
   
    String getResponse="",Feedback="";
    boolean state = false;
    int waitTime = 3000;   // timeout 3 seconds
    long startTime = millis();
    while ((startTime + waitTime) > millis()) {
      Serial.print(".");
      delay(100);      
      while (client_tcp.available()) {
          char c = client_tcp.read();
          if (state==true) Feedback += String(c);        
          if (c == '\n') {
            if (getResponse.length()==0) state=true;
            getResponse = "";
          }
          else if (c != '\r')
            getResponse += String(c);
          startTime = millis();
       }
       if (getResponse.length()>0) break;
    }
    Serial.println();
    client_tcp.stop();
    return Feedback;
  }
  else
    return "Connection failed";  
}

//開始MQTT連線伺服器
void MQTTConnecte()
{
  MQTTClient.setServer(MQTTServer, MQTTPort);
  MQTTClient.setCallback(MQTTCallback);
  while (!MQTTClient.connected()) {
    //以亂數為ClientID
    String  MQTTClientid = "esp32-" + String(random(1000000, 9999999));
    if (MQTTClient.connect(MQTTClientid.c_str(), MQTTUser, MQTTPassword)) {
      //連結成功,顯示「已連線」。
      Serial.println("MQTT已連線");
      //訂閱SubTopic1主題
      MQTTClient.subscribe(MQTTSubTopic1);
      MQTTClient.subscribe(MQTTSubTopic2);
    } else {
      //若連線不成功,則顯示錯誤訊息,並重新連線
      Serial.print("MQTT連線失敗,狀態碼=");
      Serial.println(MQTTClient.state());
      Serial.println("五秒後重新連線");
      delay(5000);
    }
  }
}

//拍照傳送到MQTT
String SendImageMQTT()
{
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();  
  if(!fb) {
    Serial.println("MQTT capture failed");
    delay(1000);
    ESP.restart();
    return "MQTT capture failed";
  }
  size_t fbLen = fb->len;
  //int ps = 512;
  //開始傳遞影像檔,批次傳黨
  MQTTClient.beginPublish(MQTTTopicPic1, fbLen, false);
  uint8_t *fbBuf = fb->buf;
  for (size_t n = 0; n < fbLen; n = n + 2048) {
    if (n + 2048 < fbLen) {
      MQTTClient.write(fbBuf, 2048);
      fbBuf += 2048;
    } else if (fbLen % 2048 > 0) {
      size_t remainder = fbLen % 2048;
      MQTTClient.write(fbBuf, remainder);
    }
  }
  boolean isPublished = MQTTClient.endPublish();
  esp_camera_fb_return(fb);//清除緩衝區
  if (isPublished) {
    return "MQTT傳輸成功";
  }
  else {
    return "MQTT傳輸失敗,請檢查網路設定";
  }
}

//接收到訂閱時
void MQTTCallback(char* topic, byte* payload, unsigned int length)
{
  Serial.print(topic); Serial.print("訂閱通知:");
  String payloadString;//將接收的payload轉成字串
  //顯示訂閱內容
  for (int i = 0; i < length; i++) {
    payloadString = payloadString + (char)payload[i];
  }
  Serial.println(payloadString);
  //比對主題是否為訂閱主題1
  if (strcmp(topic, MQTTSubTopic1) == 0)
  {
    Serial.println("LED:" + payloadString);
    if (payloadString == "ON")
    {
      digitalWrite(16, HIGH);
    }
    if (payloadString == "OFF")
    {
      digitalWrite(16, LOW);
    }
  }
  //比對主題是否為訂閱主題1
  if (strcmp(topic, MQTTSubTopic2) == 0) {
    Serial.println("Flash:" + payloadString);
    if (payloadString == "ON")
    {
      ledcWrite(4,10);
      delay(1000);
      String result = SendImageMQTT();
      Serial.println(result);
      delay(1000);
      Serial.println("starting to Line");
      sendCapturedImage2LineNotify(lineNotifyToken);
      for (int i=0;i<3;i++) {  
        ledcWrite(4,10);
        delay(200);
        ledcWrite(4,0);
        delay(200);    
      }
    }
    if (payloadString == "OFF")
    {
      ledcWrite(4,0);
    }
  }
}


2023年9月10日 星期日

Inductive trash can with ESP32

Purpose:

利用手上ESP32板子為主架構搭配PIR HC-SR505 sensor感應去控制servo motor旋轉角度另添加一塊充電模組可以完成一個充電式感應垃圾桶!!

Using the ESP32 board as the main structure with the PIR HC-SR505 sensor to control the rotation angle of the servo motor, and adding a charging module to complete a rechargeable inductive trash can!!

BOM:

Figure1 PIR HC-SR505

Figure2 充電鋰電池

Figure3 ESP32
                                                                   

Figure4 充電板
Circuit:
Figure5 整體架構
YouTube Demo:
演示影片
Code Introduce:
#include <ESP32Servo.h>
#include <BluetoothSerial.h>
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t LEDFlag=1;
  uint8_t BTFlag = 0;
  uint8_t ServoFlag = 0;
  uint8_t PIR_Flag = 1;
  uint8_t PIR_status = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//------------------------------------------------
#define LED_BUILTIN 2
BluetoothSerial SerialBT;
//------------------------------------------------
Servo myservo;  // create servo object to control a servo
// Recommended PWM GPIO pins on the ESP32 include 2,4,12-19,21-23,25-27,32-33
int servoPin = 13;
//-----------------------
int inPin = 22;  //PIR pin
//-------------------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(inPin, INPUT);
  SerialBT.begin("BT_Servo");    // BTName
  myservo.setPeriodHertz(50);    // standard 50 hz servo
  myservo.attach(servoPin, 500, 2400); // attaches the servo on pin 13 to the servo object
  myservo.write(0);
}
//-----------------------------------------
void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    if(flag.LEDFlag == 1)  //flash LED
    {
      digitalWrite(LED_BUILTIN, HIGH);
      vTaskDelay(300);
      digitalWrite(LED_BUILTIN, LOW);
      vTaskDelay(300);
    }
    if (flag.PIR_Flag == 1)  //start PIR detect
    {
      Serial.println(flag.PIR_status);
      if(digitalRead(inPin) == HIGH)
      {  
        if(flag.PIR_status==0)
        {
          Serial.println("Presence detected");
          myservo.write(100);
          flag.PIR_status=1;
          vTaskDelay(20);    
        }
      }
      else
      {
        if(flag.PIR_status==1)
        {
          Serial.println("No detected");
          myservo.write(0);
          flag.PIR_status=0;  
        }
      }
    }
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          //Serial.println( F("Debug") );
          //Serial.println( Uart.inputString );
          processCommand(Uart.line); // do something with the command
          //傳輸給藍芽
          SerialBT.println(Uart.line);
         
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    while (SerialBT.available())
    {
      //讀取藍芽資料
      String BTdata = SerialBT.readString();
      //顯示在序列視窗
      Serial.println(BTdata);
      //char charBuf[BTdata.length() + 1];
      //BTdata.toCharArray(charBuf, BTdata.length());
      BTprocessCommand(BTdata); // do something with the command
      //processCommand(charBuf); // do something with the command
    }//while (BT.available())

  }
}
void BTprocessCommand(String data)
{
  if (data == "100")
  {
    Serial.println(F("SERVO_100"));
    myservo.write(100);
  }
  if (data == "10")
  {
    Serial.println(F("SERVO_10"));
    myservo.write(10);
    //myservo.detach();
  }
  if (data == "180")
  {
    Serial.println(F("SERVO_180"));
    myservo.write(180);
  }
  if (data == "50")
  {
    Serial.println(F("SERVO_50"));
    myservo.write(50);
    //myservo.detach();
  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230710"));
  }
  //-------------- Servo --------------------
  if (strstr(data, "SERVO_5")!= NULL)
  {
    Serial.println(F("SERVO_5"));
    myservo.write(5);
    //myservo.detach();
  }
  if (strstr(data, "SERVO_10")!= NULL)
  {
    Serial.println(F("SERVO_10"));
    myservo.write(10);
  }
  if (strstr(data, "SERVO_50")!= NULL)
  {
    Serial.println(F("SERVO_50"));
    myservo.write(50);
  }
  if (strstr(data, "SERVO_100")!= NULL)
  {

    Serial.println(F("SERVO_100"));
    myservo.write(100);
  }
  if (strstr(data, "SERVO_180")!= NULL)
  {
    Serial.println(F("SERVO_180"));
    myservo.write(180);
  }
  if (strstr(data, "SERVO_270")!= NULL)
  {
    Serial.println(F("SERVO_270"));
    myservo.write(270);
  }
}
//------------------------------------------