Форум РадиоКот https://radiokot.ru/forum/ |
|
Посоветуйте алгоритм https://radiokot.ru/forum/viewtopic.php?f=20&t=75785 |
Страница 1 из 1 |
Автор: | ukr823f [ Сб июл 21, 2012 09:19:53 ] |
Заголовок сообщения: | Посоветуйте алгоритм |
Товарищи, нужна ваша помощь. Уже второй день бьюсь над проблемой Вобщем устройство - кнопка старт\стоп для двигателя. Алгоритм -один раз нажали включилось ACC -второй раз включилось зажигание -третий раз всё выключилось -если на любом этапе и нажат сцеплеие то включается стартер Так вот никак невыходит описать алгоритм включения кнопки. Нужно как то переводить состояние кнопки из одного в другое. Кнопка если первое нажатие отрабатывает нормально, то дальше второе может не отработать, а может отработать и на этом остановиться. Кнопка подключена к выводу PINB.0 . Когда она нажата - у нас логический ноль. Товарищи, может поможете новичку с кодом, а то уже аж руки опускаются.... Код: /*****************************************************
This program was produced by the CodeWizardAVR V2.05.0 Professional Automatic Program Generator © Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Version : Date : 20.07.2012 Author : Company : Comments: Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 4,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega8.h> #include <delay.h> // Timer1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) { // Place your code here } #define ADC_VREF_TYPE 0x40 // ADC interrupt service routine interrupt [ADC_INT] void adc_isr(void) { unsigned int adc_data; // Read the AD conversion result adc_data=ADCW; // Place your code here } // Declare your global variables here int time; // переменная для отсчёта времени unsigned char OFF; unsigned char ACC; unsigned char ING; unsigned char STARTER; unsigned char status; unsigned char rejim_avtomat; // Состояние режима запуска авто unsigned char rejim_ruchnoy; // Сосстояние режима запуска авто void _OFF (void) { PIND.0=0; PIND.1=0; PIND.2=0; } void _ACC (void) { PIND.0=0; PIND.1=0; PIND.2=1; } void _IGN (void) { PIND.0=0; PIND.1=1; PIND.2=1; } void _STARTER (void) { PIND.0=1; PIND.1=1; PIND.2=1; } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P //ПОРТ B - все пины входы //PIN0 - СТАРТ/СТОП кнопка. Нжата ПИН = 0, брошена, ПИН =1 //PIN1 - //PIN2 - //PIN3 - концевик педали сцепления (сцепление выжато ПИН = 1, сцепление брошено ПИН=0 //PIN4 - лампа заряда АКБ (машина заглушена ПИН = 0, машина заведена ПИН = 1 //PIN5 - Сигнал ЭБУ отключения стартера (Стартер крути ПИН = 1, стартер отключить - ПИН=0 //PIN6 - PORTB=0xFF; DDRB=0x00; // Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00; // Port D initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 //ПОРТ D - все пины выходы //PIN0 - Выход на реле стартера //PIN1 - выход на реле зажигания //PIN2 - Выход на реле ACC //PIN3 - //PIN4 - //PIN5 - //PIN6 - PORTD=0x00; DDRD=0xFF; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 3,906 kHz // Mode: CTC top=OCR1A // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x0D; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x0F; OCR1AL=0x42; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer2 Stopped // Mode: Normal top=0xFF // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off MCUCR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x10; // USART initialization // USART disabled UCSRB=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; // ADC initialization // ADC Clock frequency: 31,250 kHz // ADC Voltage Reference: AVCC pin ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0x8F; // SPI initialization // SPI disabled SPCR=0x00; // TWI initialization // TWI disabled TWCR=0x00; // Global enable interrupts #asm("sei") while (1) { if (PINB.0==0) { delay_ms(50); if (PINB.0==1) { if(status==0) { _ACC(); status=1; } else if(status==1) { _IGN(); status=2; } else if(status==2) { _OFF(); status=0; } } } |
Автор: | zero648 [ Сб июл 21, 2012 10:04:49 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Да, собственно алгоритм простой: 1 - организуем переменную - счетчик нажатий кнопки; 2 - при первом нажатии проверяем счетчик, если он равен "0", то инкрементируем счетчик, ставим ловушку, если кнопка нажата, то возвращаемся на опрос состояния кнопки, если кнопка отжата, то проскакиваем ловушку, и после ловушки выдерживаем некоторую паузу, чтобы исключить дребезг, проверяем счетчик, если "1", то выполняем необходимые действия для включения АСС; 3 - при втором нажатии проверяем счетчик, если он равен "1", то инкрементируем счетчик, ... , проверяем счетчик, если "2", то выполняем необходимые действия для включения зажигания; 4 - при третьем нажатии проверяем счетчик, если он равен "2", то инкрементируем счетчик, ... , проверяем счетчик, если "3", то выполняем необходимые действия для выключения питания, обнуляем счетчик; и т.д. На счет сцепления не понятно, что значит на любом этапе? а если на скорости стоит? нужно тогда отслеживать и сцепление и нейтраль. Можно, конечно в этой же переменной включать бит - флаг нажатого сцепления, и проверять нажатие кнопки маскируя этот бит. |
Автор: | ukr823f [ Сб июл 21, 2012 10:19:35 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
так если на скорости стоит то как раз при выжатом сцеплении только и заведётся.. |
Автор: | zero648 [ Сб июл 21, 2012 11:12:57 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Тогда проверять флаг выжатого сцепления при счетчике равном "2", т.е. когда кнопка нажата второй раз, в этот момент и проверять сцепление, в других случаях наверно не стоит. |
Автор: | ukr823f [ Сб июл 21, 2012 12:59:23 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
вот пытался написать, но так вообще ничего не выходит Я и понимаю что алгоритм простой, но что то ну никак невыходит он у меня Код: // Global enable interrupts
#asm("sei") while (1) { if (PINB.0==0) // если нажата кновпка { if (status==0) // проверяем в каком положении наш счётчик { status++; // инкрементируем статус в первое положение if (PINB.0==0) // проверяем, если кнопка до сих пор нажата { while (PINB.0==0) //заходим в замкнутый цикл { } } else // иначе, если кнопка выходит что отжата { if (status==1) // проверяем статус,если равен 1 { _ACC(); // включаем acc } } } |
Автор: | ukr823f [ Сб июл 21, 2012 13:31:24 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Вот ещё один вариант попробовал написать. Но в протеусе видно что нажал раз на кнопку, на выводе начинается моргание (вывод как всетомузыка работает) и дальше сколько не нажимай - ничего не происходит. Где я ошибаюсь??? Код: // Global enable interrupts
#asm("sei") while (1) { if (PINB.0==0) // если нажата кновпка { delay_ms(100); if (PINB.0==0) // если нажата кновпка { if (status==0) // проверяем в каком положении наш счётчик { status=+1; // инкрементируем статус в первое положение while (PINB.0==0) {} //ждём отжатия кнопки } else if (status==1) // проверяем в каком положении наш счётчик { status=+1; // инкрементируем статус в первое положение while (PINB.0==0) {} //ждём отжатия кнопки } else if (status==2) // проверяем в каком положении наш счётчик { status=+1; // инкрементируем статус в первое положение while (PINB.0==0) {} //ждём отжатия кнопки } else if (status==3) // проверяем в каком положении наш счётчик { status=0; // инкрементируем статус в первое положение while (PINB.0==0) {} //ждём отжатия кнопки } } } if (status==0) { _OFF(); } else if (status==1) { _ACC(); } else if (status==2) { _IGN(); } else if (status==3) { _STARTER(); } } } |
Автор: | zero648 [ Сб июл 21, 2012 13:47:29 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Думаю, лучше убрать первую проверку счетчика, а просто тупо его увеличивать, а потом когда он будет "3" обнулить его. Както вот так должно быть, синтаксис исправь если чё, просто на си не пишу, поэтому примерно накидал. Код: // Global enable interrupts
#asm("sei") while (1) { if (PINB.0==0) // если нажата кновпка {status++; if (PINB.0==0) // проверяем, если кнопка до сих пор нажата {while (PINB.0==0){}} //заходим в замкнутый цикл else // иначе, если кнопка выходит что отжата {if (status==1){_ACC();}} // проверяем статус,если равен 1 {if (status==2){_IGN();}} // проверяем статус,если равен 2 {if (status==3){_OFF(); status==0;}} // проверяем статус,если равен 3 } } |
Автор: | zero648 [ Сб июл 21, 2012 13:53:00 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Проверка статуса должна происходить только когда нажимаем кнопку, а не все время проверяться в цикле, и задержку небольшую надо поставить после else, когда кнопка отжата. В основном цикле можно по этому статусу определять в каком режиме находишься ACC, IGN или OFF, если это необходимо. |
Автор: | ukr823f [ Сб июл 21, 2012 14:19:41 ] | ||
Заголовок сообщения: | Re: Посоветуйте алгоритм | ||
Вот поправил немного и добавил сброс счётчика если он больше 3. Всё как бы отрабатывает но с глюками страшнейшими. Кнопка сначала включается, потом через раз потом чёрт зна что и с 10 го нажатия выключает всё таки всё. Мне кажется это из за присвоения статусу признаков зажигания и т.д во время нажатой кнопки. Скорей всего наверное это нужно выносить в отдельное место. вот приложил ещё прект в протеусе. Код: // Global enable interrupts
#asm("sei") while (1) { if (PINB.0==0) // если нажата кновпка { status++; if (status >3) //проверяем, если status больше 3, то присваиваем ему 0 (кнопка ывключена) {status=0;} if (PINB.0==0) // проверяем, если кнопка до сих пор нажата {while (PINB.0==0){}} //заходим в замкнутый цикл else // иначе, если кнопка выходит что отжата delay_ms(200); {if (status==0){_OFF();}} // проверяем статус,если равен 0 {if (status==1){_ACC();}} // проверяем статус,если равен 1 {if (status==2){_IGN();}} // проверяем статус,если равен 2 {if (status==3){_STARTER();}} // проверяем статус,если равен 3 } } }
|
Автор: | ukr823f [ Сб июл 21, 2012 14:34:20 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Эврика , только что перелистывал учебник по АВР и тут пришла идейка По кнопке, теперь она отрабатывает как нужно. Теперь главное чтоб ничего не начало мешать в написании алгоритмов работы от концевиков лампы АКБ и концевика педали сцепления. Код: #asm("sei")
while (1) { if (PINB.0==0) // если нажата кновпка { status++; if (status >3) //проверяем, если status больше 3, то присваиваем ему 0 (кнопка ывключена) {status=0;} if (PINB.0==0) // проверяем, если кнопка до сих пор нажата {while (PINB.0==0){}} //заходим в замкнутый цикл else {} // иначе, если кнопка выходит что отжата } switch (status) //Положение OFF { case 0: PORTD.0=0; PORTD.1=0; PORTD.2=0; PORTD.3=0; break; //Положение АСС case 1: PORTD.0=0; PORTD.1=0; PORTD.2=1; PORTD.3=0; break; //Положение IGN case 2: PORTD.0=0; PORTD.1=1; PORTD.2=1; PORTD.3=0; break; //Положение Стартер case 3: PORTD.0=1; PORTD.1=1; PORTD.2=1; PORTD.3=0; break; default: ; } } |
Автор: | zero648 [ Вс июл 22, 2012 10:42:00 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Получается функция switch постоянно в цикле проверяет состояние status, так чтоли? Надо, чтобы она вызывалась только при нажатии кнопки, а то как-то очень хорошо получается, и тогда она мешать ничему не будет. |
Автор: | ukr823f [ Вт июл 24, 2012 01:57:24 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
товарищи. перешёл к ещё одному элементу. Я то его сделал но может подскажете как его можно упростить. Чтоб контроллеру меньше вычислять. Просто незнаю как в течении трёх секунд, во время кручения стартера, чтоб при погасании лампы зарядки АКБ или блокировки стартера он отключался. Как его опрашивать эти три секунды не нагружая его процик... Код: if (ruchnoy==0) //если мы бытро нажали и бросили кнопку то переходм автоматический режим
{ status=3; //включаем стартер delay_ms(100);//ждём 100 милисекунд if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} проверяем состояние лампы АКБ и стартера if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} if((PINB.4==1)||(PINB.5==0)){status=2;engine=1;}else{delay_ms(100);} status=2; //двигатель завёлся и оставляем включеным зажигание engine=1; ruchnoy=0; } else { status=2; //двигатель у нас уже выходит запущен, и стратер нельзя запускать engine=1; //мы не даём ему запуститься и оставляем просто включеное зажигание } //, и присваем признак заведённого мотора |
Автор: | zero648 [ Вт июл 24, 2012 11:44:34 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Я бы подключил для этого дела таймер, и пускай он отсчитывает 3 секунды, а лампу зарядки АКБ повесил бы на внешнее прерывание со срабатыванием по переднему фронту, т.е. с "0" на "1", при погасании лампы зарядки, по-моему, на нее со стороны минуса приходит +12, по-этому думаю по переднему фронту, и процик вобще не в напряге. |
Автор: | zero648 [ Вт июл 24, 2012 12:11:16 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Использовать можно любой таймер, даже 8 битный, разрешаем прерывания по переполнению этого таймера, прескалер можно вообще вручную написать, используя переменные как счетчики. Например частота 8 МГц, получается: устанавливаем прескалер для таймера = 256, в обработчике прерывания таймера устанавливаем счетчик таймера TCNTx = 6, одну переменную используем как старший разряд счетчика и будем её увеличивать до 125, так получим 1 секунду, итого получим: 8000000 / 256 / (256-6) / 125 = 1 секунда, вторую переменную используем как счетчик секунд и увеличиваем её до 3, получим 3 секунды. |
Автор: | ukr823f [ Вт июл 24, 2012 15:08:26 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Да... тяжело быть программистом.. Я ещё в таймерах и прерываниях несовсем разобрался. И ещё вопросик, мой код, он работает. Но вот в этот момент когда он будет выполняться он несильно перегрузит атмегу? |
Автор: | zero648 [ Вт июл 24, 2012 20:22:02 ] |
Заголовок сообщения: | Re: Посоветуйте алгоритм |
Может лучше тогда цикл организовать типа for, зачем столько одинаковых строк делать? Процик не перегрузится, в любом случае, он постоянно чтото выполняет, если не в спящем режиме. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |