HOLD, DETECT SAME HOLD MANY TIMES , DO!

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello freaks , I hit a wall when doing something and hence want some advice. I know how to hold a button and do something but now I want to do something else I want to hold a button which will enable the user so that he can hold another button and then due to both of their holds something appliance will run this is simple indeed I have achieved this but now I want to detect that whenever the second button is released the avr should start a timer and during that period even if the second button is held the appliance will not run. I think You guys will understand more from the code. I am also giving a pseudo code for clarity:-

Using the atmega8 at 8MHz clock

1.1st button held - 1st led lights up 

2. 1st button released -  1st led is switched off

3. 2nd button held - held will be registered only if the 1st button is being held first and nothing will happen if 1st button is not held- 2nd led turns off

4. 2nd button released - 2nd led lights up and starts a timer (for say 10 minutes) and also starts a flashing led as an indication during the period if 2nd button is held again then 

   turn ON an output.

5. after the set time the timer stops and the flashing led also stops and then wait for manual start of the output.

This is roughly what I want any suggestions guys here Is what I have created. You can inspect my work.

/*
 * atmega8 dry_run_controller_3.c
 *
 * Created: 10-04-2020 12:46:05 PM
 * Author : HP
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "debounce.h"

void motor_on(void);
void motor_off(void);

void automatic_mode(void);
void automatic_high(void);
void automatic_low(void);
void dry_run(void);
void dry_run_flasher(void);
int dry_run_counter = 0;
int start_timer = 0;

void manual_mode(void);
void manual_low(void);
void manual_high(void);

void filling_led(void);

int mode_of_operation = 0;
int filling_counter = 0;
int filling_hold = 0;

int hold = 0;
int pressed = 0;
int activate_dry_flasher = 0;
int activate_dry_timer = 0;
void universal_dry(void);

int main(void)
{
    /* Replace with your application code */
	DDRB = 0b00100000;
	PORTB = 0b11011111;//pull ups for the inputs

	DDRC = 0xff;
	PORTC = 0x00;//all outputs turned off

	DDRD = 0b01111111;
	PORTD = 0b10000000;//pull ups for buttons

	TCCR0 = (1<<CS02);//pre-scaler of 256 at 8MHz
	TIMSK = (1<<TCNT0);//initiating the timer0 in normal mode

	debounce_init();
	OCR1A = 15624;
	TCCR1B |= (1 << WGM12);
	// Mode 4, CTC on OCR1A
	TIMSK |= (1 << OCIE1A);
	//Set interrupt on compare match
	TCCR1B |= (1 << CS02);
	// set prescaler to 1024 and start the timer

	sei();
	_delay_ms(50);
	mode_of_operation = 1;
	PORTD |= (1<<PD4);
    while (1)
    {
		if(mode_of_operation == 1)
		{
			automatic_mode();
		}
		else
		{
			manual_mode();
		}
		if(button_down(BUTTON1_MASK))//manual ON
		{
			motor_on();
		}
		if(button_down(BUTTON2_MASK))//manual OFF
		{
			motor_off();
		}
		if(button_down(BUTTON3_MASK))
		{
			mode_of_operation = 1;//ie in automatic_mode
		}
		if(button_down(BUTTON4_MASK))
		{
			mode_of_operation = 0;//ie in manual mode
		}

    }
}
ISR(TIMER0_OVF_vect)//using the timer0 for filling tasks
{
	debounce();
	if(activate_dry_flasher == 1)
	{
		PORTB ^= (1<<PB5);//dry_run led is blinking
	}

}
ISR(TIMER1_COMPA_vect)//using timer1 for separate tasks
{
	if(activate_dry_timer == 1)
	{
		if(hold == 10)//until 10 seconds have passed
		{
			if((!(PIND & (1<<PD7))) == 1)//even if dry_run is held do not turn ON the motor
			{
				motor_off();
				hold = 0;
				pressed++;//count the number of interrupts
			}
			if(pressed != 3)
			{
				//PORTC |= (1<<PC1);//stop the blinking
				activate_dry_flasher = 0;//stop the blinking
			}
			else
			{
				if((!(PIND & (1<<PD7))) == 1)//even if dry_run is held do not turn ON the motor
				{
					motor_on();
					hold = 0;
					//pressed++;//count the number of interrupts
				}
			}
		}
		else
		{
			hold++;//increment the hold timer continuously.
		}
	}
}
void motor_on()
{
	PORTC |= (1<<PC0);
}
void motor_off()
{
	PORTC &= ~(1<<PC0);
}
void automatic_mode()
{
	PORTC |= (1<<PC4);
	automatic_high();
	automatic_low();
	universal_dry();
}
void manual_mode()
{
	PORTC &= ~(1<<PC4);
	manual_low();
	manual_high();
}
void manual_low()
{
	if((!(PIND &(1<<PD5))) == 1)
	{
		PORTC |= (1<<PC2);
	}
	else
	{
		PORTC &= ~(1<<PC2);
	}
}
void manual_high()
{
	if((!(PINB &(1<<PB7))) == 1)
	{
		PORTC |= (1<<PC1);
	}
	else
	{
		PORTC &= ~(1<<PC1);
	}
}
void filling_led()
{
	PORTC ^= (1<<PC3);
}
void automatic_high()
{
	if((!(PINB &(1<<PB7))) == 1)
	{
		PORTC |= (1<<PC1);
		motor_off();
	}
	else
	{
		PORTC &= ~(1<<PC1);
	}
}
void automatic_low()
{
	if((!(PIND &(1<<PD5))) == 1)//if low is held
	{
		PORTC |= (1<<PC2);//low led ON
		if((!(PIND &(1<<PD5))) == 1)//if dry_run is held
		{
			motor_on();
			PORTC &= ~(1<<PC5);//dry run led is OFF
		}
		else//if dry_run is not held
		{
			activate_dry_timer = 1;
			activate_dry_flasher = 1;
			motor_off();
		}
	}
	else
	{
		PORTC &= ~(1<<PC2);
	}
}
void universal_dry()
{
	if((!(PIND &(1<<PD7))) == 1)//if dry_run is held
	{
		PORTC &= ~(1<<PC5);
	}
	else
	{
		motor_off();
	}
}

As you might have known after reading my code that I am working on a controller to automatically turn ON and OFF my water pump in case of water supply failure. Any advice would be highly appreciated.

Anshumaan.

This topic has a solution.

anshumaan kumar

Last Edited: Tue. May 5, 2020 - 05:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you need to have a read of this - https://www.avrfreaks.net/forum/...

 

You really only need one hardware timer.

 

As for your question, rather than look at some code, step back and think about the task at hand - not the code. Once you've figured out the required sequence, then the code will fall into place.

 

1.1st button held - 1st led lights up 

2. 1st button released -  1st led is switched off

3. 2nd button held - held will be registered only if the 1st button is being held first and nothing will happen if 1st button is not held- 2nd led turns off

4. 2nd button released - 2nd led lights up and starts a timer (for say 10 minutes) and also starts a flashing led as an indication during the period if 2nd button is held again then 

   turn ON an output.

5. after the set time the timer stops and the flashing led also stops and then wait for manual start of the output.

 

What happens if the user presses both button1 and 2 together?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Have you read about state machines?  https://www.avrfreaks.net/forum/...

Jim

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

Have you read about state machines?  https://www.avrfreaks.net/forum/...

Jim

I haven't read this article but yes I have read about them please don't compare the above given code to a code of a state machine although I am trying to create one but the above code is no where near on how to create a working state machine I am currently using Kartman's code to achieve my goal I will share that. In the mean time can someone see that how I am holding the button , I am detecting holds using this method:-

if((!(PIND &(1<<PD5))) == 1)//if dry_run is held

although I know how to use timer to detect the hold of a button but this thing works perfectly too even on the hardware so I decided to stick with this. Is this right or I should really be using timers to detect the button holds. 

