E/X-Mag Microcontroller Programming (Atmel AT90S2313)

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • LorneCash
    Got XMOD? www.NiedTech.com
    • Aug 2005
    • 365

    #31
    Originally posted by bit-wizard
    Definitely use the hardware timers. Cycle counting is possible, but accuracy depends on several factors. First, most AVR instructions are single cycle, but NOT ALL instructions. Jumps, for instance, can take more than 1 cycle. Second, if you are using interrupts, they would throw off your cycle-count based timing because they can occur unpredictably.

    Configuring the timers can be a bit of a pain initially, but it is well worth it in terms of the accuracy and flexibility that it allows. They make it much easier to change your code and functionality without having to count cycles by hand to make sure that you have just blown your timing by adding a few more instructions. In my experience, the overall project will be made much simpler in the long run if you use the hardware timers.


    bit-wizard

    I thought i read somewhere that this chip doesn't have true interrupts.

    The other thing is that the hardware timers only have certain resolutions built in(1,8,64,256,1024) . Maybe i just need some help understanding them, but if i want a timer that is exactly 30ms for the solenoid I can't use 8 because 8x4=32 now i think that is in cycles so that's actually is 4ms but either way how would i get it to branch when a value in milliseconds is hit how do i do the calculation with the timer and do i have to take into consideration the time (lines of code) between when the timer actually ends to when it is detected and when the next operation is starting?

    I hope that made sense it's still a bit fuzzy to me.

    Comment

    • Miscue
      Super Moderator

      • Oct 2000
      • 7105

      #32
      Originally posted by LorneCash
      I thought i read somewhere that this chip doesn't have true interrupts.

      The other thing is that the hardware timers only have certain resolutions built in(1,8,64,256,1024) . Maybe i just need some help understanding them, but if i want a timer that is exactly 30ms for the solenoid I can't use 8 because 8x4=32 now i think that is in cycles so that's actually is 4ms but either way how would i get it to branch when a value in milliseconds is hit how do i do the calculation with the timer and do i have to take into consideration the time (lines of code) between when the timer actually ends to when it is detected and when the next operation is starting?

      I hope that made sense it's still a bit fuzzy to me.
      Urm.... this isn't as complicated as you are making it out to be... just think about it a bit and figure out a way to do it.

      Comment

      • Miscue
        Super Moderator

        • Oct 2000
        • 7105

        #33
        Originally posted by LorneCash
        OK midterms are over time to get back into this...

        I have been looking at the timer stuff again and was reading in the AT90S2313 User Guide about Timer/Counters. Because of the nature of the timers needed for this project (30ms) I thought it would be easier to just execute a loop for a certain number of cycles based on the frequency of the chip. If i remember correctly the chip is a 4MHz chip so 4 instructions should equal 1ms.

        Is this the best way to go about this or should i try to use the Counters?
        4 instructions = 1ms? 4,000,000 (cycles/second) / 1,000 (ms/second) = 4,000 (cycles/ms).

        Like bit-wizard mentioned... one instruction does not necessarily take 1 clock cycle. It can be done without the timers... but you can also run around with scissors and laces untied.

        Comment

        • moppedclean
          Registered User
          • Feb 2005
          • 7

          #34
          Well, I am very familiar with programming PIC's but I'll see if I can lend some of experience to use with AVR's.
          To be honest, I use loops for all of my timing. The easiest way I've found is to create a subroutine that has a timing delay of 1ms. Just look at the instruction set summary and see how many clock cycles each instruction takes. Each clock cycle should take 1/4 us. Once you have the subroutine of 1ms, timing is really easy. In lame programming it would look like this:

          move #ms in to count1

          loop
          call subroutine for delay of 1ms
          decrement count1 by 1
          test to see if count 1 is zero
          if not zero, go back to loop
          if zero, timing operation done.

          It depends on what you have interrupts doing to determine whether you should worry about them happening during a timing loop and screwing it up. In my case, I have only used interrupts for turning the gun off, so as you can see in this case, it really isn't an issue. But say, if you had a button that was an interrupt used for turning the eye on/off, and it flashed an led to indicate that, then yes it could throw off your timing if it happened in the middle of the loop.

          The free counting timers as mentioned are also another valid option. Just from my experience with PIC's, it is an 8-bit register that increments every cycle unless some type of scaler that was mentioned is put on the timer- and then when it overflows an interrupt is triggered. What I would do is set the mutiplier/prescaler to 1024. Then an interrupt would be triggered approximately every .25 ms. Then you can use an inner loop of 4 to time 1ms and the outer loop to time the # of ms you want.

          I think I might have to get in to programming AVR's. I've always wanted to program a new chip for my Tribal BBT and it might be kind of fun to get in on this project.

          Comment

          • Miscue
            Super Moderator

            • Oct 2000
            • 7105

            #35
            Originally posted by moppedclean
            Well, I am very familiar with programming PIC's but I'll see if I can lend some of experience to use with AVR's.
            To be honest, I use loops for all of my timing. The easiest way I've found is to create a subroutine that has a timing delay of 1ms. Just look at the instruction set summary and see how many clock cycles each instruction takes. Each clock cycle should take 1/4 us. Once you have the subroutine of 1ms, timing is really easy. In lame programming it would look like this:

            move #ms in to count1

            loop
            call subroutine for delay of 1ms
            decrement count1 by 1
            test to see if count 1 is zero
            if not zero, go back to loop
            if zero, timing operation done.

            It depends on what you have interrupts doing to determine whether you should worry about them happening during a timing loop and screwing it up. In my case, I have only used interrupts for turning the gun off, so as you can see in this case, it really isn't an issue. But say, if you had a button that was an interrupt used for turning the eye on/off, and it flashed an led to indicate that, then yes it could throw off your timing if it happened in the middle of the loop.

            The free counting timers as mentioned are also another valid option. Just from my experience with PIC's, it is an 8-bit register that increments every cycle unless some type of scaler that was mentioned is put on the timer- and then when it overflows an interrupt is triggered. What I would do is set the mutiplier/prescaler to 1024. Then an interrupt would be triggered approximately every .25 ms. Then you can use an inner loop of 4 to time 1ms and the outer loop to time the # of ms you want.

            I think I might have to get in to programming AVR's. I've always wanted to program a new chip for my Tribal BBT and it might be kind of fun to get in on this project.
            This is a bad way to do it... he should stick with the timer interrupts.

            Comment

            • moppedclean
              Registered User
              • Feb 2005
              • 7

              #36
              No, it's not a bad way to do it- just a different way. It works perfectly fine and is incredibly accurate. I'm not sure if the Atmel micro's have more than one free counter, but if they don't, I would make use of that free counter for the automatic turn off feature.

              Comment

              • Miscue
                Super Moderator

                • Oct 2000
                • 7105

                #37
                Originally posted by moppedclean
                No, it's not a bad way to do it- just a different way. It works perfectly fine and is incredibly accurate. I'm not sure if the Atmel micro's have more than one free counter, but if they don't, I would make use of that free counter for the automatic turn off feature.
                I agree that it's different... and that is all.

                Does it work? If you make the rest of your code accomodate it... yes. This is silly if you don't have to do this.

                Is it elegant? No.

                Could it become problematic? Yes.

                Does it offer advantages over using interrupts? No.

                Whether it "works" or not doesn't mean it's good. You can wrap towels around your feet to use as shoes... and this "works" too.

                Comment

                • athomas
                  Of course it works-its AGD
                  • Jan 2002
                  • 8039

                  #38
                  I agree that using interrupts has its advantages. The problem with not using them, is you can get caught in the loop where you can't do anything until it is finished. for that time period, no outside input is possible. Using interrupts, you can continually sample your inputs and control your outputs.
                  Except for the Automag in front, its usually the man behind the equipment that counts.

                  Comment

                  • bit-wizard
                    Registered User
                    • May 2005
                    • 205

                    #39
                    If your micro is running at 4Mhz, you can get the 30ms "tick" rate that you want with the 16 bit timer in the 2313.

                    Choose the /64 prescaler setting. This results in a count frequency of 4000000/64 = 62500 counts per second. You want the timer to "time out" at 30ms, so .030 * 62500 = 1875. Therefore, set the timer up for compare-match mode and set the OCR1A match compare registers to 1875 (don't forget these 2 8 bit regs must be set in the proper order). Start the timer.

                    You have 2 main methods to handle a "time out".
                    1) Set up the match compare interrupt. It will be generated every 30ms. You can perform your periodic code in this interrupt service routine
                    2) Otherwise, you could just poll the OCF1A bit in the TIFR register. It will be set to a '1' by the hardware everytime the timer reaches 30ms. Don't forget that you will have to manually clear it after you read that it is set to a '1'. So essentially, you'd have a test in your main loop that looks at the value of OCF1A, and whenever it is set, you branch and perform your periodic code.

                    Either of these approaches will provide you with a stable, accurate time base. Method 1 is more precise, but a bit more challenging if you aren't familiar with programming interrupts. Method 2 is easier to implement, but can be slightly less accurate than method 1.

                    Best of luck. Keep hanging in there with this project

                    bit-wizard



                    Originally posted by LorneCash
                    I thought i read somewhere that this chip doesn't have true interrupts.

                    The other thing is that the hardware timers only have certain resolutions built in(1,8,64,256,1024) . Maybe i just need some help understanding them, but if i want a timer that is exactly 30ms for the solenoid I can't use 8 because 8x4=32 now i think that is in cycles so that's actually is 4ms but either way how would i get it to branch when a value in milliseconds is hit how do i do the calculation with the timer and do i have to take into consideration the time (lines of code) between when the timer actually ends to when it is detected and when the next operation is starting?

                    I hope that made sense it's still a bit fuzzy to me.

                    Comment

                    • Miscue
                      Super Moderator

                      • Oct 2000
                      • 7105

                      #40
                      30ms is no good... it needs 1ms ticks.

                      Comment

                      • bit-wizard
                        Registered User
                        • May 2005
                        • 205

                        #41
                        Not necessarily true. Most mechanical switches take at least 10ms to finish "bouncing", so 5 or 10ms is a decent interval to check. Even if the Emag does use a hall switch, a similar check interval is warranted. We are talking about 1/100 of a second, and based on human reaction time, +/- 10 or 20 or 30ms is still faster than someone can pull. So while 1ms would work, there is nothing that says that it "needs" a 1 ms tick.

                        The reason I included the info for 30ms is because that is what he said he was trying to get. If he wants a different interval, he can compute it using the same method that I illustrated. I would shoot for somewhere between 2 and 10ms if I were doing it myself.

                        Hope this helps.

                        bit-wizard


                        Originally posted by Miscue
                        30ms is no good... it needs 1ms ticks.

                        Comment

                        • Miscue
                          Super Moderator

                          • Oct 2000
                          • 7105

                          #42
                          Originally posted by bit-wizard
                          Not necessarily true. Most mechanical switches take at least 10ms to finish "bouncing", so 5 or 10ms is a decent interval to check.
                          Hehehe. Yeah... well. Paintball seems to ignore this line of thought.

                          The 1ms resolution... was for adjusting your BPS cap mostly. And... I discovered that there is about a 1ms tolerance... for whether the "4.x FA problem" shows up or not... and whether the marker shoots or not. Took me longer to figure out why this is... than it did to write the whole thing.

                          Comment

                          • bit-wizard
                            Registered User
                            • May 2005
                            • 205

                            #43
                            Interesting. I can see your point ... if you are trying to adjust the number of balls per second around 20 or above, you do get down to increments of 1/1000ths of a second (amazingly). So in other words, your statement of the need for 1ms tick resolution is based on the resolution of the adjustment that one tries to make, not any switch reading or debouncing that must take place.

                            If he wants to use the 1ms tick, it can be obtained by using the /8 prescaler with the match compare value set at 500.

                            bit-wizard

                            Originally posted by Miscue
                            Hehehe. Yeah... well. Paintball seems to ignore this line of thought.

                            The 1ms resolution... was for adjusting your BPS cap mostly. And... I discovered that there is about a 1ms tolerance... for whether the "4.x FA problem" shows up or not... and whether the marker shoots or not. Took me longer to figure out why this is... than it did to write the whole thing.

                            Comment

                            • LorneCash
                              Got XMOD? www.NiedTech.com
                              • Aug 2005
                              • 365

                              #44
                              Originally posted by bit-wizard
                              Interesting. I can see your point ... if you are trying to adjust the number of balls per second around 20 or above, you do get down to increments of 1/1000ths of a second (amazingly). So in other words, your statement of the need for 1ms tick resolution is based on the resolution of the adjustment that one tries to make, not any switch reading or debouncing that must take place.

                              If he wants to use the 1ms tick, it can be obtained by using the /8 prescaler with the match compare value set at 500.

                              bit-wizard
                              Just so I'm clear on the agreed best method...

                              1. Use the Timer/Counter on the chip
                              2. Set the prescalor to 8
                              3. Make a 1ms tick by counting the timer 500x
                              4. place the 1ms loop inside a loop that will run a given number of times so it can be used for multiple timers
                              5. Set the given number to 30 and call the Subroutine for the Solenoid timer.

                              I'm working with the microprocessors professor who seems very helpful so I want to make sure and do things the best way not the easiest way.

                              Where should i use the interrupts vs polling? I know the argument about using interrupts for detecting a trigger pull that way it is never missed but realistically i know that isn't necessary. I can't think of an example of when two things would ever need to happen at once so it seems to me that i could just use poling for everything and interrupts to incrament/decrament the "bucket" when the timer overflows... any thoughts?

                              Comment

                              • bit-wizard
                                Registered User
                                • May 2005
                                • 205

                                #45
                                My recommendation

                                I would certainly recommend that you make use of the on-chip timer hardware. If you are interested in 1ms resolution, as Miscue suggests, then you would configure the timer to use the divide-by-8 prescaler setting. You would place the value 500 in the match-compare registers. See my previous 11/7 post for details. Also, read the 2313 datasheet concerning the 16-bit timers. Your microprocessors prof should be able to explain this to you if you tell him what you are trying to accomplish (using the 16 bit hardware timer to generate a periodic 1ms tick interrupt).

                                If I were doing this project, I'd set the timer up to generate a periodic interrupt. This interrupt would occur every 1ms if you set the hardware up as previously described. You would then have this interrupt 'inc'rement a register. If it is only an 8-bit register, you will have a maximum timeable intervale of 255/1000=.255s. If you use a 16-bit register combination, then you can time up to 65.535s. You could then use this timer value in your foreground (main-line) code for timeout, debouncing, solenoid triggering, etc.

                                As a note, be sure that if you are using a 16-bit register combo for timing, that you disable interrupts momentarily around the place where you access it in the main line to prevent an interrupt from changing the value of it after you've only read 8 of the 16 bits.

                                I'd use polling to check the trigger input. No real need for an interrupt there assuming that the rest of your code isn't too huge or slow. If you use the timer to generate a tick interrupt which will automatically increment your "ticker", then you can compare to it to generate timeouts and such. For example, if you want to delay for 3ms, you would
                                1) disable interrupts
                                2) read your ticker 16 bit register into a working register pair
                                3) reenable interrupts
                                4) Add 3 to the value in your working register
                                5) enter a loop where you
                                a) disable interrupts
                                b) read the ticker registers into a second pair of working registers
                                c) reenable interrupts (because you want them disabled for the minimum possible amount of time)
                                d) compare the value you just read to the value you computed in step 4
                                e) when they are equal, you have reached your delay interval

                                Timing this way will be accurate to within 1ms. For instace, if you are trying to delay for 3ms this way, you will be guaranteed to have delayed between 2 and 3ms. If you need an absolute minimum delay of 3ms, then you would set the delay value to 4ms, which would delay between 3 and 4 ms guaranteed.

                                bit-wizard

                                Comment

                                Working...