NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Help with a state machine

June 09, 2009
by n3ueaEMTP
n3ueaEMTP's Avatar

Greetings all, I am using a state machine to control different items. I need to be able to reset the timeout during the following state only:

 case STATE_WALK2:
 state = STATE_2G;
 set_lights(0x10);
 if (temp_avg <= 49.0) 
 timeout = 800; 
 else {
 timeout = 2000;
 walk = 0;}
 break;

I've tried these methods without success:

  1. another if statement that checked a variable with a button to set the variable to "1"
  2. an if statement that checked to see if the timeout was not 0 and the above variable was "1"
  3. I put both IF statements in this specific state, before the state machine, & after the state machine. Nothing seems to just reset the timeout.

Any ideas would be appreciated, thanks

June 11, 2009
by wayward
wayward's Avatar

Hi n3ueaEMTP,

it's hard to tell without the rest of the code. Is something else possibly resetting the timeout variable before you check it? When are you reading its value? Are you accessing it from an interrupt?

Perhaps the easiest thing to do is to post us the complete code here, or even better, use one of the freely available pastebins (like Pastie) and give us the link.

June 11, 2009
by n3ueaEMTP
n3ueaEMTP's Avatar

@ Wayward, here is the code for the entire state machine. What I want to be able to do is reset the timer to its max value. Example: Assume the timeout is counting down, if a button is pressed, I would like the timer to be reset to its max value, increasing the time that the light (in this example) stays on. Basically what this does is opens a garage door, sounds a peizo buzzer & turns on a light when the fire company gets an emergency call. You'll note that the alarm must be received twice within 90 seconds to active the garage door. After the timeout, the garage door automatically closes. What I want to have happen is that if an electric eye is crossed, the garage door stays open longer. The code is below. Thanks in advance. Chris B.

// loop forever!
while(1) {
// check the walk button
if (timeout > 3 || timeout < 0)
        walk = 0;
    else if((PINC & (1<<PC5)) == 0)
        walk = 1;

temp_avg = 0.0;
for(i=0; i<100; i++) {
    last_sample = adc_read();
    this_temp = sampleToFahrenheit(last_sample);

  // add this contribution to the average
    temp_avg = temp_avg + this_temp/100.0;

}

// LCD
if(timeout > 0) {

  lcd_home();
  lcd_write_string(PSTR(" ****ALERT****"));
  lcd_write_string(PSTR(" Day: "));
  lcd_write_int16(alarm);
  lcd_write_string(PSTR("          "));
  lcd_line_two();
  lcd_write_string(PSTR("Total: "));
  lcd_write_int16(counter);
  lcd_write_string(PSTR(" "));
  lcd_write_int16_centi(timeout); 
  lcd_write_string(PSTR("sec  ")); 
  //clears the rest of the line
  lcd_write_string(PSTR("        "));
  }
else {  
  lcd_home();
    lcd_write_string(PSTR(" Alerts: "));
    lcd_write_int16(alarm);
    lcd_write_string(PSTR("   Total: "));
    lcd_write_int16(counter); 
    //clears the rest of the line       
    lcd_write_string(PSTR("          "));
    lcd_line_two();
    for(i=0; i<24; i++) 
    lcd_write_data(pgm_read_byte(linetwo + ((scrollPos+i)%linetwolen)));
    scrollPos = (scrollPos + 1) % linetwolen;
    delay_ms(150);
  }

// state transitions
if ((timeout == 0) && (call) && ((the_time / 100.0) < 90.0)){
  switch(state) {
      case STATE_1G:
        state = STATE_1Y;
        set_lights(0x00);
        timeout = 10;
        break;
      case STATE_1Y:
        if(walk) {
        state = STATE_WALK;//Peizo, bed shaker, & lights ALSO OPENs GARAGE DOOR
        alarm = alarm + 1;
        counter = counter + 1;
        eeprom_write_byte(0, counter);
        set_lights(0x31);
        timeout = 400;  //PEIZO TIME
        walk = 0;
        break;
      case STATE_WALK: 
        state = STATE_WALK2;//transition to lights & bed shaker
        //to remove shaker option change timeout to 10
        set_lights(0x10);
        timeout = 10;  //BED SHAKER TIME
        walk = 0;
        break;
      case STATE_WALK2:  //transition to lights only
        state = STATE_2G; 
        set_lights(0x10);
        if (temp_avg <= 49.0) 
            timeout = 800; 
        else {
        timeout = 2000;
        walk = 0;}
        break; 
      case STATE_2G:
        state = STATE_2Y;//GARAGE DOOR closing warning
        set_lights(0x30);
        timeout = 500;  //PEIZO TIME
        walk = 0;
        break;
     case STATE_2Y:  //  CLOSE GARAGE DOOR
        //to remove door option change timeout to 10
        state = STATE_1G;
        set_lights(0x12);
        timeout = 150; 
        walk = 0;
        call = 0;
        break;
        } 
      else {
        state = STATE_1G;           
        set_lights(0x00);
        timeout = 10;
      }
      break;
    }
}

 else if (timeout == 0) 
  switch(state) {
      case STATE_1G:
        state = STATE_1Y;
        set_lights(0x00);
        timeout = 10;
        break;
      case STATE_1Y:
        if(walk) {
        state = STATE_1G;//Peizo & lights for First Dispatch
        alarm = alarm + 1;
        counter = counter + 1;
        eeprom_write_byte(0, counter);
        set_lights(0x10);
        timeout = 500;  //PEIZO TIME
        walk = 0;
        call = 1;
        the_time = 0;
        break;
        } 
      else {
        state = STATE_1G;           
        set_lights(0x00);
        timeout = 10;
      }
      break;}
  // check the non emergency light button to turn on light only
if((PINC & (1<<PC5)) == 0)
  walk = 1;
else if((PINB & (1<<PB4)) == 0)
    {
    set_lights(0x10);
    timeout = 19500;  //LIGHT TIME in NON EMERGENCY STATE!!! 
    }
  // check the counter reset button to reset the "Day" counter
if((PINC & (1<<PC4)) == 0)
    {
    alarm = 0;
    }
// check the alarm reset button to reset the alarm
if((PINB & (1<<PB5)) == 0)
    {
    timeout = 10;
    }
//resets timer to zero
  if ((the_time / 100.0) > 1500.0)
    {
    the_time = 0;
    }
// check the counter reset button & the alarm reset button to reset the "Total" counter
if (((PINC & (1<<PC4)) == 0) && ((PINB & (1<<PB5)) == 0))
    {
    counter = 0;
    eeprom_write_byte(0, counter);
    }
// write message to serial port
printf_P(PSTR("%.2f degrees F\r\n"), temp_avg);
printf_P(PSTR("%.2f call\r\n"), call);
printf_P(PSTR("%.2f timeout\r\n"), timeout);
printf_P(PSTR("%.2f Day\r\n"), alarm);
printf_P(PSTR("%.2f Total\r\n"), counter);
printf_P(PSTR("%16.2f sec\r\n"), the_time / 100.0);

// delay a bit and decrement timeout
delay_ms(30);
timeout = timeout - 10;
}
return 0;
}

Post a Reply

Please log in to post a reply.

Did you know that you can adjust most wire strippers to make it easier to strip insulation faster? Learn more...