airsenseur: airquality monitoring open framework technical presentation

154
AirSenSeur AirSenSeur Air Air quality quality monitoring open framework monitoring open framework Technical presentation Technical presentation Marco Signorini – Liberaintentio S.r.l.

Upload: marco-signorini

Post on 21-Apr-2017

624 views

Category:

Environment


7 download

TRANSCRIPT

Page 1: AirSensEUR: AirQuality monitoring open framework technical presentation

AirSenSeurAirSenSeurAir Air qualityquality monitoring open framework monitoring open framework

Technical presentationTechnical presentationMarco Signorini – Liberaintentio S.r.l.

Page 2: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 2

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 3: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 3

AirSensEUR System OverviewAirSensEUR System Overview

Composed by two different actors: “Shield” and “Host”

The Shield is targeted to interface to physical sensors The Host is in charge of retrieve data from the shield, aggregate

with time and positioning information, store locally and periodically push the overall samples to an external server

Shield and Host are linked together by a serial line Hardware references and software sources released under

public licences (www.airsenseur.org)

Page 4: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 4

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 5: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 5

Shield HardwareShield Hardware

ATMega328 with optiboot installed (Arduino UNO compatible) Four independent Programmable Analog Front Ends (AFE) for

two and three leads chemical sensors Four 16bits high precision Analog to Digital converters Four indepentent 4 channels 12bits high precision Digital to

Analog converters for onboard reference signals synthesis I2C digital temperature, pressure and humidity sensors Opto-coupled USB interface for optional PC connection Low noise linear power supply regulators onboard

Page 6: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 6

Shield HardwareShield Hardware

AFE

A/D

D/As

AFE

A/D

D/As

AFE

A/D

D/As

AFE

A/D

D/As

Chemical sensors analog front end

and data acquisition blocks

ATMega328uController

T and %RH

Pressure

I2C sensorboard

Local Power Supply and level shifters

Chemical Sensors

Power Supply

+6V DC

TTL serialTo host

Arduino USB2Serialadapter connector

Vin-Vad

Vafe

Vout

Page 7: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 7

Shield Hardware (single channel)Shield Hardware (single channel)I2C Programmable AFE

(current to voltage conversion)

Analog to Digital conversionthrough SPI

I2C Digital to AnalogGenerates voltage

references

Compatibility withmultiple sensor brands

Page 8: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 8

Shield Hardware (AFE)Shield Hardware (AFE)

Texas Instruments LMP91000 Configurable Potentiostat Connected via I2C Generates a voltage proportional to the chemical sensor cell

current Fully programmable (bias, internal zero reference, load, gain) Supports internal or external voltage references (Vafe)

Page 9: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 9

Shield Hardware (ADC)Shield Hardware (ADC)

Texas Instruments ADC161S626 16bit, 50 to 250kSPS Connected via SPI External voltage reference (Vad) range of +0.5V to 5V True differential input: allows to inject external zero reference

(Vn-)

Page 10: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 10

Shield Hardware (DAC)Shield Hardware (DAC)

Analog Devices AD5694R quad channels 12bit DAC Connected via I2C Very low drift (2ppm/C) internal voltage reference Selectable gain for 0 to 2.5V or 0 to 5V full scale output Used to generate references for

Analog Front End (Vafe) Analog to Digital negative reference (Vn-) Analog to Digital full scale reference (Va)

Page 11: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 11

Shield Hardware (THP and supply)Shield Hardware (THP and supply)

Factory calibratedI2C Humidity and

Temperature sensor

Factory calibratedI2C Pressure sensor

Linear 5V regulator

Page 12: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 12

Shield Hardware (THP and supply)Shield Hardware (THP and supply)

TecnoSens UR100CD Temperature and Humidity sensor Calibration factory parameters stored into embedded EEPROM Connected via I2C

Bosh BMP180 Pressure sensor Fully calibrated MEMS sensor Connected via I2C

Linear Voltage regulator Provides 5V from 6-10V external power supply

Page 13: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 13

Shield Hardware (ATMega328)Shield Hardware (ATMega328)

ATMega 328Running at 16MHz

Arduino(tm) USB2Serialconnector onboard

Programmable LEDonboard

Page 14: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 14

Shield Hardware (ATMega328)Shield Hardware (ATMega328)

Connected to ADC via SPI and four dedicated chip select lines Connected to AFE via I2C Connected to DAC via I2C and four dedicated gain selection

lines Connected to THP sensors via I2C Serial line shared with external programmer and host Programmable LED on digital line (shared) Optional external serial RAM via SPI and shared chip select line

Page 15: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 15

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 16: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 16

Shield FirmwareShield Firmware

Arduino IDE 1.6.5 compatible Implemented mainly in C++ .INO file wrapper for C++ root object instance

Initializes peripherals and sensors Handles serial communication protocol Samples sensors Performs filtering and average calculations Generates timestamps for outgoing samples

Page 17: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 17

Shield Firmware (Data Flow)Shield Firmware (Data Flow)

IIR IIR DecimationFilter Averager

Sampler

Period(Fs)

Coefficient

CoefficientRatio Length

BufferTimer

Timestamp Last

Sam

ple

Sen

sor

Fs

Fs Fs

Fs/R

atio

Fs/(R

atio

*Len

gth)

Page 18: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 18

Shield Firmware (.INO wrapper)Shield Firmware (.INO wrapper)

Is the main entry point for the Arduino framework Two functions: init and loop References two external C functions where all the magic is

performed by C++ code. “_impl” functions are implemented in ChemSensorBoardImpl.cpp

extern void setup_impl();extern void loop_impl();void setup() { setup_impl();}void loop() { loop_impl();}

Page 19: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 19

Shield Firmware (setup_impl)Shield Firmware (setup_impl)

Initializes the hardware and the software data structures Initializes the timer and registers a callback

