При записи/чтении в/из EEPROM микроконтроллер как-будто пропускает шаги/повторяет цикл
Программирую микроконтроллер AMGEGA328P. Проблема начинается в функции writeNewSensorSettings(). Кратное описание - есть массив ячеек EEPROM, я прохожусь по нему начиная с 0 до 1000 по 3 шт. Так как я записываю в ячейку структуру, имеющую в себе 3 значения типа byte. Функция начинает с 0 , проверяет ячейку на пустоту сравнивая значения из нее с 255 (пусты ячейки по дефолту забиты как 255), затем, если ячейка пуста и если i=0 ставит id = 1 (т.к это первый элемент), а если i!=0, то просто смотрит на id на 3 элемента назад и делает id+1, заполняет структура инфой и пишет в EEPROM. Так вот, тут и начинается магия - если я пишу допустим 3 структуры, моя функция может написать мне и 5 и 6 структур (как-будто одна из них дублируется несколько раз или каждая из них дублируется по 2 раза) (что я точно заметил, так это то, что 0-й элемент может быть пустым, но функция isitFreeCell() - скажет что он полный (что на самом деле неверно), но при этом он все-же заполнится новой информацией и таким образом функция заполнит по 2-3 ячейки перед тем как закончится первая итерация цикла). Но как только я пытаюсь отследить ошибку при помощи Serial - ошибка перестает иметь места и все записывается корректно (я вставляю ооочень много Serial.print на каждом "повороте". Думал что проблема в скорости записи/чтения из eeprom. Натыкал везде delay, не помогло.
// ЭТО СКЕТЧ ПРИЁМНИКА (БАЗА)!!!
//--------------------- НАСТРОЙКИ ----------------------
#define CH_NUM 0x60 // номер канала, должен совпадать с передатчиком (датчик)
// УРОВЕНЬ МОЩНОСТИ ПЕРЕДАТЧИКА
// На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
#define SIG_POWER RF24_PA_MAX
// СКОРОСТЬ ОБМЕНА
// На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
// должна быть одинакова на приёмнике и передатчике!
// при самой низкой скорости имеем самую высокую чувствительность и дальность!!
// ВНИМАНИЕ!!! enableAckPayload (основная функция обмена данными) НЕ РАБОТАЕТ НА СКОРОСТИ 250 kbps!
#define SIG_SPEED RF24_1MBPS
//--------------------- НАСТРОЙКИ ----------------------
//--------------------- БИБЛИОТЕКИ ---------------------
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10
//--------------------- БИБЛИОТЕКИ ---------------------
//--------------------- ПЕРЕМЕННЫЕ ----------------------
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб
byte Data[3]; // массив принятых данных
byte callbackData[2]; //массив отправляемых данных
byte pipeNo; //Байтовая переменная хранения номера трубы для отправки
struct Sensor { //Переменная типа struct для хранения данных о датчике
byte id;
byte type;
byte data;
};
//--------------------- ПЕРЕМЕННЫЕ ----------------------
void setup() {
Serial.begin(9600); //открываем порт для связи с ПК
radioSetup();
for(int i =0; i<90; i++){
clearSensorById(i);
delay(200);
Serial.print("Info "); Serial.println(eeprom_read_byte(i));
delay(5);
}
}
void loop() {
while( radio.available(&pipeNo)){ // слушаем эфир со всех труб
radio.read( &Data, sizeof(Data) ); // чиатем входящий сигнал
if (Data[0] == 0){
Sensor newSensor;
writeNewSensorSettings(Data[1],Data[2],newSensor);
callbackData[0]=newSensor.id;
callbackData[1]=newSensor.type;
radio.writeAckPayload(pipeNo, &callbackData, sizeof(callbackData));
// Serial.print("Recieved: ID "); Serial.println(Data[0]);
// Serial.print("Recieved: TYPE "); Serial.println(Data[1]);
// Serial.print("Recieved: DATA "); Serial.println(Data[2]) ;
}
Serial.print("Recieved: ID "); Serial.println(Data[0]);
Serial.print("Recieved: TYPE "); Serial.println(Data[1]);
Serial.print("Recieved: DATA "); Serial.println(Data[2]);
}
}
void radioSetup() { // настройка радио модуля
radio.begin(); // активировать модуль
radio.setAutoAck(1); // режим подтверждения приёма, 1 вкл 0 выкл
radio.setRetries(0, 15); // (время между попыткой достучаться, число попыток)
radio.enableAckPayload(); // разрешить отсылку данных в ответ на входящий сигнал
radio.setPayloadSize(32); // размер пакета, байт
radio.openReadingPipe(1, address[0]); // хотим слушать трубу 0
radio.setChannel(CH_NUM); // выбираем канал
radio.setPALevel(SIG_POWER); // уровень мощности передатчика
radio.setDataRate(SIG_SPEED); // скорость обмена
// должна быть одинакова на приёмнике и передатчике!
// при самой низкой скорости имеем самую высокую чувствительность и дальность!!
radio.powerUp(); // начать работу
radio.startListening(); // начинаем слушать эфир, мы приёмный модуль
}
bool isItFreeCell(int num) {
byte cash = eeprom_read_byte((uint8_t*)num);
delay(15);
if (cash == 255) {
return true;
}
else {
return false;
}
}
void clearSensorById(int id) {
for (int i = 0; i < 1000; i= i + 3)
{
if (eeprom_read_byte((uint8_t*)i) == id)
{
eeprom_write_byte((byte*)i, 255);
delay(10);
eeprom_write_byte((byte*)i + 1, 255);
delay(10);
eeprom_write_byte((byte*)i + 2, 255);
delay(10);
break;
}
}
}
void writeNewSensorSettings(byte type, byte data, Sensor& CallbackData) {
Sensor mySensor;
mySensor.type = type;
mySensor.data = data;
for (int i = 0; i < 1000; i = i + 3) {
if (isItFreeCell(i) == true) {
if (i==0){
mySensor.id=1;
}else {
mySensor.id = eeprom_read_byte((uint8_t*)i-3)+1; //Чтение из eeprom
}
eeprom_write_block((void*)&mySensor, (int*)i, sizeof(mySensor));
eeprom_read_block((void*)&CallbackData, (int*)i, sizeof(CallbackData));
break;
}
}
}
void readSensorSettingsById(Sensor& mySensor, int id){
for (int i =0;i<1000;i= i+3){
if (eeprom_read_byte((uint8_t*)i) == id) {
eeprom_read_block((void*)&mySensor, (int*)i, sizeof(mySensor));
}
}
}
Ответы (1 шт):
Проблема решена, но непонятно почему потоки в arduino работают именно так. Был добавлен delay(500); иначе условие не дожидалось окончания функции isItFreeCell(i) и приходила сразу к записи
void writeNewSensorSettings(byte type, byte data, Sensor& CallbackData) {
Sensor mySensor;
mySensor.type = type;
mySensor.data = data;
for (int i = 0; i < 1000; i = i + 3) {
// Serial.print("i= "); Serial.println(i) ;
if (isItFreeCell(i) == true) {
delay(500);
if (i==0){
mySensor.id=1;
}else {
mySensor.id = eeprom_read_byte((uint8_t*)i-3)+1; //Чтение из eeprom
}
// Serial.print("Старый id = "); Serial.println(mySensor.id);
// Serial.print("Новый id = "); Serial.println(eeprom_read_byte((uint8_t*)i-3)) ;
eeprom_write_block((void*)&mySensor, (int*)i, sizeof(mySensor));
eeprom_read_block((void*)&CallbackData, (int*)i, sizeof(CallbackData));
break;
}
}
}