2022年11月2日 星期三

ESP8266-01透過I2C讀取MPU6500六軸自由度

ESP8266-01這塊雖然只有8個腳位,但假如扣除VDD、GND、RST和CH_PD,實際上板子本身有幫你引出的GPIO就有4個,網路上也有其他創作者拉引腳方式讓GPIO有10腳位可以控制,嚴格算起來還蠻多得。

以下示範是ESP8266-01和MPU6500間透過I2C傳送資料並且打印上相同區網手機瀏覽器上,並以每500毫秒自動更新數據。
可以透過以下網址下載程式碼:下載連結


  Wire.beginTransmission(MPU);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,14,1);  // request a total of 14 registers
  AcX = Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY = Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)]
  AcZ = Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  NowTemp = Wire.read()<<8|Wire.read();
  GyX = Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY = Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ = Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  
MPU這個放入的參數為:0x68,代表I2C位址,至於0x3B0x3D0x3F...等這些,是取決於你要抓取MPU6050.h這個開頭檔裡面什麼位子什麼數值。

至於剩下的WebServer部分就大多參考ESP8266所提供的範例了。




上述如果有錯誤或是更好的方法,提醒和交流我會非常感激。

2022年2月9日 星期三

arduino和esp8266透過promiscuous mode 接收所有經過它的數據(sniffer)

1.eps8266在使用混雜模式(英語:promiscuous mode)情況下,沒辦法抓取到握手包。
2.然而如果要在wireshark情況下分析也需要了解.pcapng檔格式,下方程式內也都包含了.pcapng開頭結尾檔格式。



這部分是混雜模式下開頭檔格式
對稱1為Section Header Block (SHB)
    0x0000001C(Hex)為28(Dec),所以表示從0x0A0D0D0A到0x0000001C總共有28byte
對稱2為Interface Description Block (IDB)
程式1:

  serialwrite_32(0x0A0D0D0A);
  serialwrite_32(0x0000001C);    //對稱1--
  serialwrite_32(0x1A2B3C4D);
  serialwrite_32(0x00000001);
  serialwrite_32(0xFFFFFFFF);
  serialwrite_32(0xFFFFFFFF);
  serialwrite_32(0x0000001C);    //對稱1--

  serialwrite_32(0x00000001);
  serialwrite_32(0x00000014);    //對稱2--
  serialwrite_32(105);
  serialwrite_32(0x0000FFFF);
  serialwrite_32(0x00000014);    //對稱2--

我需要確保這個funtion回傳的len是要4的倍數。
程式2:

  if (len / 4 != 0)
  {
    len += 4 - (len % 4);
  }

對稱3為Enhanced Packet Block (EPB)
當esp8266從空中抓到任何封包轉成.pcapng格式需要頭尾格式,再來就是格式裡面有一個重要需要注意的(Packet Data variable length, padded to 32 bits),收到的資料不管是127還是多少,都需要補足到132。
其中一定會好奇為什麼我會多打入兩組0x00000000,這是固定需要補足的地方,上面程式2是捕到4的倍數,但這是需要補到132byte,wireshark才有辦法做分析
程式3:

  serialwrite_32(0x00000006);
  serialwrite_32(len + 36);    //對稱3--
  serialwrite_32(0x00000000);
  
  serialwrite_32(timestamp);
  serialwrite_32(microseconds);
  serialwrite_32(incl_len);
  serialwrite_32(orig_len);
  
  char bufStr[1] = { 0 };
  char *zero = 0;
  for (int i = 12 ; i <= len ; i++)
  {
    sprintf(bufStr, "%02X ", buf[i]);
    Serial.print(bufStr);
    if ((len / 4) != 0 && i == len)
    {
      for (int k = 1 ; k <(4 - (len % 4)) ; k++)
      {
        sprintf(bufStr, "%02X ", zero);
        Serial.print(bufStr);
      }
    }
  }
  serialwrite_32(0x00000000);
  serialwrite_32(0x00000000);
  serialwrite_32(orig_len);
  serialwrite_32(len + 36);    //對稱3--

以下是完整程式碼
#include <ESP8266WiFi.h>

unsigned long time_ = 0;

