السبت، 5 يناير 2019



هذا المشروع هو نظام تتبع GPS مع شاشة LCD باستخدام Arduino Uno و Digilent PmodGPS

المكونات
اردوينو اونو  او جينون
Digilent Pmod GPS
شاشة كرستالية

قصة
 هذا المشروع بتسليط الضوء على استخدام PmodGPS من Digilent كمحدد موقع وتوجيه إلى نقطة مرجعية. يمكن أن يكون هذا مفيدًا للمتجولين ، أو الصيادين ، أو غيرهم من الملاحين في المواقف دون علامات أو علامات تحديد الموقع / الاتجاه الأخرى.

وصف
يستخدم هذا المشروع و Arduino Uno microcontroller ، شاشة PmodCLS LCD من Digilent ، و PmodGPS أيضًا من Digilent. تم تشجيع Arduino Uno لنا لاستخدامها في برمجة أسهل بدلاً من Verilog أو HDL. بمجرد التشغيل ، سيعرض هذا المشروع خطوط الطول والعرض والارتفاع والمسافة إلى المستخدم ، ونقطة زاوية ثابتة باتجاه نقطة مرجعية ثابتة ، وسرعة المستخدم ، بالإضافة إلى البيانات الأخرى التي يجب أن يختار المبرمج تنفيذها حيث أن هناك العديد من الوظائف الأخرى المتاحة لـ PmodGPS. يمكن تشغيل هذا النظام بواسطة بطارية USB متصلة لتطبيق الهاتف المحمول. فقط قم ببرمجة Arduino Uno ، قم بفصل جهاز الكمبيوتر الخاص بك ، قم بتوصيل بطارية USB ، ويجب على Arduino Uno مواصلة العمل كالمعتاد. يتم تعيين النقطة المرجعية في وقت إعادة ضبط النظام. يمكن تشغيل ذلك يدويًا بالضغط على زر إعادة الضبط على Arduino




************************************************************************/

#include <SoftwareSerial.h>
#include "PmodGPS.h"


//pin definitions
#define _3DFpin   6 //pin 6
#define _1PPSpin  7 //pin 7
//#define RSTpin    reset //

typedef enum{
  RESTART,
  PREFIXED,
  NOTFIXED,
  FIXED
}STATE;

typedef enum{
  DEGREES,
  MINUTES,
  SECONDS,
}GPSDATA;

GPS myGPS;
char* LAT;
char* LONG;
NMEA mode;

STATE state=RESTART;
GPSDATA gpsdata = DEGREES;

//declare and initialize global variables
String referenceLatitude,referenceLongitude;
String currentLatitude, currentLongitude;
float minutesToDegrees, secondsToDegrees;
float DDcurrentLatitude, DDcurrentLongitude;
float DDreferenceLatitude, DDreferenceLongitude;
float SeattleLatitude = 47.6062; //needed for local linearization
float directionDegrees, directionMagnitude;

//starts serial communication with GPS sensor
//displays to LCD to signify begining of code or system restart
void setup()
{
    lcd.begin(9600); // Begin LCD
    lcd.write("\x1b[j"); // Erase display
    lcd.write("\x1b[0h"); // configuration of the display (write on 2 lines)
    lcd.write("\x1b[0;5H"); // cursor is on line 1 and columm 5
    lcd.print("Begin");
    delay(2000);
    lcd.write("\x1b[j"); 
    lcd.write("\x1b[0h"); 
    Serial.begin(9600);
    myGPS.GPSinit(Serial, 9600, _3DFpin, _1PPSpin);
}

void loop()
{
  //State machine for GPS
  switch (state)
  {
    case(RESTART):

        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("No Sats");
        state=PREFIXED;
        delay(2000);       
        break;

    //establish connection and set reference point
    //This is done automatically on start up 
    //PREFIXED term used only to match existing states theme, it has no added meaning from the author
    //This sets the reference point to where the system is restarted    
    case(PREFIXED): 

      mode = myGPS.getData(Serial);//Receive data from GPS
      if (mode == GGA){//If GGAdata was received

        //print to LCD: "Setting Reference"
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("# of Sats: ");lcd.print(myGPS.getNumSats());
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h");
        lcd.print("Setting Reference");
        delay(2000); //delays used to keep LCD prints long enough for user to read

        //set reference latitude as current lattitude at reset
        //myGPS.getLatitude() returns a string in Degrees-Minutes_Seconds format
        referenceLatitude = myGPS.getLatitude();
        
        //convert string data to float in Decimal-Degrees format 
        DDreferenceLatitude = convertDMStoDDlatitude(referenceLatitude);

        //set reference longitude as current longitude at reset
        //myGPS.getLongitude() returns a string in Degrees-Minutes_Seconds format
        referenceLongitude = myGPS.getLongitude();
        
        //convert string data to float in Decimal-Degrees format 
        DDreferenceLongitude = convertDMStoDDlongitude(referenceLongitude);

        //display reference coordinates to LCD
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("Reference Latitude: "); lcd.print(DDreferenceLatitude, 6);
        delay(2000);
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        //longitude around Seattle is a negative number but conversion function omits this 
        lcd.print("Reference Longitude: -"); lcd.print(DDreferenceLongitude, 6);
        delay(2000);

        //if a reference point has been set, change state, otherwise repeat this state until reference is set
        if (DDreferenceLongitude != 0 && DDreferenceLatitude != 0){
          state = NOTFIXED;
          }
        }
        
        break; 
      
        
    case(NOTFIXED)://Look for satellites, display how many the GPS is connected to
      mode = myGPS.getData(Serial);//Receive data from GPS
      if (mode == GGA){//If GGAdata was received
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("# of Sats: ");lcd.print(myGPS.getNumSats());lcd.print(" Position: Not Fixed");
        delay(2000);

        //get current latitude and convert to decimal degrees format
        currentLatitude = myGPS.getLatitude();
        DDcurrentLatitude = convertDMStoDDlatitude(currentLatitude);

        //get current longitude and convert to decimal degrees format
        currentLongitude = myGPS.getLongitude();
        DDcurrentLongitude = convertDMStoDDlongitude(currentLongitude);

        //print data to LCD
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("Latitude: ");lcd.print(DDcurrentLatitude, 6);lcd.print(" Deg ");     
        delay(2000);
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("Longitude: -");lcd.print(DDcurrentLongitude, 6);lcd.print(" Deg ");
        delay(2000);
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        directionMagnitude = spaceBetween(DDcurrentLongitude, DDreferenceLongitude, DDcurrentLatitude, DDreferenceLatitude);
        lcd.print("Distance to Ref: ");lcd.print(directionMagnitude);
        lcd.print(" Meters");
        delay(2000);
        directionDegrees = directionToDegrees(DDcurrentLongitude, DDreferenceLongitude, DDcurrentLatitude, DDreferenceLatitude);
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("Angle to Ref: ");lcd.print(directionDegrees);
        lcd.print(" Deg ");lcd.print(directionToCompass(directionDegrees));
        delay(2000);
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("Speed: ");lcd.print(myGPS.getSpeedKM(), 3);lcd.print(" km/hr");
        delay(2000); 
        lcd.write("\x1b[j"); 
        lcd.write("\x1b[0h"); 
        lcd.print("Altitude: ");lcd.print(myGPS.getAltitude());lcd.print(" meters");      
        delay(2000);
        
        if (myGPS.isFixed()){//When it is fixed, continue
          state=FIXED;
        }
      }
        break;
    case(FIXED): //I am still unsure what Posisition Fixed Indicator (PFI) is used for / significance
                 //this code didn't seem to perform differently bewteen NOTFIXED and FIXED
        if(myGPS.isFixed()){//Update data while there is a position fix
          mode = myGPS.getData(Serial);
          if (mode == GGA){//If GGAdata was received
          
        //get current latitude and convert to decimal degrees format
          currentLatitude = myGPS.getLatitude();
         DDcurrentLatitude = convertDMStoDDlatitude(currentLatitude);
        
        //get current longitude and convert to decimal degrees format
          currentLongitude = myGPS.getLongitude();
          DDcurrentLongitude = convertDMStoDDlongitude(currentLongitude);

              //print data to LCD
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("Latitude: ");lcd.print(DDcurrentLatitude, 6);lcd.print(" Deg ");
              delay(2000);
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("Longitude: -");lcd.print(DDcurrentLongitude, 6);lcd.print(" Deg ");
              delay(2000);
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("Altitude: ");lcd.print(myGPS.getAltitude());lcd.print(" meters");
              delay(2000);
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("# of Sats: ");lcd.print(myGPS.getNumSats());lcd.print(" Position: Fixed");
              delay(2000);
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("\n");
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("Distance to Ref: ");lcd.print(spaceBetween(DDcurrentLongitude, DDreferenceLongitude, DDcurrentLatitude, DDreferenceLatitude));
              lcd.print(" Meters");
              delay(2000);
              directionDegrees = directionToDegrees(DDcurrentLongitude, DDreferenceLongitude, DDcurrentLatitude, DDreferenceLatitude);
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("Angle to Ref: ");lcd.print(directionDegrees);
              lcd.print(" Deg ");lcd.print(directionToCompass(directionDegrees));
              delay(2000);
              lcd.write("\x1b[j"); 
              lcd.write("\x1b[0h"); 
              lcd.print("Speed: ");lcd.print(myGPS.getSpeedKM(), 3);lcd.print(" km/hr");
              delay(2000); 
          }
        }
        else {
          state=RESTART;//If PFI = 0, re-enter connecting state
        }
      break;
  }
}