Below is how I use timers to detect the button hold:- 

Please tell which is the right way to detect a button hold:-

ISR(timer1_COMPA_vect)
{
    if(button_is_pressed)
{
    if(counter == 2)//after 2 seconds
    {
        //do something
        counter = 0;
    }
    else
    {
        counter++;
    }
}
}

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
I have read about them

So why did you decide not to use one?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

Anshumaan wrote:
I have read about them

So why did you decide not to use one?

 

Well I thought that this will be a simple project but then the requirements went on increasing because I haven't planned on how to achieve this problem ,this is what I am, I rarely plan before ,which is why I am used to confusing myself in the very simple of things. Hoping to fix myself in the upcoming projectslaugh.

By the way thanks awneil for asking.wink

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

State machines don't need to be big or complex, and are not reserved for big and/or complex projects.

 

One of the beauties of state machines is that they are (relatively) easy to extend as a project grows.

 

Perhaps now would be a time to refactor ... ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
Perhaps now would be a time to refactor ... ?

Yes this would be a perfect time for a change so you tell which code can accomplish my requirements better Kartman's multitasking code or the state machine code given by Jim??

What do you think? I love Kartman's code because it is so easy to use and I have created a working device with it in the past. I am leaning towards that code but If you have used Jim's code 

you can give me advice to use that I will have no problem using that too. New things would be nice to learn.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Multitasking and state-machines are not mutually exclusive.

 

Most of my projects are multitasking and usually several of those tasks will require a state machine.

And in several projects, there is an overall state machine that determines what tasks are active...

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
you can give me advice

I would totally echo Kartman's advice:

 

Kartman wrote:
rather than look at some code, step back and think about the task at hand - not the code. Once you've figured out the required sequence, then the code will fall into place.

 

Don't leap straight into code!

 

Spend time with pencil & paper to thoroughly understand the problem, and design your solution.

 

Drawing a state diagram can be a great way to understand a problem - and answer questions like:

 

Kartman wrote:
What happens if the user presses both button1 and 2 together?

 

EDIT - Example:  https://www.avrfreaks.net/commen...

 

Coding is the last thing you should do!

 

Anshumaan wrote:
I rarely plan before ,which is why I am used to confusing myself 

So don't do that, then!

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Apr 17, 2020 - 03:59 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need a better logic description 

like step 3 when does LED 2  turn on (it only tell about how it turn off!)

what happen if key 1 is released under step 4 ? (or key 2 pressed again etc.)

 

I agree that a state machine would be normal way to do it, but this (so far) are very simple I think.

something like:

 

init div things

 

LED1 == key1

if key1 && key2    // assume if they come at the same time it's ok

    turn LED2 off

    key2flag=on

if !key2 && key2flag==on

   LED2 on

   start timer

   key2flag=off

   flash LED

if timer_running && key2

    set out

if timer_out

    LED2 off

 

Add:

missed the step 5 part in first try

Last Edited: Fri. Apr 17, 2020 - 04:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

frog_jr wrote:
Multitasking and state-machines are not mutually exclusive.

Well I also thought like that just got confused with the names and nothing else. Thanks for clearing me up.

awneil wrote:

Don't leap straight into code!

 

Spend time with pencil & paper to thoroughly understand the problem, and design your solution.

 

Drawing a state diagram can be a great way to understand a problem - and answer questions like:

Yes you are right maybe I should try to improve myself rightaway.

awneil wrote:
Coding is the last thing you should do!

Ok. I will this time try to do the coding in the end.

sparrow2 wrote:
I agree that a state machine would be normal way to do it, but this (so far) are very simple I think.

Yes you are right this is simple I just make it a mess myselfcheeky.

Thank you guys I will share with you what I have made asap.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey guys this is what I have thought I hope I have written it clearly so that you guys can understand it clearly.

Well don't think that I am asking for code just want to ask a few things regarding the below given pseudo code:-

low is switch_1 
low led is led_2
dry_run is switch_2
dry_run is led_2
timer led is led_3
motor is led_4

