Android industrial Real-Time Data Visualization Michael Guntli - - PowerPoint PPT Presentation

β–Ά
android industrial
SMART_READER_LITE
LIVE PREVIEW

Android industrial Real-Time Data Visualization Michael Guntli - - PowerPoint PPT Presentation

Android industrial Real-Time Data Visualization Michael Guntli mguntli@imt.ch IMT AG, Switzerland 2 3 Mobile Ventilator Tester 4 System Architecture Airflow Pressure Temp. Sensor Sensor Sensor Oxygen Cell Touch Screen Pressure


slide-1
SLIDE 1

Android industrial

Real-Time Data Visualization

Michael Guntli mguntli@imt.ch IMT AG, Switzerland

slide-2
SLIDE 2

2

slide-3
SLIDE 3

3

slide-4
SLIDE 4

Mobile Ventilator Tester

4

slide-5
SLIDE 5

System Architecture

5

Baseboard (Measurement Controller) Sampling @200Hz

CAN USB Pressure Sensor Airflow Sensor RS232

UI-Board (Visualization Controller)

Touch Screen Oxygen Cell UART Ethernet Display Pressure Sensor Pressure Sensor Temp. Sensor

slide-6
SLIDE 6

6

slide-7
SLIDE 7

7

slide-8
SLIDE 8

8

slide-9
SLIDE 9

Senior Software Engineer / Project Leader

  • Bare Metal Embedded
  • BSP Development
  • Android / WPF

9

IMT AG

  • Medical Technology
  • Embedded Systems
  • Industrial Automation
slide-10
SLIDE 10

App Update- Server BSP Hardware

10

  • CPU
  • Memory
  • Flash
  • Display & Touch
  • Connectivity
  • Power Supply
slide-11
SLIDE 11

EEVblog #822 - World's Worst Tablet Computer Teardown: https://www.youtube.com/watch?v=2o8MDCIlOEk

11

slide-12
SLIDE 12

IMT-iMX6

  • Android L5.1.1
  • 1GB LPDDR2 RAM
  • 4GB eMMC
  • 2x ARM Cortex-A9

@800 MHz

  • WiFi with FCC-ID
  • 4.3" display
  • capacitive multi-touch

12

slide-13
SLIDE 13

Antutu Benchmark

13

2000 4000 6000 8000 10000 12000 UX CPU RAM i.MX6D Sabre 480 x 592 2x 792 MHz SCM-i.MX6D 480 x 592 2x 792 MHz Wiko Lenny 2 480 x 854 2x 1300 MHz

slide-14
SLIDE 14

Antutu Benchmark

14

5000 10000 15000 20000 25000 30000 35000 UX CPU RAM i.MX6D Sabre 480 x 592 2x 792 MHz SCM-i.MX6D 480 x 592 2x 792 MHz Wiko Lenny 2 480 x 854 2x 1300 MHz Nexus 6P 1440 x 2392 4x 1555 MHz 4x 1958 MHz nVidia TX1 1920 x 1080 4x 2014 MHz

slide-15
SLIDE 15

App Update- Server BSP Hardware

15

  • Hardware initialization
  • Device drivers
  • Pin configuration
  • RAM timings
  • eMMC
  • Display & touch
  • WiFi
  • Power optimizations
  • Production flashing
slide-16
SLIDE 16

App Update- Server BSP Hardware

16

slide-17
SLIDE 17

17

slide-18
SLIDE 18

Performance aware programming

  • Know your hardware
  • Developing for Android
  • Memory
  • Performance
  • Framework
  • User Interface
  • Android Performance Patterns

18

slide-19
SLIDE 19

Architecture?

Dagger Butterknife Ted Mosby ProtoBuf Picasso Parceler IcePick SQLite db

Architecture?

Activities Fragments Layouts

UI

+

19

slide-20
SLIDE 20

Your code might be somewhere here…

20

slide-21
SLIDE 21

App functionality

  • Read binary data from UART
  • Collect & convert raw data into measurement samples
  • Update chart and numeric values

