Влияние работы ионизатора на работу схемы.

forfrends
Offline
Зарегистрирован: 24.02.2015

Всем привет! Делаю воздушный фильтр с возможностью ионизации воздуха. Основа - ESP-12F. Индикатор скорости кулера (и вкл/выкл ионизации) - лента WS2812. Но столкнулся с проблемой: при включении ионизации начинаются сбои в работе схемы. А именно: перестает отвечать светодиодная лента. Если крутить энкодер и всячески пробовать оживить прибор то лента все равно не реагирует, при этом кулер изменяет скорость, но в конце концов происходит перезагрузка устройства 

схема (кликабельно):

Энкодером задается скорость вращения кулера, кнопка энкодера - вкл/выкл ионизации. Все это отбражается на ленте в виде цверной шкалы. Мотор (кулер) управляется через ШИМ. Ионизатор включается через симистор и оптопару. + все это управляется через интернет при помощи Blynk.
В схеме 3 стабилизатора: 12 вольт - для питания кулера, 5 вольт - для питания ленты, 3.3 вольт - питание ESP.
Код:

#include <Adafruit_NeoPixel.h>

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "auth_token";

char ssid[] = "login";
char pass[] = "pass";

#define LedPIN      13      // D7 - GPIO13
                            // On Trinket or Gemma, suggest changing this to 1
#define NUMPIXELS   16      // Popular NeoPixel ring size

#define FanPin      5       // D1 - GPIO5
int FanSpeed    =   910;
#define MinFanPin   800

bool Ionithation =  false;
#define IonPin      16       // D0 - GPIO16

#define Button      4        // D2 - GPIO4
#define pin_A       14       // D5 - GPIO14
#define pin_B       12       // D6 - GPIO12

int Pow     =   8;
bool Timer  =   false;
bool TimerStep  =   false;
int TimerDelay  =   1;
int timerPrev   =   0;
int timeCount   =   0;


volatile long pause    = 50;  // Пауза для борьбы с дребезгом
volatile long lastTurn = 0;   // Переменная для хранения времени последнего изменения
volatile int count = 0;       // Счетчик оборотов
int actualcount    = 0;       // Временная переменная определяющая изменение основного счетчика
volatile int state = 0;       // Статус одного шага - от 0 до 4 в одну сторону, от 0 до -4 - в другую
volatile int pinAValue = 0;   // Переменные хранящие состояние пина, для экономии времени
volatile int pinBValue = 0;   // Переменные хранящие состояние пина, для экономии времени

    const uint32_t colorIonithation   = 0x200000; 
    const uint32_t colorNoIonithation = 0x000099; 
    const uint32_t colorBackground    = 0x002000; 

//Adafruit_NeoPixel pixels(NUMPIXELS, LedPIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, LedPIN, NEO_RGB + NEO_KHZ800);

void setup()
{
    Serial.begin(9600);
    
    Blynk.begin(auth, ssid, pass);
    // You can also specify server:
    //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80);
    //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);
    pinMode(pin_A, INPUT_PULLUP);
    pinMode(pin_B, INPUT_PULLUP);
    attachInterrupt ( digitalPinToInterrupt (pin_A), A, CHANGE);
    attachInterrupt ( digitalPinToInterrupt (pin_B), B, CHANGE);
    
    pinMode(Button, INPUT_PULLUP);
    pinMode(IonPin, OUTPUT);
    digitalWrite(IonPin, LOW);
    
    pinMode(FanPin, OUTPUT);
    analogWriteFreq(23000);
    analogWrite(FanPin, FanSpeed);
    
    pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
    pixels.show();  
    StripUpdate();

    Blynk.virtualWrite(V1, Pow);
    Blynk.virtualWrite(V2, Ionithation);
}

BLYNK_READ(V0)
{
    Blynk.virtualWrite(V0, Pow);
}

BLYNK_WRITE(V1)
{
    Pow = param.asInt();
    if (Pow > NUMPIXELS) Pow = NUMPIXELS;
    else if (Pow < 1) Pow = 1;
    StripUpdate();
}

BLYNK_WRITE(V2)
{
    Ionithation = param.asInt();
    StripUpdate();
}

BLYNK_WRITE(V3)
{
    Timer = param.asInt();
    if (Timer){
        TimerStep = false;
        Ionithation  = true;
        Blynk.virtualWrite(V2, Ionithation);
        StripUpdate();
    }
}

BLYNK_WRITE(V4)
{
    TimerDelay = param.asInt();
}

void loop()
{
    Blynk.run();

    button();

    if (Timer)
    {
        if (TimerStep)
        {
            if (millis()-timerPrev > 999){
                timerPrev = millis();
                timeCount++;
                if (timeCount > (TimerDelay*60))
                {
                    timeCount = 0;
                    TimerStep = false;
                    Ionithation  = true;
                    StripUpdate();
                    Blynk.virtualWrite(V2, Ionithation);
                }
            }
        }else{
            if (millis()-timerPrev > 999){
                timerPrev = millis();
                timeCount++;
                if (timeCount > 60)
                {
                    timeCount = 0;
                    TimerStep = true;
                    Ionithation  = false;
                    StripUpdate();
                    Blynk.virtualWrite(V2, Ionithation);
                }
            }
        }
    }
}