*if switch_1 == 1
led_1 == 1
else
led_1 == 0

*if switch_1 == 1 and switch_2 == 1
led_4 == 1

*else if switch_1 == 0 and switch_2 == 1 
led_4 == 1 

*else if switch_1 == 0 and switch_2 == 1
led_4 == 1
led_1 == 0
led_2 == 0
led_3 == 0

*else if switch_1 == 1 and switch_2 == 0
led_3 ^= 1 //flashing
led_4 == 0
start a timer until the timer is out do not start the motor i.e.
led_4 == 0 until timer is != 0

*until timer is out 
{
    led_4 = 0
    led_3 ^= 1
    led_2 = 0
    if switch_1 == 1 and switch_2 == 1
    then turn ON the motor i.e. led_4 = 1
    led_2 = 0
    led_3 = 0
    else
    just let the motor off 
    led_4 = 0
    led_3 = 0
    led_2 = 1
}
*when timer is out
{
    led_4 = 0
    led_3 = 0
    led_2 = 1
    now do not start the motor even
    if switch_1 == 1 and switch_2 == 1
    led_4 = 0
    led_2 = 1
    led_3 = 0   
}

Well just clear one of my doubts that how can I achieve this part

*if switch_1 == 1 and switch_2 == 1
led_4 == 1

*else if switch_1 == 0 and switch_2 == 1 
led_4 == 1 

*else if switch_1 == 0 and switch_2 == 1

 

this is kind of confusing to me. One place to start explaining is this piece of code

 

 

sparrow2 wrote:

if key1 && key2    // assume if they come at the same time it's ok

    turn LED2 off

    key2flag=on

if !key2 && key2flag==on

 

 

Basically I am asking how can I set flags like this. Earlier than now I used a variable and store 1 or 0 in it depending on the condition. Just like this:-

 

if(button_down(BUTTON3_MASK))
        {
            mode_of_operation = 1;//ie in automatic_mode
        }
        if(button_down(BUTTON4_MASK))
        {
            mode_of_operation = 0;//ie in manual mode
        }

if(mode_of_operation == 1)
        {
            automatic_mode();
        }
        else
        {
            manual_mode();
        }

So what I do is good or not???

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Basically I am asking how can I set flags like this.

what do you mean, just use a variable & define some modes to be used:

 

if (mymode == FORWARD)

   {do this stuff...

      mymode = WAITING;}

 

if (mymode == REVERSE)

   {do this stuff...

      mymode = ALARM;}

 

Why does you program look extremely long just to fiddle with 2 switches?   Have you tried doing it in assembly?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Apr 18, 2020 - 04:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

if(button_down(BUTTON3_MASK))
        {
            mode_of_operation = 1;//ie in automatic_mode
        }
        if(button_down(BUTTON4_MASK))
        {
            mode_of_operation = 0;//ie in manual mode
        }

if(mode_of_operation == 1)
        {
            automatic_mode();
        }
        else
        {
            manual_mode();
        }

what i understood is that you have indicated this thing only just because I have used straightaway 1 and 0 it's looking weird but when I use like it:-

mode_of_operation == automode;

where, automode = 1;

everything becomes what you are indicating right??

Have I understood correctly.?

avrcandies wrote:
Why does you program look extremely long just to fiddle with 2 switches? 

It could be because I must have been really confused on how to implement my idea into the coding.

avrcandies wrote:
Have you tried doing it in assembly?

No.Really not that strong in assembly , just started learning c++ near about 6 months ago.I am basically a student of electrical engineering just took these embedded things because I am interested in them. 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

what do you mean, just use a variable & define some modes to be used:

 

if (mymode == FORWARD)

   {do this stuff...

      mymode = WAITING;}

 

if (mymode == REVERSE)

   {do this stuff...

      mymode = ALARM;}

This is actually the same thing that I was doing and I realised it long after I was working.Thanks for clearing my doubts.

sparrow2 wrote:

I agree that a state machine would be normal way to do it, but this (so far) are very simple I think.