#define HOP_INTERVAL 214
#define MAX_CHANNEL 11
#define CHANNEL 1
unsigned long lastChannelChange = 0;
int ch = CHANNEL;
char macStr[18] = { 0 };
int input_need_catch_count , count_number = 0;
bool CHANNEL_HOPPING = true;

void sniffer(uint8_t *buf, uint16_t len) 
{
  uint32_t timestamp = 0;
  uint32_t microseconds = (unsigned int)(micros() - millis() * 1000); //micro seconds offset (0 - 999)

  if (len / 4 != 0)
  {
    len += 4 - (len % 4);
  }
  
  uint32_t orig_len = len;
  uint32_t incl_len = len;
  
  serialwrite_32(0x00000006);
  serialwrite_32(len + 36);
  serialwrite_32(0x00000000);
  
  serialwrite_32(timestamp);
  serialwrite_32(microseconds);
  serialwrite_32(incl_len);
  serialwrite_32(orig_len);
  
  char bufStr[1] = { 0 };
  char *zero = 0;
  for (int i = 12 ; i <= len ; i++)
  {
    sprintf(bufStr, "%02X ", buf[i]);
    Serial.print(bufStr);
    if ((len / 4) != 0 && i == len)
    {
      for (int k = 1 ; k <(4 - (len % 4)) ; k++)
      {
        sprintf(bufStr, "%02X ", zero);
        Serial.print(bufStr);
      }
    }
  }
  serialwrite_32(0x00000000);
  serialwrite_32(0x00000000);
  serialwrite_32(orig_len);
  serialwrite_32(len + 36);
  ++count_number;
  if (count_number == input_need_catch_count)
  {
    CHANNEL_HOPPING = false;
    wifi_promiscuous_enable(0);
  }
}


void setup() 
{
  uint8_t mac[6];
  Serial.begin(115200);
  wifi_set_opmode(STATION_MODE);
  WiFi.begin("Fan", "66666663");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.hostname());
  
  Serial.print("\n inpute need catch count:");
  while(input_need_catch_count <= 1)
  {
    input_need_catch_count = Serial.parseInt();
  }
  Serial.println(input_need_catch_count);
  Serial.println("\n -> WiFi Sniffer");
  Serial.println(" -> Initializing!");
  wifi_promiscuous_enable(0);
  wifi_station_disconnect();
  wifi_set_promiscuous_rx_cb(sniffer);
  wifi_promiscuous_enable(1);
  Serial.println(" -> Init finished!\n");
  time_ = millis();
  Serial.println("-----");
  wifi_get_macaddr(STATION_IF, mac);
  sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  Serial.println(String(macStr));
  wifi_get_macaddr(SOFTAP_IF, mac);
  sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  Serial.println(String(macStr));
  Serial.println("-----");
  serialwrite_32(0x0A0D0D0A);
  serialwrite_32(0x0000001C);
  serialwrite_32(0x1A2B3C4D);
  serialwrite_32(0x00000001);
  serialwrite_32(0xFFFFFFFF);
  serialwrite_32(0xFFFFFFFF);
  serialwrite_32(0x0000001C);

  serialwrite_32(0x00000001);
  serialwrite_32(0x00000014);
  serialwrite_32(105);
  serialwrite_32(0x0000FFFF);
  serialwrite_32(0x00000014);
}
 
void loop()
{
  if(CHANNEL_HOPPING)
    {
      unsigned long currentTime = millis();
      if(currentTime - lastChannelChange >= HOP_INTERVAL){
        lastChannelChange = currentTime;
        ch++; //increase channel
        if(ch > MAX_CHANNEL) ch = 1;
        wifi_set_channel(ch); //switch to new channel
      }
    }
}


void escape32(uint32_t n, uint8_t* buf)
{
  buf[0] = n;
  buf[1] = n >>  8;
  buf[2] = n >> 16;
  buf[3] = n >> 24;
}

void serialwrite_32(uint32_t n)
{
  uint8_t _buf[4];
  char bufStr[4];
  escape32(n, _buf);
  sprintf(bufStr, "%02X %02X %02X %02X ", _buf[0], _buf[1], _buf[2], _buf[3]);
  Serial.print(bufStr);
//  Serial.write(_buf, 4);
}



最後我會直接輸入需要抓幾個封包,但通常很容易都會多抓

上述如果有錯誤或是更好的方法,提醒和交流我會非常感激。