Регулятор оборотов двигателя постоянного тока
- Войдите на сайт для отправки комментариев
Пт, 26/01/2018 - 23:37
Уважаемые Гуру программирования для Ардуино, помогите пожалуйста разобраться вот с какой пробемой - у меня есть купленный из китая Ардуино УНО, есть оптический датчик (использую как датчик оборотов), блок реле (2 шт) и собственного производства PowerShield, питающий всю схему, плюс на нем разъемы для подключения дисплея, датчика, блока реле. Задача тривиальная - регистрируем обороты с помощью оптического датчика, если они отклоняются от заданных, подаем сигнал на реле, которое включает моторчик, передвигающий ползунок реасата, который в свою очередь изменяет скорость вращения двигателя. Вот код:
#include <LiquidCrystal.h>
#define PIN_DO 2 // Установка контакта используемого в Arduino
LiquidCrystal lcd(8, 7, 9, 6, 4, 5); // (RS, E, DB4, DB5, DB6, DB7)
volatile unsigned int pulses;
float rpm;
unsigned long timeOld;
#define HOLES_DISC 4
#define RELE_UP 10
#define RELE_DOWN 11
unsigned int lock;
unsigned int t;
void setup()
{
lcd.begin(16, 2); // Задаем размерность экрана
//Serial.begin(9600);
pinMode(PIN_DO, INPUT);
pinMode(RELE_UP, OUTPUT);
pinMode(RELE_DOWN, OUTPUT);
t = 3; // время усреднения в секундах
pulses = 0;
timeOld = 0;
lock = 0;
digitalWrite(RELE_UP, HIGH);
digitalWrite(RELE_DOWN, HIGH);
rpm = 0;
}
void loop()
{
if (digitalRead(PIN_DO) == HIGH && lock == 0)
{
pulses ++;
lock = 1;
}
if (digitalRead(PIN_DO) == LOW) lock = 0;
if (millis() - timeOld >= 1000 * t)
{
rpm = (pulses * 60) / (HOLES_DISC * t);
Text();
timeOld = millis();
pulses = 0;
}
if (rpm < 1300)
{
digitalWrite(RELE_UP, HIGH);
digitalWrite(RELE_DOWN, HIGH);
}
else if ((rpm > 1300) && (rpm < 1500))
{
digitalWrite(RELE_DOWN, HIGH);
delay(20);
digitalWrite(RELE_UP, LOW);
}
else if ((rpm >= 1500) && (rpm <= 1505))
{
digitalWrite(RELE_UP, HIGH);
digitalWrite(RELE_DOWN, HIGH);
}
else if (rpm > 1505)
{
digitalWrite(RELE_UP, HIGH);
delay(20);
digitalWrite(RELE_DOWN, LOW);
}
}
void Text()
{
lcd.clear();
if (rpm < 1300)
{
lcd.setCursor(1, 0); // Устанавливаем курсор в начало 1 строки
lcd.print("Zhdu oborotov");
}
else if (rpm > 1300 && rpm < 1500)
{
lcd.setCursor(3, 0);
lcd.print("RPM Low");
}
else if (rpm >= 1500 && rpm <= 1505)
{
lcd.setCursor(3, 0);
lcd.print("RPM Normal");
}
else if (rpm > 1505)
{
lcd.setCursor(3, 0);
lcd.print("RPM High");
}
lcd.setCursor(2, 1); // Устанавливаем курсор в начало 2 строки
lcd.print(rpm, 0); // Выводим текст
lcd.setCursor(7, 1);
lcd.print("ob/min");
}
Так вот, вроде работает, но как-то странно: в течении "времени усреднения" (t - в коде) реле получает питание и на дисплее высвечивается то, что должно, а потом в течении того же времени снимается сигнал с реле, а на дисплее, обороты принимают случайные значения в пределах от 0 до 100. Не могу разобраться в чем дело.
Может проблема в китайском ардуино?
А вместо связки реле-моторчик-реостат, транзистор и ШИМ нельзя применить? Или мощность двигателя не позволяет.
А то эта связка каким-то электро-панком попахивает, но выглядит наверное довольно зрелещно.
Круто "реле-моторчик-реостат-мотор" :)
Круто "реле-моторчик-реостат-мотор" :)
Все куда как круче: "ардуино-реле-моторчик-реостат-мотор":)
if (rpm < 1300)
точно high должно быть? И вставьте код по-человечески, пожалуйста
Да, такая связка необходима, потому как последний моторчик в этой цепи на 7,5 кВт, соответственно реастат установлен в цепи параллельной обмотки возбуждения. Это что касается объекта управления. Реле действительно управляются сигналом низкого уровня. А вот как вставить код по человечески, немного не разобрался
Уважаемые Гуру программирования
Как-то пропустил этот момент, подумалось что ТС школьник, которому я в силах помочь. Ну да ладно, хотя бы тему апнул.
Реле действительно управляются сигналом низкого уровня.
Да это понятно. Логика странная по-моему.
Могу посоветовать Вам стандартную процедуру дебага - выводить переменные в последовательный порт. Pulses не переполняется? И еще рпм = 1300 выкинули из условий
http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii
Спасибо за совет, буду побывать различные варианты. Жаль, вот только, что программатор на плате спалил случайно.
Еще могу порекомендовать использовать внешние прерывания для подсчета импульсов. volatile Вы для чего использовали? И delay лучше на заменить на millis
volatile взял из примера с внешним прерыванием, однако, вне зависимости от того, считал ли я импульсы по нарастанию фронта или по спаду, ардуино мне выдавал что Бог надушу положет... поэтому пришлось отказаться и сделать счет импульсов в коде, при этом, чтобы защититься от ложных срабатываний, поставил защелку lock
Код в человеческом виде :)
Да, вот еще....
Когда реле не срабатывают, т.е. с оборотами все Ок, на дисплее всякая ересь не вылезает. Т.е. могу сделать вывод, что возможно какой-то косяк происходит при работе реле. Переменная rpm, такое ощущение, принимает случайное значение от 0 до 100, и конечно же реле отключаются. Вот только в коде у меня нет даже места, где бы я обнулял это значение
Переменная rpm, такое ощущение, принимает случайное значение от 0 до 100, и конечно же реле отключаются. Вот только в коде у меня нет даже места, где бы я обнулял это значение
pulses = 0;
Код в человеческом виде :)
заказывайте с запасом, это не последний трупик :))))
уверены, что помехи ему не мешают??? энкодеры штука капризная, навык нужен.
ИМХО. код полная шляпа - в лупе два
digitalRead(PIN_DO)
, а потом работа с релюхами, да еще delay вешает контроллер периодически. Определение t=3 секунды ,за это время код в лупе проскакивает много раз и строки 47-72 исполняются много чаще чем требуется на определение влияния предыдущего воздействия. релюхи, как и Text(); необходимо засунуть перед строками 48-49 timeOld = millis(); pulses = 0;и вообще энкодер необходимо посадить на прерывания, чтоб импульсы не терять, а уже после замеров корректировать и показывать индикацию.
7,5 кВт - ни о чем , какой ток и напруга обмотки возбуждения???
и вообще так писать (строки 31 и 36 ) очень глупо за это время состояние может измениться и оба неравенства будут не выполнены. для таких дел есть переменная boolean i == 0 или i != 0 или byte
ЗЫ сперва измерьте, потом посчитайте, потом запишите, потом измените, потом обнулите и начните с начала.
Спасибо большое за помощь, обязательно попробую реализовать данные мне рекомендации, вот только дождусь нового андурино
У тебя ток обмотки возбуждения пара ампер. Можно и без реостата неплохо его регулировать. Тем же igbt или мосфетом.