// functions for loop code, could go into header file


///**************************************************/
///* function: convertDMStoDDlatitude                                                */                                */
///* input: String
///* output: float                                  
///* description: parses string for numerical values
///*   gps coordinates captured in degrees minutes seconds mode
///*   converts DMS format to Decimal Degrees format for calcualtions
///*   convert by dividing minutes data by 60 and seconds data by 3600 then summing each with the degrees data
///*   1 degree is 60 minutes and there are 60 seconds in each minute
///**************************************************/
float convertDMStoDDlatitude(String lat){
          float coordDegreesLat = 0.00;
          String inStringLat = "";

            switch (gpsdata) {
              
              case (DEGREES):
                inStringLat += lat.substring(0,2); //first two chars are degrees
                coordDegreesLat += inStringLat.toFloat(); //convert to float, add to decimal degrees value
                inStringLat = "";//clear temp string
                gpsdata = MINUTES;//move to parse next part of string
               
               case (MINUTES):
                inStringLat += lat.substring(3,5); //skip char, next two are minutes
                minutesToDegrees = (inStringLat.toFloat() / 60);  //convert to float
                coordDegreesLat += minutesToDegrees; //add to decimal degrees value
                inStringLat = "";//clear temp string
                gpsdata = SECONDS;//move to parse next part of string
               
               case (SECONDS):
                inStringLat += lat.substring(6,11); //skip char, last five are seconds with a decimal between two integers
                secondsToDegrees = (inStringLat.toFloat() / 3600);//convert to float
                coordDegreesLat += secondsToDegrees; //add to decimal degrees value
                inStringLat = "";//clear temp string
                gpsdata = DEGREES;//move to parse next part of string
            }
 return coordDegreesLat;
}

///**************************************************/
///* function: convertDMStoDDlongitude                                                */                                */
///* input: String
///* output: float                                  
///* description: parses string for numerical values
///*   gps coordinates captured in degrees minutes seconds mode
///*   converts DMS format to Decimal Degrees format for calcualtions
///*   convert by dividing minutes data by 60 and seconds data by 3600 then summing each with the degrees data
///*   1 degree is 60 minutes and there are 60 seconds in each minute
///*   NOTE: seconds to degrees accuracy improved when normalizing difference in longitude degrees to Seattle area
///**************************************************/
float convertDMStoDDlongitude(String longit){
    
    float coordDegreesLong = 0.0;
    String inStringLong = "";
  
            switch (gpsdata) {
              
              case (DEGREES): //first 3 characters are degrees
                inStringLong += longit.substring(0,3); //parse string
               coordDegreesLong += inStringLong.toFloat(); //convert to float, add to decimal degrees value
               inStringLong = ""; //clear temp string
               gpsdata = MINUTES; //move to parse next part of string
               
               case (MINUTES): //skip a char then next two are minutes
                inStringLong += longit.substring(4,6); //parse string
               minutesToDegrees = (inStringLong.toFloat() / 60);  //convert to float 
               coordDegreesLong += minutesToDegrees; //add to decimal degrees value
               inStringLong = ""; //clear temp string
               gpsdata = SECONDS;//move to parse next part of string
               
               case (SECONDS): //skip a char then last five are seconds with a decimal in the middle of four integers
                inStringLong += longit.substring(7,12); //parse string
                secondsToDegrees = cos(SeattleLatitude*PI/180)*(inStringLong.toFloat() / 3600); //convert to float
                coordDegreesLong += secondsToDegrees; //add to decimal degrees value
                inStringLong = ""; //clear temp string
                gpsdata = DEGREES; //reset to beginning of string state for next function call
            }
 return coordDegreesLong;
  }

///**************************************************/
///* function: spaceBetween                                                                               */
///* input: 4 floats -> longitude and latitude of current posistion and reference posistion
///* output: float                                  
///* description: takes gps coordinates of two locations and calculates distance between them in meters 
///**************************************************/
float spaceBetween(float longitudeLocal, float longitudeOther, float latitudeLocal, float latitudeOther){
      float longDiff = longitudeLocal - longitudeOther;
      float latDiff = latitudeLocal - latitudeOther;
      float longMeterPerDeg = 85390; //Seattle area distance between degrees longitude
      float latMeterPerDeg = 111030; //Seattle area distance between degrees latitude
      float longMeters = longDiff*longMeterPerDeg; //convert differnce of longitude degrees to meters
      float latMeters = latDiff*latMeterPerDeg;//convert differnce of latitude degrees to meters
      float directionMag = sqrt(longMeters*longMeters + latMeters*latMeters); //pythagorean distance formula
  return directionMag;
}


///**************************************************/
///* function: directionToDegrees                                                                               */
///* input: 4 floats -> longitude and latitude of current posistion and reference posistion
///* output: float                                  
///* description: determine direction to reference from local coordinates in degrees 
///**************************************************/
float directionToDegrees(float longitudeLocal, float longitudeOther, float latitudeLocal, float latitudeOther){
      float  longDiffTemp = 0;
      float  latDiffTemp = 0;
      float  longDiff = 0;
      float  latDiff = 0;
      float directionToDegrees = 0.0;
      int posLong = 0;
      int posLat = 0;

      latDiffTemp = (latitudeOther - latitudeLocal); // y axis
      longDiffTemp = (longitudeOther - longitudeLocal);// x axis

      //determine if difference in longitude and latitude is positive or negative
      //this helps determine what quadrant the angle lies in
      if (longDiff > 0){posLong = 1;}
      if (latDiff > 0){posLat = 1;}

      //converts negative value to positive for to ease calculation
      if (longDiff < 0){longDiff = -1*longDiff;}
      if (latDiff < 0){latDiff = -1*latDiff;}

      //calculate angle 
      float directionToDegreesTemp = atan2(latDiff, longDiff) * (180 / PI);

      //determine true angle by determining which quadrant then compensating appropriately from acrtan return
      if (posLong){
        if (posLat){ //quad 1
          directionToDegrees = directionToDegreesTemp;
          }
        else{ //quad 4
          directionToDegrees = 2*PI + directionToDegreesTemp;
          }
        }   
      else{ 
          if (posLat){//quad 2 
          directionToDegrees = PI - directionToDegreesTemp;
          }
          else{ //quad 3
          directionToDegrees = PI + directionToDegreesTemp;
          }
        }  
 return directionToDegrees;
}


///**************************************************/
///* function: directionToCompass                                                                               */
///* input: float
///* output: float                                  
///* description: determine cardinal direction to reference from direction degrees 
///*      set up such that East is zero degrees and degrees increase counter clockwise to simplify
///*       a more correct approach would have North be zero degrees and report a bearing degree to East or West
///*       might be good to implement some epsilon value for N, S, E, W directions so the degree value doesn't need to be exact
///**************************************************/
String directionToCompass(float directionDegrees){
    
    String directionToCompass = "";
    
    if (directionDegrees == 0.0 || directionDegrees == 360.0){directionToCompass = "E";}
    else if (directionDegrees > 0.0 && directionDegrees < 30.0){directionToCompass = "NEE";}
    else if (directionDegrees >= 30.0 && directionDegrees < 60.0){directionToCompass = "NE";}
    else if (directionDegrees >= 60.0 && directionDegrees < 90.0){directionToCompass = "NNE";}
    else if (directionDegrees = 90.0){directionToCompass = "N";}
    else if (directionDegrees > 90.0 && directionDegrees < 120.0){directionToCompass = "NNW";}
    else if (directionDegrees >= 120.0 && directionDegrees < 150.0){directionToCompass = "NW";}
    else if (directionDegrees >= 150.0 && directionDegrees < 180.0){directionToCompass = "NWW";}
    else if (directionDegrees = 180.0){directionToCompass = "W";}
    else if (directionDegrees > 180.0 && directionDegrees < 210.0){directionToCompass = "SWW";}
    else if (directionDegrees >= 210.0 && directionDegrees < 240.0){directionToCompass = "SW";}
    else if (directionDegrees >= 240.0 && directionDegrees < 270.0){directionToCompass = "SSW";}
    else if (directionDegrees = 270.0){directionToCompass = "S";}
    else if (directionDegrees > 180.0 && directionDegrees < 210.0){directionToCompass = "SSE";}
    else if (directionDegrees >= 210.0 && directionDegrees < 240.0){directionToCompass = "SE";}
    else if (directionDegrees >= 240.0 && directionDegrees < 270.0){directionToCompass = "SEE";}

 return directionToCompass;
}
















السبت، 8 ديسمبر 2018

جهاز تحكم مزود بتقنية Bluetooth Controlled Servo

المكونات

 Arduino   UNO او   Genuino UNO
SG90 Micro-servo motor
HC-05 Bluetooth Module

حول هذا المشروع
في هذا المشروع سوف أريكم كيف يمكنك التحكم في محرك سيرفو بمساعدة تطبيق الهاتف الذكي عبر البلوتوث.

بالنسبة لهذا المشروع ، سوف نستخدم وحدة Bluetooth HC-05 مع Arduino Uno للتحكم في سيرفر 9g.


-> كيف يعمل هذا المشروع؟
يحتوي هذا المشروع على جزئين:

1. تطبيق الروبوت - سيقوم هذا التطبيق بإرسال حزم البيانات المختلفة إلى وحدة HC-05 Bluetooth الخاصة بنا. (انقر هنا لتحميل التطبيق)

2. الأجهزة - يتكون هذا من وحدة بلوتوث HC-05 ، و Arduino Uno ومحرك سيرفو.

-> هذه طريقة عملها -
يرسل تطبيق Android حزم البيانات إلى وحدة Bluetooth. ترسل وحدات Bluetooth حزمة البيانات هذه إلى Arduino Uno من خلال الاتصال التسلسلي. مبرمج اردوينو أونو لتوليد إشارة التحكم لمحرك سيرفو اعتمادا على قيمة حزمة البيانات. هنا مخطط انسيابي لفهم أفضل.


Flowchart

-> كيف تبدأ

1. قم بتنزيل تطبيق الروبوت. (انقر هنا)

2. قم بتحميل الرمز  الكود على Arduino uno.

3. اتصل بين الاردوينو والبلوتوث.

يرجى ملاحظة أن وحدة بلوتوث HC-05 يجب أن تكون متصلة مع 3.3v وليس مع vcc 5v لأنه يمكن أن يتلف الوحدة.

4. قم بتوصيل وحدة Bluetooth إلى تطبيق android - عندما تشغل جهازك ، ستصبح وحدة Bluetooth مرئية. حتى فتح التطبيق وانقر على العثور على الأجهزة المجاورة. حدد HC-05. بمجرد أن تظهر متصلا أنك على ما يرام!

يمكنك استخدام شريط التمرير أو إدخال القيمة يدويًا للتحكم في ذراع الماكينة.

الكود

#include<SoftwareSerial.h>
#include<Servo.h>
Servo x;
int bttx=0;    //tx of bluetooth module is connected to rx (pin 0) of arduino
int btrx=1;    //rx of bluetooth module is connected to tx (pin 1) of arduino
SoftwareSerial bluetooth(bttx,btrx);
void setup()
{
  x.attach(11);        // servo is connected to pin 11 of arduino
  Serial.begin(9600);
  bluetooth.begin(9600);
}
void loop()
{
  if(bluetooth.available()>0)    //if bluetooth module is transmitting data
  {
    int pos=bluetooth.read(); // store the data in pos variable
    Serial.println(pos);
    x.write(pos);             //move servo head to the given position
  }
}



Servo bt 8pvsjepd7u





الثلاثاء، 6 نوفمبر 2018

نشر بيانات اردوينو الخاصة بك إلى السحابة - Publish Your Arduino Data to the Cloud

Publish Your Arduino Data to the Cloud

المكونات

