Jump to content
pndbr

Конечный автомат.

Recommended Posts

Здравствуйте. Хочу разобраться с "конечным автоматом"

Думаю эта тема будет очень полезна для начинающих ,а для меня особенно)

Поморгать светодиодом,прочитать состояние с кнопки и вывести значение на индикатор могу.

Как дело касается более сложного алгоритма - там нужен (желателен)конечный автомат..а так как язык Си ,язык высокого уровня абстракции то весьма сложно применить чьи-то наработки,т.к каждый пишет по своему,а примеров по запросу Гугла не так много... попрошу вас выложить свои наработки в этом направлении,чтобы было больше примеров,а так же была возможность задать вопрос касательно кода.

P.s:Возникла необходимость отремонтировать мой старый автомобиль,схему заменяющую на реле я собрал. Но захотелось более технологичного решения на МК авр, попытавшись написать код,я зашёл в тупик,опытные участники подсказали что лучший вариант - конечный автомат. 

Спасибо за внимание, надеюсь на помощь.

Share this post


Link to post
Share on other sites
Posted (edited)

Тут всё просто. Допустим, есть хамелеон. Хамелеон в каждый момент времени может быть только одного цвета. Весь перечень цветов, в которые может окраситься хамелеон, мы заранее определили. Где-то в коде присваиваем ему цвет. А когда нам необходимо задать реакцию хамелеона на определённый цвет, пользуемся обычным switch ... case.Если реакция не перекликается с другими цветами, то в конце ставим break;, ежели перекликается - ничего не ставим и проваливаемся в следующий case. Ой... это уже учебник по программированию....

Edited by parovoZZ

Share this post


Link to post
Share on other sites
45 минут назад, pndbr сказал:

так как язык Си ,язык высокого уровня абстракции то весьма сложно применить чьи-то наработки

естественно. ну приведу пару примеров "тыц", "тыц" , как они вам помогут конкретно в вашем вопросе, никак.

я вам давал ссылки на лекции , там объясняется что такое графы/таблицы и как они работают.

у вас есть система , которая имеет конечное количество состояний , составляете таблицу всех состояний , потом вписываете какому состоянию соответствует какая комбинация нажатых/нажимаемых кнопок/датчиков или процессов.

а уже потом когда вы все это опишите ввиде таблицы/графов это элементарно переписывается на любом языке программирования

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

ЗЫ хотите помощи составляйте таблицу состояний , поможем с написанием кода. а так это обсуждение сферического коня в вакууме

ЗЫЫ @parovoZZ  :i-m_so_happy:

 

Share this post


Link to post
Share on other sites

Вебинар STM32G0 – новый лидер бюджетных 32-битных микроконтроллеров от STMicroelectronics

Компания Компэл приглашает вас 25 сентября принять участие в вебинаре, который посвящен новому семейству микроконтроллеров STM32G0. Вебинар рассчитан на технических специалистов и тех, кто хорошо знаком с семейством STM32. На вебинаре будут освоены современные методы тестирования производительности микроконтроллеров на примере самых бюджетных 32-битных семейств общего назначения STM32G0 и STM32F0 и проведено их подробное сравнение.

Подробнее

Posted (edited)
3 часа назад, IMXO сказал:

 

ЗЫ хотите помощи составляйте таблицу состояний , поможем с написанием кода. а так это обсуждение сферического коня в вакууме

ЗЫЫ @parovoZZ  :i-m_so_happy:

 

еще раз спасибо

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

Не рассмотрел варианты ошибок на следящем устройстве.

Устройство представляет собой дпт с следящим устройством(4 канала).

у устройства есть 3 рабочих состояния  2H 4H 4L

Устройство управляется 3 -мя кнопками, 2 - с фиксацией but4h but4l

и одной кнопкой без фиксации - сбрасывающей эти кнопки  .

Также контакт contro контролирующий любой переход с режима и на режим 4L.

but4h определение нажатия 4н

 but4l  определения нажатия  4l

flag4h флаг режима 4н

flag4l  флаг режима 4l

control любой  переход связанный с режимом 4l проходит через control

таблица 1(опрос режима и кнопок)

режим           but4h      |      but4l      |      flag4h       |      flag4l        |      control            |      действие

  2h                0             |        0            |         0              |        0                |         -                 |        опрос кнопок                              

 2h                 0              |         0           |         1             |         0               |          -                |        4H->2H

 2h                 0               |        0           |          0             |           1             |           1               |     4L->2H

2h                    0               |          0         |          0               |          1             |           0                |  вывод сообщения об ошибке - опрос кнопок

 

4h                 1               |        0            |         1              |        0                |         -                 |   опрос кнопок

4h               1              |        0            |         0              |        1                |         1                 |   4L->4H

4h               1            |        0            |         0                 |        1               |         0                  | вывод сообщения об ошибке - опрос кнопок

4h              1               |        0            |         0              |        0                |         -                  |     2H->4H

 

4l                0            |        1           |         0              |        0                |         0                |   вывод сообщения об ошибке - опрос кнопок

4l                0             |        1            |         0              |        0                |         1             | 2H->4L

4l                 0             |        1            |         1           |        0                |         0              |   вывод сообщения об ошибке -  опрос кнопок

4l               0               |        1            |         1              |        0                |       1             |   4H->4L

4l               0                |        1            |         0              |        1                |        -          |   вывод сообщения об ошибке - опрос кнопок

 

err              1             |        1            |                                                                             | опрос кнопок

 

Таблица 2 (состояний)

contr2 contr3 contr4 contr 5 - контакты следящего устройства режимов работы.

                  contr2            contr3             contr4           contr 5 

2h               0                          1                         0                       1

4h               1                            1                        0                        1

4l                  0                             0                         1                      1

 

таблица3 (переходов(без учета ошибок) )

RIGHT - крутим вправо

LEFT - крутим влево

start_contr2345  начальное положение

test_contr2345  предварительное  положение

 fin_contr2345  конечное положение

tictok() задержка перед остановкой вращения 

            RIGHT | LEFT | start_contr2345 | test_contr2345 | tictoc | fin_contr2 | flag4h | flag4l| 

2H-4H    1       |  0      |  0101                        |   1101                  | 500    |        1100      |         1     |     0      |

  2H-4L   1      |  0      |        0101                     |    0011              | 100     |           0011      |   0            |      1    |

4H-2H     0      | 1      |    1100                          |   1101               |100      |            0101       |0                |    0     |

4H-4L      1     |     0   |    1100                           |    0011             |100     |             0011       |0                |     1    |

4L-2H      0     |     1  |      0011                            |  1101             | 100       |           0101        |0               |       0  |

4l-4h         0       | 1   |    0011                                |  1110          | 500 *   |             1100          | 1               |      0      |

 

Задержка при переходах на 4H обусловлена конструктивными особенностями режима 4Н (будет корректироваться на месте)

 

график переходов состояний следящего устройства  при вращении RIGHT

 0101(2H) ->1101->1001->1101->1100(4H)->1100->0110->0111->0110->0111->0110->0011(4L)

Положения  0101(2H) и 0011(4L) являются крайними и двигатель дальше не крутит.

 

Таблицы получились не к черту,но хотябы свои наработки изложил..и самому стало яснее)

 

 

Цитата

Тут всё просто. Допустим, есть хамелеон. Хамелеон в каждый момент времени может быть только одного цвета. Весь перечень цветов, в которые может окраситься хамелеон, мы заранее определили. Где-то в коде присваиваем ему цвет. А когда нам необходимо задать реакцию хамелеона на определённый цвет, пользуемся обычным switch ... case.Если реакция не перекликается с другими цветами, то в конце ставим break;, ежели перекликается - ничего не ставим и проваливаемся в следующий case. Ой... это уже учебник по программированию....

Спасибо и Вам  @parovoZZ

Но тут я добавил еще зависимость положения лап от цвета,и в зависимости от положения лап он не всегда может окраситься в нужный цвет.А только при определенном положении лап он может стать зеленым,красным или синим. А еще если он нарушит последовательность движения лапами(сделает лишний шаг) он не превратится из зеленого в красного,из красного в синего и . т .д.

вот это и  основная сложность,как лаконично и ясно решить эту задачу, знаний у меня не много,но научится хочется)

Edited by pndbr

Share this post


Link to post
Share on other sites

честно говоря вы ничего не изложили...

в таблицах ерунда какая-то написана , как может осуществятся переход 4H->2H или  4L->2H , если устройство уже находится в режиме 2H ????

опроса кнопок вообще не должно быть в режимах это процесс происходящий параллельно режимам

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

Share this post


Link to post
Share on other sites
                     

Построение оптимального преобразователя мощности

