highlight.js

星期一, 11月 27, 2017

ESP8266 Arduino Core 中 ctype.h 內預先定義的常數

我在編譯 ESP8266 的 Arduino 程式時, 遇到一個莫名其妙的事情, 底下這行程式碼一直遇到編譯錯誤:
    double _N;        //-- Number of samples
錯誤訊息如下:
expected unqualified-id before numeric constant 
想說, 奇怪, 這裡哪來的數值常數?找了一下才發現, 原來 ESP8266 Arduino Core 中 ctype.h 定義了 _N 為 04, 如下:
#define  _U  01
#define _L  02
#define _N  04
#define _S  010
#define _P  020
#define _C  040
#define _X  0100
#define _B  0200
所以如果你的程式中使用到了 _N, 就會變前處理器取代成 04, 我的那一行程式就變成:
    double 04;        //-- Number of samples
自然無法編譯成功了。要注意的是, 除了我碰到的 _N 外, 還有許多已經被 ctype.h 事先定義的名稱, 如果你遇到的奇怪的編譯結果, 可以到原始碼找看看, 可能你也跟我一樣遇到類似的情況, 解決的方法最簡單的就是更改自己的程式變數名稱, 避免和 ESP8266 Arduino Core 中的名稱衝突。

星期五, 11月 17, 2017

ESP8266 的 EEPROM 注意事項

在 ESP8266上使用 EEPROM 要注意兩件事, 首先是必須叫用 EEPROM.begin(), 並指定要使用的 EEPROM 區域大小:
  EEPROM.begin(sizeof(int) * 4);
其次, 寫入 EEPROM 的操作必須叫用 EEPROM.commit() 才會真的儲存下來:
  EEPROM.commit();
這是和 Arduino 不同的地方。如果同一個程式希望在 Arduino 和 ESP8266 上都能編譯,可以使用 ESP8266 Arduino Core 在前處理器上定義的名稱 ESP8266 來做條件式編譯, 例如:
  #ifdef ESP8266
  EEPROM.commit();
  #endif
這樣就只會在編譯 ESP8266程式時叫用 commit(), 若式編譯 Arduino 程式時, 這一行就不會生效了。

星期四, 11月 16, 2017

小心, ESP8266 有看門狗 (Watch Dog Timer)

ESP8266 雖然有 Arduino Core 可以直接用 Arduino IDE 寫程式, 不過 ESP8266 畢竟不是 Arduino, 有些硬體上的差異還是可能讓你的程式掛掉, 今天就遇到一個搞死我的問題。我有一個機器人的程式, 跑一些動作時 ESP2866 就會 reset, 本來以為是供電不足, 但馬達單獨供電還是會 reset, 開了 Serial 看資料才發現, reset 時有以下訊息:
Soft WDT reset


ctx: cont
....
原來 ESP8266 有看門狗計時器 (Watch Dog Timer), 程式會在 loop() 結束或是呼叫 delay() 時更新看門狗計時器, 如果很長一段時間沒有更新看門狗計時器, 就會啟動 reset 機制, 警告你程式某些地方有閒置過久的問題。舉例來說, 如果你在 ESP8266 上跑以下這個在 loop() 中閒置 10 秒的程式:
void setup() {
  Serial.begin(9600);
  Serial.println("Begin testing");
}

unsigned long prevTime;

void loop() {
  prevTime = millis();
  while(millis() - prevTime < 10000);  
}
就會在序列埠監控視窗中看到看門狗計時器 reset 的訊息:


解決的方法很簡單, 只要在閒置區域中呼叫 yield() 或是 delay(0) 就會更新看門狗計時器, 也就不會 reset 了。修改的程式如下:
void setup() {
  Serial.begin(9600);
  Serial.println("Begin testing");
}

unsigned long prevTime;

void loop() {
  prevTime = millis();
  while(millis() - prevTime < 10000) {yield();}  
}

星期六, 11月 11, 2017

中計, 同一資料型別但不同平台資料長度不同的陷阱

這幾天測試 ESP8266 的 Arduino core, 拿以前寫的 Arduino 程式來試看看相容性, 遇到一個程式怎麼跑數值都錯, 這個程式會從感測器讀取兩個位元組的資料, 再由這兩個位元組組成一個 16-bit int, 結果原來是 ESP8266 的 int 是 32-bit, 而 Arduino 的 int 是 16-bit, 因此, 原本以下正確的程式:
return int(word(high,low));
遇到負數時會出現超過 32767 的數值, 害我還回頭看感測器的規格書, 以為是自己程式寫錯了。後來才想到, 可能是資料長度的問題, 改成以下這樣就正確了:
return int16_t(word(high,low));

星期四, 11月 09, 2017

Arduino 命令行錯誤:avr-g++: error: missing argument to '-mmcu='

不知道為什麼, 突然遇到使用 Arduino 命令行編譯上傳程式到 Nano 板時, 出現以下錯誤:

avr-g++: error: missing argument to '-mmcu='

明明之前都沒問題, 不知道是動到了什麼, 經過網路查詢之後, 明確加上 CPU 型號就可以了:

--board arduino:avr:nano:cpu=atmega328

雖然可解, 但我還是不知道出了什麼事?而且同樣的指令在其他機器上是可以正常運作的。

附記:使用上述方法正常編譯後, 再把 CPU 參數去掉, 就恢復正常了, 我還是不知道出了什麼事?