WEEK 11: _ write an application that interfaces with an input/output device you made.


Interface and Application Programming


At first I was confused about how this week differed from the embedded programming week. Then, while programming my microcontroller to convert thermistor readings to temperatures via the Steinhart + Hart equation, I got this error message, and it all made sense:

Specifically, an interface or application program is very useful when the data processing you are attempting excedes the computing power of your ATTiny! (Of course there are many good reasons to have application programming, but this is good justification for me). Thus, my temp conversion function, which requires manu=ipulating many 'doubles' with math functions like log(), can be done on my computer since the microcontroller is already hard at work being a serial bus master.


One more new program: Processing feels much like the arduino language and has a huge library of example code to learn and scavenge from - and it''s FREEE!


In order to communicate from board to computer you must define a device interface. I chose serial from the USB port running to my FTDI cable on the cow networking board (see Week12). I initiate this in processing with the code:
String portName = Serial.list()[0]; myPort = new Serial(this, portName, 9600);.


Other things to set up include your application window size, size(640,480); and any libraries that you want for visual effects, as in a font for writing in the screen, e.g. font = createFont("Arial",32);. The rest gets drawn and redrawn continuously in the main loop.


Here's my first shot at output code for data coming from the thermistors, and video of the result:

import processing.serial.*;

Serial myPort;
PFont font;
String readval1 = "1";
String readval2 = "2";
String readval3 = "3";
String readval4 = "4";
float temp1 = 0.0;

void setup() {
font = createFont("Arial",32);
size(640,480);
String portName = Serial.list()[0];

myPort = new Serial(this, portName, 9600);

}

double Thermistor(int RawADC) {
double Temp;
Temp = (20.0*RawADC);
Temp = log(10000.0*((1024.0/RawADC-1)));
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp
);
Temp = Temp - 273.15;
//Temp = (Temp * 9.0)/ 5.0 + 32.0; //for farenhiet
return Temp;
}

float Thermistor2(int v) {
float out=0.0;
out = (float) v;
out = v*5.1;
out = 2.5 - out * 5.0/(20.0*512.0);
out = 10000.0/(5.0/out-1.0);
out = 1.0/(log(out/10000.0)/3750.0+(1/(25.0+273.15))) - 273.15;
return out;
}

void draw() {
background(120);

if( myPort.available() > 0 ) {
String sread1 = " ";
String sread2 = " ";
sread1 = myPort.readStringUntil('\n');
sread2 = myPort.readStringUntil('\n');
if( sread1 != null ) {
readval1 = sread1;
}
if( sread2 != null ) {
readval2 = sread2;
}
}
if( readval1 != null ) {
textFont(font);
text(readval1,100,100);
println(readval1);
}
if( readval2 != null ) {
int raw = int(readval2.trim());
temp1 = (float)Thermistor2(raw);
text(str(temp1),200,100);

}
delay(200);
}


In case it's hard to tell, that's me 'breathing' on the thermister. It reads an increase from '10' to '28' - good, but there is something wrong with the conversion from resistance to an actual celcius reading. Also, when the second cow node is added, it is printing blank spaces from the serial.... I'll have to revise this in the next version of code.



After edditing, here is the final code. It is looking much better visually, reading temperature accuartely, and believe it or not both cows are within +/-0.2 deg of eachother!

import processing.serial.*;
Serial cowPort;
Serial heatPort;
PFont font;
String readvalM1 = "1";
String readvalM2 = "2";
String readvalT1 = "1";
String readvalT2 = "2";
float temp1 = 0.0;
float temp2 = 0.0;
float[] graph1;
float[] graph2;
void setup() {
font = createFont("Arial",22);
size(800,480);
String portName = Serial.list()[0];
// String portName2 = Serial.list()[1];
graph1 = new float[200];
for(int i = 0; i < graph1.length; i++) {
graph1[i] = 100.0;
}
graph2 = new float[200];
for(int i = 0; i < graph2.length; i++) {
graph2[i] = 25.0;
}
cowPort = new Serial(this, portName, 9600);

}

double Thermistor(int RawADC) {
double Temp;
Temp = (20.0*RawADC);
Temp = log(10000.0*((1024.0/RawADC-1)));
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp = Temp - 273.15;
//Temp = (Temp * 9.0)/ 5.0 + 32.0;
return Temp;
}

float Thermistor2(int v) {
float out=0.0;
out = (float) v;
out = v*5.1;
out = 2.5 - out * 5.0/(20.0*512.0);
out = 10000.0/(5.0/out-1.0);
out = 1.0/(log(out/10000.0)/3750.0+(1/(25.0+273.15))) - 273.15;
return out;
}

void draw() {
background(255);

if( cowPort.available() > 0 ) {
String sread1 = " ";
String sread2 = " ";
sread1 = cowPort.readStringUntil('\n');
if( sread1 != null) {

if( sread1.trim().equals("M001")) {
readvalM1 = sread1;
sread2 = cowPort.readStringUntil('\n');
if( sread2 != null) {
readvalT1 = sread2;
print("Master: ");
println(readvalT1);
}
}
if( sread1.trim().equals("M002")) {
readvalM2 = sread1;
sread2 = cowPort.readStringUntil('\n');
if( sread2 != null) {
print("Slave: ");
readvalT2 = sread2;
println(readvalT2);
}
}
}
}
fill(102);
if( readvalM1 != null ) {
textFont(font);
text(readvalM1.trim(),100,100);
}
if( readvalT1 != null ) {
int raw = int(readvalT1.trim());
temp1 = (float)Thermistor2(raw);
text(str(temp1),200,100);
graph1[0] = (map(temp1,20,40,0,240));
}

if( readvalM2 != null ) {
textFont(font);
text(readvalM2.trim(),100,150);
}
if( readvalT2 != null ) {
int raw = int(readvalT2.trim());
temp2 = (float)Thermistor2(raw);
text(str(temp2),200,150);
graph2[0] = (map(temp2,20,40,0,240));
}
delay(100);

for(int i = 0; i < graph1.length-1; i++) {
stroke(200,30,10,map(i,0,graph1.length-1,255,10));
line( (i+1)*(width/graph1.length), height, (i+1)*(width/graph1.length) , height-graph1[i+1] );
}

for(int i = graph1.length-1; i > 0 ; i--) {
graph1[i] = graph1[i-1];
}

for(int i = 0; i < graph2.length-1; i++) {
stroke(59,200,10,map(i,0,graph2.length-1,255,10));
line( (i+1)*(width/graph2.length)+2, height, (i+1)*(width/graph2.length)+2 , height-graph2[i+1] );
}

for(int i = graph2.length-1; i > 0 ; i--) {
graph2[i] = graph2[i-1];

}
}


So coool! My next step will be to add output logic to this input interface. When it reads in below a user-specified temperature on either cow, it will send a signal via serial to another board. That board will be told to turn HIGH the pins to the nichrome wire.

Tools used this week: Processing, Arduino, USBtiny Programmer