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. 

1 comment: