diff --git a/Software/ALL-H3-CC-V1.0A Headers.ods b/Software/ALL-H3-CC-V1.0A Headers.ods index 08d1445..e4cc7ce 100644 Binary files a/Software/ALL-H3-CC-V1.0A Headers.ods and b/Software/ALL-H3-CC-V1.0A Headers.ods differ diff --git a/Software/dashboard/Makefile b/Software/dashboard/Makefile index 43b6558..9839a58 100644 --- a/Software/dashboard/Makefile +++ b/Software/dashboard/Makefile @@ -4,7 +4,7 @@ TARGET_PATH := /home/$(TARGET_USER)/heartbeatmice/dashboard TARGET_PATH_STR := \/home\/$(TARGET_USER)\/heartbeatmice\/dashboard TARGET_PASS := 'a2nr' PROBE_USER := a2nr -PROBE_HOST := mekatronika +PROBE_HOST := 10.4.106.249 PROBE_PATH := /home/$(PROBE_USER)/ PROBE_PASS := 'Bismillah...' @@ -12,7 +12,8 @@ all: comp up run debug: comp_debug up run_debug init: install_dep install_flutter_pi up: copy_target -install: comp up install_app +install: clean comp up install_app +install_debug: comp_debug up install_app_debug uninstall: uninstall_app clean: @@ -25,12 +26,15 @@ copy_target: sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'mkdir -p $(TARGET_PATH)' \ && sshpass -p $(TARGET_PASS) rsync -a --info=progress2 ./build/flutter_assets $(TARGET_USER)@$(TARGET_HOST):$(TARGET_PATH) run: - sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S flutter-pi -r 270 --release $(TARGET_PATH)/flutter_assets' + sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S flutter-pi -r 90 --release $(TARGET_PATH)/flutter_assets' run_debug: sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S flutter-pi -o landscape_left $(TARGET_PATH)/flutter_assets' install_app: sshpass -p $(TARGET_PASS) rsync -a --info=progress2 ./heartbeatmice.service $(TARGET_USER)@$(TARGET_HOST):$(TARGET_PATH) \ && sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'sed -i -e "s/@thepath/$(TARGET_PATH_STR)/g" $(TARGET_PATH)/heartbeatmice.service && echo $(TARGET_PASS) | sudo -S cp $(TARGET_PATH)/heartbeatmice.service /lib/systemd/system/ && echo $(TARGET_PASS) | sudo -S systemctl enable heartbeatmice.service && echo $(TARGET_PASS) | sudo -S systemctl start heartbeatmice.service' +install_app_debug: + sshpass -p $(TARGET_PASS) rsync -a --info=progress2 ./heartbeatmiceDebug.service $(TARGET_USER)@$(TARGET_HOST):$(TARGET_PATH) \ + && sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'sed -i -e "s/@thepath/$(TARGET_PATH_STR)/g" $(TARGET_PATH)/heartbeatmiceDebug.service && echo $(TARGET_PASS) | sudo -S cp $(TARGET_PATH)/heartbeatmiceDebug.service /lib/systemd/system/ && echo $(TARGET_PASS) | sudo -S systemctl enable heartbeatmiceDebug.service && echo $(TARGET_PASS) | sudo -S systemctl start heartbeatmiceDebug.service' uninstall_app: sshpass -p $(TARGET_PASS) ssh -t $(TARGET_USER)@$(TARGET_HOST) 'echo $(TARGET_PASS) | sudo -S systemctl stop heartbeatmice.service && echo $(TARGET_PASS) | sudo -S systemctl disable heartbeatmice.service && echo $(TARGET_PASS) | sudo -S rm /lib/systemd/system/heartbeatmice.service' install_dep: diff --git a/Software/dashboard/ecg_sim.py b/Software/dashboard/ecg_sim.py new file mode 100644 index 0000000..9c992cf --- /dev/null +++ b/Software/dashboard/ecg_sim.py @@ -0,0 +1,6 @@ +import neurokit2 as nk # Load the package +simulated_ecg = nk.ecg_simulate(duration=8, sampling_rate=200, heart_rate=80) +signal, info = nk.ecg_process(simulated_ecg, sampling_rate=200) +nk.write_csv(signal, "./ecg_simulate_data.csv") +# nk.signal_plot(simulated_ecg, sampling_rate=200) # Visualize the signal + diff --git a/Software/dashboard/heartbeatmiceDebug.service b/Software/dashboard/heartbeatmiceDebug.service new file mode 100644 index 0000000..864e080 --- /dev/null +++ b/Software/dashboard/heartbeatmiceDebug.service @@ -0,0 +1,9 @@ +[Unit] +Description=Heartbeatmice dari UM Debug Version + +[Service] +Type=simple +ExecStart=flutter-pi -r 90 --release @thepath/flutter_assets + +[Install] +WantedBy=multi-user.target diff --git a/Software/dashboard/lib/hal/X9C10X.dart b/Software/dashboard/lib/hal/X9C10X.dart index 59a8bc3..a293c05 100644 --- a/Software/dashboard/lib/hal/X9C10X.dart +++ b/Software/dashboard/lib/hal/X9C10X.dart @@ -1,59 +1,65 @@ import 'package:dart_periphery/dart_periphery.dart'; import 'package:logging/logging.dart'; +import 'dart:io'; class X9c10x { - int ohm; - late GPIO inc; - late GPIO ud; - late GPIO? ss; - final log = Logger("X9C10X"); - late Function() onSelect; - late Function() onRelease; + final int _id; + final int _ohm; + final GPIO _inc; + final GPIO _ud; + final GPIO? _ss; + final _log = Logger("X9C10X"); + Function(int)? _onSelect; + Function(int)? _onRelease; X9c10x({ - required this.ohm, - required int gpioChip, - required int pinInc, - required int pinUd, - int? pinSs}){ - inc = GPIO(pinInc, GPIOdirection.gpioDirOutHigh, gpioChip); - ud = GPIO(pinUd, GPIOdirection.gpioDirOutHigh, gpioChip); - ss = pinSs != null ? GPIO(pinSs, GPIOdirection.gpioDirOutHigh, gpioChip) : null; - onSelect = selectChip; - onRelease = releaseChip; + required int id, + required int ohm, + required GPIO inc, + required GPIO ud, + GPIO? ss, + dynamic Function(int)? onSelect, + dynamic Function(int)? onRelease, + }) : _onRelease = onRelease, _onSelect = onSelect, _ss = ss, _ud = ud, _inc = inc, _ohm = ohm, _id = id; + + void _selectChip(){ + _onSelect?.call(_id); + _ss?.write(false); } - - void setCallBack(Function() onSelect, Function() onRelease){ - this.onSelect = onSelect; - this.onRelease = onRelease; + void _releaseChip(){ + _ss?.write(true); + _onRelease?.call(_id); } - void selectChip()=>ss?.write(false); - void releaseChip()=>ss?.write(true); + void _skip()=>sleep(const Duration(milliseconds: 3)); + void _storeSkip()=>sleep(const Duration(milliseconds: 20)); - void wipeUp(){ - onSelect.call(); - ud.write(true); - const Duration(microseconds: 3); - inc.write(false); - const Duration(microseconds: 1); - inc.write(true); - onRelease.call(); + Future wipeUp() async { + _selectChip(); + _ud.write(true); + _skip(); + _inc.write(false); + //while(true){} //TODO: DEAD CODE; + _skip(); + _inc.write(true); + _releaseChip(); + _storeSkip(); } - void wipeDown(){ - onSelect.call(); - ud.write(false); - const Duration(microseconds: 3); - inc.write(false); - const Duration(microseconds: 1); - inc.write(true); - onRelease.call(); + Future wipeDown() async { + _selectChip(); + _ud.write(false); + _skip(); + _inc.write(false); + _skip(); + _inc.write(true); + _releaseChip(); + _storeSkip(); } void dispose(){ - inc.dispose(); - ud.dispose(); - ss?.dispose(); + _inc.dispose(); + _ud.dispose(); + _ss?.dispose(); } } diff --git a/Software/dashboard/lib/hal/ads1256.dart b/Software/dashboard/lib/hal/ads1256.dart index f452855..0d39c27 100644 --- a/Software/dashboard/lib/hal/ads1256.dart +++ b/Software/dashboard/lib/hal/ads1256.dart @@ -133,7 +133,7 @@ class Ads1256 { skipClk(); bufferNCS = buffen; autoCalibrationNCS = true; - clockOutRateNCS = CLKOUT_1; + clockOutRateNCS = CLKOUT_OFF; programmableGainNCS = gain; dataRateNCS = drate; var st = statusNCS.toRadixString(16); @@ -168,16 +168,18 @@ class Ads1256 { } int get controlRegisterNCS => readRegister(RADD_ADCON); - set clockOutRateNCS(int clk) => writeRegister(RADD_ADCON, controlRegisterNCS | (clk << 5 )); - set programmableGainNCS(int gain) => writeRegister(RADD_ADCON, controlRegisterNCS | gain); + set clockOutRateNCS(int clk) => writeRegister(RADD_ADCON, (controlRegisterNCS & ~(0x03 << 5 )) & (clk << 5 )); + set programmableGainNCS(int gain) => writeRegister(RADD_ADCON, (controlRegisterNCS & ~(0x07)) & gain); int get dataRateNCS => readRegister(RADD_DRATE); set dataRateNCS(int rate) => writeRegister(RADD_DRATE, rate); set ioDir(List dir){ + log.info(" set ioDir <$dir>"); csOn(); int d = (dir[0] | dir[1]<<1 | dir[2]<<2 | dir[3]<<3) <<4; + log.info(" > <${d.toRadixString(16)}>"); writeRegister(RADD_IO, d); csOff(); } @@ -185,9 +187,11 @@ class Ads1256 { csOn(); int dio = readRegister(RADD_IO); csOff(); + log.info(" get ioDir <${dio.toRadixString(16)}>"); return dio.toListBoolbit(); } set dIO(List io){ + log.info(" set ioDir <$io -- ${io.toNibble()}>"); csOn(); writeRegister(RADD_IO, io.toNibble() ); csOff(); diff --git a/Software/dashboard/lib/hardware/heartbeatmice.dart b/Software/dashboard/lib/hardware/heartbeatmice.dart index dc22272..81e6e45 100644 --- a/Software/dashboard/lib/hardware/heartbeatmice.dart +++ b/Software/dashboard/lib/hardware/heartbeatmice.dart @@ -1,7 +1,7 @@ import 'package:dashboard/hal/X9C10X.dart'; import 'package:logging/logging.dart'; - -import '../hal/ads1256.dart'; +import 'package:dashboard/hal/ads1256.dart'; +import 'package:dart_periphery/dart_periphery.dart'; class HeartBeatMice { Ads1256 adc1 = Ads1256(tag: "adc1", @@ -20,49 +20,138 @@ class HeartBeatMice { pinCS: 21, isCSActiveHigh: false, /*pinReset: 20*/); - X9c10x pot = X9c10x(ohm: 104000, gpioChip: 1, pinUd: 204, pinInc: 205); + late List gain; + late List offset; Logger log = Logger("[HeartBeatMice]"); + + HeartBeatMice(){ + var inc = GPIO(205, GPIOdirection.gpioDirOutHigh, 1); + var ud = GPIO(204, GPIOdirection.gpioDirOutHigh, 1); + gain = List.generate(15, (i){ + return X9c10x( + id: i, + ohm: 104000, + inc:inc, + ud: ud, + onSelect: _selectGain, + onRelease: _releaseGain, + ); + }, growable: false); + offset = List.generate(15, (i){ + return X9c10x( + id: i, + ohm: 104000, + inc:inc, + ud: ud, + onSelect: _selectOffset, + onRelease: _releaseOffset, + ); + }, growable: false); + } - void potSelect(){ - - } - void potRelease(){ - - } void init(){ adc1.begin(Ads1256.DRATE_500SPS, Ads1256.GAIN_1, true); adc2.begin(Ads1256.DRATE_500SPS, Ads1256.GAIN_1, true); adc1.ioDir = [Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT]; adc2.ioDir = [Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT, Ads1256.IO_DIR_OUT]; + adc1.dIO = [false, false, false, false]; + adc2.dIO = [false, false, false, false]; } - int readAnalog(int no){ + + + Future readAnalog(int no) async { + //TODO: check kebenaran var adc = switch (no) { - 1 || 2 || 3 || 4 || 9 || 10 || 11 || 12 =>adc2, - 5 || 6 || 7 || 8 || 13 || 14 || 15 || 16 || _ =>adc1, + 1 || 2 || 3 || 4 || 9 || 10 || 11 || 12 =>adc2, + 5 || 6 || 7 || 8 || 13 || 14 || 15 || 16 || _ =>adc1, }; + //TODO: check kebenaran var ain = switch (no) { - 1 || 15=>Ads1256.MUXP_AIN0, - 2 || 14=>Ads1256.MUXP_AIN1, - 13=>Ads1256.MUXP_AIN2, - 8=>Ads1256.MUXP_AIN3, - 12=>Ads1256.MUXP_AIN4, - 4 || 6 || 11=>Ads1256.MUXP_AIN5, - 3 || 5 || 10=>Ads1256.MUXP_AIN6, - 7 || 9 || 16=>Ads1256.MUXP_AIN7, + 1 || 13=>Ads1256.MUXP_AIN0, + 2 || 14=>Ads1256.MUXP_AIN1, + 3 || 15=>Ads1256.MUXP_AIN2, + 4 || 8=>Ads1256.MUXP_AIN3, + 7 || 12=>Ads1256.MUXP_AIN4, + 6 || 11=>Ads1256.MUXP_AIN5, + 5 || 10=>Ads1256.MUXP_AIN6, + 9 || 16=>Ads1256.MUXP_AIN7, _=>Ads1256.MUXP_AINCOM }; log.info('readAnalog() <$no>'); log.info('> adc : <${adc.log.name}> | ain : <${ain.toRadixString(16)}> '); - var r = adc.analogRead(ain, Ads1256.MUXN_AINCOM); + var r = adc.analogRead(ain, Ads1256.MUXN_AINCOM).toVolt(); log.info('> $r'); return r; } + void _signalMux(int n, bool val) { + log.info('_signalMux() <$n> <$val>'); + int i = switch (n) { + 1 => 0, + 2 => 1, + _ => -1 + }; + log.info(' >mux : $i'); + if (i == -1){ + return; + } + List io = adc2.dIO; + log.info(' >current <$io>'); + io[i] = val; + io[i+2] = val; + adc2.dIO = io; + log.info(' >confirm <${adc2.dIO}>'); + } + void _channelMux(int val) { + log.info('_channelMux() <${val.toRadixString(16)}>'); + log.info(' >current <${adc1.dIO}>'); + adc1.dIO = val.toListBoolbit(); + log.info(' >confirm <${adc1.dIO}>'); + } + int _routeMux(an) => switch(an){ + 1 ||2 || 3|| 4|| 5|| 6|| 7|| 8 =>1, + 9 ||8 || 10|| 11|| 12|| 13|| 14|| 15 =>2, + _ => -1 + }; + void _selectOffset(int an){ + log.info('_selectOffset() <${an.toRadixString(16)}>'); + int n = _routeMux(an); + if (n == -1){ + return; + } + _channelMux((an*2)-1); // - 1 for offset + _signalMux(n, true); + } + void _releaseOffset(int an){ + log.info('_releaseGain() <${an.toRadixString(16)}>'); + int n = _routeMux(an); + _signalMux(n, false); + } + void _selectGain(int an){ + log.info('_selectGain() <${an.toRadixString(16)}>'); + int n = _routeMux(an); + if (n == -1){ + return; + } + _channelMux((an*2)-2); // - 2 for gain + _signalMux(n, true); + } + void _releaseGain(int an){ + log.info('_releaseGain() <${an.toRadixString(16)}>'); + int n = _routeMux(an); + _signalMux(n, false); + } + void dispose(){ adc1.dispose(); adc2.dispose(); - pot.dispose(); - } + for (var g in gain) { + g.dispose(); + } + for (var a in offset) { + a.dispose(); + } + } } diff --git a/Software/dashboard/lib/main.dart b/Software/dashboard/lib/main.dart index c0e37d6..a96132f 100644 --- a/Software/dashboard/lib/main.dart +++ b/Software/dashboard/lib/main.dart @@ -1,18 +1,19 @@ -import 'package:dashboard/hal/ads1256.dart'; +//import 'dart:nativewrappers/_internal/vm/lib/core_patch.dart'; + import 'package:dashboard/hardware/heartbeatmice.dart'; -//import 'package:flutter/cupertino.dart'; import 'ui/plot.dart'; import 'package:flutter/material.dart'; import 'util/mouse_cursor.dart'; import 'package:logging/logging.dart'; +import 'dart:core'; void main() { - Logger.root.level = Level.ALL; - Logger.root.onRecord.listen((record){ - + Logger.root.level = Level.ALL; + Logger.root.onRecord.listen((record){ + print('[${record.time.hour}:${record.time.minute}:${record.time.second}][${record.level.name}][${record.loggerName}] ${record.message}'); - }); + }); runApp(const MyApp()); } @@ -21,18 +22,18 @@ class MyApp extends StatelessWidget { // This widget is the root of your application. @override - Widget build(BuildContext context) { - return SoftwareMouseCursor( - child : MaterialApp( - title: 'Heart Beat Mice', - theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), - useMaterial3: true, - ), - home: const MyHomePage(title: 'Heart Beat Mice Coba'), - ) + Widget build(BuildContext context) { + return SoftwareMouseCursor( + child : MaterialApp( + title: 'Heart Beat Mice', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const MyHomePage(title: 'Heart Beat Mice Coba'), + ) ); - } + } } class MyHomePage extends StatefulWidget { @@ -41,7 +42,7 @@ class MyHomePage extends StatefulWidget { final String title; @override - State createState() => _MyHomePageState(); + State createState() => _MyHomePageState(); } class _MyHomePageState extends State { @@ -62,43 +63,143 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { + double height = 300/4; + double width = (MediaQuery.of(context).size.width-30)/4; return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), - body: ListView.builder( - itemCount: 10, - itemBuilder: (BuildContext context, int index){ - log.info("build ListView index : $index"); - return Center( - child: Column ( - children: [ - const SizedBox(height: 10,), - SizedBox ( - height: 100, - width: MediaQuery.of(context).size.width-100, - child : LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { - double height = constraints.maxHeight; - double width = constraints.maxWidth; - var i = index; - return Plot( - title: "analog $i", - aspectRatio: (height/width), - maxTimeSeconds: 10, - sampleTimeMillis: 2, - readAnalog: () async { - return await device.readAnalog(i).toVolt(); - }, - ); - }) - ), - const SizedBox(height: 10,), - ], - ) - ); - }) - ); + body: Row(children: [ + SizedBox( + width: width, + child: ListView.builder( + itemCount: 4, + itemBuilder: (context, i){ + var index = i+12; + return Column( + children: [ + Text("Analog $index"), + SizedBox ( + height: height.toDouble(), + width: width, + child : Plot( + title: "Analog $index", + aspectRatio: (height/ width), + minY: -5, + maxY: 5, + maxTimeSeconds: 0.5, + sampleTimeMicross: 1, + readAnalog: () async { return device.readAnalog(index); } + ), + ), + ], + ); + }, + )), + SizedBox( + width: width, + child: ListView.builder( + itemCount: 4, + itemBuilder: (context, i){ + var index = i+8; + return Column( + children: [ + Text("Analog $index"), + SizedBox ( + height: height.toDouble(), + width: width, + child : Plot( + title: "Analog $index", + aspectRatio: (height/ width), + minY: -5, + maxY: 5, + maxTimeSeconds: 0.5, + sampleTimeMicross: 1, + readAnalog: () async { return device.readAnalog(index); } + ), + ), + ], + ); + }, + )), + SizedBox( + width: width, + child: ListView.builder( + itemCount: 4, + itemBuilder: (context, i){ + var index = i+4; + return Column( + children: [ + Text("Analog $index"), + SizedBox ( + height: height.toDouble(), + width: width, + child : Plot( + title: "Analog $index", + aspectRatio: (height/ width), + minY: -5, + maxY: 5, + maxTimeSeconds: 0.5, + sampleTimeMicross: 1, + readAnalog: () async { return device.readAnalog(index); } + ), + ), + ], + ); + }, + )), + SizedBox( + width: width, + child: ListView.builder( + itemCount: 4, + itemBuilder: (context, i){ + var index = i; + return Column( + children: [ + Text("Analog $index"), + SizedBox ( + height: height.toDouble(), + width: width, + child : Plot( + title: "Analog $index", + aspectRatio: (height/ width), + minY: -5, + maxY: 5, + maxTimeSeconds: 0.5, + sampleTimeMicross: 1, + readAnalog: () async { return device.readAnalog(index); } + ), + ), + ], + ); + }, + )), + ]) + ); } } +// Column(children: [ +// Row(children: [ +// Row(children: [ +// IconButton( +// onPressed: () async {device.offset[index].wipeUp();} , +// icon: const Icon(Icons.arrow_drop_up_outlined)), +// const Text("Offset"), +// IconButton( +// onPressed: () async {device.offset[index].wipeDown();} , +// icon: const Icon(Icons.arrow_drop_down_outlined)) +// ]), +// Row(children: [ +// IconButton( +// onPressed: () async {device.gain[index].wipeUp();} , +// icon: const Icon(Icons.arrow_drop_up_outlined)), +// const Text("Gain"), +// IconButton( +// onPressed: () async {device.gain[index].wipeDown();} , +// icon: const Icon(Icons.arrow_drop_down_outlined)), +// ]), +// ],), +// ], +// ), diff --git a/Software/dashboard/lib/ui/plot.dart b/Software/dashboard/lib/ui/plot.dart index c6178d4..38b8688 100644 --- a/Software/dashboard/lib/ui/plot.dart +++ b/Software/dashboard/lib/ui/plot.dart @@ -14,22 +14,27 @@ class Plot extends StatefulWidget { required this.aspectRatio, required this.maxTimeSeconds, required this.readAnalog, - required this.sampleTimeMillis}); + required this.minY, + required this.maxY, + required this.sampleTimeMicross}); final String title; final double aspectRatio; - final int maxTimeSeconds; + final double maxTimeSeconds; final Future Function() readAnalog; - final int sampleTimeMillis; + final int sampleTimeMicross; + final double minY; + final double maxY; @override State createState() => _Plot(); } class _Plot extends State { late Timer timer; - late int limit= ((widget.maxTimeSeconds)/(widget.sampleTimeMillis/1000)).toInt(); + late int limit= ((widget.maxTimeSeconds)/(widget.sampleTimeMicross/1000)).toInt(); late List adc = []; int index = 0; double el = 0.0; + double valPrev = 0; late Logger log; @@ -44,7 +49,7 @@ class _Plot extends State { super.initState(); log = Logger("Plot : ${widget.title}"); log.info('limit : $limit'); - timer = Timer.periodic(Duration(milliseconds: widget.sampleTimeMillis), (timer) { + timer = Timer.periodic(Duration(microseconds: widget.sampleTimeMicross), (timer) { widget.readAnalog().then((val){ if (index>=limit) { log.info('================================================================ reset $index : $el : ${index != 0 ? adc[index-1] : 0}'); @@ -53,7 +58,7 @@ class _Plot extends State { adc.clear(); } setState(() { - el = (index * widget.sampleTimeMillis)/1000; + el = (index * widget.sampleTimeMicross)/1000; adc.add(FlSpot( el, val)); log.info('================================================================ $index : $el : ${adc[index]}'); index +=1; @@ -68,8 +73,10 @@ class _Plot extends State { aspectRatio: widget.aspectRatio, child : LineChart( LineChartData( - minY: -5, - maxY: 5, + minY: widget.minY, + maxY: widget.maxY, +// minY: -0.5, +// maxY: 0.5, minX: 0, maxX: widget.maxTimeSeconds.toDouble(), lineBarsData: [LineChartBarData( diff --git a/Software/dashboard/pubspec.lock b/Software/dashboard/pubspec.lock index 799b261..157b94c 100644 --- a/Software/dashboard/pubspec.lock +++ b/Software/dashboard/pubspec.lock @@ -119,18 +119,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -164,21 +164,21 @@ packages: source: hosted version: "0.12.16+1" material_color_utilities: - dependency: transitive + dependency: "direct main" description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" path: dependency: transitive description: @@ -252,10 +252,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.2" vector_math: dependency: transitive description: @@ -268,10 +268,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.5" sdks: dart: ">=3.4.3 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/Software/dashboard/pubspec.yaml b/Software/dashboard/pubspec.yaml index 829e2f7..2ef0574 100644 --- a/Software/dashboard/pubspec.yaml +++ b/Software/dashboard/pubspec.yaml @@ -33,6 +33,7 @@ dependencies: dart_periphery: ^0.9.6 logging: ^1.2.0 fl_chart: ^0.69.0 + material_color_utilities: ^0.12.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. diff --git a/Software/dashboard/pulseview_session_manual_debug_setup.pvs b/Software/dashboard/pulseview_session_manual_debug_setup.pvs new file mode 100644 index 0000000..a48efcf --- /dev/null +++ b/Software/dashboard/pulseview_session_manual_debug_setup.pvs @@ -0,0 +1,75 @@ +[General] +decode_signals=0 +meta_objs=0 +views=1 + +[D0] +color=4279638298 +conv_options=0 +conversion_type=0 +enabled=false +name=D0 + +[D1] +color=4287582722 +conv_options=0 +conversion_type=0 +enabled=false +name=D1 + +[D2] +color=4291559424 +conv_options=0 +conversion_type=0 +enabled=false +name=D2 + +[D3] +color=4294277376 +conv_options=0 +conversion_type=0 +enabled=false +name=D3 + +[D4] +color=4293776384 +conv_options=0 +conversion_type=0 +enabled=false +name=D4 + +[D5] +color=4285780502 +conv_options=0 +conversion_type=0 +enabled=false +name=D5 + +[D6] +color=4281623972 +conv_options=0 +conversion_type=0 +enabled=false +name=D6 + +[D7] +color=4285878395 +conv_options=0 +conversion_type=0 +enabled=true +name=DEBUG ME SENPAI + +[view0] +D0\trace_height=34 +D1\trace_height=34 +D2\trace_height=34 +D3\trace_height=34 +D4\trace_height=34 +D5\trace_height=34 +D6\trace_height=34 +D7\trace_height=34 +offset=22 serialization::archive 19 0 0 0 0 0 0 0 0 0 0 0 0 0 6 +scale=0.001 +segment_display_mode=1 +splitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\0\x9e\0\0\x5\x65\x1\0\0\0\x1\x1\0\0\0\x1\0) +v_offset=-127 diff --git a/Software/dashboard/test/labview/ecg_generator/Main.vi b/Software/dashboard/test/labview/ecg_generator/Main.vi new file mode 100644 index 0000000..67775f9 Binary files /dev/null and b/Software/dashboard/test/labview/ecg_generator/Main.vi differ diff --git a/Software/dashboard/test/labview/ecg_generator/Untitled Project 1.aliases b/Software/dashboard/test/labview/ecg_generator/Untitled Project 1.aliases new file mode 100644 index 0000000..eeb33ec --- /dev/null +++ b/Software/dashboard/test/labview/ecg_generator/Untitled Project 1.aliases @@ -0,0 +1,6 @@ +[Mobile-Robot-K4-001] +Mobile-Robot-K4-001 = "172.16.0.1" + +[My Computer] +My Computer = "192.168.100.247" + diff --git a/Software/dashboard/test/labview/ecg_generator/Untitled Project 1.lvproj b/Software/dashboard/test/labview/ecg_generator/Untitled Project 1.lvproj new file mode 100644 index 0000000..ab9a1eb --- /dev/null +++ b/Software/dashboard/test/labview/ecg_generator/Untitled Project 1.lvproj @@ -0,0 +1,174 @@ + + + false + + + + 100 + false + 10000 + 0 + 9 + true + false + true + true + false + 0 + My Computer/VI Server + My Computer/VI Server + true + true + false + + + + + + + + + + + Mobile-Robot-K4-001 + 172.16.0.1 + OS,Linux;CPU,ARM;DeviceCode,762F;TARGET_TYPE,RT;FPGAPersonality,myRIO_FP_Default; + 762F + ARMLinux + true + 5000 + 1000 + 8 + 8 + false + 300 + 80 + 60 + + 100 + false + 10000 + 0 + 0 + true + true + true + 8001 + /c/ni-rt/startup/startup.rtexe + true + +* + false + /c/ni-rt/startup + true + true + +* + false + true + 3363 + Main Application Instance/VI Server + Main Application Instance/VI Server + +* + true + true + false + false + /c/ni-rt/system/www/www.log + 80 + /c/ni-rt/system/www + c+* + 60 + +* + PqVr/ifkAQh+lVrdPIykXlFvg12GhhQFR8H9cUhphgg=:pTe9HRlQuMfJxAG6QCGq7UvoUpJzAzWGKy5SbZ+roSU= + 15 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + + + diff --git a/Software/dashboard/test/labview/ecg_generator/documentation/myRIO Project Documentation.html b/Software/dashboard/test/labview/ecg_generator/documentation/myRIO Project Documentation.html new file mode 100644 index 0000000..98ab8e4 --- /dev/null +++ b/Software/dashboard/test/labview/ecg_generator/documentation/myRIO Project Documentation.html @@ -0,0 +1,541 @@ + + + + +myRIO Project + + + + + + + +

myRIO Project

+ +

You can use the myRIO Project template as a starting point for creating myRIO applications with the myRIO default FPGA personality. With the myRIO Project template, you can easily access myRIO I/O channels and onboard devices without making major modifications to the structure of the application.

+ +

Table of Contents

+

System Requirements

+

Understanding the Components of This Template

+

Running This Template

+

Modifying This Template

+

Related Information

+ +
+ + +

System Requirements

+

Development System

+ +
    +
  • LabVIEW Full or Professional Development System
  • +
  • LabVIEW Real-Time Module
  • +
  • LabVIEW myRIO Toolkit
  • +
+ +

Hardware

+
    +
  • myRIO
  • +
+ + + +

Understanding the Components of This Template

+

This template uses a Flat Sequence structure that executes frames from left to right.

+ +

The Flat Sequence structure in this template executes the following frames from left to right:

+
    +
  1. Initialize—Initializes the myRIO, variables, and user interface elements, such as controls and indicators. Initializing code depends on your application needs.
  2. +
  3. Acquire and process data—Acquires data from the myRIO and processes the data for presentation. The While Loop repeats code until you click Stop or an error occurs.
  4. +
  5. Close—Closes user interface elements and variables, and resets the myRIO output values to zero before the application exits. Closing code is optional.
  6. +
