為了測速球計畫, 萊恩大兵得找個方法讓 Arduino 能將 MPU6050 測得的數據暫存起來. Arduno Uno 只有 1KB 的 EEPROM 空間, 萊恩大兵本來是不考慮的. 後來想說做個實驗也好, 換個不同思考角度, 也許 1KB 夠用也說不定.
本來以為這實驗小蛋糕一片, 結果.. 很可怕. 寫入和讀出兩邊的數值比較起來, 都是前數十筆資料不對, 而後面百多筆資料是正確的.
![]() |
| 第17筆資料之後, 才兩邊一致. |
![]() |
| 第33筆資料之後, 才兩邊一致. |
不懂這是怎麼回事.. 難道寫入 EEPROM 之前要先 warm up 嗎? 萊恩大兵需要有經驗的朋友指點一下. 謝謝.
(2014/8/25 更新-1) 感謝各位路過朋友的指點, 這題目在臉書的討論串1和討論串2.
(2014/8/25 更新-2) 萊恩大兵改寫程式, 解決了寫入與讀取不一致的問題.
- 宣告一個 array 來暫存 MPU6050 ax/ay/az 的輸出值.
- 找個適當時機做一次寫入.
- 寫入 EEPROM 時, 還要 delay 夠長一段時間, 才能去中斷程式執行. 如果等不夠久的話, 這次反而會造成讀出與寫入數值相比, 變成是前半段一致, 後半段不一致的情況.
// Based on I2Cdevlib, MPU6050_raw
// Experiments to verify if any data loss when writing MPU6050 outputs to EEPROM
#include "I2Cdev.h"
#include "MPU6050.h"
#include <EEPROM.h>
#include "eeprom_anything.h"
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 accelgyro;
int16_t ax, ay, az;
int16_t gx, gy, gz;
// [eeprom]
struct accelData{
int16_t ax;
int16_t ay;
int16_t az;
};
accelData acc;
int accIdx = 0;
int accMem = 0;
int writeOnce = 0;
#define NUM 170
//int max = 1024 / sizeof(acc);
accelData accArray[NUM];
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// initialize serial communication
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
// it's really up to you depending on your project)
Serial.begin(38400);
// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
}
void loop() {
/*int n = writeEEPROM();
if (n >= NUM 200 && !writeOnce)
{
EEPROM_writeAnything(0, accArray);
writeOnce = 1;
delay(5000); // give enough time to write EEPROM
Serial.println("Now you can stop this program...");
}
*/
dumpEEPROM();
}
int writeEEPROM()
{
// read raw accel/gyro measurements from device
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// waive the first 200 sensor data
if (accIdx >= 200 && accIdx < NUM+200)
{
int n = accIdx - 200;
Serial.print("Idx: "); Serial.print(n);
Serial.print(", ax: "); Serial.print(ax); accArray[n].ax = ax;
Serial.print(", ay: "); Serial.print(ay); accArray[n].ay = ay;
Serial.print(", az: "); Serial.println(az); accArray[n].az = az;
//accMem = EEPROM_writeAnything(accMem, acc);
}
return accIdx ;
}
void dumpEEPROM()
{
accelData accTmp;
int tmpMem = 0;
for (int i=0; i<NUM; i )
{
tmpMem = EEPROM_readAnything(tmpMem, accTmp);
Serial.print("Idx: "); Serial.print(i);
Serial.print(", ax: "); Serial.print(accTmp.ax);
Serial.print(", ay: "); Serial.print(accTmp.ay);
Serial.print(", az: "); Serial.println(accTmp.az);
}
}
-=-=-=-=-=-=-= 分隔線 =-=-=-=-=-=-=-=-=-
萊恩大兵這個實驗的規劃如下:
(1) 怎麼讀寫 EEPROM?
- 這個簡單, 參考 Cooper Maa (可讀寫任何資料的 EEPROM 函式) 或葉難 (Arduino:自訂整組資料讀寫EEPROM) 的文章, 有現成的教學指引. 萊恩大兵直接引用了葉難的 eeprom_anything.h.
(2) 寫入 EEPROM vs MPU6050 數據產出, 速度對決
- 講起來這是個假議題. 如果寫 EEPROM 跟不上, 那就把 MPU6050 量測輸出調慢一點啊. 是這樣沒錯, 錯的就在萊恩大兵不懂怎麼去調慢 MPU6050 的時脈. XD.
- 只好拿現成的東西來改. i2cdevlib 的示範程式 MPU6050_raw 讓 MPU6050 的數據輸出間隔為 10ms. 就用這標準來做實驗.
(3) 改寫 MPU6050_raw, 包括:
- 將 ax, ay, az 的值寫入 EEPROM, 共 170 筆 [1024/(2+2+2)]. 同時也將 ax, ay, az 的值倒在 serial port monitor 上.
- 再從 EEPROM 去讀出值來, 兩邊做比對.
程式碼如下:
// Based on I2Cdevlib, MPU6050_raw
// Experiments to verify if any data loss when writing MPU6050 outputs to EEPROM
#include "I2Cdev.h"
#include "MPU6050.h"
#include <EEPROM.h>
#include "eeprom_anything.h"
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 accelgyro;
int16_t ax, ay, az;
int16_t gx, gy, gz;
// [eeprom]
struct accelData{
int16_t ax;
int16_t ay;
int16_t az;
};
accelData acc;
int accIdx = 0;
int accMem = 0;
int max = 1024 / sizeof(acc);
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// initialize serial communication
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
// it's really up to you depending on your project)
Serial.begin(38400);
// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
}
void loop() {
//writeEEPROM();
dumpEEPROM();
}
void writeEEPROM()
{
// read raw accel/gyro measurements from device
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// waive the first 100 sensor data
if (accIdx >= 200 && accIdx < max + 200)
{
Serial.print("Idx: "); Serial.print(accIdx-200);
Serial.print(", ax: "); Serial.print(ax); acc.ax = ax;
Serial.print(", ay: "); Serial.print(ay); acc.ay = ay;
Serial.print(", az: "); Serial.println(az); acc.az = az;
accMem = EEPROM_writeAnything(accMem, acc);
}
accIdx ;
}
void dumpEEPROM()
{
accelData accTmp;
int tmpMem = 0;
for (int i=0; i<max; i )
{
tmpMem = EEPROM_readAnything(tmpMem, accTmp);
Serial.print("Idx: "); Serial.print(i);
Serial.print(", ax: "); Serial.print(accTmp.ax);
Serial.print(", ay: "); Serial.print(accTmp.ay);
Serial.print(", az: "); Serial.println(accTmp.az);
}
}
-=-=-=-=-=-=-= 分隔線 =-=-=-=-=-=-=-=-=-
未來, 這技術應該可以用在測速球計畫上面.
(1) 寫 EEPROM 的作法, 本質上也是將資料暫存起來, 等以後再找時機將資料倒出來. 這樣來看, 應該可以是測速球的實作選項之一.
(2) 1KB 空間, 可以存多少資料?
[萊恩大兵的其它文章]
自製大四軸
* 自製大四軸, 實作分享@華山文創園區
* 自製大四軸, (1) 零組件篇, 遙控器 (Drone, Quadcopter, Futaba, Maker, Arduino, Animatronic Eye)
* 自製大四軸, (2) 零組件篇, 飛控板 (Drone, Quadcopter, MultiWii, Arduino, Futaba, Maker)
* 自製大四軸, (3) 零組件篇, 自行雷切木質機架 (Drone, Quadcopter, Maker, Laser Cut)
* 自製大四軸, (4) 零組件篇, 馬達與電變調整 (Drone, Quadcopter, Maker, Electric Speed Control, Motor)
* 自製大四軸, (5) 組裝篇, 四軸飛行器成形 (Drone, Quadcopter, MultiWii, Arduino, Maker, Electric Speed Control, Motor)
* 自製大四軸, (6) 調整篇, 飛行前兩三事 (Drone, Quadcopter, Maker, Futaba, Arduino, MultiWii)
* 自製大四軸, (7) 充電篇, iMax B6 充電器操作記要 (Charger, Battery)
* 自製大四軸, (8) 問題篇, 機架損壞維修 (Drone, Quadcopter, Laser Cut)
* 自製大四軸, (9) 改良篇, 方便拆卸的木質機架 (Drone, Quadcopter, Maker, Laser Cut)
自動報球速的棒球
* 自動報球速的棒球, (1) 概念與雛形 (Arduino, MPU-6050, HC-06)
* 自動報球速的棒球, (2) 第一版試作品 (Arduino, NanoWii, microSD, MPU6050)
* 自動報球速的棒球, (3) 拋接實驗的數據分析 (Arduino, NanoWii, microSD, MPU6050)
* 自動報球速的棒球, (2) 第一版試作品 (Arduino, NanoWii, microSD, MPU6050)
* 自動報球速的棒球, (3) 拋接實驗的數據分析 (Arduino, NanoWii, microSD, MPU6050)
* 做實驗, 寫入 EEPROM 的速度能否跟得上 MPU6050 的數據產出? (Arduino, MPU-6050, EEPROM)
* 筆記, NanoWii, 一些經驗分享 (Arduino, NanoWii, MPU6050)
* Murmur, 很小很強大的穿戴式裝置模組 (Realtag, Bluetooth, CC2540, MPU6050, BMP180)
* 筆記, NanoWii, 一些經驗分享 (Arduino, NanoWii, MPU6050)
* Murmur, 很小很強大的穿戴式裝置模組 (Realtag, Bluetooth, CC2540, MPU6050, BMP180)
CC2540 Bluetooth Low Energy
* 筆記, CC2540 Bluetooth Low Energy, (1) 開發環境 架設 (Bluetooth, CC2540)
* 筆記, CC2540 Bluetooth Low Energy, (2) 跑第一個範例程式 (Bluetooth, CC2540)
* 筆記, CC2540 Bluetooth Low Energy, (3) SimpleBLEPeripheral 簡單介紹 (Bluetooth, CC2540)
* 筆記, CC2540 Bluetooth Low Energy, (4) 在智慧手機上執行範例程式 (Bluetooth, CC2540)
* 筆記, CC2540 Bluetooth Low Energy, (5) 偵測與發送 iBeacon 訊號 (Bluetooth, CC2540, iBeacon)
* 實作, iBeacon 發訊器 x 防丟器 (Bluetooth, CC2540, iBeacon)
* 實作, iBeacon 尋寶遊戲 (Bluetooth, CC2540, iBeacon, iOS app)
* 實作, BLE + iOS app, 遙控燈泡君 (Bluetooth, CC2540, iOS app)
* 做實驗, 用 iBeacon 做自動控制的可行性 (Bluetooth, iBeacon, CC2540, Automation, URL Scheme, iOS app)
* 筆記, CC2540 Bluetooth Low Energy, (2) 跑第一個範例程式 (Bluetooth, CC2540)
* 筆記, CC2540 Bluetooth Low Energy, (3) SimpleBLEPeripheral 簡單介紹 (Bluetooth, CC2540)
* 筆記, CC2540 Bluetooth Low Energy, (4) 在智慧手機上執行範例程式 (Bluetooth, CC2540)
* 筆記, CC2540 Bluetooth Low Energy, (5) 偵測與發送 iBeacon 訊號 (Bluetooth, CC2540, iBeacon)
* 實作, iBeacon 發訊器 x 防丟器 (Bluetooth, CC2540, iBeacon)
* 實作, iBeacon 尋寶遊戲 (Bluetooth, CC2540, iBeacon, iOS app)
* 實作, BLE + iOS app, 遙控燈泡君 (Bluetooth, CC2540, iOS app)
* 做實驗, 用 iBeacon 做自動控制的可行性 (Bluetooth, iBeacon, CC2540, Automation, URL Scheme, iOS app)
藍色小鋪一起來做
* 藍色小鋪一起來做, (1) 用 beacon 控制開關的枱燈
* 藍色小鋪一起來做, (2) 講解 BLE CC2540 UART 通訊範例程式 (Bluetooth, CC2540, UART)
* 藍色小鋪一起來做, (3) 藍牙枱燈專案實作 (上) (Bluetooth, CC2540)
* 藍色小鋪一起來做, (4) 藍牙枱燈專案實作 (下) (Bluetooth, CC2540)
* 藍色小鋪一起來做, (5) iBeacon scanner 專案示範與解說 (Bluetooth, CC2540, iBeacon)
* 藍色小鋪一起來做, (6) 完成, 用 iBeacon 控制開關的枱燈 (Bluetooth, CC2540, iBeacon)
* 藍色小鋪, 初嚐樹莓派 (Raspberry Pi)
* 藍色小鋪, iBeacon 應用, 自動記錄到訪時間 (iBeacon, Geohopper, Zapier)
小惡魔 無線溫度感測器
* 小惡魔, (1) 溫度感測 + 物聯網 (Electric Imp, Xively, LM35, Internet of Things)
* 小惡魔, (2) 溫度感測 + 物聯網 + 事件觸發 (Electric Imp, Xively, LM35, Internet of Things)
* 小惡魔, (2) 溫度感測 + 物聯網 + 事件觸發 (Electric Imp, Xively, LM35, Internet of Things)
108 大眼仔
Plot Clock
* 體驗, 蛋生音互動裝置@兒童美術館 (Arduino, 3D Printing, HC-SR04, Interactive)
* 實作, 電容感應音樂樹
* 修理, 樂高馬達 8883 (LEGO 8883 Power Functions M-Motor)
* 修理, (part 2) 樂高馬達 8883 (LEGO 8883 Power Functions M-Motor)
* 修理, 液晶螢幕 (LCD)
* 108 大眼仔, 初登場 (Arduino, SG-90, Maker Faire Taipei 2014, Animatronic Eye)
* 108 大眼仔, 進化, (1) 專屬程式庫 (Arduino, SG90, Animatronic Eye)
* 108 大眼仔, 進化, (2) 當我們串在一起 (Arduino, SG90, Animatronic Eye, I2C)
* 108 大眼仔, 進化, (3) 檢查 Gmail 信箱 (Arduino, SG90, Animatronic Eye, Temboo)
* 108 大眼仔, 進化, (4) 看著我的臉 (Arduino, SG90, Animatronic Eye, OpenCV, Processing, I2C)
* 108 大眼仔, 進化, (5) 迎著人來人往 (Arduino, SG90, Animatronic Eye, OpenCV, Processing, I2C)
* 108 大眼仔, 檢討筆記, 我要一個打十個 (Arduino, SG90, Animatronic Eye)
* 108 大眼仔, 進化, (1) 專屬程式庫 (Arduino, SG90, Animatronic Eye)
* 108 大眼仔, 進化, (2) 當我們串在一起 (Arduino, SG90, Animatronic Eye, I2C)
* 108 大眼仔, 進化, (3) 檢查 Gmail 信箱 (Arduino, SG90, Animatronic Eye, Temboo)
* 108 大眼仔, 進化, (4) 看著我的臉 (Arduino, SG90, Animatronic Eye, OpenCV, Processing, I2C)
* 108 大眼仔, 進化, (5) 迎著人來人往 (Arduino, SG90, Animatronic Eye, OpenCV, Processing, I2C)
* 108 大眼仔, 檢討筆記, 我要一個打十個 (Arduino, SG90, Animatronic Eye)
* 自造 Time Plotting Clock, (1) 零件採購
* 自造 Time Plotting Clock, (2) 組裝
* 自造 Time Plotting Clock, (3) 校正
* 自造 Time Plotting Clock, (2) 組裝
* 自造 Time Plotting Clock, (3) 校正
* Murmur, 有趣的零件售價
* Murmur, Arduino 保險桿 (Arduino, bumper, 3D printing)
* Murmur, 許一個 maker 分享網站
* Murmur, 物聯網新概念- The Physical Web (Internet of Things, The Physical Web)
* Murmur, 關於 HP Sprout 的一點想法
* Murmur, 說中文很難嗎? (Toy, Reed Switch, Voice Recorder Module)
* Murmur, 停車場自動繳費機的兩三事 (Kiosk)
* Murmur, 為什麼是 WiFi? 關於小米空氣清淨器的一點看法.. (Internet of Things)
* Murmur, 機器人是時尚元素? (Robot, Fashion)
* Murmur, Nordic 才會是 Bluetooth LE 晶片戰爭的恐龍王者? (Bluetooth, Nordic)
* 體驗, 原住民互動故事書@宜蘭大同鄉泰雅生活館* Murmur, Arduino 保險桿 (Arduino, bumper, 3D printing)
* Murmur, 許一個 maker 分享網站
* Murmur, 物聯網新概念- The Physical Web (Internet of Things, The Physical Web)
* Murmur, 關於 HP Sprout 的一點想法
* Murmur, 說中文很難嗎? (Toy, Reed Switch, Voice Recorder Module)
* Murmur, 停車場自動繳費機的兩三事 (Kiosk)
* Murmur, 為什麼是 WiFi? 關於小米空氣清淨器的一點看法.. (Internet of Things)
* Murmur, 機器人是時尚元素? (Robot, Fashion)
* Murmur, Nordic 才會是 Bluetooth LE 晶片戰爭的恐龍王者? (Bluetooth, Nordic)
* 體驗, 蛋生音互動裝置@兒童美術館 (Arduino, 3D Printing, HC-SR04, Interactive)
* 開箱, 鋼彈小劇場 (Pepper's Ghost, GUNDAM)
* 開箱, 偉力控二號機, 小四軸飛行器 (CG022, Quadcopter)
* 偉力控二號機, 修理防護罩與飛行心得 (CG022, Quadcopter)
* 偉力控二號機, 我想有個家 (CG022, Quadcopter)
* 偉力控二號機, 換馬達 (CG022, Quadcopter)
* 偉力控二號機, 盒子上的洞 (CG022, Quadcopter)
* 開箱, 偉力控二號機, 小四軸飛行器 (CG022, Quadcopter)
* 偉力控二號機, 修理防護罩與飛行心得 (CG022, Quadcopter)
* 偉力控二號機, 我想有個家 (CG022, Quadcopter)
* 偉力控二號機, 換馬達 (CG022, Quadcopter)
* 偉力控二號機, 盒子上的洞 (CG022, Quadcopter)
* 修理, 樂高馬達 8883 (LEGO 8883 Power Functions M-Motor)
* 修理, (part 2) 樂高馬達 8883 (LEGO 8883 Power Functions M-Motor)
* 修理, 液晶螢幕 (LCD)



沒有留言:
張貼留言