void setup_impl() { // Initialize the heartbeat pin pinMode(HBLEDPIN, OUTPUT); digitalWrite(HBLEDPIN, LOW); hbTimer = 0; // Initialize the serial line Serial.begin(9600); // Instantiate the main objects sensorBoard = new SensorsArray(); commProtocol = new CommProtocol(sensorBoard); // Initialize the timer at 10ms Timer1.initialize(10000); Timer1.attachInterrupt(timerInterrupt);}

Page 20: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 20

Shield Firmware (loop_impl)Shield Firmware (loop_impl)

Calls the main sensorBoard loop, handles heartbeat and the serial line

void loop_impl() { // Propagate to the sensor array bool newSample = sensorBoard->loop(); // Heartbeat led if (newSample && (hbTimer == 0)) { hbTimer = HBLED_NEWSAMPLE_TMR; } // Handle the serial line if (Serial.available()) { unsigned char val = Serial.read(); commProtocol->onDataReceived(val); }}

Page 21: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 21

Shield Firmware (timer callback)Shield Firmware (timer callback)

Propagate timing callback to the main objects, handles the heartbeat LED

void timerInterrupt() { if (sensorBoard) { sensorBoard->timerTick(); } if (commProtocol) { commProtocol->timerTick(); } // Heartbeat led if (hbTimer != 0) { hbTimer--; digitalWrite(HBLEDPIN, HIGH); } else { digitalWrite(HBLEDPIN, LOW); }}

Page 22: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 22

Shield Firmware (global objects)Shield Firmware (global objects)

Two global objects are instantiated in the setup_impl function:

SensorsArray* sensorBoard;CommProtocol* commProtocol;

SensorsArray is the main entry point for all sensors management and samples retrieval. It's implemented in SensorsArray.cpp file

CommProtocol is responsible for handling serial data communications with the host. It's implemented in CommProtocol.cpp file. It receives a SensorArray reference so it's able to interact with it.

Page 23: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 23

Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)

OnDataReceived handles the communications with the Host timerTick should be called periodically to properly handle

protocol timeouts Valid commands are wrapped by a specific private callback

class CommProtocol {public: CommProtocol(SensorsArray *sensors); void timerTick(); void onDataReceived(unsigned char pivotChar);private: void reset(); void processBuffer(); static bool sampleEnable(...); static bool sampleDisable(...);

Page 24: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 24

Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)

typedef struct _commandinfo { unsigned char commandID; unsigned char parNum; bool (*handler)(CommProtocol* context, unsigned char cmdOffset);} commandinfo; private: static const commandinfo validCommands[];

Each valid command is associated to a callback function and the number of expected parameters

A list of valid commands is statically defined and stored in the FLASH memory

Page 25: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 25

Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)

typedef enum _rxstatus {RX_IDLE,RX_HEADER_FOUND

} rxstatus;private:

unsigned char buffer[COMMPROTOCOL_BUFFER_LENGTH]; unsigned char offset; rxstatus rxStatus;

The internal state machine is based on two possible statues: “waiting for a valid header” and “header found” (i.e. Idle or running)

Incoming data are stored on a RAM buffer at the “offset” position. Offset is changed on each incoming data

Page 26: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 26

Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)

void CommProtocol::onDataReceived(unsigned char pivotChar) {

switch (rxStatus) {case RX_IDLE: {

// Searching for an header...

}break;case RX_HEADER_FOUND: {

// Searching for a trailerif(pivotChar == COMMPROTOCOL_TRAILER) {ProcessBuffer();...

}break;

}}

onDataReceived is responsible for data framing and processing

Page 27: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 27

Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)

void CommProtocol::processBuffer() {

// .. we expect the command ID, validate it...

// Execute the actiontypedef bool (*fpointer)(CommProtocol* context, unsigned

char cmdOffset);fpointer handler = &(validCommands[offsetId].handler);if (valid && handler != 0) {

valid = (*handler)(this, offsetId);}// Signal an invalid/fault conditionif (!valid) {

strcpy_P((char*)buffer, commProtocolErrorString);}

// Send back the resultSerial.print((char*)buffer);

ProcessBuffer calls the proper callback and send back results

Page 28: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 28

Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)

bool CommProtocol::setSampleDecimation(CommProtocol* context, unsigned char cmdOffset) { unsigned char channel = context->getParameter(0); unsigned char decimation = context->getParameter(1); if (context->sensorsArray->setSampleDecimation(channel, decimation)) { return context->renderOKAnswer(cmdOffset, channel); } return false;}

Command handler example: no dynamic answer to the host

Page 29: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 29

Shield Firmware (CommProtocol)Shield Firmware (CommProtocol)

bool CommProtocol::getSampleDecimation(CommProtocol* context, unsigned char cmdOffset) { unsigned char channel = context->getParameter(0); unsigned char decimation; if (!context->sensorsArray->getSampleDecimation(channel, &decimation)) { return false; } context->buffer[0] = COMMPROTOCOL_HEADER; context->buffer[1] = validCommands[cmdOffset].commandID; context->buffer[2] = 0; context->writeValue(channel, false); context->writeValue(decimation, true);

return true;}

Command handler example: dynamic result sent to the host

Page 30: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 30

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

Is the “container” of all sensor implementation objects and related data averagers and FIRs

Provides a type-unaware interface for all sensor channels Orchestrates the sampling process for all sensors through a pair

of functions: loop and timerTick.

Page 31: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 31

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

class SensorsArray {...

private:static const LMP91000 AFEList[NUM_OF_CHEM_SENSORS];static const ADC16S626 ADCList[NUM_OF_CHEM_SENSORS];

static const AD5694R DACList[NUM_OF_CHEM_SENSORS]; static UR100CD ur100cd;static SFE_BMP180 bmp180;static DitherTool ditherTool; Sampler* samplers[NUM_OF_TOTAL_SENSORS];SamplesAverager* averagers[NUM_OF_TOTAL_SENSORS]; ...

};

Sensors implementations are statically defined and allocated in FLASH area, when possible

Page 32: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 32

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

class SensorsArray {...

public: unsigned char setSamplePrescaler(...); bool getSamplePrescaler(...); unsigned char setSamplePostscaler(...); bool getSamplePostscaler(...); bool getLastSample(...); bool writeDACRegisters(...); bool readDACRegisters(...);

...};

Provides type-unaware interface for all sensor channels

Page 33: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 33

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

class SensorsArray {public: SensorsArray(); virtual ~SensorsArray();

Public:

bool timerTick(); bool loop();

...};

Implements the entry point functions to be called periodically by the main loop and timer

Page 34: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 34

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

The constructor is responsible for: Initialize the internal coefficients for the pressure sensor Initialize the samplers and averagers arrays Allocate and initialize the sampler units Allocate the data averagers Link averagers with the dithering tool Initialize DACs Load preset stored on the EEPROM

Page 35: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 35

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

The timerTick function propagates the event to all samplers Samplers with unread samples shall return true; false otherwise

bool SensorsArray::timerTick() { bool result = false; // Loop on each sensor samplers for (unsigned char n = 0; n < NUM_OF_TOTAL_SENSORS; n++) { if (samplers[n] != 0) { result |= samplers[n]->sampleTick(); } } // Increase the internal timestamp timestamp++; return result;}

Page 36: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 36

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

The timerTick function propagates the event to all samplers Samplers with unread samples shall return true; false otherwise

bool SensorsArray::loop() {...

bool result = false; for (unsigned char n = 0; n < NUM_OF_TOTAL_SENSORS; n++) { if (samplers[n] != 0) { if (samplers[n]->sampleLoop()) { // A new sample is ready to be averaged result |= averagers[n]->collectSample(samplers[n]->getLastSample(), timestamp); }; } } return result;}

Page 37: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 37

Shield Firmware (SensorsArray)Shield Firmware (SensorsArray)

The loop function propagates the event to all samplers. When a new sample is available, it propagates to the proper averager.

bool SensorsArray::loop() { // If sampling is disabled, skip this function if (!samplingEnabled) return false; // Otherwise loop on each sensor sampler and averager bool result = false; for (unsigned char n = 0; n < NUM_OF_TOTAL_SENSORS; n++) { if (samplers[n] != 0) { if (samplers[n]->sampleLoop()) { // A new sample is ready to be averaged result|=averagers[n]->collectSample(samplers[n]->get LastSample(), timestamp); }; } } return result;}

Page 38: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 38

Shield Firmware (Sampler)Shield Firmware (Sampler)

Sampler is an abstract class and is the base class for other specialized sampler units

Implements common sampler funcionalities: prescaler, IIR and decimation filter.

It contains a reference to a singleton DitherTool used by IIR to reduce the data DC offset introduced by rouding math

Two functions needs to be implemented by specialized classes:

sampleTick() sampleLoop()

Page 39: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 39

Shield Firmware (Samplers hierarchy)Shield Firmware (Samplers hierarchy)

Sampler

ChemSensorSampler

HumSensorSampler

PressSensorSampler

TempSensorSampler

Page 40: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 40

Shield Firmware (Sampler Subclasses)Shield Firmware (Sampler Subclasses)

Two functions needs to be implemented by specialized classes:

sampleTick() SampleLoop()

Specialized classes dialogate with the hardware through a set of objects providing low level hardware abstraction. Those objects are allocated by the SensorsArray constructor and linked to the specialized object at construction time.

Page 41: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 41

Shield Firmware (Sampler Subclasses)Shield Firmware (Sampler Subclasses)

The sampleTick function defines the sampling time by comparing an internal counter to a prescaler value.

Time for sampling is signalled by setting the “go” variable to true

bool ChemSensorSampler::sampleTick() { if (timer == prescaler) { // It's time for a new sample timer = 0; go = true; return true; } timer++; return false;}

Page 42: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 42

Shield Firmware (Sampler Subclasses)Shield Firmware (Sampler Subclasses)

The sampleLoop function reads a new sample from the sensor (sensor.getSample) then calls the onReadSample function.

The sampleLoop is responsible for applying IIR and decimation filters

bool ChemSensorSampler::sampleLoop() { // Take the new sample if (go) { onReadSample(sensor.getSample()); go = false; // Filter with two cascade single pole IIRs applyIIRFilter(IIR1); applyIIRFilter(IIR2); // Apply the decimation filter return applyDecimationFilter(); } return false;}

Page 43: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 43

Shield Firmware (Sampler)Shield Firmware (Sampler)

The applyIIRFilter calculates the IIR filter from samples stored on workSample.

The result is stored on workSample. This allows multiple calls of the same function when multiple poles are required

void Sampler::applyIIRFilter(unsigned char iiRID) { unsigned char *denom = iIRDenum + iiRID; // The filter is disabled if denominator == 0 if (*denom == 0) return; double* S = iIRAccumulator + iiRID; // S(n) = S(n-1) + 1/den * (I(n) - S(n-1)) *S = *S + ((double)workSample - *S)/(*denom); workSample = (unsigned short)(ditherTool->applyDithering(*S));}

Page 44: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 44

Shield Firmware (Sampler)Shield Firmware (Sampler)

The applyDecimationFilter skips samples based on the decimation parameter.

It returns true each “decimation” samples so the calling procedure could evaluate it.

bool Sampler::applyDecimationFilter() { if (decimationTimer == decimation) { decimationTimer = 0; lastSample = workSample; } else { decimationTimer++; } return ((decimationTimer == 0) || (blankTimer != 0));}

Page 45: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 45

Shield Firmware (SamplesAverager)Shield Firmware (SamplesAverager)

Implements the last filter in the chain: average Historical samples are stored in a dynamically allocated array

so it's possible to change the buffer's deep at runtime Averaged results are released at 1/buffersize rate Fast implementation. The most important funcion is

collectSample Dithering is used to prevent DC insertion due to round floats

and limited C toolchain float support

Page 46: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 46

Shield Firmware (SamplesAverager)Shield Firmware (SamplesAverager)

The collectSample function uses an accumulator to count the average

The oldest sample is removed by the accumulator and the newest is added

The result is divided by buffer size and dithered

bool SamplesAverager::collectSample(unsigned short sample, unsigned long _timestamp) { ... accumulator = accumulator - dataBuffer[sampleOffset]; accumulator = accumulator + sample; dataBuffer[sampleOffset] = sample; sampleOffset++; lastAverageSample=ditherTool->applyDithering(accumulator/bSize);}

Page 47: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 47

Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)

Samplers and SensorsArray use specific class drivers to dialogate with hardware

Driver classes hide the low level details for handshaking I/O lines and connecting onboard peripherals

Driver classes increase software modularity and code reuse Driver classes implementation details are strictly based on

target devices datasheet

Page 48: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 48

Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)

Several driver classes are provided in the firmware. Each class targets a specific device.

LMP91000ADC16S626

AD5694RUR100CD

SFE_BMP180

Page 49: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 49

Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)

Driver classes are mainly statically allocated by the SensorsArray class and passed to Samplers via constructors

const LMP91000 SensorsArray::AFEList[NUM_OF_CHEM_SENSORS] = ...const ADC16S626 SensorsArray::ADCList[NUM_OF_CHEM_SENSORS] = ...const AD5694R SensorsArray::DACList[NUM_OF_CHEM_SENSORS] = ... UR100CD SensorsArray::ur100cd = UR100CD();SFE_BMP180 SensorsArray::bmp180 = SFE_BMP180();SensorsArray::SensorsArray() { // Initialize the sampler units samplers[CHEMSEN1]= new ChemSensorSampler(ADCList[CHEMSEN1]); samplers[CHEMSEN2]= new ChemSensorSampler(ADCList[CHEMSEN2]); ... samplers[TEMPSEN] = new TempSensorSampler(ur100cd); samplers[PRESSEN1] = new PressSensorSampler(bmp180); ...

Page 50: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 50

Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)

A simple driver class example is provided by ADC16S626 A/D converter connected to the microcontroller via an SPI and a chip select line

class ADC16S626 {public: ADC16S626(const unsigned char csPin); virtual ~ADC16S626(); unsigned short getSample() const; private: unsigned short toLinear(unsigned short twoComplSample) const; private: const unsigned char m_csPin;};

Page 51: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 51

Shield Firmware (Driver Classes)Shield Firmware (Driver Classes)

unsigned short ADC16S626::getSample() const { byte inByteHigh, inByteMid, inByteLow; digitalWrite(m_csPin, LOW); inByteHigh = SPI.transfer(0x00); inByteMid = SPI.transfer(0x00); inByteLow = SPI.transfer(0x00); digitalWrite(m_csPin, HIGH); unsigned short result = ((inByteLow >> 6) & 0x03); result |= (((unsigned short)inByteMid) << 2); result |= (((unsigned short)inByteHigh) << 10); result = toLinear(result); return result;}

Page 52: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 52

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 53: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 53

Java Panel ApplicationJava Panel Application

Targeted to run on an PC connected to the AirSensEUR Shield via RS232 to USB opto-coupled interface

Developed for debug purposes but elected by usage as main console for initial AirSensEUR set-up and configuration tool

Java based: runs on any PC and/or MAC with installed JRE (Java Runtime Environment)

NetBeans project files available It's not perfect... a lot of improvements should be done... so think

to it as a working progress project

Page 54: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 54

Java Panel ApplicationJava Panel Application Depends on jna and purejavacomm

libraries. They provides direct access to the USB/serial line interface from the JVM

Depends on AirSensEURLib project, mainly for .comm and .exceptions packages shared with other AirSensEUR Host applications (see later)

Page 55: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 55

Java Panel Application (Communcation Layer)Java Panel Application (Communcation Layer)

ChemSensorBoard is an abstract class providing the basic interface for connect/disconnect and read/write to the AirSensEUR Shield

ChemSensorCommHandler implements ChemSensorBoard with the help of SerialPortHelper and CommProtocolHelper classes

ChemSensorBoard

ChemSensorCommHandler

CommProtocolHelper

SerialPortHelper

AirSensEURLib

Page 56: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 56

AirSensEURLib (SerialPortHelper)AirSensEURLib (SerialPortHelper)

The SerialPortHelper class provides a connection layer between purejavacomm library and AirSensEUR applications

Is used to enumerate available serial interfaces Is used to open/close a known serial interface and to read/write

characters from/to it It implements the SerialPortEventListener.serialEvent defined in

the purejavacomm library. This is called each time the serial line receives data from the AirSensEUR Shield

It defines a SerialReceiverParser.onDataReceived callback interface. This should be implemented by data consumers.

Page 57: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 57

AirSensEURLib (SerialPortHelper)AirSensEURLib (SerialPortHelper)

public static interface SerialReceiverParser {

void onDataReceived(InputStream inputStream);} private class SerialReceiverListener implements SerialPortEventListener { @Override public void serialEvent(SerialPortEvent event) { if(event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { if (inputStream.available() != 0) { rxDataParser.onDataReceived(inputStream); } } }}

Page 58: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 58

AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)

The CommProtocolHelper class implements the protocol engine for connecting to the AirSensEUR Shield via a list of logical DataMessage(s)

Defines the DataMessage class used to encapsulate high level commands sent and received by the overlying application

Translates DataMessage instances to/from data stream to be sent/received via serial line

The CommProtocolHelper encapsulates low level AirSensEUR Shield protocol details providing high level function calls for the Java applications

Page 59: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 59

AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)

Three set of methods are provided:

“render” methods “eval” methods “data list” methods

Page 60: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 60

AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)

“render” methods are used by the application to “send” commands to the AirSensEUR Shield

void renderSamplerPrescaler(int channelId, int prescaler);void renderSamplerPrescalerRead(int channelId);public void renderSensorInquiry(int channelId);public void renderGetLastSample(int channelId);public void renderStartSample()public void renderStopSample()

Page 61: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 61

AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)

“eval” methods are used by the application to “receive and parse” answers coming from the AirSensEUR Shield.

“eval” methods automatically detect contents present on received DataMessage and return “null” for a not matching condition. This allows for multiple safe and distributed evaluations of the same DataMessage.

Integer evalPrescalerInquiry(DataMessage rxMessage, int channel)Integer evalDecimationInquiry(DataMessage rxMessage, int channel) String evalSensorInquiry(DataMessage rxMessage, int channel)List<Integer> evalLastSampleInquiry(DataMessage rxMessage, int channel)

Page 62: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 62

AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)

“data list” methods are used to access to internal messaging datastructure in order to push/pop commands/answers

public synchronized void clearCurrentCommandList() public synchronized List<DataMessage> getSafeCurrentCommandList()public synchronized DataMessage getNextRxDataMessage()

Page 63: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 63

AirSensEURLib (CommProtocolHelper)AirSensEURLib (CommProtocolHelper)

The conversion between incoming data from AirSensEUR Shield and DataList items is performed by the function onRxDataReceived

This function should be called by the SerialPortHelper::SerialReceiverParser implementor

// This is the main rx state machine. It aggregates all incoming// data and populates the fromBoard list as a FIFO buffer // containing all the received messagessynchronized public boolean onRxCharReceived(byte value)

Page 64: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 64

AirSensEURLib (ChemSensorBoard)AirSensEURLib (ChemSensorBoard)

ChemSensorBoard is an abstract class providing the basic interface for connect/disconnect and read/write to the AirSensEUR Shield

public interface ChemSensorBoard { public void connectToBoard(CommPortIdentifier serialPort); public void disConnectFromBoard(); public void writeBufferToBoard(); public List<CommProtocolHelper.DataMessage> getCurrentBuffer();}

Page 65: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 65

Java Panel Application Java Panel Application (ChemSensorCommHandler)(ChemSensorCommHandler)

ChemSensorCommHandler implements the ChemSensorBoard interface

It contains a SerialPortHelper instance to perform actions through the serial port

It implements the SerialPortHelper.SerialReceiverParser interface by calling the CommProtocolHelper.onRxCharReceived when needed

Allows to the Java application to access to DataMessage Lists and to flush pending commands through the serial line

Page 66: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 66

Java Panel Application (Dialogs and Panels)Java Panel Application (Dialogs and Panels)

The Java Panel application is implemented using the Swing GUI framework

Swing defines a set of graphical objects targeted to design portable graphic user applications

Graphical objects are grouped in Panels Panels are grouped together to form Dialogs

AirSensEUR Java Panel Application defines a common class for sensor properties Dialogs. This is the SensorSetupDialog

Page 67: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 67

Java Panel Application (SensorSetupDialog)Java Panel Application (SensorSetupDialog)

Provides a common interface for all setup dialogs The interface contains all methods needed to dialogate with the

AirSensEUR Shield through the CommProtocolHelper

public class SensorSetupDialog extends javax.swing.JDialog { public SensorSetupDialog(java.awt.Frame parent, boolean modal) { super(parent, modal); } public void storeToBoard() { } public void readFromBoard() { } public void evaluateRxMessage(CommProtocolHelper.DataMessage msg) { }}

Page 68: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 68

Java Panel Application (SensorSetupDialog)Java Panel Application (SensorSetupDialog)

storeToBoard is called by the application asking the setup dialog to dump their current settings to the CommProtocolHelper buffers (in order to be sent to the AirSensEUR Shield)

readFromBuffer is called by the application asking the setup dialog to fill the CommProtocolHelper with query commands for AirSensEUR Shield parameters retrieval

evaluateRxMessage is called by the application each time a new DataMessage has been received back by the AirSensEUR Shield. The dialog may use the coming DataMessage for update their panels status

Page 69: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 69

Java Panel Application (SensorSetupDialog)Java Panel Application (SensorSetupDialog)

Two setup dialogs are derived from the SensorSetupDialog:

ChemSensorSetupDialog GenericSensorSetupDialog

Page 70: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 70

Java Panel Application Java Panel Application (ChemSensorSetupDialog)(ChemSensorSetupDialog)

LMP9100Panel

AD5694RPanel

IIRAndAvgPanel

Page 71: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 71

Java Panel Application Java Panel Application (GenericSensorSetupDialog)(GenericSensorSetupDialog)

IIRAndAvgPanel

Each Dialog propagates to their panels the storeToBoard, readFromBoard, evaluateRxMessage events

Each panel is responsible for dump or updating their proper specific settings through a set of DataMessage

Page 72: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 72

Java Panel Application (setupPanel example)Java Panel Application (setupPanel example)

The simplest panel is the IIRAndAvgPanel

Page 73: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 73

Java Panel Application (Setup Panels)Java Panel Application (Setup Panels)

IIRAndAvgPanel

Items in the panel are implemented by a set of Swing widgets Widget options are defined in Data Models Data Models associate a “label” to be shown to the user with a

“value” to be sento to the AirSensEUR Shield registers and viceversa

Page 74: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 74

Java Panel Application (Data Models)Java Panel Application (Data Models)

Two common typologies are needed:

Slider and Register Data Models

Page 75: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 75

Java Panel Application (SampleLogger)Java Panel Application (SampleLogger)

SampleLogger is a Swing JPanel derived class providing basic abastraction interface for entities able to manage set of samples

Defines the DataProcessing interface targeted to evaluate incoming samples through a set of mathematical expressions

Implements the DataProcessing interface by providing a standard two complements translation to be applied to AirSensEUR Shield four chemical channels data

Implements the common procedures needed to extract and detect new samples based on associated timestamp

Implements the readFromBoard and evaluateRxMessage common to all derived sample loggers

Page 76: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 76

Java Panel Application (SampleLogger)Java Panel Application (SampleLogger)

Two SampleLogger derived classes:

LineGraphSampleLoggerPanel TextBasedSampleLoggerPanel

Page 77: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 77

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 78: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 78

Host HardwareHost Hardware

ARM9@400MHz based, 256MB RAM, running Debian Linux from a micro SD card

LiFePO4 Battery and/or USB/Wall adapter operated, with battery parameters available to the CPU through I2C

USB/wall power plugs protected by overvoltage and polarity reversal

Four independent step-up power supply, supervised by the CPU

Onboard USB sockets for WiFi and GPRS dongles Onboard low power GPS module with 1PPS signal feed back to

the CPU and optional high gain external antenna

Page 79: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 79

Host HardwareHost Hardware

I2C connected front panel with 8 programmable LEDs and 8 programmable pusbuttons

Expansion socket providing access to not yet used onboard peripherals (note: 3v3 operating only) like:

SPI I2C Low res A/D converter lines Low res PWM lines

Page 80: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 80

Host HardwareHost Hardware

Step up Power Supply

5V@1A

LiFePO4Battery

ARM9 basedmodule

GPSmoduleFront Panel

Step up Power Supply

7V@300mA and level shifters

BatteryManager

+5VDC@3A SerialUSB

Step up Power Supply

5V@1A

Step up Power Supply

5V@1A

Unregulated3v3 line5V line

WiFiDongle

GPRSDongle

AirSensEURShield

I2C

USB

Page 81: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 81

Host Hardware (Battery Manager)Host Hardware (Battery Manager)LTC4156 I2C programmable

LiFePO4 battery manager

LTC2942 I2CFuel Gauge Engine

Active overvoltage andreverse polarity protection

Page 82: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 82

Host Hardware (Battery Manager)Host Hardware (Battery Manager)

Built as external module for easy replacement when targeting different battery techologies

Based on Linear Technology LTC4156 dual input, high efficient, I2C programmable LiFePO4 battery manager single chip solution

Inputs are protected from overvoltage and polarity reversal Independent, programmable current limiters for USB and wall

adapter lines Instant-on operation with low battery; operation without battery

installed is allowed Embeds a Linear Technology LTC2942 I2C programmable fuel

gauge with charge counter and voltage converter

Page 83: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 83

Host Hardware (Main Power Supply)Host Hardware (Main Power Supply)MAX8815 step up converter

5V up to 1APower on and shutdown

signals controlled by a PIC12microcontroller

Page 84: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 84

Host Hardware (Main Power Supply)Host Hardware (Main Power Supply)

5V up to 1A are generated by a dedicated Maxim MAX8815A step up converter, independently by battery charge status

A PIC12F1571 microcontroller generates the proper power on/shutdown signals (wake and shutdown) based on user request on the Power On pushbutton

Shutdown signal is propagated to the CPU thus allowing a graceful Linux power off

Standard PIC brown out circuit detects low battery status and shuts down the system

Page 85: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 85

Host Hardware (Shield connection)Host Hardware (Shield connection)TTL to 3v3 bidirectional

translators

CPU controlled7V@300mA Step Up

Power supply

Page 86: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 86

Host Hardware (Main Power Supply)Host Hardware (Main Power Supply)

A Philips dual channels IC translator interfaces the TTL based serial line coming from the AirSensEUR Shield into a 3v3 lines and viceversa

The AirSensEUR Shield power supply is generated by the Host through a Microchip MCP1661 step up converter.

MCP1661 generates 7V with 300mA max current starting from the unregulated battery voltage.

An active switch, composed by Q3 and Q4, is used to completely shut off the 7V generation if required by the CPU

Page 87: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 87

Host Hardware (Dongles connection)Host Hardware (Dongles connection)USB host connectors

For USB WiFi and GPRS

MAX8815 step up converter5V max 1A

Control line from theCPU module

Page 88: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 88

Host Hardware (Dongles connection)Host Hardware (Dongles connection)

Two 5V up to 1A rails are generated by two dedicated Maxim MAX8815A step up converter, independently by battery charge status

Compatible to USB specifications (max 500mA for USB 1 and 2 and up to 900mA for USB3)

Step up converters can be turned on/off by a dedicated GPIO line in the CPU module

Page 89: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 89

Host Hardware (Front Panel)Host Hardware (Front Panel)PORTB used as input

MCP23017 I2C16 I/O programmable lines

PORTA used as output

Page 90: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 90

Host Hardware (Front panel)Host Hardware (Front panel)

Based on Microchip MCP23017 I2C 16 bit programmable I/O expander

Supported by Linux driver kernels as a standard GPIO and LED devices

Two available input/output ports used, respectively, for LEDs and pushbuttons

The front panel implements other spare pushbuttons, like PowerOn and Reset, and 3DFix LED, via custom lines

Page 91: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 91

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 92: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 92

Host Linux CustomizationHost Linux Customization

The AirSensEUR Host runs a small Debian Linux distribution Targeted to Debian Wheezy with kernel 4.2.6 for armel

architecture The AirSensEUR Host is an embedded system... no BIOS

installed To properly boot Linux, a suitable bootloader is needed. This is

an open source bootloader provided by Atmel Corporation Kernel and bootloader should be patched to target to the CPU

module and to AirSensEUR framework A 115200bps 8N1 serial debug port is available for reading boot

logs and interact with a bare ASCII shell

Page 93: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 93

Host Linux Customization (Boot process)Host Linux Customization (Boot process)

Three actors are involved: CPU, bootloader and Linux Kernel The CPU scans for a well known places in order to find a

“signed” binary acting as bootloader The CPU loads the bootloader binary into an onchip RAM

memory and starts running the bootloader The bootloader initializes the onchip peripherals (timers,

memory interface and so on) then loads the kernel image, from a well defined location, into the external RAM

The bootloader loads the kernel configuration image file from a well defined location

The bootloader uncompress the Linux kernel then starts run it

Page 94: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 94

Host Linux Customization (Boot process)Host Linux Customization (Boot process)

The kernel parses the binary configuration image and initializes the drivers embedded into the kernel image

The kernel “mounts” an external filesystem where other drivers are availables as “modules”

The kernel locates all the available driver modules, loads and configure them based on the binary configuration image details

The kernel starts the application services The kernel runs the user defined initialization script

Page 95: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 95

Host Linux Customization (Boot process)Host Linux Customization (Boot process)

CPU: AT91SAM9G25 made by Atmel Corporation CPU module: AriettaG25 made by Acme Systems Srl Bootloader: at91bootstrap-3.7 (patched) compiled as boot.bin Kernel: Linux kernel 4.2.6 (patched)

Kernel Image: zImage Kernel binary configuration file tree: acme-arietta.dtb

Linux filesystem: Debian Wheezy generated with Multistrap Kernel modules: located on /lib/modules/4.2.6+ User defined initialization script: bash script located at

/etc/rc.local

Page 96: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 96

Host Linux Customization (CPU Boot process)Host Linux Customization (CPU Boot process)

AT91SAMG25 is not a “simple” CPU: is a SystemOnChip (SOC) It embeds an ARM CPU core AND a lot of peripherals like: MMU,

MMC, Timers, I/O, ADC, PWM, I2C, SPI, USB, Watchdog, and many other

It provides a very small ROM where a very basic program is stored and is run by the CPU at power on

The CPU scans a set of well known peripherals (USB, SPI, GPIO and MMC) in order to find a predefined byte pattern signature identifying a suitable bootloader.

AirSensEUR Host provides this bootloader in a boot.bin file located in the first partition of the microSD card. This partition should be formatted with a valid FAT16 filesystem

Page 97: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 97

Host Linux Customization (Bootloader)Host Linux Customization (Bootloader)

At91boostrap code is an open source bootloader provided by Atmel Corporation

It's targeted to a set of SOC made by Atmel and should be patched to target the AriettaG25 module

The bootloader initializes the basic peripherals (timer, watchdog, MMU) in order to allow access to the external RAM memory

The bootloader loads kernel and configuration images from the first partition of the microSD card, formatted with FAT filesystem, by pointing to the files zImage and acme-arietta.dtb

The bootloader deflates the Linux kernel image and jumps to the first kernel opcode

Page 98: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 98

Host Linux Customization (Kernel boot)Host Linux Customization (Kernel boot)

AirSensEUR Host runs a patched version of the Linux kernel 4.2.6

Patches are related to some missing/mismatching drivers (the battery manager IC, the I2C expander in the front panel and some minor changes in the CPU module)

The kernel parses the binary tree configuration file then starts configuring and executing the drivers found in the uncompressed zImage file

The kernel “mounts” the second partition found in the microSD where an EXT4 filesystem is populated with dynamically compiled driver modules

The kernel loads and configure the external driver modules

Page 99: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 99

Host Linux Customization (DTS and DTB)Host Linux Customization (DTS and DTB)

The Linux kernel is widely adopted in platform with different architecture, peripherals and options

When running on a PC, a set of enumeration and discovery systems have been provided. This is not true for an embedded system

The solution is to provide a standard configuration file where all configuration details are specified. This is performed by the Device Tree

ASCII readableconfiguration file

source (DTS)

Binary parsableconfiguration file

(DTB)DTS Compiler

Page 100: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 100

Host Linux Customization (DTS and DTB)Host Linux Customization (DTS and DTB)

The DTS is a “tree” where the hardware relationships and parameters are defined

Bus controllers are linked with bus connected devices Bus connected devices are logically added to low level services

and so on

Page 101: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 101

Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)

Page 102: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 102

Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)

Page 103: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 103

Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)