+ + +

Running This Template

+
    +
  1. In the Project Explorer window, navigate to your myRIO target and open the Main VI.
  2. +
  3. Click Run. This application acquires acceleration data from the onboard accelerometer and displays changes to acceleration values in a waveform chart.
  4. +
  5. Rotate or shake the myRIO and observe the changes of the X, Y, and Z acceleration values.
  6. +
  7. Click Stop to stop the application.
  8. +
+ + +

Modifying This Template

+ +

The following table summarizes the design decisions you must make when modifying this template.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Design DecisionDesign ExampleDetailed Information
How do you want to control the order of execution in your application?You want data to flow as desired without using the Flat Sequence structure.Controlling the Order of Execution
What data does your application need to initialize?You want your application to open a file for logging.Adding Initialization Code
Which myRIO I/O channels does your application need to access?You want your application to control the DIO channels on the myRIO.Modifying the Data Acquisition and Processing Code
What executions does your application need to complete before exiting?You want your application to close references to make memory resources available.Adding Closing Code
How does your application handle errors?You want your application to report errors at the end of the execution flow.Modifying Error Handling
+ +

Controlling the Order of Execution

+

This template uses the Flat Sequence structure to control data flow. The data leaves each frame as the frame finishes executing. This template uses the Flat Sequence structure to demonstrate the purpose of the code in each frame.

+

Note  Do not overuse the Flat Sequence structure for controlling the execution order because the Flat Sequence structure prohibits parallel operations.

+

When you modify this template, you can remove the Flat Sequence structure and establish data dependency between nodes. For example, wiring the error in and error out clusters through nodes controls the data to flow from one node to another.

+ + +

Adding Initialization Code

+

This template initializes the error in cluster to specific values. You can add code to initialize your user interface and the myRIO. For example, you may want to initialize the data to specific values or to open a file for logging.

+ +

Modifying the Data Acquisition and Processing Code

+

This template uses the Accelerometer Express VI to read the acceleration values from the onboard accelerometer and uses a waveform chart to display the acceleration values.

+

You can add code to acquire data from the myRIO and process the data based on your application needs. The myRIO Toolkit provides Express VIs and Low Level VIs for you to access I/O channels and the onboard devices.

+ +

Adding Closing Code

+

This template uses the Reset VI to reset the onboard accelerometer. You must use the Reset VI after the completion of all operations with the myRIO I/O channels. Otherwise, the Reset VI might return unexpected results.

+

You can add code that executes after the data acquisition and processing completes but before the application exits. Closing code commonly accomplishes the following tasks:

+
    +
  • Frees memory by closing any open references
  • +
  • Flushes any buffers in use
  • +
  • Resets the myRIO
  • +
+ +

Modifying Error Handling

+

By default, if an error occurs in the Accelerometer Express VI, this template stops. If you do not want the error to stop your application, you can remove the OR function and wire the Stop control directly to the conditional terminal of the While Loop. The error in and error out clusters pass error information from the beginning of the VI to the end and report the error at the end of the execution flow.

+ + + +

Related Information

+

Refer to the LabVIEW Help, available by selecting Help»LabVIEW Help from LabVIEW, for information about LabVIEW concepts or objects used in this sample project. You also can use the Context Help window to learn basic information about LabVIEW objects as you move the cursor over each object. To display the Context Help window in LabVIEW, select Help»Show Context Help.

+

Refer to the myRIO sample projects, available from the Create Project dialog box, for examples of adapting this template to more complex applications.

+ +
+

Legal Information

+ +

Copyright

+

© 2013–2015 National Instruments. All rights reserved.

+ +

Under the copyright laws, this publication may not be reproduced or transmitted in any form, electronic or mechanical, including photocopying, recording, storing in an information retrieval system, or translating, in whole or in part, without the prior written consent of National Instruments Corporation.

+ +

National Instruments respects the intellectual property of others, and we ask our users to do the same. NI software is protected by copyright and other intellectual property laws. Where NI software may be used to reproduce software or other materials belonging to others, you may use NI software only to reproduce materials that you may reproduce in accordance with the terms of any applicable license or other legal restriction.

+ +

End-User License Agreements and Third-Party Legal Notices

+

You can find end-user license agreements (EULAs) and third-party legal notices in the following locations after installation:

+
    +
  • Notices are located in the <National Instruments>\_Legal Information and <National Instruments> directories.
  • +
  • EULAs are located in the <National Instruments>\Shared\MDF\Legal\license directory.
  • +
  • Review <National Instruments>\_Legal Information.txt for information on including legal information in installers built with NI products.
  • +
+

U.S. Government Restricted Rights

+

If you are an agency, department, or other entity of the United States Government ("Government"), the use, duplication, reproduction, release, modification, disclosure or transfer of the technical data included in this manual is governed by the Restricted Rights provisions under Federal Acquisition Regulation 52.227-14 for civilian agencies and Defense Federal Acquisition Regulation Supplement Section 252.227-7014 and 252.227-7015 for military agencies.

+ +

IVI Foundation Copyright Notice

+ +

Content from the IVI specifications reproduced with permission from the IVI Foundation.

+ +

The IVI Foundation and its member companies make no warranty of any kind with regard to this material, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The IVI Foundation and its member companies shall not be liable for errors contained herein or for incidental or consequential damages in connection with the furnishing, performance, or use of this material.

+ + + +

Trademarks

+ + +

Refer to the NI Trademarks and Logo Guidelines at ni.com/trademarks for information on National Instruments trademarks. Other product and company names mentioned herein are trademarks or trade names of their respective companies.

+ + + +

Patents

+

For patents covering the National Instruments products/technology, refer to the appropriate location: Help»Patents in your software, the patents.txt file on your media, or the National Instruments Patent Notice at ni.com/patents.

+ + + + \ No newline at end of file diff --git a/Software/dashboard/test/labview/ecg_generator/documentation/myRIO_Project_Diagram.gif b/Software/dashboard/test/labview/ecg_generator/documentation/myRIO_Project_Diagram.gif new file mode 100644 index 0000000..9e25779 Binary files /dev/null and b/Software/dashboard/test/labview/ecg_generator/documentation/myRIO_Project_Diagram.gif differ