اردوينو نانو R3
DHT11 مستشعر درجة الحرارة والرطوبة
Everything ESP ESP8266 ESP-01
المقاوم 10K أوم
المقاوم 2.21k أوم

حول هذا المشروع
نظرة عامة
الهدف من هذا المشروع هو أن توضح لك كيف يمكنك الوصول عبر الإنترنت إلى ما تتم قراءته في أحد مسامير إدخال Arduino الخاصة بك.

يتم ذلك دون أي خادم ويب على Arduino الخاص بك ولكن باستخدام خدمة عبر الإنترنت.

في مشروعنا نحن نستخدم نموذج اردوينو نانو. لا توجد مشكلة في استخدام نموذج مجلس آخر - نانو هو واحد مع الموارد ليه - ولكن عليك أن تولي اهتماما بشأن التي هي دبابيس المناسبة لحالتك.

للوصول إلى شبكة الإنترنت سوف تستخدم وحدة ESP8266 WIFI
ما سنقرأه هو درجة حرارة البيئة. للحصول على التدابير التي اخترناها جهاز استشعار DHT11 نموذجي.


وأخيرًا ، للتخلص من جانب الخادم ، سنستخدم الخدمة عبر الإنترنت
هنـــــــــــــــــــــــــــــــــــــا        حيث يمكننا ربط الأجهزة والتطبيقات بحساب اجتماعي واحد.

تشغيل المكونات على
يرجى ملاحظة أن هذا هو برنامج تعليمي نموذجي وليس منتج قائم بذاته بشكل مثالي. ما أعنيه هو أنني سأستخدم مصدر جهد مثبت مختبريًا لتحقيق 3.3 فولت اللازم لـ ESP8266 ولن أقوم بنشر كل ما يلزم للحصول على هذا الجهد من 5 فولت أو بطاريات أو شبكة ... فقط لتسهيل الأمر.


... ولكن ، إذا قررت الحصول على هذه 3 ، 3V من مصدر آخر ، فيجب مراعاة ما يلي:

ESP8266 حساس جدا. سوف الفولت فوق 3.6V تقلى ذلك. هناك بعض المناقشات على الشبكة حول ما إذا كان يمكن أن تقف لمزيد من الجهد ، ولكن ذلك يعتمد على كيفية توصيل دبابيس أخرى أو أي صانع هو من. لا تأخذ المخاطر ، تذكر: أقل من 3.6V.
ما لم يقله أحد لي وربما يوفر عليك يومًا واحدًا هو أنك قد ترى الوحدة الخاصة بك تعمل بكفاءة ، مع المصابيح المتلألئة ... ولكن المشاكل المتكررة للوصول إلى الشبكة. يبدو أن تربيطا تحت الجهد الاسمي قد يفترض وجود نقص في الطاقة التي يمكن أن تؤثر على أداء الترددات اللاسلكية.
يجب أن تدرك أن ESP8266 قد تستهلك ما يصل إلى 250mA. لا تحاول أبدا أن مصدرها من دبوس "3.3V" الخاص بك نانو ، وأنها ليست قادرة على مصدر هذا التيار.
مرة أخرى ، من أجل البساطة ، لن أستخدم مصدر 5Vdc خارجي لتشغيل لوحة Nano حيث سيتم توصيله بالكمبيوتر مع منفذ USB (كما ستجد في هذا البرنامج التعليمي ، سيتم مراقبة الاتصال التسلسلي على USB لتصحيح الأخطاء) ).

... ولكن إذا قررت الحصول على 5V من مصدر آخر ، فعليك أن تأخذ بعين الاعتبار:

السماح للنانو ، وليس فقط الجهد 5V ، ولكن التيار الكافي. يجب أن يكون المصدر قادراً على توفير 1A أو أكثر.
توصيل المصدر على دبوس "فين" من نانو ، وليس في دبوس "5V". الأول هو المكان المناسب لأنه محمي من قبل جهة تنظيم داخلية (لا تخف من إعطاء 6V). والثاني هو الإخراج الذي يمكن أن يغذي مكونات أخرى (سيكون لطيفا لجهاز استشعار DHT11 لدينا).

توصيل وحدة WiFi إلى اللوحة
قبل أن نصل إلى لوحة ...

... هل تعرف حقا أي معدل الباود التسلسلي يتم تعيينه في وحدة ESP8266 الخاصة بك من قبل صانع أو أي دولة أخرى؟ إذا كانت الإجابة بنعم ، فانتقل إلى النقطة التالية.

صناع عادة تعيينه إلى 9600 أو 115200 ، ولكن ربما معدل آخر.

قد ترغب في معرفة ذلك بعد طريقة التجربة والخطأ عند الترميز ، ومجرد محاولة معدلات الباود مختلفة ومعرفة ما إذا كان يعمل.

أو قد ترغب في توصيل جهاز الكمبيوتر الخاص بك بـ ESP8266 ، المتصل بين وحدة نمطية FTDI ، لطلب معدل الباود الفعلي باستخدام أوامر ATT. أوصي بهذه الطريقة لأنه أكثر توضيحًا بالإضافة إلى أنه يمكنك التأكد من أن الوحدة تعمل بشكل صحيح (وليس مقليًا أو تالفًا بصمت). ولتحقيق ذلك ، اتبعت هذا البرنامج التعليمي ، فهو جيد جدًا وواضح.

أوصي بتعيينه في 9600 bauds: سهل وبطيء للإلكترونيات الخاصة بك ، بسرعة كافية لصبرك. سيكون الأمر الصحيح هو AT + CIOBAUD = 9600.

الاتصال باللوحة
والآن بعد أن عرفنا معدل البث بالباود الذي لدينا على وحدة ESP8266 ، يمكننا المضي قدمًا.

لن نستخدم منفذ UR RX / TX الخاص بلوحة Nano للاتصال بـ ESP8266. هذا لأننا نريد الحصول على هذه القناة مجانًا لتصحيح الأخطاء من جهاز الكمبيوتر الخاص بنا.

ثم سنستخدم اثنين من دبابيس رقمية مختلفة أن يكون لها منفذ تسلسلي آخر ، ما يسمى "المنفذ التسلسلي للبرمجيات". دعونا اليوم D2 سيكون TX و D3 سيكون دبوس RX. لا تقلق بشأن كيفية تنفيذ هذا المنفذ الجديد ، ستجد في قسم الترميز مدى سهولة التعامل مع المكتبة.

ثم ، هذه هي الطريقة التي يجب أن يكون الاتصال بين ESP8266 واللوحة نانو.


لاحظ أنه يجب تمكين CHIN PIN على ESP8266 من خلال تعيين حالة عالية (3.3 فولت). يتم وضع المقاوم 10Kohm للحماية.

هناك مفهوم آخر يجب أخذه في الاعتبار هو أن de TX / RX مزروع بمستويات جهد مختلفة في كلا الجهازين. يعمل ESP8266 بين 0 و 3.3 فولت ، يعمل Nano بين 0 و 5 فولت. ونظرًا لأن Nano قادر على اكتشاف 3.3V كدولة عالية ، يمكنك توصيل RX على Nano مباشرةً إلى TX على ESP8266. ولكن على العكس من ذلك ينصح مقسم التوتر لحماية المدخلات RX مع الجهد المناسب 3.3V عندما عالية.

... الشيء هو أن لي والعديد من الآخرين قد فحص أنه يعمل بشكل جيد خلال أشهر دون الحاجز التوتر ، ويبدو ESP8266 المحمية بما فيه الكفاية. لكن لا تثق بي ، افعل ذلك جيداً.

ضبط جهاز استشعار درجة الحرارة
ما نراه هو أنه يحتوي على 3 دبابيس فقط. سيكون "+" هو المكان الذي سيتم فيه توفير 5 فولت ، حيث يتم توصيله بـ "5V" من لوحة Nano. "-" هي الأرضية المشتركة مع بقية المكونات. و "الخارج" ليس ناتجا تناظريا أو مقاوما كما قد يخمنه المرء ، بل هو في الواقع ناتج تسلسلي رقمي حيث أن هذا المستشعر مزود بمكونات ذكية على متنه.


لا تقلق بشأن هذا البروتوكول ، كما هو موضح في الأقسام التالية ، سنجد بسهولة مكتبة Arduino التي تسمح لك بإدارتها دون جهد. يبدو أن مواصفات هذا البروتوكول يصعب العثور عليها بسبب نقص المعلومات (باللغة الصينية فقط) فقط للحالة التي تهتم بها.

سنقرأ هذا الاتصال التسلسلي على رقم التعريف الشخصي 5 في مثالنا (نعم ، يمكن أن يكون أي دبوس رقمي آخر من اللوح الخاص بك بينما تضعه في الاعتبار عند الترميز).

