Arduino Single Channel Logic Analyser

I have this idea that an arduino could be used as a simple logic analyser. People without such toys asking on here for help decoding IR remote, Serial or RF transmitter data could be asked to load a sketch, attach the device and grab some data that can be used to decode/debug.
As the arduino has very little memory I figure the best way to sample data is to grab pin transition times instead of taking a sample every x micro seconds. Store the time in a circular buffer so you can start serial printing the data out ASAP while still capturing, to further extend the capture duration.
I have started on some arduino code and it seems to be working okay (still debugging it) but now the data needs displaying on the computer and this is where I'm hoping someone else will be willing/able to help.
I figure the best option to make the PC code is to use something like Processing as it's free and works on Windows, Linux & Mac.
Does anyone think this is a good idea and is willing to write/help write the processing code to realize the idea.

Attached is an idea of what the Processing output should look like though it would be single channel only. It would need ability to zoom in/out and maybe measure time between 2x user movable cursors.
Also attached is a sample dump of the serial data from this capture session. Each number is the approx duration in milliseconds since the last transition and bit zero of this number denotes if the signal is high/low (1=high, 0=low)

This is unpaid as I want the code to become public domain.

EDIT: Added current Arduino code

Sample.txt (305 Bytes)

Logic_Scanner.ino (7.77 KB)

captureMode has to be protected by a critical section in loop.

bufferWrite probably has to be protected by a critical section.

bufferRead probably has to be protected by a critical section.

This...

    if (noiseThreshold > 0){
      if (microDiff < noiseThreshold){                      // Pulse to short?
        return;                                             // Yes, so drop out now
      }
    }

...may be useless and could cause problems. I believe the hardware that detects CHANGE already has noise suppression.

        //noInterrupts();
        noiseThreshold = (unsigned long)cmdData;
        //interrupts();

...any particular reason you comment-out those two important lines of code?

  Serial.begin(57600);                                      // Fast(ish) Serial

...250000, 500000, and 1000000 are better choices for the baud rate.

Overall I like it. Karma for you.

I currently use freeMemory to show how much RAM is spare so I can eventually tweak the buffer size but I really need to know if things like the stack are dynamic and can grow into the free memory or does it have a fixed space not included in the freeMemory result. This is so if I increase ringBuffer so only 20 or so bytes remain will the stack or Serial grow into this space and corrupt?

EDIT: Added sketch

Logic_Scanner.ino (8.04 KB)

Riva:
I've hopefully protected captureMode where it counts now. I figure there is less need to protect when capture not active as ISR does not access anything but captureMode and it's byte size so will never get interrupted half way though storing a byte (I hope).

The problem is that you manipulate individual bits. captureMode has to be fetched, altered, and then stored when you change a bit. The risk is that an interrupt occurs after fetch but before store. At that point the value stored may have been poisoned.

For your PC client have a look at SUMP

I think it will do what you want, all you have to do is spit out the data in the right format.


Rob

[quote author=Coding Badly link=topic=156228.msg1173875#msg1173875 date=1364350007]
The problem is that you manipulate individual bits. captureMode has to be fetched, altered, and then stored when you change a bit. The risk is that an interrupt occurs after fetch but before store. At that point the value stored may have been poisoned.[/quote]
I think the only unprotected code now is when the capture is turned off so the ISR is only reading captureMode and not altering it.

Graynomad:
For your PC client have a look at SUMP
I think it will do what you want, all you have to do is spit out the data in the right format.

I have seen SUMP but not keen to run it as it need Java console.

Disappointingly not much takeup on this project so I have posted my current work in progress of the arduino and processing code. I'm no C++ programmer and until I started this thread had never seen processing so the code I a bit of a Frankenstein's monster.
Basically load the arduino sketch on the arduino and the processing sketch into processing. In processing, toggle the trigger direction with the green box/button. Arm the capture using the red record circle/button & stop capturing with the blue square/button. The left/right cursors keys move along the capture data and the up/down adjust the scale. Enter key resets back to start of capture data and sets scale to 1.

Logic_Scanner.ino (8.12 KB)

Logic2.pde (8.39 KB)

I can't test this because I don't have processing installed. Anyway I have a real LA so don't really have the need.

Can you show a screen shot?

Also, what sort of samples rates are you getting?


Rob

Graynomad:
I can't test this because I don't have processing installed. Anyway I have a real LA so don't really have the need.
Processing is very like Arduino IDE. Just unpack to directory and run, no install needed.
I also have LA but though something like this would be useful to those without.
Can you show a screen shot?
Attached.
Also, what sort of samples rates are you getting?
The thing is driven by event (pin change interrupt) instead of the usual time slice method and seems happy down to about 50uS or above though this would obviously fill buffer a lot quicker with lots of quick switching.

That looks pretty good actually. I've been saying for ages that if everyone had an LA we would only have half the questions on this forum, and even though you can buy a good one for $150 that's still too much for many people.

down to about 50uS

You could probably get faster, that code looks like it could be optimised a fair bit.

I think for this to be useful it has to be able to capture the 3 basic serial comms, UART, I2C and SPI as that's where a lot of people have trouble, they may have to be slowed down to do the capture but at least a user will see that the right information is being transmitted/received. If the app still doesn't work at the faster speed then that's a different problem but you know the fundamentals are in place.

Any chance of 2 channels? :slight_smile:


Rob

Graynomad:
That looks pretty good actually. I've been saying for ages that if everyone had an LA we would only have half the questions on this forum, and even though you can buy a good one for $150 that's still too much for many people.
My sentiments exactly, hence this project.

down to about 50uS

You could probably get faster, that code looks like it could be optimised a fair bit.
It will respond to shorter durations but in testing I found I had noise causing spurious triggers.

I think for this to be useful it has to be able to capture the 3 basic serial comms, UART, I2C and SPI as that's where a lot of people have trouble, they may have to be slowed down to do the capture but at least a user will see that the right information is being transmitted/received. If the app still doesn't work at the faster speed then that's a different problem but you know the fundamentals are in place.
I was mostly thinking of IR/RF signals you get from remote controls or weather station sensors but anything extra like you suggest would be useful. When I'm off shift I may get time to do more testing and will post results.

Any chance of 2 channels? :slight_smile:
It should be possible to use the other interrupt pin to give a second channel and I did think about maybe doing a standard time slice version that logs 4 or 8 channels (though this has already been done with SUMP) but that's a future version assuming I get this polished and off the ground.


Rob

Okay, so I have done some tests and the results look reasonable though could be better.

Serial 9600 & Manchester
First image (black background) is from the signal generator, second image (grey background) is the capture using arduino.

1-Wire & I2C
First image (black background) is from the signal generator, second image (grey background) is the capture using arduino.

Finally SPI clock & IR remote
First image (black background) is from the signal generator, second image (grey background) is the capture using arduino. The IR only has arduino image.

Most of them look pretty close, it dies on SPI and 1-wire by the looks of it. But the SPI is 2MHz isn't it? No chance there.


Rob

1-wire is pretty rubbish but with SPI you can at least see some structure. I think the ISR is taking to long and missing fine detail. Maybe the code can be optimized to improve this or maybe add a separate high speed capture mode.

I've been experimenting with the Input Capture Mode of the timers for fast capturing of a single boolean signal and wrote an article about it. You can capture pulse-widths of 3µs with an accuracy of 65ns with the sketch attached to the article.

The article itself is in German, but the screenshots and the code (with english comments) should be enough to understand how it works:
http://www.mikrocontroller.net/articles/High-Speed_capture_mit_ATmega_Timer

Here the direct link to the code for the Arduinos
For Uno, Leonardo and other ATmega328 based Arduinos: HighSpeedCaptureAtmegaTimer Source.zip
For the Arduino Mega2560: HighSpeedCaptureAtmegaTimerATmega2560 Source.zip

Michael

If one does not need the high refresh rate - that is, an update every few seconds would suffice - and if you need logging (Excel or notepad) then my USB HID logger may be your answer. Plus, it picks up the analog, too.

If you do not wish to mess with V-USB, use a Leonardo.

http://forum.arduino.cc/index.php?topic=135623.msg1027748#msg1027748

Ray