OnStep telescope control on teensy.

Status
Not open for further replies.
One other minor detail about ARM interrupt priorities is how the 8 bit numbers are mapped onto the hardware's actual capability.

Priority numbers are from 0 (the highest priority) to 255 (the lowest). But the interrupt controller is limited in how many levels of interrupts it can actually nest. On this chip, it's 16 levels. So on this chip, these are the distinct priority levels:

Code:
  0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240

If you set 2 interrupts to priority 64 and 69, they'll actually be the same priority. ARM designed it this way so code is more portable from one chip to another. For a chip that only implements 4 levels of nesting, only 0,64,128,192 would be distinct, but you can still use the same numbers on both chips.
 
I figured this more advanced chip would have interrupt priority levels. I was disappointed by their absence on the Atmel Mega's. Anyway millis() and Timer1 must never be skipped, if they happen a little late that's ok. Timer3 and Timer4, ideally, need to always happen right on time. How about other possible interrupt sources, like that USB port for example, any idea of how long things might get tied up for (if at all) servicing that?

[edit: now that I'm awake, I see that it you say that the USB will be interrupted - which is nice. I'll move the millis() timer down one priority level from the motor interrupts so it doesn't bother them. Timer3/4 will still overlap and cause some jitter at high speeds, but it will be less pronounced since the ISR's execution times are less.]
 
Last edited:
USB defaults to priority level 112. It's not really critical, timing-wise, but delaying the USB ISR more than about 8 to 15 us could result in less USB bandwidth being available. Even then, USB serial should be be much faster than Arduino Mega using slow hardware serial.
 
A question Paul, when you call IntervalTimer's begin() function to reconfigure for a new interval... what happens to the prior interval that's counting up to the compare value when this happens? OnStep needs a smooth transition from one interval to another, we're calling this thing and adjusting the rate every ?mS while ramping up/down. :)
 
Jerry, Could you email me a copy of the OnStep.ino file you're using so I can see the way you have it configured.
 
I am using Christoph's fork from here with no modifications. I was just mostly seeing if the software would connect last night. https://github.com/crteensy/OnStep

I played with it some more last night and I could get it to goto in stellarium mode but when it gets to the location it stops tracking. I downloaded StellariumScope, a secondary program that allows you to use ASCOM setups with stellarium, and it tracks and I can usually slew to different locations. It is kind of flakey, not sure if it is a software problem on the stellarium side or what, sometimes it works, sometimes it does not.

I also tried POTH Hub which gives you a little controller and it wont let me unpark the scope. The button just returns back to the original state after you click it.

I get it hooked up to the oscilloscope tonight and take a coupe screen captures.
 
Ok, that's more like it... A little flaky but kind of sort of working, I wonder if serial I/O on the Teensy is just hanging on by the skin of it's teeth for some reason or if a timing issue exists between my ASCOM driver and this Teensy OnStep. These Teensy's don't try to hardware handshake the virtual serial port do they?

About OnStep... When powered on the default is to assume the mount's in the Polar Home position. Tracking is disabled. If no park position has been set, the mount will report that it's not parked. POTH/ASCOM can turn the tracking on, but it's off by default until you either start an align or unpark (which doesn't become available until you set a park position and park the mount.) You have two options to do the alignment, a bluetooth serial adapter on a serial port and my Android App (running on a phone/tablet) as a hand controller or my Sky Planetarium software on Windows. Once a park position has been set, POTH should park and unpark the mount correctly.
 
Last edited:
I wonder if serial I/O on the Teensy is just hanging on by the skin of it's teeth for some reason or if a timing issue exists between my ASCOM driver and this Teensy OnStep. These Teensy's don't try to hardware handshake the virtual serial port do they?
So there appears to be a bottleneck related to serial output? AFAIK, the Serial driver will buffer single byte writes and combine them in larger packets. These are then sent to the host. This buffering is important, as there is (I'm not 100% sure here) a limit of 1000 USB transfers per second. So I'd say it's not the Serial driver.

The Serial driver does not hardware handshake unless you explicitly tell it to.
 
So there appears to be a bottleneck related to serial output? AFAIK, the Serial driver will buffer single byte writes and combine them in larger packets. These are then sent to the host. This buffering is important, as there is (I'm not 100% sure here) a limit of 1000 USB transfers per second. So I'd say it's not the Serial driver.

The Serial driver does not hardware handshake unless you explicitly tell it to.

Excellent, thank you. I double checked ISR rates and that looks fine too (my worries were over something bringing the main-loop to a crawl during fast slews.)

I almost wonder, from Jerry's description, if OnStep isn't really working correctly so far. The only behavior out of the ordinary seems to be with "StellariumScope." And even with that, it occurs to me that a safety feature of OnStep is maybe causing some confusion here... When slewing to an object, if another slew is requested before the first is done, OnStep will stop the mount. When a slew is finishing up you need to wait for a couple of seconds before requesting another slew, even after the target indicator in your program of choice appears to stop moving.
 
On Teensy 3.1, when you use Serial.print(), your data is written into USB packet buffers. Unless there's no buffers available, which shouldn't really happen under normal circumstances, Serial.print() should always return quickly.

By default, there are 12 of these USB packet buffers, each capable of holding 64 bytes. Two are normally queued to receive incoming data, and if the PC has transmitted data that hasn't be received with Serial.read(), more of the buffers might be used up holding that data. Normally, about 8 to 10 buffers ought to be available for Serial.print().

All USB endpoints automatically have end-to-end flow control. If the PC isn't ready to receive, the data simply waits in those buffers until the PC is able to receive it. But on Windows, Linux and Mac, the USB serial driver almost always receives data as rapidly as possible and holds it in big buffers on the PC side until the PC-side program (eg, the Arduino Serial Monitor) actually reads it.

Exactly when the PC reads the packets depends on the USB host driver and host controller chip, and how they interact with the application software running on the computer. There are lots of combinations. As you might expect, the drivers on Windows aren't nearly as good as those on Linux and Macintosh. But on all 3, the tendency is to read as many packets as Teensy is capable of sending without any delay, then stop as soon at Teensy can't reply immediately with another packet. Some versions of Windows won't retry again until the next 1ms USB frame. Windows also won't try again quickly if the application software issues small-size read requests. Macintosh is particularly good about dealing with small size requests efficiently, and Linux is somewhere in the middle. All 3 work really well if the PC-side application uses large blocks. But even on Macs, the way the application software is written has a substantial effect on the USB bandwidth utilization. The effect is particularly severe on Windows.

On Teensy 3.1, the packets that get queued up by Serial.print() and Serial.write() are given to the USB hardware, which can have at most 2 packets ready to transfer. So after each packet is transmitted to the PC, an interrupt is needed to reconfigure the USB hardware with another packet from the queue. On USB, each 64 byte packet takes about 6.42 us, factoring in USB protocol overhead. If the USB interrupt is delayed by 2 of these 6.42 us packet times, another packet can't get ready to be sent, so the USB hardware will automatically answer the USB host controller chip with a NAK response. That's not the end of the world, but it does mean those queued packets will tend to sit in memory until the host controller decides to start asking for data again. With some computers and Microsoft Windows, that might be an entire millisecond.

Normally, you don't need to worry about all this stuff. The USB stack takes care of everything. Normally on Teensy 3.1, interrupts run very quickly, so the USB interrupt doesn't tend to get delayed by 12 us.
 
I should mention the USB interrupt defaults to priority 112 and the hardware serial interrupts default to 64. Almost all others default to 128, including the interval timers.

You should definitely raise the priority of those interval timers, so they interrupt the USB and serial code, rather than allowing serial and USB to interrupt the timers.
 
A very high speed command channel isn't really important here. My ASCOM driver that glues much of this together on the PC has a 2 second receive timeout. The most timing sensitive thing folks do with 'scopes is guide during imaging. Little corrections to the mount's tracking are sent over to form a feedback loop. But the exposures used for guiding are the dominant source of latency and are almost always in the 1/2 second to 5 second range... then the image data has to move to the computer... then guide software has to decide what it's got... the :Mgdnnnn# command's trip across the USB interface doesn't really amount to much no matter how you slice it.

I do read data out of the controller when initially connecting, might amount to a couple of K bytes and I'm sure that'll go way faster.
 
I should mention the USB interrupt defaults to priority 112 and the hardware serial interrupts default to 64. Almost all others default to 128, including the interval timers.

You should definitely raise the priority of those interval timers, so they interrupt the USB and serial code, rather than allowing serial and USB to interrupt the timers.

As soon as I get the hardware I'll make the changes and check it out. Still wondering what that rate reprogramming outside of the ISR will do, that didn't work well on the 2560 but I possibly understand things a bit better now...

Timer3 and Timer 4 on the Mega256... Looking it over, I'm wondering if I should move the pre-scaler programming into the ISR (form the control reg value as is, but drop it into a variable and set the register in the ISR). Instead of controlling inside of the ISR, I could possibly even calculate a new counter value for the Interval outside of the ISR to correct for the timing havoc that changing the OCR value (and pre-scaler) brings, but it would be much more complicated.

With the Teensy, we have clocks to burn in those ISRs... Possibly the stepper drivers won't work as is because it's too fast. One option would be to use a second OCR (do we have two?) to trigger another beforehand to pull the step pin low (say 4) uS before the actual ISR runs. Another solution, that would possibly kill two birds with one stone, would be to move the call to your timer.begin() into the ISRs.

[Edit: please feel free to correct me if I'm going wrong here, I'm certain that you guys know more about this stuff than I]
 
Last edited:
hjd, I downloaded your Sky Planetarium software and it does let me park and unpark now that I set a location. The goto command is still flaky. Sometimes it will slew to a location, sometimes it will not.
 
hjd, I downloaded your Sky Planetarium software and it does let me park and unpark now that I set a location. The goto command is still flaky. Sometimes it will slew to a location, sometimes it will not.

I'll have a look at it once my Teensy is in my hands. I have stepper motors and drivers around to setup a test and evaluate it's performance too.
 
I ordered a bluetooth module today as well as the 26ls31 line drivers for my servo drives. They should be here next week and then I can actually make something move.
 
I ordered a bluetooth module today as well as the 26ls31 line drivers for my servo drives. They should be here next week and then I can actually make something move.

Ok, I have the Teensy.

Seemed a little erratic at first, "Sky Planetarium" locked up at one point. I immediately dropped the clock from the default 96 back down to 72MHz, and then spent about an hour messing with it without any sign of trouble. CdC, POTH, "Sky", Stellarium, all worked perfectly without a single hiccup. Lots and lot of slews.

Then I attached stepper driver and spun a Nema17 200 step motor... The good news is that it seems to work. The bad news is, it doesn't seem very smooth, I will investigate.
 
Wow, that was fast. I look forward to see where you get.

And thanks for conceding to my selfish request to get this working with a Teensy!
 
Wow, that was fast. I look forward to see where you get.

And thanks for conceding to my selfish request to get this working with a Teensy!

I have everything around already for testing, just needed to solder a header on and plug in. Which reminds me, I moved the RA pin assignments to keep them all on one side of the board so I can just plug a jumper in (now, for the Teensy, they're on pins 10,11, and 12).

Again, I have my own reasons for getting this working too, I want double precision floating point mainly.

The version I'm testing has several changes already, most importantly the addition of the interrupt priority setting code. Also, earlier I noticed that the motor wasn't reaching the correct speed during slews maybe a third of the correct rpm. I inserted a 2uS delay in each motor ISR between pulling the step pin low and back to high, which has the motor running faster and smoother. Still not like it should be though... at low speeds it runs a bit rough, between it smooths out, up high it stalls. I'm using the same exact setup for testing as with the Mega2560. This driver/motor/voltage would spin at a 24uS rate without stalling before so the timing of step pulses is not what it was.
 
Well, either way thanks.

I got my Bluetooth module and the line drivers today. Going to dig out a breadboard and wire something up.
 
Well, either way thanks.

I got my Bluetooth module and the line drivers today. Going to dig out a breadboard and wire something up.

Made some progress today, can now spin that stepper motor faster at 12VDC than with the Mega2560 OnStep (stable at a 16uS step pulse)... suppose that's saying something, but it still seems to run a little rough. The updated source is on my Github, but hang on for an updated ASCOM driver to match... I made a minor protocol change for better LX200 compatibility in another area.

This is encouraging,
Howard
 
OK, i will give it a try soon.

16us is getting a little long for a pulse. Most stepper drives like a pulse anywhere from 1 to 5us.
 
OK, i will give it a try soon.

16us is getting a little long for a pulse. Most stepper drives like a pulse anywhere from 1 to 5us.

The pulse width is about 2.5us probably, what I mean is that it's taking a micro-step every 16us. So, this 200 step motor (16x micro-stepping) is running at about 20 rps. I lowered that pulse width to about 1.5us and ran it again this morning, not perfect but even smoother running now.

I'm still reading up on the Teensy's timers, starting to understand them better - I have fixes to make. :)
 
My iphone cant see the BT module. I will have to try my android tablet.
Yes, mobile devices + bluetooth modules = pain. You'll sort it out, I'm sure. You said that you're "not so hot with the software side of things" when this thread started, but you needed just some small hints and example code to get this far! So this won't be a show stopper.
 
Status
Not open for further replies.
Back
Top