Page 104: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 104

Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)

Page 105: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 105

Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)

Page 106: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 106

Host Linux Customization (DTS examples)Host Linux Customization (DTS examples)

Page 107: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 107

Host Linux Customization Host Linux Customization (Hardware Abstraction)(Hardware Abstraction)

The Linux Kernel provides an “easy” way to map hardware subsystems into files descriptors.

AirSensEUR Host uses this feature to statically map I/O, serial lines, I2C subsystems into a well known set of file descriptors

High level applications and bash scripts can use those files to access to the hardware “like if” they're interacting with a file

That's one of the sucess keys of the Linux kernel!

echo 1 > /sys/class/leds/led_1/brightnessecho "Hello" > /dev/ttyS1echo “ATDT123456” > /dev/ttyUSB2

Page 108: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 108

Host Linux Customization Host Linux Customization (Hardware Abstraction)(Hardware Abstraction)

Subsystem Driver File PathDirect GPIO atmel-gpio /sys/class/gpioDirect GPIO leds-gpio /sys/class/ledsI2C LEDs leds-gpio (gpio virtualized

by gpio-mcp23s08 driver)/sys/class/leds

Direct pushbuttons gpio-keys ./sys/class/input/event0I2C pushbuttons gpo-keys-polled (gpio

virtualized by gio-mcp23s08 driver)

/sys/class/input/event1

I2C Battery manager ltc4156_charger /sys/class/power-supply/ltc4156-charger-0

I2C Battery Fuel Gauge ltc2941-battery-gauge /sys/class/power-supply/ltc2943-0

Step up converters, GPS power supply and PPS signals are treated as GPIO lines

Page 109: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 109

Host Linux Customization (rootfs)Host Linux Customization (rootfs)

The Linux kernel is only part of the game. AirSensEUR Host applications runs over a Linux Debian

Wheezy distribution A Wheezy distribution can be easily obtained though Multistrap Multistap allows defining a set of application packages to be

included in the target file system, thus simplifying the Debian customization process

The target file system should be copied into the microSD second partition, formatted with an EXT4 filesystem, together with the AirSensEUR Host application binaries and shell scripts

Page 110: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 110

Host Linux Customization (middleware)Host Linux Customization (middleware)

Small programs running in background Provides elementary functions needed to interface the

hardware with high level applications To be compiled from sources and copied on the target rootfs

Eventmonitor rpi_gpio_ntp

Page 111: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 111

Host Linux Customization (Eventmonitor)Host Linux Customization (Eventmonitor)

Small C custom program for AirSensEUR Host Listen to incoming pushbuttons event and executes the

appropriate batch script Batch script should be located into /etc/eventmonitor folder,

should be named “hadler_xx” where xx is the event number associated to the pushbutton. Script should be marked as executable

Page 112: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 112

Host Linux Customization (rp_gpio_ntp)Host Linux Customization (rp_gpio_ntp)

Written by Folkert van Heusden and released under GPLv2 Works together with an NTP server running on the same

platform Analyzes a GPIO line where a PPS signal is connected and

transfer information to the NTP server Useful to implement a local precise NTP server when no

network connectivity is present but GPS information is available

Page 113: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 113

Host Linux Customization (NTP Service)Host Linux Customization (NTP Service)

NTPd https://www.eecis.udel.edu/~mills/ntp/html/ntpd.html Synchronizes the local real time clock with a set of sources Sources can be defined via a configuration script Contacts external NTP server when data network is ready Interact with GPS local services when available

Page 114: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 114

Host Linux Customization (GPS Service)Host Linux Customization (GPS Service)

GPSd http://www.catb.org/gpsd/ Monitors the AirSensEUR Host GPS module connected through

a serial line Publishes JSON data through a local TCP socket on port 2947 Provides an abstraction layer between GPS module brands and

protocols Provides access to GPS data to multiple processes Interacts with a local NTP server for (second based) precise

local timestamp synchronization with GPS information

Page 115: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 115

Host Linux Customization (Hostapd)Host Linux Customization (Hostapd)

Hostapd is a user space daemon for access point and authentication servers (https://w1.fi/hostapd/)

It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and more

Licenced under the terms of BSD license. Implementred by Jouni Malinen

AirSensEUR Host requires Hostapd to provide a WiFi access point connection through a WiFi USB dongle.

Page 116: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 116

Host Linux Customization (WvDial)Host Linux Customization (WvDial)

WvDial https://github.com/wlach/wvdial Is a command line ppp dialer Easy to configure and use Can be run by external batch scripts

AirSensEUR Host requires WvDial to handle GPRS ppp connections via a GPRS USB dongle

Page 117: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 117

Host Linux Customization (Lighttpd)Host Linux Customization (Lighttpd)

Lighttpd https://www.lighttpd.net/ Small footprint, efficient HTTP server Easy to configure Can provide CGI and integrate with interpreted languages, like

PHP

AirSensEUR Host requires Lighttpd to provide a Web Console Management for easy setup and control

Page 118: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 118

Host Linux Customization (Many others)Host Linux Customization (Many others)

Many others services and middle layer applications are required by the AirSensEUR Host to properly operate

Some examples are: Shell Cron Network tools SSH Server Java Runtime Environment …

The whole services are downloaded and installed by Multistrap

Page 119: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 119

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 120: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 120

AirSensEUR Host ApplicationsAirSensEUR Host Applications

Two categories

BASH Scripts

Java Applications

Page 121: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 121

Host Applications (Bash scripts)Host Applications (Bash scripts)

Mainly for very high level, very common, system related actions Start/stop processes and services Check processes and service status Handle network interfaces Handle LEDs and step up converter status

Fast and easy to implement and maintain Mainly located in /usr/local/airsenseur

Page 122: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 122

Host Applications (Java Applications)Host Applications (Java Applications)

Targeted to data management Connect to the AirSensEUR Shield and other data sources Store collected data in a local sqlite database Perform data transfer to external servers

Can benefit from the pletora of freely available and tested Java libraries

Developing Java is fast and the debug can be performed remotely through a TCP connection

Page 123: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 123

Host Applications (Java Applications)Host Applications (Java Applications)

Three main Actors:

Data Aggregator Data PushHost

Page 124: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 124

Host Applications (Java Applications)Host Applications (Java Applications)

Data Aggregator

Sqlite FileGPS Info

AirSesEUR Shield

GPSd

Host/dev/ttyS1

/dev/ttyS2

JSONRPCTCP 8000

JSONTCP 2947

Page 125: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 125

Host Applications (Java Applications)Host Applications (Java Applications)

Sqlite File

Data Push

JSON, XML,

...

Page 126: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 126

Host Applications (AirSensEURHost)Host Applications (AirSensEURHost) Depends on jna and purejavacomm

libraries. They provides direct access to the USB/serial line interface from the JVM

Depends on json rpc and jackson libraries

Depends on expr-master libraries providing mathematical expression evaluation

Depends on AirSensEURLib project, mainly for .comm, .json, .persisters and .exceptions packages

Page 127: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 127

AirSensEURHost (Communcation Layer)AirSensEURHost (Communcation Layer)

ChemSensorBoard is an abstract class providing the basic interface for connect/disconnect and read/write to the AirSensEUR Shield

ChemSensorHostCommHandler implements ChemSensorBoard with the help of SerialPortHelper and CommProtocolHelper classes

ChemSensorBoard

ChemSensorHostCommHandler

CommProtocolHelper

SerialPortHelper

AirSensEURLib

Page 128: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 128

AirSensEURHost AirSensEURHost (ChemSensorHostCommHandler)(ChemSensorHostCommHandler)

ChemSensorHostCommHandler implements the ChemSensorBoard interface

It contains a SerialPortHelper instance to perform actions through the serial port

It implements the SerialPortHelper.SerialReceiverParser interface by calling the CommProtocolHelper.onRxCharReceived when needed

Defines a ChemSensorMessageHandler.onNewPacketReady callback function used to signal new valid packets received from the AirSensEUR Shield

It automatically connects and re-connects to the serial line if errors where detected on the received data

Page 129: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 129

AirSensEURHost (ChemSensorHost)AirSensEURHost (ChemSensorHost)

ChemSensorHost implements the ChemSensorMessageHandler interface and extends the Timer functionality

It periodically asks for new samples availability to the AirSensEUR Shield

Each sample received by the AirSensEUR Shield is evaluated and stored on a local buffer (implemented by the CollectedData internal class)

The collected data list contents is extracted by the ChemSensorServiceImpl class (explained later)

Page 130: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 130

AirSensEURHost (JSONServer)AirSensEURHost (JSONServer)

JSONServer is a wrapper class used to instantiate a JSON RPC server by mean of the jsonrpc4j library

Available procedures are defined by the ChemSensorService interface located on the AirSensEURLib library

Page 131: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 131

AirSensEURHost (ChemSensorServiceImpl)AirSensEURHost (ChemSensorServiceImpl)

ChemSensorService interface is implemented by ChemSensorServiceImpl class

Each method is called by the JSONServer engine Data are sent back to the client through containers defined in

AirSensEURLib library

Page 132: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 132

AirSensEURLib (SampleData)AirSensEURLib (SampleData)

Page 133: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 133

Host Applications (ASDataAggregator)Host Applications (ASDataAggregator) Depends on json rpc and jackson

libraries Depends on sqlite4java and gpsd4java

libraries Depends on AirSensEURLib project,

mainly for .comm, .json, .persisters and .exceptions packages

Depends on AirSensEURSqlLib project, where SQL helpers and containers are shared with other host applications

Page 134: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 134

AirSensEURDataAggregator AirSensEURDataAggregator

AirSensEURDataAggregator aggregates information coming from multiple sources and store all together in a local sqlite database

Acts as a JSON client for the GPSd daemon Acts ad a JSON client for the AirSensEURHost application Uses local clock to timestamp all information inserted in the

database

All aggregated information are stored as a single entry in the database table and, for convenience, on a .csv local file

Page 135: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 135

ASDataAggregator (ASDataAggregatorEngine)ASDataAggregator (ASDataAggregatorEngine)

AirSensEURDataAggregatorEngine.task() implements the whole actions. It's periodically called by the main routine

End

Start

GPSDataCollector.poll()

ChemSensorClient.getLastSample

SamplePersisterFile.addSample()

SamplePersisterSQL.addSample()

Page 136: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 136

ASDataAggregator (GPSDataCollector)ASDataAggregator (GPSDataCollector)

GPSDataCollector is a wrapper class for the GPSEndpoint provided by the gpsd4java library

It connects to the GPSd server and retrieves JSON data GPS information are temporarily stored to be used by the

aggregator engine when required

Page 137: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 137

AirSensEURLib (ChemSensorClient)AirSensEURLib (ChemSensorClient)

ChemSensorClient is a wrapper for a ChemSensorService proxy implementation

Any call to a function by instances of ChemSensorClient generates an RPC to the server through a socket connection

RPC results are returned as a plain java object

Remote Procedure Calls details are completely hidden to calling methods

Page 138: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 138

AirSensEURLib (ChemSensorClient)AirSensEURLib (ChemSensorClient)

Page 139: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 139

AirSensEURLib (SampleData)AirSensEURLib (SampleData)

Page 140: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 140

AirSensEURLib (SamplesPersister)AirSensEURLib (SamplesPersister)

SamplesPersister is a public interface defining a set of functions common to an abstract entity providing persistance of sample datasets (SampleDataContainer)

Page 141: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 141

AirSensEURLib (SamplePersisterFile)AirSensEURLib (SamplePersisterFile)

SamplePersisterFile implements a SamplePersister interface by providing a comma separated values file persistence

Page 142: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 142

AirSensEURSqlLib (SamplePersisterSQL)AirSensEURSqlLib (SamplePersisterSQL)

SamplePersisterSQL implements a SamplePersister interface by providing persistence through sqlite database

Page 143: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 143

Host Applications (AirSensEURDataPush)Host Applications (AirSensEURDataPush) Depends on sqlite4java, httpclient and

jackson libraries Depends on AirSensEURLib project,

mainly for .comm, .json, .persisters and .exceptions packages

Depends on AirSensEURSqlLib project, where SQL helpers and containers are shared with other host applications

Depends on AirSensEURSOSDbLib project where 52North SOS RPCs are implemented

Depends on AirSensEURInfluxDBLib project where INFLUX DB helpers are implemented

Page 144: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 144

AirSensEURDataPushAirSensEURDataPush

AirSensEURDataPush reads information stored on a local sqlite database and pushes uncommitted data to a remote data server

It can push data to two remote data server types: 52North SOS server (JSON InsertObservations API) INFLUX DB

Page 145: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 145

AirSensEURDataPushAirSensEURDataPush

In 52North SOS working mode: For each sensor channel:

Ask for the last valid sample data timestamp Retrieve a chunk of data from the local database with

timestamp greater than the last found timestamp Populate an InsertObservation by filling a multiple set of

Observations Generate an HTTP POST with the JSON(ized)

InsertObservation pointing to the remote server Repeat until no more samples are available in local

database

Page 146: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 146

AirSensEURDataPushAirSensEURDataPush

In INFLUX DB working mode: Retrieve, from a local history database file, the timestamp for

the last valid commit operation Retrieve, from the local samples database, a chunk of data

with timestamp greater than the last found timestamp Populate a SampleDataSerie with collected information Generate an HTTP POST with the JSON(ized)

SampleDataSerie pointing to the remote server Update the local history database with last updated

timestamp Repeat until no more samples are available in the local

database

Page 147: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 147

AirSensEURDataPushAirSensEURDataPush

Data Push

History persister

SQL persisterSample persister

Configuration engine

Page 148: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 148

AirSensEURDataPush (HistoryPersister)AirSensEURDataPush (HistoryPersister)

Used to retrieve the timestamp of a last valid data committed to the server

HistoryPersisterSQL generates a local sqlite file and uses it as a persistance medium

HistorySOSDB executes a GetDataAvailability RPC on SOS server

Page 149: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 149

AirSensEURDataPush (SamplesPersister)AirSensEURDataPush (SamplesPersister)

SamplePersisterInfluxDB persists data through a set of HTTP JSON post compatible with Influx DBs

SamplePersisterSOSDB generates a set of InsertObservation calls. Each InsertObservation is filled by several Observation(s) in order to increase the network efficiency. Required containers are defined in the .dao package in AirSensEUDSOSDbLib project

Page 150: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 150

Java Host Application configurationJava Host Application configuration

Configuration is handled by a private Configuration class implemented in all Java Host Applications

Configuration is read from .properties file. Valid tokens and possible values are defined in the Configuration class

configuration.properties files are located at /usr/local/etc and are specified by the shell startup scripts with the following rules

Application Configuration FileAirSensEURHost sensor.propertiesAirSensEURDataAggregator aggregator.propertiesAirSensEURDataPush (SOSDb) datapushsosdb.propertiesAirSensEURDataPush (InfluxDb) influxpush.properties

Page 151: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 151

AgendaAgenda

System Overview AirSensEUR Shield Hardware AirSensEUR Shield Firmware The Java Panel Application AirSensEUR Host Hardware AirSensEUR Host Linux Customization AirSensEUR Host Applications AirSensEUR Web Management Console

Page 152: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 152

Web Management ConsoleWeb Management Console

Feedback on AirSensEUR Host activities status Simple configuration of main working parameters Wi-Fi reachable

Page 153: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 153

Web Management ConsoleWeb Management Console

Server Side Browser Side

HTTPAjaxJSON

Page 154: AirSensEUR: AirQuality monitoring open framework technical presentation

January 2016 154

Web Management ConsoleWeb Management Console

Client side developed with ReactJs and styled with Bootstrap Client-Server data exchange in JSON format Server side developed with small PHP scripts targeting a single

function each one PHP scripts interacting with BASH for configuration files

generation, start/stop processes Live data retrieved by PHP scripts through JSON calls to

AirSensEURHost application and sent back to the client Data Push scheduling through custom cron file PHP editors