Ви не увійшли.
Доброго дня. Дістався мені непоганий кухонний комбайн profi cook pc km 1004 але з нюансом згоріла плата керування. Так з'явилася ідея відновити з допомогою ардуїно нано. За базу вирішив взяти код від ПІТ регулятора так як вже з заводу двигун має датчик холла.
const int obMin = 200; //ввести минимальные обороты
const int obMax = 9000; //ввести максимальные обороты
const int kImp = 60; //ввести кол-во импульсов на 10 оборотов
const int minzn = 120; // минимальное значение симмистора на котором начинается вращение.
const int ogrmin = 70 ; // ограничение симистора на минимальных оборотах.
const int mindimming = 80; //значение симистора при закллинившем станке (первоначальный импульс)
const int dopusk = 200 ; //допуск оборотов в минус и плюс
int AC_LOAD = 3; // пин управления симистором
volatile int dimming = 130; // время задержки от нуля 7 = максимально, 130 = минимально
volatile unsigned long time; // время в микросекундах срабатывания датчика нуля
unsigned long tims; // переменная показаний времени
int holl = 0; //переменная срабатываня датчика
int pR; // показания регулятора
int ogr ; //переменная ограничений симистора натекущих оборотах
volatile int sp = 0; //переменная суммы срабатываний датчика
volatile int prOb ; //предвар реальн обороты
volatile int rOb ; // реальные обороты
volatile unsigned int int_tic; //переменные для подсчёта времени между импульсами.
volatile unsigned long tic;
volatile int t = 0; //минимальное время импульсов +1
int val ;
void setup()
{
t = (15000 / ( obMin * (kImp / 10))) * 2; //высчитываем минимальное время импульсов +1
pinMode(AC_LOAD, OUTPUT); // назначаем выходом
attachInterrupt(0, zero_crosss_int, RISING); // прерывание по пину 2
Serial.begin(9600);
pinMode (8, INPUT); // вход сигнала ICP( №8 only для atmega328)
//настройка 16 бит таймера-счётчика 1
TCCR1B = 0; TCCR1A = 0; TCNT1 = 0;
TIMSK1 = (1 << ICIE1) | (1 << TOIE1); //создавать прерывание от сигнала на пине ICP1
TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CS10); //div 1
}
ISR (TIMER1_CAPT_vect) { //прерывание захвата сигнала на входе ICP1
tic = ((uint32_t)int_tic << 16) | ICR1 ; //подсчёт тиков
ICR1 = 0; int_tic = 0; TCNT1 = 0;
sp = sp + 1 ; // для подсчёта оборотов в минуту.
holl = holl + 1;
} // после каждого срабатывания датчика холл+1
ISR (TIMER1_OVF_vect) { //прерывание для счёта по переполнению uint
int_tic++; //считать переполнения через 65536 тактов
if (int_tic > t) {
tic = 0; //если на входе пусто более минимального времени то обнулить счётчики
int_tic = 0;
}
if (int_tic > 500) {
dimming = 130; // если стоим 2 секунды, то сбрасываем напряжение.
}
}
// the interrupt function must take no parameters and return nothing
void zero_crosss_int() // function to be fired at the zero crossing to dim the light
{
time = micros();
}
void loop() {
val = analogRead(A0);
pR = map(val, 0, 1023, obMin, obMax); //Приводим показания регулятора к минимальным и максимальным оборотам
if (val > 0) { // если регулятор больше 0
if ( holl >= 1) { // если сработал датчик
prOb = 60000000 / ((tic * 0.0625 ) * kImp / 10); //Высчитываем обороты по показаниям датчика
if ( prOb >= 0) { //проверяем на соответствие.
rOb = prOb ; //если нормально, записываем в реальные обороты
}
ogr = map(val, 0, 1023, ogrmin, 7); //исходя из показаний регулятора узнаём на сколько может быть открыт симистор.
dimming = map(rOb, (pR - dopusk), (pR + dopusk), ogr, minzn); //рассчитываем управление симистором.
holl = 0; // обнуляем срабатывание датчика
}
if (tic == 0) { // если двигатель не вращается
dimming = mindimming ; // время задержки равно первоначальному импульсу
}
dimming = constrain(dimming, ogr, minzn) ; // Следим чтоб время задержки было не меньше ограничения и не больше минимального значения
}
else {
dimming = 130; //Если регулятор на 0 то время задержки 130
}
int dimtime = (75 * dimming); // For 60Hz =>65
tims = micros(); // считываем время, прошедшее с момента запуска программы
if (tims >= (time + dimtime)) { //если время больше или равно времени срабатывания нуля + время задержки
digitalWrite(AC_LOAD, HIGH); // открываем симистор
delayMicroseconds(10); // задержка 10 микросекунд (для 60Hz = 8.33)
digitalWrite(AC_LOAD, LOW); // выключаем сигнал на симистор.
}
else {}
}
Тільки залишилось додати п'ять кнопок з вілповідними програмамми, але щось не виходить.
//константы
const int obMin = 200; //ввести минимальные обороты
const int obMax = 9000; //ввести максимальные обороты
const int kImp = 60; //ввести кол-во импульсов на 10 оборотов
const int minzn = 120; // минимальное значение симмистора на котором начинается вращение.
const int ogrmin = 70 ; // ограничение симистора на минимальных оборотах.
const int mindimming = 80; //значение симистора при закллинившем станке (первоначальный импульс)
const int dopusk = 200 ; //допуск оборотов в минус и плюс
//переменные
int AC_LOAD = 3; // пин управления симистором
volatile int dimming = 130; // время задержки от нуля 7 = максимально, 130 = минимально
volatile unsigned long time; // время в микросекундах срабатывания датчика нуля
unsigned long tims; // переменная показаний времени
//unsigned long currentTime; //временные переменные для таймера экрана
//unsigned long loopTime;
int holl = 0; //переменная срабатываня датчика
int pR; // показания регулятора
int ogr ; //переменная ограничений симистора натекущих оборотах
volatile int sp = 0; //переменная суммы срабатываний датчика
volatile int prOb ; //предвар реальн обороты
volatile int rOb ; // реальные обороты
volatile unsigned int int_tic; //переменные для подсчёта времени между импульсами.
volatile unsigned long tic;
volatile int t = 0; //минимальное время импульсов +1
int val ;
unsigned char mode;
boolean flag = 0;
boolean btn_flag = 0;
boolean btnState;
unsigned long btnTimer = 0;
#define button_manual 4
#define button_mixing 5
#define button_egg_milk 6
#define button_fruit_juice 7
#define button_grinding 9
#define led_manual A1
#define led_mixing A2
#define led_egg_milk A3
#define led_fruit_juice A4
#define led_grinding A5
void setup() {
Serial.begin(9600);
pinMode(button_manual, INPUT_PULLUP);
pinMode(led_manual, OUTPUT);
pinMode(button_mixing, INPUT_PULLUP);
pinMode(led_mixing, OUTPUT);
pinMode(button_egg_milk, INPUT_PULLUP);
pinMode(led_egg_milk, OUTPUT);
pinMode(button_fruit_juice, INPUT_PULLUP);
pinMode(led_fruit_juice, OUTPUT);
pinMode(button_grinding, INPUT_PULLUP);
pinMode(led_grinding, OUTPUT);
t = (15000 / ( obMin * (kImp / 10))) * 2; //высчитываем минимальное время импульсов +1
pinMode(AC_LOAD, OUTPUT); // назначаем выходом
attachInterrupt(0, zero_crosss_int, RISING); // прерывание по пину 2
Serial.begin(9600);
pinMode (8, INPUT); // вход сигнала ICP( №8 only для atmega328)
//настройка 16 бит таймера-счётчика 1
TCCR1B = 0; TCCR1A = 0; TCNT1 = 0;
TIMSK1 = (1 << ICIE1) | (1 << TOIE1); //создавать прерывание от сигнала на пине ICP1
TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CS10); //div 1
}
ISR (TIMER1_CAPT_vect) { //прерывание захвата сигнала на входе ICP1
tic = ((uint32_t)int_tic << 16) | ICR1 ; //подсчёт тиков
ICR1 = 0; int_tic = 0; TCNT1 = 0;
sp = sp + 1 ; // для подсчёта оборотов в минуту.
holl = holl + 1;
} // после каждого срабатывания датчика холл+1
ISR (TIMER1_OVF_vect) { //прерывание для счёта по переполнению uint
int_tic++; //считать переполнения через 65536 тактов
if (int_tic > t) {
tic = 0; //если на входе пусто более минимального времени то обнулить счётчики
int_tic = 0;
}
if (int_tic > 500) {
dimming = 130; // если стоим 2 секунды, то сбрасываем напряжение.
}
}
void zero_crosss_int() // function to be fired at the zero crossing to dim the light
{
time = micros();
}
void loop() {
// читаем инвертированное значение для удобства
btnState = !digitalRead(4);
if (btnState && !flag && millis() - btnTimer > 200) {
flag = true;
btnTimer = millis();
}
if (btnState && flag && millis() - btnTimer > 500) {
btnTimer = millis();
mode = 1;
flag =!flag;
}
if (!btnState && flag && millis() - btnTimer > 500) {
flag = false;
btnTimer = millis();
}
btnState = !digitalRead(button_mixing); // режим миксер
if (btnState == 1 && btn_flag == 0 && millis() - btnTimer > 200) {
btn_flag = 1;
btnTimer = millis();
flag =!flag;
mode = 2;
// digitalWrite(led, flag);
}
if (btnState == 0 && btn_flag == 1) {
btn_flag = 0;
}
else if (btnState == 1 && flag == 1 && mode > 0) {
mode = 0;
}
btnState = !digitalRead(button_egg_milk); // режим сливки
if (btnState == 1 && btn_flag == 0 && millis() - btnTimer > 200) {
btn_flag = 1;
btnTimer = millis();
flag =!flag;
mode = 3;
// digitalWrite(led, flag);
}
if (btnState == 0 && btn_flag == 1) {
btn_flag = 0;
}
else if (btnState == 1 && flag == 1 && mode > 0) {
mode = 0;
}
btnState = !digitalRead(button_fruit_juice); // режим блендер
if (btnState == 1 && btn_flag == 0 && millis() - btnTimer > 200) {
btn_flag = 1;
btnTimer = millis();
flag =!flag;
mode = 4;
// digitalWrite(led, flag);
}
if (btnState == 0 && btn_flag == 1) {
btn_flag = 0;
}
else if (btnState == 1 && flag == 1 && mode > 0) {
mode = 0;
}
btnState = !digitalRead(button_grinding); // режим мясорубка
if (btnState == 1 && btn_flag == 0 && millis() - btnTimer > 200) {
btnTimer = millis();
btn_flag = 1;
flag =!flag;
mode = 5;
// digitalWrite(led, flag);
}
if (btnState == 0 && btn_flag == 1) {
btn_flag = 0;
}
else if (flag == 1 && mode == 5 ) {
mode = 0;
}
switch(mode){
case 0:
digitalWrite(led_manual, LOW);
digitalWrite(led_mixing, LOW);
digitalWrite(led_egg_milk, LOW);
digitalWrite(led_fruit_juice, LOW);
digitalWrite(led_grinding, LOW);
Serial.println("stop");
break;
case 1:
val = analogRead(A0);
pR = map(val, 0, 1023, obMin, obMax); //Приводим показания регулятора к минимальным и максимальным оборотам
if (val > 0) { // если регулятор больше 0
if ( holl >= 1) { // если сработал датчик
prOb = 60000000 / ((tic * 0.0625 ) * kImp / 10); //Высчитываем обороты по показаниям датчика
if ( prOb >= 0) { //проверяем на соответствие.
rOb = prOb ; //если нормально, записываем в реальные обороты
}
ogr = map(val, 0, 1023, ogrmin, 7); //исходя из показаний регулятора узнаём на сколько может быть открыт симистор.
dimming = map(rOb, (pR - dopusk), (pR + dopusk), ogr, minzn); //рассчитываем управление симистором.
holl = 0; // обнуляем срабатывание датчика
}
if (tic == 0) { // если двигатель не вращается
dimming = mindimming ; // время задержки равно первоначальному импульсу
}
dimming = constrain(dimming, ogr, minzn) ; // Следим чтоб время задержки было не меньше ограничения и не больше минимального значения
}
else {
dimming = 130; //Если регулятор на 0 то время задержки 130
}
int dimtime = (75 * dimming); // For 60Hz =>65
tims = micros(); // считываем время, прошедшее с момента запуска программы
if (tims >= (time + dimtime)) { //если время больше или равно времени срабатывания нуля + время задержки
digitalWrite(AC_LOAD, HIGH); // открываем симистор
delayMicroseconds(10); // задержка 10 микросекунд (для 60Hz = 8.33)
digitalWrite(AC_LOAD, LOW); // выключаем сигнал на симистор.
}
else {}
Serial.println("manual");
digitalWrite(led_manual, HIGH);
digitalWrite(led_mixing, LOW);
digitalWrite(led_egg_milk, LOW);
digitalWrite(led_fruit_juice, LOW);
digitalWrite(led_grinding, LOW);
break;
case 2: mixing(); break;
case 3:egg_milk();break;
case 4:fruit_juice(); break;
case 5:grinding(); break;
}
}
void grinding(){
Serial.println("grinding");
digitalWrite(led_manual, LOW);
digitalWrite(led_mixing, LOW);
digitalWrite(led_egg_milk, LOW);
digitalWrite(led_fruit_juice, LOW);
digitalWrite(led_grinding, HIGH);
}
void manual(unsigned long tm, unsigned int ho){
val = analogRead(A0);
pR = map(val, 0, 1023, obMin, obMax); //Приводим показания регулятора к минимальным и максимальным оборотам
if (val > 0) { // если регулятор больше 0
if ( ho >= 1) { // если сработал датчик
prOb = 60000000 / ((tic * 0.0625 ) * kImp / 10); //Высчитываем обороты по показаниям датчика
if ( prOb >= 0) { //проверяем на соответствие.
rOb = prOb ; //если нормально, записываем в реальные обороты
}
ogr = map(val, 0, 1023, ogrmin, 7); //исходя из показаний регулятора узнаём на сколько может быть открыт симистор.
dimming = map(rOb, (pR - dopusk), (pR + dopusk), ogr, minzn); //рассчитываем управление симистором.
ho = 0; // обнуляем срабатывание датчика
}
if (tic == 0) { // если двигатель не вращается
dimming = mindimming ; // время задержки равно первоначальному импульсу
}
dimming = constrain(dimming, ogr, minzn) ; // Следим чтоб время задержки было не меньше ограничения и не больше минимального значения
}
else {
dimming = 130; //Если регулятор на 0 то время задержки 130
}
int dimtime = (75 * dimming); // For 60Hz =>65
tims = micros(); // считываем время, прошедшее с момента запуска программы
if (tims >= (tm + dimtime)) { //если время больше или равно времени срабатывания нуля + время задержки
digitalWrite(AC_LOAD, HIGH); // открываем симистор
delayMicroseconds(10); // задержка 10 микросекунд (для 60Hz = 8.33)
digitalWrite(AC_LOAD, LOW); // выключаем сигнал на симистор.
}
else {}
Serial.println("manual");
digitalWrite(led_manual, HIGH);
digitalWrite(led_mixing, LOW);
digitalWrite(led_egg_milk, LOW);
digitalWrite(led_fruit_juice, LOW);
digitalWrite(led_grinding, LOW);
}
void mixing(){
Serial.println("mixing");
digitalWrite(led_manual, LOW);
digitalWrite(led_mixing, HIGH);
digitalWrite(led_egg_milk, LOW);
digitalWrite(led_fruit_juice, LOW);
digitalWrite(led_grinding, LOW);
pR = 9000; // режи з постійними обертами
if (val > 0) { // если регулятор больше 0
if ( holl >= 1) { // если сработал датчик
prOb = 60000000 / ((tic * 0.0625 ) * kImp / 10); //Высчитываем обороты по показаниям датчика
if ( prOb >= 0) { //проверяем на соответствие.
rOb = prOb ; //если нормально, записываем в реальные обороты
}
ogr = map(val, 0, 1023, ogrmin, 7); //исходя из показаний регулятора узнаём на сколько может быть открыт симистор.
dimming = map(rOb, (pR - dopusk), (pR + dopusk), ogr, minzn); //рассчитываем управление симистором.
holl = 0; // обнуляем срабатывание датчика
}
if (tic == 0) { // если двигатель не вращается
dimming = mindimming ; // время задержки равно первоначальному импульсу
}
dimming = constrain(dimming, ogr, minzn) ; // Следим чтоб время задержки было не меньше ограничения и не больше минимального значения
}
else {
dimming = 130; //Если регулятор на 0 то время задержки 130
}
int dimtime = (75 * dimming); // For 60Hz =>65
tims = micros(); // считываем время, прошедшее с момента запуска программы
if (tims >= (time + dimtime)) { //если время больше или равно времени срабатывания нуля + время задержки
digitalWrite(AC_LOAD, HIGH); // открываем симистор
delayMicroseconds(10); // задержка 10 микросекунд (для 60Hz = 8.33)
digitalWrite(AC_LOAD, LOW); // выключаем сигнал на симистор.
}
else {}
}
void egg_milk(){
Serial.println("egg");
digitalWrite(led_manual, LOW);
digitalWrite(led_mixing, LOW);
digitalWrite(led_egg_milk, HIGH);
digitalWrite(led_fruit_juice, LOW);
digitalWrite(led_grinding, LOW);
}
void fruit_juice(){
Serial.println("fruit_juice");
digitalWrite(led_manual, LOW);
digitalWrite(led_mixing, LOW);
digitalWrite(led_egg_milk, LOW);
digitalWrite(led_fruit_juice, HIGH);
digitalWrite(led_grinding, LOW);
}
Суть в тому що в першому випадку двигун працює ідеально, а в другом де я додав кнопок двигун починає сіпатись. Розуміє що десь натупив, а не рузумію де. Чи не може хтось допогти ? Шкода викидквати гарну річ
Остання редакція James_Pont (2025-10-04 23:27:15)
Неактивний
Ви якось дивно управляєте симістором. Було б логічно ловити interrupt по переходу через 0 , запускати таймер, і по interrupt від таймера запускати симістор. Всередині loop там що завгодно може вилізти.
В логіку коду не вчитувався, бо він сумбурний і ледь структурований. Сумнівають, що воно навіть скомпілиться. Але як мінімум, у вас неатомарні звернення до змінних, які оновлюються в обробниках переривань. ПЗ для вбудованих систем так не пишеться.
Наскільки критичний той таймінг керування симістором? 10 мкс співрозмірне з часом виконання обробників переривань. Не очікуйте, що та затримка буде завжди 10 мкс. А якщо важлива не тільки тривалість імпульсів, а й тривалість пауз між ними, то тільки analogRead() дає затримку більше 100 мкс.
Неактивний
Добре. Спробую переписати з урахуванням ваших коментарів. Може що вийде, тоді відпишусь. Заодно думаю ще додати принципову схему.
Неактивний
Із схемою теж непогано
Ще хороша ідея - синхронізувати все з частотою мережі. Піднімати прапорець по interrupt і крутити далі бізнес-логіку з кнопками і всим іншим. Тоді не треба запам"ятовувати мілісекунди для кнопок, можна рахувати 100-герцові тіки. І за analogread можна смикати рідше. Це ж регулятор обертів, так? Ви ж не крутите його 3000 обертів за хвилину?
Неактивний
Неактивний
Швидко зробив, трохи було часу обмаль.
Неактивний
Ну, все правильно, питань ніт Всі рекомендації в силі. Конденсатори на живленні є, але на схемі не показані, правда? Ще непогано задіяти watchdog.
Так є. Не став заморочуватись
Ну, все правильно, питань ніт
Всі рекомендації в силі. Конденсатори на живленні є, але на схемі не показані, правда? Ще непогано задіяти watchdog.
Неактивний
Хттпс://arduino.stackexchange.com/questions/83616/turn-off-timer1-timer1-one-shot
Здається те що вам потрібно
Хттпс://arduino.stackexchange.com/questions/83616/turn-off-timer1-timer1-one-shot
Здається те що вам потрібно
Дякую! Корисна інформація.
Неактивний