If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

E/X-Mag Microcontroller Programming (Atmel AT90S2313)

I am a student at UW-Milwaukee and have chosen to do an Independent Study for my final semester to write my own software for my X-Mag. One of the bigest problems was finding the connectors and making the wire harness to connect the Programmer to the Gun. I was finally able to do that and spent quite a bit of time and money but after that it's all in the code... I actually purchased the crimping tool necessary to make the cables, so if anyone else is interested in trying to program their own gun send me a Private Message or an email and we can discuss getting you setup with the hardware. (I'll tell you what to buy, you have it shipped to Me and i'll make the wire harness for you, test it and then ship it to you.)

I am opening this thread for anyone who wishes to discuss any programming problems or ideas. I had been just sending Private messages to Miscue and several others but it was pointed out to me that i should open a thread since other people might have the same questions. Hopefully this thread can follow my progress and act as a beginners guide for anyone who wishes to write their own software.

Once you have browsed through the documents and have the ability to flash in your own code you will have to start writing it. to start Look at the example files that come with AVR Studio, particularily tutor1.asm and avr108.asm which should be in the appnotes folder under the install directory. Once you assimilate this concentrate on the I/O Ports Section of the AT90S2313 User Guid (page 50) You'll need to know what devices are connected to which ports.

Here is a list of what i found when doing a pinnout of the Board. If anyone wants a full pinnout of the Microcontroller or a reverse engineered schematic on the board let me know and i'll either email it to you or post it if i get enough requests.

Can someone double check these? I haven't gotten far enough in the code to use all of them yet and it would be extreemly frustrating if i had this part wrong. Send Me a PM and i'll edit my post so as not to confuse anyone who reads this later.

I understand there is not a real time clock and that i will have to set up timers based on the clock speed. How do i go about doing that? Is there an internal counter of the number of clock cycles since power on, or do i have to incrament a register and do it all myself or what? Since i know i will need many timers is there a way to set up at least part of it as a function or subroutine or will i have to repete the code for every timer i need.

Good work. Ihave always been interested in this. Keep us posted on the progress.

Oh, another thing I was wondering, is it possible to download the code off of the controller board and look at it?

Yes, Kinda... you can download the code from one gun and copy it to another or reload it on that gun later and you can look at the code but the AVR Studio compiles it to a hex file. You can load this hex file back into the Studio and it will translate it back to assembly language but it's not really too helpful because about Even though its back to assembly there are no comments and about 25% of the stuff you do in the Studio is a function and generates assembly code that you never wrote and won't need to. Maybe it would be more useful to a more advenced programmer but I really couldn't make much of it.

Timing on the AVR

You were asking about timing ... the AVR has 8 and 16 bit timers (depending on the variant) that can be configured to time at different rates, based on the oscillator. Depending on how the prescalers are configured, you can choose the rate that it "counts" at. I've written quite a bit of code for the AVR series micro (Tiny15, 4433, Mega8, Mega16, Mega32), and could get you started on some of the low-level routines to configure the peripherals if you like.

ACE Functionality

Can someone please explain to me how to check the ACE for a signal? I tried checking it the same way i checked the Trigger (HES) but it didn't give me a signal... Do i need to send power to it somehow first and then check it?

Can someone please explain to me how to check the ACE for a signal? I tried checking it the same way i checked the Trigger (HES) but it didn't give me a signal... Do i need to send power to it somehow first and then check it?

Im pretty sure the ACE is always powered when the marker is on. I know from pics where you can see the IR light comming from the emmitter that it was 'on' eventhough the ACE was set to 0.

There should be 2 wires going to the ace board that are used: one is a +5v and the other is SIG. The board, like the rest of the gun, uses the frame as a ground, (probably the screw that hold the ACE in.)

As far as checking it for a signal, I am guessing that you would have to have the ACE set to 1 and then cover the eye sensor. Im not sure, but I would be that the SIG wire would be where you need to check. However, I am not sure of the value that you would be looking for. I dont know if its a +5v or much smaller. Remember, I am only guessing

Can someone please explain to me how to check the ACE for a signal? I tried checking it the same way i checked the Trigger (HES) but it didn't give me a signal... Do i need to send power to it somehow first and then check it?

No... it's always on. Should be pretty straight forward to get input from the ACE.

Good work. Ihave always been interested in this. Keep us posted on the progress.

Oh, another thing I was wondering, is it possible to download the code off of the controller board and look at it?

