ARDUINO Работа с ЕЕМЕМ. Ищу глюк.

Mix_man

✩✩✩✩✩✩✩
21 Янв 2020
91
9
Проблема не пойму в чем, при записывании в ЕЕМЕМ 32-ух битных данных, они косячатся и при выгрузке уже дичь какаято.
C++:
#include <EEPROM.h>
#include <Arduino.h>


//******* EEPROM******
uint16_t EEMEM r_D1;
uint16_t EEMEM r_D2; 
uint16_t EEMEM p_Set;
byte EEMEM w_Mode;
boolean EEMEM stepZero_eemem;   
uint8_t EEMEM stepLuft_eemem;   
boolean EEMEM stepLuft_Down_eemem; 
boolean EEMEM stepLuft_Up_eemem;
uint32_t EEMEM vol_D1;//счетчики
uint32_t EEMEM vol_D2;
long EEMEM step_M; // позиция шаговика, AccelStepper.h , для функции *.setCurrenpPosition(long position)
//int32_t EEMEM step_M; // шаг мотора. текущая позиция

#define INIT_ADDR 1023  // номер резервной ячейки
#define INIT_KEY 50     // ключ первого запуска. 0-254, на выбор

byte workMode=0;
uint8_t stepLuft =0;
boolean stepLuft_Up=true;
boolean stepLuft_Down=true;
//------------------------------------------

void setup() {
  Serial.begin(9600);
if (EEPROM.read(INIT_ADDR) != INIT_KEY) { // первый запуск
    EEPROM.write(INIT_ADDR, INIT_KEY);    // записали ключ
    WriteNewBackup();  //пишем "нулевые" настройки
    BackupRead();         //читаем их куда надо
  }else{
    BackupRead();
  }
}

//----------------------------------------
void WriteNewBackup(){
  EEPROM.put((int)&r_D1, 2000);
  EEPROM.put((int)&r_D2, 100);
  EEPROM.put((int)&p_Set, 10);
  EEPROM.put((int)&step_M, 8000);
  EEPROM.put((int)&w_Mode, 0);
  EEPROM.put((int)&vol_D1, 5);
  EEPROM.put((int)&vol_D2, 7);
  EEPROM.put((int)&stepZero_eemem,false);
  EEPROM.put((int)&stepLuft_eemem,0);
  EEPROM.put((int)&stepLuft_Down_eemem,true);
  EEPROM.put((int)&stepLuft_Up_eemem,true);
}
//-----------------------------------------------------------
void BackupRead(){
  uint32_t tmp;

  EEPROM.get((int)&r_D1, tmp);
  Serial.print(F("r_D1 = "));  Serial.println(tmp);

  EEPROM.get((int)&r_D2, tmp);
  Serial.print(F("r_D2 = "));  Serial.println(tmp);

  uint16_t pSet_tmp=0;
  EEPROM.get((int)&p_Set, pSet_tmp);
  Serial.print(F("rD1_per = "));  Serial.println(pSet_tmp);
 
  long step_tmp=0;
  EEPROM.get((int)&step_M, step_tmp);
  Serial.print(F("curr_pos _get= "));  Serial.println(step_tmp);
 //stepper2.setCurrentPosition(step_tmp);
 // Serial.print(F("curr_pos_stepper = "));  Serial.println(stepper2.currentPosition());
 
  EEPROM.get((int)&w_Mode, workMode);
  Serial.print(F("workMode = "));  Serial.println(workMode);

  EEPROM.get((int)&vol_D1, tmp);
  Serial.print(F("cnt1 = "));  Serial.println(tmp);

  EEPROM.get((int)&vol_D2, tmp);
  Serial.print(F("cnt2 = "));  Serial.println(tmp);
    
  boolean tmp_b;
  EEPROM.get((int)&stepZero_eemem, tmp_b);
  Serial.print(F("stepZero = "));  Serial.println(tmp_b);

  EEPROM.get((int)&stepLuft_eemem, stepLuft);
  Serial.print(F("stepLuft = "));  Serial.println(stepLuft);

  EEPROM.get((int)&stepLuft_Down_eemem, stepLuft_Down);
  Serial.print(F("stepLuft_Down = "));  Serial.println(stepLuft_Down);

  EEPROM.get((int)&stepLuft_Up_eemem, stepLuft_Up);
  Serial.print(F("stepLuft_Up = "));  Serial.println(stepLuft_Up);
}
//-------------------------------------------------------------
void loop(){
    delay(2000);
    WriteNewBackup();
    BackupRead();
}
И вот какой лог получается:
r_D1 = 4294903760 //должен быть 2000
r_D2 = 131072100 // 100
rD1_per = 10
curr_pos _get= 7936 //8000
workMode = 0
cnt1 = 1677721605 //5
cnt2 = 4278190087 //7
stepZero = 0
stepLuft = 0
stepLuft_Down = 1
stepLuft_Up = 1

