현재 상태 : PC와의 UPD 통신, PWM, Motor Controller 용 GPIO, Encoder Reading 완료.

추가할 내용 : Timer Interrupt, I2C for GY-BNO055, PID 

#include <WiFi.h>
#include <WiFiUdp.h>
#include <Wire.h>
#include "Parse.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>


// ESP32's I2C Pin No.
#define _ESP32_HAL_I2C_H_

#ifdef _ESP32_HAL_I2C_H_
#define SDA_PIN 32
#define SCL_PIN 12
#endif

#define BUFFER_SIZE 100

#define THIS_MACHINE "002"  // Set this bot's no. : 2
const int ThisMachine = 2;

//IP address to send UDP data to:
const char * udpAddress = "192.168.1.100"; // 저의 PC의 고정주소
const int udpPort = 6767;    // 제가 로봇용으로 주로 사용하는 포트번호

const char serverip[]="192.168.1.100";
char packetBuffer[255];

//The udp library class
WiFiUDP udp;

//Are we currently connected?
boolean connected = false;

float ax, ay, az, aSqrt, gx, gy, gz, mDirection, mx, my, mz;

const char * host = "ESP32-02";
const char * networkName = "****";  // 집이나 사무실 와이파이 아이디
const char * networkPswd = "****";  // 와이파이 연결 비밀번호
char botresp[50] = "001-CCCC:4,000,000,000,000";  // default init size should be size of string + 1

String ToServerStr;

char ReplyBuffer[] = "acknowledged"; // a string to send back
unsigned long preMillis = 0;
unsigned long curMillis = 0;

///////////  BNO-055
TwoWire I2CBNO = TwoWire(0);
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x29, &I2CBNO);
double xPos = 0, yPos = 0, headingVel = 0;
uint16_t BNO055_SAMPLERATE_DELAY_MS = 10; //how often to read data from the board

void ExecuteLogicalCommand() {
   // WHON : Wheel StandBy : Params ( on / off )
   if (((char)p2b_command[0] == 'W') and ((char)p2b_command[1] == 'H')) { 
      if (debugSerial) {
         s = "<*WHON=";  s += p2b_paramcount; s += ">";     
         Serial.println(s);
      }
      digitalWrite(StandBy, param1);
      reset_encoder_count();
   }; 

   // FWDM : Forward Move 양 바퀴 전진, 첫 파라메터는 좌측 바퀴 속도, 둘째는 우측 바퀴 속도.
   if (((char)p2b_command[0] == 'F') and ((char)p2b_command[1] == 'W')) { 
      if (debugSerial) {
         s = "<*FWDM=";  s += p2b_paramcount; s += ">";     
         Serial.println(s);
      }
      reset_encoder_count();
      // Left Wheel (A)
      digitalWrite(Ain1, 1);
      digitalWrite(Ain2, 0);
      ledcWrite(WheelChannelLeft, param1);
      // Right Wheel (B)
      digitalWrite(Bin1, 0);
      digitalWrite(Bin2, 1);
      ledcWrite(WheelChannelRight, param2);   
   }; 

      // BWDM : Backward Move 양 바퀴 후진, 첫 파라메터는 좌측 바퀴 속도, 둘째는 우측 바퀴 속도.
   if (((char)p2b_command[0] == 'B') and ((char)p2b_command[1] == 'W')) { 
      if (debugSerial) {
         s = "<*BWDM=";  s += p2b_paramcount; s += ">";     
         Serial.println(s);
      }
      reset_encoder_count();
      // Left Wheel (A)
      digitalWrite(Ain1, 0);
      digitalWrite(Ain2, 1);
      ledcWrite(WheelChannelLeft, param1);
      // Right Wheel (B) // Currently one signal not working on B (33, 34)
      digitalWrite(Bin1, 1);
      digitalWrite(Bin2, 0);
      ledcWrite(WheelChannelRight, param2);
   };    

}  

void setupControlPins(){ 
   freq = 5000;
   resolution = 8;
   StartingSpeed = 0; // 0 - 255 (8 bit)   

   ledcSetup(WheelChannelLeft,  freq, resolution);
   ledcSetup(WheelChannelRight, freq, resolution);

   ledcAttachPin(WheelLeft,  WheelChannelLeft);
   ledcAttachPin(WheelRight, WheelChannelRight);

   ledcWrite(WheelRight, StartingSpeed);
   pinMode(Ain2, OUTPUT);
   pinMode(Ain1, OUTPUT);
   pinMode(StandBy, OUTPUT);
   pinMode(Bin1, OUTPUT);
   pinMode(Bin2, OUTPUT);
   ledcWrite(WheelLeft,  StartingSpeed);

   // Two encoder pins for wheels
   pinMode(Encoder2_A_Left, INPUT);
   pinMode(Encoder2_B_Right, INPUT);
}

void reset_encoder_count() {  // Reset before start moving
   count_AL = 0;
   count_BR = 0;
   last_count_AL = 0;
   last_count_BR = 0;
}

void ISR_Left_Encoder() {
   count_AL++;
}

void ISR_Right_Encoder() {
   count_BR++;
}

void setup() {
  
   setupControlPins(); // IO 핀들 세팅할 것.

   // 모든 시리얼은 드론에는 사용 못하고 다른 ESP32 Development Board에서 개발/디버깅 중에만 사용 가능합니다.
   Serial.begin(115200);  // 시리얼을 안쓰더라도 반드시 이렇게 놔 둘 것.

   //Connect to the WiFi network  네트웍에 연결
   connectToWiFi(networkName, networkPswd);

   // Wait for connection
   while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
   }   

   // 모든 시리얼은 무선 작동시에는 사용 못하고 디버깅 중에만 사용 가능합니다.

/*   Wire.begin(SDA_PIN, SCL_PIN); // ESP32는 반드시 이렇게.
   //Serial.println("I2C enabled! ");

   I2CBNO.begin(SDA_PIN, SCL_PIN);
   if (!bno.begin()){
      Serial.print("No BNO055 detected");
      while (1);
   } */

   delay(1000);

   r = 0;

   // Encoder Setting
   pinMode(Encoder2_A_Left, INPUT_PULLUP);
   attachInterrupt(Encoder2_A_Left, ISR_Left_Encoder, FALLING);
   pinMode(Encoder2_B_Right, INPUT_PULLUP);
   attachInterrupt(Encoder2_B_Right, ISR_Right_Encoder, FALLING);
}

void uPrint(){   // print whatever in "udpStr" with station # and ending ">"
   s = "#";  s += THIS_MACHINE;  s += ":"; s += udpStr; s += ">";
   udp.beginPacket(udpAddress,udpPort);
   udp.print(s);
   udp.endPacket();
}

void loop() {
   r++;

   if ((r % 3000) == 0){ 
      if(connected){
         //Send a packet
         udpStr = "#L/R: "; udpStr += count_AL; udpStr += ", ";  udpStr += count_BR; ;
         uPrint(); // it prints whatever in udpString      
      }
   }

   // Expected message format : <002-MECH:4,10,10,70,70>
   // "<"  beginning mark, 002 mechine no., MECH command, 4 params, + 4 values ,">" ending mark 
   //  3 digit machine no., 4 char command, # of params, params seperated by ","
   int packetSize = udp.parsePacket();
   if (packetSize) {
        
      int len = udp.read(packetBuffer, 255); // here, len = packetSize
      if (len > 0) {
         packetBuffer[len] = 0;
         if (len < 51) {
            for (i=1;i<51;i++)
               botresp[i+3] = packetBuffer[i];            
         }
      };  
      i = 0;

      while ((packetSize) >= i){
         inChar = packetBuffer[i];  // get the new byte:
         inputString[i] = inChar;
         i++;
      
         // if the incoming character is a newline, set a flag
         if ((inChar == '#') or (inChar == '<')) {
            p2b_status = P2B_STAT_CMD;
            ClearP2BCommand();
            j = i-1;         
            // ===== Debug Purpose =====
            Serial.println("시작점  #, <");
            
         } else if (inChar == '>') {  // so the main loop can do something about it:

            // First, get the machine # first, who is this command to
            p2b_machno  = 0;
            if (inputString[j+1] != '0') {
               p2b_machno = (int(inputString[j+1])-48) * 100;
            }
            if (inputString[j+2] != '0') {
               p2b_machno = p2b_machno + (int(inputString[j+2])-48) * 10;
            }
            if (inputString[j+3] != '0') {
               p2b_machno = p2b_machno + (int(inputString[j+3])-48);
            }
 
            // If this command is for ME (This machine)
            if (ThisMachine == p2b_machno){
           
               p2b_mach[0] = inputString[j+1];
               p2b_mach[1] = inputString[j+2];
               p2b_mach[2] = inputString[j+3];
               
               p2b_command[0] = inputString[j+5];
               p2b_command[1] = inputString[j+6];
               p2b_command[2] = inputString[j+7];
               p2b_command[3] = inputString[j+8];

               p2b_paramcount = int(inputString[j+10])-48; // take out 0

               Serial.print("Machine : ");
               Serial.println(p2b_machno); 
               Serial.print("Command :");
               Serial.println(p2b_command); 
               Serial.print("Parameter Count : ");
               Serial.println(p2b_paramcount);              

               j = j + 12;  // now j is pointing param starting position 
               if (p2b_paramcount > 0) {
                  tempVal = 0; 
                  nPos = 0;
                  k = 1;
                  for (n=j;n<=packetSize;n++){
                     // end of param 
                     if ((inputString[n] == ',') or (inputString[n] == '>')){  
                        if (k == 1){
                           param1 = tempVal;
                           Serial.print("Param 1 : ");
                           Serial.println(param1);
                        }
                        if (k == 2){
                           param2 = tempVal;
                           Serial.print("Param 2 : ");
                           Serial.println(param2);
                        }
                        if (k == 3){
                           param3 = tempVal;
                           Serial.print("Param 3 : ");
                           Serial.println(param3);
                        }
                        if (k == 4){
                           param4 = tempVal;
                           Serial.print("Param 4 : ");
                           Serial.println(param4);
                        }
                        tempVal = 0; 
                        k++;  // Param No.
                        nPos = 0;
                     } else {
                        if (nPos == 1) {
                           tempVal = (byte(inputString[n]) - 48); 
                        } else {
                           tempVal = tempVal * 10 + (byte(inputString[n]) - 48); 
                        }
                     }
                  }
               }
            //   Serial.println("");  
            
               ExecuteLogicalCommand();
            } // end of if command is for this Machine
         
            i = 100;  // refresh counter
            stringComplete = true;
            p2b_status = P2B_STAT_NONE;
            
         } else {
            lp = i-1;  // set last position on each entry;
         }
      }
   }   //  while ((packetSize) >= i){
 
   if (stringComplete) {
      ClearParamsAndInputstring(); 
   };      

   if (r == 5000) { 
//      if (contGetAll) {  GetAll();     }
//      if (contAccel)  {  Get3DAccel(); } 
//      if (contGyro)   {  Get3DGyro();  } 
//      if (contMag)    {  Get3DMag();   }  
//      if (contHeight) {  GetHeight();  }        
   }
   
   // Reset r
   if (r > 1000000) { r = 0; }

}

void connectToWiFi(const char * ssid, const char * pwd){
  Serial.println("Connecting to WiFi network: " + String(ssid));

  // delete old config
  WiFi.disconnect(true);
  //register event handler
  WiFi.onEvent(WiFiEvent);
  
  //Initiate connection
  WiFi.begin(ssid, pwd);

  connected = true;

  Serial.println("Waiting for WIFI connection...");
}

//wifi event handler
void WiFiEvent(WiFiEvent_t event){
    switch(event) {
      case SYSTEM_EVENT_STA_GOT_IP:
          //When connected set 
          Serial.print("WiFi connected! IP address: ");
          Serial.println(WiFi.localIP());  
          //initializes the UDP state
          //This initializes the transfer buffer
          udp.begin(WiFi.localIP(),udpPort);
          connected = true;
          break;
      case SYSTEM_EVENT_STA_DISCONNECTED:
          Serial.println("WiFi lost connection");
          connected = false;
          break;
      default: break;
    }
}

 

Parse.h 화일

int P2B_NEWLINE  = 11; // < -- Beginning of Command to Remote Control that controls R/C Car
int P2B_COM_TYPE = 12; // 0..9 -- First 2 letters following "<"
                       // Total Command Types : 10 x 10 = 100
int P2B_DATA     = 12; // Data section
int P2B_ENDING   = 13; // > -- End of Message Signal

int P2B_STAT_NONE = 1; // Do nothing until '<' has received
int P2B_STAT_CMD  = 2; // Accepting Command
int P2B_STAT_DATA = 3; // Accepting Command data
int P2B_STAT_END  = 4; // '>' has receieve, it is the end of   command;

char p2b_mach[4];
char p2b_command[5];
char p2b_data[50];
int  p2b_machno = 0;
int  p2b_paramcount = 0;
int  p2b_status = 0;

int i = 0; // dumb int
int j = 0; // dumb int
int k = 0; // dumb int
int n = 0; // dumb int
int lp =0; // dumb last position of input command string

int r = 0; // Simple Counter to replace delay() in the main loop

String s; // Temporary string for general purpose
String udpStr; 

boolean debugSerial = false;

char    inputString[200];           // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
char    inChar;
String  tempStr;
char    buffer[12]; // buffer used for itoa  (int to string conversion)
int     inlen = 0;  // Length of inputString
char    RemoteString[50];    
// value from PC Command (integer params 1 .. 4 max) 
int     paramcount = 0; // How many params in input String
int     param1 = -1;  // value from PC Command (Param 1)
int     param2 = -1;  // value from PC Command (Param 2)
int     param3 = -1;  // value from PC Command (Param 3)
int     param4 = -1;  // value from PC Command (Param 4)

int tempVal = 0;
int nPos = 1;

float fparam1 = 0.0; 
float fparam2 = 0.0; 
float fparam3 = 0.0; 
float fparam4 = 0.0; 

boolean SecondParam = false;   // Now gettign second parameter (after ,)

// Wheel PWM Related Definitions
// A = Left, B = Right

int WheelChannelLeft  = 0; // motor A PWM Channel
int WheelChannelRight = 1; // motor B PWM Channel

// NEW PINS 19, 23, 26, 5, 18
const int WheelLeft  = 19; // GREY - motor A on my design sheet
const int Ain2 = 25;       // WHITE
const int Ain1 = 23;       // ORANGE
const int StandBy = 5;     // YELLOW
const int Bin1 = 14;       // PINK (34 didn't work, changed to 14
const int Bin2 = 33;       // BROWN
const int WheelRight = 18; // BLUE - motor B on my design sheet

// Speed Read from Encoder
const int Encoder2_A_Left  = 36;  // Yellow Color 
const int Encoder2_B_Right = 26;  // Yellow Color 
int count_AL = 0;
int count_BR = 0;
int last_count_AL = 0;
int last_count_BR = 0;

int freq = 5000;
int resolution = 8;

int StartingSpeed = 0; // 0 - 255 (8 bit)

int targetHeight = 0;
int msAi = 0;  
int msBi = 0;
int msCi = 0;
int msDi = 0;
int maximumSpeed = 50;

int height = 0;
int targetLR = 0;  // Target Left/Right
int targetFB = 0;  // Target Forward / Backward
int targetTN = 0;  // Target Turn (+ CW, - CCW)

boolean contMag = false;
boolean contAccel = false;
boolean contGyro = false;
boolean contHeight = false;
boolean contGetAll = false;
boolean AutoBalancing = true;
boolean NoOffset = false;

////////////////////////////////////////////////////////////////

void ClearP2BCommand() {
   p2b_mach[0] = 0;  // null
   p2b_mach[1] = 0;  // null
   p2b_mach[2] = 0;  // null
   p2b_mach[3] = 0;  // null   
     
   p2b_command[0] = 0;  // null
   p2b_command[1] = 0;  // null
   p2b_command[2] = 0;  // null   
   p2b_command[3] = 0;  // null
   p2b_command[4] = 0;  // null 
   for (int i=0; i <= 49; i++){
      p2b_data[i] = 0;  // null
   }
   p2b_machno = 0;

   // set as none, 0 could be value
   param1 = -1;  // 
   param2 = -1;  // 
   param3 = -1;  // 
   param4 = -1;  // 

   SecondParam = false;
}

void ClearRemoteString() {
   for (i=0;i<=49;i++) {
      RemoteString[i] = 0;
   };
}

void ClearParamsAndInputstring(){
   // clear the string:
   for (i=0;i<=49;i++) {
      inputString[i] = 0;
   };
   i = 0;
   j = 0;

   paramcount = 0; // How many params in input String
   param1 = -1; 
   param2 = -1; 
   param3 = -1; 
   param4 = -1; 
   
   fparam1 = 0.0; 
   fparam2 = 0.0; 
   fparam3 = 0.0; 
   fparam4 = 0.0;
      
   stringComplete = false;
}

'ESP32 BOT > My ESP32 Bot' 카테고리의 다른 글

My ESP32 Bot - The beginning.  (0) 2021.11.03

+ Recent posts