If the chip was locked, no (assuming there isn't a hack). Otherwise yes...

I think it's easier to look at what the program does on the simulator than to figure out what it's doing by looking at the assembly. Although... yeah, you can figure out exactly how it works by examining the hex file. I don't know why you would want to go through that trouble though.

This is the low voltage line. There is no dedicated pin going from the microcontroller to the warp feed specifically. The Intellifeed port shares the same line as the output line going to the solenoid.

One of the things you'll want to do is: Prime the loader if the ACE does not detect a ball... kinda makes sense... no ball = try to feed a ball! To do this, it's the same as firing the marker... but you only send a signal to the solenoid line for a short duration... just enough for your loader to pick it up... but not nearly enough to fire the marker.

This line sharing also infers that you can fire the marker via the Intellifeed cable. Also... if your loader has a problem... it can fire your marker. It is very possible to locate a cheater board in your loader.

Cable a bunch of EMags together through the Intellifeed port... fire one marker and they all shoot in unison!

I understand there is not a real time clock and that i will have to set up timers based on the clock speed. How do i go about doing that? Is there an internal counter of the number of clock cycles since power on, or do i have to incrament a register and do it all myself or what? Since i know i will need many timers is there a way to set up at least part of it as a function or subroutine or will i have to repete the code for every timer i need.

Total number of clock cycles since power on? Not that I know of.

Yeah... you can write a subroutine for the timer stuff. When the built-in timer rolls over... it results in an interrupt... have it go to a subroutine then.

Can someone double check these? I haven't gotten far enough in the code to use all of them yet and it would be extreemly frustrating if i had this part wrong. Send Me a PM and i'll edit my post so as not to confuse anyone who reads this later.

Something I wrote in '03... if it gives you any ideas on how you might want to do your timer scheme.

My shot buffering and timing scheme is completely different. What I have now is a leaky bucket approach. I have a bunch of timers that are independent of each other, instead of one clock timer. These timers are at all times counting down to 0, decremented after an interrupt. These timers are filled up to appropriate values when the trigger is pulled. About a dozen instructions control all of these timers, which greatly simplifies things.

If like timer A is not 0 (the bucket hasn't leaked out completely yet), event A cannot happen yet... it just skips that part.

Stuff like that. These events can me mixed up, it doesn't matter what order they are in really. Before, stuff had to happen sequentially... and basing everything off of one timer had it's problems - made coding larger, clumsy, and more difficult.

Also, there is now no distinction between a buffered shot and a non-buffered shot... everything is a 'buffered' shot I suppose - and my code checks the trigger only once (rather than multiple times like in Q1.1), regardless of what stage of the cycle it is in. The rule is: A shot can be buffered when the debounce timer has expired. If this is your first shot, then it's already at 0. If during a cycle, you can buffer a shot after the debounce timer expires. Now, this shot cannot be fired until the ROF timer is at 0. For your first shot, it is already 0. Otherwise it must wait for the ROF timer to expire.

This probably doesn't make sense... I'd have to use diagrams to explain it better.

Still having ACE problems

Thanks for the timer help, and I like your bucket analogy that's a good way to explain it.
can you help me a bit more with the ACE?
I had tried this a few days ago but it didn't seem to work:

sbis PINB, ACE ; See if ACE is ready (ACE=6)
rjmp ACE_Ready ; If ace is ready do the code

I noticed at the bottom of the timer code you had this exact same thing but you jumped to resetACE. How exactly does that work do i have to continuously be resetting the line to a low and a high means that it saw something since the last time i reset it?

I figured there must be a little more to it then just what I had because if it was just a matter of sensing a ball or not sensing a ball how could the difference be between ACE-1 and ACE-2. Could you please elaborate on that too? thanks.

Thanks for the timer help, and I like your bucket analogy that's a good way to explain it.
can you help me a bit more with the ACE?
I had tried this a few days ago but it didn't seem to work:

sbis PINB, ACE ; See if ACE is ready (ACE=6)
rjmp ACE_Ready ; If ace is ready do the code

I noticed at the bottom of the timer code you had this exact same thing but you jumped to resetACE. How exactly does that work do i have to continuously be resetting the line to a low and a high means that it saw something since the last time i reset it?

I figured there must be a little more to it then just what I had because if it was just a matter of sensing a ball or not sensing a ball how could the difference be between ACE-1 and ACE-2. Could you please elaborate on that too? thanks.

"ACE 1" just needed one successful read from the ACE. "ACE 2" needed like... X number of successful reads. So that ResetAce2 thing was... to reset the number of successful reads that it counted. Does it make any difference? Not that I can tell... "ACE 1" seems to be sufficient and "ACE 2" does no harm. I put two modes in there just in case...

I don't know what's wrong with your ACE.
Did you set the port resistors correctly?

If I switch the line to say "sbis PORTD, 5" it works fine when i push the bottom button so i don't think its a flaw in the logic just in how i access the ACE. All i'm trying to do is make it say READY on the Display when i have the ACE covered with my finger. I tried loading other software and the ACE works fine with that. I'm really stuck here.

Try cbis PINB, ACE ; See if ACE is ready
instead of sbis PINB, ACE ; See if ACE is ready

ACE = 6 right?

There is no instruction cbis do you mean cbi or sbic? I tried sbic... do i have to clear it or set it first to "prime" it or something? Yea, ACE=6. Just to remind you in your post #13 you used sbis to jump to resetACE... What's resetACE all doing, you said before you used some type of counter for ACE 2, but i don't have any idea what would need to be reset unless it's just the counter reset.

There is no instruction cbis do you mean cbi or sbic? I tried sbic... do i have to clear it or set it first to "prime" it or something? Yea, ACE=6. Just to remind you in your post #13 you used sbis to jump to resetACE... What's resetACE all doing, you said before you used some type of counter for ACE 2, but i don't have any idea what would need to be reset unless it's just the counter reset.

There is no priming. I told you the wrong instruction... tried to do it from memory and mixed up the instructions. Whatever is the opposite of sbis... probably sbic.

All that my ACE 2 mode does is look for X number of successful reads from the ACE - the theory was that it might be a more reliable way of reading from the ACE. Turned out to be unnecessary as far as I could tell.

Here is a silly question: Is your ACE plugged in to the board? I'd check your physical connections.

There is no priming. I told you the wrong instruction... tried to do it from memory and mixed up the instructions. Whatever is the opposite of sbis... probably sbic.

All that my ACE 2 mode does is look for X number of successful reads from the ACE - the theory was that it might be a more reliable way of reading from the ACE. Turned out to be unnecessary as far as I could tell.

Here is a silly question: Is your ACE plugged in to the board? I'd check your physical connections.

I got it, but i'm not sure i understand it completely... From what i got I had the pullup resistor for that bit on PORTB set wrong. Here's what i have now. Can you please check all 4 of the bytes i'm loading to confirm they're correct, and if you don't mind explain a bit about that.

Sorry for the runnaround I didn't understand what those 2 lines were doing... I understood the DDRx is setting the Direction, 0 is input and 1 is output, and it's not too hard to figure out if the device is input or output, but the resistors thing i don't get.

In General, how do you know what the resistor should be set to? Even though I seem to have it set correctly now I would still like to understand why... comes with being an engineer... lol.

The PORTx reg is a multipurpose register. When the DDRx reg has a '1' in a given port pin location, the port is an output, and the value placed in the corresponding PORTx bit is output on the equivalent micro pin. When the DDRx reg has a '0' in the given port pin location, the port pin is set to an input, and the value placed in the PORTx reg bit determines whether the pullup is active '1' or not '0'. If it is active, then a 20 to 100K resister internally connects the pin to VCC. This "pulls" the input up to the supply when nothing external pulls it down. So if the pin was not connected to anything externally, it would be pulled to 5V and would be prevented from being a floating input, which is a bad thing in terms of power consumption. Another reason to use pullups is if the external device that is connected to the pin is an open collector or open drain output.

So it really boils down to what the external circuitry that is attached consists of as to whether or not you want the pullups on.

I'm purely speculating since I haven't seen the schematic, but is is possible that the external device connected to the input that you had configured incorrectly as a pullup ('1') may have had an associated pulldown (external to the micro). The 2 resistors (pullup and pulldown) would look like a resistive divider on to the input pin, which could keep it from changing state depending on the relative values of the resistors.

bit-wizard

Originally Posted by LorneCash

Sorry for the runnaround I didn't understand what those 2 lines were doing... I understood the DDRx is setting the Direction, 0 is input and 1 is output, and it's not too hard to figure out if the device is input or output, but the resistors thing i don't get.

In General, how do you know what the resistor should be set to? Even though I seem to have it set correctly now I would still like to understand why... comes with being an engineer... lol.

Timers again

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?

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.