· 

ArduinoのEEPROMに書き込、、、めない

ArduinoのEEPROMに初期値を書いておきたいことってまれにある。が、じつはすんなりではない。書いてくれないぞっていう結果と、じゃぁどうやって書くかってのをメモっておく。

まずはこういうコードを書く。EEMEMってのがこれをEEPROMに入れるぜってことを示している。ちなみにPROGMEMってのはFlashにはいる。

 

eeprom_initial_value.ino

#include <avr/eeprom.h>
#include <EEPROM.h>

typedef struct tag_test_data_element_struct{
    uint8_t upper:4;
    uint8_t lower:4;
}test_data_element_struct_t;

typedef union tag_test_data_struct{
    uint8_t asByte;
    test_data_element_struct_t elm;
}test_data_struct_t;

typedef struct tag_test_struct{
    uint8_t len;
    test_data_struct_t data[247];
    uint8_t cmd1[4];
    uint8_t cmd2[4];
}test_struct_t;

volatile test_struct_t test_mem EEMEM = {
    23,{ 0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x02,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x03,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x04,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x05,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x06,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x07,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x08,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x09,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0A,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0B,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0C,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0D,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0E,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0F,0x12,0x23,0x34,0x45,0x56,0x67,0x78},{0x01,0x02,0x03,0x04},{0xDE,0xAD,0xBE,0xEF}
};

test_struct_t test_data;

void setup(){
    uint8_t d[256];
    char line[100];
    Serial.begin(115200);
    for(int i=0;i<256;i++){
        d[i]=EEPROM.read(i);
    }
    for(int i=0;i<16;i++){
        sprintf(
            line,
            "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            d[i*16+0],d[i*16+1],d[i*16+2],d[i*16+3],d[i*16+4],d[i*16+5],d[i*16+6],d[i*16+7],
            d[i*16+8],d[i*16+9],d[i*16+10],d[i*16+11],d[i*16+12],d[i*16+13],d[i*16+14],d[i*16+15]
        );
        Serial.println(line);
    }
#if 0    
    EEPROM.get(0, test_data);
    Serial.println(test_data.len);
    for(int i=0;i<247;i++){
        Serial.print(test_data.data[i].elm.upper);
        Serial.print("/");
        Serial.println(test_data.data[i].elm.lower);
    }
    for(int i=0;i<4;i++){
        Serial.print(test_data.cmd1[i]);
    }
    Serial.println("");
    for(int i=0;i<4;i++){
        Serial.print(test_data.cmd2[i]);
    }
    Serial.println("");
#endif
}
void loop(){

}

コンパイル結果が出力されるようにする。

.vscode/arduno.json

{
    "board": "arduino:avr:uno",
    "port": "COM5",
    "sketch": "eeprom_initial_value.ino",
    "output": "../output"
}

で、書き込んで、シリアルモニターを見ると、

書き込まれていないTT

ではコンパイル結果はどうなっているのか、

.eepファイルができていて、中身はそれらしい。つまり、書き込んでくれないんだよ。どうしたらいいのか、あまり情報がないんよー。ギブアップ。(下のほうの<悶絶の記録>参照)

どうすっか、、、

#include <avr/eeprom.h>
#include <EEPROM.h>

typedef struct tag_test_data_element_struct{
    uint8_t upper:4;
    uint8_t lower:4;
}test_data_element_struct_t;

typedef union tag_test_data_struct{
    uint8_t asByte;
    test_data_element_struct_t elm;
}test_data_struct_t;

typedef struct tag_test_struct{
    uint8_t len;
    test_data_struct_t data[247];
    uint8_t cmd1[4];
    uint8_t cmd2[4];
}test_struct_t;

test_struct_t test_mem = {
    23,{ 0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x02,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x03,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x04,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x05,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x06,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x07,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x08,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x09,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0A,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0B,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0C,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0D,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0E,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9A,0xAB,0xBC,0xCD,0xDE,0xEF,0xF0,
    0x0F,0x12,0x23,0x34,0x45,0x56,0x67,0x78},{0x01,0x02,0x03,0x04},{0xDE,0xAD,0xBE,0xEF}
};
void setup(){
    uint8_t d[256];
    char line[100];
    EEPROM.put(0,test_mem);

    delay(100);
    Serial.begin(115200);
    for(int i=0;i<256;i++){
        d[i]=EEPROM.read(i);
    }
    for(int i=0;i<16;i++){
        sprintf(
            line,
            "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            d[i*16+0],d[i*16+1],d[i*16+2],d[i*16+3],d[i*16+4],d[i*16+5],d[i*16+6],d[i*16+7],
            d[i*16+8],d[i*16+9],d[i*16+10],d[i*16+11],d[i*16+12],d[i*16+13],d[i*16+14],d[i*16+15]
        );
        Serial.println(line);
    }
}
void loop(){

}

はい、実行時に書いちゃいます。(現実逃避ーー)

できた、、、

eepファイルを作る、そして書き込む、ってやりたかったが、まぁわからんのよ。いつか再挑戦するかもしれない。

 


<悶絶の記録=失敗>

