So here is the source code to read the sensor connected according to the description in the previous blog post. Now, this sample is just developed without considerations for footprint, power consumption etc which is so important when developing an embedded application in any language (but Java should obviously be the the choice).
First the IMlet, nothing really strange here at all
package tmp36rpi;
import javax.microedition.midlet.*;
/**
* @author atael
*/
public class IMlet extends MIDlet {
private MCP3008Checker mcp3008Checker;
private static final String name = "MCP3008";
public void startApp() {
System.out.println("***************************************");
System.out.println("* MCP3008/TMP36 Thermometer Sample *");
System.out.println("***************************************");
mcp3008Checker = new MCP3008Checker(name);
if (mcp3008Checker.start() ) {
System.out.println("MCP3008Checker start is OK.");
} else {
System.out.println("MCP3008Checker start has failed.");
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
if (mcp3008Checker != null) {
mcp3008Checker.stop();
}
}
}
Then my helper class, MCP3008Checker, which extends TimerTask and I have hard coded that it should execute every 5000ms. When it kicks in it will get the temperature from the TMP36 class (see below): /*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tmp36rpi;
import java.util.Timer;
import java.util.TimerTask;
/**
*
* @author atael
*/
public class MCP3008Checker extends TimerTask {
private Timer timer;
private static int INTERVAL_MS = 5000;
private int temperature;
private String name;
MCP3008Checker( String name){
this.name = name;
}
public boolean start () {
boolean isStarted = false;
System.out.println ("Trying...");
if (TMP36.connect()) {
timer = new Timer();
timer.schedule(this, 0, INTERVAL_MS);
temperature = TMP36.getTemperature();
isStarted = true;
}
return isStarted;
}
public void run() {
int newTemperature = TMP36.getTemperature();
if (newTemperature != temperature) {
temperature = newTemperature;
}
System.out.println("Temp in Andys office: " + temperature );
}
public void stop () {
if (timer != null) {
timer.cancel ();
}
TMP36.disconnect();
}
}
The TMP36 class is the part of the code that "talks" to the MCP3008. This is the hard part according to me becuase I am pretty junior on how to read hardware documentation and understanding bits and bytes. But I'll learn as I go (with great help from other colleagues):
package tmp36rpi;
import com.oracle.deviceaccess.Peripheral;
import com.oracle.deviceaccess.PeripheralConfigInvalidException;
import com.oracle.deviceaccess.PeripheralExistsException;
import com.oracle.deviceaccess.PeripheralManager;
import com.oracle.deviceaccess.PeripheralNotAvailableException;
import com.oracle.deviceaccess.PeripheralNotFoundException;
import com.oracle.deviceaccess.PeripheralTypeNotSupportedException;
import com.oracle.deviceaccess.gpio.GPIOPin;
import com.oracle.deviceaccess.spibus.SPIDevice;
import com.oracle.deviceaccess.spibus.SPIDeviceConfig;
import java.io.IOException;
/**
*
* @author atael
*/
public class TMP36 {
private static SPIDevice mcp3008 = null;
private static GPIOPin cs = null;
private static final int spiBusNumber = 0; // number of the bus the slave device is connected to
private static final int spiAddress = 1; // Chip Select address of the slave device on the bus
private static final int spiClockFrequency = 7500; // clock frequency of the slave device in Hz
private static final int spiClockMode = 2;
private static final int spiWordLength = 8;
private static final int spiBitOrdering = Peripheral.BIG_ENDIAN;
public static boolean connect() {
boolean isConnected = false;
try {
cs = (GPIOPin) PeripheralManager.open(18);
SPIDeviceConfig spiCfg = new SPIDeviceConfig(
spiBusNumber,
spiAddress,
spiClockFrequency,
spiClockMode,
spiWordLength,
spiBitOrdering);
cs.setValue(true);
mcp3008 = (SPIDevice) PeripheralManager.open(SPIDevice.class, spiCfg);
isConnected = true;
} catch (PeripheralNotAvailableException ex) {
ex.printStackTrace();
} catch (PeripheralNotFoundException ex) {
ex.printStackTrace();
} catch (PeripheralTypeNotSupportedException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (PeripheralConfigInvalidException ex) {
ex.printStackTrace();
} catch (PeripheralExistsException ex) {
ex.printStackTrace();
}
return isConnected;
}
public static void disconnect() {
if (mcp3008 != null) {
try {
if (cs.isOpen()) {
cs.close();
}
if (mcp3008.isOpen()) {
mcp3008.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static int getTemperature() {
int readAdc = 0;
float milliVolts = 0;
float tempCelsius = 0;
try {
cs.setValue(false);
byte[] rxBuf = new byte[3];
byte[] txBuf = new byte[3];
txBuf[0] = (byte) 1;
txBuf[1] = (byte) ((8 + 0) << 4);
txBuf[2] = (byte) 0;
mcp3008.begin();
mcp3008.writeAndRead(txBuf, 0, txBuf.length, rxBuf, 0, rxBuf.length);
mcp3008.end();
cs.setValue(true);
readAdc = convUnsignedByte(rxBuf[2]);
readAdc += ((rxBuf[1] & 3) << 8);
/* TMP36 Formula: Temp °C = 100*(reading in V) - 50
*
* The MCP3008 is a 10-bit ADC. That means it will read a value
* from 0 to 1023 (2^^10 = 1024 values) where 0 is the same as
* 'ground' and '1023' is the same as '3.3 volts'.
*/
// Convert analog reading to millivolts
milliVolts = readAdc * (3300 / 1023);
// 10 mv per degree
tempCelsius = ((milliVolts - 100) / 10) - 40;
return (int)tempCelsius;
} catch (PeripheralNotAvailableException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return 0;
}
public static int convUnsignedByte (byte value) {
int returnValue = value;
if (value < 0) {
returnValue = 0xFF + value + 1;
}
return returnValue;
}
}
And when I execute this I can see the following in my console. It is a lot of information that gets written but I do have a temperature of 18 degress celsius and if I put my finger on my sensor I can see the temperature go up. So it seems that it works!
***************************************
* MCP3008/TMP36 Thermometer Sample *
***************************************
Trying...
[INFO] [UNKNOWN] gpio.c line 636: Try to open pin 18 on port 0 with direction 1
[INFO] [UNKNOWN] gpio.c line 727: GPIO pin 18 open successfully done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 0
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
MCP3008Checker start is OK.
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 0
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[AMS-TRACE] MIDlet:TMP36rpi status=1
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
Temp in Andys office: 18
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 0
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
Temp in Andys office: 18
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 0
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
Temp in Andys office: 18
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 0
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
Temp in Andys office: 19
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 0
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
Temp in Andys office: 19
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 0
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
[INFO] [UNKNOWN] gpio.c line 551: Pin 18 direction: 1
[INFO] [UNKNOWN] gpio.c line 305: Pin 18 write value 1
[INFO] [UNKNOWN] gpio.c line 312: Pin 18 write value done
Temp in Andys office: 20
That's all for now folks. Now I am going to figure out how to make this application to auto start and how to make this very important information available to a end-user application such a servlet, JavaFX application or something like that. That means lot's of reading and I will blog about the findings. I will also connect other types of sensors, just because I think it is fun to build embedded applications with Java (and I need to impress my dog as he is the only one in my family that thinks this is cool).
<<Andy>>