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

Hangs after a while #6

Closed
mabartibin opened this issue Jun 20, 2021 · 18 comments
Closed

Hangs after a while #6

mabartibin opened this issue Jun 20, 2021 · 18 comments

Comments

@mabartibin
Copy link

mabartibin commented Jun 20, 2021

In "loop" acquisition mode, after a few minutes (sometimes after a few seconds), no more data is acquired. Either the Girino didn’t get the message that it is supposed to acquire data, or Girinoscope isn’t happy with the response it got. Hard to tell which.

Clicking the stop button, and then restarting works.

Does this only happen for me?

@Chatanga
Copy link
Owner

You've closed the issue.. Does it means that you fixed your problem? If not, I've pushed a small update which add a trace level option in the help menu of the application. By setting the trace level to ALL, you should have more clues on which is the culprit in your problem.

@mabartibin
Copy link
Author

No, I closed it inadvertently, it seems.

I’ll try with the tracing!

@mabartibin mabartibin reopened this Jun 21, 2021
@mabartibin
Copy link
Author

It acquired 390 frames, and then died with

Jun 21, 2021 7:42:47 PM org.hihan.girinoscope.ui.UI$DataAcquisitionTask process
FINE: 1 data buffer(s) to display.

@mabartibin
Copy link
Author

Yeah well… this time around, it’s running for 10000 frames without problems. I’ll just keep the tracing on :-)

@Chatanga
Copy link
Owner

Could you characterize your signal and how you capture it (acquisition rate and trigger)? It would help me reproduce the problem at home.

@mabartibin
Copy link
Author

The signal is a sine wave from a little Wien bridge oscillator. Just to have something to plot. It oscillates between about +1V and +2.5V and goes right into A0, without the Girino electronics before it.

Screenshot 2021-06-21 at 22 09 17

Now I rewrote the ISR code of Girino to do the triggering by software. And actually quite a few other bits of Girino as well by now 😅

I daresay the hangups after some time were there already before I did most of the rewriting… but who knows.

I can do some hunting of my own to pin it down.

@mabartibin
Copy link
Author

I added some more tracing statements in acquireData and process of UI.DataAcquisitionTask.

    protected void process(List<ByteArray> byteArrays) {
        LOGGER.log(Level.FINE, "{0} data buffer(s) to display.", byteArrays.size());
        graphPane.setData(byteArrays.get(byteArrays.size() - 1).bytes);
        LOGGER.log(Level.FINE, "Done with setData");
        exportLastFrameAction.setEnabled(true);
        LOGGER.log(Level.FINE, "Done with setEnabled");
    }

and

                    if (buffer != null) {
                        publish(new ByteArray(buffer));
                        LOGGER.log(Level.FINE, "Done with publish");
                        acquisition = null;
                        terminated = !repeated;

It dies like this:

Jun 22, 2021 8:48:27 AM org.hihan.girinoscope.ui.UI$DataAcquisitionTask process
FINE: 1 data buffer(s) to display.
Jun 22, 2021 8:48:27 AM org.hihan.girinoscope.ui.UI$DataAcquisitionTask process
FINE: Done with setData
Jun 22, 2021 8:48:27 AM org.hihan.girinoscope.ui.UI$DataAcquisitionTask process
FINE: Done with setEnabled
Jun 22, 2021 8:48:28 AM org.hihan.girinoscope.comm.Serial readBytes
FINE: < 1,280 byte(s)
Jun 22, 2021 8:48:28 AM org.hihan.girinoscope.comm.Serial writeLine
FINE: > (S)
Jun 22, 2021 8:48:28 AM org.hihan.girinoscope.ui.UI$DataAcquisitionTask acquireData
FINE: Done with publish
Jun 22, 2021 8:48:28 AM org.hihan.girinoscope.comm.Serial writeLine
FINE: > (s)
Jun 22, 2021 8:48:28 AM org.hihan.girinoscope.ui.UI$DataAcquisitionTask process
FINE: 1 data buffer(s) to display.
Jun 22, 2021 8:48:28 AM org.hihan.girinoscope.ui.UI$DataAcquisitionTask process
FINE: Done with setData
Jun 22, 2021 8:48:28 AM org.hihan.girinoscope.ui.UI$DataAcquisitionTask process
FINE: Done with setEnabled

Note sure this helps?

@mabartibin
Copy link
Author

When it stops acquiring, it loops in Serial.readBytes(…) without having gotten any bytes.

Now I modified the Girino code to turn on the D13 LED in startADC() and turn it off in stopADC(). When it hangs, the LED is off.

That would mean Girino sits waiting for commands, not acquiring data, while Girinoscope waits for it to send data.

Possibly the ‘s’ is sometimes corrupted in the Serial transmission, and the system has no way of recovering.

@Chatanga
Copy link
Owner

Nice of you to have investigated that thoroughly this issue. When considering your information, I don’t think anymore that it is an annoying race condition in the Girinoscope code. I could be wrong, but it looks more like a buffering problem with the Girino and its simple protocol. Does this patched Girino.acquireData method solve your problem?

public byte[] acquireData() throws Exception {
    if (serial != null) {
        /*
         * When acquiring data in loop, give some time to the device between
         * a STOP and a START.
         */
        Thread.sleep(200);
        serial.writeLine(START_ACQUIRING_COMMAND);
        /*
         * Note that the Girino reset its buffer (with zeros), meaning we won’t
         * catch a lot of the signal before the trigger if it happens too fast.
         */
        try {
            FrameFormat frameFormat = device.getFrameFormat();
            byte[] buffer = new byte[frameFormat.sampleCount * frameFormat.sampleSizeInBit];
            int size = serial.readBytes(buffer);
            return size == buffer.length ? buffer : null;
        } finally {
            /*
             * We can only acquire a single buffer and need to stop / start to
             * get the next one. That’s how the Girino code works, but it was
             * probably a bit different during its development. In practise,
             * this 'stop' is only required when we cancel a trigger waiting.
             */
            serial.writeLine(STOP_ACQUIRING_COMMAND);
        }
    } else {
        throw new IllegalStateException("No serial connection");
    }
}

@mabartibin
Copy link
Author

I’ll try this. It’s quite likely a timing thing, because I still have the impression that it takes much longer to fail with the (slow) logging turned on.

@mabartibin
Copy link
Author

The Girino protocol could really use some improvements to make it easier to recover from error conditions.

I think ultimately, the front end code should evolve together with the back-end. E.g. I added a "continuous acquisition" trigger mode, that just acquires without triggering. Very handy to figure out at which level to set the threshold.
But of course it won’t work without the corresponding code on the Arduino.

Next project is to alternate between two analog inputs and plot two channels, either superimposed or as X and Y. But again, no use to have that in the frontend unless you use my modified Arduino code.

@mabartibin
Copy link
Author

Like this :-)

Screenshot 2021-06-22 at 22 55 12

@mabartibin
Copy link
Author

It hasn’t been hanging recently, so it seems the patch was successful.

I’ll let it run overnight and report back tomorrow.

@mabartibin
Copy link
Author

Seems to be stable now 👍

Thank you for the fix!

@Chatanga
Copy link
Owner

Good news, even if I don't reproduce the problem at home. I do reckon that the Girino protocol is fragile and crude, lacking any XON/XOFF control, but it is difficult to ask more of the small AVR chip! Beside, there was only one place where 2 commands (STOP and START) were chained without response from the device in-between. As such, the current issue, if correctly diagnosed, shouldn't crept somewhere else.

Regarding your "continuous" acquisition (the name is a bit misleading, it's more a "ASAP" acquisition, isn't it?), it shouldn't be difficult for me to integrate it since there is already a way to support custom devices with additional capabilities. That's also true for 2-Channels even if it involves a bit more work. However, for the X-Y mode, I'm not sure it would be useful in the lack of a true continuous acquisition. That being said, Lissajous figures would make for nice screenshots!

If I want to conduct some tests on my behalf, is there a way to download your code somewhere? In addition, how are you planning to multiplex mutiples channels? By interleaving the samples from the N channels into the returned data frame?

@mabartibin
Copy link
Author

mabartibin commented Jun 23, 2021

Like all the old James Bond movies taught us: it’s not an oscilloscope if it doesn’t have a Lissajous figure on it. Though with the blockwise sampling it will never have the hypnotic quality of the analog original.

So the right way would be to add a new device? That makes sense!

Doing that, one could also fix the protocol maybe, so there is a handshake for the s and S commands. And some kind of prefix on the returned buffer data to make it distinguishable from other messages?

You are right of course, „continuous” is about as wishful thinking as 150MHz sampling 😅

I can send you my changes… I could push the branch if that’s fine. But I need to tidy up a bit. Currently, it can only display two channels.

What I do for two channels is that I change the ADMUX register between ports A0 and A1 after each sample. And I check the triggering condition only on the A0 signal. Works for up to 76.9kHz sampling (i.e. 38.5 per channel), but not with 153.8 kHz. It seems by the time the ISR manages to flip bit 0 of ADMUX, the ADC has already come too far. Apart from that, there are no changes in the backend, so the buffer has one sample from A0, one for the odd numbered bytes and one for the even numbered ones.

I thought I might try more channels, but it would mean even slower sample rates, and even more complicated interrupt handlers. And they’re not needed for Lissajous figures.

@mabartibin
Copy link
Author

I now added a device ("SoftGirino" since it does the triggering in software) and a parameter Channels for that device. It basically works, also with X-Y plots.

  • the code is ugly since most of the additions are based on duplicating existing code for other parameters
  • the icons don’t look good
  • the code for the X axis in X-Y mode is a quick hack. Doesn’t even change the labels on the axis.

Do you want me to upload/push etc. the code somewhere?

@Chatanga
Copy link
Owner

Regarding the Java part, it's probably easier to simply send me your changes as an archive at [email protected]. It would be a good occasion for me to merge back the refactoring branch into the main one. For the firmware however, creating your own dedicated repository (like for other devices) would be more appropriate I think.

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

No branches or pull requests

2 participants