Лента WS2812B мигает вместо того, чтобы беспрерывно светиться с EEPROM

magdara
Offline
Зарегистрирован: 30.01.2018

Здравствуйте. Буду благодарен за помощь новичку в ардуино, чтобы исправить проблему.
Я использую Arduino Nano V3.0 AVR ATmega328P и диодную ленту с ШИМ WS2812B.
Задача в том, чтобы в EEPROM памяти сохранялось сколько диодов горело перед выключением питания, и за тем после возобновления питания на ленте загорались столько же диодов, как и до выключения питания.
Столкнулся с проблемой, что лента раз в пол секунды загорается и тухнет (какой делей поставил так и работает) и я не понимаю почему.
Буду благодарен за исправления и разъяснения почему оно так работает.
Заранее благодарен:)

 Arduino Nano V3.0 AVR ATmega328P

#include <Adafruit_NeoPixel.h>
#include <EEPROM.h>
#define ledPIN 2
#define redButtonPIN 3
#define greenButtonPIN 4
#define NUMPIXELS 15
uint8_t maxValue EEMEM = 15;
uint8_t currentValue EEMEM;
uint8_t firstByteInEEOROM EEMEM = 0;
uint8_t secondByteInEEOROM EEMEM = 1;
bool isFirstSession = true;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, ledPIN, NEO_GRB + NEO_KHZ800);

void setup() {
  if (EEPROM.read(firstByteInEEOROM) == isFirstSession) {
    EEPROM.put(firstByteInEEOROM, false);
    EEPROM.put(secondByteInEEOROM, maxValue);
  }
  currentValue = EEPROM.get(secondByteInEEOROM, currentValue);
  strip.begin();
  strip.show(); 
  pinMode(ledPIN, OUTPUT);
  pinMode(redButtonPIN, INPUT);
  pinMode(greenButtonPIN, INPUT);
 }

void loop() {
  outPixels();
  redButton();
  greenButton();
 }

void outPixels(){

  uint8_t valuePoints = calculationCurrentValue();

    if (currentValue == 0){
      displayRedPixels();
      delay(70);
      displayEmptyPixels();
      delay(70);
      displayRedPixels();
      delay(70);
    } 
    else {
    for (uint8_t displayPixel = 0; displayPixel < valuePoints; displayPixel++){
     strip.setPixelColor(displayPixel, strip.Color(0, 50, 0)); // R, G, B
     strip.show();
    }
   
    for (uint8_t displayRedPixel = maxValue-1; displayRedPixel != valuePoints-1; displayRedPixel--){
      strip.setPixelColor(displayRedPixel, strip.Color(0, 0, 0)); // R, G, B
      strip.show();
    }
   delay(500);
   }
 }

uint8_t calculationCurrentValue(){
  return 0 + currentValue;
 }

void displayRedPixels(){
  for (uint8_t displayRedPixel = 0; displayRedPixel < NUMPIXELS; displayRedPixel++){
      strip.setPixelColor(displayRedPixel, strip.Color(100, 0, 0)); // R, G, B
      strip.show();
     }
 }

void displayEmptyPixels(){
  for (uint8_t displayEmptyPixel = 0; displayEmptyPixel < NUMPIXELS; displayEmptyPixel++){
      strip.setPixelColor(displayEmptyPixel, strip.Color(0, 0, 0)); // R, G, B
      strip.show();
  }
 }

void wrightCurrentValueToStorage() {
  EEPROM.write(secondByteInEEOROM, currentValue);
 }

void redButton(){
  uint8_t redValue = digitalRead(redButtonPIN);
  Serial.print(redValue);
  if (redValue == 1){
    if (currentValue > 0){
    currentValue--;
    wrightCurrentValueToStorage();
    delay(500);
    }
  }
 }

void greenButton(){
  uint8_t greenValue = digitalRead(greenButtonPIN);
  if (greenValue == 1){
    if (currentValue < maxValue){
      currentValue++;
      wrightCurrentValueToStorage();
      delay(500);
      }
    }
 }


 

 

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

Ну, вы же указываете, что "какой делей поставил, так и работает". Получается, что все согласно задумке и функционирует. Проблема-то в чем заключается?

magdara
Offline
Зарегистрирован: 30.01.2018

Лента не должна мигать раз в пол секунды, а светить постоянно. 

__Alexander
Offline
Зарегистрирован: 24.10.2012
041       displayRedPixels();
042       delay(70);
043       displayEmptyPixels();
044       delay(70);
045       displayRedPixels();
046       delay(70);

Ну вот тут и мигает. При EmptyPixels. Всё логично.

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

В этом случае зачем вам строки 54-57 ?

magdara
Offline
Зарегистрирован: 30.01.2018

Оно мигает только если использовать EEPROM память 

Мигает сразу при включении питания. И ещё уточнение важное: 

в строках 

040     if (currentValue == 0){
041       displayRedPixels();
042       delay(70);
043       displayEmptyPixels();
044       delay(70);
045       displayRedPixels();
046       delay(70);
047     }
   

мигает красным светом displayRedPixels()

А при подключении питания мигает зелёным светом 

Если из этого кода убрать всё что касается EEPROM, то лента работает как надо 

строки:

 
018   if (EEPROM.read(firstByteInEEOROM) == isFirstSession) {
019     EEPROM.put(firstByteInEEOROM, false);
020     EEPROM.put(secondByteInEEOROM, maxValue);
021   }
022   currentValue = EEPROM.get(secondByteInEEOROM, currentValue);

 

080 void wrightCurrentValueToStorage() {
081   EEPROM.write(secondByteInEEOROM, currentValue);
082  }

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

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

Кнопки как подключены? Подтягивающие резисторы есть?

magdara
Offline
Зарегистрирован: 30.01.2018

Резисторов нету. 

Использую в качестве кнопок Датчик вибрации SW-420

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

Тогда сложно предсказывать как у вас  вызываются redButton() и greenButton(), которые определяют поведение ленты. И, возможно, они скоро угробят EEPROM.

Подключите кнопки по схеме для pinMode(..., INPUT_PULLUP) - это временно уберет фактор случайности.

 
magdara
Offline
Зарегистрирован: 30.01.2018

Хорошо, попробую, спасибо за ответ. 

Только, могли бы вы разъяснить, каким образом они могут угробить EEPROM и почему оно случайно и не предсказуемо работает? Это поможет в дальнейшем понимать как оно работает и не делать других ошибок в этой области.

__Alexander
Offline
Зарегистрирован: 24.10.2012

У вас пины для кнопок настроены на вход без всякой поддтяжки, управление идет логической 1, т.е. питанием. Так вот при такой настройке пина, на нем в результате наводок и помех может появлятся уровень, соответствующий "1". И скорее всего оно таки и есть, т.к. вызывается функция сохранения в эпром, а она вызывается из функций обработок кнопок. Сделайте настройку пинов как подсказали выше, только в таком случае управление надо будет осуществлять нулем. Т.е. надо будет комутировать на землю и в программе сравнивать уже не с 1, а с 0.

А эпром угробиться из-за ограниченного количества перезаписей. 100000. 

 

magdara
Offline
Зарегистрирован: 30.01.2018

Спасибо за помощь :) буду пробовать