В какую сторону искать решение ?
типы данных проверил чтоб совпадали в ЕЕМЕМ и в функциях.Даже дело и не в этом, простое число записывается косо.

---------------------------------------
Плата Arduino Nano китайская. Прошивается только процессор: Atmega328P( OldBootloader )

Еще опыт провёл - оставил только большие цифры писать в память , и вот :
r_D1 = 167774160
r_D2 = 131072100
curr_pos _get= 1677729600
cnt1 = 4278190085
cnt2 = 7

Ай ниид хэлп:rolleyes:o_O
 

Mix_man

✩✩✩✩✩✩✩
21 Янв 2020
91
9
Похоже вычислил в чём глюк.
Нельзя в функцию put сразу переменную писать, надо через переменную. Хотя байт пишется нормально.
Так не работает:
EEPROM.put((int)&r_D1, 2000); //uint16_t

А так работает:
uint16_t tmp=2000;
EEPROM.put((int)&r_D1, tmp);

Это типо глюк какой-то или наоборот так и должно быть(что нельзя в put сразу цифру написать)?
 

b707_2

★★✩✩✩✩✩
22 Июл 2020
182
51
у вас каша в голове.
Если вы описали переменную с квалификатором EMEM. то запихивать ее в ЕЕПРОМ методом put не нужно, достаточно написать просто
r_D1 = 2000;
эта переменная УЖЕ В ЕЕПРОМ.

с чтением тоже самое.
 
  • Лойс +1
Реакции: Un_ka

Mix_man

✩✩✩✩✩✩✩
21 Янв 2020
91
9
у вас каша в голове.
Если вы описали переменную с квалификатором EMEM. то запихивать ее в ЕЕПРОМ методом put не нужно, достаточно написать просто
r_D1 = 2000;
эта переменная УЖЕ В ЕЕПРОМ.
Да вот ХренаСдва! это Вы какую-то кашу написали. Может имел ввиду какуюто другую плату, на Ардуино Нано ваша теория не работает от слова совсем. Ни запись ни чтение.


Похоже вычислил в чём глюк.
Нельзя в функцию put сразу переменную писать, надо через переменную. Хотя байт пишется нормально.
Так не работает:
EEPROM.put((int)&r_D1, 2000); //uint16_t

А так работает:
uint16_t tmp=2000;
EEPROM.put((int)&r_D1, tmp);
Работает вот так. с многоходовочкой через переменную. Ито не со всеми типами данных!!!
Методом научного тыка изучаю какие типы можно напрямую записать , без посредников.

И Un_ka лайкос прожал непонятно на что.🤷‍♂️🤦‍♂️
 

b707_2

★★✩✩✩✩✩
22 Июл 2020
182
51
Да вот ХренаСдва! это Вы какую-то кашу написали. Может имел ввиду какуюто другую плату, на Ардуино Нано ваша теория не работает от слова совсем. Ни запись ни чтение.
приведите код, как вы это делаете, что у вас не работает.

Еще раз, описание переменной с квалификатором EMEM размещает ее в ЕЕПРОМ. Если вы присваиваете этой переменной какое-то значение, скажем r_D1 = 2000; - то это значение АВТОМАТИЧЕСКИ записывается в ЕЕПРОМ.

А так, как вы делаете, через EEPROM.put() - тогда не понятно, зачем вам вообще EMEM

uint16_t tmp=2000;
EEPROM.put((int)&r_D1, tmp);

Работает вот так. с многоходовочкой через переменную. Ито не со всеми типами данных!!!
Тут у вас другая ошибка. Нафига вы ссылку на переменную r_D1 приводите к типу инт? поэтому вам и приходится писать туда значение через временную переменную типа uint16_t

И давайте без лишних эмоций. Раз вы задаете вопросы - явно не очень в этом разбираетесь
 

Mix_man

✩✩✩✩✩✩✩
21 Янв 2020
91
9
так я вроде всё делаю в соответствии как в уроке прочитал.

Без приведения ссылки к типу int вообще работать не будет. Это жэ относится непосредственно к типу самой ссылки. что её формат будет типа int, а то на какие какие данные она ссылает , это получается уже совсем другое. Эту мысль надо обсудить.

Как в примере - так это прощще простого. Сначала объявили список переменных ЕЕМЕМ, кампилятор сам адреса раздаст. Потом какието данные надо записать, конструкция для записи и чтения вот из примера тоже(с приведением ссылки к типу int.

Это вы то что говорите прямо реально не один раз делали? и Всё работает? .

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

Может вы какуюто другую литературу читали про ЕЕМЕМ, тогда давайте оспаривать терминологию из примера Алекса.
 

b707_2

★★✩✩✩✩✩
22 Июл 2020
182
51
если вы хотите практически решить вопрос - используйте конструкции, описанные в этом гайде в разделе
Библиотека EEPROM.h, они точно работают.
то есть лучше не путать в одном коде EEMEM и EEPROM.


Если же вы хотите разобраться. то проверять все. что там написано - я сейчас не готов, я на работе и ардуины у меня с собой нет
 
Изменено:

Mix_man

✩✩✩✩✩✩✩
21 Янв 2020
91
9
Даже если ардуины и нет под рукой, то в этом гайде уж точно нет описания работы c EEPROM подобного вашему и что автоматически само кудато будет записываться. Я уже сказал вашу теорию я проверил, НЕ работает.

Конструкции из гайда работают используя буферную переменную. Осталось проблема с одной переменной, всё время Ноль читается из памяти
 

b707_2

★★✩✩✩✩✩
22 Июл 2020
182
51
Даже если ардуины и нет под рукой, то в этом гайде уж точно нет описания работы c EEPROM подобного вашему и что автоматически само кудато будет записываться. Я уже сказал вашу теорию я проверил, НЕ работает.
Да, был неправ, переменные EEMEM автоматически в епром не пишутся.


Конструкции из гайда работают используя буферную переменную.
что касается этого вопроса - тут я могу дать ответ. Посмотрите внимательнее, в гайде нет таких строк, как у вас:
C++:
EEPROM.put((int)&r_D1, 2000);
В гайде везде на втором месте стоит переменная, а не просто число, как у вас. С числом это не работает и вот почему. Метод EEPROM.put() реализован через шаблоны, для того чтобы он работал правильно - ему нужно знать, какого типа переменную вы пытаетесь записать. А когда вы указываете просто значение "2000" - у него нет никакого типа и метод не может правильно определить, как с ней работать.
Напишите так
C++:
EEPROM.put((int)&r_D1, (uint32_t)2000);
или так
C++:
EEPROM.put((int)&r_D1, 2000ul);
и буферная переменная будет не нужна
 
  • Лойс +1
Реакции: Mix_man

Mix_man

✩✩✩✩✩✩✩
21 Янв 2020
91
9
Напишите так
C++:
EEPROM.put((int)&r_D1, (uint32_t)2000);
или так
C++:
EEPROM.put((int)&r_D1, 2000ul);
и буферная переменная будет не нужна
вот вот. Проверю, отпишусь. Может заодно и решится проблема с "вредной переменной" которая не хочет записаться.

Так а функцию какуюто, которая возвращает значение я же могу писать на втором месте? поидее должно работать, ведь у возвращаемого значения тип известен.
=============================================

работает 100%. Отлично поработали :)
Считаю эту информацию можно дописать в гайд. Чтоб молодые мозги сразу учились хорошему :)
В виде отдельного абзаца про записывание просто цифр.
 
Изменено: