Blog moved to http://www.andrevdm.com/

Showing posts with label electronics. Show all posts
Showing posts with label electronics. Show all posts

Monday, 12 January 2015

Capturing multiple channels of digital data on a two channel digital oscilloscope

In my last post I showed how I parsed the CSV data to do some basic logic analysis. The problem is that I have a two channel scope and need to capture three channels for SPI (i.e. clock + MOSI + MISO).

As it turns out this can be done without too much fuss by using a digital to analogue (DAC) "resistor ladder". The two options I looked at were the R-2R ladder and the simpler binary weighted ladder. For two levels the binary weighted DAC is the simplest, it just needs two resistors (one double the other one's resistance).

Here is the circuit diagram

So one input goes through the 1k resistor and the other through a 2k resistor and you measure the output. With an DAC with only two levels there is tolerance for some noise on the digital lines.

I'm working at ~3 volts, so the levels I'm going to see are
Voltage D0 D1
0v 0 0
1V 0 1
2V 1 0
3V 1 1


You can clearly see the three levels on the scope when measuring Vout



I kept the clock separate on channel 2 so that I could trigger on it. Here is the clock + data



With only two channels going through the DAC you could reconstruct the two digital data channels by eye. That is not much fun though. So I modified my F# script from the previous post to split the data into two values and then do the logical analysis and print out two channels of data. This proved very useful when using a SPI device that returns data (e.g. SD card). Here is the full F# script also available as a gist.

Logic level parsing Rigol oscilloscope CSV data with F#

I was recently debugging a SPI communication but had no logic analyser. Fortunately my oscilloscope (rigol DS1052e) can export a capture as CSV (I assume that most digital oscilloscopes can export to CSV too).
Parsing the CSV is trivial, getting a logic level from it is also fairly easy. I realise that this is terribly quick & dirty but it worked 100% for what I needed. Here is the high level process
  1. Ignore timings - SPI is clocked so actual timing is irrelevant for this analysis
  2. Parse X and Y channels
  3. Convert clock channel voltage into logic level 1 or 0
  4. Discard all rows apart from rows where the clock goes high
  5. Convert data channel to logic level
  6. Group into bytes
  7. Display hex value

As I said, very simple but it worked well and I was able to see exactly what was going on. Obviously this only works for synchronous (clocked) protocols like SPI/I2C but that is all I needed.

Here is the full F# script (also see the gist)

Friday, 25 July 2014

Unit testing embedded C projects with seatest

I recently wrote my first embedded C project and was quite surprised to find that unit tests were not as widely used as I would have expected. There seems to be a general opinion that unit tests are less useful for embedded development that for application development. I find this very strange because debugging embedded systems is hard compared to application development.

Fortunately not everyone agrees with this sentiment and in the end it was relatively easy to get unit tests working thanks to SeaTest (https://code.google.com/p/seatest/). SeaTest is simple and specifically designed for embedded-c projects.

To get it working for a Microchip MPLabX project I did this
  1. Created a _test directory in my main projects directory
  2. Created my unit tests in this directory in test.c
  3. In this directory created a bash script named "test"
  4. Copied seatest.c and seatest.h into the directory
  5. Created dummy PIC include files in this directory
    1. xc.h
    2. xc.c
    3. pic18f4550.h
  6. Created a plib directory under _test containing
    1. timers.h
The idea being that the my test directory (_test) contained files for mocking the Microchip libraries to make testing possible. This turned out to be much simpler than I had feared.


Test runner bash script

#/bin/sh
gcc -std=c99 -o test.o -D TESTING -I . -I .. xc.c test.c ../buttons.c ../lcd.c ../dateTime.c ../timerUi.c ../timer.c seatest.c && ./test.o

Nothing fancy... It does this
  • Defines a TESTING constant
  • Includes the local directory for the "mock" libraries
  • Includes the parent directory for my actual code
  • Runs ./test.o if the compile succeeds

Mock/Stub files

Most of the stub files (timers.h etc) are empty files just to keep the compiler happy. I then just copied whatever definitions I needed from MPLabX's libraries to get the rest working.


Tests

Tests are then simply a matter of calling a function and using the seatest assert functions.

There definitely are things that are hard to test e.g. interrupt routines but as long as your code is modular you should usually be able to test the methods that e.g. the interrupt routine calls.

Overall I found this to be a very simple approach and it certainly helped me get my project up and running a lot faster with a lot more confidence