Управляющие контроллеры, драйверы и МОП-транзисторы являются важнейшими элементами для инверторов и импульсных источников питания. Проектирование современных импульсных преобразователей, таких как импульсные источники питания (SMPS), DC/DC-преобразователи, приводы промышленных двигателей и инверторы солнечных батарей, необходимо выполнять с учетом целого ряда факторов. Существуют коммерческие, законодательные и экологические требования, направленные на повышение эффективности, снижение потерь, уменьшение эксплуатационных расходов, минимизацию потребления энергии. Кроме того, пользователи хотят видеть постоянное повышение эффективности без какого-либо увеличения габаритов и необходимости принятия дополнительных мер для защиты как элементов схемы, так и самих пользователей.

Подробнее...

 

8 часов назад, IMXO сказал:

честно говоря вы ничего не изложили...

Провел работу над ошибками

Пока снова много ерунды не написал,напишу часть..1.jpg.53d29e1f8fcbee35979fcab073841b99.jpg

так правильнее?

Share this post


Link to post
Share on other sites

@pndbr , послушайте моего совета: если у вас нет базовой подготовки в области программирорования, и вы с нуля хотите освоить микроконтроллеры и написать первую свою полезную программу, на начинайте с конечных автоматов. Это студентов хорошо учить с этих "азов", а для практикующего новичка это мрак и немцы под Полтавой.

Нарисуйте просто алгоритм программы и, при помощи эквивалентов графических примитивов из языка Си, просто опишите его на Си. Возможно, проштудируйте систему прерываний - может пригодиться. И для начала все будет работать и вас радовать. А потом займетесь "наворотами".

Share this post


Link to post
Share on other sites
5 часов назад, pndbr сказал:

так правильнее? 

правильней - нет, понятней - да.в конечном автомате номер режима определяется состоянием выходов.

смотрим, у вас в 1,2,3,7,8 и 11 одно и тоже состояние выходов. почему?

или вы что-то не так описываете или это один и тот же режим.

и расшифруйте сокращения. 

Share this post


Link to post
Share on other sites
29.07.2019 в 17:09, IMXO сказал:

 

Здравствуйте.

Записал все возможные комбинации в массив(кнопки и считывающий энкодер)

Скрытый текст

pos[] = PINC

unsigned double pos[60] =

{
    0b11010111,0b10010111,0b11010110,0b10010110,0b11010101,0b10010101,0b11010011,0b10010011,0b11010010,0b10010010,
    0b11010001,0b10010001,0b11011011,0b10011011,0b11011010,0b10011010,0b11011001,0b10011001,0b11010011,0b10010011,
    0b11010010,0b10010010,0b11010001,0b10010001,0b11010011,0b10010011,0b11010010,0b10010010,0b11010001,0b10010001,
    0b11110011,0b10110011,0b11110010,0b10110010,0b11110001,0b10110001,0b11100011,0b10100011,0b11100010,0b10100010,
    0b11100001,0b10100001,0b11100111,0b10100111,0b11100110,0b10100110,0b11100101,0b10100101,0b11000111,0b10000111,
    0b11000110,0b10000110,0b11000101,0b10000101,0b11001111,0b10001111,0b11001110,0b10001110,0b11001101,0b10001101
};

при состояниях будут  выполняться ф-ии

при положениях

1.2 -2h()
3.4.9.10.15.16.21.22.27.28-leftto4h()
6.12.18.24.30.36.42.48.54-leftto4l()
7.8.13.14.19.20.25.26.31.32.37.38.44.50.56-rightto2h()
39.40.46.52.58-rightto4h()
59.60 - 4l()
33.34 - 4h()

при остальных error()

подскажите пожалуйста как это можно красиво завернуть в код...с моими недознаниями получается ужас из кучи switch case или if else-ов

спасибо

 

29.07.2019 в 10:39, ARV сказал:

@pndbr , послушайте моего совета: если у вас нет базовой подготовки в области программирорования, и вы с нуля хотите освоить микроконтроллеры и написать первую свою полезную программу, на начинайте с конечных автоматов. Это студентов хорошо учить с этих "азов", а для практикующего новичка это мрак и немцы под Полтавой.

Нарисуйте просто алгоритм программы и, при помощи эквивалентов графических примитивов из языка Си, просто опишите его на Си. Возможно, проштудируйте систему прерываний - может пригодиться. И для начала все будет работать и вас радовать. А потом займетесь "наворотами".