コードの書き込みに使われているavrdudeはeepromも書き込めるので、書き込み用のtaskを作るという寝技でとりあえずやっつける。何かを設定することでコードの書き込みと同時にやってくれる方法があるのかもしれないけど、まぁわからんのよねー。

で、avrdudeでeepromを書き込むにはどうするか、

 

C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\bin\avrdude.exe -C "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -p atmega328p -c arduino -v -P COM5 -b 115200 -U eeprom:w:"..\output\eeprom_initial_value.ino.eep":i

 

かなり長いけど、こうすればいいらしい。

これをtaskとして登録する。

Terminal-->Configure Tasks...

どれを選んでも大手術なので、一番内容が近そうなこいつを選ぶ。

こうなる。

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "Write EEPROM",
            "command": "C:\\Users\\hoge\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avrdude\\6.3.0-arduino17\\bin\\avrdude.exe",
            "args": [
                "-C","\"C:\\Users\\hoge\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avrdude\\6.3.0-arduino17\\etc\\avrdude.conf\"",
                "-p","atmega328p",
                "-v",
                "-U","eeprom:w:\"..\\output\\eeprom_initial_value.ino.eep\":i",
                "-c","arduino",
                "-P","COM5",
                "-b","115200"
            ],
            "options": {
                
            },
        }
    ]
}

こうする。

avrdudeの場所とか、はPCによって違うので、事前に確認しておく。

Terminal-->Run Task...

さっき作ったやつがいるのでつつく。

なんのこっちゃかわからんけど、こいつをつつく。

 *  Executing task in folder eeprom_initial_value: C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\bin\avrdude.exe -C "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -p atmega328p -c arduino -v -P COM5 -b 115200 -U eeprom:w:"..\output\eeprom_initial_value.ino.eep":i 

 

 

avrdude.exe: Version 6.3-20190619

             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

             Copyright (c) 2007-2014 Joerg Wunsch

 

             System wide configuration file is "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf"

 

             Using Port                    : COM5

             Using Programmer              : arduino

             Overriding Baud Rate          : 115200

             AVR Part                      : ATmega328P

             Chip Erase delay              : 9000 us

             PAGEL                         : PD7

             BS2                           : PC2

             RESET disposition             : dedicated

             RETRY pulse                   : SCK

             serial program mode           : yes

             parallel program mode         : yes

             Timeout                       : 200

             StabDelay                     : 100

             CmdexeDelay                   : 25

             SyncLoops                     : 32

             ByteDelay                     : 0

             PollIndex                     : 3

             PollValue                     : 0x53

             Memory Detail                 :

 

                                      Block Poll               Page                       Polled

               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack

               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------

               eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff

               flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff

               lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

               hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

               efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

               lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

 

             Programmer Type : Arduino

             Description     : Arduino

             Hardware Version: 3

             Firmware Version: 4.4

             Vtarget         : 0.3 V

             Varef           : 0.3 V

             Oscillator      : 28.800 kHz

             SCK period      : 3.3 us

 

avrdude.exe: AVR device initialized and ready to accept instructions

 

Reading | ################################################## | 100% 0.02s

 

avrdude.exe: Device signature = 0x1e950f (probably m328p)

avrdude.exe: safemode: lfuse reads as 0

avrdude.exe: safemode: hfuse reads as 0

avrdude.exe: safemode: efuse reads as 0

avrdude.exe: reading input file "..\output\eeprom_initial_value.ino.eep"

avrdude.exe: writing eeprom (256 bytes):

 

Writing | ################################################## | 100% 2.05s

 

avrdude.exe: 256 bytes of eeprom written

avrdude.exe: verifying eeprom memory against ..\output\eeprom_initial_value.ino.eep:

avrdude.exe: load data eeprom data from input file ..\output\eeprom_initial_value.ino.eep:

avrdude.exe: input file ..\output\eeprom_initial_value.ino.eep contains 256 bytes

avrdude.exe: reading on-chip eeprom data:

 

Reading | ################################################## | 100% 2.05s

 

avrdude.exe: verifying ...

avrdude.exe: verification error, first mismatch at byte 0x0000

             0xff != 0x17

avrdude.exe: verification error; content mismatch

 

avrdude.exe: safemode: lfuse reads as 0

avrdude.exe: safemode: hfuse reads as 0

avrdude.exe: safemode: efuse reads as 0

avrdude.exe: safemode: Fuses OK (E:00, H:00, L:00)

 

avrdude.exe done.  Thank you.

 

 

 *  The terminal process "C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -Command C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\bin\avrdude.exe -C "C:\Users\hoge\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -p atmega328p -c arduino -v -P COM5 -b 115200 -U eeprom:w:"..\output\eeprom_initial_value.ino.eep":i" terminated with exit code: 1. 

 *  Terminal will be reused by tasks, press any key to close it. 

ターミナルにこう出る。ベリファイ結果がおかしい。

実はやっているようで、やってない。なんでやー

 

会社は椅子取りゲームへの全員参加を推奨しています。本当は普通に毎日行きたいが全員分の座席がないやん。やる気というかいろいろ失せるわ。