16. Interface and application programming¶
This week’s assignment:
group assignment:
compare as many tool options as possible
individual assignment:
write an application that interfaces with an input &/or output device that you made
Group assignment¶
For this week’s group project, we decided to divide up the different tools between the four of us. Once we all individually researched our tools, we shared our research and took notes.
MIT App Inventor (Kai)¶
- Modular
- Scratch but for apps
- You can test your apps on Android devices
Chili Peppr (Kai)¶
Chili Peppr is a “Javascript software workspaces that talk to your hardware”. We plan to use it in conjunction with the GRBL workspace for our gCode.
Processing (Kai)¶
Processing is a visual, user friendly interface tool. Arduino IDE is built on Processing. It works with Java or Python; there are additional adaptations of the architecture linked below.
Different Adaptations of the Program: - Processing Javascript - Processing Python - Processing Android - Processing Pi
- Hit play to run the code, visually similar to serial monitor to python
- Might not have visuals - screen running indicates that program is running
- Define window size (in pixel size) - use variables to make program parametric
Processing Python (Maxine)¶
Processing Python is an interaction of Processing.
Firefly (Maxine)¶
Simulink (Will)¶
Simulink, built around simulation and model based design. It is an evolution and add on of Matlab
- Allows you to analyze and understand complex systems by giving you block based diagrams
- start model simulation by simply pressing the play button
- allows you to simulate and analyze a broad range of signals from digital to analogue to mixed
- allows you to compare the progress of your algorithms to that of your targeted goal
- has additional capabilities for model based design
- you can generate code from a model to prototype and test things in real time
Wiring (Will)¶
-open source programming framework for microcontrollers -used to create all kinds of creative coding, interactive objects, spaces or physical experiences -includes support for many different hardware architectures -used for learning, prototyping, and finished professional work production
The site is well documented with many helpful resources that can be found here
-Wiring builds off of processing which Kai documented above.
Arduino Firmata (Katie)¶
Firmata is an Arduino library that utilizes the Firmata Protocol to software communication.
*These photos were found from this source
Here is some example code listed on the Firmata Arduino page.
This code starts the Firmata library.
begin(); //start the library begin(long); //start the library and override the default baud rate begin(Stream &s); // start the library using a [Stream](http://www.arduino.cc/en/Reference/Stream) other than Serial (eg Serial1 or EthernetClient) printVersion(); //send the protocol version to the host computer blinkVersion(): //blink the protocol version on the build in LED (typically pin 13) printFirmwareVersion(); //send the firmware name and version to the host computer setFirmwareVersion(byte major, byte minor); //set the firmware name and version, using the sketch's filename, minus the '.ino' setFirmwareNameAndVersion(const char *name, byte major, byte minor); //set both the name and version of the firmware
This code sends messages.
sendAnalog(byte pin, int value); //send an analog message sendDigitalPort(byte portNumber, int portData); //send an 8-bit port in a single digital message sendString(const char* string); //send a string to the host computer sendString(byte command, byte bytec, byte *bytev); //send a string to the host computer using a custom command type sendSysex(byte command, byte bytec, byte* bytev); //send a command with an arbitrary array of bytes write(byte c); //write a byte to the Stream
This code receives the messages.
available(); //check to see if there are any incoming messages in the buffer processInput(); //process incoming messages from the buffer, sending the data to any registered callback functions attach(byte command, callbackFunction myFunction); //attach a function to an incoming message type detach(byte command); //detach a function from an incoming message type
This examples is for sending and receiving messages.
#include <Firmata.h> byte analogPin; void analogWriteCallback(byte pin, int value) { pinMode(pin, OUTPUT); analogWrite(pin, value); } void setup() { Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION); Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); Firmata.begin(); } void loop() { while (Firmata.available()) { Firmata.processInput(); } for (analogPin = 0; analogPin < TOTAL_ANALOG_PINS; analogPin++) { Firmata.sendAnalog(analogPin, analogRead(analogPin)); } }
Firmata Protocol¶
The Firmata Protocol is a protocol that aids in software communication with microcontrollers to computers. The Firmata Protocol can be used on any microcontroller and any computer!
Firmata Protocol is “based on the midi message format in that commands bytes are 8 bits and data bytes are 7 bits” (soundanalogous). Ex. “MIDI Channel Pressure (Command: 0xD0) message is 2 bytes long, in Firmata the Command 0xD0 is used to enable reporting for a digital port (collection of 8 pins)” (soundanalogous). “In Firmata, the number of bytes in a message must conform with the corresponding midi message” (soundanalogous).
MIDI Messages Format¶
This link provides a table for MIDI Messages. It is in binary order!
Python / mbed SDK / RPC (Katie)¶
To understand interfacing with Python, I looked at this [tutorial] (https://os.mbed.com/cookbook/Interfacing-with-Python).
The tutorial referenced this developmental kit. It is called the mbed SDK. It is a C/C++ platform, but I read the tutorial for interfacing with Python.
Here are the different platforms that can be used to interface with Python.
Windows:
-
Run Python Windows Binary
-
Run Python Win32 Extensions
-
Run Python Serial Port Extension
Mac:
-
Python already installed
-
Run terminal ( sudo easy_install pyserial)
Linux: - Python is probably already installed
- Terminal (sudo easy_install pyserial)
RPC¶
mbed libraries (this is the company that the tutorial came from) support RPC so you can interface using that. I referred to this tutorialto learn about RPC interfacing.
HTTP¶
This is an HTTP example of Hello World code which references the Python RPC library.
1 2 3 4 5 6 7 8 9 10 11 | python >>> from mbedrpc import * >>> mbed = HTTPRPC("192.168.0.4") >>> x = DigitalOut(mbed,"LED1")#These objects should already exist on mbed >>> z = DigitalOut(mbed,"LED2") >>> ain = AnalogIn(mbed, "LED3") >>> x.write(1) >>> z.write(0.5) >>> ain.read() 0.786757474 >>> |
I decided to focus on RPC with serial.
Serial¶
Here is how to connect to the COM port.
1 2 3 4 5 6 | python >>> import serial >>> serdev = 15 >>> s = serial.Serial(serdev) >>> s.write("hello") >>> s.close( |
This is a Serial example of RPC that receives the commands from the serial port and then pass them.
#include "mbed.h" #include "mbed_rpc.h" /** * This example program has been updated to use the RPC implementation in the new mbed libraries. * This example demonstrates using RPC over serial */ //Use the RPC enabled wrapped class - see RpcClasses.h for more info RpcDigitalOut myled(LED4,"myled"); Serial pc(USBTX, USBRX); int main() { //The mbed RPC classes are now wrapped to create an RPC enabled version - see RpcClasses.h so don't add to base class // receive commands, and send back the responses char buf[256], outbuf[256]; while(1) { pc.gets(buf, 256); //Call the static call method on the RPC class RPC::call(buf, outbuf); pc.printf("%s\n", outbuf); } }
Personal Assignment¶
For the personal assignment, I decided to use Processing to create a display for temperature data from the TMP36 sensor that I used for inputs week.
First, I downloaded the software from the website and began to scroll through the reference material. Note: due to Processing just being an .exe file, it didn’t add itself to my Start menu, so I followed this helpful tutorial to add it to my Start menu for easy access. I also looked at multiple examples in the software to get a better understanding of how Java works, as well as tutorials from others who did projects similar to mine, like this one.
For reference, here is the code I used for my Satshakit with the sensor:
int sensorPin = 0; void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: int reading = analogRead(sensorPin); float voltage = reading * 5.0; voltage /= 1024.0; float tempC = (voltage - 0.5) * 100 ; float tempF = (tempC * 9.0 / 5.0) + 32.0 ; Serial.print(tempF); delay(1000); }
// Example by Tom Igoe import processing.serial.*; Serial myPort; // The serial port void setup() { // List all the available serial ports printArray(Serial.list()); // Open the port you are using at the rate you want: myPort = new Serial(this, "COM9", 9600); } void draw() { while (myPort.available() > 0) { int inByte = myPort.read(); println(inByte); } }
I found the following code to find available serial ports and read them here on the reference pages for the Serial library.
// Example by Tom Igoe import processing.serial.*; Serial myPort; // The serial port void setup() { // List all the available serial ports printArray(Serial.list()); // Open the port you are using at the rate you want: myPort = new Serial(this, Serial.list()[0], 9600); } void draw() { while (myPort.available() > 0) { int inByte = myPort.read(); println(inByte); } }
Using this as a basis, I determined that I would try to use the temperature values sent by my Satshakit to my PC to make a bar increase or decrease in size with temperature change. To do so, I explored the Shape category on the reference page, as well as the Color tutorial. I tried to use a variable (the temp. as read from serial) to directly change a dimesion of the rectangle. When this didn’t work, I tried to use the same variable and the scale tool. However, this too didn’t work, so I decided to make a text-based GUI with the data, which is when I realized that I might have an issue with the data. The temperature displayed fine in the console, but when I opened the GUI, the number displayed was erratic.
My code up to this point (you can see remnants of the shape experiment commented out):
// Example by Tom Igoe import processing.serial.*; Serial myPort; // The serial port PShape square; // The PShape object float temp = 0; void setup() { // List all the available serial ports printArray(Serial.list()); // Open the port you are using at the rate you want: myPort = new Serial(this, "COM9", 9600); size(600, 400); /* square = createShape(RECT, 0, 0, 20, 50); square.setFill(color(255, 0, 0)); square.setStroke(false); // Creating the PShape as a square. The // numeric arguments are similar to rect(). */ } void draw() { while (myPort.available() > 0) { int inByte = myPort.read(); temp = myPort.read(); // println(inByte); } // shape(square, 25, 150); Shape not currently working textSize(32); text("The current temprature is", 10, 30); fill(0, 0, 255); textSize(32); text(temp, 10, 60); fill(0, 0, 255); }
UPDATE (6/1/19): I have successfully created a temperature display.
I noticed a few issues that, with some browsing through the Internet, I was able to resolve.
One of the biggest issues was that I was updating the temperature data from the serial input rapidly, but Processing was not erasing the previous values, meaning that numbers were writing over each other and making a scrambled mess.
I also refined the sizing of the window and added a bar that changes color (slightly) and length depending on the temperature.
My final code is as follows:
// Example by Tom Igoe import processing.serial.*; Serial myPort; // The serial port PShape square; // The PShape object int temp = 0; void setup() { // List all the available serial ports printArray(Serial.list()); // Open the port you are using at the rate you want: myPort = new Serial(this, "COM9", 9600); size(450, 150); } void draw() { while (myPort.available() > 0) { int inByte = myPort.read(); temp = inByte; println(inByte); } background(0,100,25); square = createShape(RECT, 0, 0, temp*5, 50); square.setFill(color(255, 0, 2*temp)); square.setStroke(false); shape(square, 25, 90); textSize(32); text("The current temperature is", 10, 30); fill(0, 0, 255); textSize(32); text(temp+" degrees Fahrenheit", 10, 60); fill(0, 0, 255); delay(5); }
You can see the resulting program in the video above. Note that the TMP36 sensor’s readings are not very accurate (I am working in a room temperature environment, ~70 degrees Fahrenheit). However, the changing temperature is accurate because I put my finger on and off the sensor to demonstrate the changing data feed. According to this forum thread, the analog sensor is subject to variable reference voltage, while a digital sensor, such as the BMP280 Temperature, Humidity, and Pressure sensor I am hoping to use for my final project, is more reliable and accurate.