Really Simple Raspberry Pi Logic Analyser (Digital Oscilloscope)

The source here is an extremely simple 2 channel Logic Analyser. It shows two digital signals like an oscilloscope would, but its extremely simple and easily extendable.

For the ultrasonic distance sensor, I wanted to check my code an wiring was doing what I thought. Ideally, I would have connected up an oscilloscope and looked at the signals that way, but my ‘scope is ancient and hasn’t been used for so long I don’t exactly know where it is anymore. But I’m working with a Pi and there’s plenty of IO available and a couple of CPU cores I’m not really using either so why not make one.

The code below defines 2 pins to collect data on. These are in the wiringPi pin numbering scheme. My other code is also using these pins and has already set up the direction an pull-ups as required so I had the pinMode lines  commented out when I used it.

The basic operation is to wait until the input of channel 1 is low, then goes high. Then it takes 101 samples from the two pins with a small delay between each one. Finally it plots the traces. I use . and # for my traces as it’s nice and clear what’s high and low. I could have messed about with the line drawing characters, but keeping it simple was the priority.

// g++ -o dso dso.cpp -lwiringPi

// #includes for various stuff
#include 
#include 
#include 

// Parameters for the main code
#define LEN 101
#define INPIN1 4
#define INPIN2 5

int main (void)
{
  if (wiringPiSetup () == -1)
    return 1;

  pinMode (INPIN1, INPUT);
  pinMode (INPIN2, INPUT);

  // Optionally turn off the pullup/down resustors.
  //pullUpDnControl (INPIN1, PUD_OFF);
  //pullUpDnControl (INPIN2, PUD_OFF);

  bool ch1[LEN];
  bool ch2[LEN];

  while (true)
  {
    // Wait for trigger
    while (digitalRead(INPIN1));
    while (!digitalRead(INPIN1));

    // Sample the data
    for(int i = 0 ; i < LEN ; i++)
    {
      ch1[i] = digitalRead(INPIN1);
      ch2[i] = digitalRead(INPIN2);
      usleep(1);
    }

    // Display the data
    printf("\n\n\n\n");
    printf("\n.         .         .         .         .         .         .         .         .         .         .\n");
    for(int i = 0 ; i < LEN ; i++)
    {
      printf(ch1[i]? "#" : ".");
    }

    printf("\n.         .         .         .         .         .         .         .         .         .         .\n");
    for(int i = 0 ; i < LEN ; i++)
    {
      printf(ch2[i]? "#" : ".");
    }
    printf("\n.         .         .         .         .         .         .         .         .         .         .\n");
  }

  // Pointless return as we never get here, but it keeps the compiler happy.
  return 0;
}

I usually put the command line to build simple apps like this at the top of the source file, as you can see this one is built with

g++ -o dso dso.cpp -lwiringPi

It requires g++ and the wiringPi library to build. They can both be obtained with apt-get on the Raspbian OS.

In case you’re wondering why I take 101 samples instead of 100, it just looks better with the 10 sample grid lines.

As the Pi Operating System supports multi tasking, there’s a possibility that this will be interrupted while sampling the data. This doesn’t seem to be a problem whenever I’ve tried it, but if you use this and occasionally see the chunks of time missing from your traces, that’s probably why. You could run this in high priority to avoid that, but I’ve never found the need to. I am using a Pi version 3 though which has a 4 core CPU so is more able to leave my process alone.

Improvements

The timing is handled by usleep. It seems fine, but doesn’t account for the time taken to actually sample the data and loop the counter etc. I’m sure there are better methods.
The trace is shown as hashes and dots. I find it nice and easy to read like that, but some people would doubtless prefer proper lines. There should be some extended characters to draw these.
Controls of any kind that don’t mean re-compiling the source would definitely be an improvement. As would some kind of timing information. At them moment you just have to know it’s 1uS per character and therefore 10uS per grid line.
Analogue input, and of course display, would be nice too. To do that you’d need to use an analogue capture system of some kind and a graphical interface.
The list goes on, but my primary focus was to get two traces on my screen as quickly and simply as possible.

If ever I do introduce any of these improvements, I’ll add a blog entry about it. Watch this space, but don’t hold your breath.

5 Replies to “Really Simple Raspberry Pi Logic Analyser (Digital Oscilloscope)”

Leave a Reply

Your email address will not be published. Required fields are marked *