Вывод - симистор хорошая штука для управления мощной нагрузкой.
Согласен. Но есть небольшие нюансы. Схема сложнее из за отслеживания нуля. скетч сложнее по тойже причине. А на мосфете используем встроенный ШИМ.
И самое важное. На постоенке двигатель мощнее. А это хороший +.
Глубоко над этими вопросами пока не задумывался. Просто меня удивила простота и миниатюрность схемы регулятора размещенного в кнопке и регулирующая мощность 710 ватт. Там симистор, SMD кондерчик, SMD резистор, микроскопический динистор и переменник в виде двух полосок. А в кнопке которую я купил на замену и изломал, схема еще проще.
Я со своим двигателем пока тоже затормазил. Схема схожая. Проблемы в том, что нужны стабильные низкие обороты. При датчике, который даёт 8 импульсов за оборот, достичть стабильности на низких оборотах сложно, нашёл опрический датчик с перфорацией на 36 отверстий по окружности. С 65 герцами париться не стоит, будет работать и на 50 я проверял.
Не претендую на истину, но мне кажется что для управления двигателем лучше просто электронный блок с обратной связью от двигателя и быстрой реакцией. Должно быть как можно проще, а следовательно и надежно. Думаю, что ардуину здесь прикручивать не стоит....ну разве что для украшения.....ну там..режимы...обороты ....ток....цветные лампочки....
у меня такой код без делая. поковыряйся может поможет:
Спасибо. "ковырялся" и так, и с переводчиком....
Вобщем мозгов у меня не хватило. Даже не до конца понял что куда подключать. Буду признатеен если пояснишь на "великом и могучем".
Но методом проб и ошибок написл своё.
потенциометр на А0, Холл на пин 8 , Зерро на пин 2, управление симистором на пин 3. Дисплей - 4,5,6,7,9,10
Дал 0,5 процента погрешности в каждую сторону от требуемых оборотов. С 1000 об /мин держит вполне сносно. Дальше - лучше. Понимаю, что очень коряво, но довольный как удав.
Пока без всяких "плюшек". на экран вывел время задержки от нуля, нужные обороты от потенциометра, паследние показания оборотов датчика и средние обороты. Хотя средние не очень нравятся. На мой взгляд ошибочны.
Снова приветствую всех участников темы, и всех с наступающими праздниками.
Появилось свободное врямя, и я снова вернулся к регулятору. Но что то у меня, впрочем как всегда, не идёт.
Решил подойти к вопросу с другой стороны. Алгоритм такой: Есть нужные нам обороты, например 1000об\мин. даём "зазор" например 5% в одну и в другую сторону. поручается от 950 до 1050 об\мин. Этот промежуток приравниваем к управлению симистором. 950 и ниже - полностью открыт, 1050 и выше - закрыт. Всё что в середине это промежуточные значения. При таком алгоритме обороты должны стабилизироваться в этом диапазоне в зависимости от нагрузки.
Реализация , на мой взгляд, должна быть такая:
float ko = pR/rOb; //делим нужные нам обороты на реальные это коэфициент. если обороты равны, получаем 1, если реальные больше, то от 0 до 1. если меньше то от 1 и выше. Нас интересует число с 4 цифры после запятой.
long ai = ko * 10000; //приводим коэфициент к целому положительному числу.
int g =map(ai, 10500, 9500, 7, 130); //задаём значение симистора от7-открыт до 130-закрыт исходя из полученного числа.
Кажется, всё просто. но почему то не работает. Тоесть работает, но только без промежуточных значений. ВКЛ или ВЫКЛ. Ошибка в самой первой строке. выводил значения на экран, либо 1, либо 0. После запятой 00 и всё.
Скорее всего pR и rOb являются целочисленными. В такой ситуации компилятор будет отдавать тоже целочисленные. Для перехода на дроби там нужно каккой-то толи префикс, то ли в конце что-то добавить. Еще не настолько хорошо знаю С.
Здесь все зависит от дискретности датчика. Если у вас один такт на оборот (один датчик в месте по кругу вращения), то обратная связь может сильно запаздывать. Для более плавной регулировки на низких оборотах придется увеличить число датчиков для увеличения числа отсчетов. Бесконечно понижать число оборотов все равно не получится и думаю примерно на 400-500 оборотах в минуту наступит предел для понижения уже из-за импульсов ускорения и понижения мощности.
Есть шпиндель 300w 48В, ШИМ регулятор как на фото и инфракрасный датчик.
Разница наверное только в управлении скоростью по шим от 0 до 255.
Пока тестировал все процессы отдельно, все работает. Правда шпиндель через этот регулятор сильно свистит на неполных оборотах.
P.s.: проблему свиста решил увеличением штатной частоты ШИМ ардуины
Здравствуйте Александр, мне лень заходить на ютуб, поэтому напишу сюда.
Как-то приходилось ремонтировать центрифугу на старой работе, когда работал медтехником, там был тоже коллекторник на 220В, и рулил им мосфет, в целом аппарат был неплох, и работал долго, а попал он к нам, в мастерскую потому, что на датчике Холла окислом убился контакт... Я это к чему, почему бы Вам не смотреть в сторону высоковольтного полевика и ШИМ? Это же занимает куда меньше ресурсов чем постоянно ждать переход через ноль и ещё добавлять задержку после него?
К стати, мой проект от части пересекается, на данный момент, с Вашим, но у меня не индуктивная нагрузка, пока что, но в планах есть замахнуться и на неё, просто пока что нету RC снабера, а от индуктивной нагрузки, в моём случае, симистор хаотично открывается когда надо и не надо.
Я это к чему, почему бы Вам не смотреть в сторону высоковольтного полевика и ШИМ?
Если почитаете тему с первой страницы, то именно так я и начинал. Но мои полевики, почему то вылетали один за одним. Может нужен был более мощный, а может нужно было делать драйвер на управление. Незнаю. ответ я так и не нашел. Именно поэтому и перешел на симистор.
В общем, проблема в самом алгоритме стабилизации. Сейчас пробую разные варианты. Удалось снизить порог до 500об.мин.
И к стати, у меня есть в мыслях возложить на отдельный контроллер фазовое управление, я ему буду только по юарт или АЦП подкидывать нужное значение 0-100%, а основной микроконтроллер будет делать всю остальную работу.
Схема примерно эта и была, только без опторазвязки.
HWman пишет:
И к стати, у меня есть в мыслях возложить на отдельный контроллер фазовое управление, я ему буду только по юарт или АЦП подкидывать нужное значение 0-100%, а основной микроконтроллер будет делать всю остальную работу.
Думаю, это лишнее. И одна ардуинка справляется.
Просто управлять симистором мы можем 100 раз в секунду, а импульсов от датчика получаем на 200об\мин получаем всего 40
Схема примерно эта и была, только без опторазвязки.
Опторазвязка нужна, а вдруг что-то пойдёт не так и на затвор полевика пойдёт сетевое напряжение?
Если у Вас была похожая схемотехника странно что полевики вылетали, у центрифуги была похожая схемотехника, там на валу ещё был барабан для пробирок, за счёт этого двигатель останавливался около 20 секунд, и ничего, всё работало. Частоту ШИМ не изменяли? По умолчанию она довольно таки большая, оптотрон может не успевать на ней.
Если у Вас была похожая схемотехника странно что полевики вылетали, у центрифуги была похожая схемотехника, там на валу ещё был барабан для пробирок, за счёт этого двигатель останавливался около 20 секунд, и ничего, всё работало. Частоту ШИМ не изменяли? По умолчанию она довольно таки большая, оптотрон может не успевать на ней.
Частоту уменьшал. Вылетали при малейшей нагрузке на вал. Либо если разгон не плавный. Может слабый мосфет стоял? 10А
Берёт меня большое сомнение, что от пяти вольт, напрямую, можно управлять сколь нибудь заметной мощностью. Не припомню схем (блоков питания, например), где напряжение управления менее 12 В + драйвер по затвору. Не зря это, не зря.
Берёт меня большое сомнение, что от пяти вольт, напрямую, можно управлять сколь нибудь заметной мощностью. Не припомню схем (блоков питания, например), где напряжение управления менее 12 В + драйвер по затвору. Не зря это, не зря.
Полностью с Вами солидарен, драйвер для полевика, особенно высоковольтного нужен 100% при варинте с ШИМ.
Мне кажется что надо юзать IRFP450 + IR2110 для таких целей как у Александра.
Эта схема практически ничем не отличается от той что вы привели несколькими постами выше. Добавлен только драйвер полевика и запитывается низковольтная часть от стабилитрона вместо батарейки. У меня по такой же схеме собрано, там обратной связью и не пахнет, на низких оборотах момента нету.
Эта схема практически ничем не отличается от той что вы привели несколькими постами выше. Добавлен только драйвер полевика и запитывается низковольтная часть от стабилитрона вместо батарейки. У меня по такой же схеме собрано, там обратной связью и не пахнет, на низких оборотах момента нету.
ОС можно прикрутить от таходатчика, а регулировку можно сделать плавнее, увеличив разрядность ШИМ, благо ардуина позволяет до целых 10 бит поднять, а это уже, внимание, 0..1023.
При малых ШИМ никакое повышение его разрядности не добавить момента в мотор. Потому как ШИМ на моторе "интегрируется" и малые значения = малое напряжение на моторе => малый момент мотора. Нужна положительная обратная связь по току и аппаратная, а не "Ардуино".
При малых ШИМ никакое повышение его разрядности не добавить момента в мотор. Потому как ШИМ на моторе "интегрируется" и малые значения = малое напряжение на моторе => малый момент мотора.
Проблема не в " добавить момента" проблема в точности управления моментом при малых оборотах. И именно разрядность ШИМ тут ключевое. Другой вопрос, что значением ШИМ надо управлять грамотно, т.к. при одном и том же значении ШИМ возможно как медленое движение так и останов. Все потому, что момент трения покоя выше чем момент трения медленого движения. И тахометр, или аналогичное, как раз наилучшее решение проблемы.
Arhat109-2 пишет:
Нужна положительная обратная связь по току и аппаратная, а не "Ардуино".
Это вобще нечто трансцендентное. Аппаратную ПОС(!!!) по току должны паять девственицы из бескислородной меди соблюдая направленость проводов.
ПС. Ликбез для использующих слово "момент". В установившемся режиме, т.е. при постоянном числе оборотов (в т.ч и равном 0) момент вращения равен моменту нагрузки. Это 3-ё закон Нютона для вращательного движения. Повышение момента вращения при постоянной нагрузке приводит к повышению числа оборотов и обратно. Момент нагрузки - штука тонкая, зависит от характера нагрузки. Для тележек момента трения покоя при 0 выше чем при малой скорости. Исходя из вышесказаного фразы типа "на низких оборотах момента нету" некоректны.
Задачу стабилизации числа оборотов при неизвестной и переменной нагрузке можно решить только через ОС от числа оборотов (тахометра и т.п.) Стабилизация по току возможна только в узком диапазоне и исключая малые скорости, т.к. ток неоднозначно зависит от частоты.
Господа, о чем Вы?! Что за диспут аналоговый или цифровой на ардуине? При правильной реализации и одинаковой матмодели существенных различий нет. Про тахометр, так выше уже писано, нужен.
Решил поиграться с коллекторным двигателем, замутил на STM32F103 ШИМ в 20 кГц, слепил такую схемку, по классике жанра - из того что было под рукой, а полевиков логического уровня не было, тем более драйвера для обычных мосфетов, я же не буржуй, поэтому взял, старый добрый TIP122, выпаяный непомню откуда, непомню когда. Транзюк в целом неплох, фронты на входе конечно поровнее чем на выходе, но в целом справляется со своей задачей, тем более ток у меня небольшой, 0.1-0.2А, так как я замутил плавный пуск двигателя, типа этого, только транзюк не КТ827 а TIPок.
Тыкнул осциллом, и тут я кажется понял почему у Александра вылетали высоковольтные полевики - при напряжении питания в 36 В выбросы противоЭДС от движка, и диод HER302 уже не помогает, ничего удивительного, частота то большая.
Как можно увидеть на скрине осцилла, выбросы противоЭДС составляют почти в 2 раза больше напряжение, чем питалово, поэтому надо брать детали, с троекратным запасом.
З.Ы. Пробовал ещё ставить в разрыв по плюсу дроссель на 50 мкГ, испульсы противоЭДС пропадают, добавить кондюк, диод и будет DC-DCшка почти готовая.
Я бы для начала подкинул резистор порядка дестка ом последовотально диоду (он похоже действительно не работает) для снижения добротности контура, дающего колебания. Он кстати судя по частоте на индуктивности потока рассеянья.
sany_sch я Вам очень рекомендовал бы отказаться от симмисторного управления в пользу ШИМ, регулировка симмистором это всего лишь диапазон от 7 до 130, а ШИМ можно 0..1023, к тому же освободиться больше ресурсов микроконтроллера, потому как ШИМ аппаратный, минимум математики.
Главное разобраться почему у Вас вылетали транзисторы.
Здравствуйте. Заинтересовала данная тема по симисторному управлению. Вот только проблемма, у мен ардуино мега 2560 а прошивка заточена под мини, не могли бы вы помочь переделать ее под мегу. Вот код.Заранее спасибо)
Ладно попробую начать сам .Я так понимаю что основная проблемма это отсутствие у меги вывода модуля захата ICP1, остальные пины вроде как соответствуют пинам ардуины мини. Как можно реализовать эту функцию в меге??? Хочу сказать сразу что в програмировании я не сильно силен, но стремление огромное)
Вывод - симистор хорошая штука для управления мощной нагрузкой.
Согласен. Но есть небольшие нюансы. Схема сложнее из за отслеживания нуля. скетч сложнее по тойже причине. А на мосфете используем встроенный ШИМ.
И самое важное. На постоенке двигатель мощнее. А это хороший +.
По этой статье http://cxem.net/arduino/arduino71.php собрал диммер. схему слегка изменил:
Я со своим двигателем пока тоже затормазил. Схема схожая. Проблемы в том, что нужны стабильные низкие обороты. При датчике, который даёт 8 импульсов за оборот, достичть стабильности на низких оборотах сложно, нашёл опрический датчик с перфорацией на 36 отверстий по окружности. С 65 герцами париться не стоит, будет работать и на 50 я проверял.
Не претендую на истину, но мне кажется что для управления двигателем лучше просто электронный блок с обратной связью от двигателя и быстрой реакцией. Должно быть как можно проще, а следовательно и надежно. Думаю, что ардуину здесь прикручивать не стоит....ну разве что для украшения.....ну там..режимы...обороты ....ток....цветные лампочки....
Как реализовать управление симистором без функции "Делей"?
Грузит всё особенно на малых оборотах.
01
{
02
// Firing angle calculation : 1 full 50Hz wave =1/50=20ms
03
// Every zerocrossing thus: (50Hz)-> 10ms (1/2 Cycle) For 60Hz => 8.33ms
04
// 10ms=10000us
05
// (10000us - 10us) / 128 = 75 (Approx) For 60Hz =>65
06
int
dimtime = (75*dimming);
// For 60Hz =>65
07
delayMicroseconds(dimtime);
// Off cycle
08
digitalWrite(AC_LOAD, HIGH);
// triac firing
09
delayMicroseconds(10);
// triac On propogation delay (for 60Hz use 8.33)
10
digitalWrite(AC_LOAD, LOW);
// triac Off
11
}
Как реализовать управление симистором без функции "Делей"?
у меня такой код без делая. поковыряйся может поможет:
001
// TRIAC
002
#define triac_control 12 // Triac control - pin
003
#define open_loop 13 // open loop control (no PID)
004
//RPM control
005
#define sensorPin A1 // potentiometer or MACH3 - pin
006
007
//Power
008
#define powerOn 4 // manual motor switch - pin
009
010
//Zero Detect
011
#define zero_detect 2 //Zero detect - pin
012
// when using values in the main routine and IRQ routine must be volatile value
013
volatile
byte
zero_byte = LOW;
// declare IRQ flag
014
// HIGH = 1, LOW = 0
015
016
// HALL SENSOR
017
#define hallsensor 3 // hall or optical sensor pin
018
#define hallsensor2 A4 // to check signal on hall or optical sensor pin
019
unsigned
int
rpmcount;
020
unsigned
int
rpm;
021
unsigned
long
timeold;
022
unsigned
long
time1;
023
024
//LCD
025
//LiquidCrystal::LiquidCrystal(rs, enable, d0, d1, d2, d3)
026
#include <Wire.h>
027
#include <LiquidCrystal.h>
028
LiquidCrystal lcd(5, 6, 7, 8, 9, 10);
029
030
//INTERRUPT
031
#include <avr/io.h>
032
#include <avr/interrupt.h>
033
#define PULSE 24 // pulse length on triac control pin
034
//in timer cycles (1/64 prescalar=> 4us per cycle=>96us)
035
// PID
036
#include <PID_v1.h>
037
038
//Define Variables we'll be connecting to
039
double
Setpoint, Input, Output;
040
041
//Define the aggressive and conservative Tuning Parameters
042
//double consKp=4, consKi=0.2, consKd=1;
043
//double consKp=0.4, consKi=0.001, consKd=1;
044
//double consKp=4, consKi=0.2, consKd=1;
045
//double consKp=1, consKi=0.4, consKd=0.01; //100% work
046
//double consKp=0.4, consKi=0.001, consKd=1;
047
double
consKp=1, consKi=0.4, consKd=0.01;
048
049
//Specify the links and initial tuning parameters
050
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
051
int
sensorValue=0;
052
unsigned
int
analogValue=0;
053
unsigned
int
delayValue=8000;
054
unsigned
int
rpmmin = 6000;
// Minimum and max rpm for the motor
055
unsigned
int
rpmmax = 35000;
056
unsigned
int
analogmin = 1;
// analogmin and analogmax are the range of delay
057
unsigned
int
analogmax = 1023;
// time and fot each motor must be determined empirically
058
059
void
setup
() {
060
061
//Triac control setup
062
pinMode(triac_control, OUTPUT);
063
digitalWrite(triac_control, 0);
// triac and LED off
064
pinMode(open_loop, INPUT);
065
digitalWrite(open_loop, 1);
066
//Power switch
067
pinMode(powerOn, INPUT);
068
digitalWrite(powerOn, 1);
// pull up on
069
//Zero detect
070
pinMode(zero_detect, INPUT);
071
digitalWrite(zero_detect, 1);
// pull up on
072
attachInterrupt(0, zero_fun, FALLING);
// interrupt 0 digital pin 2 connected ZC circuit
073
// Hall sensor
074
pinMode(hallsensor2, INPUT);
075
pinMode(hallsensor, INPUT);
076
digitalWrite(hallsensor, 1);
// pull up on
077
attachInterrupt(1, rpm_fun, FALLING);
// interrupt 1 digital pin 3 connected hall sensor
078
rpmcount = 0;
079
rpm = 0;
080
timeold = 0;
081
// LCD detect
082
lcd.begin(16,2);
// initialize the lcd
083
lcd.home ();
// go home
084
lcd.print(
" Hello "
);
085
lcd.setCursor ( 0, 1 );
// go to the next line
086
lcd.print (
" GOOD LUCK "
);
087
delay(1000);
088
lcd.clear();
089
090
// set up TIMER1
091
OCR1A = 100;
//initialize the comparator
092
TIMSK1 = 0x03;
//enable comparator A and overflow interrupts
093
TCCR1A = 0x00;
//timer control registers set for
094
TCCR1B = 0x00;
//normal operation, timer disabled
095
// Serial.begin(9600);
096
//PID
097
Input = rpm;
098
Setpoint = analogValue;
099
//turn the PID on
100
myPID.SetMode(AUTOMATIC);
101
myPID.SetOutputLimits(analogmin,analogmax);
//usage of this parameters instead of
102
// rpmmin and rpmmax lets use only one mapping
103
// in PID
104
}
105
void
loop
()
106
{
107
//motor switch and indicator = ON/OFF
108
if
(!digitalRead(powerOn))
// manual or by PC
109
{
110
// digitalWrite(powerIndicator, 1);
111
zero_byte=HIGH;
112
113
///////////////RPM counter ///////////////////
114
//////////////////////////////////////////////////////////////
115
if
((millis()-timeold) >= 250)
116
{
117
//Update RPM every 250 millis, increase this for better RPM resolution,
118
//decrease for faster update
119
//rpm = 60*1000/(millis() - timeold)*rpmcount;
120
unsigned
long
time = millis() - timeold;
121
float
time_in_sec = (
float
)time / 1000;
122
float
impuls_time = (
float
)rpmcount / time_in_sec;
123
rpm = (
int
)impuls_time*60;
124
rpmcount = 0;
//reset
125
timeold = millis();
//reset time
126
127
}
128
//#######################PID ###############################
129
//##########################################################
130
analogValue = analogRead(sensorPin);
131
int
analogLevel = map(analogValue,23,833, analogmin,analogmax);
132
//here we convert the voltage on pot to delay value
133
// 23-833 is the range of voltages that I got from my pot (in 0-1023 scale)
134
analogValue = analogLevel;
135
136
if
(digitalRead(open_loop)==1)
137
{ Input = map(rpm, rpmmin,rpmmax,analogmin,analogmax);
138
// Here we put correspondance between rpm and delay values)
139
Setpoint = analogValue;
140
myPID.Compute();
141
analogValue = Output;
142
}
143
analogValue = analogmax-analogValue+analogmin;
144
// this inverts the delay values- higher rpm corrsponds to shorter delay times.
145
if
(analogValue > analogmax)
146
{analogValue = analogmax;}
147
if
(analogValue < analogmin)
148
{analogValue = analogmin;}
149
delayValue=analogValue;
// we need this as during a cycle of PID
150
//calculations analogvalue changes several times
151
//??????????????????TRIAC delay control ???????????????????
152
153
OCR1A = delayValue/4;
154
155
//**************indicator ************************
156
157
if
(rpm < 10)
158
{
159
lcd.setCursor ( 0, 0 );
160
lcd.print(
" "
);
161
lcd.print (rpm);}
162
if
(10<= rpm && rpm < 100)
163
{
164
lcd.setCursor ( 0, 0 );
165
lcd.print(
" "
);
166
lcd.print (rpm);}
167
if
(100<= rpm &&rpm < 1000)
168
{
169
lcd.setCursor ( 0, 0 );
170
lcd.print(
" "
);
171
lcd.print (rpm); }
172
if
(1000<= rpm && rpm < 10000)
173
{
174
lcd.setCursor ( 0, 0 );
175
lcd.print(
" "
);
176
lcd.print (rpm);
177
}
178
if
(10000<= rpm)
179
{
180
lcd.setCursor ( 0, 0 );
181
lcd.print (rpm);}
182
lcd.setCursor ( 7, 0 );
183
lcd.print (
"RPM"
);
184
//////// output power indicator ///////////////////////////////
185
// max power 13 bars min power bars
186
lcd.setCursor ( 0, 1 );
187
lcd.print(
" "
);
188
lcd.setCursor ( 0, 1 );
189
int
Level = map(delayValue,analogmin,analogmax, 13, 0);
190
// if the array element's index is less than ledLevel,
191
// turn the pin for this element on:
192
for
(
int
bar = 0; bar < 13; bar++) {
193
if
(bar < Level) {lcd.print(0);}
194
}
195
}
196
else
197
// when motor is OFF, the display allows to check the input of Hall sensor
198
//(or optical level)
199
{
200
// digitalWrite(powerIndicator, 0);
201
zero_byte=LOW;
202
if
(millis()-time1 >=10)
203
{ sensorValue = analogRead(hallsensor2);
204
//lcd.setCursor ( 0, 1 );
205
//lcd.print(" ");
206
lcd.clear();
207
lcd.setCursor ( 0, 1 );
208
int
sensLevel = map(sensorValue,20,1000, 0, 13);
209
// values 20,1000 is the output voltage range of sensor in 0-1023 scale (0-5V),
210
// change them according to your sensor's output
211
for
(
int
sbar = 0; sbar < 13; sbar++) {
212
if
(sbar < sensLevel) { lcd.print(0);}
213
}
214
time1=millis();
215
}
216
}
217
}
// end of loop
218
//Interrupt Service Routines
219
220
ISR(TIMER1_COMPA_vect)
//comparator match
221
{ digitalWrite(triac_control, 1);
//triac on;
222
TCNT1 = 65536-PULSE;
//trigger pulse width = PULSE
223
}
224
ISR(TIMER1_OVF_vect)
//timer1 overflow
225
{
226
digitalWrite(triac_control, 0);
//turn off triac gate
227
TCCR1B = 0x00;
//disable timer stop unintended triggers
228
}
229
230
void
zero_fun()
//zero detect
231
{
if
(zero_byte)
232
{ TCCR1B=0x03;
//start timer with divide by 64 input
233
TCNT1 = 0;
//reset timer - count from zero
234
}
235
}
236
237
void
rpm_fun()
238
{
239
rpmcount++;
240
//Each rotation, this interrupt function is run
241
}
у меня такой код без делая. поковыряйся может поможет:
Спасибо. "ковырялся" и так, и с переводчиком....
Вобщем мозгов у меня не хватило. Даже не до конца понял что куда подключать. Буду признатеен если пояснишь на "великом и могучем".
Но методом проб и ошибок написл своё.
потенциометр на А0, Холл на пин 8 , Зерро на пин 2, управление симистором на пин 3. Дисплей - 4,5,6,7,9,10
Дал 0,5 процента погрешности в каждую сторону от требуемых оборотов. С 1000 об /мин держит вполне сносно. Дальше - лучше. Понимаю, что очень коряво, но довольный как удав.
Пока без всяких "плюшек". на экран вывел время задержки от нуля, нужные обороты от потенциометра, паследние показания оборотов датчика и средние обороты. Хотя средние не очень нравятся. На мой взгляд ошибочны.
001
#include <LiquidCrystal.h> // библиотека экрана
002
003
LiquidCrystal lcd( 4, 5, 6, 7,9,10);
// пины экрана
004
005
int
AC_LOAD = 3;
// пин управления симистором
006
007
volatile
int
dimming = 130;
// время задержки от нуля 7 = максимально, 128 = минимально
008
volatile
int
i = 0;
// переменная для уменьшения времени задержки.
009
010
volatile unsigned
long
time;
// время в микросекундах срабатывания датчика нуля
011
unsigned
long
tims;
// переменная показаний времени
012
013
unsigned
long
currentTime;
//временные переменные для таймера экрана
014
unsigned
long
loopTime;
015
016
int
obMax = 8000;
//ввести максимальные обороты
017
int
obMin = 200;
//ввести минимальные обороты
018
float
kImp = 12;
//ввести кол-во импульсов на 1 оборот
019
020
volatile
int
holl = 0;
//переменная срабатываня датчика
021
volatile
int
prOb = 0;
//предвар реальн обороты
022
volatile
int
rOb = 0;
// реальные обороты
023
024
volatile
int
zicls = 0;
// кол-во циклов для средних оборотов.
025
volatile unsigned
long
sp = 0;
//переменная суммы оборотов/мин.
026
027
volatile unsigned
int
int_tic;
//переменные для подсчёта времени между импульсами.
028
volatile unsigned
long
tic;
029
030
031
void
setup
()
032
{
033
pinMode(AC_LOAD, OUTPUT);
// назначаем выходом
034
attachInterrupt(0, zero_crosss_int, RISING);
// прерывание по пину 2
035
036
lcd.begin(16, 2);
//дисплей 16символов 2строчки
037
lcd.setCursor(0,0);
038
039
lcd.write(
"R:"
);
//в верхней строке выводим время задержки
040
041
lcd.setCursor(0,1);
042
043
lcd.write(
"t:"
);
// В нижней выводим показания датчика
044
045
lcd.setCursor(7,0);
046
047
lcd.write(
"S:"
);
//в верхней строке будем выводить требуемые обороты
048
049
lcd.setCursor(7,1);
050
051
lcd.write(
"S:"
);
// В нижней выводим фактичесские обороты
052
053
pinMode (8,INPUT);
// вход сигнала ICP( №8 only для atmega328)
054
//настройка 16 бит таймера-счётчика 1
055
TCCR1B = 0; TCCR1A = 0; TCNT1 = 0;
056
TIMSK1 = (1<<ICIE1)|(1<<TOIE1);
//создавать прерывание от сигнала на пине ICP1
057
TCCR1B = (1<<ICNC1)|(1<<ICES1)|(1<<CS10);
//div 1
058
}
059
060
ISR (TIMER1_CAPT_vect) {
//прерывание захвата сигнала на входе ICP1
061
tic= ((uint32_t)int_tic<<16)|TCNT1 ;
//подсчёт тиков
062
ICR1=0; int_tic=0; TCNT1=0;
063
holl =holl+ 1;}
// после каждого срабатывания датчика холл+1
064
065
ISR (TIMER1_OVF_vect) {
//прерывание для счёта по переполнению uint
066
int_tic++;
//считать переполнения через 65536 тактов
067
if
(int_tic > 50) {tic=0; int_tic=0;}
//если на входе пусто более 1/5 секунды
068
}
//то обнулить счётчики
069
070
// the interrupt function must take no parameters and return nothing
071
void
zero_crosss_int()
// function to be fired at the zero crossing to dim the light
072
{
073
time = micros();
074
075
}
076
077
void
loop
() {
078
079
080
int
val = analogRead(A0);
081
int
pR =map(val, 0, 1023, obMin, obMax);
//Приводим показания регулятора к минимальным и максимальным оборотам
082
083
prOb = 60000000/((tic * 0.0625 )*kImp);
//Высчитываем обороты по показаниям датчика
084
if
( prOb >= 0){
//проверяем на соответствие.
085
rOb = prOb ;
//если нормально, записываем в переменную
086
087
}
088
else
{}
089
if
(val > 0){
// если регулятор больше 0
090
if
( holl>=1){
// если сработал датчик
091
092
093
if
( rOb < ( pR-pR/200)){
//если реальные обороты меньше нужных - 0,5%
094
i= pR / rOb*3 ;
// просчитываем на сколько увеличим управление симистором.
095
i = constrain(i,1,5) ;
// ограничиваем результат от 1 до 5
096
dimming = dimming-i ;
//меняем время задержки на полученное значение
097
holl = 0;
// обнуляем срабатывание датчика
098
}
099
else
{}
100
101
if
( rOb > ( pR+pR/200)){
//если реальные обороты больше нужнх + 0,5%
102
103
dimming =dimming+10 ;
// время задержки увеличиваем на 10
104
dimming = constrain(dimming,7,110) ;
// и ограничиваем от 7 до 110
105
holl = 0;
// обнуляем срабатывание датчика.
106
}
107
else
{}
108
}
109
else
{}
110
111
if
(tic ==0){
// если двигатель не вращается
112
dimming = 100 ;
// время задержки = 100 подбираем опытным путём
113
}
114
else
{}
115
116
}
117
else
{
118
dimming =130;
//Если регулятор на 0 то время задержки 130
119
}
120
121
dimming = constrain(dimming,7,130) ;
// Следим чтоб время задержки было не меньше 7 и не больше 130
122
int
dimtime = (75*dimming);
// For 60Hz =>65
123
tims = micros();
// считываем время, прошедшее с момента запуска программы
124
if
(tims >= (time + dimtime)){
//если время больше или равно времени срабатывания нуля + время задержки
125
126
digitalWrite(AC_LOAD, HIGH);
// открываем симистор
127
delayMicroseconds(10);
// задержка 10 микросекунд (для 60Hz = 8.33)
128
digitalWrite(AC_LOAD, LOW);
// выключаем сигнал на симистор.
129
}
130
else
{}
131
132
sp = sp + rOb;
//суммируем обороты для средних показаний
133
zicls = zicls + 1 ;
//считаем кол -во циклов
134
135
136
// Для вывода значений на дисплей 1 раз в секунду
137
138
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
139
if
(currentTime >= (loopTime + 1000)){
// сравниваем текущий таймер с переменной loopTime + 1 секунда
140
141
lcd.setCursor(2,1);
142
lcd.print(prOb);
143
lcd.print(
" "
);
// выводим показания датчика
144
145
lcd.setCursor(2,0);
146
lcd.print(dimming);
147
lcd.print(
" "
);
// выводим время задержки на экран.
148
149
lcd.setCursor(9,0);
150
lcd.print(pR);
151
lcd.print(
" "
);
// выводим нужные обороты на экран.
152
153
lcd.setCursor(9,1);
154
155
lcd.print (sp/zicls);
// выводим средние обороты на экран.
156
lcd.print(
" "
);
157
158
159
sp = 0;
//обнуляем переменная суммы оборотов/мин.
160
zicls = 0;
// обнуляем количество циклов.
161
loopTime = currentTime;
// в loopTime записываем новое значение
162
}
163
}
Посмотрите пожалуйста кто знает: http://www.mopedist.ru/blogs/raznye-poleznjashki/upravlenie-kolektornym-dvigatelem-u2010b.html
Правильно я понимаю что эта схема только для коллекторных двигателей работающих от АС напряжения или можно сделать и для ДС?
Вот тут уже реализованный проект на ардуине с пид регулятором http://bascom.at.ua/publ/simistornyj_pid_reguljator/1-1-0-128
Снова приветствую всех участников темы, и всех с наступающими праздниками.
Появилось свободное врямя, и я снова вернулся к регулятору. Но что то у меня, впрочем как всегда, не идёт.
Решил подойти к вопросу с другой стороны. Алгоритм такой: Есть нужные нам обороты, например 1000об\мин. даём "зазор" например 5% в одну и в другую сторону. поручается от 950 до 1050 об\мин. Этот промежуток приравниваем к управлению симистором. 950 и ниже - полностью открыт, 1050 и выше - закрыт. Всё что в середине это промежуточные значения. При таком алгоритме обороты должны стабилизироваться в этом диапазоне в зависимости от нагрузки.
Реализация , на мой взгляд, должна быть такая:
float ko = pR/rOb; //делим нужные нам обороты на реальные это коэфициент. если обороты равны, получаем 1, если реальные больше, то от 0 до 1. если меньше то от 1 и выше. Нас интересует число с 4 цифры после запятой.
long ai = ko * 10000; //приводим коэфициент к целому положительному числу.
int g =map(ai, 10500, 9500, 7, 130); //задаём значение симистора от7-открыт до 130-закрыт исходя из полученного числа.
Кажется, всё просто. но почему то не работает. Тоесть работает, но только без промежуточных значений. ВКЛ или ВЫКЛ. Ошибка в самой первой строке. выводил значения на экран, либо 1, либо 0. После запятой 00 и всё.
Что не правильно?
Скорее всего pR и rOb являются целочисленными. В такой ситуации компилятор будет отдавать тоже целочисленные. Для перехода на дроби там нужно каккой-то толи префикс, то ли в конце что-то добавить. Еще не настолько хорошо знаю С.
Спасибо. Но я уже сумел всё исправить и записал всё одной строкой.:
int g =map(rOb, pR*0.95, pR*1.05, ogr, 130);
Если обороты больше 1000, работает хорошо. А меньше - плохо.
И рывки какието посторонние.
Здесь все зависит от дискретности датчика. Если у вас один такт на оборот (один датчик в месте по кругу вращения), то обратная связь может сильно запаздывать. Для более плавной регулировки на низких оборотах придется увеличить число датчиков для увеличения числа отсчетов. Бесконечно понижать число оборотов все равно не получится и думаю примерно на 400-500 оборотах в минуту наступит предел для понижения уже из-за импульсов ускорения и понижения мощности.
На один оборот приходится 12 импульсов. Уже не так мало. 400-500 об\мин. меня бы устроило.
Обороты считаются на каждом импульсе или усредненно по нескольким?
И еще можно при оборотах скажем ниже 1500 подавать не полный импульс на разгон, а половинный (по ШИМ например) чтобы не было резкого скачка ускорения.
Обороты считаем на каждом импульсе.
Симистор ограничен исходя из оборотов.
Тоже интересна данная тема.
Есть шпиндель 300w 48В, ШИМ регулятор как на фото и инфракрасный датчик.
Разница наверное только в управлении скоростью по шим от 0 до 255.
Пока тестировал все процессы отдельно, все работает. Правда шпиндель через этот регулятор сильно свистит на неполных оборотах.
P.s.: проблему свиста решил увеличением штатной частоты ШИМ ардуины
Обороты считаем на каждом импульсе.
Симистор ограничен исходя из оборотов.
Здравствуйте Александр, мне лень заходить на ютуб, поэтому напишу сюда.
Как-то приходилось ремонтировать центрифугу на старой работе, когда работал медтехником, там был тоже коллекторник на 220В, и рулил им мосфет, в целом аппарат был неплох, и работал долго, а попал он к нам, в мастерскую потому, что на датчике Холла окислом убился контакт... Я это к чему, почему бы Вам не смотреть в сторону высоковольтного полевика и ШИМ? Это же занимает куда меньше ресурсов чем постоянно ждать переход через ноль и ещё добавлять задержку после него?
К стати, мой проект от части пересекается, на данный момент, с Вашим, но у меня не индуктивная нагрузка, пока что, но в планах есть замахнуться и на неё, просто пока что нету RC снабера, а от индуктивной нагрузки, в моём случае, симистор хаотично открывается когда надо и не надо.
P.S. Можно ускорить АЦП, пример тут https://geektimes.ru/post/255744/ тем самым поднять немного общую производительность.
P.P.S. Ешё можно не использовать много раз функцию lcd.print а формировать вывод при помощи sprintf_P http://arduino.ru/forum/programmirovanie/vyvod-na-lcd-teksta-i-dannykh-v-odnoi-stroke#comment-62647
Я это к чему, почему бы Вам не смотреть в сторону высоковольтного полевика и ШИМ?
Если почитаете тему с первой страницы, то именно так я и начинал. Но мои полевики, почему то вылетали один за одним. Может нужен был более мощный, а может нужно было делать драйвер на управление. Незнаю. ответ я так и не нашел. Именно поэтому и перешел на симистор.
В общем, проблема в самом алгоритме стабилизации. Сейчас пробую разные варианты. Удалось снизить порог до 500об.мин.
За советы спасибо. Буду пробовать.
Вот, мне нравится эта схемотехника:
(с) http://arduino.ru/forum/apparatnye-voprosy/upravlenie-tokarnym-stankom#comment-30941
Только главное частоту ШИМ не задерать выше 1к Гц, оптотрон может несправляться и полевику мало непокажется. Вообще в идеале 50-100 Гц.
И к стати, у меня есть в мыслях возложить на отдельный контроллер фазовое управление, я ему буду только по юарт или АЦП подкидывать нужное значение 0-100%, а основной микроконтроллер будет делать всю остальную работу.
Схема примерно эта и была, только без опторазвязки.
И к стати, у меня есть в мыслях возложить на отдельный контроллер фазовое управление, я ему буду только по юарт или АЦП подкидывать нужное значение 0-100%, а основной микроконтроллер будет делать всю остальную работу.
Думаю, это лишнее. И одна ардуинка справляется.
Просто управлять симистором мы можем 100 раз в секунду, а импульсов от датчика получаем на 200об\мин получаем всего 40
Схема примерно эта и была, только без опторазвязки.
Опторазвязка нужна, а вдруг что-то пойдёт не так и на затвор полевика пойдёт сетевое напряжение?
Если у Вас была похожая схемотехника странно что полевики вылетали, у центрифуги была похожая схемотехника, там на валу ещё был барабан для пробирок, за счёт этого двигатель останавливался около 20 секунд, и ничего, всё работало. Частоту ШИМ не изменяли? По умолчанию она довольно таки большая, оптотрон может не успевать на ней.
Если у Вас была похожая схемотехника странно что полевики вылетали, у центрифуги была похожая схемотехника, там на валу ещё был барабан для пробирок, за счёт этого двигатель останавливался около 20 секунд, и ничего, всё работало. Частоту ШИМ не изменяли? По умолчанию она довольно таки большая, оптотрон может не успевать на ней.
Частоту уменьшал. Вылетали при малейшей нагрузке на вал. Либо если разгон не плавный. Может слабый мосфет стоял? 10А
Думаю, это лишнее. И одна ардуинка справляется.
Согласен, это быстрое решение, мне просто лень переписывать код на Си.
Схема примерно эта и была, только без опторазвязки.
Вы же в курсе что ВВ полевику надо около 9-ти вольт на затвор чтобы тот полностью, а не частично, открывался?
Схема примерно эта и была, только без опторазвязки.
Вы же в курсе что ВВ полевику надо около 9-ти вольт на затвор чтобы тот полностью, а не частично, открывался?
Выбирал цифровой, чтоб 5 вольт на управлении. 10nk60zfp
Выбирал цифровой, чтоб 5 вольт на управлении. 10nk60zfp
Да, симмистор получается самый простой вариант, но ведь двигатель это индуктивная нагрузка, от неё симмистору будет не очень хорошо.
Берёт меня большое сомнение, что от пяти вольт, напрямую, можно управлять сколь нибудь заметной мощностью. Не припомню схем (блоков питания, например), где напряжение управления менее 12 В + драйвер по затвору. Не зря это, не зря.
Берёт меня большое сомнение, что от пяти вольт, напрямую, можно управлять сколь нибудь заметной мощностью. Не припомню схем (блоков питания, например), где напряжение управления менее 12 В + драйвер по затвору. Не зря это, не зря.
Полностью с Вами солидарен, драйвер для полевика, особенно высоковольтного нужен 100% при варинте с ШИМ.
Мне кажется что надо юзать IRFP450 + IR2110 для таких целей как у Александра.
А вот и то, о чём я говорил I2C диммер на базе ATtiny85
http://arduino.ru/forum/programmirovanie/attiny85-i-preryvanie#comment-2...
Вот некоторый результат на ПИД-регуляторе. может кто подскажет как правильно подобрать коэффициенты.
https://youtu.be/kf4bfDD_nDc
Похоже вот так выглядит правильная регулировка при помощи ШИМ.
Эта схема практически ничем не отличается от той что вы привели несколькими постами выше. Добавлен только драйвер полевика и запитывается низковольтная часть от стабилитрона вместо батарейки. У меня по такой же схеме собрано, там обратной связью и не пахнет, на низких оборотах момента нету.
Эта схема практически ничем не отличается от той что вы привели несколькими постами выше. Добавлен только драйвер полевика и запитывается низковольтная часть от стабилитрона вместо батарейки. У меня по такой же схеме собрано, там обратной связью и не пахнет, на низких оборотах момента нету.
ОС можно прикрутить от таходатчика, а регулировку можно сделать плавнее, увеличив разрядность ШИМ, благо ардуина позволяет до целых 10 бит поднять, а это уже, внимание, 0..1023.
И к тому же освободится немного ресурсов, вообщем ШИМ наше всё.
При малых ШИМ никакое повышение его разрядности не добавить момента в мотор. Потому как ШИМ на моторе "интегрируется" и малые значения = малое напряжение на моторе => малый момент мотора. Нужна положительная обратная связь по току и аппаратная, а не "Ардуино".
Есть библия по следящим электроприводам, она правда по аналоговым, но формульная часть присутствует везде
При малых ШИМ никакое повышение его разрядности не добавить момента в мотор. Потому как ШИМ на моторе "интегрируется" и малые значения = малое напряжение на моторе => малый момент мотора.
Проблема не в " добавить момента" проблема в точности управления моментом при малых оборотах. И именно разрядность ШИМ тут ключевое. Другой вопрос, что значением ШИМ надо управлять грамотно, т.к. при одном и том же значении ШИМ возможно как медленое движение так и останов. Все потому, что момент трения покоя выше чем момент трения медленого движения. И тахометр, или аналогичное, как раз наилучшее решение проблемы.
Нужна положительная обратная связь по току и аппаратная, а не "Ардуино".
ПС. Ликбез для использующих слово "момент". В установившемся режиме, т.е. при постоянном числе оборотов (в т.ч и равном 0) момент вращения равен моменту нагрузки. Это 3-ё закон Нютона для вращательного движения. Повышение момента вращения при постоянной нагрузке приводит к повышению числа оборотов и обратно. Момент нагрузки - штука тонкая, зависит от характера нагрузки. Для тележек момента трения покоя при 0 выше чем при малой скорости. Исходя из вышесказаного фразы типа "на низких оборотах момента нету" некоректны.
Задачу стабилизации числа оборотов при неизвестной и переменной нагрузке можно решить только через ОС от числа оборотов (тахометра и т.п.) Стабилизация по току возможна только в узком диапазоне и исключая малые скорости, т.к. ток неоднозначно зависит от частоты.
В аналоговых использовался тахометр )))
Господа, о чем Вы?! Что за диспут аналоговый или цифровой на ардуине? При правильной реализации и одинаковой матмодели существенных различий нет. Про тахометр, так выше уже писано, нужен.
Решил поиграться с коллекторным двигателем, замутил на STM32F103 ШИМ в 20 кГц, слепил такую схемку, по классике жанра - из того что было под рукой, а полевиков логического уровня не было, тем более драйвера для обычных мосфетов, я же не буржуй, поэтому взял, старый добрый TIP122, выпаяный непомню откуда, непомню когда. Транзюк в целом неплох, фронты на входе конечно поровнее чем на выходе, но в целом справляется со своей задачей, тем более ток у меня небольшой, 0.1-0.2А, так как я замутил плавный пуск двигателя, типа этого, только транзюк не КТ827 а TIPок.
Тыкнул осциллом, и тут я кажется понял почему у Александра вылетали высоковольтные полевики - при напряжении питания в 36 В выбросы противоЭДС от движка, и диод HER302 уже не помогает, ничего удивительного, частота то большая.
Как можно увидеть на скрине осцилла, выбросы противоЭДС составляют почти в 2 раза больше напряжение, чем питалово, поэтому надо брать детали, с троекратным запасом.
З.Ы. Пробовал ещё ставить в разрыв по плюсу дроссель на 50 мкГ, испульсы противоЭДС пропадают, добавить кондюк, диод и будет DC-DCшка почти готовая.
а диодом коллектор-эмиттер выходного зашунтировать не пробовали? (как в составном)
Я бы для начала подкинул резистор порядка дестка ом последовотально диоду (он похоже действительно не работает) для снижения добротности контура, дающего колебания. Он кстати судя по частоте на индуктивности потока рассеянья.
Возможно проблема в том, что компоненты у меня все БУ, но я проверил диод мультиметром, он адекватно "звониться".
а диодом коллектор-эмиттер выходного зашунтировать не пробовали? (как в составном)
А зачем? Составной транзистор же имеет.
sany_sch я Вам очень рекомендовал бы отказаться от симмисторного управления в пользу ШИМ, регулировка симмистором это всего лишь диапазон от 7 до 130, а ШИМ можно 0..1023, к тому же освободиться больше ресурсов микроконтроллера, потому как ШИМ аппаратный, минимум математики.
Главное разобраться почему у Вас вылетали транзисторы.
https://www.youtube.com/watch?v=MuyDereKrp8
Он я у себя в группе даже опрос сделал по этому поводу. Большинство согласны что ШИМ лучше.
Здравствуйте. Заинтересовала данная тема по симисторному управлению. Вот только проблемма, у мен ардуино мега 2560 а прошивка заточена под мини, не могли бы вы помочь переделать ее под мегу. Вот код.Заранее спасибо)
001
int
obMin = 200;
//ввести минимальные обороты
002
int
obMax = 9000;
//ввести максимальные обороты
003
int
kImp = 120;
//ввести кол-во импульсов на 10 оборотов
004
int
minzn = 115;
// минимальное значение симмистора на котором начинается вращение.
005
int
ogrmin = 70 ;
// ограничение симистора на минимальных оборотах.
006
int
mindimming = 80;
//значение симистора при закллинившем станке (первоначальный импульс)
007
int
dopusk = 200 ;
//допуск оборотов в минус и плюс
008
int
razgon = 50;
//переменная разгона 1 - 100
009
010
011
#include <LiquidCrystal.h> // библиотека экрана
012
013
LiquidCrystal lcd( 9, 10, 4, 5, 6, 7);
// пины экрана
014
015
int
AC_LOAD = 3;
// пин управления симистором
016
volatile
int
dimming = 130;
// время задержки от нуля 7 = максимально, 130 = минимально
017
volatile unsigned
long
time;
// время в микросекундах срабатывания датчика нуля
018
unsigned
long
tims;
// переменная показаний времени
019
020
unsigned
long
currentTime;
//временные переменные для таймера экрана
021
unsigned
long
loopTime;
022
023
int
holl = 0;
//переменная срабатываня датчика
024
int
pR;
// показания регулятора
025
int
pRR;
// переменная для расчёта.
026
int
ogr ;
//переменная ограничений симистора натекущих оборотах
027
volatile
int
sp = 0;
//переменная суммы срабатываний датчика
028
volatile
int
prOb ;
//предвар реальн обороты
029
volatile
int
rOb ;
// реальные обороты
030
031
volatile unsigned
int
int_tic;
//переменные для подсчёта времени между импульсами.
032
volatile unsigned
long
tic;
033
volatile
int
t = 0;
//минимальное время импульсов +1
034
int
val ;
035
void
setup
()
036
{
037
pRR = obMin;
038
t = (15000 / ( obMin * (kImp / 10))) * 2;
//высчитываем минимальное время импульсов +1
039
pinMode(AC_LOAD, OUTPUT);
// назначаем выходом
040
attachInterrupt(0, zero_crosss_int, RISING);
// прерывание по пину 2
041
042
lcd.begin(16, 2);
//дисплей 16символов 2строчки
043
lcd.setCursor(0, 0);
044
045
lcd.write(
"R:"
);
//в верхней строке выводим время задержки
046
047
lcd.setCursor(0, 1);
048
049
lcd.write(
"t:"
);
// В нижней выводим показания датчика
050
051
lcd.setCursor(8, 0);
052
053
lcd.write(
"S:"
);
//в верхней строке будем выводить требуемые обороты
054
055
lcd.setCursor(8, 1);
056
057
lcd.write(
"S:"
);
// В нижней выводим фактичесские обороты
058
059
060
pinMode (8, INPUT);
// вход сигнала ICP( №8 only для atmega328)
061
//настройка 16 бит таймера-счётчика 1
062
TCCR1B = 0; TCCR1A = 0; TCNT1 = 0;
063
TIMSK1 = (1 << ICIE1) | (1 << TOIE1);
//создавать прерывание от сигнала на пине ICP1
064
TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CS10);
//div 1
065
066
}
067
068
ISR (TIMER1_CAPT_vect) {
//прерывание захвата сигнала на входе ICP1
069
tic = ((uint32_t)int_tic << 16) | ICR1 ;
//подсчёт тиков
070
ICR1 = 0; int_tic = 0; TCNT1 = 0;
071
sp = sp + 1 ;
// для подсчёта оборотов в минуту.
072
holl = holl + 1;
073
}
// после каждого срабатывания датчика холл+1
074
075
076
ISR (TIMER1_OVF_vect) {
//прерывание для счёта по переполнению uint
077
int_tic++;
//считать переполнения через 65536 тактов
078
if
(int_tic > t) {
079
tic = 0;
//если на входе пусто более минимального времени то обнулить счётчики
080
int_tic = 0;
081
}
082
if
(int_tic > 500) {
083
dimming = 130;
// если стоим 2 секунды, то сбрасываем напряжение.
084
}
085
}
086
087
// the interrupt function must take no parameters and return nothing
088
void
zero_crosss_int()
// function to be fired at the zero crossing to dim the light
089
{
090
time = micros();
091
092
}
093
094
void
loop
() {
095
096
097
val = analogRead(A0);
098
pR = map(val, 0, 1023, obMin, obMax);
//Приводим показания регулятора к минимальным и максимальным оборотам
099
100
if
(val > 0) {
// если регулятор больше 0
101
if
( holl >= 1) {
// если сработал датчик
102
prOb = 60000000 / ((tic * 0.0625 ) * kImp / 10);
//Высчитываем обороты по показаниям датчика
103
if
( prOb >= 0) {
//проверяем на соответствие.
104
rOb = prOb ;
//если нормально, записываем в реальные обороты
105
106
}
107
if
( rOb < pR ) {
//сверяем показания регулятора и реальные обороты
108
int
fff = pR - rOb;
//узнаём разницу между оборотами
109
int
pRu = map(fff, 1, obMax, 1, razgon);
//исходя из разницы и разгона высчитываем на сколько увеличить переменную для расчёта
110
pRR = pRR + pRu ;
//увеличиваем переменную расчёта
111
}
112
if
( pR < (rOb - 20) ) {
//сверяем показания регулятора и реальные обороты
113
int
fff = rOb - 20 - pR;
//узнаём разницу между оборотами
114
int
pRu = map(fff, 1, obMax, 1, razgon);
//исходя из разницы и разгона высчитываем на сколько уменьшить переменную для расчёта
115
pRR = pRR - pRu ;
//увеличиваем переменную расчёта
116
}
117
pRR = constrain(pRR, (pR / 2), obMax);
//задаём пределы переменной для расчёта.
118
ogr = map(val, 0, 1023, ogrmin, 7);
//исходя из показаний регулятора узнаём на сколько может быть открыт симистор.
119
120
dimming = map(rOb, (pRR - dopusk), (pRR + dopusk), ogr, minzn);
//рассчитываем управление симистором.
121
holl = 0;
// обнуляем срабатывание датчика
122
}
123
124
if
(tic == 0) {
// если двигатель не вращается
125
dimming = mindimming ;
// время задержки равно первоначальному импульсу
126
}
127
dimming = constrain(dimming, ogr, minzn) ;
// Следим чтоб время задержки было не меньше ограничения и не больше минимального значения
128
}
129
else
{
130
dimming = 130;
//Если регулятор на 0 то время задержки 130
131
pRR = obMin;
132
}
133
134
135
int
dimtime = (75 * dimming);
// For 60Hz =>65
136
tims = micros();
// считываем время, прошедшее с момента запуска программы
137
if
(tims >= (time + dimtime)) {
//если время больше или равно времени срабатывания нуля + время задержки
138
139
digitalWrite(AC_LOAD, HIGH);
// открываем симистор
140
delayMicroseconds(10);
// задержка 10 микросекунд (для 60Hz = 8.33)
141
digitalWrite(AC_LOAD, LOW);
// выключаем сигнал на симистор.
142
}
143
else
{}
144
145
146
147
148
// Для вывода значений на дисплей 2 раз в секунду
149
150
currentTime = millis();
// считываем время, прошедшее с момента запуска программы
151
if
(currentTime >= (loopTime + 500)) {
// сравниваем текущий таймер с переменной loopTime + 0,5 секунд
152
153
// выводим показания датчика
154
155
lcd.setCursor(2, 0);
156
lcd.print(dimming );
157
lcd.print(
" "
);
// выводим время задержки на экран.
158
159
lcd.setCursor(2, 1);
160
lcd.print(val );
161
lcd.print(
" "
);
// выводим нужные обороты на экран.
162
163
lcd.setCursor(10, 0);
164
lcd.print(map(val, 0, 1023, obMin, obMax));
165
lcd.print(
" "
);
// выводим нужные обороты на экран.
166
167
lcd.setCursor(10, 1);
168
169
lcd.print (sp * (1200 / kImp));
// выводим средние обороты на экран.
170
lcd.print(
" "
);
171
sp = 0;
172
loopTime = currentTime;
// в loopTime записываем новое значение
173
}
174
}
Ладно попробую начать сам .Я так понимаю что основная проблемма это отсутствие у меги вывода модуля захата ICP1, остальные пины вроде как соответствуют пинам ардуины мини. Как можно реализовать эту функцию в меге??? Хочу сказать сразу что в програмировании я не сильно силен, но стремление огромное)