ATtiny85 и работа с EEPROM
- Войдите на сайт для отправки комментариев
Имеется скромный проект из данного МК и набора из шести светодиодов WS2812, которыми он управляет. Это подсветка. Режимов у подсветки целый набор. В один прекрасный вечер решил, что информацию о режиме подсветки будет удобнее хранить в ПЗУ, чтобы каждый раз при выкл/вкл подстветка продолжала работать в том режиме, когда отрубили питание.
Написал код. Проверил на макете с Attiny85. Вроде все ок. Но вот при работе в реальных условиях режим часто либо не восстанавливается (леды не горят и нет реакции на нажатие кнопки), либо режим перескакивает на другой (чаще +1, но бывает и больше).
Спасает обнуление ЕЕПРОМа и запись прошивки по новой, но чтобы с этим не мучится в сетап добавил пару строк:
if (EEPROM.read(addr) > NUM_PATTERNS || EEPROM.read(addr) < 0)
{
EEPROM.write(addr,0);
}В loop у меня сидит функция startShow (EEPROM.read(addr)), которая на основе прочитанного из addr зажигает тот или иной режим подсветки, которых от 0 до 14 (NUM_PATTERNS). 0 - выкл.
Для каждого режима подсветки написана отдельная функция. В каждой из них обрабатывается нажатие кнопки, которая перебирает режимы от 0 до 14. Нажатие кнопки также сидит в своей функции. Вот она:
boolean chkBtn(int buttonState) {
if (buttonState == HIGH && (millis() - mark) > BTN_DELAY) {
mark = millis();
pattern = EEPROM.read(addr);
pattern++;
if (pattern > NUM_PATTERNS) {pattern = 0;}
EEPROM.write(addr, pattern);
return true;
}
else { return false; }
}Здесь она соответственно считывает из ЕЕПРОМа данные о режиме, записывает их во временную переменную pattern (тип byte), прибавляет к ней единичку, проверяет не вылетели ли мы за пределы, а если да то начинаем отсчет с начала, если ок, то записываем переменную в ЕЕПРОМ.
При изучении глюка выяснилось, что на макетке тоже не все так радостно. В лучшем случае режим работы подсветки работал (корректно восстанавливался) 5 раз из 10 включений.
Однако если залить эту самую прошивку в Atmega328 (Arduino NANO) глюка нет. Чую что не правильно работаю с ЕЕПРОМом (юзаю стандартную библиотеку из Arduino IDE), глюк в прошивке. Правда есть одно но. Тини работает в очень скромной "обвязке" - 2 кондера по питанию 0,1мкф, 100мкф и все. А Atmega328 располагается на нашпигованой плате.
Помогите советом...
1. Код надо приводить полностью. Например, мне кажется, у Вас ошибка в строке №6, но по этому куску уверенно не скажешь.
2. Как установлен фьюз EESAVE?
Большое спасибо за мысль с фьюзом. Как он стоит сейчас не вспомню, но как только будет возможность проверью и отпишусь. Сответственно тогда и скину код.
и никада не пиши в AVR EEPROM ничего значимого с адреса 0, протухает время от времени. Пиши начиная хотя бы с 0x10.
и никада не пиши в AVR EEPROM ничего значимого с адреса 0, протухает время от времени. Пиши начиная хотя бы с 0x10.
Семён, развенчание этих сказок Atmel уже даже в FAQ вынес. Пишут, что была проблема, когда при внезапном отключении питания нулевая ячейка не успевала записаться. Но ее давно уже пофиксили, ввели в чип мониторы напряжения или типа того.
тем не менее. я всего с одной Nanoй абжогса полтора года назад еще, дак теперь не только с 0х10 пишу, а еще и контрольную сумму считаю при старте.
ее давно уже пофиксили
Это микрочип пофиксил, а Вы уверены, что то, что мы закупаем в Поднебесной имеет отношение к микрочип?
Спасибо за совет. Тоже попробую.
ее давно уже пофиксили
Это микрочип пофиксил, а Вы уверены, что то, что мы закупаем в Поднебесной имеет отношение к микрочип?
Справки я не выдаю, рентгеном все чипы не просвечиваю. О чем прочитал - тем поделился.
ее давно уже пофиксили
Это микрочип пофиксил, а Вы уверены, что то, что мы закупаем в Поднебесной имеет отношение к микрочип?
я уверен - лично вам продают палёные контроллеры и палёную водку.
палёную водку.
Ты ошибся, родной, он водку не покупает. Ему продают палёный боярышник.
это мне всё паленое продають.
Как и обещал привожу код ниже целиком:
#include <EEPROM.h> #include <Adafruit_NeoPixel.h> #define RND_PIN 5 //для рандома (5 для ATTiny85 1ая нога) #define PHOTO_PIN 4 //фоторезистор (3 для ATTiny85 2ая нога) #define NUM_LEDS 6 //кол-во светодиодов #define DATA_PIN 2 //output pin (0 для ATTiny85 5ая нога) mega328 - 2 #define BTN_PIN 3 //input pin (4 для ATTiny85 3ья нога) mega328 - 3 #define BTN_DELAY 250 //задержка для дребезга #define NUM_PATTERNS 14 //кол-во эффектов #define PHOTO_MIN 20 //минимальный порог показания датчика освещенности #define PHOTO_MAX 800 //максимальный порог показания датчика освещенности #define BRIGHT_MIN 150 //минимальная яркость #define BRIGHT_MAX 255 //максимальная яркость #define PHOTO_LATENCY 10000 //период опроса датчика освещенности //массивы uint32_t colorset[] = {0xFF0000, 0x00FF00, 0x0000FF, 0xFFC000, 0xFF4000, 0xFF0C00, 0xFF0040, 0xFF7F00, 0x00FFFF, 0xFF00FF, 0xC0FF00, 0x40FF00, 0x00FFC0, 0x00FF40, 0xFF007F, 0x7FFF00, 0x7F00FF, 0xC000FF, 0x4000FF, 0x00C0FF, 0x0040FF, 0xFFFF00, 0x00FF7F, 0x007FFF}; uint32_t RGB[] = {0,0,0,0,0,0}; //общие переменные uint8_t num = 0; uint8_t buttonState = 0; uint8_t direction = 1; uint8_t j = 1; uint32_t mark, lastCheckPhoto; byte pattern = 0; int addr = 0; //ledJump переменные uint8_t total_leds; uint8_t r; //randomFader переменные uint8_t lastRND; uint8_t lastPix = 0; uint8_t myPix = 0; uint32_t pastColor = 0; //colorFader переменные int8_t direct1 = 1; int8_t direct2 = -direct1; uint8_t v = 0; int16_t color1 = 0; int16_t color2 = 0; Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800); void setup() { delay (1500); randomSeed(analogRead(RND_PIN)); pinMode(BTN_PIN,INPUT); strip.begin(); strip.show(); delay (1500); if (EEPROM.read(addr) > NUM_PATTERNS || EEPROM.read(addr) < 0) { EEPROM.write(addr,0); } } void loop() { if (direction == 1) { j++; } else { j--; } if (j > 254 || j < 1) {direction = -direction;} if (millis() - lastCheckPhoto > PHOTO_LATENCY) { uint16_t photo = constrain(analogRead(PHOTO_PIN), PHOTO_MIN, PHOTO_MAX); uint8_t bright = map(photo, PHOTO_MIN, PHOTO_MAX, BRIGHT_MIN, BRIGHT_MAX); strip.setBrightness(bright); lastCheckPhoto = millis(); } startShow (EEPROM.read(addr)); } void startShow (int show) { switch(show){ case 0: fastColor(0,0,0); break; case 1: colorFader (1, 150, 10); break; case 2: colorFader (2, 150, 10); break; case 3: colorFader (3, 150, 10); break; case 4: if (num == 24) {num = 0;} ledJumpIn(100, 10000); ledJumpOut(100, 1000); num++; break; case 5: randomPixelFader (1500); break; case 6: randomStripFader(500); break; case 7: rainbowCycle(50); break; case 8: rainbow(50); break; case 9: fastColor(255,0,0); break; case 10: fastColor(255,255,0); break; case 11: fastColor(0,255,0); break; case 12: fastColor(0,255,255); break; case 13: fastColor(0,0,255); break; case 14: fastColor(255,0,255); break; } } void ledJumpIn (uint16_t wait, uint16_t interval_) { total_leds=NUM_LEDS; for (int i = 0; i < total_leds; i++) { strip.setPixelColor(i, colorset[num]); strip.show(); if (i == total_leds-1) { i=-1; --total_leds; if (total_leds == -1) { break;} } timer(wait); strip.setPixelColor(i, 0); strip.show(); } timer(interval_); } void ledJumpOut(uint16_t wait, uint16_t interval_) { total_leds = NUM_LEDS; r = 1; for (int i = NUM_LEDS-1; i < total_leds+1; i++) { if (r == total_leds+1) {break;} strip.setPixelColor(i, colorset[num]); strip.show(); if (i==total_leds) { ++r; i -= r; } timer(wait); strip.setPixelColor(i, 0); strip.show(); } timer(interval_); } void colorFader (int8_t colormode, uint16_t wait, uint16_t shift) { uint8_t red, green, blue; if (direct1 == 1) { v++; } else { v--; } color1 += direct1*shift; color1 = constrain (color1,0,255); color2 += direct2*shift; color2 = constrain (color2,0,255); switch (colormode) { case 1: red = color1; green = color2; blue = 0; break; case 2: red = 0; green = color1; blue = color2; break; case 3: red = color1; green = 0; blue = color2; break; } for (int pos = strip.numPixels()-1; pos > -1; pos--) { if (pos != 0) { strip.setPixelColor(pos, RGB[pos]); RGB[min(pos+1,strip.numPixels()-1)] = RGB[pos]; } else if (pos == 0) { RGB[pos] = strip.Color(red, green, blue); strip.setPixelColor(pos, RGB[pos]); RGB[pos+1] = RGB[pos]; } } strip.show(); timer(wait); if (v == (255/shift) || v == 0) { direct1 = -direct1; direct2 = -direct2;} } void randomPixelFader(uint16_t wait) { uint32_t timer = 0; uint8_t colorPick[] = {0,0,0}; uint8_t getRND1, getRND2; if (millis() - timer > wait) { if(myPix != lastPix) { getRND1 = (random(3)); do { getRND2 = (random(3)); } while (getRND1 == getRND2 || getRND2 == lastRND); colorPick[getRND1] = (random(255)); colorPick[getRND2] = 255; fromColorToColor(myPix, 0, RGB[myPix], 10); RGB[myPix] = strip.Color(colorPick[0], colorPick[1], colorPick[2]); fromColorToColor(myPix, RGB[myPix], 0, 10); strip.show(); timer=millis(); lastPix=myPix; lastRND=getRND2; } else { myPix=random(0,strip.numPixels());} } } void randomStripFader(uint16_t wait) { uint8_t colorPick[] = {0,0,0}; uint8_t getRND1, getRND2; getRND1 = (random(3)); do { getRND2 = (random(3)); } while (getRND1 == getRND2 || getRND2 == lastRND); colorPick[getRND1] = (random(255)); colorPick[getRND2] = 255; uint32_t color = strip.Color(colorPick[0], colorPick[1], colorPick[2]); for(uint16_t d = 0; d < strip.numPixels(); d++) { fromColorToColor(d, color, pastColor, 2); timer(wait); } pastColor = color; lastRND = getRND2; } void rainbow(uint8_t wait) { for (uint16_t f = 0; f < strip.numPixels(); f++) { strip.setPixelColor(f, Wheel((f + j) & 255));} strip.show(); timer (wait); } void rainbowCycle(uint8_t wait) { for (uint16_t g = 0; g < strip.numPixels(); g++) { strip.setPixelColor(g, Wheel(((g * 256 / strip.numPixels()) + j) & 255));} strip.show(); timer(wait); } void fastColor (uint8_t red, uint8_t green, uint8_t blue) { for (uint16_t k = 0; k < strip.numPixels(); k++) { strip.setPixelColor(k, red, green, blue); strip.show(); if(chkBtn(digitalRead(BTN_PIN))) { break; } } } void fromColorToColor(uint8_t pixel, uint32_t newColor, uint32_t oldColor, uint8_t wait) { int16_t new_c[3], old_c[3], diff[3], cur_c[3]; for (uint8_t l = 0; l < 3; l++) { new_c[l] = (uint8_t)((newColor >> (16-(l*8))) & 0xff); old_c[l] = (uint8_t)((oldColor >> (16-(l*8))) & 0xff); cur_c[l] = old_c[l]; } for (uint8_t q = 0; q < 255; q++) { for (uint8_t w = 0; w < 3; w++) { if (cur_c[w] < new_c[w]) {diff[w] = 1;} else if (cur_c[w] > new_c[w]) {diff[w] = -1;} else {diff[w] = 0;} cur_c[w] += diff[w]; } strip.setPixelColor(pixel,cur_c[0],cur_c[1],cur_c[2]); strip.show(); timer(wait); } } void timer(uint16_t period) { uint32_t timer = 0; timer = millis(); do { if(chkBtn(digitalRead(BTN_PIN))) { break; } } while (millis() - timer < period); } boolean chkBtn(int buttonState) { if (buttonState == HIGH && (millis() - mark) > BTN_DELAY) { j = 1; pastColor = 0; mark = millis(); pattern = EEPROM.read(addr); pattern++; if (pattern > NUM_PATTERNS) {pattern = 0;} EEPROM.write(addr, pattern); return true; } else { return false; } } uint32_t Wheel(byte WheelPos) { if (WheelPos < 85) { return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } else if (WheelPos < 170) { WheelPos -= 85; return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else { WheelPos -= 170; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } }А вот по поводу фьюзов конфуз. Я вообще их не выставлял и как они должны быть выставлены не знаю. Если можно как-то выставить конкретный фьюз то как это сделать через тот же Ардуино ИДЕ например?
В Ардуино ИДЕ чтобы прошить ATtiny85 я выставляю настройки через меню следующим образом
И как Вы её прошиваете?
Давайте так, Вы не тяните кота за хвост, а расскажит епоностью.
1. Что за 85-ая? На какой плате? на самопальной или покупной? Если ли на плате кварц? Какой?
2. Как Вы её прошиваете? Командой "пршить через программатор" или у Вас там на плате FTDI имеется? Если через программатор, что какой?
Тогда я сомогу ответить про фьюзы и всё остальное. Потому как, если кварца нет, то 16МГц явно много. Должно быть 8 или 1 в зависимости от фьюзов. Ну и много всего - давайте информацию.
Извините, что не предоставил информацию заранее
Это ATTINY85-20SU SOIC8
Шью из Arduino IDE через Arduino NANO, который заранее прошил скетчем ArduinoISP из готовых примеров. Шью на обычной борде вот в таком виде только без светодиода с резистором
В готовом проекте кварц не использую
Для работы с Тини тянул библиотеки отсюда https://github.com/SpenceKonde/ATTinyCore
Значит 16МГц - ТОЧНО мимо. Пробуйте 8, но чтобы гоаорить точно ... можете зайти в меню "Файл|настройки", Включить там подробный вывод загрузки и скопипастить сюда всё, что выдаётся во время загрузки?
Я может че не знаю, но уже штук несколько программировал at85 там же просто выбирается в arduino ide нужный МК и жмется пункт записать загрузчик - ставиться нужная частота - нет?
И кстати attiny при 3 вольтах питания работает только при частоте 1 МГц
Я не знаю, я ни разу не прошивал через ардуино.
Но точно я знаю, что
1. 16МГц (как стоит у ТС) без кварца невозможно
2. Если стоит 16МГц, а реально там 1 или 8, то всё, что связано со временем (millis, delay и т.п.) будет врать
Вот и пытаюсь узнать какие там у ТС фьюзы.
1. 16МГц (как стоит у ТС) без кварца невозможно
ATtiny85 на частоте 16 МГц с использованием PLL должен работать нормально при напряжении питания более 3,3В.
1. 16МГц (как стоит у ТС) без кварца невозможно
ATtiny85 на частоте 16 МГц с использованием PLL должен работать нормально при напряжении питания более 3,3В.
Должен? Сами пробовали?
1. 16МГц (как стоит у ТС) без кварца невозможно
ATtiny85 на частоте 16 МГц с использованием PLL должен работать нормально при напряжении питания более 3,3В.
Нормально работает - интервалы соответствуют установленным.Работает от 5ти вольт. Что еще проверить ?Иде 1.8.5 , AttinyCore из ссылки ТС
1. 16МГц (как стоит у ТС) без кварца невозможно
ATtiny85 на частоте 16 МГц с использованием PLL должен работать нормально при напряжении питания более 3,3В.
Нормально работает - интервалы соответствуют установленным.Работает от 5ти вольт. Что еще проверить ?Иде 1.8.5 , AttinyCore из ссылки ТС
Я извиняюсь но вопрос был про 16 МГц и 3 вольта, а вы пишите что работает при 5 вольт .
Впрочем не важно, пока сами на грабли не наступил это все теория.
И вообще тема про eeprom - давайте придерживаться
Я извиняюсь но вопрос был про 16 МГц и 3 вольта,
Где вопрос про 16Мгц и 3 вольта? Евгений спрашивал про возможность работы от внутреннего на 16Мгц. Вот я и ответил и проверил. А на 3,3 вольта если кому и надо - пусть проверяют.Хотя сейчас гляну...
Работает и на 3.3вольта. Но надо проверять на стабильность.
Спасибо.