Tuesday, December 22, 2015

Arduino Emulator, part 2

In my last post I introduced the Arduino emulator that I wrote for CS-11M. The source code is here:

https://github.com/mike-matera/ArduinoGrader

The emulator was designed for grading and has limitations. The emulator code and the sketch run in one thread so if the sketch goes into an infinite loop the emulator hangs (unless the loop calls into Arduino code which calls the emulator). Sketches often use static initialization (see the Servo library examples) which makes emulator initialization fragile. Most of all it's tedious writing test code in C++.

Before next year I want to rewrite the emulator to make it more flexible and complete. Here are my goals for the next implementation:

  1. Write tests in Python. 
  2. Serial port interaction using Pexpect.
  3. Loadable sketches. Sketches should be loadable at run-time, rather than linked in. Loading a sketch with dlopen() let's me ensure the emulator is initialized before static initialization in the sketch. 
  4. Threading support. It will be necessary for attachInterrupt().
  5. Arduino IDE integration. It would be ideal to have the IDE compile the sketch for the emulator. That way I can integrate the emulator back-end in the same way that different chips and architectures are integrated. 
There's a significant leap in complexity. The emulator will be two processes, the C++ sketch and the Python script, communicating via a socket (and Google's protocol buffers). The emulator state that's now embodied in the Emulator class should be Python side and socket calls from the sketch should be synchronous so test code can be as precise as possible. 

But when will I have the time to build it? 

Monday, December 21, 2015

The Arduino Emulator

I needed a way to grade assignments in CS-11M, which is taught on Arduino. Downloading student's designs would have been extremely tedious. I would have had to have been strict about the circuit (exact pins, wiring, values, etc.) which I thought would have negative consequences. So I decided to build myself a simple emulator. You can see the work here:

https://github.com/mike-matera/ArduinoGrader

The emulator works at the Arduino API level. I added to it as needed to make it functional enough for the assignments I gave. Here's the anatomy of the emulator:

  emulator/


Emulator code is here. The Emulator object mediates communication between the sketches and the test code. The implementation of Arduino functions in the main namespace is in emulator.cpp. Defined:

  • micros() and millis()
  • delay() and delayMicroseconds()
  • digitalRead(), digitalWrite() and pinMode()
  • analogRead(), analogWrite() and analogReference()
  • tone() and noTone()
  • random() and randomSeed()
  • map(), etc.
These core functions internally operate on the Emulator object rather than pins or a processor-centric emulator.

  arduino/


The arduino directory contains Arduino code that was ported to the emulator. Porting proved to be easy. The serial port is emulated using stdio which handless TTYs and pipes properly. There's also a hack that lets test code create input. But it's threaded code that's not synchronized it's bound to fail in a complicated test. The arduino directory contains emulation of
  • HardwareSerial (as Serial) including Serial, Stream, Print and WString
  • Servo 
Additional libraries will have to be ported if they're used. 

  tests/ 


The tests directory contains tests for class projects. Each <sketch-name>_test.cpp is meant to test an assignment given in class where the student was asked to turn in <sketch-name>.ino. The main directory has shell scripts that glue everything together. 

Building the Emulator


Three parts are built together:
  1. Base emulator code. 
  2. <sketch-name>.ino
  3. The <sketch-name>_test.cpp 
The resulting executable runs the sketch and the test together. The build procedure is: 
  1. Gather <sketch-name>.ino and related sources. 
  2. Use the Arduino command line interface to build the sketch and leave intermediate files. This creates the <sketch-name>.cpp file.  
  3. Compile the <sketch-name>.cpp file and related source with the test code and emulator
Step 2 is important. Arduino creates function declarations that make otherwise illegal C++ legal. Further, a fail at this step tells me that the original sketch didn't compile (i.e. it's the student's fault) most compile failures in step three are my fault. 

The emulator was an indispensable but it really needs improvement. In my next post I'll discuss what I would like to do with it.