Обсуждаем контроллеры компании Atmel.
Ответить

Re: плавный пуск + регулятор скорости коллекторного двигател

Ср сен 30, 2020 07:53:13

Болгарка плавно набирает обороты при запуске, когда регулятор установлен на минимум, после этого можно добавить обороты до нужной величины.

Re: плавный пуск + регулятор скорости коллекторного двигател

Ср сен 30, 2020 09:37:23

BlackKilkennyCat писал(а):Это схема детектора перехода через ноль с бп, симистор к ней как-то рано.
Там же еще МК будет? Или полностью схему нарисовать?
BlackKilkennyCat писал(а):Управляющий ток, если его действительно не хватает, обеспечивают транзистором. Зачем сразу лепить оптрон?
С чего вы будете брать питание для этого транзистора?
U2010B выдает 125 мА, это более чем достаточно для открытия любого симистора.
Понадобится высоковольтный транзистор и ...., напомните мне чем симистор отличается от тиристора?

MOC3023 - это готовое решение, с минимумом обвеса.

Мое мнение остается неизменным - существует специализированная микросхема фазового управления с обратной связью по току и защитой от перегрузки U2010B. Остальное "велосипед".

Но если все таки "велосипед", то сначала я бы собрал источник питания, нагрузил бы его нагрузкой 100 - 150 мА, светодиод поставил бы для визуального контроля, и раз так 50 включить-выключить, если не увидим "зарождение электрона", то все ОК.
Тут же прибором контролируем наличие 5 Вольт, осциллографом проверяем схему детектора, возможно так же применение стабилизатора AMS1117. (?)
PS на схеме не дорисовал один резистор килоом так на 300 параллельно С1.

Re: плавный пуск + регулятор скорости коллекторного двигател

Ср сен 30, 2020 10:54:24

таких микрух хватает
U2010B. лиш 1из них и не самая распространеная
у нас например в рознице не наблюдаю сейчас

Re: плавный пуск + регулятор скорости коллекторного двигател

Ср сен 30, 2020 12:40:29

Там же еще МК будет? Или полностью схему нарисовать?

Вообще-то да. Какой смысл от очередного варианта бестрансформаторного питания и чем оно отличается от ранее описанных?
С чего вы будете брать питание для этого транзистора?
U2010B выдает 125 мА, это более чем достаточно для открытия любого симистора.

а она эти 125 мА где берет?
Понадобится высоковольтный транзистор
нет
и ...., напомните мне чем симистор отличается от тиристора?
поясните, что имеете в виду, без намеков.
MOC3023 - это готовое решение, с минимумом обвеса.
дорого и много места. Кроме того, надо быть последовательным - какой смысл готовое решение в одном лишь месте? Давайте и всё остальное в виде готового решения, они есть.
существует специализированная микросхема фазового управления с обратной связью по току и защитой от перегрузки U2010B. Остальное "велосипед".
Велосипеды изобретают до сих пор. Ваш вариант блока питания с детектором нуля - тот же велосипед, как и 99% радиолюбительских поделок в сегодняшнее время, к чему об этом разговаривать? Кроме того, существует куча различных требований к режимам работы электроприводов, и не всегда какая-то уникально-заточенная микросхема может их обеспечить. И как заметил musor, микросхема редкая, а вариант покупать на али - да лучше выкинуть электропривод и пойти пить чай...

Re: плавный пуск + регулятор скорости коллекторного двигател

Ср сен 30, 2020 12:53:38

BlackKilkennyCat писал(а):Давайте и всё остальное в виде готового решения, они есть.
U2010B

Re: плавный пуск + регулятор скорости коллекторного двигател

Ср сен 30, 2020 13:08:27

ну, вот так лучше :)

Re: плавный пуск + регулятор скорости коллекторного двигател

Чт окт 01, 2020 21:50:07

Изображение

во че нашел! :)))

фьюзы: Low = 0x2A , High = 0xFB

Добавлено after 5 hours 53 minutes 43 seconds:
Re: плавный пуск + регулятор скорости коллекторного двигателя
допишите плавный пуск, кому не трудно :? у меня не получается :dont_know:

Спойлер#define F_CPU (9600000uL / 8)

#include "stdint.h"
#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.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


inline void pwm2_on() { PORTB |= (1<<PB1); }
inline void pwm2_off(){ PORTB &= ~(1<<PB1); }




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];



