Re: плавный пуск + регулятор скорости коллекторного двигател
Добавлено: Ср сен 30, 2020 07:53:13
Болгарка плавно набирает обороты при запуске, когда регулятор установлен на минимум, после этого можно добавить обороты до нужной величины.
Здесь можно немножко помяукать :)
https://radiokot.ru/forum/
Там же еще МК будет? Или полностью схему нарисовать?BlackKilkennyCat писал(а):Это схема детектора перехода через ноль с бп, симистор к ней как-то рано.
С чего вы будете брать питание для этого транзистора?BlackKilkennyCat писал(а):Управляющий ток, если его действительно не хватает, обеспечивают транзистором. Зачем сразу лепить оптрон?
а она эти 125 мА где берет?С чего вы будете брать питание для этого транзистора?
U2010B выдает 125 мА, это более чем достаточно для открытия любого симистора.
нетПонадобится высоковольтный транзистор
поясните, что имеете в виду, без намеков.и ...., напомните мне чем симистор отличается от тиристора?
дорого и много места. Кроме того, надо быть последовательным - какой смысл готовое решение в одном лишь месте? Давайте и всё остальное в виде готового решения, они есть.MOC3023 - это готовое решение, с минимумом обвеса.
Велосипеды изобретают до сих пор. Ваш вариант блока питания с детектором нуля - тот же велосипед, как и 99% радиолюбительских поделок в сегодняшнее время, к чему об этом разговаривать? Кроме того, существует куча различных требований к режимам работы электроприводов, и не всегда какая-то уникально-заточенная микросхема может их обеспечить. И как заметил musor, микросхема редкая, а вариант покупать на али - да лучше выкинуть электропривод и пойти пить чай...существует специализированная микросхема фазового управления с обратной связью по току и защитой от перегрузки U2010B. Остальное "велосипед".
U2010BBlackKilkennyCat писал(а):Давайте и всё остальное в виде готового решения, они есть.
Код: Выделить всё
pwm_set[0] = ADCH; Код: Выделить всё
//===плавный старт===
if (start_first==0){
//int STOP =ADCH;
for (pwm_cur = 0xC8; pwm_cur > ADCH; pwm_cur--){
for (int k = 0; k<10000; k++){ // ПОТОМ УБРАТЬ !!!
if (!kbd_en[1]) pwm_set[1] =ADCH;
if (!kbd_en[0]) pwm_set[0] =ADCH;
}
}
start_first = 1;
}
//=================== Код: Выделить всё
/*
* main.c
*
* Created on: May 11, 2015
* Author: qwer
*/
#include "main.h"
volatile uint8_t sync_flag; // PWM top sync flag
volatile uint8_t pwm_top = 0xFF; // PWMs maximum
register uint8_t pwm_set[2] asm("r2"); // PWMS set
register uint8_t pwm_cur[2] asm("r4"); // PWMS current
register uint8_t pwm_ac asm("r6"); // AC sync flag
uint8_t limit_en[2] = {1, 1}, limit[2];
uint8_t startup_cnt = STARTUP_DELAY;
uint8_t kbd_en[2], kbd_cnt[2], kbd_prev[2], kbd_cur[2], kbd_inc[2];
uint8_t pwm_sete[2] EEMEM;
register uint8_t eep_update_cnt asm("r7");
#define pwm2_on() PORTB |= (1 << PB1)
#define pwm2_off() PORTB &= ~(1 << PB1)
int main()
{
// setup
// GPIO
PORTB |= (1 << PB3) | (1 << PB4) | (1 << PB2);
DDRB &= ~((1 << PB2) | (1 << PB3) | (1 << PB4));
PORTB &= ~((1 << PB0) | (1 << PB1));
DDRB |= (1 << PB0) | (1 << PB1);
// PCINT
GIMSK |= (1 << PCIE);
PCMSK = (1 << PCINT2);
// timer 0
TCCR0A = 0;
TCCR0B = (1 << CS01) | (1 << CS00);
TIMSK0 = (1 << TOIE0) | (1 << OCIE0B) | (1 << OCIE0A);
// ADC
ADMUX = (1 << ADLAR) | (1 << MUX1);
ADMUX |= (1 << MUX0);
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADCSRB = 0;
DIDR0 = 0;
// check buttons/Pots
for (uint8_t i = 0; i < 2; i++)
{
while (ADCSRA & (1 << ADSC))
;
kbd_en[i] = (ADCH < KBD_ADC_THRESHOLD) || (ADCH > (0xFF - KBD_ADC_THRESHOLD));
if (kbd_en[i])
limit_en[i] = 0;
//ADMUX ^= (1 << MUX0);
ADCSRA |= (1 << ADSC);
}
// restore current power from EEPROM
// pwm_set[0] = eeprom_read_byte(&pwm_sete[0]);
// pwm_set[1] = eeprom_read_byte(&pwm_sete[1]);
// pwm_set[0] = pwm_set[1] = 0xFF;
EEARL = 0;
EECR |= (1 << EERE);
pwm_set[0] = EEDR;
EEARL = 1;
EECR |= (1 << EERE);
pwm_set[1] = EEDR;
sei();
// main loop
while (1)
{
// ZC sync
if (sync_flag)
{
sync_flag = 0;
// decrement startup timer
if (startup_cnt)
{
startup_cnt--;
}
// update limiters
else
{
for (uint8_t i = 0; i < 2; i++)
{
if (limit_en[i] == 1)
{ // limit increment
if (limit[i] < (0xFF - LIMIT_INC))
limit[i] += LIMIT_INC;
else
{
limit[i] = 0xFF;
limit_en[i] = 0;
}
}
else if (limit_en[i] == 2)
{ // limit decrement
if (limit[i] > LIMIT_INC)
limit[i] -= LIMIT_INC;
else
{
limit[i] = 0;
limit_en[i] = 0;
}
}
}
}
// calculate PWMs
uint8_t pwm = (!pwm_set[1]) ? 0 : (pwm_set[1] < limit[1]) ? pwm_set[1] : limit[1];
pwm = pwm_top - (((uint16_t)pwm * pwm_top) >> 8);
pwm_cur[1] = (startup_cnt || (pwm_set[1] < PWM_MIN) || ((pwm_top - pwm) < PWM_MAX_DIF)) ? 0 : pwm;
// read ADC
if (ADMUX & (1 << MUX0))
{
if (!kbd_en[1])
pwm_set[1] = ADCH;
}
ADCSRA |= (1 << ADSC);
}
}
// exit
return 0;
}
ISR(TIM0_COMPA_vect)
{
}
ISR(TIM0_COMPB_vect)
{
if (pwm_cur[1])
{
pwm2_on();
sei();
if (pwm_ac)
{
_delay_us(PWM_AC_PULSE);
pwm2_off();
}
}
}
ISR(TIM0_OVF_vect)
{
pwm2_off(); // PWMs off
pwm_top = 0xFF; // update PWM top
OCR0B = pwm_cur[1]; // reload PWMs
sync_flag = 1;
pwm_ac = 0; // set Sync flag / reset AC flag
TIFR0 |= (1 << OCF0A) | (1 << OCF0B); // reset capture interrupts
}
// external interrupt on zero-cross
ISR(PCINT0_vect)
{
pwm2_off(); // PWMs off
pwm_top = TCNT0; // get PWM top
// uint8_t cnt = TCNT0; // get PWM top
TCNT0 = 0; // reset TCNT0
OCR0B = pwm_cur[1]; // reload PWMs
sync_flag = pwm_ac = 1; // set Sync/AC flag
// pwm_top = ((uint16_t)cnt + pwm_top) >> 1; // filter PWM top
TIFR0 |= (1 << OCF0A) | (1 << OCF0B) | (1 << TOV0); // reset capture interrupts
}
Код: Выделить всё
/*
* main.h
*
* Created on: May 11, 2015
* Author: qwer
*/
#ifndef MAIN_H_
#define MAIN_H_
#define F_CPU (9600000uL / 8)
#include "stdint.h"
#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.h"
#include "avr/eeprom.h"
#define PWM_AC_PULSE 4
#define PWM_MIN 5
#define PWM_MAX_DIF 10
#define LIMIT_INC 10
#define STARTUP_DELAY 50
#define KBD_ADC_THRESHOLD 5
#define KBD_CNT_ONOFF 5
#define KBD_CNT_ONOFF_THRESHOLD 50
#define KBD_CNT_LONG 200
#endif /* MAIN_H_ */
наверно...вообще плавный пуск есть, но коротенький, удлинить наверное можно
Код: Выделить всё
/*
* main.c
*
* Created on: May 11, 2015
* Author: qwer
*/
#include "main.h"
volatile uint8_t sync_flag; // PWM top sync flag
uint8_t sync_cnt;
volatile uint8_t pwm_top = 0xFF; // PWMs maximum
register uint8_t pwm_set[2] asm("r2"); // PWMS set
register uint8_t pwm_cur[2] asm("r4"); // PWMS current
register uint8_t pwm_ac asm("r6"); // AC sync flag
uint8_t limit_en[2] = {1, 1}, limit[2];
uint8_t startup_cnt = STARTUP_DELAY;
uint8_t kbd_en[2], kbd_cnt[2], kbd_prev[2], kbd_cur[2], kbd_inc[2];
uint8_t pwm_sete[2] EEMEM;
register uint8_t eep_update_cnt asm("r7");
#define pwm2_on() PORTB |= (1 << PB1)
#define pwm2_off() PORTB &= ~(1 << PB1)
int main()
{
// setup
// GPIO
PORTB |= (1 << PB3) | (1 << PB4) | (1 << PB2);
DDRB &= ~((1 << PB2) | (1 << PB3) | (1 << PB4));
PORTB &= ~((1 << PB0) | (1 << PB1));
DDRB |= (1 << PB0) | (1 << PB1);
// PCINT
GIMSK |= (1 << PCIE);
PCMSK = (1 << PCINT2);
// timer 0
TCCR0A = 0;
TCCR0B = (1 << CS01) | (1 << CS00);
TIMSK0 = (1 << TOIE0) | (1 << OCIE0B) | (1 << OCIE0A);
// ADC
ADMUX = (1 << ADLAR) | (1 << MUX1);
ADMUX |= (1 << MUX0);
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADCSRB = 0;
DIDR0 = 0;
// check buttons/Pots
for (uint8_t i = 0; i < 2; i++)
{
while (ADCSRA & (1 << ADSC))
;
kbd_en[i] = (ADCH < KBD_ADC_THRESHOLD) || (ADCH > (0xFF - KBD_ADC_THRESHOLD));
if (kbd_en[i])
limit_en[i] = 0;
//ADMUX ^= (1 << MUX0);
ADCSRA |= (1 << ADSC);
}
// restore current power from EEPROM
// pwm_set[0] = eeprom_read_byte(&pwm_sete[0]);
// pwm_set[1] = eeprom_read_byte(&pwm_sete[1]);
// pwm_set[0] = pwm_set[1] = 0xFF;
EEARL = 0;
EECR |= (1 << EERE);
pwm_set[0] = EEDR;
EEARL = 1;
EECR |= (1 << EERE);
pwm_set[1] = EEDR;
sync_cnt = 0;
sei();
// main loop
while (1)
{
// ZC sync
if (sync_flag)
{
sync_flag = 0;
if (++sync_cnt == 3)
{
sync_cnt = 0;
// decrement startup timer
if (startup_cnt)
{
startup_cnt--;
}
// update limiters
else
{
for (uint8_t i = 0; i < 2; i++)
{
if (limit_en[i] == 1)
{ // limit increment
if (limit[i] < (0xFF - LIMIT_INC))
limit[i] += LIMIT_INC;
else
{
limit[i] = 0xFF;
limit_en[i] = 0;
}
}
else if (limit_en[i] == 2)
{ // limit decrement
if (limit[i] > LIMIT_INC)
limit[i] -= LIMIT_INC;
else
{
limit[i] = 0;
limit_en[i] = 0;
}
}
}
}
}
// calculate PWMs
uint8_t pwm = (!pwm_set[1]) ? 0 : (pwm_set[1] < limit[1]) ? pwm_set[1] : limit[1];
pwm = pwm_top - (((uint16_t)pwm * pwm_top) >> 8);
pwm_cur[1] = (startup_cnt || (pwm_set[1] < PWM_MIN) || ((pwm_top - pwm) < PWM_MAX_DIF)) ? 0 : pwm;
// read ADC
if (ADMUX & (1 << MUX0))
{
if (!kbd_en[1])
pwm_set[1] = ADCH;
}
ADCSRA |= (1 << ADSC);
}
}
// exit
return 0;
}
ISR(TIM0_COMPA_vect)
{
}
ISR(TIM0_COMPB_vect)
{
if (pwm_cur[1])
{
pwm2_on();
sei();
if (pwm_ac)
{
_delay_us(PWM_AC_PULSE);
pwm2_off();
}
}
}
ISR(TIM0_OVF_vect)
{
pwm2_off(); // PWMs off
pwm_top = 0xFF; // update PWM top
OCR0B = pwm_cur[1]; // reload PWMs
sync_flag = 1;
pwm_ac = 0; // set Sync flag / reset AC flag
TIFR0 |= (1 << OCF0A) | (1 << OCF0B); // reset capture interrupts
}
// external interrupt on zero-cross
ISR(PCINT0_vect)
{
pwm2_off(); // PWMs off
pwm_top = TCNT0; // get PWM top
// uint8_t cnt = TCNT0; // get PWM top
TCNT0 = 0; // reset TCNT0
OCR0B = pwm_cur[1]; // reload PWMs
sync_flag = pwm_ac = 1; // set Sync/AC flag
// pwm_top = ((uint16_t)cnt + pwm_top) >> 1; // filter PWM top
TIFR0 |= (1 << OCF0A) | (1 << OCF0B) | (1 << TOV0); // reset capture interrupts
}Код: Выделить всё
#define STARTUP_DELAY 5Код: Выделить всё
#define LIMIT_INC 1Я ТАК ПОНЯЛ - ЭТО ШАГИ ПЕРЕМЕННОГО РЕЗИСТОРА ИЛИ НЕТ?#define LIMIT_INC
Код: Выделить всё
uint8_t pwm = (!pwm_set[1]) ? 0 : (pwm_set[1] < limit[1]) ? pwm_set[1] : limit[1];Код: Выделить всё
// limit increment
if (limit[i] < (0xFF - LIMIT_INC))
limit[i] += LIMIT_INC;
// limit decrement
if (limit[i] > LIMIT_INC)
limit[i] -= LIMIT_INC;Код: Выделить всё
uint8_t
pwm = (!pwm_set) ? 0 : (pwm_set < limit) ? pwm_set : limit;
pwm = pwm_top - (((uint16_t)pwm * pwm_top) >> 8);
pwm_cur = (startup_cnt || (pwm_set < PWM_MIN)||((pwm_top - pwm) < PWM_MAX_DIF)) ? 0 : pwm;Код: Выделить всё
if (a › b)
z = a;
else
z = b;Код: Выделить всё
z = (a › b) ? a: b; /* z = max(a, b) */uint8_t
pwm = (!pwm_set) ? 0 : (pwm_set < limit) ? pwm_set : limit;
pwm = pwm_top - (((uint16_t)pwm * pwm_top) >> 8 );
pwm_cur = (startup_cnt || (pwm_set < PWM_MIN)||((pwm_top - pwm) < PWM_MAX_DIF)) ? 0 : pwm;