something like:

Thanks this helped me a lot.Thanks man.

 

I had worked hard on this,it could still look to you a little bit of a mess sorry for that but it works I will clean it a bit later.

 

awneil wrote:

Don't leap straight into code!

 

Spend time with pencil & paper to thoroughly understand the problem, and design your solution.

 

Drawing a state diagram can be a great way to understand a problem - and answer questions like:

Paper computer always works.Thanks man.

/*
 * atmega8 dry_run_controller_3.c
 *
 * Created: 10-04-2020 12:46:05 PM
 * Author : HP
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "debounce.h"

void motor_on(void);//motor is on
void motor_off(void);//motor is off
void low_led(void);
void full_led(void);
void sensor_show(void);//showing all the lights

void automatic_mode(void);
void automatic_high(void);
void automatic_low(void);
void dry_run_led(void);
void dry_run_function(void);

void manual_mode(void);
void manual_low(void);
void manual_high(void);
void filling_led(void);
void timer_check(void);

uint8_t start_timer = 0;
uint8_t start_flasher = 0;
uint8_t timer_is_running = 0;
uint8_t dry_flag = 0;
uint8_t counter = 0;
uint8_t timer0_counter = 0;
uint8_t manual_start_flag = 0;
uint8_t dry_tries = 0;//stating that the tries have been done.
uint8_t mode_of_operation = 0;
int main(void)
{
 /* Replace with your application code */
 DDRB = 0b00100000;
 PORTB = 0b11011111;//pull ups for the inputs

 DDRC = 0xff;
 PORTC = 0x00;//all outputs turned off

 DDRD = 0b00010000;
 PORTD = 0b11101111;//pull ups for buttons
 TCCR0 = (1<<CS02);
 TIMSK = (1<<TCNT0);
 //starting the timer_1
 OCR1A = 7812;//truly 250ms count
 TCCR1B |= (1 << WGM12);
 // Mode 4, CTC 1 OCR1A
 TIMSK |= (1 << OCIE1A);
 //Set interrupt 1 compare match
 TCCR1B |= (1 << CS02);
 debounce_init();
 sei();
 _delay_ms(50);
 mode_of_operation = 1;
 while (1)
 {
  if(button_down(BUTTON1_MASK))//manual ON
  {
   motor_on();
   manual_start_flag = 0;
  }
  if(button_down(BUTTON2_MASK))//manual OFF
  {
   motor_off();
  }
  if(button_down(BUTTON3_MASK))
  {
   mode_of_operation = 1;//i.e. in automatic_mode
  }
  if(button_down(BUTTON4_MASK))
  {
   mode_of_operation = 0;//i.e. in manual mode
  }	

  if(mode_of_operation == 1)
  {
   automatic_mode();
  }
  else
  {
   manual_mode();
  }
 }
}

ISR(TIMER0_OVF_vect)
{
 debounce();
 filling_led();
}

ISR(TIMER1_COMPA_vect)
{
 //PORTD ^= (1<<PD4);//power led
 //debounce();
 //filling_led();
 if(start_flasher == 1)
 {
  PORTB ^= (1<<PB5);//timer led
 }
 else
 {
  PORTB &= ~(1<<PB5);
 }
 if(start_timer == 1)//starting the timer
 {
  if(counter == 20)//after 5 seconds
  {
   timer_check();
   counter = 0;//restarting the counter to start again
   start_timer = 0;
   start_flasher = 0;
   dry_flag = 0;
  }
  else
  {
   counter++;
   timer_is_running = 1;
   start_flasher = 1;
  }
 }
 else
 {
  counter = 0;//stopping the counter
  start_flasher = 0;
  timer_is_running  = 0;
 }

}
void motor_on()
{
 PORTC |= (1<<PC0);
}
void motor_off()
{
 PORTC &= ~(1<<PC0);
}
void automatic_mode()
{
 PORTC |= (1<<PC4);
 sensor_show();//showing the values of sensors in each mode
 automatic_high();
 automatic_low();
}
void manual_mode()
{
 PORTC &= ~(1<<PC4);
 sensor_show();
}
void filling_led()
{
 if((!(PINB & (1<<PB0))) == 1)
 {
  PORTC ^= (1<<PC3);
 }
 else
 {
  PORTC &= ~(1<<PC3);
 }
}
void low_led()
{
 if((!(PIND &(1<<PD5))) == 1)
 {
  PORTC |= (1<<PC2);//low led == 1
 }
 else
 {
  PORTC &= ~(1<<PC2);//low led == 0
 }
}
void full_led()
{
 if((!(PINB &(1<<PB7))) == 1)
 {
  PORTC |= (1<<PC1);//full_led == 1
 }
 else
 {
  PORTC &= ~(1<<PC1);//full_led == 0
 }
}
void sensor_show()
{
 low_led();
 full_led();
 dry_run_led();
}
void dry_run_led()
{
 if((!(PIND &(1<<PD7))) == 1)
 {
  PORTC &= ~(1<<PC5);
 }
 else
 {
  PORTC |= (1<<PC5);
  motor_off();//always turn off the motor when the supply is out
 }
}
void automatic_low()
{
 if((!(PIND &(1<<PD5))) == 1)//if low is pressed
 {
  dry_run_function();
 }
}
void dry_run_function()
{
 //and then dry_run has been pressed  / released then :-
 if(((!(PIND &(1<<PD7))) == 1) && (((!(PIND &(1<<PD5))) == 1)) && (manual_start_flag == 0) && (timer_is_running == 0))//if low and dry has been pressed together
 {
  //This is the ON condition when the timer has been fired for the first time
  motor_on();
  dry_flag = 1;//now storing that the motor is being ON for the first time
 }
 if(((!(PIND &(1<<PD7))) == 0) && (dry_flag == 1))//supply is out for the first time
 {
  //This stops the motor and starts the timer
  motor_off();
  start_timer = 1;
  start_flasher = 1;
 }
 //ALL other conditions than this are ignored
}
void automatic_high()
{
 if((!(PINB &(1<<PB7))) == 1)
 {
  PORTC |= (1<<PC1);//full_led == 1
  motor_off();//turning off the motor
 }
 else
 {
  PORTC &= ~(1<<PC1);//full_led == 0
 }
}
void timer_check()
{
 if((!(PIND & (1<<PD7))) && (dry_flag == 1) &&(timer_is_running == 1))//if supply comes in the timer period
 {
  motor_on();
  start_timer = 0;
  start_flasher = 0;
  dry_flag = 0;//resetting the counter to start checking again if supply goes out
 }
}

One more question regarding this I wanna ask although this code works fine in a simulation but on a practical chip I noticed a flaw:-

As you noticed that I am using two timers the things in the timer0 mainly the filling function and the debounce function works on the simulation but in practical no buttons works and no filling function

blinking is achieved as if timer0 isn't started on the actual chip anything you guys could find on the code that I have missed that is messing these functions??

I have tried merging both of the timers code into one but to no affectsad

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The secret is to isolate the code that decodes the buttons from the rest of the code - you've got a mish mash of stuff everywhere.  This just makes it harder for you to debug.

 

I recently wrote a tutorial on debugging - maybe you might want to read it and apply some of the techniques mentioned?

 

https://www.avrfreaks.net/forum/...

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A big mess...

separate your  detection of conditions from what you want to happen under those conditionns .....a state machine

 

switch mystate

      case motor_forward

             if pin1 mystate= motor_pause

             else if timer1>500 mystate=motor_stop

     

      case motor_stop

             if pin 22 mystate= motor_forward

             else if pin 34 mystate= motor_reverse

 

      case motor_hot

            if tempsensor<200 mystate=motor_resume

 

//take actions here

   switch mycase

       case motor_hot

                 turn on alarm

 

       case motor forward

                 turn on led green

                 turn on PWM

 

This captures some of the idea, but there can be more.  Usually you track the previous state (not shown here)

If the current state matches the previous state nothing has changed, and you can do keep those state things that need repeated over & over (maybe making continuous pulses, or calling a routine that displays the current pressure)

If the current state does not match the previous state, you have entered a new state and can do things that happen only once (like turn the motor ON, or make one pulse when entering open_trap_door state)...these things happen only when entering the state.

So just because you are in open_trap_door, you don't have to keep making pulses, but  maybe there are other things you want to do repeatedly (maybe display a list of messages).

 

The  previous state is the set to match the current state (previous_state=mystate)

 

Hopefully this gives you some ideas to make things cleaner.

 

 

     

     

     

 

 

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
I recently wrote a tutorial on debugging

Wow. The thing that I wanted to learn I can code but can't code clean that's why its hard to debug that's right maybe I should first clean the code in a nice readable manner and then maybe I would find the problem myself.

 

Kartman wrote:

The secret is to isolate the code that decodes the buttons from the rest of the code

Nice piece of advice I am on it.

avrcandies wrote:
A big mess...

ya.I am afraid it is sadthis happens when you are desperate to build something and then panic moment comes.

avrcandies wrote:

This captures some of the idea, but there can be more.  Usually you track the previous state (not shown here)

If the current state matches the previous state nothing has changed, and you can do keep those state things that need repeated over & over (maybe making continuous pulses, or calling a routine that displays the current pressure)

If the current state does not match the previous state, you have entered a new state and can do things that happen only once (like turn the motor ON, or make one pulse when entering open_trap_door state)...these things happen only when entering the state.

So just because you are in open_trap_door, you don't have to keep making pulses, but  maybe there are other things you want to do repeatedly (maybe display a list of messages).

 

The  previous state is the set to match the current state (previous_state=mystate)

 

Hopefully this gives you some ideas to make things cleaner.

Yes.This will. Thanks for the explanation man I will do it as much as you could to make the code cleaner.Thanks for the help mate.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a lot less twisted when you separate the flow between states  from the actions states allow to be taken.  

 

There are many variations. A few to consider:

 

A state can take an action when it is first entered (once, say: turn on an led, turn off a valve)

    This might additionally involve performing some checks  (if the battery voltage is low turn on the led)

 

A state can take an action when it is leaving (going to another state) (once, say: turn on an led, turn off a valve)

    This might additionally involve performing some checks  (if the door is open, sound the alarm)

 

A state can take an action repetitively while remaining in the state (refresh the display with the latest voltage reading)

    This might additionally involve performing some checks (if the motor voltage is high, apply the brakes)

 

Sometimes the checks get complicated enough, or logically partitioned to naturally warrant becoming their own states.  It's a decision balancing between having too many (minor) states or too few (major) ones. 

 

Having options at your disposal lets you arrange the actions in an understandable manner, and more importantly allows you to easily manage and modify them.

 

States can even be combined or nested. A "high level" printer could have a set of states for handling paper  (moving, ready, jammed, empty, wrong size, etc) , and another set for running the menus, perhaps coordinated by another set of system states.

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
States can even be combined or nested. A "high level" printer could have a set of states for handling paper  (moving, ready, jammed, empty, wrong size, etc) , and another set for running the menus, perhaps coordinated by another set of system states.
Believe me or not this is one of the advice that I have got here and I will never forget nice explaining Sir. It really made my day.Thanks

Kartman wrote:
You really only need one hardware timer.

Well I already know that but I was not accepting it until you have told me to do so. Thanks man I fired the timer1 at 10ms and then checked for button debounce routines and then created a 1 second counter to do all the other slow stuff and you know it worked. Thanks Good Sir.

avrcandies wrote:
A big mess...

It Still ischeekyBut I am Glad it works now as I wanted it to be. But don't worry I will try to create more clean codes from now on.Thanks man.

Stay Safe and Stay at home. Best thing to do at home is to code and try to build something .If stuck somewhere come here for help .A great place guys .Thank you all.

Anshumaan.

anshumaan kumar