Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix iguider issues #2012

Merged
merged 5 commits into from
Mar 7, 2024
Merged

Fix iguider issues #2012

merged 5 commits into from
Mar 7, 2024

Conversation

beaglebot
Copy link
Contributor

@beaglebot beaglebot commented Mar 1, 2024

I've resolved the exposure issue #1722 with the iOptron iGuider/iPolar cameras.

Unfortunately fixing this has brought up another problem with excessively slow capture startup times. I've partially resolved this, however there's still a reliability issue where the camera sometimes refuses to start after being stopped, or ignores exposure commands.

Any suggestions on dealing with this last issue would be appreciated!

Notes on Exposure Issue

The iGuider manual and ASCOM dialogs give the impression that negative values need to be used to set the Absolute Exposure time on the camera. This turns out to be not true. Sniffing the USB bus while changing exposure settings in ASCOM shows the negative values do not get sent to the USB Absolute Exposure Controls. Instead somewhat conventional ticks are sent. See the table below:

Duration (s) Value from USB sniff
0.01 1
0.02 2
0.05 5
0.1 10
0.2 20
0.5 39
1 78
1.5 156
2 312
2.5 625
3 1250
3.5 2500

By 'somewhat', I mean that the ticks are not linear with respect to duration. It appears they are linear until 0.2 seconds, then exponential afterwards. Presumably this is done to give more resolution at lower exposure times. We can recover the formula for the exponential equation by assuming 4 seconds corresponds to 5000 ticks (the max). This gives us:

        ticks <= 0.2 ? duration * 100 : 19.53 * pow(4, duration)

Where the constant 19.53 is 5000 / 4^4. This matches the values in the table exactly when rounded.

Plugging in this conversion factor works, and the resulting frame timings in the debug logs are correct.

See ddce625

Notes on the slow capture start up issue

This brought up another issue. If you attempt to start the capture with a multi-second exposure time, the camera takes many, many seconds before delivering the first frame. For example:

Initial exposure time (s) Delay before first frame delivered (s)
1.0 4.0
2.0 8.0
3.0 12
4.0 27

This looks exponential-ish, as if there's a delay somewhere in the driver or camera based on the tick count.

ASCOM seems to deal with this by rarely shutting down the stream. As soon as the ASCOM driver is activated, the camera immediately begins sending frames over USB, which presumably the driver just discards. Clicking stop/start in PHD doesn't result in any USB commands being sent to the camera - this must just affect whether the driver forwards the frames to PHD or discards them. Even after disconnecting the camera in PHD, the frames continue to be sent over USB. A little wasteful perhaps, but it seems to work.