спасибо и вам за ответ.

Но 4 сигнала с энкодера + 2 кнопки + контрольный сигнал 

и возможными 60 (даже больше,не все возможные ошибки пока учел)комбинациями разрастаются в страшную мешанину  в моих руках

Share this post


Link to post
Share on other sites
Только что, pndbr сказал:

Но 4 сигнала с энкодера + 2 кнопки + контрольный сигнал 

и возможными 60 (даже больше,не все возможные ошибки пока учел)комбинациями разрастаются в страшную мешанину  в моих руках

И вы считаете, что конечный автомат на 60 с хвостиком состояний у вас получится лучше?! Прикиньте хотя бы на глазок количество разрешенных ПЕРЕХОДОВ меду этими состояниями, чтобы оценить масштаб беды. А ведь еще могут быть запретные переходы, которые тоже надо обрабатывать и которых может оказаться гораздо больше...

Я продолжаю настаивать на своём мнении ради вашего же блага.

Share this post


Link to post
Share on other sites
23.08.2019 в 16:12, ARV сказал:

Я продолжаю настаивать на своём мнении ради вашего же блага.

Спасибо за совет, прислушался я к Вам и накидал простыню кода.

Скрытый текст

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/tick.h>
#define F_CPU 8000000UL
#define  CTRL 7   //контроль ручник
#define RIGHT (1<<PB0)//крутим вправо
#define LEFT  (1<<PB1)//крутив влево
#define SW4H  (1<<PB2)//индикатор 4н
#define SW4L  (1<<PB3)//индикатор 4л
#define ERROR (1<<PB4)//индикатор ошибки
volatile unsigned char but2H = 0 ;//флаг 2н
volatile unsigned char but4H = 0 ;//флаг 4н
volatile unsigned char but4L = 0 ;//флаг 4л
uint16_t t0_ctr;
uint16_t t_ms;  //задержка
uint32_t t_sec32;
uint8_t pin_state;
uint8_t enc_state = 0b00000000; //состояние энкодера
uint8_t btn_state = 0b00000000; //состояние кнопок
uint8_t enc = 0;//переменная энкодера
uint16_t tbut = 0;//время опроса кнопок
uint16_t tmot = 0;//время кручения мотора
uint8_t errorswl = 0;//ошибка вращения влево
uint8_t errorswr = 0;//ошибка вращения вправо

uint16_t tbutctr = 0;//антидребезг кнопок
uint16_t tenc = 0;//опрос энкодера

static volatile uint8_t ovf_ctr;

ISR(TIMER0_OVF_vect)
{
	ovf_ctr++;
}
void t0_update()  //ф-ии задержки
{
	uint8_t ctr_high, ctr_low;
	static uint16_t last_ms, last_sec;
	
	do {
		ctr_high = ovf_ctr;
		ctr_low = TCNT0;
	} while((TIFR & (1<<TOV0)) || (ovf_ctr != ctr_high));
	t0_ctr = ctr_low | (ctr_high << 8);
	
	while(t0_ctr - last_ms >= T0_MS(1))
	{
		t_ms++;
		last_ms += T0_MS(1);

		if(t_ms - last_sec >= 1000)
		{
			t_sec32++;
			last_sec += 1000;
		}
	}
}
void t0_init()//инициализация таймера для задержки
{
	TCCR0 = T0_PRESC;      /* запустить счёт */
	TIMSK |= 1<<TOIE0;      /* разрешить прерывание по переполнению */
}
void t2h()
{
	PORTB|=(SW4H|SW4L|RIGHT|ERROR);
	errorswr=0;
}
void t4h()
{
	PORTB&=~SW4H ;
	PORTB|=(LEFT|SW4L|ERROR);
	errorswr=0;
	errorswl=0;
}
void t4l()
{
	PORTB&=~SW4L;
	PORTB|=(LEFT|SW4H|ERROR);
	errorswl=0;
}
void toright2h()//двигаем вправо с 4н до 2н
{
	if(errorswr<=3)
	{
		do
		{
			PORTB&=~RIGHT;
			tmot=t_ms;
		}
		while ((((int16_t)(t_ms - tmot) >= 2000)) || (enc==1));//положение энкодера 1 или крутим дольше 2с
		PORTB|=RIGHT;
		if (enc==1)
		{
			t2h();
		}
		else
		{
			PORTB&=~ERROR;
			errorswr++;
		}
	}
	else PORTB&=~ERROR;
	
}
void toright2hl()//двигаем с 4л до 2н
{
	if (0==(PIND&(1<<CTRL))&&(errorswr<=3))//контроль ручника
	{
		do
		{
			PORTB&=~RIGHT;
			tmot=t_ms;
		}
		while ((((int16_t)(t_ms - tmot) >= 2000))&&(enc==1));
		PORTB|=LEFT;
		if (enc==1)
		{
			t2h();
		}
		else
		{
			PORTB&=~ERROR;
			errorswr++;
		}

	}

	else
	{
		PORTB&=~ERROR;
	}
}
void  toleft4l()//крутим влево до 4л
{
	if (0==(PIND&(1<<CTRL))&&(errorswl<=3))//контроль ручника
	{
		do
		{
			PORTB&=~LEFT;
			tmot=t_ms;
		}
		while ((((int16_t)(t_ms - tmot) >= 2000))||(enc==8));//
		PORTB|=LEFT;
		if (enc==8)
		{
			t4l();
		}
		else
		{
			PORTB&=~ERROR;
			errorswl++;
		}

	}
}
void toleft4h()
{
	if(errorswl<=3)
	{
		do
		{
			PORTB&=~LEFT;
			tbut=t_ms;
		}
		while ((((int16_t)(t_ms - tmot) >= 2000))||(enc==4));
		PORTB|=LEFT;
		if (enc==4)
		{
			t4h();
		}
		else
		{
			PORTB&=~ERROR;
			errorswl++;
		}
	}
	else
	{
		PORTB&=~ERROR;
	}
	
}
void toright4h()
{
	if (0==(PIND&(1<<CTRL))&&(errorswr<=3))
	{
		do
		{
			PORTB&=~RIGHT;
			tbut=t_ms;
		}
		while ((((int16_t)(t_ms - tmot) >= 2000))||(enc==4));
		PORTB|=RIGHT;
		if (enc==4)
		{
			t4h();
		}
		else
		{
			PORTB&=~ERROR;
			errorswr++;
		}
	}
	else
	{
		PORTB&=~ERROR;
	}
}
void enc_state_f()//опрос энкодера каждые 50мс
{
	tenc = t_ms;
	while(((int16_t)(t_ms - tenc) >= 0 ))
	{
		tenc+=T0_MS(50);
		enc=0;
		
		pin_state=PIND ;

		enc_state = pin_state & 0b00111100 ;//маска 2345 битов энкодера
		
		if(enc_state==0x14)  enc=1 ; //2h  0х14 0b00010100
		if(enc_state==0x10)  enc=2 ; //     0х10 0b00010000
		if(enc_state==0x18)  enc=3 ;//     0х18 0b00011000
		if(enc_state==0x30)  enc=4 ;//4h   0х30 0b00110000
		if(enc_state==0x20)  enc=5 ;//     0х20 0b00100000
		if(enc_state==0x24)  enc=6 ;//     0х24 0b00100100
		if(enc_state==0x04)  enc=7 ;//     0х04 0b00000100
		if(enc_state==0x0C)  enc=8 ;//4l   0х0С 0b00001100
		if(enc==0)  PORTB &=~ ERROR;
		
	}
	
}
void btn_state_f() //опрос кнопок каждую секунду
{
	tbutctr = t_ms;
	while(((int16_t)(t_ms - tbutctr) >= 0 ))
	{
		tbutctr+=T0_SEC(1);

		btn_state = PIND & 0b00000011 ;


		if ((btn_state & 0b00000011) == 0b00000010 ) //4h
		{
			tbut = t_ms;
			while(((int16_t)(t_ms - tbut) >= 0 ))//антидребезг
			{
				tbut+=T0_MS(150);
				if ((((btn_state & 0b00000011 ) == 0b00000010 )))
				{
					but4H = 1;
					but4L = 0;
					but2H = 0;
				}
				else
				{
					but4H = 0;
				}
			}
		}
		if ((btn_state & 0b00000011 )== 0b00000001 )//4l
		{
			tbut = t_ms;
			while(((int16_t)(t_ms - tbut) >= 0 ))
			{
				tbut+=T0_MS(150);
				if(((btn_state & 0b00000011 ) == 0b00000001 ))
				{
					but4L = 1;
					but4H = 0;
					but2H = 0;
				}
				else
				{
					but4L = 0;
				}
			}
		}
		if ((btn_state & 0b00000011)==0b00000011) //2h
		{
			tbut = t_ms;
			while(((int16_t)(t_ms - tbut) >= 0 ))
			{
				tbut+=T0_MS(150);
				if(((btn_state & 0b00000011)==0b00000011))
				{
					but2H = 1;
					but4L = 0;
					but4H = 0;
				}
				
				else
				
				{
					but2H = 0;
				}
			}
		}
	}
}
void swto4hnew()//
{
	switch (enc)
	{
		case 1: toleft4h()	; break;
		case 2: toleft4h()	; break;
		case 3: toleft4h()	; break;
		case 4: t4h() ; break;
		case 5: toright4h()	; break;
		case 6: toright4h()	; break;
		case 7: toright4h()	; break;
		case 8: toright4h()	; break;
		default: PORTB &=~ ERROR;
	}
}
void swto4lnew()
{
	switch (enc)
	{
		case 1: toleft4l()	; break;
		case 2: toleft4l()	; break;
		case 3: toleft4l()	; break;
		case 4: toleft4l()  ; break;
		case 5: toleft4l()	; break;
		case 6: toleft4l()	; break;
		case 7: toleft4l()	; break;
		case 8: t4l()        ; break;
		default: PORTB &=~ ERROR;
	}
}
void swto2hnew()
{
	switch (enc)
	{
		case 1: t2h()	; break;
		case 2: toright2h()	; break;
		case 3: toright2h()	; break;
		case 4: toright2h()   ; break;
		case 5: toright2hl()	; break;
		case 6: toright2hl()	; break;
		case 7: toright2hl()	; break;
		case 8: toright2hl()	; break;
		default: PORTB &=~ ERROR;
	}
}
void change()//главная ф-ия
{
	if (but2H==1) swto2hnew();
	if (but4H==1) swto4hnew();
	if (but4L==1) swto4lnew();
}

int main()
{
	DDRD = 0b00000000;
	DDRB = 0b11111111;
	PORTB = 0b11111111;
	PORTD = 0b11111111;
	t0_init();
	sei();
	while (1)
	{
		t0_update();
		enc_state_f();
		btn_state_f();
		change();
	}
}

 

в симуляторе студии работает,сегодня попробую потестить в железе

 

Share this post


Link to post
Share on other sites

По простыне кода ничего сказать не могу... Если оно работает, это уже успех.

Конкретные рекомендации от меня могут последовать только в том случае, если я буду понимать общий алгоритм устройства. В целом же у вас пока просматривается не реализация алгоритма системы управления (по большому счету почти все самоделки могут быть отнесены к категории таких систем), а довольно хаодтическое нагромождение функций, просто замещающих куски еще более хаодитческого когда. То есть разделение на функции у вас носит скорее косметический характер, нежели, собственно, алгоритмический (если позволите так выразиться). Я, конечно, могу и ошибаться... но вот так мне показалось

По-крупному любая система управления, взаимодействующая с человеком, содержит несколько основных элементов: система индикации, система взаимодействия с управляемым и/или контролируемым устройством, система взаимодействия с пользователем. Связаны эти системы между собой потоком управляющих сигналов (мне больше нравится термин - событий). При этом главный цикл выглядит в общем случае как-то так:

while(1){
	display(); // выводим индикацию
	event = get_event(); // запрашиваем событие, которое могло произойти
	// обработка события
	switch(event){
    	case EV_BUTTON: // нажата кнопка
    		break;
    	case EV_ENCODER: // повернулся енкодер
    		break;
    	case EV_DATCHIK: // на что-то среагировал какой-то датчик
    		break;
    	default:
    		// ничего не происходило
    		break;
    }
}

Само собой, вместо break должна быть какая-то полезная работа. И, кстати, на эту концепцию отлично накладывается концепция конечного автомата, только автомата не по состояниям внешних линий, а автомата по состояниям программы управления. Например, если в обработчике EV_BUTTON получен код кнопки "Стоп", можно активировать состояние "Стоп", в котором тот же обработчик кнопок будет реагировать на другие кнопки по-другому, дисплей будет отображать иначе, и сигналы датчика будут игнорироваться. В этом случае вполне допустимо завести переменную внутреннего состояния state и передавать её во все функции, зависящие от состояния, например, так:

static STATE state = ST_DEFAULT;
while(1){
	display(state); // выводим индикацию
	event = get_event(state); // запрашиваем событие, которое могло произойти
	// обработка события
	switch(event){
    	case EV_BUTTON: // нажата кнопка
        	switch(get_button(event)){
            		case KEY_STOP: state = ST_STOP; break;
            		case KEY_RUN: state = ST_RUN; break;
        	}
    		break;
    	case EV_ENCODER: // повернулся енкодер
    		break;
    	case EV_DATCHIK: // на что-то среагировал какой-то датчик
    		break;
    	default:
    		// ничего не происходило
    		break;
    }
}

У вас же пока что от концептуального подхода в проектировании нет ничего.

Я пытался как-то систематизировать предлагаемый мной подход, и написал статью... Но сейчас статья имеет непрезентабельный вид, хотя смысл её не пострадал (хозяин сайта сменил движок и врезки кода "поплыли" в сторону безобразия).

Share this post


Link to post
Share on other sites
5 часов назад, ARV сказал:

. То есть разделение на функции у вас носит скорее косметический характер, нежели, собственно, алгоритмический (если позволите так выразиться). Я, конечно, могу и ошибаться... но вот так мне показалось

Вам не показалось, многое я убрал в отдельные ф-ии для того чтобы удобнее было воспринимать код(недокод). И это почти первый мой код,и концептуальному подходу тут,пока неоткуда взяться.

За этим я и обратился на форум,чтобы подпинывали в нужном направлении)

Устройство имеет 3 кнопки выбора режима,2 с фиксацией(4н 4l) и одна сбрасывающая любую из них в режим (2h).

Имеется привод вращающий исполнительный механизм от упора до упора влево и вправо. На этом механизме установлен энкодер на котором во время вращения есть 8 состояний. 3 из них соответствуют положениям кнопок 1- это режим 2н(первое крайнее) когда кнопки не нажаты или сброшены(состояние энк 1),и 4н и 4л(второе крайнее соответствующее енк 8). Из положения 2н мы можем перейти 4н и 4л(при условии срабатывания контакта кнтр) из 4н в 2н и 4л(при кнтр),из 4л мы можем перейти в 2н и 4н только при  срабатывании контакта "кнтр". При срабатывании режимов 4н и 4л загораются соответствующие индикаторы .

 

В выше написанной простыни я сначала опрашиваю текущее состояние энкодера каждые 50 мс по спец функции,дабы  уйти от delay и записываю состояние чз маску и даю им значения от 1 до 8,потом опрашиваю кнопки 4н и 4л каждую секунду с антидребезгом в 150 мс,после исходя из текущего состояния  энкодера и кнопок вращаю двигатель влево или вправо с 3 мя этапами контроля:

1- это контроль вращения не дольше 2-секунд(чтобы не сжечь в крайнем положении двигатель)

2- это контроль состояния режима энкодера соответствующего кнопке.

3- контроль контакта  "кнтр"(дабы переключать только в безопасных режимах)

Так же добавил аккумулятор ошибки,при ошибке переходов больше или равное 3 двигатель вращать перестаём,дабы не сжечь.

 

В итоге в бесконечном цикле я опрашиваю состояние энкодера с частотой 50 мс и стояние кнопок каждую секунду и исходя из этих данных кручу двигатель в нужную сторону и зажигаю  соответствующий режиму светодиод.

 

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

Спасибо

 

Share this post


Link to post
Share on other sites
18 часов назад, pndbr сказал:

На этом механизме установлен энкодер на котором во время вращения есть 8 состояний.

Проблемы программирования начинаются с того что у вас очень туманное представление о том что ваша машина должна делать и о критериях контроля этих действий.

Вот если бы вы хотя бы попытались перечислить эти 8 состояний и их описание, вы бы перешли на новый уровень понимания вашей задачи. Из ваших пояснений можно догадаться что это(состояния) как то связано с позицией (двигателя?) и его направлением движения, так вот эта связь должна быть математически точно зафиксирована с помощью математических формул!

Share this post


Link to post
Share on other sites

Добавлю к только что сказанному @ruhi : "состояние" может быть разным при одном и том же, все зависит от степени детализации и направления взгляда на проблему. Если смотреть на систему, как на черный ящик с N входами и M выходами, состоянием надо называть каждую уникальную комбинацию [N,M]. Если же смотреть внутрь этого ящика, то вполне могут появиться состояния "ожидание включения", "вычисление скорости", "перерегулирование", "аварийное состояние" и т.п.

