Проблема чтения EEPROM при записи скетча через программатор

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Уважаемые форумчане, добрый день.

Столкнулся с такой проблемой. Есть простая программа (код ниже) для  Ардутно Нано, светодиода и кнопки.  Кнопкой можнго светодиод включить/выключить, при этом состояние светодиода (включен он или выключен) сохраняется в постоянноьй памяти. То есть, при пуске программы код перваым делом считывает значения ячейки из постояннолй памяти. Если порследний раз светодилж горел, то он при пуске зажжется, если не горел - то, естественно, нет.

Суть проблемы: При записи скетча через USB Нано все работает исправно. При записи через  USBASP программатор программа не работает. Светодиод загорается сразу, на кнопку нет реакции.

Перед каждой загрузкой прораммы произвожу очистку EEPROM (для чистоты эксперимента) - поэтому при первом вклюяении (до нажатия кнопки) светодиод гореть  не должен.

 

 

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

#define BUTTON_PIN     19
#define LED_PIN        3

boolean buttonWasUp = true;
byte led_state = 0;

void setup()
{
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);

  led_state = EEPROM.read(100);
}

void loop()
{
  boolean buttonIsUp = digitalRead(BUTTON_PIN);
  if (buttonWasUp && !buttonIsUp)
  {
    delay(10);
    buttonIsUp = digitalRead(BUTTON_PIN);
    if (!buttonIsUp)
    {
      led_state = 1 - led_state;
      EEPROM.write(100, led_state);
    }
  }
  buttonWasUp = buttonIsUp;

  digitalWrite(LED_PIN, led_state);
}

 

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

ДОПОЛНИТЕЛЬНО ВАЖНЫЙ МОМЕНТ

Если строку 25 закомментировать

25  // EEPROM.write(100, led_state);

то программа начинает исправно работать как при записи через порт USB Нано, так и через USBASP программатор. Только не будет происходить чтения записанного состояния светодиода. 

Строка чтения EEPROM при записи скетча через программатор рушит программу. В чем может быть проблема?

Буду очень признателен за пормощь.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

а я вроде вам писал уже ..... после 24 строки выведете в монитор порта состояние переменной led_state - хоть один раз ноль будет?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Очистка EEPROM делается вовсе не обязательно нулями, может быть 255. Так что напишите строку 24 по-человечески

led_state = ! led_state;

И должно всё заработать.

