diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..17578fd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+__pycache__
+.vscode
+mainwindow.py
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e44208e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# Libelium Calibration App
+
+## Run
+```bash
+pyuic5 app/gui/mainwindow.ui -o app/gui/mainwindow.py
+python3 app/libelium-calibration.py
+```
\ No newline at end of file
diff --git a/app/boards.py b/app/boards.py
new file mode 100644
index 0000000..874b960
--- /dev/null
+++ b/app/boards.py
@@ -0,0 +1,183 @@
+import typing as tp
+
+from sensors import (
+ ClSensor,
+ ConductivitySensor,
+ NH4Sensor,
+ NO2Sensor,
+ NO3Sensor,
+ ORPSensor,
+ OxxygenSensor,
+ TemperatureSensor,
+ pHSensor,
+ TurbiditySensor,
+)
+from parsers import BoardData, ParserStrategy
+from logger import get_logger
+
+
+_LOGGER = get_logger(__name__)
+
+
+class BoardStatus:
+ Connected: str = "подключено"
+ Disconnected: str = "не подключено"
+ Connection: str = "подключение..."
+
+
+class Board:
+ def __init__(self, sensors):
+ self._message_id: str = ""
+ self._sensor_objects = sensors
+ self._board_data = BoardData()
+ self._parser_strategy = None
+ self._connected_sockets: tp.Dict[str, int] = {}
+ self._sensors = {}
+ self._sockets = {}
+ for sensor in self._sensor_objects:
+ self._sensors[sensor.get_name()] = sensor
+
+ def set_signals(
+ self,
+ data_update,
+ coeffs_update,
+ battery_update,
+ info_update,
+ calibration_progress,
+ restart
+ ) -> None:
+ self._parser_strategy = ParserStrategy(
+ data_update,
+ coeffs_update,
+ battery_update,
+ info_update,
+ calibration_progress,
+ restart,
+ )
+
+ def parser(self, data: str) -> bool:
+ return self._parser_strategy.get_parser(data, self._message_id).parse(
+ self._board_data
+ )
+
+ def update_connected_sockets(self, connected_sockets: tp.Dict):
+ self._connected_sockets = connected_sockets
+
+ def get_sensors_data(self) -> tp.Dict:
+ sensors_data = {}
+ for sensor_name in self._connected_sockets:
+ sensors_data[sensor_name] = self._board_data.sensors_data[
+ self._connected_sockets[sensor_name]
+ ]
+ return sensors_data
+
+ def get_calibration_coeffs(self, sensor_name: str) -> tp.Dict:
+ return self._board_data.calibration_coeffs[self._connected_sockets[sensor_name]]
+
+ def get_board_info(self) -> tp.Dict:
+ return self._board_data.board_info
+
+ def check_message_id(self, data: str) -> bool:
+ return data.startswith(f"${self._message_id}")
+
+ def get_show_coeff_command(self) -> (bytes, tp.Optional[str]):
+ return b"z", "#z"
+
+ def get_board_info_command(self) -> (bytes, tp.Optional[str]):
+ return b"f", "#f"
+
+ def get_set_counter_command(self, duration: int) -> (bytes, tp.Optional[str]):
+ return f"t{duration}".encode(), "#t"
+
+ def get_sensor_names(self):
+ return [sensor.get_name() for sensor in self._sensor_objects]
+
+ def get_sensor_units(self, sensor_name: str) -> str:
+ return self._sensors[sensor_name].get_units()
+
+ def get_sensor_calibration_solutions(self, sensor_name: str) -> tp.List[str]:
+ return self._sensors[sensor_name].get_calibration_solutions()
+
+ def get_calibration_command(
+ self, sensor_name: str = None
+ ) -> (bytes, tp.Optional[str]):
+ pass
+
+ def get_socket_sensors(self, socket: int) -> tp.List[str]:
+ return self._sockets[socket]
+
+ def get_battery_level(self) -> int:
+ return self._board_data.battery_level
+
+
+class SWBoard(Board):
+ def __init__(self):
+ super().__init__(
+ [
+ TemperatureSensor(),
+ pHSensor(),
+ ConductivitySensor(),
+ OxxygenSensor(),
+ ORPSensor(),
+ TurbiditySensor(),
+ ]
+ )
+ self._message_id = "w"
+ self._sockets = {
+ 1: ["Датчик рН"],
+ 2: ["Датчик кислорода"],
+ 3: ["Датчик проводимости"],
+ 4: ["Датчик температуры"],
+ 5: ["Датчик ОВП"],
+ 6: ["Датчик мутности"],
+ }
+
+ def get_calibration_command(
+ self, calibration_solution: str, sensor_name: str = None
+ ) -> (bytes, tp.Optional[str]):
+ return (
+ self._sensors[sensor_name].get_calibration_command(calibration_solution),
+ "#?",
+ )
+
+
+class SWIonsBoard(Board):
+ def __init__(self):
+ super().__init__(
+ [
+ NO2Sensor(),
+ NO3Sensor(),
+ NH4Sensor(),
+ ClSensor(),
+ TemperatureSensor(),
+ ]
+ )
+ self._message_id = "i"
+ self._socket_calibration_commands = {
+ 1: ["a", "b", "c"],
+ 2: ["k", "l", "m"],
+ 3: ["n", "o", "p"],
+ 4: ["q", "r", "s"],
+ }
+ self._sockets = {
+ 1: ["Датчик NH4", "Датчик NO3", "Датчик NO2", "Датчик Cl"],
+ 2: ["Датчик NO3", "Датчик NO2", "Датчик NH4", "Датчик Cl"],
+ 3: ["Датчик NO2", "Датчик NO3", "Датчик NH4", "Датчик Cl"],
+ 4: ["Датчик Cl", "Датчик NO3", "Датчик NH4", "Датчик NO2"],
+ 5: [],
+ 6: ["Датчик температуры"],
+ }
+
+ def get_calibration_command(
+ self, calibration_solution: str, sensor_name: str = None
+ ) -> (bytes, tp.Optional[str]):
+ consentration, solution_number = self._sensors[sensor_name].get_consentration(
+ calibration_solution
+ )
+ socket_command = self._socket_calibration_commands[
+ self._connected_sockets[sensor_name]
+ ][solution_number]
+ return f"{socket_command}{consentration}".encode(), "#?"
+
+ def get_multiions_calibration_command(self, sensors_on_sockets) -> str:
+ pass
diff --git a/app/gui/mainwindow.ui b/app/gui/mainwindow.ui
new file mode 100644
index 0000000..63f937d
--- /dev/null
+++ b/app/gui/mainwindow.ui
@@ -0,0 +1,873 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 521
+ 631
+
+
+
+ SmartWaterGUI
+
+
+ false
+
+
+
+
+
+ 10
+ 60
+ 501
+ 521
+
+
+
+ 0
+
+
+
+ Текущие измерения
+
+
+
+
+ 10
+ 50
+ 421
+ 403
+
+
+
+
+ 0
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
-
+
+
+ Гнездо 1
+
+
+ true
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
-
+
+ Датчик температуры
+
+
+
+
+ -
+
+
+
+ 130
+ 30
+
+
+
+
+ -
+
+
+
+ 50
+ 16777215
+
+
+
+ ℃
+
+
+
+
+
+
+
+ -
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+ Гнездо 2
+
+
+ true
+
+
+
+ -
+
+
+ 10
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
-
+
+ Датчик рН
+
+
+
+
+ -
+
+
+
+ 130
+ 30
+
+
+
+
+ -
+
+
+
+ 50
+ 16777215
+
+
+
+ ед. рН
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Гнездо 3
+
+
+ true
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
-
+
+ Датчик проводимости
+
+
+
+
+ -
+
+
+
+ 130
+ 30
+
+
+
+
+ -
+
+
+
+ 50
+ 16777215
+
+
+
+ мкСм
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Гнездо 4
+
+
+ true
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
-
+
+ Датчик кислорода
+
+
+
+
+ -
+
+
+
+ 130
+ 30
+
+
+
+
+ -
+
+
+
+ 50
+ 16777215
+
+
+
+ %
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Гнездо 5
+
+
+ true
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
-
+
+ Датчик ОВП
+
+
+
+
+ -
+
+
+
+ 130
+ 30
+
+
+
+
+ -
+
+
+
+ 50
+ 16777215
+
+
+
+ мВ
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Гнездо 6
+
+
+ false
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
-
+
+ Датчик мутности
+
+
+
+
+ -
+
+
+
+ 130
+ 30
+
+
+
+
+ -
+
+
+
+ 50
+ 16777215
+
+
+
+ NTU
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+ 10
+ 111
+ 31
+
+
+
+ Smart Water
+
+
+ true
+
+
+
+
+
+ 140
+ 10
+ 141
+ 31
+
+
+
+ Smart Water Ions
+
+
+
+
+
+ Калибровка
+
+
+
+
+ 270
+ 10
+ 211
+ 31
+
+
+
+
+
+
+ 10
+ 16
+ 71
+ 21
+
+
+
+ Датчик
+
+
+
+
+
+ 10
+ 50
+ 181
+ 31
+
+
+
+ Калибровочный раствор
+
+
+
+
+
+ 270
+ 50
+ 211
+ 31
+
+
+
+
+
+
+ 150
+ 140
+ 211
+ 41
+
+
+
+ Начать калибровку
+
+
+
+
+
+ 10
+ 90
+ 181
+ 31
+
+
+
+ Время стабилизации
+
+
+
+
+
+ 270
+ 90
+ 211
+ 31
+
+
+ -
+
+ 1 минута
+
+
+ -
+
+ 2 минуты
+
+
+ -
+
+ 3 минуты
+
+
+ -
+
+ 4 минуты
+
+
+ -
+
+ 5 минут
+
+
+
+
+
+
+ 10
+ 440
+ 471
+ 31
+
+
+
+ 24
+
+
+
+
+
+ 10
+ 260
+ 161
+ 151
+
+
+
+
+
+
+ 10
+ 210
+ 151
+ 21
+
+
+
+ Калибровочные
+
+
+
+
+
+ 10
+ 230
+ 151
+ 21
+
+
+
+ значения:
+
+
+
+
+
+ 179
+ 209
+ 301
+ 221
+
+
+
+
+
+
+ Информация об устройстве
+
+
+
+
+ 10
+ 10
+ 221
+ 21
+
+
+
+
+ 75
+ true
+
+
+
+ Информация об устройстве
+
+
+
+
+
+ 10
+ 50
+ 481
+ 171
+
+
+
+ -
+
+
-
+
+
+
+ 180
+ 16777215
+
+
+
+ Имя устройства:
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 180
+ 16777215
+
+
+
+ Serial ID:
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 180
+ 16777215
+
+
+
+ Прошивка:
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 180
+ 16777215
+
+
+
+ Версия прошивки:
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 180
+ 16777215
+
+
+
+ md5 hash:
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+ 20
+ 81
+ 31
+
+
+
+ USB Порт
+
+
+
+
+
+ 90
+ 20
+ 211
+ 31
+
+
+
+
+
+
+ 340
+ 574
+ 171
+ 31
+
+
+
+
+ 9
+
+
+
+ SmartWaterGUI версия ПО 2.0
+
+
+
+
+
+ 410
+ 20
+ 51
+ 31
+
+
+
+ Заряд:
+
+
+
+
+
+ 460
+ 20
+ 31
+ 31
+
+
+
+ Qt::LeftToRight
+
+
+ ...
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 490
+ 20
+ 21
+ 31
+
+
+
+ %
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 10
+ 580
+ 61
+ 21
+
+
+
+ Статус:
+
+
+
+
+
+ 70
+ 580
+ 121
+ 21
+
+
+
+ не подключено
+
+
+
+
+
+
+
+ PlotWidget
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/app/libelium-calibration.py b/app/libelium-calibration.py
new file mode 100644
index 0000000..b8d3655
--- /dev/null
+++ b/app/libelium-calibration.py
@@ -0,0 +1,292 @@
+import sys
+import typing as tp
+
+from PyQt5 import QtGui, QtWidgets
+import pyqtgraph as pg
+
+from boards import SWBoard, SWIonsBoard, BoardStatus
+from sensors_const import MULTIIONS_SOLUTIONS, SW_BOARD_TYPE, SWIONS_BOARD_TYPE
+from workers import BoardSerial, PortDetectThread
+from logger import get_logger
+from gui.mainwindow import Ui_MainWindow
+
+
+_LOGGER = get_logger(__name__)
+
+
+class Calibration:
+ def __init__(self, main_window: QtWidgets.QMainWindow):
+ self.main_window = main_window
+ self.button = main_window.pushButtonStartCalibration
+ self.progress_bar = main_window.progressBarCalibration
+ self.graphics_view = main_window.graphicsViewCalibration
+ self.board_serial = main_window.board_serial
+ self.duration: int = (
+ int(main_window.boxStabilisationTime.currentText().split()[0]) * 10 * 2
+ )
+ self.progress_bar.setMinimum(0)
+ self.progress_bar.setMaximum(self.duration)
+ self.board_serial.calibrationProgressUpdate.connect(
+ self._progress_update
+ )
+ self.board_serial.restartSignal.connect(self._start_calibration)
+ self._start_calibration()
+ self.button.setEnabled(False)
+
+ def _start_calibration(self):
+ sensor_name = self.main_window.boxSensors.currentText()
+ solution = self.main_window.boxCalibrationSolution.currentText()
+ self._setup_graphics()
+ self.board_serial.start_calibration(sensor_name, solution, self.duration)
+
+ def _setup_graphics(self):
+ self.graphics_view.clear()
+ self.pen = pg.mkPen(color=(255, 0, 0), width=3)
+ self.graphics_view.setXRange(0, self.duration)
+ self.line = None
+ self.steps = []
+ self.values = []
+
+ def _progress_update(self, data):
+ _LOGGER.debug(f"Progress update: {data['step']}")
+ self.progress_bar.setValue(data["step"] + 1)
+ self._draw_graphics(data)
+ if data["step"] == (self.duration - 1):
+ self._finish_calibration()
+
+ def _finish_calibration(self):
+ self.button.setEnabled(True)
+ self.board_serial.calibrationProgressUpdate.disconnect()
+ self.board_serial.restartSignal.disconnect()
+
+ def _draw_graphics(self, data):
+ self.steps.append(data["step"])
+ self.values.append(data["value"])
+ if self.line is None:
+ self.line = self.graphics_view.plot(self.steps, self.values, pen=self.pen, symbol="o", symbolSize=5, symbolBrush="r")
+ else:
+ self.line.setData(self.steps, self.values)
+
+
+class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
+ def __init__(self, parent=None, app=None):
+ super(MainWindow, self).__init__(parent)
+ self.setupUi(self)
+ self.board_serial = None
+ self.board_status = BoardStatus.Disconnected
+ self.current_board_type: str = SW_BOARD_TYPE
+ self.boards = {SW_BOARD_TYPE: SWBoard(), SWIONS_BOARD_TYPE: SWIonsBoard()}
+ self.current_board: str = self.boards[SW_BOARD_TYPE]
+ self.current_sensor_calibration: str = ""
+ self.port_detect: PortDetectThread = PortDetectThread()
+ self.port_detect.portsUpdate.connect(self.populate_boards)
+ self.port_detect.start()
+ self.boxUSBPorts.currentTextChanged.connect(self.choose_port)
+ self.boxSensors.currentTextChanged.connect(self.choose_sensor_calibration)
+ self.radioButtonSW.toggled.connect(self.sw_swions_switched)
+ self.pushButtonStartCalibration.clicked.connect(self.handle_calibration_button)
+ self.progressBarCalibration.setValue(0)
+ self.sensors_gui: list = [
+ (
+ self.comboBoxSensor_1,
+ self.checkBoxSensor_1,
+ self.dataMeasSensor_1,
+ self.labelUnitsSensor_1,
+ ),
+ (
+ self.comboBoxSensor_2,
+ self.checkBoxSensor_2,
+ self.dataMeasSensor_2,
+ self.labelUnitsSensor_2,
+ ),
+ (
+ self.comboBoxSensor_3,
+ self.checkBoxSensor_3,
+ self.dataMeasSensor_3,
+ self.labelUnitsSensor_3,
+ ),
+ (
+ self.comboBoxSensor_4,
+ self.checkBoxSensor_4,
+ self.dataMeasSensor_4,
+ self.labelUnitsSensor_4,
+ ),
+ (
+ self.comboBoxSensor_5,
+ self.checkBoxSensor_5,
+ self.dataMeasSensor_5,
+ self.labelUnitsSensor_5,
+ ),
+ (
+ self.comboBoxSensor_6,
+ self.checkBoxSensor_6,
+ self.dataMeasSensor_6,
+ self.labelUnitsSensor_6,
+ ),
+ ]
+ self.change_sensor_board(self.current_board_type)
+ for sensor in self.sensors_gui:
+ sensor[1].stateChanged.connect(self.sensor_enabled_changed)
+ sensor[0].currentTextChanged.connect(self.sensors_sockets_changed)
+ self._update_connected_sockets()
+ self.sensors_enabled: tp.List[str] = []
+ self.populate_sensors_on_calibration()
+ self._setup_graphic()
+ self.show()
+
+ def _setup_graphic(self):
+ self.graphicsViewCalibration.setBackground("w")
+ self.graphicsViewCalibration.showGrid(x=True, y=True)
+
+ def handle_calibration_button(self):
+ if self.board_status == BoardStatus.Connected:
+ self.calibration = Calibration(self)
+
+ def sensors_sockets_changed(self, data):
+ self._update_connected_sockets()
+
+ def _update_connected_sockets(self):
+ i = 1
+ connected_sockets = {}
+ for sensor in self.sensors_gui:
+ connected_sockets[sensor[0].currentText()] = i
+ i += 1
+ self.current_board.update_connected_sockets(connected_sockets)
+
+ def populate_sensors_on_calibration(self):
+ self.sensors_enabled = []
+ for checkbox in self.sensors_gui:
+ if checkbox[1].checkState() and checkbox[0].currentText() != "":
+ self.sensors_enabled.append(checkbox[0].currentText())
+ self.boxSensors.clear()
+ self.boxSensors.addItems(self.sensors_enabled)
+ if self.board_status == BoardStatus.Connected:
+ self._update_sensors_meas()
+ if self.radioButtonSWIons.isChecked():
+ self.boxSensors.addItem("Multi Ions (NO3, NH4, Cl)")
+
+ def choose_sensor_calibration(self, sensor: str):
+ self.current_sensor_calibration = sensor
+ self.boxCalibrationSolution.clear()
+ if sensor in self.current_board.get_sensor_names():
+ self.boxCalibrationSolution.addItems(
+ self.current_board.get_sensor_calibration_solutions(sensor)
+ )
+ else:
+ self.boxCalibrationSolution.addItems(MULTIIONS_SOLUTIONS)
+ if self.board_status == BoardStatus.Connected:
+ self._update_calibration_coeffs()
+
+ def sw_swions_switched(self):
+ _LOGGER.debug(
+ f"SW: {self.radioButtonSW.isChecked()}, SW Ions: {self.radioButtonSWIons.isChecked()}"
+ )
+ self.change_sensor_board(
+ SW_BOARD_TYPE if self.radioButtonSW.isChecked() else SWIONS_BOARD_TYPE
+ )
+ self.populate_sensors_on_calibration()
+
+ def set_sensors_units(self):
+ for sensor in self.sensors_gui:
+ sensor_name = sensor[0].currentText()
+ if sensor_name != "":
+ sensor[3].setText(self.current_board.get_sensor_units(sensor_name))
+ else:
+ sensor[3].setText("")
+
+ def change_sensor_board(self, board_type: str):
+ self.current_board_type = board_type
+ self.current_board = self.boards[board_type]
+ socket_number = 1
+ for socket in self.sensors_gui:
+ socket[0].clear()
+ socket[0].addItems(self.current_board.get_socket_sensors(socket_number))
+ if self.current_board.get_socket_sensors(socket_number) == []:
+ socket[1].setEnabled(False)
+ else:
+ socket[1].setEnabled(True)
+ socket_number += 1
+ self.set_sensors_units()
+
+ def sensor_enabled_changed(self, state: int):
+ _LOGGER.debug(f"Checkbox state changed: {state}")
+ self.populate_sensors_on_calibration()
+
+ def _update_sensors_meas(self) -> None:
+ sensors_data = self.current_board.get_sensors_data()
+ for sensor in self.sensors_gui:
+ if sensor[1].checkState():
+ sensor[2].setText(str(sensors_data.get(sensor[0].currentText(), "")))
+ sensor[2].setEnabled(True)
+ else:
+ sensor[2].setEnabled(False)
+ sensor[2].setText("")
+
+ def _update_battery(self) -> None:
+ battery_data = self.current_board.get_battery_level()
+ self.dataBattery.setText(str(battery_data))
+
+ def _update_board_info(self) -> None:
+ board_info = self.current_board.get_board_info()
+ self.dataDeviceName.setText(board_info["name"])
+ self.dataSerialID.setText(board_info["serial_id"])
+ self.dataFirmware.setText(board_info["firmware"])
+ self.dataFirmwareVersion.setText(board_info["firmware_version"])
+ self.datamd5.setText(board_info["md5_hash"])
+
+ def _update_calibration_coeffs(self) -> None:
+ current_sensor = self.boxSensors.currentText()
+ text = f"Раствор - значение\n"
+ if current_sensor == "":
+ self.textCalibrationValues.setText(text)
+ return
+ calibration_coeffs = self.current_board.get_calibration_coeffs(current_sensor)
+ for value in calibration_coeffs:
+ text += f"{value} - {calibration_coeffs[value]}\n"
+ self.textCalibrationValues.setText(text)
+
+ def _update_board_status(self, board_status: str):
+ self.board_status = board_status
+ self.dataStatus.setText(board_status)
+
+ def populate_boards(self, ports: tp.List[str]):
+ self.boxUSBPorts.clear()
+ if self.boxUSBPorts.currentText() == "" and len(ports) > 0:
+ self.boxUSBPorts.setCurrentIndex(0)
+ if len(ports) > 0:
+ self.boxUSBPorts.addItems([p.name for p in ports])
+ else:
+ sep = QtGui.QStandardItem("Платы не найдены")
+ sep.setEnabled(False)
+ self.boxUSBPorts.model().appendRow(sep)
+
+ def chose_curent_board(self, board_type: str):
+ self.current_board = self.boards[board_type]
+ if board_type == SW_BOARD_TYPE and not self.radioButtonSW.isChecked():
+ self.radioButtonSW.toggle()
+ elif board_type == SWIONS_BOARD_TYPE and not self.radioButtonSWIons.isChecked():
+ self.radioButtonSWIons.toggle()
+ self.radioButtonSW.setEnabled(False)
+ self.radioButtonSWIons.setEnabled(False)
+
+ def choose_port(self, port):
+ _LOGGER.debug(f"New port chosen: {port}")
+ if port != "Платы не найдены" and port != "":
+ if self.board_serial is not None:
+ self.board_serial.close_connection()
+ self.board_serial = BoardSerial(port, self.boards)
+ self.board_serial.dataUpdate.connect(self._update_sensors_meas)
+ self.board_serial.batteryUpdate.connect(self._update_battery)
+ self.board_serial.infoUpdate.connect(self._update_board_info)
+ self.board_serial.currentBoardUpdate.connect(self.chose_curent_board)
+ self.board_serial.coeffsUpdate.connect(self._update_calibration_coeffs)
+ self.board_serial.boardStatusUpdate.connect(self._update_board_status)
+ self.board_serial.start()
+ else:
+ self.radioButtonSW.setEnabled(True)
+ self.radioButtonSWIons.setEnabled(True)
+
+
+app = QtWidgets.QApplication(sys.argv)
+window = MainWindow()
+app.exec_()
diff --git a/app/logger.py b/app/logger.py
new file mode 100644
index 0000000..f3cd693
--- /dev/null
+++ b/app/logger.py
@@ -0,0 +1,11 @@
+import logging
+import sys
+
+def get_logger(name: str):
+ logger = logging.getLogger(name)
+ logger.setLevel(logging.DEBUG)
+ handler = logging.StreamHandler(stream=sys.stdout)
+ formatter = logging.Formatter("%(name)s %(asctime)s %(levelname)s %(message)s")
+ handler.setFormatter(formatter)
+ logger.addHandler(handler)
+ return logger
\ No newline at end of file
diff --git a/app/parsers.py b/app/parsers.py
new file mode 100644
index 0000000..90d4f04
--- /dev/null
+++ b/app/parsers.py
@@ -0,0 +1,197 @@
+import typing as tp
+from logger import get_logger
+
+_LOGGER = get_logger(__name__)
+
+class BoardData:
+ def __init__(self):
+ self.sensors_data: tp.Dict[int, tp.Optional[float]] = {
+ 1: None,
+ 2: None,
+ 3: None,
+ 4: None,
+ 5: None,
+ 6: None,
+ }
+ self.board_info: tp.Dict[str, str] = {
+ "name": None,
+ "serial_id": None,
+ "firmware": None,
+ "firmware_version": None,
+ "md5_hash": None,
+ }
+ self.battery_level: int = 0
+ self.calibration_coeffs: tp.Dict[int, tp.Dict] = {
+ 1: {},
+ 2: {},
+ 3: {},
+ 4: {},
+ 5: {},
+ 6: {},
+ }
+
+class Parser:
+ def __init__(self, data: str, signals: tp.List = None):
+ self.signals = signals
+ self.data = data
+
+ def emit_signals(func: tp.Callable):
+ def wrapper(self, *args, **kwargs):
+ resp = func(self, *args, **kwargs)
+ for signal in self.signals:
+ signal.emit()
+ return resp
+ return wrapper
+
+ @emit_signals
+ def parse(self, board_data: BoardData) -> bool:
+ return True
+
+class ParserStrategy:
+ def __init__(
+ self,
+ data_update,
+ coeffs_update,
+ battery_update,
+ info_update,
+ calibration_progress,
+ restart,
+ ):
+ self._data_update_signal = data_update
+ self._coeffs_update_signal = coeffs_update
+ self._battery_update_signal = battery_update
+ self._info_update_signal = info_update
+ self._calibration_progress_signal = calibration_progress
+ self._restart_signal = restart
+ self._measure_signal = "$measure"
+ self._coeffs_prefix = "#z"
+ self._info_prefix = "#f"
+ self._calibration_prefix = "^|"
+ self._restart_prefix = "J#"
+
+ def get_parser(self, data: str, message_id: str) -> Parser:
+ _LOGGER.debug(f"Parser strategy get {data}")
+ if self._restart_prefix in data:
+ _LOGGER.debug("Restart parser")
+ return RestartParser(data, [self._restart_signal])
+ elif data.startswith(self._coeffs_prefix):
+ if message_id == "w":
+ return SWCoeffParser(data, [self._coeffs_update_signal])
+ elif message_id == "i":
+ return SWIonsCoeffParser(data, [self._coeffs_update_signal])
+ elif data.startswith(self._info_prefix):
+ return BoardInfoParser(data, [self._info_update_signal])
+ elif data.startswith(f"${message_id}"):
+ if message_id == "w":
+ return SWDataParser(data, [self._data_update_signal, self._battery_update_signal])
+ elif message_id == "i":
+ return SWIonsDataParser(data, [self._data_update_signal, self._battery_update_signal])
+ elif data.startswith(self._calibration_prefix):
+ return CalibrationParser(data, [self._calibration_progress_signal])
+ elif self._measure_signal in data:
+ return StartMeasureParser(data)
+ else:
+ return TrueParser(data)
+
+class RestartParser(Parser):
+ @Parser.emit_signals
+ def parse(self, board_data: BoardData) -> bool:
+ return False
+
+class TrueParser(Parser):
+ def parse(self, board_data: BoardData) -> bool:
+ return True
+
+class StartMeasureParser(Parser):
+ def parse(self, board_data: BoardData) -> bool:
+ return False
+
+class SWDataParser(Parser):
+ @Parser.emit_signals
+ def parse(self, board_data: BoardData) -> bool:
+ _LOGGER.debug(f"Data parser got {self.data}")
+ values = self.data.split("|")
+ for i in range(1, 7):
+ board_data.sensors_data[i] = round(float(values[i]), 3)
+ board_data.battery_level = int(values[7])
+ return True
+
+class SWIonsDataParser(Parser):
+ @Parser.emit_signals
+ def parse(self, board_data: BoardData) -> bool:
+ _LOGGER.debug(f"Data parser got {self.data}")
+ values = self.data.split("|")
+ for i in range(2, 6):
+ board_data.sensors_data[i-1] = round(float(values[i]), 3)
+ board_data.sensors_data[6] = round(float(values[1]), 3)
+ board_data.battery_level = int(values[6])
+ return True
+
+class BoardInfoParser(Parser):
+ @Parser.emit_signals
+ def parse(self, board_data: BoardData) -> bool:
+ _LOGGER.debug(f"Info parser got {self.data}")
+ values = self.data.split("|")
+ board_data.board_info["name"] = values[1]
+ board_data.board_info["serial_id"] = values[2]
+ board_data.board_info["firmware_version"] = values[3]
+ board_data.board_info["md5_hash"] = values[4]
+ board_data.board_info["firmware"] = values[5]
+ return True
+
+class CalibrationParser(Parser):
+ def parse(self, board_data: BoardData) -> None:
+ if "^|finished" in self.data:
+ return True
+ values = self.data[2:].split(" - ")
+ self.signals[0].emit({"step": int(values[0]), "value": round(float(values[1].split("\\")[0]), 3)})
+ return False
+
+class SWCoeffParser(Parser):
+ @Parser.emit_signals
+ def parse(self, board_data: BoardData) -> bool:
+ _LOGGER.debug(f"Coeffs parser got {self.data}")
+ coeffs = []
+ for value in self.data.split("|"):
+ coeffs_sensor = []
+ for coeff in value.split(","):
+ coeffs_sensor.append(coeff)
+ coeffs.append(coeffs_sensor)
+ for coeff in coeffs[1]:
+ board_data.calibration_coeffs[1][coeff.split("-")[0]] = round(float(coeff.split("-")[1]), 3)
+ board_data.calibration_coeffs[1]["Температура"] = round(float(coeffs[4][0]), 1)
+ for coeff in coeffs[2]:
+ board_data.calibration_coeffs[2][coeff.split("-")[0]] = round(float(coeff.split("-")[1]), 3)
+ for coeff in coeffs[3]:
+ board_data.calibration_coeffs[3][coeff.split("-")[0]] = round(float(coeff.split("-")[1]), 1)
+ for coeff in coeffs[5]:
+ board_data.calibration_coeffs[5][coeff.split("-")[0]] = round(float(coeff.split("-")[1]), 0)
+ return True
+
+class SWIonsCoeffParser(Parser):
+ @Parser.emit_signals
+ def parse(self, board_data: BoardData) -> bool:
+ _LOGGER.debug(f"Coeffs parser got {self.data}")
+ coeffs = []
+ for value in self.data.split("|"):
+ coeffs_sensor = []
+ for coeff in value.split(","):
+ coeffs_sensor.append(coeff)
+ coeffs.append(coeffs_sensor)
+ board_data.calibration_coeffs[1] = {}
+ for coeff in coeffs[1]:
+ solution = f"{int(float(coeff.split('-')[0].split()[0]))} {coeff.split('-')[0].split()[1]}"
+ board_data.calibration_coeffs[1][solution] = round(float(coeff.split("-")[1]), 3)
+ board_data.calibration_coeffs[2] = {}
+ for coeff in coeffs[2]:
+ solution = f"{int(float(coeff.split('-')[0].split()[0]))} {coeff.split('-')[0].split()[1]}"
+ board_data.calibration_coeffs[2][solution] = round(float(coeff.split("-")[1]), 3)
+ board_data.calibration_coeffs[3] = {}
+ for coeff in coeffs[3]:
+ solution = f"{int(float(coeff.split('-')[0].split()[0]))} {coeff.split('-')[0].split()[1]}"
+ board_data.calibration_coeffs[3][solution] = round(float(coeff.split("-")[1]), 3)
+ board_data.calibration_coeffs[4] = {}
+ for coeff in coeffs[4]:
+ solution = f"{int(float(coeff.split('-')[0].split()[0]))} {coeff.split('-')[0].split()[1]}"
+ board_data.calibration_coeffs[4][solution] = round(float(coeff.split("-")[1]), 3)
+ return True
\ No newline at end of file
diff --git a/app/sensors.py b/app/sensors.py
new file mode 100644
index 0000000..9b59acd
--- /dev/null
+++ b/app/sensors.py
@@ -0,0 +1,176 @@
+import typing as tp
+from logger import get_logger
+
+
+_LOGGER = get_logger(__name__)
+
+
+class Sensor:
+ def __init__(self):
+ self._name = ""
+ self._units = ""
+ self._calibration_solutions = []
+
+ def get_name(self) -> str:
+ return self._name
+
+ def get_units(self) -> str:
+ return self._units
+
+ def get_calibration_solutions(self) -> tp.List[str]:
+ return self._calibration_solutions
+
+ def get_calibration_command(self, calibration_solution: str) -> tp.Optional[str]:
+ return None
+
+ def get_consentration(self, calibration_solution: str) -> (tp.Optional[str], int):
+ return None
+
+
+class TemperatureSensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик температуры"
+ self._units = "℃"
+ self._calibration_solutions = []
+
+
+class pHSensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик рН"
+ self._units = "ед. рН"
+ self._calibration_solutions = ["p4", "p7", "p10"]
+ self._calibration_commands = {"p4": b"r", "p7": b"q", "p10": b"p"}
+
+ def get_calibration_command(self, calibration_solution: str) -> tp.Optional[str]:
+ return self._calibration_commands.get(calibration_solution)
+
+
+class ConductivitySensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик проводимости"
+ self._units = "мкСм"
+ self._calibration_solutions = [
+ "84 мкСм (пара 84 и 1413)",
+ "1413 мкСм (пара 84 и 1413)",
+ "12880 мкСм (пара 12880 и 80000)",
+ "80000 мкСм (пара 12880 и 80000)",
+ "12880 мкСм (пара 12880 и 150000)",
+ "150000 мкСм (пара 12880 и 150000)",
+ ]
+ self._calibration_commands = {
+ "84 мкСм (пара 84 и 1413)": b"a",
+ "1413 мкСм (пара 84 и 1413)": b"k",
+ "12880 мкСм (пара 12880 и 80000)": b"c",
+ "80000 мкСм (пара 12880 и 80000)": b"m",
+ "12880 мкСм (пара 12880 и 150000)": b"b",
+ "150000 мкСм (пара 12880 и 150000)": b"l",
+ }
+
+ def get_calibration_command(self, calibration_solution: str) -> tp.Optional[str]:
+ return self._calibration_commands.get(calibration_solution)
+
+
+class OxxygenSensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик кислорода"
+ self._units = "%"
+ self._calibration_solutions = ["0%", "100%"]
+ self._calibration_commands = {"0%": b"o", "100%": b"n"}
+
+ def get_calibration_command(self, calibration_solution: str) -> tp.Optional[str]:
+ return self._calibration_commands.get(calibration_solution)
+
+
+class ORPSensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик ОВП"
+ self._units = "мВ"
+ self._calibration_solutions = ["225 мВ"]
+ self._calibration_commands = {"225 мВ": b"s"}
+
+ def get_calibration_command(self, calibration_solution: str) -> tp.Optional[str]:
+ return self._calibration_commands.get(calibration_solution)
+
+
+class TurbiditySensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик мутности"
+ self._units = "NTU"
+ self._calibration_solutions = ["0 NTU", "10 NTU", "40 NTU"]
+ self._calibration_commands = {"0 NTU": b"", "10 NTU": b"", "40 NTU": b""}
+
+ def get_calibration_command(self, calibration_solution: str) -> tp.Optional[str]:
+ return self._calibration_commands.get(calibration_solution)
+
+
+class NO2Sensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик NO2"
+ self._units = "мг/л"
+ self._calibration_solutions = ["10 мг/л", "100 мг/л", "1000 мг/л"]
+
+ def get_consentration(self, calibration_solution: str) -> (tp.Optional[str], int):
+ return (
+ calibration_solution.split()[0],
+ self._calibration_solutions.index(calibration_solution),
+ )
+
+
+class NO3Sensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик NO3"
+ self._units = "мг/л"
+ self._calibration_solutions = [
+ "10 мг/л",
+ "100 мг/л",
+ "1000 мг/л",
+ "Multi-Ion 1 (132 мг/л)",
+ "Multi-Ion 2 (660 мг/л)",
+ "Multi-Ion 2 (1320 мг/л)",
+ ]
+
+ def get_consentration(self, calibration_solution: str) -> (tp.Optional[str], int):
+ if "Multi-Ion" in calibration_solution:
+ return calibration_solution.split()[2][1:], self._calibration_solutions.index(calibration_solution) - 3,
+ else:
+ return calibration_solution.split()[0], self._calibration_solutions.index(calibration_solution),
+
+
+class NH4Sensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик NH4"
+ self._units = "мг/л"
+ self._calibration_solutions = [
+ "10 мг/л",
+ "100 мг/л",
+ "1000 мг/л",
+ "Multi-Ion 1 (4 мг/л)",
+ "Multi-Ion 2 (20 мг/л)",
+ "Multi-Ion 2 (40 мг/л)",
+ ]
+
+ def get_consentration(self, calibration_solution: str) -> (tp.Optional[str], int):
+ if "Multi-Ion" in calibration_solution:
+ return calibration_solution.split()[2][1:], self._calibration_solutions.index(calibration_solution) - 3,
+ else:
+ return calibration_solution.split()[0], self._calibration_solutions.index(calibration_solution),
+
+
+class ClSensor(Sensor):
+ def __init__(self):
+ self._name = "Датчик Cl"
+ self._units = "мг/л"
+ self._calibration_solutions = [
+ "10 мг/л",
+ "100 мг/л",
+ "1000 мг/л",
+ "Multi-Ion 1 (75 мг/л)",
+ "Multi-Ion 2 (375 мг/л)",
+ "Multi-Ion 2 (750 мг/л)",
+ ]
+
+ def get_consentration(self, calibration_solution: str) -> (tp.Optional[str], int):
+ if "Multi-Ion" in calibration_solution:
+ return calibration_solution.split()[2][1:], self._calibration_solutions.index(calibration_solution) - 3,
+ else:
+ return calibration_solution.split()[0], self._calibration_solutions.index(calibration_solution),
diff --git a/app/sensors_const.py b/app/sensors_const.py
new file mode 100644
index 0000000..04b2ee9
--- /dev/null
+++ b/app/sensors_const.py
@@ -0,0 +1,4 @@
+SW_BOARD_TYPE = "SW"
+SWIONS_BOARD_TYPE = "SWIons"
+
+MULTIIONS_SOLUTIONS = ["Multi-Ion 1", "Multi-Ion 2", "Multi-Ion 3"]
\ No newline at end of file
diff --git a/app/workers.py b/app/workers.py
new file mode 100644
index 0000000..11e68b4
--- /dev/null
+++ b/app/workers.py
@@ -0,0 +1,133 @@
+import time
+import typing as tp
+
+import serial
+import serial.tools.list_ports
+from PyQt5 import QtCore
+from boards import Board, BoardStatus
+
+from logger import get_logger
+
+BAUDRATE = 115200
+
+_LOGGER = get_logger(__name__)
+
+
+class PortDetectThread(QtCore.QThread):
+ interval = 1.0
+ portsUpdate = QtCore.pyqtSignal([list])
+
+ def run(self):
+ """Checks list of available ports and emits signal when necessary"""
+ ports = None
+ while True:
+ new_ports = serial.tools.list_ports.comports()
+ if ports is None or [p.name for p in ports] != [p.name for p in new_ports]:
+ self.portsUpdate.emit(new_ports)
+ time.sleep(self.interval)
+ ports = new_ports
+
+
+
+class BoardSerial(QtCore.QThread):
+ interval = 0.1
+ dataUpdate = QtCore.pyqtSignal()
+ coeffsUpdate = QtCore.pyqtSignal()
+ batteryUpdate = QtCore.pyqtSignal()
+ infoUpdate = QtCore.pyqtSignal()
+ calibrationProgressUpdate = QtCore.pyqtSignal(dict)
+ currentBoardUpdate = QtCore.pyqtSignal(str)
+ boardStatusUpdate = QtCore.pyqtSignal(str)
+ restartSignal = QtCore.pyqtSignal()
+
+ def __init__(self, port: str, boards: tp.Dict[str, Board], parent=None):
+ super(QtCore.QThread, self).__init__(parent)
+ self._port_is_opened = True
+ if "tty" in port:
+ self.port: str = f"/dev/{port}"
+ else:
+ self.port: str = port
+ self.serial: serial.Serial = serial.Serial(self.port, BAUDRATE)
+ self.current_board = None
+ self._commands_queue = []
+ self._allowed_send_command = False
+ self.boards = boards
+ self._wait_response = None
+
+ def _define_board(self, data: str) -> None:
+ # Calls on first message from board
+ for board_type in self.boards:
+ if self.boards[board_type].check_message_id(data):
+ self.current_board = self.boards[board_type]
+ self.currentBoardUpdate.emit(board_type)
+ self.current_board.set_signals(
+ data_update=self.dataUpdate,
+ coeffs_update=self.coeffsUpdate,
+ battery_update=self.batteryUpdate,
+ info_update=self.infoUpdate,
+ calibration_progress=self.calibrationProgressUpdate,
+ restart=self.restartSignal,
+ )
+ self.boardStatusUpdate.emit(BoardStatus.Connected)
+ break
+ else:
+ return
+ self._allowed_send_command = self.current_board.parser(data)
+ self.update_board_info()
+ self.update_calibration_coeff()
+
+ def update_board_info(self) -> None:
+ _LOGGER.debug("Update board info call")
+ self._add_command_to_queue_or_send(self.current_board.get_board_info_command())
+
+ def update_calibration_coeff(self) -> None:
+ _LOGGER.debug("Update calibration coeffs call")
+ self._add_command_to_queue_or_send(self.current_board.get_show_coeff_command())
+
+ def start_calibration(self, sensor: str, solution: str, duration: int) -> QtCore.pyqtSignal:
+ self._add_command_to_queue_or_send(self.current_board.get_set_counter_command(duration))
+ self._add_command_to_queue_or_send(self.current_board.get_calibration_command(solution, sensor))
+
+ def close_connection(self):
+ if self._port_is_opened:
+ self.serial.close()
+ self.boardStatusUpdate.emit(BoardStatus.Disconnected)
+ _LOGGER.info(f"Port {self.port} is closed")
+ self._port_is_opened = False
+
+ def run(self):
+ while True:
+ if not self._port_is_opened:
+ break
+ try:
+ if self.serial.inWaiting() > 0:
+ new_line = str(self.serial.readline())[2:-1]
+ _LOGGER.debug(f"New serial line: {new_line}")
+ _LOGGER.debug(f"Wait response: {self._wait_response}")
+ if self._wait_response and new_line.startswith(self._wait_response):
+ self._commands_queue.pop(0)
+ self._wait_response = None
+ _LOGGER.debug(f"Commands queue after pop: {self._commands_queue}")
+ if self.current_board is not None:
+ self._allowed_send_command = self.current_board.parser(new_line)
+ else:
+ self.boardStatusUpdate.emit(BoardStatus.Connection)
+ self._allowed_send_command = self._define_board(new_line)
+ _LOGGER.debug(f"Allow send command: {self._allowed_send_command}")
+ if self._allowed_send_command and self._commands_queue:
+ self._send_command(self._commands_queue[0])
+ time.sleep(self.interval)
+ except OSError:
+ self.close_connection()
+
+ def _add_command_to_queue_or_send(self, command: tuple) -> None:
+ self._commands_queue.append(command)
+ if self._allowed_send_command:
+ self._send_command(command)
+ _LOGGER.debug(f"Send command queue: {self._commands_queue}")
+
+ def _send_command(self, command: tuple) -> None:
+ self._wait_response = command[1]
+ self.serial.write(command[0])
+ self._allowed_send_command = False
+ _LOGGER.debug(f"Command {command} was sent")
diff --git a/firmware/smart_water_with_calibration.pde b/firmware/smart_water_with_calibration.pde
new file mode 100644
index 0000000..f4ad205
--- /dev/null
+++ b/firmware/smart_water_with_calibration.pde
@@ -0,0 +1,846 @@
+#include
+#include
+#include
+
+
+char check_md5[] = "64d73b68f07a8480ecdceeb437ef63b9";
+char filename[] = "SmartWater_FRMW_V1_2.hex";
+char node_ID[] = "Node_01";
+
+// Выбор датчика температуры
+// 0 - pt1000;
+// 1 - датчик температуры, встроенный в датчик мутности
+//!ПРИ ИСПОЛЬЗОВАНИИ ДАТЧИКА МУТНОСТИ ДАТЧИК ТЕМПЕРАТУРЫ pt1000 ДОЛЖЕН БЫТЬ ОТКЛЮЧЕН!
+int TEMP_SENSOR_TYPE = 0;
+int debug = 0;
+// 0 - show nothing (calibration mode)
+// 1 - show frame
+// 2 - show data
+int ShowData = 2;
+
+
+// Время калибровки
+int counter = 10;
+int zadergka = 500;
+
+
+//версия прошивки (хранится в EEPROM)
+int addressFVMajor = 1025;
+int addressFVMinor = 1026;
+int FVMajor = 1;
+int FVMinor = 2;
+int auxFVMajor = 0;
+int auxFVMinor = 0;
+
+
+unsigned long timer = 0;
+int command = 0;
+
+
+float value_pH; // pH values in volts
+float value_temp; // temp in celsius
+float value_pH_calculated;
+float value_orp; // orp in volts
+float value_orp_calculated;
+//float value_di;
+float value_do; // oxygen in volts
+float value_do_calculated;
+float value_cond; // conductivity in Ohms
+float value_cond_calculated;
+float value_turbidity;
+
+//-----------------------------------
+// калибровочные точки для pH датчика
+float cal_point_10 = 1.985;
+float cal_point_7 = 2.070;
+float cal_point_4 = 2.227;
+int addr_p10 = 1030;
+int addr_p7 = 1035;
+int addr_p4 = 1039;
+long aux_p10 = 0;
+long aux_p7 = 0;
+long aux_p4 = 0;
+//-----------------------------------
+// Температура калибровки
+float cal_temp = 23.7;
+int addr_cal_temp = 1043;
+long aux_cal_temp = 0;
+//-----------------------------------
+// оффсет для ORP датчика (показание - 0.225)
+float calibration_offset = 0.015;
+int addr_orp_offset = 1047;
+long aux_orp_offset = 0;
+//-----------------------------------
+// показание датчика кислорода для нормального воздуха
+float air_calibration = 2.65;
+// нулевая точка для датчика кислорода (0%)
+float zero_calibration = 0.0;
+int addr_air_calib = 1051;
+int addr_zero_air = 1055;
+long aux_air_calib = 0;
+long aux_zero_air = 0;
+//-----------------------------------
+// значение первого раствора для датчика проводимости
+long point1_cond = 10500;
+// значение второго раствора для датчика проводимости
+long point2_cond = 40000;
+// точка калибровки для первого раствора для датчика проводимости
+float point1_cal = 197.00;
+// точка калибровки для второго раствора для датчика проводимости
+float point2_cal = 150.00;
+int addr_p1_cond = 1059;
+int addr_p2_cond = 1063;
+int addr_p1 = 1067;
+int addr_p2 = 1071;
+long aux_p1_cond = 0;
+long aux_p2_cond = 0;
+long aux_p1 = 0;
+long aux_p2 = 0;
+
+
+pHClass pHSensor;
+ORPClass ORPSensor;
+//DIClass DISensor;
+DOClass DOSensor;
+conductivityClass ConductivitySensor;
+pt1000Class TemperatureSensor;
+turbidityClass Turbidity;
+
+void setup()
+{
+ USB.ON();
+
+ cal_point_10 = LongToFloat(EEPROMReadLong(addr_p10));
+ cal_point_7 = LongToFloat(EEPROMReadLong(addr_p7));
+ cal_point_4 = LongToFloat(EEPROMReadLong(addr_p4));
+ air_calibration = LongToFloat(EEPROMReadLong(addr_air_calib));
+ zero_calibration = LongToFloat(EEPROMReadLong(addr_zero_air));
+ point1_cond = EEPROMReadLong(addr_p1_cond);
+ point2_cond = EEPROMReadLong(addr_p2_cond);
+ point1_cal = LongToFloat(EEPROMReadLong(addr_p1));
+ point2_cal = LongToFloat(EEPROMReadLong(addr_p2));
+ cal_temp = LongToFloat(EEPROMReadLong(addr_cal_temp));
+ calibration_offset = LongToFloat(EEPROMReadLong(addr_orp_offset));
+
+ Utils.writeEEPROM(addressFVMajor, FVMajor);
+ Utils.writeEEPROM(addressFVMinor, FVMinor);
+ auxFVMajor = Utils.readEEPROM(addressFVMajor);
+ auxFVMinor = Utils.readEEPROM(addressFVMajor);
+
+ delay(5000);
+
+ if (debug == 1) {
+ USB.println(cal_point_10);
+ USB.println(cal_point_7);
+ USB.println(cal_point_4);
+ USB.println(air_calibration);
+ USB.println(zero_calibration);
+ USB.println(point1_cond);
+ USB.println(point2_cond);
+ USB.println(point1_cal);
+ USB.println(point2_cal);
+ USB.println(cal_temp);
+ USB.println(calibration_offset);
+ }
+
+ // Configure the calibration values
+ pHSensor.setCalibrationPoints(cal_point_10, cal_point_7, cal_point_4, cal_temp);
+ DOSensor.setCalibrationPoints(air_calibration, zero_calibration);
+ ConductivitySensor.setCalibrationPoints(point1_cond, point1_cal, point2_cond, point2_cal);
+//------------------------------------------------------------------------------------------
+ //-----------------------------------------------------------------
+ USB.flush();
+}
+
+void loop()
+{
+ ///////////////////////////////////////////
+ // 1. Turn on the board
+ ///////////////////////////////////////////
+
+ if (ShowData == 2) {
+ SesorData();
+ USB.flush();
+ }
+
+// USB commands reading
+ timer = millis();
+ while(millis()-timer < 5000)
+ {
+ if (USB.available() > 0)
+ {
+ command = USB.read();
+ switch (command) {
+ case 65: // A
+ //USB.flush();
+ ShowData = 0;
+ USB.println(F("#!"));
+ break;
+ case 66: //B
+ ShowData = 1;
+ USB.println(F("#+"));
+ break;
+ case 67: // C
+ ShowData = 2;
+ USB.println(F("#-"));
+ break;
+ case 121: // y
+ debug = 1;
+ break;
+ case 122: // z
+ ShowCoeff();
+ case 100: // d
+ TEMP_SENSOR_TYPE = 1;
+ if (debug == 1) { USB.println(F("Temp from turbidity sensor")); }
+ break;
+ case 101: // e
+ TEMP_SENSOR_TYPE = 0;
+ if (debug == 1) { USB.println(F("temp from pt1000")); }
+ break;
+ case 116: // t
+ counter = USBGetInt();
+ USB.println(F("#t"));
+ if (debug == 1) { USB.println(counter); }
+ break;
+ case 97: // a
+ //USB.flush();
+ delay(1000);
+ USB.println(F("#?"));
+ //CondCalib_R1(220, 3000);
+ CondCalib_R1(84, 1413);
+ USB.println(F("#a"));
+ ShowCoeff();
+ break;
+ case 98: // b
+ delay(1000);
+ USB.println(F("#?"));
+ //CondCalib_R1(10500, 40000);
+ CondCalib_R1(12880, 150000);
+ USB.println(F("#b"));
+ ShowCoeff();
+ break;
+ case 99: // c
+ delay(1000);
+ USB.println(F("#?"));
+ //CondCalib_R1(62000, 90000);
+ CondCalib_R1(12880, 80000);
+ USB.println(F("#c"));
+ ShowCoeff();
+ break;
+ case 107: // k
+ delay(1000);
+ USB.println(F("#?"));
+ //CondCalib_R2(220, 3000);
+ CondCalib_R2(84, 1413);
+ USB.println(F("#k"));
+ ShowCoeff();
+ break;
+ case 108: // l
+ delay(1000);
+ USB.println(F("#?"));
+ //CondCalib_R2(10500, 40000);
+ CondCalib_R2(12880, 150000);
+ USB.println(F("#l"));
+ ShowCoeff();
+ break;
+ case 109: // m
+ delay(1000);
+ USB.println(F("#?"));
+ //CondCalib_R2(62000, 90000);
+ CondCalib_R2(12880, 80000);
+ USB.println(F("#m"));
+ ShowCoeff();
+ break;
+ case 110: // n
+ delay(1000);
+ USB.println(F("#?"));
+ OxygenCalib_100p();
+ USB.println(F("#n"));
+ ShowCoeff();
+ break;
+ case 111: // o
+ delay(1000);
+ USB.println(F("#?"));
+ OxygenCalib_0p();
+ USB.println(F("#0"));
+ ShowCoeff();
+ break;
+ case 112: // p
+ delay(1000);
+ USB.println(F("#?"));
+ pHSensorCalibP10();
+ USB.println(F("#p"));
+ ShowCoeff();
+ break;
+ case 113: // q
+ delay(1000);
+ USB.println(F("#?"));
+ pHSensorCalibP7();
+ USB.println(F("#q"));
+ ShowCoeff();
+ break;
+ case 114: // r
+ delay(1000);
+ USB.println(F("#?"));
+ pHSensorCalibP4();
+ USB.println(F("#r"));
+ ShowCoeff();
+ break;
+ case 115: // s
+ delay(1000);
+ USB.println(F("#?"));
+ ORPSensorCalib();
+ USB.println(F("#s"));
+ ShowCoeff();
+ break;
+ case 102: // f
+ auxFVMajor = Utils.readEEPROM(addressFVMajor);
+ auxFVMinor = Utils.readEEPROM(addressFVMajor);
+ //USB.print(F("Имя устройства: "));
+ //USB.println(node_ID);
+ USB.print(F("#f|"));
+ //delay(1000);
+ //USB.println();
+ USB.print(node_ID);
+ USB.print("|");
+ ShowSerialNumber();
+ USB.print("|");
+ //USB.print(F("Версия прошивки: "));
+ USB.print(auxFVMajor);
+ USB.print(F("."));
+ //USB.println(auxFVMinor);
+ USB.print(auxFVMinor);
+ USB.print("|");
+ USB.print(check_md5);
+ USB.print("|");
+ USB.print(filename);
+ USB.println(F("|"));
+ break;
+ default:
+ //USB.println(F("Wrong command!"));
+ break;
+ }
+ USB.flush();
+
+ }
+ if (millis() < timer)
+ {
+ timer = millis();
+ }
+ }
+ //frame.showFrame();
+}
+
+long USBGetLong() {
+ char number[10];
+ int i = 0;
+ while (USB.available() > 0) {
+ number[i] = (char) USB.read();
+ i++;
+ }
+
+ long result = atol(number);
+ return result;
+}
+
+int USBGetInt() {
+ char number[10];
+ int i = 0;
+ while (USB.available() > 0) {
+ number[i] = (char) USB.read();
+ i++;
+ }
+
+ int result = atoi(number);
+ return result;
+}
+
+long FloatToLong(float val) {
+ long a = val * 1000;
+ return a;
+}
+
+float LongToFloat(long val1) {
+ float b = (float) val1/1000.0;
+ return b;
+}
+
+//запись в EEPROM данных типа long
+void EEPROMWriteLong(int address, long value) {
+ byte four = (value & 0xFF);
+ byte three = ((value >> 8) & 0xFF);
+ byte two = ((value >> 16) & 0xFF);
+ byte one = ((value >> 24) & 0xFF);
+
+ Utils.writeEEPROM(address, four);
+ Utils.writeEEPROM(address + 1, three);
+ Utils.writeEEPROM(address + 2, two);
+ Utils.writeEEPROM(address + 3, one);
+}
+
+//чтение из EEPROM данных типа long
+long EEPROMReadLong(int address1) {
+ long four = Utils.readEEPROM(address1);
+ long three = Utils.readEEPROM(address1 + 1);
+ long two = Utils.readEEPROM(address1 + 2);
+ long one = Utils.readEEPROM(address1 + 3);
+
+ return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
+}
+
+//--------------------------------------
+// Выбор с какого датчика читаем температуру с одного из двух датчиков
+float readTemp() {
+ float val_temp = 0.0;
+ if (TEMP_SENSOR_TYPE == 1)
+ {
+ val_temp = Turbidity.getTemperature();
+ }
+ else
+ {
+ val_temp = TemperatureSensor.readTemperature();
+ }
+
+ return val_temp;
+}
+
+//--------------------------------------
+// автоматический выбор датчика температуры (тестовая функция!)
+float readTempAuto() {
+ float val_temp1 = 0.0;
+ val_temp1 = Turbidity.getTemperature();
+ if (val_temp1 == -1000.0)
+ {
+ val_temp1 = TemperatureSensor.readTemperature();
+ }
+ return val_temp1;
+
+}
+
+//--------------------------------------
+// Калибровка рН датчика в растворе рН10
+void pHSensorCalibP10() {
+ float pH_val_ohm = 0.0;
+ float temp1 = 0.0;
+ aux_p10 = EEPROMReadLong(addr_p10);
+ aux_p7 = EEPROMReadLong(addr_p7);
+ aux_p4 = EEPROMReadLong(addr_p4);
+ aux_cal_temp = EEPROMReadLong(addr_cal_temp);
+ pHSensor.setCalibrationPoints(LongToFloat(aux_p10), LongToFloat(aux_p7), LongToFloat(aux_p4), LongToFloat(aux_cal_temp));
+ Water.ON();
+
+ for (int i = 0; i < counter; i++) {
+ pH_val_ohm = pHSensor.readpH();
+ //temp1 = readTemp();
+ temp1 = readTempAuto();
+ USB.print(F("^|"));
+ USB.print(i);
+ USB.print(F(" - "));
+ USB.println(pH_val_ohm);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ EEPROMWriteLong(addr_p10, FloatToLong(pH_val_ohm));
+ EEPROMWriteLong(addr_cal_temp, FloatToLong(temp1));
+ //EEPROMWriteLong(addr_p7, FloatToLong(aux_p7));
+ //EEPROMWriteLong(addr_p4, FloatToLong(aux_p4));
+ pHSensor.setCalibrationPoints(pH_val_ohm, LongToFloat(aux_p7), LongToFloat(aux_p4), temp1);
+ if (debug == 1) {
+ USB.println(F("Калибровка для раствора pH10 завершена."));
+ }
+}
+
+//--------------------------------------
+// Калибровка рН датчика в растворе рН7
+void pHSensorCalibP7() {
+ float pH_val_ohm = 0.0;
+ float temp1 = 0.0;
+ aux_p10 = EEPROMReadLong(addr_p10);
+ aux_p7 = EEPROMReadLong(addr_p7);
+ aux_p4 = EEPROMReadLong(addr_p4);
+ aux_cal_temp = EEPROMReadLong(addr_cal_temp);
+ pHSensor.setCalibrationPoints(LongToFloat(aux_p10), LongToFloat(aux_p7), LongToFloat(aux_p4), LongToFloat(aux_cal_temp));
+ Water.ON();
+
+ for (int i = 0; i < counter; i++) {
+ pH_val_ohm = pHSensor.readpH();
+ //temp1 = readTemp();
+ temp1 = readTempAuto();
+ USB.print(F("^|"));
+ USB.print(i);
+ USB.print(F(" - "));
+ USB.println(pH_val_ohm);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ EEPROMWriteLong(addr_p7, FloatToLong(pH_val_ohm));
+ //EEPROMWriteLong(addr_p7, FloatToLong(aux_p7));
+ //EEPROMWriteLong(addr_p4, FloatToLong(aux_p4));
+ pHSensor.setCalibrationPoints(LongToFloat(aux_p10), pH_val_ohm, LongToFloat(aux_p4), temp1);
+ if (debug == 1) {
+ USB.println(F("Калибровка для раствора pH7 завершена."));
+ }
+}
+
+//--------------------------------------
+// Калибровка рН датчика в растворе рН4
+void pHSensorCalibP4() {
+ float pH_val_ohm = 0.0;
+ float temp1 = 0.0;
+ aux_p10 = EEPROMReadLong(addr_p10);
+ aux_p7 = EEPROMReadLong(addr_p7);
+ aux_p4 = EEPROMReadLong(addr_p4);
+ aux_cal_temp = EEPROMReadLong(addr_cal_temp);
+ pHSensor.setCalibrationPoints(LongToFloat(aux_p10), LongToFloat(aux_p7), LongToFloat(aux_p4), LongToFloat(aux_cal_temp));
+ Water.ON();
+
+ for (int i = 0; i < counter; i++) {
+ pH_val_ohm = pHSensor.readpH();
+ //temp1 = readTemp();
+ temp1 = readTempAuto();
+ USB.print(F("^|"));
+ USB.print(i);
+ USB.print(F(" - "));
+ USB.println(pH_val_ohm);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ EEPROMWriteLong(addr_p4, FloatToLong(pH_val_ohm));
+ //EEPROMWriteLong(addr_p7, FloatToLong(aux_p7));
+ //EEPROMWriteLong(addr_p4, FloatToLong(aux_p4));
+ pHSensor.setCalibrationPoints(LongToFloat(aux_p10), LongToFloat(aux_p7), pH_val_ohm, temp1);
+ if (debug == 1) {
+ USB.println(F("Калибровка для раствора pH4 завершена."));
+ }
+}
+
+//--------------------------------------
+// Калибровка датчика окислительно-восстановительного процесса
+void ORPSensorCalib() {
+ float orp_calib = 0.0;
+ float orp_calculated = 0.0;
+ aux_orp_offset = LongToFloat(EEPROMReadLong(addr_orp_offset));
+ Water.ON();
+ for (int k = 0; k < counter; k++) {
+ orp_calib = 1000*ORPSensor.readORP();
+ // orp_calculated = orp_calib - LongToFloat(aux_orp_offset);
+ USB.print(F("^|"));
+ USB.print(k);
+ USB.print(F(" - "));
+ USB.println(orp_calib);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ aux_orp_offset = orp_calib - 225;
+ EEPROMWriteLong(addr_orp_offset, FloatToLong(aux_orp_offset));
+ calibration_offset = LongToFloat(EEPROMReadLong(addr_orp_offset));
+ if (debug == 1) {
+ USB.print(F("Калибровка завершена. Значение калибровочного смещения(вольт): "));
+ USB.println(aux_orp_offset);
+ }
+}
+
+//--------------------------------------
+// Калибровка датчика кислорода в 100% растворе кислорода
+void OxygenCalib_100p() {
+ aux_air_calib = EEPROMReadLong(addr_air_calib);
+ aux_zero_air = EEPROMReadLong(addr_zero_air);
+ float result = 0.0;
+ DOSensor.setCalibrationPoints(LongToFloat(aux_air_calib), LongToFloat(aux_zero_air));
+ Water.ON();
+ for (int j = 0; j < counter; j++) {
+ result = DOSensor.readDO();
+ USB.print(F("^|"));
+ USB.print(j);
+ USB.print(F(" - "));
+ USB.println(result);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ EEPROMWriteLong(addr_air_calib, FloatToLong(result));
+ DOSensor.setCalibrationPoints(result, LongToFloat(aux_zero_air));
+ if (debug == 1) {
+ USB.print(F("Калибровка первой точки (100) завершена."));
+ }
+}
+
+//--------------------------------------
+// Калибровка датчика кислорода в 0% растворе кислорода
+void OxygenCalib_0p() {
+ aux_air_calib = EEPROMReadLong(addr_air_calib);
+ aux_zero_air = EEPROMReadLong(addr_zero_air);
+ float result = 0.0;
+ DOSensor.setCalibrationPoints(LongToFloat(aux_air_calib), LongToFloat(aux_zero_air));
+ Water.ON();
+ for (int j = 0; j < counter; j++) {
+ result = DOSensor.readDO();
+ USB.print(F("^|"));
+ USB.print(j);
+ USB.print(F(" - "));
+ USB.println(result);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ EEPROMWriteLong(addr_zero_air, FloatToLong(result));
+ DOSensor.setCalibrationPoints(LongToFloat(aux_air_calib), result);
+ if (debug == 1) {
+ USB.print(F("Калибровка второй точки (0) завершена."));
+ }
+}
+
+//--------------------------------------
+// Калибровка датчика проводимости для 1-го раствора из комплекта
+// Калибровочные растворы
+// K = 0.1 220 uS 3000 uS
+// K = 1 10500 uS 40000 uS
+// K = 10 62000 uS 90000 uS
+void CondCalib_R1(long rastvor1, long rastvor2) {
+ //aux_p1_cond = EEPROMReadLong(addr_p1_cond);
+ //aux_p2_cond = EEPROMReadLong(addr_p2_cond);
+ aux_p1_cond = rastvor1;
+ aux_p2_cond = rastvor2;
+ EEPROMWriteLong(addr_p1_cond, aux_p1_cond);
+ EEPROMWriteLong(addr_p2_cond, aux_p2_cond);
+ aux_p1 = EEPROMReadLong(addr_p1);
+ aux_p2 = EEPROMReadLong(addr_p2);
+ float resist = 0.0;
+ ConductivitySensor.setCalibrationPoints(aux_p1_cond, LongToFloat(aux_p1), aux_p2_cond, LongToFloat(aux_p2));
+ Water.ON();
+ for (int n = 0; n < counter; n++) {
+ resist = ConductivitySensor.readConductivity();
+ USB.print(F("^|"));
+ USB.print(n);
+ USB.print(F(" - "));
+ USB.println(resist);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ EEPROMWriteLong(addr_p1, FloatToLong(resist));
+ ConductivitySensor.setCalibrationPoints(rastvor1, resist, aux_p2_cond, LongToFloat(aux_p2));
+ if (debug == 1) {
+ USB.print(F("Раствор: "));
+ USB.println(aux_p1_cond);
+ USB.print(F("Коэффициент: "));
+ USB.println(resist);
+ USB.print(F("Калибровка для первого раствора завершена."));
+ }
+}
+
+//--------------------------------------
+// Калибровка датчика проводимости для 1-го раствора из комплекта
+// Калибровочные растворы
+// K = 0.1 220 uS 3000 uS
+// K = 1 10500 uS 40000 uS
+// K = 10 62000 uS 90000 uS
+void CondCalib_R2(long rastvor1, long rastvor2) {
+ //aux_p1_cond = EEPROMReadLong(addr_p1_cond);
+ //aux_p2_cond = EEPROMReadLong(addr_p2_cond);
+ aux_p1_cond = rastvor1;
+ aux_p2_cond = rastvor2;
+ EEPROMWriteLong(addr_p1_cond, aux_p1_cond);
+ EEPROMWriteLong(addr_p2_cond, aux_p2_cond);
+ aux_p1 = EEPROMReadLong(addr_p1);
+ aux_p2 = EEPROMReadLong(addr_p2);
+ float resist = 0.0;
+ ConductivitySensor.setCalibrationPoints(aux_p1_cond, LongToFloat(aux_p1), aux_p2_cond, LongToFloat(aux_p2));
+ Water.ON();
+ for (int n = 0; n < counter; n++) {
+ resist = ConductivitySensor.readConductivity();
+ USB.print(F("^|"));
+ USB.print(n);
+ USB.print(F(" - "));
+ USB.println(resist);
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ Water.OFF();
+ EEPROMWriteLong(addr_p2, FloatToLong(resist));
+ ConductivitySensor.setCalibrationPoints(aux_p1_cond, LongToFloat(aux_p1), rastvor2, resist);
+ if (debug == 1) {
+ USB.print(F("Раствор: "));
+ USB.println(aux_p2_cond);
+ USB.print(F("Коэффициент: "));
+ USB.println(resist);
+ USB.print(F("Калибровка для второго раствора завершена."));
+ }
+}
+
+void ShowSerialNumber() {
+ //USB.print(F("Serial ID:"));
+ USB.printHex(_serial_id[0]);
+ USB.printHex(_serial_id[1]);
+ USB.printHex(_serial_id[2]);
+ USB.printHex(_serial_id[3]);
+ USB.printHex(_serial_id[4]);
+ USB.printHex(_serial_id[5]);
+ USB.printHex(_serial_id[6]);
+ USB.printHex(_serial_id[7]);
+ //USB.println();
+ //delay(1000);
+}
+
+void ShowCoeff() {
+ cal_point_10 = LongToFloat(EEPROMReadLong(addr_p10));
+ cal_point_7 = LongToFloat(EEPROMReadLong(addr_p7));
+ cal_point_4 = LongToFloat(EEPROMReadLong(addr_p4));
+ air_calibration = LongToFloat(EEPROMReadLong(addr_air_calib));
+ zero_calibration = LongToFloat(EEPROMReadLong(addr_zero_air));
+ point1_cond = EEPROMReadLong(addr_p1_cond);
+ point2_cond = EEPROMReadLong(addr_p2_cond);
+ point1_cal = LongToFloat(EEPROMReadLong(addr_p1));
+ point2_cal = LongToFloat(EEPROMReadLong(addr_p2));
+ cal_temp = LongToFloat(EEPROMReadLong(addr_cal_temp));
+ calibration_offset = LongToFloat(EEPROMReadLong(addr_orp_offset));
+
+ USB.print(F("#z|10 pH-"));
+ USB.print(cal_point_10);
+ USB.print(F(",7 pH-"));
+ USB.print(cal_point_7);
+ USB.print(F(",4 pH-"));
+ USB.print(cal_point_4);
+ USB.print(F("|100%-"));
+ USB.print(air_calibration);
+ USB.print(F(",0%-"));
+ USB.print(zero_calibration);
+ USB.print(F("|"));
+ USB.print(point1_cond);
+ USB.print(F(" mkS-"));
+ USB.print(point1_cal);
+ USB.print(F(","));
+ USB.print(point2_cond);
+ USB.print(F(" mkS-"));
+ USB.print(point2_cal);
+ USB.print(F("|"));
+ USB.print(cal_temp);
+ USB.print(F("|225 mV-"));
+ USB.print(calibration_offset);
+ USB.println(F("|"));
+
+
+ if (debug == 1) {
+ USB.println(F("Ph (10, 7, 4):"));
+ USB.println(cal_point_10);
+ USB.println(cal_point_7);
+ USB.println(cal_point_4);
+ USB.println(F("DO (air, zero):"));
+ USB.println(air_calibration);
+ USB.println(zero_calibration);
+ USB.println(F("Cond solutions:"));
+ USB.println(point1_cond);
+ USB.println(point2_cond);
+ USB.println(F("Cond cal points:"));
+ USB.println(point1_cal);
+ USB.println(point2_cal);
+ USB.println(F("Cal temp:"));
+ USB.println(cal_temp);
+ USB.println(F("ORP offset:"));
+ USB.println(calibration_offset);
+ }
+}
+
+void SesorData() {
+ USB.println(F("$measure"));
+ Water.ON();
+ Turbidity.ON();
+ delay(2000);
+
+ ///////////////////////////////////////////
+ // 2. Read sensors
+ ///////////////////////////////////////////
+
+ // Read the ph sensor
+ value_pH = pHSensor.readpH();
+ if (debug == 1) {
+ USB.print(F("Ph_volt: "));
+ USB.println(value_pH);
+ }
+ // Read the temperature sensor
+ //value_temp = TemperatureSensor.readTemperature();
+ //value_temp = Turbidity.getTemperature();
+ //value_temp = readTemp();
+ value_temp = readTempAuto();
+ if (debug == 1) {
+ USB.print(F("Temp: "));
+ USB.println(value_temp);
+ }
+ value_turbidity = Turbidity.getTurbidity();
+ // Convert the value read with the information obtained in calibration
+ value_pH_calculated = pHSensor.pHConversion(value_pH,value_temp);
+ if (debug == 1) {
+ USB.print(F("Ph final: "));
+ USB.println(value_pH_calculated);
+ }
+ // Reading of the ORP sensor
+ value_orp = 1000*ORPSensor.readORP();
+ if (debug == 1) {
+ USB.print(F("ORP volts: "));
+ USB.println(value_orp);
+ }
+ // Apply the calibration offset
+ value_orp_calculated = value_orp - calibration_offset;
+ if (debug == 1) {
+ USB.print(F("ORP final: "));
+ USB.println(value_orp_calculated);
+ }
+ // Reading of the DI sensor
+ //value_di = DISensor.readDI();
+ // Reading of the ORP sensor
+ value_do = DOSensor.readDO();
+ if (debug == 1) {
+ USB.print(F("DO volts: "));
+ USB.println(value_do);
+ }
+ // Conversion from volts into dissolved oxygen percentage
+ value_do_calculated = DOSensor.DOConversion(value_do);
+ if (debug == 1) {
+ USB.print(F("DO final: "));
+ USB.println(value_do_calculated);
+ }
+ // Reading of the Conductivity sensor
+ value_cond = ConductivitySensor.readConductivity();
+ if (debug == 1) {
+ USB.print(F("Cond before calc: "));
+ USB.println(value_cond);
+ }
+ // Conversion from resistance into ms/cm
+ value_cond_calculated = ConductivitySensor.conductivityConversion(value_cond);
+ if (debug == 1) {
+ USB.print(F("Cond final: "));
+ USB.println(value_cond_calculated);
+ }
+
+ ///////////////////////////////////////////
+ // 3. Turn off the sensors
+ ///////////////////////////////////////////
+
+ Water.OFF();
+ USB.print("$w|");
+ //USB.print(FloatToLong(value_temp));
+ USB.print(value_temp);
+ USB.print("|");
+ //USB.print(FloatToLong(value_pH_calculated));
+ USB.print(value_pH_calculated);
+ USB.print("|");
+ //USB.print(FloatToLong(value_cond_calculated));
+ USB.print(value_cond_calculated);
+ USB.print("|");
+ //USB.print(FloatToLong(value_do_calculated));
+ USB.print(value_do_calculated);
+ USB.print("|");
+ //USB.print(FloatToLong(value_orp_calculated));
+ USB.print(value_orp_calculated);
+ USB.print("|");
+ //USB.print(FloatToLong(value_turbidity));
+ USB.print(value_turbidity);
+ USB.print("|");
+ USB.print(PWR.getBatteryLevel(), DEC);
+ USB.print("|$");
+ USB.println();
+}
\ No newline at end of file
diff --git a/firmware/water_ions_with_calibration.pde b/firmware/water_ions_with_calibration.pde
new file mode 100644
index 0000000..1f51624
--- /dev/null
+++ b/firmware/water_ions_with_calibration.pde
@@ -0,0 +1,891 @@
+#include
+#include
+
+//----------------------------------------------------------------------------------------
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//ОСТАЛЬНЫЕ НАСТРОЙКИ МЕНЯТЬ ЗАПРЕЩАЕТСЯ!
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+char check_md5[] = "417e4d803cefa2397901a94089f91e21";
+char filename[] = "SWIons1_2.hex";
+char node_ID[] = "Node_02";
+
+// 0 - show nothing (calibration mode)
+// 1 - show frame
+// 2 - show data
+int ShowData = 2;
+
+int debug = 0;
+
+// Время калибровки
+int counter = 100;
+int zadergka = 500;
+
+//версия прошивки (хранится в EEPROM)
+int addressFVMajor = 1025;
+int addressFVMinor = 1026;
+int FVMajor = 1;
+int FVMinor = 2;
+int auxFVMajor = 0;
+int auxFVMinor = 0;
+
+// serial transfer vars
+unsigned long timer = 0;
+int command = 0;
+float command_consentration = 0;
+
+// калибровочные точки для pH датчика
+// float cal_point_10 = 1.985;
+// float cal_point_7 = 2.070;
+// float cal_point_4 = 2.227;
+// int addr_p10 = 1030;
+// int addr_p7 = 1035;
+// int addr_p4 = 1039;
+// long aux_p10 = 0;
+// long aux_p7 = 0;
+// long aux_p4 = 0;
+//-----------------------------------
+// Температура калибровки
+float cal_temp = 23.7;
+int addr_cal_temp = 1043;
+long aux_cal_temp = 0;
+
+//calib coeffs for sensor on socket A
+float A_point1_V = 0.0;
+float A_point2_V = 0.0;
+float A_point3_V = 0.0;
+int addr_A_p1 = 1047;
+int addr_A_p2 = 1051;
+int addr_A_p3 = 1055;
+long aux_A_p1 = 0;
+long aux_A_p2 = 0;
+long aux_A_p3 = 0;
+float concent_A_1 = 4.0;
+float concent_A_2 = 20.0;
+float concent_A_3 = 40.0;
+int addr_concent_A_1 = 1059;
+int addr_concent_A_2 = 1063;
+int addr_concent_A_3 = 1067;
+
+//calib coeffs for sensor on socket B
+float B_point1_V = 0.0;
+float B_point2_V = 0.0;
+float B_point3_V = 0.0;
+int addr_B_p1 = 1071;
+int addr_B_p2 = 1075;
+int addr_B_p3 = 1079;
+long aux_B_p1 = 0;
+long aux_B_p2 = 0;
+long aux_B_p3 = 0;
+float concent_B_1 = 132.0;
+float concent_B_2 = 660.0;
+float concent_B_3 = 1320.0;
+int addr_concent_B_1 = 1083;
+int addr_concent_B_2 = 1087;
+int addr_concent_B_3 = 1091;
+
+//calib coeffs for sensor on socket C
+float C_point1_V = 0.0;
+float C_point2_V = 0.0;
+float C_point3_V = 0.0;
+int addr_C_p1 = 1095;
+int addr_C_p2 = 1099;
+int addr_C_p3 = 1103;
+long aux_C_p1 = 0;
+long aux_C_p2 = 0;
+long aux_C_p3 = 0;
+float concent_C_1 = 10.0;
+float concent_C_2 = 100.0;
+float concent_C_3 = 1000.0;
+int addr_concent_C_1 = 1107;
+int addr_concent_C_2 = 1111;
+int addr_concent_C_3 = 1115;
+
+//calib coeffs for sensor on socket D
+float D_point1_V = 0.0;
+float D_point2_V = 0.0;
+float D_point3_V = 0.0;
+int addr_D_p1 = 1119;
+int addr_D_p2 = 1123;
+int addr_D_p3 = 1127;
+long aux_D_p1 = 0;
+long aux_D_p2 = 0;
+long aux_D_p3 = 0;
+float concent_D_1 = 75.0;
+float concent_D_2 = 375.0;
+float concent_D_3 = 750.0;
+int addr_concent_D_1 = 1131;
+int addr_concent_D_2 = 1135;
+int addr_concent_D_3 = 1139;
+
+// A,B,D,C - any ion sensor
+// F - pt1000 sensor
+ionSensorClass SensorSocketA(SOCKET_A); // socket 1 - NH4
+ionSensorClass SensorSocketB(SOCKET_B); // socket 2 - NO3
+ionSensorClass SensorSocketC(SOCKET_C); // socket 3 - NO2
+ionSensorClass SensorSocketD(SOCKET_D); // socket 4 - Cl
+pt1000Class tempSensor;
+
+float SOCK_A_Raw = 0.0;
+float SOCK_B_Raw = 0.0;
+float SOCK_C_Raw = 0.0;
+float SOCK_D_Raw = 0.0;
+float SOCK_A_Calc = 0.0;
+float SOCK_B_Calc = 0.0;
+float SOCK_C_Calc = 0.0;
+float SOCK_D_Calc = 0.0;
+// float value_pH = 0.0;
+// float value_pH_calculated = 0.0;
+float value_temp = 0.0;
+
+
+void setup() {
+ USB.ON();
+ SWIonsBoard.ON();
+ cal_temp = LongToFloat(EEPROMReadLong(addr_cal_temp));
+ // cal_point_10 = LongToFloat(EEPROMReadLong(addr_p10));
+ // cal_point_7 = LongToFloat(EEPROMReadLong(addr_p7));
+ // cal_point_4 = LongToFloat(EEPROMReadLong(addr_p4));
+ A_point1_V = LongToFloat(EEPROMReadLong(addr_A_p1));
+ A_point2_V = LongToFloat(EEPROMReadLong(addr_A_p2));
+ A_point3_V = LongToFloat(EEPROMReadLong(addr_A_p3));
+ concent_A_1 = LongToFloat(EEPROMReadLong(addr_concent_A_1));
+ concent_A_2 = LongToFloat(EEPROMReadLong(addr_concent_A_2));
+ concent_A_3 = LongToFloat(EEPROMReadLong(addr_concent_A_3));
+ B_point1_V = LongToFloat(EEPROMReadLong(addr_B_p1));
+ B_point2_V = LongToFloat(EEPROMReadLong(addr_B_p2));
+ B_point3_V = LongToFloat(EEPROMReadLong(addr_B_p3));
+ concent_B_1 = LongToFloat(EEPROMReadLong(addr_concent_B_1));
+ concent_B_2 = LongToFloat(EEPROMReadLong(addr_concent_B_2));
+ concent_B_3 = LongToFloat(EEPROMReadLong(addr_concent_B_3));
+ C_point1_V = LongToFloat(EEPROMReadLong(addr_C_p1));
+ C_point2_V = LongToFloat(EEPROMReadLong(addr_C_p2));
+ C_point3_V = LongToFloat(EEPROMReadLong(addr_C_p3));
+ concent_C_1 = LongToFloat(EEPROMReadLong(addr_concent_C_1));
+ concent_C_2 = LongToFloat(EEPROMReadLong(addr_concent_C_2));
+ concent_C_3 = LongToFloat(EEPROMReadLong(addr_concent_C_3));
+ D_point1_V = LongToFloat(EEPROMReadLong(addr_D_p1));
+ D_point2_V = LongToFloat(EEPROMReadLong(addr_D_p2));
+ D_point3_V = LongToFloat(EEPROMReadLong(addr_D_p3));
+ concent_D_1 = LongToFloat(EEPROMReadLong(addr_concent_D_1));
+ concent_D_2 = LongToFloat(EEPROMReadLong(addr_concent_D_2));
+ concent_D_3 = LongToFloat(EEPROMReadLong(addr_concent_D_3));
+
+ Utils.writeEEPROM(addressFVMajor, FVMajor);
+ Utils.writeEEPROM(addressFVMinor, FVMinor);
+ auxFVMajor = Utils.readEEPROM(addressFVMajor);
+ auxFVMinor = Utils.readEEPROM(addressFVMajor);
+
+ delay(1000);
+
+ const float concentrations_A[] = {concent_A_1, concent_A_2, concent_A_3};
+ const float concentrations_B[] = {concent_B_1, concent_B_2, concent_B_3};
+ const float concentrations_C[] = {concent_C_1, concent_C_2, concent_C_3};
+ const float concentrations_D[] = {concent_D_1, concent_D_2, concent_D_3};
+ const float voltages_A[] = {A_point1_V, A_point2_V, A_point3_V};
+ const float voltages_B[] = {B_point1_V, B_point2_V, B_point3_V};
+ const float voltages_C[] = {C_point1_V, C_point2_V, C_point3_V};
+ const float voltages_D[] = {D_point1_V, D_point2_V, D_point3_V};
+
+ SensorSocketA.setCalibrationPoints(voltages_A, concentrations_A, 3);
+ SensorSocketB.setCalibrationPoints(voltages_B, concentrations_B, 3);
+ SensorSocketC.setCalibrationPoints(voltages_C, concentrations_C, 3);
+ SensorSocketD.setCalibrationPoints(voltages_D, concentrations_D, 3);
+ // pHSensor.setpHCalibrationPoints(cal_point_10, cal_point_7, cal_point_4, cal_temp);
+
+ // frame.setID(node_ID);
+ // WiFi_Init();
+
+}
+
+void loop() {
+
+ if (ShowData == 2) {
+ SensorData();
+ USB.flush();
+ }
+
+ // USB commands reading
+ timer = millis();
+ while(millis()-timer < 5000)
+ {
+ if (USB.available() > 0)
+ {
+ command = USB.read();
+ switch (command) {
+ case 65: // A
+ //USB.flush();
+ ShowData = 0;
+ USB.println(F("#!"));
+ break;
+ // case 66: //B
+ // ShowData = 1;
+ // USB.println(F("#+"));
+ // break;
+ case 67: // C
+ ShowData = 2;
+ USB.println(F("#-"));
+ break;
+ case 121: // y
+ debug = 1;
+ break;
+ case 122: // z
+ ShowCoeff();
+ case 100: // d
+ //TEMP_SENSOR_TYPE = 1;
+ //if (debug == 1) { USB.println(F("Temp from turbidity sensor")); }
+ break;
+ case 101: // e
+ //TEMP_SENSOR_TYPE = 0;
+ //if (debug == 1) { USB.println(F("temp from pt1000")); }
+ break;
+ case 116: // t
+ counter = USBGetInt();
+ USB.println(F("#t"));
+ if (debug == 1) { USB.println(counter); }
+ break;
+ case 97: // a
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_A_Calib(command_consentration, 1);
+ USB.println(F("#a"));
+ ShowCoeff();
+ break;
+ case 98: // b
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_A_Calib(command_consentration, 2);
+ USB.println(F("#b"));
+ ShowCoeff();
+ break;
+ case 99: // c
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_A_Calib(command_consentration, 3);
+ USB.println(F("#c"));
+ ShowCoeff();
+ break;
+ case 107: // k
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_B_Calib(command_consentration, 1);
+ USB.println(F("#k"));
+ ShowCoeff();
+ break;
+ case 108: // l
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_B_Calib(command_consentration, 2);
+ USB.println(F("#l"));
+ ShowCoeff();
+ break;
+ case 109: // m
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_B_Calib(command_consentration, 3);
+ USB.println(F("#m"));
+ ShowCoeff();
+ break;
+ case 110: // n
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_C_Calib(command_consentration, 1);
+ USB.println(F("#n"));
+ ShowCoeff();
+ break;
+ case 111: // o
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_C_Calib(command_consentration, 2);
+ USB.println(F("#0"));
+ ShowCoeff();
+ break;
+ case 112: // p
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_C_Calib(command_consentration, 3);
+ USB.println(F("#p"));
+ ShowCoeff();
+ break;
+ case 113: // q
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_D_Calib(command_consentration, 1);
+ USB.println(F("#q"));
+ ShowCoeff();
+ break;
+ case 114: // r
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_D_Calib(command_consentration, 2);
+ USB.println(F("#r"));
+ ShowCoeff();
+ break;
+ case 115: // s
+ delay(1000);
+ command_consentration = (float) USBGetLong();
+ USB.println(F("#?"));
+ Socket_D_Calib(command_consentration, 3);
+ USB.println(F("#s"));
+ ShowCoeff();
+ break;
+ case 102: // f
+ auxFVMajor = Utils.readEEPROM(addressFVMajor);
+ auxFVMinor = Utils.readEEPROM(addressFVMajor);
+ //USB.print(F("Имя устройства: "));
+ //USB.println(node_ID);
+ USB.print(F("#f|"));
+ //delay(1000);
+ //USB.println();
+ USB.print(node_ID);
+ USB.print("|");
+ ShowSerialNumber();
+ USB.print("|");
+ //USB.print(F("Версия прошивки: "));
+ USB.print(auxFVMajor);
+ USB.print(F("."));
+ //USB.println(auxFVMinor);
+ USB.print(auxFVMinor);
+ USB.print("|");
+ USB.print(check_md5);
+ USB.print("|");
+ USB.print(filename);
+ USB.println(F("|"));
+ break;
+ default:
+ //USB.println(F("Wrong command!"));
+ break;
+ }
+ }
+ }
+}
+
+long USBGetLong() {
+ char number[10];
+ int i = 0;
+ while (USB.available() > 0) {
+ number[i] = (char) USB.read();
+ i++;
+ }
+
+ long result = atol(number);
+ return result;
+}
+
+int USBGetInt() {
+ char number[10];
+ int i = 0;
+ while (USB.available() > 0) {
+ number[i] = (char) USB.read();
+ i++;
+ }
+
+ int result = atoi(number);
+ return result;
+}
+
+//------------------------------------------
+long FloatToLong(float val) {
+ long a = val * 1000;
+ return a;
+}
+
+float LongToFloat(long val1) {
+ float b = (float) val1/1000.0;
+ return b;
+}
+
+//запись в EEPROM данных типа long
+void EEPROMWriteLong(int address, long value) {
+ byte four = (value & 0xFF);
+ byte three = ((value >> 8) & 0xFF);
+ byte two = ((value >> 16) & 0xFF);
+ byte one = ((value >> 24) & 0xFF);
+
+ Utils.writeEEPROM(address, four);
+ Utils.writeEEPROM(address + 1, three);
+ Utils.writeEEPROM(address + 2, two);
+ Utils.writeEEPROM(address + 3, one);
+}
+
+//чтение из EEPROM данных типа long
+long EEPROMReadLong(int address1) {
+ long four = Utils.readEEPROM(address1);
+ long three = Utils.readEEPROM(address1 + 1);
+ long two = Utils.readEEPROM(address1 + 2);
+ long one = Utils.readEEPROM(address1 + 3);
+
+ return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
+}
+
+//--------------------------------------
+// калибровка датчика в сокете А, точка калибровки задается аргументом conc_temp, номер раствора задается аргументом concent_number
+void Socket_A_Calib(float conc_temp, int concent_number)
+{
+ float volts = 0.0;
+ concent_A_1 = LongToFloat(EEPROMReadLong(addr_concent_A_1));
+ concent_A_2 = LongToFloat(EEPROMReadLong(addr_concent_A_2));
+ concent_A_3 = LongToFloat(EEPROMReadLong(addr_concent_A_3));
+ float concent[] = {concent_A_1, concent_A_2, concent_A_3};
+ //float temp_volts_A_Cal[] = {0.0, 0.0, 0.0};
+ aux_A_p1 = EEPROMReadLong(addr_A_p1);
+ aux_A_p2 = EEPROMReadLong(addr_A_p2);
+ aux_A_p3 = EEPROMReadLong(addr_A_p3);
+ const float temp_volts_A[] = {LongToFloat(aux_A_p1), LongToFloat(aux_A_p2), LongToFloat(aux_A_p3)};
+ SensorSocketA.setCalibrationPoints(temp_volts_A, concent, 3);
+ for (int i = 0; i < counter; i++) {
+ SWIonsBoard.ON();
+ volts = SensorSocketA.read();
+ USB.print(F("^|"));
+ USB.print(i);
+ USB.print(F(" - "));
+ USB.println(volts);
+ SWIonsBoard.OFF();
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ if (concent_number == 1)
+ {
+ EEPROMWriteLong(addr_A_p1, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_A_1, FloatToLong(conc_temp));
+ const float temp_volts_A_Cal_10[] = {volts, LongToFloat(aux_A_p2), LongToFloat(aux_A_p3)};
+ const float temp_conc_A_Cal_10[] = {conc_temp, concent_A_2, concent_A_3};
+ SensorSocketA.setCalibrationPoints(temp_volts_A_Cal_10, temp_conc_A_Cal_10, 3);
+ }
+ else if (concent_number == 2)
+ {
+ EEPROMWriteLong(addr_A_p2, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_A_2, FloatToLong(conc_temp));
+ const float temp_volts_A_Cal_100[] = {LongToFloat(aux_A_p1), volts, LongToFloat(aux_A_p3)};
+ const float temp_conc_A_Cal_100[] = {concent_A_1, conc_temp, concent_A_3};
+ SensorSocketA.setCalibrationPoints(temp_volts_A_Cal_100, temp_conc_A_Cal_100, 3);
+ }
+ else if (concent_number == 3)
+ {
+ EEPROMWriteLong(addr_A_p3, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_A_3, FloatToLong(conc_temp));
+ const float temp_volts_A_Cal_1000[] = {LongToFloat(aux_A_p1), LongToFloat(aux_A_p2), volts};
+ const float temp_conc_A_Cal_1000[] = {concent_A_1, concent_A_2, conc_temp};
+ SensorSocketA.setCalibrationPoints(temp_volts_A_Cal_1000, temp_conc_A_Cal_1000, 3);
+ }
+ else
+ {
+ //const float temp_volts_A_Cal = {volts, volts, volts};//do nothing
+ }
+
+ //SensorSocketA.setCalibrationPoints(temp_volts_A_Cal, concent, 3);
+ if (debug == 1) {
+ USB.print(F("Калибровка датчика в сокете А для раствора с концентрацией "));
+ USB.print(conc_temp);
+ USB.println(" завершена.");
+ }
+}
+
+//--------------------------------------
+// калибровка датчика в сокете B, точка калибровки задается аргументом conc_temp, номер раствора задается аргументом concent_number
+void Socket_B_Calib(float conc_temp, int concent_number)
+{
+ float volts = 0.0;
+ concent_B_1 = LongToFloat(EEPROMReadLong(addr_concent_B_1));
+ concent_B_2 = LongToFloat(EEPROMReadLong(addr_concent_B_2));
+ concent_B_3 = LongToFloat(EEPROMReadLong(addr_concent_B_3));
+ float concent[] = {concent_B_1, concent_B_2, concent_B_3};
+ aux_B_p1 = EEPROMReadLong(addr_B_p1);
+ aux_B_p2 = EEPROMReadLong(addr_B_p2);
+ aux_B_p3 = EEPROMReadLong(addr_B_p3);
+ const float temp_volts_B[] = {LongToFloat(aux_B_p1), LongToFloat(aux_B_p2), LongToFloat(aux_B_p3)};
+ SensorSocketB.setCalibrationPoints(temp_volts_B, concent, 3);
+ for (int i = 0; i < counter; i++) {
+ SWIonsBoard.ON();
+ volts = SensorSocketB.read();
+ USB.print(F("^|"));
+ USB.print(i);
+ USB.print(F(" - "));
+ USB.println(volts);
+ SWIonsBoard.OFF();
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ if (concent_number == 1)
+ {
+ EEPROMWriteLong(addr_B_p1, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_B_1, FloatToLong(conc_temp));
+ const float temp_volts_B_Cal_10[] = {volts, LongToFloat(aux_B_p2), LongToFloat(aux_B_p3)};
+ const float temp_conc_B_Cal_10[] = {conc_temp, concent_B_2, concent_B_3};
+ SensorSocketB.setCalibrationPoints(temp_volts_B_Cal_10, temp_conc_B_Cal_10, 3);
+ }
+ else if (concent_number == 2)
+ {
+ EEPROMWriteLong(addr_B_p2, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_B_2, FloatToLong(conc_temp));
+ const float temp_volts_B_Cal_100[] = {LongToFloat(aux_B_p1), volts, LongToFloat(aux_B_p3)};
+ const float temp_conc_B_Cal_100[] = {concent_B_1, conc_temp, concent_B_3};
+ SensorSocketB.setCalibrationPoints(temp_volts_B_Cal_100, temp_conc_B_Cal_100, 3);
+ }
+ else if (concent_number == 3)
+ {
+ EEPROMWriteLong(addr_B_p3, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_B_3, FloatToLong(conc_temp));
+ const float temp_volts_B_Cal_1000[] = {LongToFloat(aux_B_p1), LongToFloat(aux_B_p2), volts};
+ const float temp_conc_B_Cal_1000[] = {concent_B_1, concent_B_2, conc_temp};
+ SensorSocketB.setCalibrationPoints(temp_volts_B_Cal_1000, temp_conc_B_Cal_1000, 3);
+ }
+ else
+ {
+ //const float temp_volts_B_Cal = {volts, volts, volts};//do nothing
+ }
+
+ //SensorSocketA.setCalibrationPoints(temp_volts_B_Cal, concent, 3);
+ if (debug == 1) {
+ USB.print(F("Калибровка датчика в сокете B для раствора с концентрацией "));
+ USB.print(conc_temp);
+ USB.println(" завершена.");
+ }
+}
+
+//--------------------------------------
+// калибровка датчика в сокете C, точка калибровки задается аргументом conc_temp, номер раствора задается аргументом concent_number
+void Socket_C_Calib(float conc_temp, int concent_number)
+{
+ float volts = 0.0;
+ concent_C_1 = LongToFloat(EEPROMReadLong(addr_concent_C_1));
+ concent_C_2 = LongToFloat(EEPROMReadLong(addr_concent_C_2));
+ concent_C_3 = LongToFloat(EEPROMReadLong(addr_concent_C_3));
+ float concent[] = {concent_C_1, concent_C_2, concent_C_3};
+ aux_C_p1 = EEPROMReadLong(addr_C_p1);
+ aux_C_p2 = EEPROMReadLong(addr_C_p2);
+ aux_C_p3 = EEPROMReadLong(addr_C_p3);
+ const float temp_volts_C[] = {LongToFloat(aux_C_p1), LongToFloat(aux_C_p2), LongToFloat(aux_C_p3)};
+ SensorSocketC.setCalibrationPoints(temp_volts_C, concent, 3);
+ for (int i = 0; i < counter; i++) {
+ SWIonsBoard.ON();
+ volts = SensorSocketC.read();
+ USB.print(F("^|"));
+ USB.print(i);
+ USB.print(F(" - "));
+ USB.println(volts);
+ SWIonsBoard.OFF();
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ if (concent_number == 1)
+ {
+ EEPROMWriteLong(addr_C_p1, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_C_1, FloatToLong(conc_temp));
+ const float temp_volts_C_Cal_10[] = {volts, LongToFloat(aux_C_p2), LongToFloat(aux_C_p3)};
+ const float temp_conc_C_Cal_10[] = {conc_temp, concent_C_2, concent_C_3};
+ SensorSocketC.setCalibrationPoints(temp_volts_C_Cal_10, temp_conc_C_Cal_10, 3);
+ }
+ else if (concent_number == 2)
+ {
+ EEPROMWriteLong(addr_C_p2, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_C_2, FloatToLong(conc_temp));
+ const float temp_volts_C_Cal_100[] = {LongToFloat(aux_C_p1), volts, LongToFloat(aux_C_p3)};
+ const float temp_conc_C_Cal_100[] = {concent_C_1, conc_temp, concent_C_3};
+ SensorSocketC.setCalibrationPoints(temp_volts_C_Cal_100, temp_conc_C_Cal_100, 3);
+ }
+ else if (concent_number == 3)
+ {
+ EEPROMWriteLong(addr_C_p3, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_C_3, FloatToLong(conc_temp));
+ const float temp_volts_C_Cal_1000[] = {LongToFloat(aux_C_p1), LongToFloat(aux_C_p2), volts};
+ const float temp_conc_C_Cal_1000[] = {concent_C_1, concent_C_2, conc_temp};
+ SensorSocketC.setCalibrationPoints(temp_volts_C_Cal_1000, temp_conc_C_Cal_1000, 3);
+ }
+ else
+ {
+ //const float temp_volts_C_Cal = {volts, volts, volts};//do nothing
+ }
+
+ //SensorSocketC.setCalibrationPoints(temp_volts_B_Cal, concent, 3);
+ if (debug == 1) {
+ USB.print(F("Калибровка датчика в сокете C для раствора с концентрацией "));
+ USB.print(conc_temp);
+ USB.println(" завершена.");
+ }
+}
+
+//--------------------------------------
+// калибровка датчика в сокете D, точка калибровки задается аргументом conc_temp, номер раствора задается аргументом concent_number
+void Socket_D_Calib(float conc_temp, int concent_number)
+{
+ float volts = 0.0;
+ concent_D_1 = LongToFloat(EEPROMReadLong(addr_concent_D_1));
+ concent_D_2 = LongToFloat(EEPROMReadLong(addr_concent_D_2));
+ concent_D_3 = LongToFloat(EEPROMReadLong(addr_concent_D_3));
+ float concent[] = {concent_D_1, concent_D_2, concent_D_3};
+ aux_D_p1 = EEPROMReadLong(addr_D_p1);
+ aux_D_p2 = EEPROMReadLong(addr_D_p2);
+ aux_D_p3 = EEPROMReadLong(addr_D_p3);
+ const float temp_volts_D[] = {LongToFloat(aux_D_p1), LongToFloat(aux_D_p2), LongToFloat(aux_D_p3)};
+ SensorSocketD.setCalibrationPoints(temp_volts_D, concent, 3);
+ for (int i = 0; i < counter; i++) {
+ SWIonsBoard.ON();
+ volts = SensorSocketD.read();
+ USB.print(F("^|"));
+ USB.print(i);
+ USB.print(F(" - "));
+ USB.println(volts);
+ SWIonsBoard.OFF();
+ delay(zadergka);
+ }
+ USB.print(F("^|finished"));
+ if (concent_number == 1)
+ {
+ EEPROMWriteLong(addr_D_p1, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_D_1, FloatToLong(conc_temp));
+ const float temp_volts_D_Cal_10[] = {volts, LongToFloat(aux_D_p2), LongToFloat(aux_D_p3)};
+ const float temp_conc_D_Cal_10[] = {conc_temp, concent_D_2, concent_D_3};
+ SensorSocketD.setCalibrationPoints(temp_volts_D_Cal_10, temp_conc_D_Cal_10, 3);
+ }
+ else if (concent_number == 2)
+ {
+ EEPROMWriteLong(addr_D_p2, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_D_2, FloatToLong(conc_temp));
+ const float temp_volts_D_Cal_100[] = {LongToFloat(aux_D_p1), volts, LongToFloat(aux_D_p3)};
+ const float temp_conc_D_Cal_100[] = {concent_D_1, conc_temp, concent_D_3};
+ SensorSocketD.setCalibrationPoints(temp_volts_D_Cal_100, temp_conc_D_Cal_100, 3);
+ }
+ else if (concent_number == 3)
+ {
+ EEPROMWriteLong(addr_D_p3, FloatToLong(volts));
+ EEPROMWriteLong(addr_concent_D_3, FloatToLong(conc_temp));
+ const float temp_volts_D_Cal_1000[] = {LongToFloat(aux_D_p1), LongToFloat(aux_D_p2), volts};
+ const float temp_conc_D_Cal_1000[] = {concent_D_1, concent_D_2, conc_temp};
+ SensorSocketD.setCalibrationPoints(temp_volts_D_Cal_1000, temp_conc_D_Cal_1000, 3);
+ }
+ else
+ {
+ //const float temp_volts_C_Cal = {volts, volts, volts};//do nothing
+ }
+
+ //SensorSocketC.setCalibrationPoints(temp_volts_B_Cal, concent, 3);
+ if (debug == 1) {
+ USB.print(F("Калибровка датчика в сокете D для раствора с концентрацией "));
+ USB.print(conc_temp);
+ USB.println(" завершена.");
+ }
+}
+
+void ShowSerialNumber() {
+ //USB.print(F("Serial ID:"));
+ USB.printHex(_serial_id[0]);
+ USB.printHex(_serial_id[1]);
+ USB.printHex(_serial_id[2]);
+ USB.printHex(_serial_id[3]);
+ USB.printHex(_serial_id[4]);
+ USB.printHex(_serial_id[5]);
+ USB.printHex(_serial_id[6]);
+ USB.printHex(_serial_id[7]);
+ //USB.println();
+ //delay(1000);
+}
+
+void ShowCoeff() {
+ cal_temp = LongToFloat(EEPROMReadLong(addr_cal_temp));
+// cal_point_10 = LongToFloat(EEPROMReadLong(addr_p10));
+// cal_point_7 = LongToFloat(EEPROMReadLong(addr_p7));
+// cal_point_4 = LongToFloat(EEPROMReadLong(addr_p4));
+ A_point1_V = LongToFloat(EEPROMReadLong(addr_A_p1));
+ A_point2_V = LongToFloat(EEPROMReadLong(addr_A_p2));
+ A_point3_V = LongToFloat(EEPROMReadLong(addr_A_p3));
+ concent_A_1 = LongToFloat(EEPROMReadLong(addr_concent_A_1));
+ concent_A_2 = LongToFloat(EEPROMReadLong(addr_concent_A_2));
+ concent_A_3 = LongToFloat(EEPROMReadLong(addr_concent_A_3));
+ B_point1_V = LongToFloat(EEPROMReadLong(addr_B_p1));
+ B_point2_V = LongToFloat(EEPROMReadLong(addr_B_p2));
+ B_point3_V = LongToFloat(EEPROMReadLong(addr_B_p3));
+ concent_B_1 = LongToFloat(EEPROMReadLong(addr_concent_B_1));
+ concent_B_2 = LongToFloat(EEPROMReadLong(addr_concent_B_2));
+ concent_B_3 = LongToFloat(EEPROMReadLong(addr_concent_B_3));
+ C_point1_V = LongToFloat(EEPROMReadLong(addr_C_p1));
+ C_point2_V = LongToFloat(EEPROMReadLong(addr_C_p2));
+ C_point3_V = LongToFloat(EEPROMReadLong(addr_C_p3));
+ concent_C_1 = LongToFloat(EEPROMReadLong(addr_concent_C_1));
+ concent_C_2 = LongToFloat(EEPROMReadLong(addr_concent_C_2));
+ concent_C_3 = LongToFloat(EEPROMReadLong(addr_concent_C_3));
+ D_point1_V = LongToFloat(EEPROMReadLong(addr_D_p1));
+ D_point2_V = LongToFloat(EEPROMReadLong(addr_D_p2));
+ D_point3_V = LongToFloat(EEPROMReadLong(addr_D_p3));
+ concent_D_1 = LongToFloat(EEPROMReadLong(addr_concent_D_1));
+ concent_D_2 = LongToFloat(EEPROMReadLong(addr_concent_D_2));
+ concent_D_3 = LongToFloat(EEPROMReadLong(addr_concent_D_3));
+
+ USB.print(F("#z|"));
+ USB.print(concent_A_1);
+ USB.print(F(" mg/L-"));
+ USB.print(A_point1_V);
+ USB.print(F(","));
+ USB.print(concent_A_2);
+ USB.print(F(" mg/L-"));
+ USB.print(A_point2_V);
+ USB.print(F(","));
+ USB.print(concent_A_3);
+ USB.print(F(" mg/L-"));
+ USB.print(A_point3_V);
+ USB.print(F("|"));
+ USB.print(concent_B_1);
+ USB.print(F(" mg/L-"));
+ USB.print(B_point1_V);
+ USB.print(F(","));
+ USB.print(concent_B_2);
+ USB.print(F(" mg/L-"));
+ USB.print(B_point2_V);
+ USB.print(F(","));
+ USB.print(concent_B_3);
+ USB.print(F(" mg/L-"));
+ USB.print(B_point3_V);
+ USB.print(F("|"));
+ USB.print(concent_C_1);
+ USB.print(F(" mg/L-"));
+ USB.print(C_point1_V);
+ USB.print(F(","));
+ USB.print(concent_C_2);
+ USB.print(F(" mg/L-"));
+ USB.print(C_point2_V);
+ USB.print(F(","));
+ USB.print(concent_C_3);
+ USB.print(F(" mg/L-"));
+ USB.print(C_point3_V);
+ USB.print(F("|"));
+ USB.print(concent_D_1);
+ USB.print(F(" mg/L-"));
+ USB.print(D_point1_V);
+ USB.print(F(","));
+ USB.print(concent_D_2);
+ USB.print(F(" mg/L-"));
+ USB.print(D_point2_V);
+ USB.print(F(","));
+ USB.print(concent_D_3);
+ USB.print(F(" mg/L-"));
+ USB.print(D_point3_V);
+ USB.print(F("|"));
+ USB.print(cal_temp);
+ USB.println(F("|"));
+
+// USB.println(cal_point_10);
+// USB.println(cal_point_7);
+// USB.println(cal_point_4);
+ if (debug == 1) {
+ USB.println(F("NH4: concent - volts"));
+ USB.print(concent_A_1);
+ USB.print(F(" - "));
+ USB.println(A_point1_V);
+ USB.print(concent_A_2);
+ USB.print(F(" - "));
+ USB.println(A_point2_V);
+ USB.print(concent_A_3);
+ USB.print(F(" - "));
+ USB.println(A_point3_V);
+ USB.println(F("NO3: concent - volts"));
+ USB.print(concent_B_1);
+ USB.print(F(" - "));
+ USB.println(B_point1_V);
+ USB.print(concent_B_2);
+ USB.print(F(" - "));
+ USB.println(B_point2_V);
+ USB.print(concent_B_3);
+ USB.print(F(" - "));
+ USB.println(B_point3_V);
+ USB.println(F("NO2: concent - volts"));
+ USB.print(concent_C_1);
+ USB.print(F(" - "));
+ USB.println(C_point1_V);
+ USB.print(concent_C_2);
+ USB.print(F(" - "));
+ USB.println(C_point2_V);
+ USB.print(concent_C_3);
+ USB.print(F(" - "));
+ USB.println(C_point3_V);
+ USB.println(F("Cl: concent - volts"));
+ USB.print(concent_D_1);
+ USB.print(F(" - "));
+ USB.println(D_point1_V);
+ USB.print(concent_D_2);
+ USB.print(F(" - "));
+ USB.println(D_point2_V);
+ USB.print(concent_D_3);
+ USB.print(F(" - "));
+ USB.println(D_point3_V);
+ USB.println(F("temp: concent - volts"));
+ USB.println(cal_temp);
+ }
+}
+
+void SensorData() {
+ USB.println(F("$measure"));
+ SWIonsBoard.ON();
+ //delay(2000);
+ ///////////////////////////////////////////
+ // 2. Read sensors
+ ///////////////////////////////////////////
+ value_temp = tempSensor.read();
+ // value_pH = pHSensor.read();
+ // value_pH_calculated = pHSensor.pHConversion(value_pH, value_temp);
+ // delay(500);
+ SOCK_A_Raw = SensorSocketA.read();
+ SOCK_A_Calc = SensorSocketA.calculateConcentration(SOCK_A_Raw);
+ if (debug == 1) {
+ USB.print(F("NH4 volts: "));
+ USB.print(SOCK_A_Raw);
+ USB.print(F(", value: "));
+ USB.println(SOCK_A_Calc);
+ }
+ delay(1500);
+ SOCK_B_Raw = SensorSocketB.read();
+ SOCK_B_Calc = SensorSocketB.calculateConcentration(SOCK_B_Raw);
+ if (debug == 1) {
+ USB.print(F("NO3 volts: "));
+ USB.print(SOCK_B_Raw);
+ USB.print(F(", value: "));
+ USB.println(SOCK_B_Calc);
+ }
+ delay(1500);
+ SOCK_C_Raw = SensorSocketC.read();
+ SOCK_C_Calc = SensorSocketC.calculateConcentration(SOCK_C_Raw);
+ if (debug == 1) {
+ USB.print(F("NO2 volts: "));
+ USB.print(SOCK_C_Raw);
+ USB.print(F(", value: "));
+ USB.println(SOCK_C_Calc);
+ }
+ delay(1500);
+ SOCK_D_Raw = SensorSocketD.read();
+ SOCK_D_Calc = SensorSocketD.calculateConcentration(SOCK_D_Raw);
+ if (debug == 1) {
+ USB.print(F("Cl volts: "));
+ USB.print(SOCK_D_Raw);
+ USB.print(F(", value: "));
+ USB.println(SOCK_D_Calc);
+ }
+ delay(500);
+ ///////////////////////////////////////////
+ // 3. Turn off the sensors
+ ///////////////////////////////////////////
+ SWIonsBoard.OFF();
+
+ USB.print("$i|");
+ USB.print(value_temp);
+ USB.print("|");
+ USB.print(SOCK_A_Calc);
+ USB.print("|");
+ USB.print(SOCK_B_Calc);
+ USB.print("|");
+ USB.print(SOCK_C_Calc);
+ USB.print("|");
+ USB.print(SOCK_D_Calc);
+ USB.print("|");
+ USB.print(PWR.getBatteryLevel(), DEC);
+ USB.print("|$");
+ USB.println();
+}