لذلك ، الاتصال ببساطة كما يلي
الأداة الكاملة
يجب أن يكون كل ذلك متصلاً هكذا:


تسجيل دبوس على الخدمة عبر الإنترنت
اتبع العملية للاشتراك في circusofthings.com إذا لم يكن لديك حساب حتى الآن. انها حرة وتبحث عن اختبار.

في لوحة البيانات الخاصة بك ، قم بإنشاء "إشارة جديدة". لاحظ أنه يعرض مفتاحًا يحدد الإشارة. تذكر ذلك للخطوة التالية



ترميز وتحميل البرنامج
قبل ضبط الرمز ، سيكون عليك الحصول على بعض مكتبات Arduino:

مكتبة DHT الاستشعار ، للتواصل مع مجس. أحضره هنا.
CircusWifiLib ، لتنفيذ API للمجتمع عبر الإنترنت. أحضره هنا.
(أنت لا تحتاج إلى أي lib لـ Wifi / ESP8266 كما تتم بواسطة CircusWifiLib).

الآن يمكننا إلقاء نظرة على الكود:
#include <CircusWifiLib.h>
// ------------------------------------------------
// These are the CircusWifiLib related declarations
// ------------------------------------------------
int TXPinForWifiModule = 2; // IO port in your arduino you will use as TX for serial communication with the wifi module
int RXPinForWifiModule = 3; // IO port in your arduino you will use as RX for serial communication with the wifi module
char ssid[] = "your_ssid_here"; // your wifi network SSID
char pass[] = "your_wifi_password_here"; // your wifi network password
int wifiSerialBaudRate = 9600; // Baud rate between your arduino and your wifi module. Did you check that your module actually uses this baud rate?
int debugSerialBaudRate = 9600; // Baud rate between your arduino and your computer
char token[] = "your_token_here"; // Your API token for Circus
char analogSignalTemperatureKey[] = "944668525"; // The key of the signal you have created at circusofthings.com
SoftwareSerial ss(RXPinForWifiModule,TXPinForWifiModule);
CircusWifiLib circus(Serial,&ss,ssid,pass,DEBUG_YES,KEEP_ALIVE);
// ------------------------------------------------
// These are the Example related declarations
// ------------------------------------------------
#define DHTPIN 5 // digital for serial propietary portocol of sensor DHT11
#define DHTTYPE DHT11 // exact model of temperature sensor DHT 11 for the general library
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(debugSerialBaudRate);
ss.begin(wifiSerialBaudRate);
dht.begin();
circus.begin();
}
void loop() {
float t = dht.readTemperature();
if (isnan(t)) {
t=-1; // if so, check the connection of your DHT11 sensor
}
delay(3000);
circus.write(analogSignalTemperatureKey,t,token);
}

ضع SSID الخاص بـ WIFI بدلاً من your_wifi_SSID_here.

ضع كلمة مرور WIFI بدلاً من your_wifi_password_here.

ضع رمز حسابك بدلاً من your_user_token_here.

ضع مفتاح الإشارة التي أنشأتها بدلاً من your_signal_key_here.

سيحصل الرمز أعلاه على قيمة المستشعر كل 3 ثوانٍ وسيقوم بنشره على الإشارة المحددة بواسطة المفتاح الذي تملكه.

كما يلي


وفتح الشاشة التسلسلية من IDE (إشعار في حالتنا قمنا بتعيين 9600 baud لتصحيح)


هل تصل إلى الويب؟

إذا سار كل شيء بشكل صحيح ، فيجب أن تشاهد الإشارة  والتي توضح درجة الحرارة التي لديك بالفعل في غرفتك

الآن ، يمكنك تعديل مستوى رؤيتها في لوحة التحكم وتعيينها للجمهور.

ثم لديك الرابط لمشاركتها مع أولئك الذين ليس لديهم حساب 

يمكن الوصول إليه الآن من خلال أي جهاز أو تطبيق آخر في العالم.

يمكن لأي شخص يتابع البرنامج التعليمي التالي لدينا الحصول على البيانات من السحابة إلى Arduino الخاص بك وقراءة هذه الإشارة من لوحة اردوينو.

آمل أن تكون مثيرة للاهتمام بالنسبة لك. شكرا على انتباهك