Согласитесь, что второе намного понятнее и "охватнее" умом, нежели первое...

Share this post


Link to post
Share on other sites

да там из такой словесной каши вообще ничего не понять.

что это за режимы и чем они характеризуются (чем отличаются)?

почему режимы и кнопки имеют одинаковые названия?

что или кто нажимает эти кнопки, и где стоят эти кнопки?

то же самое про контакт  "кнтр" - где он стоит и что его нажимает?

нужна кинематическая схема устройства или подробное однозначное словесное описание устройства.

а так ни из одного поста автора ровным счетом ни хера не понятно...

и еще.

 если двигатель (механизм) дошел до упора, то отключать двигатель нужно моментально. а то двух секунд вполне может хватить, чтобы двигатель сгорел.

Share this post


Link to post
Share on other sites
17 часов назад, Starichok сказал:

нужна кинематическая схема устройства или подробное однозначное словесное описание устройства.

Вот! Это по существу! Но, к сожалению, обычно люди предпочитают рассуждать о каких то абстрактных "конечных автоматах", "состояниях", "направлениях взгляда на проблему", ...

о чем угодно, только не об условиях реальной задачи :( !

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения

    • возможно - у меня мало опыта - но как понял они слабое звено в цепи - может ошибаюсь - с учетом не большого опыта - чем лучше сделать условия работы ключей - меньше проблем - в схеме на ир2153 - я применил - с подсказки Сергея диоды на разряд - резисторы между затвором -истоком - результат - практически не греются и даже радиатор на них не ставил - здесь ес все в конечном итоге выйдет с основной схемой шим и зашитой- норм - что предложил - почему-бы не сделать работу ключей более комфортной.имхо
    • Много раз видел такие сообщения от других, про доп диоды, но не разу не встречал пробитые диоды у собственных транзисторов и никогда доп диоды не ставил и в сварочниках да же не видел такого, так что это миф о доп диодах)
    • Клиенту безграмотному я начну с 10-20 у.е. за страницу текста А4 .... и никак иначе ... А пока тебе ответят КНИГИ и ГУГЛЬ, которые ты даже не открывал, но возомнил себя супер-пупер программером, который безотказен для друзей .... Я таких всегда спрашиваю - А если друг уже без девочки пол-года и попросит тебя .... Тоже "возмешь" - ся
    • Делать линейный блок питания с такими характеристиками на микросхемах затруднительно. Слишком уж большие напряжения. Поэтому проще нарисовать схему на дискретных элементах. Расчетные параметры следующие. Выходное напряжение от 13в до 34в и выше. Устанавливается R17R18. Номинальное сопротивление нагрузки 14,45ом. Выходной ток номинальный 2,35А. Выходной ток в режиме ограничения не менее 3,0А. Задается R8. Выходной ток короткого замыкания около 0,2А. Порог распознавания напряжения короткого замыкания не менее 2 вольт. Задается резистором R9. Порог распознавания сопротивления короткого замыкания не менее 1,5ом. Задается резистором R9. Размах пульсаций выходного напряжения от пика до пика около 95мкв. Просадка напряжения при изменении выходного тока от 0А до 2,35А около 1,8мв. Выходное сопротивление около 0,00077ом или 0,77мОм. При изменении входного напряжения от 41в до 91в выходное напряжение изменяется примерно на 6мв (коэффициент стабилизации по напряжению около 4396). Температурный дрейф выходного напряжения около минус 2мв/°C. Минимальное статическое падение напряжения между входом и выходом 3,1в. Минимальное динамическое падение напряжения между входом и выходом 2,14в. 00_Bp_30v_80w_Расчетная_модель.pdf BP_34V_80W_Оригиналы_рисунков.zip    
    • @rocker60 , где и кто тут говорил про деление уровня сигнала с генератора?
    • спасибо, но ведь у вас источник 12 вольт, будет эта схема работать на 5 вольтах?
    • Я не знаю, как кто, я подаю на вход сигнал без всяких делителей! Зачем сигнал 250 mV делить на 10. На универсальный вход поступит 25 mV.  Во всех инструкциях и Service Manual как на отечественные, так и на импортные УНЧ и ресиверы вход AUX -250 mV. При таком уровне сигнала и надо проверять УНЧ. Грамотная проверка сигналом прямоугольной формы описана выше
×
×
  • Create New...