Ваш модуль Bluetooth, вероятно, в порядке. Проблемы с производительностью, которые вы видите, более вероятны из-за реализации вашего протокола: А именно, символы s
находятся не там, где вы ожидаете их видеть. Для этого есть несколько причин, поэтому давайте go пройдем через них один за другим:
Значение ЭКГ
Обратите внимание, что возвращаемое значение analogRead()
в диапазоне от 0 до 1023 ( документы ), что соответствует диапазону от 0 В до Vref
. Если предположить, что Vref
равно 5 В, то выходной сигнал 3,3 В на ЭКГ приведет к тому, что analogRead()
вернет 675
. Таким образом, на практике ECG
, вероятно, колеблется от 0
до 675
. Вот почему у вас есть эта логика масштабирования c:
float Volt = (float)ECG*5.0/1023.0;
, которая преобразует показания AD C обратно в напряжение.
Точность логики масштабирования c
Если ECG
равно 5
, то Volt
будет 0.024437929
. Это противоречит вашему предположению, что Volt
всегда является четырехзначным числом с плавающей запятой, и это приводит к смещению ваших s
символов.
Проблемы Logcat
Пропущенные сообщения: это не из-за сбоя в вашем BT-соединении. Это потому, что вы получаете больше сообщений в один буфер, чем планировали. mmInStream.read(buffer)
попытается прочитать до 1024 байтов; это означает, что он может захватить несколько сообщений. Но если вы получаете несколько сообщений в своем буфере, вы обрабатываете только первое.
Поврежденные сообщения: например, s0.����
. Это связано с тем, что mmInStream.read(buffer)
читает только 3 байта, но вы предполагали, что он прочитал 5. Видите ли, read()
возвращает значение, как только у него есть хотя бы 1 новый доступный байт. Это не значит, что он прочитал все , что вы хотели. В этом случае последние 2 байта были унифицированы (0), но вы все равно пытались преобразовать их в String
.
Смещенные сообщения: по той же причине root как испорченные сообщения. Обратите внимание, что следующая строка в logcat - 15s0.
. Это потому, что 15-е сообщение (s0.15
) разбилось прямо посередине. Затем часть 16-го сообщения (s0.
) была добавлена в конец, потому что теперь ваше выравнивание отключено. Перестройка была восстановлена только (на следующей строке) из-за причуд в синхронизации сокетов.
Решение всех 3 из этих проблем состоит в том, чтобы убедиться, что read()
блокируется до тех пор, пока читает ровно 5 байтов (см. «Fix # 2»).
Fix # 1
Принудительно все преобразования строк приводят к получению ровно 4 символов ( docs ):
myBT.print("s"+String(Volt,2)); //2 decimal places works out to 4 characters total, for your input range.
Fix # 2
Убедитесь, что все чтения BT-сокета имеют длину ровно 5 байтов.
buffer = new byte[1024];
// Read from the InputStream
int totalRead = 0;
while(totalRead < 5)
{
bytes = mmInStream.read(buffer,totalRead,5-totalRead);
if(bytes==-1)
throw new IOException("EOS reached");
totalRead += bytes;
}
В качестве альтернативы, Вы можете использовать функцию, разработанную для этой цели, например DataInputStream.readFully () .
Fix # 3
По причинам, которые не являются Совершенно ясно, что отправленные сообщения имеют фиксированное смещение относительно полученных сообщений. Это может быть из-за проблемы с начальными условиями; Ваш Arduino может отправлять данные в модуль BT, не зная, подключен он или нет. Таким образом, в тот момент, когда соединение BT фактически происходит, оно начинает посылать в середине сообщения, а не в начале. Чтобы устранить эту проблему и восстановить выравнивание, я предлагаю использовать некоторый код, подобный следующему:
// Keep listening to the InputStream until an exception occurs
byte[] buffer;
int bytes = 0;
try {
while(mmInStream.read() != (byte) 's') //TODO: Handle "-1" case
{}
//Since we already read out the "s", we need to read 4 more bytes, to regain alignment.
mmInStream.read();
mmInStream.read();
mmInStream.read();
mmInStream.read();
//Now, the next byte read should be an "s".
} catch (IOException e) {
return;
}
while (true) {
(...)
После того, как эти исправления будут реализованы, вы можете избавиться от sleep()
в вашем приеме l oop, потому что read()
logi c блоков до получения необходимых данных . Кроме того, вместо обработки сообщений, только если первый байт равен s
, вы должны закрыть соединение , если это условие не выполняется (поскольку это указывает на то, что ваш партнер работает неправильно).
Примечание: я не проверял этот код, но он должен работать. Чтобы избежать подобных проблем в будущем, добавьте logi c, чтобы проверить больше ваших предположений . Например, на Arduino вы можете включить светодиод if(strlen(String(Volt))!=4)
. И если s
не там, где вы ожидаете, не игнорируйте проблему; выяснить почему .