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 » Sequencer project (help needed with timing)

April 21, 2012
by jfreethy
jfreethy's Avatar

Hello all,

I wanted to get my feet wet after completing the Nerd kit projects and well here I am. I found that micro controllers could be very useful in my other hobbies. One of those hobbies being pyrotechnics, which I have been, involved with for about 12 years the last 5 being a licensed professional. But enough about me and on the project. The idea was to make a sequencer! Basically the user would input a standard delay in either minutes, second, milliseconds, or a combination of all three. Once the time for the delay was entered, the system would wait for an input signal (a stepped down voltage from the firing system). Once the voltage was received the “sequence” would begin to fire an output voltage (which would switch a mosfet) across my outputs at the desired delay. My out puts are leds currently. Here is the problem when I input minutes and seconds it will only display a value so high before it switched to a negative value and counted backwards. Those values being 32 for seconds and 3 for minutes, so I thought that it was an absolute value problem hence the abs in the code. Which none the less did not help. I think that the problem is that all my counting values are in milliseconds and that I am exceeding the total number of bites. Which I believe would result in me having to use some sort of timer in my code in place of just counting milliseconds. But I thought that I would ask here first being new The code is basic and rough but it’s my first code I did ;

// led_blink.c
// for NerdKits with ATmega168
// jason_Freethy

#define F_CPU 14745600

#include <stdlib.h>
#include <avr/io.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
// PIN DEFINITIONS:
//
// PC4 -- LED anode
// PC3 -- LED anode
// PC2 -- LED anode
// PC1 -- LED anode
// PC0 -- LED anode
// PB2 -- Button input to fire code
// PB3 -- Button for delay ms imput
// PB1 -- Button for reset delay value
// PB4 -- Button for delay  sec imput
// PB5 -- Button for delay min imput

 void led_output(){
// LED as output
  DDRC |= (1<<PC4);
  DDRC |= (1<<PC3);
  DDRC |= (1<<PC2);
  DDRC |= (1<<PC1);
  DDRC |= (1<<PC0);
  }
void buttons(){
DDRB &= ~(1<<PB2); // set PB2 as input
DDRB &= ~(1<<PB3); // set PB3 as input
DDRB &= ~(1<<PB1); // set PB1 as input
DDRB &= ~(1<<PB4); // set PB4 as input
DDRB &= ~(1<<PB5); // set PB5 as input

PORTB |= (1<<PB3); // turn on pull up resistor
PORTB |= (1<<PB2);
PORTB |= (1<<PB1);
PORTB |= (1<<PB4);
PORTB |= (1<<PB5);
}
int16_t a1;
int16_t a2;
int16_t a3;
int delay(uint16_t delay){
return delay = a1 + a2 + a3; // function for adding up the total delay
}
int main() {
//declare uinte used for our imput
uint16_t button1;
uint16_t button2;
uint16_t button3;
uint16_t button4;
uint16_t delay;
uint16_t delay_min;
uint16_t delay_sec;
led_output();
buttons();

lcd_init(); // main screen on start up
  lcd_home();
  lcd_line_one();
  lcd_write_string(PSTR("SEQUENCER v1.0"));
delay_ms(2000); // delay to make it able to be viewed by the user
lcd_clear_and_home();

 while(1) {

 if (PINB & (1<<PB3)) // function for milli second delay
  {
  }
  else
  {
  button1 = (PINB & (1<<PB3)) & 1;// turn on pull up resistor for pin B3

  a1 = abs (a1 + 5);

  delay_ms(60); // give user time to press the button
  }

  if (PINB & (1<<PB4)) // function for second delay
  {
  }
  else
  {
  button2 = (PINB & (1<<PB4)) & 1;// turn on pull up resistor for pin B4

  a2 = abs (a2 + 1000);

  delay_ms(60); // give user time to press the button
  }

  if (PINB & (1<<PB5)) // function for minute delay
  {
  }
  else
  {
  button3 = (PINB & (1<<PB5)) & 1;// turn on pull up resistor for pin B5

  a3 = abs (a3 + 10000);

  delay_ms(60); // give user time to press the button
  } 
  if (PINB & (1<<PB1)) // rest function to return all values to zero
  {
  }
  else
  {
  button4 = (PINB & (1<<PB1)) & 1;// turn on pull up resistor for pin B1

  a1 = 0;
  a2 = 0;
  a3 = 0;
  delay_ms(30); // give user time to press the button
  }

  delay = a1 + a2 + a3; // total delay time for minutes, seconds, and milliseconds
  delay_sec = (a2 / 1000); // display properly delay for seconds
  delay_min = (a3 / 10000); // display properly delay for minutes

  // lcd go to time delay imput information
 lcd_home();
 lcd_line_one();
  lcd_write_string(PSTR("Select delay for cues"));
  lcd_line_two();
  lcd_write_int16(delay_min);
  lcd_write_string(PSTR("min "));
  lcd_write_int16(delay_sec);
  lcd_write_string(PSTR("sec "));
  lcd_write_int16(a1);
  lcd_write_string(PSTR("ms"));

  // wait untill fire imput 
  if (PINB & (1<<PB2))
  {
  }
  else
    // turn on LED
 {   // LED as output
  PORTC |= (1<<PC4); //TURN LED's ON
        delay_ms(20); // delay pin for 20ms to pass fire
        PORTC &= ~(1<<PC4);// turn off led
delay_ms(delay);                 //wait for delay value
    PORTC |= (1<<PC3);
        delay_ms(20);
        PORTC &= ~(1<<PC3);
delay_ms(delay-20);            // delay value minus the 20ms to maintain delay value
  PORTC |= (1<<PC2);
        delay_ms(20);
        PORTC &= ~(1<<PC2);
delay_ms(delay-20);
    PORTC |= (1<<PC1);
        delay_ms(20);
        PORTC &= ~(1<<PC1);
delay_ms(delay-20);     
  PORTC |= (1<<PC0);
      delay_ms(20);
      PORTC &= ~(1<<PC0);
    }
  }

   return 0;
}
April 21, 2012
by sask55
sask55's Avatar

Hi jfreethy

Since none of the other member have posted a reply to your questions I thought I wouold make a few comments about your code.

Keep in mind that a int16_t variable is 16 bit integer number. That means there are 16 bits of memory available to hold its value. One of the bits is used to indicate the values sign positive or negative, leaving 15 bits to store your values. 2 ^15 is 32768. The range of values that can be held in a int_16 is therefor -32767 to 32767.

You could use uint16_t variables which would double the size of the possible value to 65536. Even that number would be a time of just over one minute in terms of milliseconds. Since each second has 1000 milliseconds and each minute has 60 seconds. Therefore to hold a time value expressed in milliseconds for time greater then about 65 seconds you will have to initiate the variable as int32_t or unit32_t

A few more ideas.

code lines 50 ,51,52 These variables are not used outside the main and could be moved down inside the main loop.

code lines 53,54,55 This function is never called as you have written the code. You could just remove these code lines

code lines 58,59,60,61 I don’t understand what your intent for these variables are, I do not see how they are used for anything in your code.

code line 62 Variable to small to hold values.

code lines 82,94,106,117 It is not clear what the intent of this code is. It does not change the values of the pull up resistors registers on port B. There is no need to change the state of the pull up resistors. This code could be removed.

code lines 84,96,108, There is no need for the Absolute values here

code line Since there are 60000 milliseconds in each minute this line should be a3=a3+60000. That is if you are intending to increment the time value by one minute changes with this button.

You could consider holding your values for second and minutes as integer units and converting them to milliseconds to be added together in line 125.

a2 would be a value held in seconds not milliseconds

a3 would be a value held in minutes not milliseconds

line 125 would be

delay = a1 + (a2 * 1000) + (a3 * 60000);

That change would eliminate the need for two of your variables delay_min and delay_sec. you would only require one large (32 bit) variable

code lines 134,135,136,137,138, 139 you could consider to a single lcd_write_string(PSTR() line formatted to show your delay timing selections selection.

I am not certain how clear or helpful any of this is. Many other memberson this form are much better at wtiting code then I am perhaps someone else will also post .

Darryl

April 21, 2012
by jfreethy
jfreethy's Avatar

Thank you for the comments sask55 I will review the changes that you suggested. Ans make some changes.

April 21, 2012
by jfreethy
jfreethy's Avatar

After making some of your changes noted above i was able to extend the range of time out further for my needs. Thank you so very much! I knew that if i asked someone would be able to help me. On ward and upward to the next steps.

j

April 21, 2012
by sask55
sask55's Avatar

That's great!

Happy to be of some help. I think you will find this a very frendly, interesting and useful forum.

Post a Reply

Please log in to post a reply.

Did you know that reading a double floating point variable with scanf requires "%lf" for "long float"? Learn more...