И ещё, мужики, не бесите. Если Вам нужна помощь, то выкладывайте полный (от слова совсем полный) (не знаете что означает это слово - смотрите в словаре) код. Задолбали уже через одного - "я удалил то, что несущественно". Вот, блин, мы тут все такие умные - отлично знаем, что существенно, а что - нет, только две строчки отладить не можем :( 

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Евгений, большое спасибо за дельный совет.

Я выложил полную программу.  Внес изменения, все заработало. Через USBASP программатор пишется исправно.  Только при первом после загрузки включении светодиод начинает сразу светиться.  

 

mixail844
Offline
Зарегистрирован: 30.04.2012

ЕвгенийП пишет:

И ещё, мужики, не бесите. Если Вам нужна помощь, то выкладывайте полный (от слова совсем полный) (не знаете что означает это слово - смотрите в словаре) код. Задолбали уже через одного - "я удалил то, что несущественно". Вот, блин, мы тут все такие умные - отлично знаем, что существенно, а что - нет, только две строчки отладить не можем :( 

Мсье знает толк...

Всетаки, кмк , best practice это когда выкладывается минимальный пример который воспроизводит проблему. Если проблема не воспроизводится на другом железе, тогда смотреть остальное.
А то читать простыню где идёт обращение к серверу, когда ошибка в при работе с EEPROM, так себе удовольствие.
Да, этот подход предполагает что код работы с сервером никак не затрагивает исправность работы с EEPROM.и вопрошающий помощи это понимает.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Aleksandr1968 пишет:

Евгений, большое спасибо за дельный совет.

Я выложил полную программу.  Внес изменения, все заработало. Через USBASP программатор пишется исправно.  Только при первом после загрузки включении светодиод начинает сразу светиться.  

эх....нельзя намеками подсказывать - нужно конкретно решение всегда писать.

чтоб при старте всегда не горел светодиод - в setup в eeprom прописываете значение что светодиод не горит, и соотвественно led state 0 делаете

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Поясняю свои слова . Записываем программу в предварительно очищенную память через USB порт и через USBasp программатор.

При записи программы через USB порт светодиод посе заливки программы не загорается. При записи через программатор - всегда загорается. 

В остальном все работает идентично

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

а надо то как????? чтоб горел или чтоб не горел при старте :) ?

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Не важно. Нужно, чтобы было одинаково, и понять, в чем была причина

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Aleksandr1968 пишет:

Не важно. Нужно, чтобы было одинаково, и понять, в чем была причина

"одинаково" с чем ?

 

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

при загрузке через USBASP программатор и через USB вход 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

не, я тупой, нифига не понял. Какая хрен разница через что программировать - светодиод должен гореть или нет при старте? или запоминаться предыдущее состояние?

вот вам кусок из реальной программы включения реле в зависимости от последнего состояния, сделайте аналогично и будет вам счастье

это запись в eeprom при изменении статуса

          // relay 2 ON
          EEPROM.write(pos_eeprom_relay2_mode, 21);
          digitalWrite(A3, LOW);

          // relay 2 OFF
          EEPROM.write(pos_eeprom_relay2_mode, 00);
          digitalWrite(A3, HIGH);

это соотвественно чтение при старте программы

  // on off relay
  if (EEPROM.read(pos_eeprom_relay2_mode) == 21) digitalWrite(A3, LOW); else digitalWrite(A3, HIGH);
 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Aleksandr1968 пишет:

Я выложил полную программу. 

Да, что Вы? А теперь возьмите её из того поста, вставьте в чистый файл и попытайтесь скомпилировать. Получите сообщение, что EEPROM не определено. Это Вы называете полной?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

mixail844 пишет:
Всетаки, кмк , best practice это когда выкладывается минимальный пример который воспроизводит проблему.
Кто бы спорил, но только работающий пример. В данном же случае он даже не компилировался.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andycat пишет:

Какая хрен разница через что программировать

Если в одном случае в настройках IDE стоит чистить епром, а в другом - нет (или наоборот), вот и разница. Он туда зафигачиает 255, а потом ТС (считая, что там 0) вычитает эту 255 из 1, считая, что инвертиирует.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

andycat пишет:

Какая хрен разница через что программировать

Если в одном случае в настройках IDE стоит чистить епром, а в другом - нет (или наоборот), вот и разница. Он туда зафигачиает 255, а потом ТС (считая, что там 0) вычитает эту 255 из 1, считая, что инвертиирует.

А где это конфигурируется?

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018
#include <EEPROM.h>

#define BUTTON_PIN     19
#define LED_PIN        3

boolean buttonWasUp = true;
byte led_state = 0;

void setup()
{
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);

  led_state = EEPROM.read(100);
}

void loop()
{
  boolean buttonIsUp = digitalRead(BUTTON_PIN);
  if (buttonWasUp && !buttonIsUp)
  {
    delay(10);
    buttonIsUp = digitalRead(BUTTON_PIN);
    if (!buttonIsUp)
    {
      led_state = 1 - led_state;
      EEPROM.write(100, led_state);
    }
  }
  buttonWasUp = buttonIsUp;

  digitalWrite(LED_PIN, led_state);
}

 

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Виноват, опростоволосился. Пропустил первую строчку при копировании. Сейчас код полностью.

 

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Прошиваю этот код через USB и через программатор. Через USB - Работает. Через программатор - нет. Совет Евгения П помогает.

Евгений, поясните пожалуйста, что Вы понимаете под настройками IDE (чистка епром)? Это настройки фьюзов? Перед прошивкой Нано через USB я сначала прошиваю загрузчик через прогррамматор (при этом он конфигурирует фьюзы). 

Когда я пишу код через программатор загрузчик стирается, но конфигурация фьюзов меняться при этом не должна.

Я не очень силен в программировании, моэтому могу не совсем корпектно ставить вопросы. Прошу не судить строго.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ЕвгенийП пишет:

andycat пишет:

Какая хрен разница через что программировать

Если в одном случае в настройках IDE стоит чистить епром, а в другом - нет (или наоборот), вот и разница. Он туда зафигачиает 255, а потом ТС (считая, что там 0) вычитает эту 255 из 1, считая, что инвертиирует.

Это понятно, мне не понятно что ТС хочет увидеть при старте.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andycat пишет:
ЕвгенийП пишет:

andycat пишет:

Какая хрен разница через что программировать

Если в одном случае в настройках IDE стоит чистить епром, а в другом - нет (или наоборот), вот и разница. Он туда зафигачиает 255, а потом ТС (считая, что там 0) вычитает эту 255 из 1, считая, что инвертиирует.

Это понятно, мне не понятно что ТС хочет увидеть при старте.

Одинаковости поведения девайса при любом способе прошивки

sadman41
Offline
Зарегистрирован: 19.10.2016

Прошивка МК должна приравниваться к аварийной ситуации в которой содержание EEPROM было утеряно или искажено. При этом приводится в действие план "Б", при котором самой прошивкой в долговременную память записываются корректные дефолтные данные и, при необходимости, об этом сообщается пользователю. Теряете при замене прошивки EEPROM МК - пишите во внешнюю память, которую ни один прошивальщик не достает физически. Не надейтесь на то, что IDE никогда не будет запускать дудку без опций полной зачистки МК - это сэкономит кучу нервов и времени.

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Господа, есть пример кода с корректировкой от Евгения П Возьмём его за основу и записываем 2 способами Через USB и через программатор в ардуино Нано. Эксперимент проводим одинаково. Сначала прошиваем загрузчик.  Потом в примерах IDE запускаем программу  ЕЕPROM  clear.  Чтобы в еепром были нули. Это подготовка.  Далее прошиваем код. При прошивке через USB при старте светодиод не горит.  Понятно почему.  В ячейках еепром  прописан 0 

После аналогичной подготовки пишем через программатор. При этом загрузчик старается. После записи и пуска программы светодиод загорается.  Почем? В еепром были предварительно прописаны нули.  

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Насколько мне известно, при "стирании" в EEPROM записывается 255, а не 0. Соответственно, если хотите, чтобы работа программы не зависела от способа прошивки, минимум, надо писать 255.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Aleksandr1968 пишет:

Господа, есть пример кода с корректировкой от Евгения П Возьмём его за основу и записываем 2 способами Через USB и через программатор в ардуино Нано. Эксперимент проводим одинаково. Сначала прошиваем загрузчик.  Потом в примерах IDE запускаем программу  ЕЕPROM  clear.  Чтобы в еепром были нули. Это подготовка.  Далее прошиваем код. При прошивке через USB при старте светодиод не горит.  Понятно почему.  В ячейках еепром  прописан 0 

После аналогичной подготовки пишем через программатор. При этом загрузчик старается. После записи и пуска программы светодиод загорается.  Почем? В еепром были предварительно прописаны нули.  

Я же вам готовый пример привел, если меняется МК или обнуляется eeprom - светодиод никогда при старте не загорится - что ещё не так?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Aleksandr1968 пишет:

После аналогичной подготовки пишем через программатор. При этом загрузчик старается. После записи и пуска программы светодиод загорается.  Почем? В еепром были предварительно прописаны нули.  

Вам умный человек сказал умную вещь в посте #3, но Вы этот совет игнорируете.

Ну, напечатайте Вы, наконец, содержимое епрома и убедитесь, что нету там нулей, потому и загорается. Просто напечатайте и посмотрите.

Ваш фраза "пишем через программатор" ни о чём без параметров avrdude

sadman41
Offline
Зарегистрирован: 19.10.2016

Вводная

 "When the -U option with flash memory is specified, avrdude will perform a chip erase before starting any of the programming operations, since it generally is a mistake to program the flash without performing an erase first. ... This will reset the contents of the flash ROM and EEPROM to the value `0xff' , and clear all lock bits."

-D Disable auto erase for flash. When the -U option with flash memory is specified, avrdude will perform a chip erase before starting any of the programming operations, since it generally is a mistake to program the flash without performing an erase first. This option disables that. Auto erase is not used for ATxmega devices as these devices can use page erase before writing each page so no explicit chip erase is required. Note however that any page not affected by the current operation will retain its previous contents.

1) Заливаем через бутлоадер
 
C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -V -patmega328p -carduino -PCOM4 -b115200 -D -Uflash:w:C:\Users\...\arduino_build_797193/test_eeprom.ino.hex:i 
 
Проверяем:
 
EEPROM cell #10: 0x0
 
 
2) Заливаем через программатор
 
C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -V -patmega328p -cusbasp -Pusb -Uflash:w:C:\Users\...\arduino_build_797193/test_eeprom.ino.hex:i 
 
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
 
EEPROM cell #10: 0xFF
 
Тестовый скетч:
#include <EEPROM.h>

#define LED_PIN        13

byte led_state = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);

  led_state = EEPROM.read(10);
  Serial.print(" EEPROM cell #10: 0x"); Serial.println(led_state, HEX);
  digitalWrite(LED_PIN, led_state);
}

void loop() { }

 

Какие-то вопросы еще остались?
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andycat пишет:
что ещё не так?

Так Вы ещё вчера ТС посоветовали печатать, но он предпочитает работать вслепую и мозг всем выносить.

У него в опция avrdude стоит -e  (в конфигурационных файла IDE), отсюда и вся фигня.

-e - стирает содержимое FLASH и EEPROM памяти (заполнение значениями 0xFF), очищаются fuse-bits (биты защиты). Исключением являются микроконтроллеры семейства ATxmega в которых используется постраничная запись;

0xFF, а не 0, Карл! Вот он и горит при запуске, а куда ему деваться?

Aleksandr1968,  Вы бы делали, что Вам говорят. Напечатали бы, как Вам ещё вчера утром посоветовали, уж давно бы всё поняли.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41, зря Вы так. Человек должен был, наконец, сам напечатать. Про эту FF уже писали и №25 и в №16 - не доходило. И не дойдёт, пока САМ не напечатаешь. А Вы всё сделали за ТС - завтра будет тоже самое.

sadman41
Offline
Зарегистрирован: 19.10.2016

Ладно... больше не буду пить с утра, а то излишне добрым становлюсь.

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Очень много умных слов, дайте осмыслить и добиться просветления.

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018
/*
 * EEPROM Clear
 *
 * Sets all of the bytes of the EEPROM to 0.
 * Please see eeprom_iteration for a more in depth
 * look at how to traverse the EEPROM.
 *
 * This example code is in the public domain.
 */

#include <EEPROM.h>

void setup()
{

  /***
    Iterate through each byte of the EEPROM storage.    
    
    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduno Duemilanove: 512b EEPROM storage.
    - Arduino Uno:        1kb EEPROM storage.
    - Arduino Mega:       4kb EEPROM storage.
    
    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.    
  ***/
  
  for ( int i = 0 ; i < EEPROM.length() ; i++ )
    EEPROM.write(i, 0);

  // turn the LED on when we're done
  digitalWrite(13, HIGH);
}

void loop(){ /** Empty loop. **/ }

andriano пишет:

Насколько мне известно, при "стирании" в EEPROM записывается 255, а не 0. Соответственно, если хотите, чтобы работа программы не зависела от способа прошивки, минимум, надо писать 255.

 

Это мой встроенный в  IDE   EEPROM Clear.  Он пишет 0

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Aleksandr1968 пишет:

Это мой встроенный в  IDE   EEPROM Clear.  Он пишет 0

А после этого Вы запускаете прошивание и в процессе этого прошивания туда пишется 255.

Слушайте, я пишу Вам в последний раз, просто напечатайте свой епром и посмотрите. Если Вы и на этот раз этого не сделаете, я считаю, что Вы просто нас троллите - тогда без меня.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41, кстати, заметьте, таки не дошло.

Всё-таки 

ЕвгенийП пишет:

пока САМ не напечатаешь

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Aleksandr1968 пишет:

Это мой встроенный в  IDE   EEPROM Clear.  Он пишет 0

Ну вот и нашли источник ошибки, это "ваш встроенный в  IDE   EEPROM Clear".

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

sadman41, кстати, заметьте, таки не дошло.

Всё-таки 

Так выходит, что я ничего и не испортил - можно продолжать клевать его в печень ))

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Главное свою печень не победить)
А ТС пусть мучается дальше.
To ТС : бесплатный совет--если что то не получается - выводите переменные в консоль после каждой строки - возможно тогда придёт понимание.

bwn
Offline
Зарегистрирован: 25.08.2014

for (int i = 0; i < 1024; i++) {
Serial.println(EEPROM.read(i),HEX);
}
Вставить в setup и посмотреть в том и другом случае. Это трудно?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

bwn пишет:

for (int i = 0; i < 1024; i++) {
Serial.println(EEPROM.read(i),HEX);
}
Вставить в setup и посмотреть в том и другом случае. Это трудно?

" А девкой был бы краше" )))
 

#include <EEPROM.h>
void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 1024;) {
    Serial.print(i,HEX);
     for (int a = 0; a <16; a++){
       Serial.print(" ");
       Serial.print(EEPROM.read(i),HEX);
       i++;
      }
      Serial.println();
    }
  }
 

void loop() {
}

PS я не настоящий сталевар, поправьте, чтобы еще краше )))

sadman41
Offline
Зарегистрирован: 19.10.2016

Открою вам секрет - в IDE есть Examples к библиотеке EEPROM. И там уже написан скетчик eeprom_read...

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Как тут жизнь кипит, оказывается!

Только до компа добрался. Сделал вывод в порт. Ваши слова подтвердились. Когда гружу программу через USB все работает. Диод горит - выводится 1, не горит - 0. 

При загрузке через программатор светодиод зажигается сразу и в порт идет 255. После нагжатия кнопки диод гаснет  - в порт идет 0. Повторное нажатие  - диод загорается - в порт идет 1.  Кроме того сносятся 2 лок фьюза, которые устанавливаются при прошивке загрузчика. Реально программатор забивает ЕЕПРОМ числом 255.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

Открою вам секрет - в IDE есть Examples к библиотеке EEPROM. И там уже написан скетчик eeprom_read...


Где Вы раньше были, ну ничего размял мозги:
 


#include <EEPROM.h>
void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 1024;) {
    if (i  <16)Serial.print("00");
    if (i >0 && i <256)Serial.print("0");
    Serial.print(i,HEX);
     for (int a = 0; a <16; a++){
       Serial.print(" ");
       if (int b = EEPROM.read(i) <16)Serial.print("0");
       Serial.print(EEPROM.read(i),HEX);
       i++;
      }
      Serial.println();
    }
  }
 

void loop() {

}

 

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Теперь вопос как с avrdude бороться

Здесь очень нужна детальная помощь. С ходу разобраться не могу, пока слабое поверхностное понимание

Какие опции отключить и как это сделать?

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Есть, то она есть, но не про нашу честь, почувствуйте разницу!!!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Aleksandr1968 пишет:
Реально программатор забивает ЕЕПРОМ числом 255.
Не сам программатор, а опции, которые Вы ему задаёте. Ему-то пофиг.

Aleksandr1968
Offline
Зарегистрирован: 06.02.2018

Это понятно, что не сам программатр. Как эти опции правильно сконфигурировать, что с ними делать?

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

Aleksandr1968 пишет:
что с ними делать?

Включить fuse-бит EESAVE.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Aleksandr1968 пишет:

Это понятно, что не сам программатр. Как эти опции правильно сконфигурировать, что с ними делать?

1. Почитать про них и знать что какой флажок означает.

2. Залезть в конфигурационный файл IDE и поставить те, какие нужны

sadman41
Offline
Зарегистрирован: 19.10.2016

ua6em пишет:

sadman41 пишет:

Открою вам секрет - в IDE есть Examples к библиотеке EEPROM. И там уже написан скетчик eeprom_read...

Где Вы раньше были, ну ничего размял мозги:
 

#include <EEPROM.h>
....

Замысловатый кот. Предлагаю свой вариант:

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  for (uint16_t i = 0; i < EEPROM.length(); i++) {
    if (0x00 == (i % 0x10)) {
      Serial.println();
      if (i < 0x0F) { Serial.print("0"); }
      if (i < 0xFF) { Serial.print("0"); }
      Serial.print(i, HEX);  Serial.print(" ");
    }
    uint8_t val = EEPROM.read(i);
    if (val < 0x0F) { Serial.print("0"); }
    Serial.print(val, HEX); Serial.print(" ");
  }
}

void loop() {}

А стоковый скетч делает ровно то, что ему положено. Формат вывода - это уже вкусовщина.