21

slide-22
SLIDE 22

Offload from UI thread

Read binary data Convert measurement samples Update chart & numeric values Render Chart

UI Thread OpenGL-Rendering Thread Processing Thread Communication Thread

22

slide-23
SLIDE 23

Functional Units

Component

𝑔 𝑦 = 𝑏0 +

π‘œ=1 ∞

π‘π‘œ cos π‘œπœŒπ‘¦ 𝑀 + π‘π‘œ sin π‘œπœŒπ‘¦ 𝑀 Input(x) Output f(x)

23

slide-24
SLIDE 24

Data flow & event driven design

UI Communication Processing Raw data Measurement samples float flow; float pChannel; float tChannel; VolumetricFlow flow; Pressure pChannel; Temperature tChannel; 010101000110101 200Hz 200Hz 60Hz / 30Hz

24

slide-25
SLIDE 25

Simple concurrency with actor model

  • Receiving, processing and sending messages
  • Each actor is a handler thread

https://www.youtube.com/watch?v=0Z5MZ0jL2BM

25

slide-26
SLIDE 26

Android Main Looper Thread

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ActivityThread.java

26

slide-27
SLIDE 27

IMT DFF Notation (Active Parts)

Input Output

27

slide-28
SLIDE 28

IMT DFF Notation (Active Parts)

28 DataTrending

medium Priority medium Priority high Priority low Priority

PortIn PortIn PortIn PortIn Uart3

IOIOI

PortOutData PortOutData RawData Measurement Samples Measurement Samples PortOutUpdate

slide-29
SLIDE 29

IMT DFF Notation (Active Parts)

29 DataTrending

medium Priority medium Priority high Priority low Priority

PortIn PortIn PortIn PortIn

medium Priority

PortIn UpdateServer Uart3

IOIOI

PortOutData PortOutData

low Priority

PortIn

low Priority

PortIn PortOutData PortOutAlarm RawData Measurement Samples Measurement Samples PortOutStatus PortOutUpdate AlarmLogs

slide-30
SLIDE 30

IMT DFF Notation (Active Parts)

30 DataTrending

medium Priority medium Priority high Priority low Priority

PortIn PortIn PortIn PortIn Uart3

IOIOI

PortOutData PortOutData RawData Measurement Samples Measurement Samples PortOutUpdate

slide-31
SLIDE 31

Code Example: Create & Connect

31 private final CommunicationAP com; private final ProcessingAP processing; private final UiAP ui; private final TrendingAP trending; private final ChannelOneToOne comToProcessing; private final ChannelOneToAny processingToAny; @Override public void onInitialize() { super.onInitialize(); comToProcessing.connectPorts(com.portOutData, processing.portIn); processingToAny.connectPorts(processing.portOutData, ui.portIn); processingToAny.connectPorts(processing.portOutData, trending.portIn); … }

DataTrending

medium Priority medium Priority high Priority low Priority

PortIn PortIn PortIn PortIn Uart3

IOIOI

PortOutData PortOutData RawData Measurement Samples Measurement Samples PortOutUpdate

slide-32
SLIDE 32

Code Example: RawData

