Простой резистор спасет есп от кз. И скорее всего сериал останется работоспособным, сможете нормально отлаживать.Но TX при загрузке шлет информацию в последовательный порт, от этого не уйдешь.
Последнее редактирование:
Простой резистор спасет есп от кз. И скорее всего сериал останется работоспособным, сможете нормально отлаживать.Но TX при загрузке шлет информацию в последовательный порт, от этого не уйдешь.
Вы обновите схему, чтобы можно было на нее ссылаться.Но TX при загрузке шлет информацию в последовательный порт, от этого не уйдешь. Это то же самое, что товарищ, который сделал диммер на ESP, использовал для детектора 0 пин GPIO0. И на переднюю панель этого диммера вывел кнопку перезапуска. У него спрашивают, а зачем вам кнопка перезапуска на передней панели, а он отвечает, что ESP стартует не с первого раза и приходится перезапускать несколько раз для нормального старта.
//#define CAYENNE_DEBUG
#define CAYENNE_PRINT Serial // Comment this out to disable prints and save space
#include <CayenneMQTTESP8266.h> // Include library file for MQTT
#define TRIAC_PIN 2 //GPIO2
#define ZC_PIN 1 //GPIO1 - TXD
#define BUTTON_PIN 3 //GPIO3 - RXD
void ICACHE_RAM_ATTR zero_crosss_int();
char ssid[] = "ASUS"; // Your WIFI Name
char wifiPassword[] = "gCU8YNZs"; // Your WIFI password
char username[] = "***"; // Your MQTT cayenne username
char Password[] = "****"; // Your MQTT cayenne Password
char clientID[] = "***"; // Your MQTT cayenne clientID
int DIMMING_VALUES = 0;
int DIMMING_TIME = 0;
int BUTTON = 0;
int lightStatus = 0;
volatile unsigned long countZeroCross = 0;
unsigned long lastMillis = 0;
/*
// This function sends Arduino's up time every second to Virtual Pin 5.
void sendUptime()
{
// Send values using the virtualWrite function. Cayenne currently accepts int and float values.
// Please don't send more that 10 values per second.
Cayenne.virtualWrite(V5, millis() / 1000);
}*/
//=====================Basic Setup ============================
void setup(){
// Serial.begin(115200); // Setup Debug uart port if you want ?
pinMode(TRIAC_PIN, OUTPUT); // Set AC Load pin as output
digitalWrite(TRIAC_PIN, LOW);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(ZC_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ZC_PIN), zero_crosss_int, FALLING); // Choose the zero cross interrupt egde selection
Cayenne.begin(username, Password, clientID, ssid, wifiPassword); // Setup cayenne server for MQTT protocol
}
void loop()
{
if(millis() - lastMillis > 10000){
lastMillis = millis();
}
BUTTON = digitalRead(BUTTON_PIN);
}
void ICACHE_RAM_ATTR zero_crosss_int() //function to be fired at the zero crossing to dim the light
{
DIMMING_TIME = (75 * DIMMING_VALUES); // For 60Hz =>65
delayMicroseconds(DIMMING_TIME); // Wait till firing the TRIAC
digitalWrite(TRIAC_PIN, HIGH); // Fire the TRIAC
delayMicroseconds(10); // triac On propogation delay
// (for 60Hz use 8.33) Some Triacs need a longer period
digitalWrite(TRIAC_PIN, LOW); // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC
countZeroCross += countZeroCross;
}
CAYENNE_OUT_DEFAULT()
{
Cayenne.virtualWrite(V0, millis());
Cayenne.virtualWrite(V5, BUTTON);
Cayenne.virtualWrite(V6, countZeroCross);
}
CAYENNE_IN(1)
{
int Dimm_Val=getValue.asInt();
DIMMING_VALUES = (120-Dimm_Val);
}
CAYENNE_IN(2)
{
digitalWrite(TRIAC_PIN, !getValue.asInt()); // to get the value from the website
}
//==================================================================
Я выше выкладывал алгоритм. Попробуйте запрограммировать его. Он до безобразия простой.Правда, при такой схеме подключения детектора нуля не получается прошить с подключенным pull-down резистором на 10к. И импульсы управления симистором вроде бы присутствуют, но при изменении значения диммирования, импульс открытия симистора не перемещается относительно перехода через 0.
И наблюдается мерцание лампы. Походу нужно переписать обработчик прерывания. Так как вроде бы яркость регулируется, но с уменьшение яркости усиливается мерцание (тухнут вразнобой на доли секунд)
пардон, не увидел что вход разный. Вопрос снимаю.ОК1 и ОК2 совместить не получится. При выключенном выключателе света, сигнала с ОК1 не будет. Но вентилятор должен работать. Поэтому и пришлось лепить две оптопары по входу.
/*******************************************************
Chip type : ATmega8
AVR Core Clock frequency: 8,000000 MHz
*******************************************************/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define BUT_PLUS PC1 //кнопка увеличения оборотов
#define BUT_MINUS PC0 //кнопка уменьшения оборотов
#define ZERO_CROSS PD2 //Вход импульсов ZERO-CROSS (INT0)
#define CONTROL_TRIAC PD1 //Вывод на управляющий электрод симистора
#define V_CHANGE_SPEED 10 //Шаг регулировки скорости изменения оборотов
#define T_PULSE_TRIAC 30 //Длительность отпирающего импульса симистора 20 мкс (смотреть по ТУ для конкретного симистора)
volatile unsigned char speed = 0xB8; //256-216 = 40 тиков по 0,128мс = 5,12 мс
//Обработчик прерывания от INT0 при переходе сетевого напряжения через 0
ISR (INT0_vect)
{
TCNT0 = speed;
TCCR1B = 0;
asm("cli");
//прерывание по переполнению T1 каждые 10мс (8 МГц/8 = 1 МГц, 1 тик - 1 мкс)
//Число тактов таймера до переполнения = 0x2710 (10000 тиков по 1 мкс)
TCNT1H = 0xFF - 0x27;
TCNT1L = 0xFF - 0x10;
TCCR1B |= (1 << CS11); // Коэффициент деления предделителя - 8.
asm("sei");
}
// Обработчик прерывания по переполнению Timer 0
ISR (TIMER0_OVF_vect)
{
// Импульс открытия на симистор
PORTD &= ~(1 << CONTROL_TRIAC);
_delay_us(T_PULSE_TRIAC);
PORTD |= (1 << CONTROL_TRIAC);
}
// Обработчик прерывания по переполнению Timer 1 (второй полупериод сетевого напряжения)
ISR (TIMER1_OVF_vect)
{
// инициализируем знчение счетного регистра таймера/счетчика 0
TCNT0 = speed;
PORTB = !PORTB;
}
int main(void)
{
// Инициализация портов ввода/вывода
DDRB = 0b00000001; //PB0 - на вывод (для отладки меандр)
PORTB = 0b00000000;
DDRC = 0b00000000; //PC0, PC1 - на ввод (кнопки "ПЛЮС" и "МИНУС")
PORTC = 0b00000011; //подтягивающий резистор включен на PC0 и PC1
DDRD = 0b00000011; //PD1, PD0 - на вывод (симистор)
PORTD = 0b00000000;
// Инициализация таймера/счетчика 0
TCCR0 |= (1 << CS02) | (1 << CS00); //Коэффициент деления предделителя - 1024.
//прерывание по переполнению T0 каждые 10мс (8 МГц/1024 = 7,813 кГц, 1 тик - 128 мкс)
TCNT0 = 0xB2;
// Инициализация таймера/счетчика 1
TCCR1A = 0;
TCCR1B |= (1 << CS11); // Коэффициент деления предделителя - 8.
//Число тактов таймера до переполнения = 0x2710 (10000 тиков по 1 мкс)
TCNT1H = 0xFF - 0x27;
TCNT1L = 0xFF - 0x10;
// Инициализация прерываний таймеров/счетчиков
TIMSK |= (1 << TOIE1) | (1 << TOIE0); //прерывание по переполнению таймера Т1 и таймера Т0
// Инициализация внешних прерываний
GICR |= (0 << INT1) | (1 << INT0); //включаем внешнее прерывание 0
MCUCR |= (1 << ISC01) | (1 << ISC00); //прерывание срабатывает по растущему фронту на INT0
GIFR |= (1 << INTF0); //сбрасываем флаг внешнего прерывания 0
// Глобальное разрешение прерываний
asm("sei");
while (1)
{
if (PINC & (1 << BUT_PLUS)) {
speed = speed + 1;
if (speed > 253) {
speed = 253;
};
_delay_ms(16);
}
if (PINC & (1 << BUT_MINUS)) {
speed = speed - 1;
if (speed < 180) {
speed = 180;
};
_delay_ms(16);
};
};
return 0;
}
Ну вот опять двадцать пять.Доброй ночи!
Посмотрел я на СИ-код, ранее делал диммер на ATmega8
И понял, что нужно конкретно переписывать код, который используется сейчас. Проблема в том, что на Си для AVR я знаю как писать, а для ESP могу только Arduino (wiring)
Код:/******************************************************* Chip type : ATmega8 AVR Core Clock frequency: 8,000000 MHz *******************************************************/ #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define BUT_PLUS PC1 //кнопка увеличения оборотов #define BUT_MINUS PC0 //кнопка уменьшения оборотов #define ZERO_CROSS PD2 //Вход импульсов ZERO-CROSS (INT0) #define CONTROL_TRIAC PD1 //Вывод на управляющий электрод симистора #define V_CHANGE_SPEED 10 //Шаг регулировки скорости изменения оборотов #define T_PULSE_TRIAC 30 //Длительность отпирающего импульса симистора 20 мкс (смотреть по ТУ для конкретного симистора) volatile unsigned char speed = 0xB8; //256-216 = 40 тиков по 0,128мс = 5,12 мс //Обработчик прерывания от INT0 при переходе сетевого напряжения через 0 ISR (INT0_vect) { TCNT0 = speed; TCCR1B = 0; asm("cli"); //прерывание по переполнению T1 каждые 10мс (8 МГц/8 = 1 МГц, 1 тик - 1 мкс) //Число тактов таймера до переполнения = 0x2710 (10000 тиков по 1 мкс) TCNT1H = 0xFF - 0x27; TCNT1L = 0xFF - 0x10; TCCR1B |= (1 << CS11); // Коэффициент деления предделителя - 8. asm("sei"); } // Обработчик прерывания по переполнению Timer 0 ISR (TIMER0_OVF_vect) { // Импульс открытия на симистор PORTD &= ~(1 << CONTROL_TRIAC); _delay_us(T_PULSE_TRIAC); PORTD |= (1 << CONTROL_TRIAC); } // Обработчик прерывания по переполнению Timer 1 (второй полупериод сетевого напряжения) ISR (TIMER1_OVF_vect) { // инициализируем знчение счетного регистра таймера/счетчика 0 TCNT0 = speed; PORTB = !PORTB; } int main(void) { // Инициализация портов ввода/вывода DDRB = 0b00000001; //PB0 - на вывод (для отладки меандр) PORTB = 0b00000000; DDRC = 0b00000000; //PC0, PC1 - на ввод (кнопки "ПЛЮС" и "МИНУС") PORTC = 0b00000011; //подтягивающий резистор включен на PC0 и PC1 DDRD = 0b00000011; //PD1, PD0 - на вывод (симистор) PORTD = 0b00000000; // Инициализация таймера/счетчика 0 TCCR0 |= (1 << CS02) | (1 << CS00); //Коэффициент деления предделителя - 1024. //прерывание по переполнению T0 каждые 10мс (8 МГц/1024 = 7,813 кГц, 1 тик - 128 мкс) TCNT0 = 0xB2; // Инициализация таймера/счетчика 1 TCCR1A = 0; TCCR1B |= (1 << CS11); // Коэффициент деления предделителя - 8. //Число тактов таймера до переполнения = 0x2710 (10000 тиков по 1 мкс) TCNT1H = 0xFF - 0x27; TCNT1L = 0xFF - 0x10; // Инициализация прерываний таймеров/счетчиков TIMSK |= (1 << TOIE1) | (1 << TOIE0); //прерывание по переполнению таймера Т1 и таймера Т0 // Инициализация внешних прерываний GICR |= (0 << INT1) | (1 << INT0); //включаем внешнее прерывание 0 MCUCR |= (1 << ISC01) | (1 << ISC00); //прерывание срабатывает по растущему фронту на INT0 GIFR |= (1 << INTF0); //сбрасываем флаг внешнего прерывания 0 // Глобальное разрешение прерываний asm("sei"); while (1) { if (PINC & (1 << BUT_PLUS)) { speed = speed + 1; if (speed > 253) { speed = 253; }; _delay_ms(16); } if (PINC & (1 << BUT_MINUS)) { speed = speed - 1; if (speed < 180) { speed = 180; }; _delay_ms(16); }; }; return 0; }
по мне так все гораздо проще.Добрый день!
Наконец смог добраться до диммера, так как на работе завал, и не успеваю хобби заниматься. По поводу алгоритма, как я его вижу и как я его делал на AVR
Для реализации алгоритма управления симистором используем 2 обработчика прерывания. Основное прерывание при переходе сетевого напряжения через "0" каждые 10 мс. После срабатывания данного прерывания, мы должны таймером отсчитать от начала периода время задержки включения симистора, обратно пропорциональное требуемой яркости. То есть если требуется максимальная яркость, то включаем сразу, если минимальная, то включаем симистор в конце полупериода. Импульс открытия симистора можно сделать 10-50 мкс, или оставить открытым симистор до конца полупериода. Но тут возникает подводный камень, если нагрузка индуктивная, то симистор может не выключиться, если в момент перехода сетевого напряжения через "0" , будет протекать ток через симистор.
Далее в следующем полупериоде повторяем вышеописанные действия.
В коде для AVR, выше в теме используется 3 обработчика прерываний. Так как для отслеживания перехода через "0" используется только положительная полуволна сетевого напряжения, поэтому таймер Т1 используется для отсчета 10 мс интервалов, а таймер Т0 используется для организации задержки включения симистора после перехода напряжения через "0".
Для ESP доступен один железный таймер, поэтому использовал двухполупериодное выпрямление, чтобы не отслеживать 10 мс интервалы.
Далее в основном цикле для изменения яркости обновляем текущее значение яркости - требуемым значением. Требуемое значения получаем из облака, http-страницы или последовательного порта. Это уже детали. Правда еще непонятно, если формировать импульс управления симистором в обработчике прерывания с помощью функции delay(us) насколько это правильно?
Теперь есть вопрос по "железному" таймеру ESP8266. Использовал библиотеку hw_timer.h я так понимаю из SDK ESP. Но так как я пишу в Arduino IDE, то почему-то не срабатывает прерывание от таймера. В видео с работающим примеромтоварищ крайне рекомендует использовать менеджер плат версии 2.4.1. Сделал даунгрейд последней версии менеджера плат в Arduino IDE, но даже не получается прошить ESP.
Если у кого есть простейший пример использования данной библиотеки в среде Arduino IDE? то был бы рад если бы поделились, так как все найденные готовые исходники, почему-то нормально не работают.