int main(){
// setup

// GPIO
PORTB |= (1<<PB3)|(1<<PB2);
DDRB &= ~((1<<PB2)|(1<<PB3));
PORTB &= ~(1<<PB1);
DDRB |= (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);
ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
ADCSRB = 0;
DIDR0 = 0;




pwm_set[0] = pwm_set[1] = 0xFF;


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[0]) ? 0 : (pwm_set[0] < limit[0]) ? pwm_set[0] : limit[0];
pwm = pwm_top - (((uint16_t)pwm * pwm_top) >> 8);
pwm_cur[0] = (startup_cnt || (pwm_set[0] < PWM_MIN)||((pwm_top - pwm) < PWM_MAX_DIF)) ? 0 : pwm;

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)){ ADMUX &= ~(1<<MUX0); if (!kbd_en[1]) pwm_set[1] = ADCH;
} else { ADMUX |= (1<<MUX0); if (!kbd_en[0]) pwm_set[0] = ADCH; }
ADCSRA |= (1<<ADSC);



}
}

// exit
return 0;
}



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
OCR0A = pwm_cur[0]; 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
OCR0A = pwm_cur[0]; 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
}
Вложения
t13-dim.zip
(151.48 KiB) Скачиваний: 246

Re: плавный пуск + регулятор скорости коллекторного двигател

Пт окт 02, 2020 15:42:31

Спойлер#define F_CPU (9600000uL / 8 )

#include "stdint.h"
#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.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 //ПОРОГ АЦП



inline void pwm2_on() { PORTB |= (1<<PB1); }
inline void pwm2_off(){ PORTB &= ~(1<<PB1); }




volatile uint8_t sync_flag; //Флаг верхней синхронизации ШИМ
volatile uint8_t pwm_top=0xFF; // Максимальное ШИМ
register uint8_t pwm_set[2] asm("r2"); // ШИМ-комплект
register uint8_t pwm_cur asm("r4"); // Ток ШИМ
register uint8_t pwm_ac asm("r6"); // Флаг синхронизации переменного тока

unsigned int start_first = 0; // флаг первого запуска

uint8_t limit_en[2] = {1,1},limit[2];

uint8_t startup_cnt = STARTUP_DELAY;

uint8_t kbd_en[2]; //kbd_inc[2];



int main(){
// setup

// GPIO
PORTB |= (1<<PB3)|(1<<PB2);
DDRB &= ~((1<<PB2)|(1<<PB3));
PORTB &= ~(1<<PB1);
DDRB |= (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);
ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
ADCSRB = 0;
DIDR0 = 0;

sei();

// main loop
while(1){




// ZC sync
if (sync_flag){
sync_flag = 0;

//===плавный старт======================
if (start_first==0){
for (pwm_cur = 0; pwm_cur < 0xFF; 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;
}
//========


// таймер запуска уменьшение
if (startup_cnt) startup_cnt--;

// ограничители обновления
else for (uint8_t i=0; i<2; i++){
if (limit_en[i] == 1){ // предельное увеличение
if (limit[i] < (0xFF - LIMIT_INC)) limit[i] += LIMIT_INC;
else {
limit[i] = 0xFF;
limit_en[i] = 0;
}
} else if (limit_en[i] == 2){ //предельное уменьшение
if (limit[i] > LIMIT_INC) limit[i] -= LIMIT_INC;
else {
limit[i] = 0;
limit_en[i] = 0;
}
}
}

// расчет ШИМ
uint8_t pwm = (!pwm_set[0]) ? 0 : (pwm_set[0] < limit[0]) ? pwm_set[0] : limit[0];
pwm = pwm_top - (((uint16_t)pwm * pwm_top) >> 8 ) ;


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 = (startup_cnt || (pwm_set[1] < PWM_MIN)||((pwm_top - pwm) < PWM_MAX_DIF)) ? 0 : pwm;

// read ADC
if (ADMUX & (1<<MUX0)){ ADMUX &= ~(1<<MUX0); if (!kbd_en[1]) pwm_set[1] = ADCH;
} else { ADMUX |= (1<<MUX0); if (!kbd_en[0]) pwm_set[0] = ADCH; }
ADCSRA |= (1<<ADSC);
}
}

// exit
return 0;
}



ISR(TIM0_COMPB_vect){ //внешнее прирывание
if (pwm_cur){
pwm2_on();
sei();
if (pwm_ac){
_delay_us(PWM_AC_PULSE); //ШИМ-ИМПУЛЬС ПЕРЕМЕННОГО ТОКА
pwm2_off();
}
}
}

ISR(TIM0_OVF_vect){
pwm2_off(); // PWMs off
pwm_top = 0xFF; // обновление PWM сверху
OCR0B = pwm_cur; // перезарядка ШИМ
sync_flag = 1; pwm_ac = 0; // установить флаг синхронизации / сбросить флаг переменного тока
TIFR0 |= (1<<OCF0A)|(1<<OCF0B); // сброс прерываний захвата
}

// внешнее прерывание на нулевом пересечении
ISR(PCINT0_vect){
pwm2_off(); // PWMs off
pwm_top = TCNT0; // получить ШИМ сверху
// uint8_t cnt = TCNT0; //получить ШИМ сверху
TCNT0 = 0; // сброс TCNT0
OCR0B = pwm_cur; // перезарядка ШИМ
sync_flag = pwm_ac = 1; // установить флаг синхронизации/переменного тока
// pwm_top = ((uint16_t)cnt + pwm_top) >> 1; // фильтр ШИМ сверху
TIFR0 |= (1<<OCF0A)|(1<<OCF0B)|(1<<TOV0); // сброс прерываний захвата
}






ткните в код, пожалуйста, где эта "переменная" напряжения на центральном контакте переменного резистора.
чтобы при подачи питания скорость двигателя плавно возросла до этой "переменной"

for (pwm_cur = 0; pwm_cur < "переменная"на центральном контакте переменного резистора; pwm_cur++)

Re: плавный пуск + регулятор скорости коллекторного двигател

Пт окт 02, 2020 16:08:02

тэг 'Code' есть для исходников - покрасивше будет
переменная вроде эта с ацп считывается
Код:
 pwm_set[0] = ADCH;

Re: плавный пуск + регулятор скорости коллекторного двигател

Пт окт 02, 2020 23:39:11

Код:
            //===плавный старт===
               
                   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;
                     }
            //===================   



НИ ФИГА НЕ ПОЛУЧАЕТСЯ :dont_know:

начинается с 0xC8 правильно, и не останавливаясь на середине примерно 0х7F увеличивает обороты до 0хFF и только потом становиться в нужное положение :?




порект взят с https://www.radiokot.ru/forum/viewtopic.php?p=2353553 автор ncp1400
Вложения
13_dimmer.zip
(75.06 KiB) Скачиваний: 212

Re: плавный пуск + регулятор скорости коллекторного двигател

Сб окт 03, 2020 11:17:02

вообще плавный пуск есть, но коротенький, удлинить наверное можно
Изображение
повыкидывал "лишнее":
main.c
Спойлер
Код:
/*
 * 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
Спойлер
Код:
/*
 * 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_ */

Re: плавный пуск + регулятор скорости коллекторного двигател

Сб окт 03, 2020 12:03:01

вообще плавный пуск есть, но коротенький, удлинить наверное можно


наверно... :dont_know: я только второй день ломаю голову... еще вся жизнь впереди :wink:

Re: плавный пуск + регулятор скорости коллекторного двигател

Сб окт 03, 2020 12:46:19

легким движением руки удлиняем в три раза (больше тоже легко - увеличиваем магическую цифру '3' ):
Изображение
Спойлер
Код:
/*
 * 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
}

в main.h поменял
Код:
#define STARTUP_DELAY           5

правда и ацп медленнее вычитывается...

Re: плавный пуск + регулятор скорости коллекторного двигател

Сб окт 03, 2020 13:33:43

интересный ход с тыла :beer: , но это не то...
надо завести "вредную-переменную" и крутить ее ставя в нее цифры больше-меньше
а она бы увеличивала время разгона двигателя или уменьшала :idea: :roll:

Re: плавный пуск + регулятор скорости коллекторного двигател

Сб окт 03, 2020 14:00:36

так там еще можно крутить типа
Код:
#define LIMIT_INC               1

Re: плавный пуск + регулятор скорости коллекторного двигател

Сб окт 03, 2020 14:51:42

#define LIMIT_INC


Я ТАК ПОНЯЛ - ЭТО ШАГИ ПЕРЕМЕННОГО РЕЗИСТОРА ИЛИ НЕТ?

Re: плавный пуск + регулятор скорости коллекторного двигател

Сб окт 03, 2020 15:40:33

не, онj участвует в значении переменной pwm, от которой зависит pwm_cur[1], которое записывают в OCR0B = pwm_cur[1]; // reload PWMs
Код:
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;

Re: плавный пуск + регулятор скорости коллекторного двигател

Пн окт 05, 2020 11:52:33

Спойлер#define F_CPU (9600000uL / 8 )

#include "stdint.h"
#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.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


inline void pwm2_on() { PORTB |= (1<<PB1); }
inline void pwm2_off(){ PORTB &= ~(1<<PB1); }

unsigned int start_first = 0;
unsigned int STOP;


volatile uint8_t sync_flag; // PWM top sync flag

volatile uint8_t pwm_top=0xFF; // PWMs maximum
register uint8_t pwm_set asm("r2"); // PWMS set
register uint8_t pwm_cur asm("r4"); // PWMS current
register uint8_t pwm_ac asm("r6"); // AC sync flag

uint8_t limit_en = 1, limit;

uint8_t startup_cnt = STARTUP_DELAY;




int main(){
// setup

// GPIO
PORTB |= (1<<PB3)|(1<<PB2);
DDRB &= ~((1<<PB2)|(1<<PB3));
PORTB &= ~(1<<PB1);
DDRB |= (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)|(1<<MUX0);
ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
ADCSRB = 0;
DIDR0 = 0;

sei();

// main loop
while(1){
//===плавный старт===

if (start_first==0){
// read ADC
while(ADCSRA & (1<<ADSC));
pwm_set = ADCH;
ADCSRA |= (1<<ADSC);
STOP =ADCH;
for (pwm_cur = 0xFF; pwm_cur > STOP; pwm_cur--){

for (int k = 0; k<10000; k++){ // ПОТОМ УБРАТЬ !!!

pwm_set =ADC;

}
}
start_first = 1;
}
//===================

// ZC sync
if (sync_flag){
sync_flag = 0;

// decrement startup timer
if (startup_cnt) startup_cnt--;


// update limiters
else

if (limit_en == 1){ // limit increment
if (limit < (0xFF - LIMIT_INC)) limit += LIMIT_INC;
else {
limit = 0xFF;
limit_en= 0;
}
}
else if (limit_en== 2){ // limit decrement
if (limit> LIMIT_INC) limit-= LIMIT_INC;
else {
limit= 0;
limit_en= 0;
}
}


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;

// read ADC
while(ADCSRA & (1<<ADSC));
pwm_set = ADCH;
ADCSRA |= (1<<ADSC);

}
}

// exit
return 0;
}


ISR(TIM0_COMPB_vect){
if (pwm_cur){
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; // 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; // 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
}


ни фига не получается плавный пуск :cry:

Код:
         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;


а что тут написано? кто нибуть может прочитать и пояснить?

Re: плавный пуск + регулятор скорости коллекторного двигател

Пн окт 05, 2020 12:07:25

основоположников почитать - понятнее будет
2.11 Условные выражения

Инструкции
Код:
if (a › b)

 z = a;

else

 z = b;


пересылают в z большее из двух значений a и b. Условное выражение, написанное с помощью тернарного (т. е. имеющего три операнда) оператора "?: ", представляет собой другой способ записи этой и подобных ей конструкций. В выражении

выр1 ? выр2 : выр3

первым вычисляется выражение выр1. Если его значение не нуль (истина), то вычисляется выражение выр2, и значение этого выражения становится значением всего условного выражения. В противном случае вычисляется выражение выр3 и его значение становится значением условного выражения. Следует отметить, что из выражений выр2 и выр3 вычисляется только одно из них. Таким образом, чтобы установить в z большее из a и b, можно написать

Код:
z = (a › b) ? a: b; /* z = max(a, b) */

https://www.rulit.me/books/yazyk-progra ... section_34

Re: плавный пуск + регулятор скорости коллекторного двигател

Пн окт 05, 2020 13:10:17

? : что это значит я понимаю...
я про другое спрашивал, что мы здесь считаем в этом именно коде
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;
Ответить