/** * A Raw data packet contains the sampled sensor values as primitive data types. */ public final class RawDataProtocol implements SerializableIfc { // sequence number of sampled data private long samplingNumber; // volumetric flow [l/min] private float flow; // pressure differential [mbar] private float pressureDiff; // pressure in channel [mbar] private float pressureChannel; 32

slide-33
SLIDE 33

Code Example: Measurement Sample

/** * A measurement sample contains values that belong to the same point in time. */ public class MeasurementSampleProtocol implements SerializableIfc { // The sequence number of the current sample. private long samplingNumber; // The current flow. private VolumetricFlow flow; // P Diff., the current external differential pressure. private Pressure pressureDiff; // P Channel, the current channel pressure. private Pressure pressureChannel; 33

slide-34
SLIDE 34

Code Example: ProcessingAP (V1)

public void execute(int protocolIdentifier, SerializableIfc eventData) { switch (protocolIdentifier) { case ProtocolIdentifiers.RAW_DATA: processRawData((RawDataProtocol) eventData); break; default: break; } } private void processRawData(RawDataProtocol rawdata) { Entity<MeasurementSample> sample = new Entity<MeasurementSample>.Builder() .samplingNumber(rawdata.getSamplingNumber() .flow(new VolumetricFlow(rawdata.getFlow(), VolumetricFlowUnit.lpm) .pressureDiff(new Pressure(rawdata.getPressureDiff(), PressureUnit.mbar) .pressureChannel(new Pressure(rawdata.getPressureChannel(), PressureUnit.mbar); … .build(); PortOutData.write(ProtocolIdentifiers.MEASUREMENT_SAMPLE, sample); } 34

medium Priority

PortIn PortOutData RawData Measurement Samples

slide-35
SLIDE 35

Code Example: ProcessingAP (V1)

public void execute(int protocolIdentifier, SerializableIfc eventData) { switch (protocolIdentifier) { case ProtocolIdentifiers.RAW_DATA: processRawData((RawDataProtocol) eventData); break; default: break; } } private void processRawData(RawDataProtocol rawdata) { Entity<MeasurementSample> sample = new Entity<MeasurementSample>.Builder() .samplingNumber(rawdata.getSamplingNumber() .flow(new VolumetricFlow(rawdata.getFlow(), VolumetricFlowUnit.lpm) .pressureDiff(new Pressure(rawdata.getPressureDiff(), PressureUnit.mbar) .pressureChannel(new Pressure(rawdata.getPressureChannel(), PressureUnit.mbar); … .build(); PortOutData.write(ProtocolIdentifiers.MEASUREMENT_SAMPLE, sample); } 35

medium Priority

PortIn PortOutData RawData Measurement Samples

slide-36
SLIDE 36

36 /** * The sequence number of the current sample. */ private long samplingNumber; // FastData /** * The current flow. */ private VolumetricFlow flow; /** * P Diff., the current external differential pressure. */ private Pressure pressureDiff; /** * P Channel, the current channel pressure. */ private Pressure pressureChannel; /** * P High, the current high pressure. */ private Pressure pressureHigh; /** * O2, the current oxygen concentration. */ private OxygenConcentration oxygen; /** * The current integrated volume in high flow [ml] since trigger start with configured volume standard and gas type. */ private Volume volume; /** * The current breath state. */ @BreathPhase.Enum int breathPhase;

slide-37
SLIDE 37

Units and Quantity

Unit

e.g. Pressure: Pascal, Bar, Torr, cmH2O, inHg

Quantity

e.g. Pressure, Flow, Volume, Temperature

37

slide-38
SLIDE 38

Units and Quantity

public class Pressure extends Quantity<PressureUnit> { public Pressure(double value, PressureUnit unit) { super(value, unit); } public enum PressureUnit implements Unit<PressureUnit> { // Pressure in bar [bar]. bar(PressureUnitFactor.bar, R.string.units_pressure_bar, UnitId.bar), // Pressure in millibar [mbar]. mbar(PressureUnitFactor.mbar, R.string.units_pressure_mbar, UnitId.mbar), // Pressure in pound-force per square inch [psi]. psi(PressureUnitFactor.psi, R.string.units_pressure_psi, UnitId.psi),

Example

Pressure pressureAmbient = new Pressure(1013.25, PressureUnit.mbar); assertEquals(1.01325d, pressureAmbient.getValue(PressureUnit.bar)); assertEquals(407.181170d, pressureAmbient.getValue(PressureUnit.inH2O)); 38

slide-39
SLIDE 39

Units and Quantity

Primitive types

double pressure_mbar = 1013.25; double pressure_bar = pressure_mbar / 1000; double pressure_inH2O = pressure_mbar * 0.401843;

Complex types

Pressure p = new Pressure(1013.25, PressureUnit.mbar); double pressure_bar = p.getValue(PressureUnit.bar)); double pressure_inH2O = p.getValue(PressureUnit.inH2O)); 39

slide-40
SLIDE 40

Units and Quantity

  • JSR 363: Units of Measurement API
  • Type safety
  • Imt.Base.Units focused on Android performance
  • Type safety
  • Most probable unit is pre-calculated
  • Lazy conversion
  • No reflection
  • No dynamic memory
  • Fast conversion (not through base unit)

40

slide-41
SLIDE 41

41

slide-42
SLIDE 42

42

DataTrending

medium Priority medium Priority high Priority low Priority

PortIn PortIn PortIn PortIn Uart3

IOIOI

PortOutData PortOutData RawData Measurement Samples Measurement Samples PortOutUpdate

slide-43
SLIDE 43

43

DataTrending

medium Priority medium Priority high Priority low Priority

PortIn PortIn PortIn PortIn Uart3

IOIOI

PortOutData PortOutData RawData Measurement Samples Measurement Samples PortOutUpdate

slide-44
SLIDE 44

44

RecyclerBuffer DataTrending

medium Priority medium Priority high Priority low Priority

PortIn PortIn PortIn PortIn Uart3

IOIOI

PortOutData PortOutData RawData Measurement Samples PortOutUpdate RecyclerBuffer

slide-45
SLIDE 45

RecyclerBuffer

  • Recycle-Aware programming (as less heap as possible)
  • Single producer – single consumer
  • Multiple producer – multiple consumer
  • Overflow?

45

slide-46
SLIDE 46

RecyclerBuffer: Twolock Queue

  • Simple, fast, and practical non-blocking and blocking concurrent

queue algorithms

  • by Maged M. Michael Michael L. Scott
  • http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf

E

next

Head Tail

46

slide-47
SLIDE 47

RecyclerBuffer

E

next

Head Tail Producer Consumer

E

next

Head Tail

dataQueue emptyQueue

47

200Hz 30Hz

slide-48
SLIDE 48

RecyclerBuffer - Overflow

E

next

Head Tail Producer Consumer

E

Tail

48

200Hz 30Hz … 5Hz?

slide-49
SLIDE 49

RecyclerBuffer - API

Producer Consumer

49

200Hz 30Hz

slide-50
SLIDE 50

Code Example: ProcessingAP (V2)

public void execute(int protocolIdentifier, SerializableIfc eventData) { switch (protocolIdentifier) { case ProtocolIdentifiers.RAW_DATA: processRawData((RawDataProtocol) eventData); break; default: break; } } private void processRawData(RawDataProtocol rawdata) { Entity<MeasurementSample> entity = recyclerBuffer.getEmptyElement(); entity.payload.samplingNumber = rawdata.getSamplingNumber(); entity.payload.flow.update(rawdata.getFlow()); entity.payload.pressureDiff.update(rawdata.getPressureDiff()); entity.payload.pressureChannel.update(rawdata.getPressureChannel()); … recyclerBuffer.commit(entity); } 50

slide-51
SLIDE 51

Code Example: ProcessingAP (V2)

public void execute(int protocolIdentifier, SerializableIfc eventData) { switch (protocolIdentifier) { case ProtocolIdentifiers.RAW_DATA: processRawData((RawDataProtocol) eventData); break; default: break; } } private void processRawData(RawDataProtocol rawdata) { Entity<MeasurementSample> entity = recyclerBuffer.getEmptyElement(); entity.payload.samplingNumber = rawdata.getSamplingNumber(); entity.payload.flow.update(rawdata.getFlow()); entity.payload.pressureDiff.update(rawdata.getPressureDiff()); entity.payload.pressureChannel.update(rawdata.getPressureChannel()); … recyclerBuffer.commit(entity); } 51

slide-52
SLIDE 52

52

slide-53
SLIDE 53

App Update- Server BSP Hardware

53

slide-54
SLIDE 54

Questions?

Android Industrial: Real-Time Data Visualization

Michael Guntli mguntli@imt.ch IMT AG, Switzerland