void button(){
    if (!digitalRead(Button)){
        Ionithation = !Ionithation;
        StripUpdate();
        Blynk.virtualWrite(V2, Ionithation);
        delay(300);
    }
}

void StripUpdate()
{
    FanSpeed = map(Pow, 1, NUMPIXELS, MinFanPin, 1023);
    if (FanSpeed > 1015){
        digitalWrite(FanPin, HIGH);
    }else{
        analogWrite(FanPin, FanSpeed);
    }
    digitalWrite(IonPin, Ionithation);
    cli(); // запрещаем перывания

    for (uint8_t i = 0; i < 16; i++) {
        pixels.setPixelColor(i, (i < Pow) ? (Ionithation ? colorIonithation : colorNoIonithation) : colorBackground);
    }

    pixels.show();
    sei(); // разрешаем прерывания
    delay(30);
}

void A()
{
    if (micros() - lastTurn < pause) return;  // Если с момента последнего изменения состояния не прошло
                                              // достаточно времени - выходим из прерывания
    pinAValue = digitalRead(pin_A);            // Получаем состояние пинов A и B
    pinBValue = digitalRead(pin_B);
    
    cli();    // Запрещаем обработку прерываний, чтобы не отвлекаться
    if (state == 0  && !pinAValue &&  pinBValue || state == 2  && pinAValue && !pinBValue) {
        state += 1;                         // Если выполняется условие, наращиваем переменную state
        lastTurn = micros();
    }
    if (state == -1 && !pinAValue && !pinBValue || state == -3 && pinAValue &&  pinBValue) {
        state -= 1;                         // Если выполняется условие, наращиваем в минус переменную state
        lastTurn = micros();
    }
    setCount(state); // Проверяем не было ли полного шага из 4 изменений сигналов (2 импульсов)
    sei();                                  // Разрешаем обработку прерываний
    
    if (pinAValue && pinBValue && state != 0) state = 0; // Если что-то пошло не так, возвращаем статус в исходное состояние
}

void B()
{
    if (micros() - lastTurn < pause) return;
    pinAValue = digitalRead(pin_A);
    pinBValue = digitalRead(pin_B);
    
    cli();
    if (state == 1 && !pinAValue && !pinBValue || state == 3 && pinAValue && pinBValue) {
        state += 1;                     // Если выполняется условие, наращиваем переменную state
        lastTurn = micros();
    }
    if (state == 0 && pinAValue && !pinBValue || state == -2 && !pinAValue && pinBValue) {
        state -= 1;                     // Если выполняется условие, наращиваем в минус переменную state
        lastTurn = micros();
    }
    setCount(state);                    // Проверяем не было ли полного шага из 4 изменений сигналов (2 импульсов)
    sei();
    
    if (pinAValue && pinBValue && state != 0) state = 0; // Если что-то пошло не так, возвращаем статус в исходное состояние
}

void setCount(int state) {              // Устанавливаем значение счетчика
    if (state == 4) {                   // Если переменная state приняла заданное значение приращения
        lastTurn = micros();            // Запоминаем последнее изменение
        if (Pow < NUMPIXELS){
            Pow++;
        }else{
            Pow=NUMPIXELS;
        }
        StripUpdate();
        Blynk.virtualWrite(V1, Pow);
    }else if (state == -4) {            // Если переменная state приняла заданное значение приращения
        lastTurn = micros();
        if (Pow > 1){
            Pow--;
        }else{
            Pow=1;
        }
        StripUpdate();
        Blynk.virtualWrite(V1, Pow); 
    }   
}

На работу устройства влияет именно ионизатор. Пробовал вместо него вешать лампочку - проблем (глюков) нет. Последовательность сборки:
Воздушный фильтр - Электроника - Кулер - Ионизатор.
Воздух проходит через фильтр, обдувает электронику, вытягивается кулером, а дальше ионизируется. Так что ионизированный воздух не попадает на электронику.
В общем, что можете посоветовать? 

forfrends
Offline
Зарегистрирован: 24.02.2015

Ионизатор вот такой: http://ali.pub/3fl3jv

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

Имхо, только экранировать всю низковольтную часть.

IVAN222
Offline
Зарегистрирован: 19.04.2017

И еще ионизатор через фильтр пустите перед симистером что бы высокая не лезла в низковольтную часть.

forfrends
Offline
Зарегистрирован: 24.02.2015

Да, похоже без экрана никуда...

IVAN222, симистор развязан оптопарой. Вроде больше ничего не нужно?