A dirty hack to get around this is to set the initial exposure to 0.01s (1 tick), start the capture, wait for the first frame to be delivered, then set the exposure to the desired value (earlier doesn't work). This works, and results in a delay of about 150ms, which is acceptable. As long as the stream is shutdown lazily, rather than immediately after a frame is delivered, PHDs frequent frame requests don't incur this delay and everything works well.

See e0b86fe

*** Ongoing issues

Well, almost. I can get some reasonable runs with PHD where everything works: I can stop and start the capture, set different exposure rates and gains successfully, however at some point something fails and the capture won't restart.

Occasionally when this happens, I can issue repeated IOCTLs to abort the capture, or re-set the values of USB controls, and this will restart it, however many times this does not work. When attempting to change the 'Capture Size' I get an 'Resource busy' error, suggesting the driver/camera wasn't correctly shutdown.

Occasionally, it will restart but run at 9 or 20fps, and ignore attempts to change the exposure, again as if the driver/camera is stuck in some other mode.

This doesn't occur on windows. One difference is that when ASCOM needs to stop the capture or change a control it issues an ABORT_PIPE URB followed by a SYNC_RESET_PIPE_AND_CLEAR_STALL URB. Linux/libuvc/v4l2 doesn't do this and just issues the ABORT_PIPE URB.

There's an interesting comment around this in the libuvc source: https://github.com/torvalds/linux/blob/87adedeba51a822533649b143232418b9e26d08b/drivers/media/usb/uvc/uvc_video.c#L2254. In our case the interface alt_setting is changed after the ABORT_PIPE, so alt_setting is still set to 6, so the branch in the code above isn't taken, and the usb_clear_halt isn't called.

I could try tweaking this function in the kernel to see if it fixes our problem, but even if it did, I imagine it's hard to get a patch applied to the kernel - I can't imagine linus risking breaking a bunch of UVC cameras for our iGuider.

Any thoughts/suggestions very welcome!

@knro knro self-assigned this Mar 1, 2024
@knro
Copy link
Contributor

knro commented Mar 1, 2024

That's some great analysis @beaglebot , the changes I've made recently as I have access to iGuider and was never able to control it properly before. I concur the relationship isn't linear but I got confirmation from iOptron that the absolute exposure is interpolated differently within the camera from the standard absolute_exposure definition in units of 100 uS.

  1. Changes to the Kernel could fix this? Even if it doesn't immediately apply to most of us, it will eventually land in the future (if accepted) so if you're confident with this change, I'd say go ahead as it will help other use cases as well. Did you happen to test this locally as well?
  2. I didn't test this yet with Ekos or PHD2, just tried a few simple capture sessions and it seems to hold fine, but my test wasn't extensive in any way. How often do you get the PHD2 capture issues? does it occur after 30 seconds? 5 minutes? or random?

@beaglebot
Copy link
Contributor Author

beaglebot commented Mar 1, 2024 via email

@knro
Copy link
Contributor

knro commented Mar 6, 2024

Let me test and see if this works with iGuider, thanks!

@beaglebot
Copy link
Contributor Author

Ok, getting somewhere.

I tried all of the UVC quirks and USB quirks that seemed relevant, but nothing helped. I tried modifying the uvc_video_stop_streaming function in uvc_video.c in the kernel to call usb_clear_halt in the hope that that would
reset the device, but no luck.

Also, while it looks like you should be able to set any tick value, only the tick values that correspond to durations in the iOptron PDF succeed. Not sure what to do about this - round a requested duration to the nearest allowed value, except for values greater than the max which get stacked?

It seems that whenever the stream is stopped, or suspended the device risks going into a state where it either produces no more frames when is is started again, or falls back to the 'default' of 9 or 19fps.

You can also reproduce this issue quite easily from the command line:

sudo usbreset 0130:1466 # from usbutils
v4l2-ctl -d /dev/video2 -c exposure_time_absolute=78 # 1 second
v4l2-ctl -d /dev/video2 -c auto_exposure=1 # manual exposure

v4l2-ctl -d /dev/video2  --stream-mmap 3 --stream-count=3 # wait for 3 frames
# this first call to retrieve frames always succeeds, however if you call it several times more, at some point you'll either get a stall (requiring a ctrl-c), or the frames will start coming through too quickly.
# sometimes repeating the frame request will work, often it doesnt. Another call to usbreset will cause the next frame request to succeed.

The code I just pushed is working reasonably well - it needs a lot more testing, and cleaning up, but getting somewhere.

@beaglebot
Copy link
Contributor Author

I've tidied this up, and it's working, more or less.

There's still the odd hang up when the stream is closed, eg if you restart kstars/indiserver, or when changing the capture size. At this point not quite sure what we can about that other than perhaps detecting it and advising the user to plug it in again.

Let me know what you like to do with the PR. Happy to make any changes you suggest.

drivers/video/v4l2driver.cpp Outdated Show resolved Hide resolved
drivers/video/v4l2driver.cpp Outdated Show resolved Hide resolved
drivers/video/v4l2driver.cpp Outdated Show resolved Hide resolved
@knro knro merged commit c360105 into indilib:master Mar 7, 2024
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants