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);
}



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

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

2020年10月25日 星期日

PL2303HXA 三用電表量測後發現是芯片內部5V轉3.3V失敗 導致讀不到COM PORT(已解決)

 



量測到這部分發現實際電壓輸出只有1V多,內部變壓失效,所以改攻3V3OUT這個(輸出PIN腳)

為何標示其為紅色?因為重點就在這一般我們都會當成他沒辦法做輸入,但測試強制輸入電壓進去是沒問題的。

以下為更改的步驟:

1.首先弄清楚IC的VCC腳位在20腳,3.3V腳位在17腳,為什麼先提及這兩隻腳?首先要把這兩隻腳解焊,20和17的腳位可以拉空或是剪掉。

2.再來另外做出3.3v的電源供應R1為51歐姆、R2為110歐姆其實抓個大概電壓有在3.3V左右就可以。
3.5V的部分就焊USB電壓來源(5V),GND就焊在USB的GND,至於3.3V就焊接到下圖紅色圈圈電阻的左邊


4.完成後就會像下圖(杜邦線的顏色請別太在意)

焊接完成後我在Win10作業系統無法動作,所以改在Win7作業系統測試是可以的,測試模組為HM-10。
1.這部分比較麻煩的是我是用焊槍作焊接,所以要小心芯片腳位會有短路問題,當然在焊接完      成後不管是5V和GND或是3.3V和GND,都要去量是否有短路才可以接上電腦。
2.對此這款pl2303hxa driver在Win8以上會無法使用,這部分就需要自行去網路上找資料,畢竟這方面的東西很多,所以這裡就不多做解釋

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

2020年9月20日 星期日

convert 'const char*' to 'String' in initialization

 如標題所述我要讓string 轉為 char*

前提:會使用到toCharArray()length()這個兩個Function

流程:

1.有可能會像我一樣從Serial monitor輸入一組string或是寫另一組C# Farmework做輸入

2.要做出兩種宣告

char str[insert_str.length() + 1];
char *str1[insert_str.length() + 1];

insert_str 為輸入string

3.把insert_str轉為字串需要用到toCharArray()

insert_str.toCharArray(str , insert_str.length() + 1);
//一定要多+1個位子,在arduino Reference裡有特別標示string - char array後一定要多加空字符

 4.利用for迴圈把char放入*char

for (int i = 0 ; i <= insert_str.length() ; i++)
{
 str1[i] = &str[i];
}

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

2017年8月4日 星期五

Arduino limit switches 軟碟機內極限開關

既上次的步進馬達後,老早就想研究旁邊的一顆極限開關,下圖中藍色框框

拆下來後變成,下圖我也已經自行焊上三條線方便接上麵包板



下圖是接腳和電路圖(電阻值不一定要一樣上下不要差太多都是可以的)



下列為程式碼:
int swPin = 8;     // input
int LEDPin = 13; // output

void setup()                    // run once, when the sketch starts
{
  pinMode(LEDPin, OUTPUT);      // sets the digital pin as output
  Serial.begin(9600);
}

void loop()                     // run over and over again
{
  if (digitalRead(swPin)) {
     Serial.println("HIGH");
     digitalWrite(LEDPin,HIGH);
  }
  else {
     Serial.println("LOW"); 
     digitalWrite(LEDPin,LOW);
  }
}


在程式裡我寫出兩個反應方式:
1.再監控視窗裡,如果極線開關中間有東西阻隔,便會打印出HIGH,反之是LOW
2.Arduino板上第13隻接腳就有LED,而極線開關中間有東西阻隔,便會亮燈,反之滅燈

最後最後附上影片

2017年5月28日 星期日

Arduino 軟碟機內步進馬達控制

在家裡電腦硬碟壞了,所以又來了一顆新硬碟,才順手把電腦裡的軟碟機拆了
拆開後會發現上方的小步進馬達,原諒我沒有花多的時間查這顆步進馬達的參考資料。
但就我想破頭網路上很多大大相關步進馬達控制的資料,不外乎都要用到ULN2003或是H橋式電路來控制。
在我為這顆步進馬達接線出來後只看到四條接腳,秉持著實驗精神也堅持不購入ULN2003,最後在我只單純用5V和GND就可以控制其前進後退(這點如果有興趣的可能要自行去研究嘍),這方法麻煩的是四隻接腳要不停的在5V和GND間來回才會讓馬達動起來。

馬達接腳和Arduino接腳圖
接腳由右到左接上Arduino是2.3.4.5(在這樣做前我有先用三用電表量測哪兩隻接是一對的),可能很多人好奇這怎麼可以直接接上Arduino,一方面我覺得可能這種小步進馬達電壓電流要求不高,單單晶片上的控制訊號就可以達到啟動步進馬達動作。

但在操作上我發現如果有附載(如圖的讀頭部分)可能電壓不夠,動作做不太出來只要稍微對其加壓或是去除附載就可以完全動作嘍

以上個人小實驗,如有錯誤一定要跟我說!

2017年1月14日 星期六

Arduino nano 燒壞和維修方法

  有接觸到arduino 的人一定會遇到晶片不小心接短路燒壞了





於是放手一搏後





把圖中B2零件(這是我看零件上的數字碼)解焊候用單心線接上就可以通電了
在沒接上單心線前上電也不會亮燈(理所當然的是燒壞也不會亮)
於是乎修好後上電,燈正常亮動作也正常
或許那個零件就是保護晶片短路燒毀所以的措施,但在接下來的日子可能就要保佑不會再接短路嘍!