Появляется вторая запятая после числа с запятой, кто сталкивался?
- Войдите на сайт для отправки комментариев
Ср, 11/10/2017 - 10:25
Здравствуйте.
В своём проекте использую Arduino Nano и АЦП HX711.
Использую числа и значения типа float.
Программа работает нормально, в терминале выводит число с двумя разрядами после запятой, например: "123.00".
Потом, через некоторое время в конце числа с запятой появляется еще одно число с запятой и еще два числа после неё, которые не меняются, например: "123.001.30", последнее значение в конце "1.30" не изменяется, хотя само число, которое в начале изменяется, то есть как бы добавляется вот этот остаток "1.30", а так всё нормально.
Если сделать сброс, то всё восстанавливается и снова показывает число с двумя знаками после запятой.
Что можно сделать, как это вылечить?
Код приложите, а то как то видно плохо строки с 15 по 25
Пример "неправильного" вывода, плииз
Схема на базе этого:

Пояснение к коду:
К этому подключен АЦП HX711, конфигурируется, настраивается UDP порт на приём 4220 и два UDP порта на передачу, 4020 и 4120. IP адрес получает автоматически, также предусмотрено включение конфигурации статического адреса. При старте считываются калибровоные значения, значение деления и значение смещения. В цикле частотой 0.25 сек. измеряется вес и оправляется на IP адрес 192,168,182,250 на порт 4120 и с частотой 1 сек. отправляется на тот-же адрес на порт 4020. И слушает порт 4220, чтобы принимать команды управления. При поступлении команд, выполняются операции изменения калибровочного значения, делителя и смещения шкалы и записываются в EEPROM.
Из всего сказанного, делаем смелый вывод что указанный "в терминале выводит" некое устройство, а в Serial все выводит правильно. Так? Тогда ищите в терминале.Для очистки совести проконтрольте что уходит в передачу в 141 и 154
Пример "неправильного" вывода, плииз
Пример неправильного вывода:
26.51.23
19.45.23
26.43.23
23.68.23
22.77.23
Вывод после сброса:
23.54
26.51
21.85
17.05
25.02
Из всего сказанного, делаем смелый вывод что указанный "в терминале выводит" некое устройство, а в Serial все выводит правильно. Тогда ищите в терминале.Для очистки совести проконтрольте что уходит в передачу в 141 и 154
Проверял данные, которые присылает по Ethernet и в терминале COM порта через USB, всё одинаково. Менял даже платы разные, эффект один и тот-же.
Ну для меня это не проблема, я на сервере всёравно это число парсю и округляю до двух чисел после запятой, пришлось это сделать. Но например у меня есть датчик на базе ESP8266, там вроде такого нет, чтобы появлялась еще одна запятая, но бывает увеличивается число разрядов после запятой, но точно не могу сказать, нужно проверить еще раз.
Ну а с ARDUINO просто уже чисто спортивный интерес возник, хотелось бы разобраться и всё выяснить, не грозит ди это еще одной проблемой, чтобы потом в самый не подходящий момент не произошел аврал.
Нужно будет поинтересоваться еще не страдают ли таким промышленные контроллеры, может быть это нормальное явление с float числами.
del
А если в районе 50 строки вставить
data[len]=0;
;)
[q]
может быть это нормальное явление с float числами.
[/quote]
float тут не при чем. Где-то со строками нахомутали
Проверял данные, которые присылает по Ethernet и в терминале COM порта через USB, всё одинаково.
Одинаково что? неправильный вывод?
Добавьте в 141 (154) вывод в Serial cstr (cstr1)
Проверял данные, которые присылает по Ethernet и в терминале COM порта через USB, всё одинаково.
Одинаково что? неправильный вывод?
Добавьте в 141 (154) вывод в Serial cstr (cstr1)
Да, неправильный вывод со временем появляется везде и по сети и в сом порту, после сброса, всё востанавливается, начинает выводить правильно.
Вывод в сериал мне не нужен, потому, что мне нужно то, что он отсылает в сеть. Вывод в сериал я добавлял, когда таестировал логику работы, как только всё стало работать, я удалил эти строки из кода. Думаю зачем он зря будет в сериал еще выводить?
Да, я понял, только дошло, сейчас проверю. Но искажается уже в переменной w2.
Сейчас наверно переароверю все переменные наверно, выведу их все и посмотрю...
Да, неправильный вывод со временем появляется везде и по сети и в сом порту, после сброса, всё востанавливается, начинает выводить правильно.
сейчас у Вас вывод в сом только в коллбеке. А надо проверить, что именно отдаем на передачу. Хотя дело то Ваше.
А если в районе 50 строки вставить
data[len]=0;
;)
Ну я не думаю, что это поможет, потому что эта функция практически не работает, за всё время когда начало искажаться число эта функция ниразу не сработала, но думаю, что попробую её вообще вырезать и посмотреть, спасибо за идею.
Но искажается уже в переменной w2.
Да ладно!!!! float не может быть с двумя дробными частями :)
Я бы от String избавился напрочь для начала и попробовал изобразить что-то из этих запчастей:
PS. Правда, я float избегать пытаюсь в 98% случаев, а для конвертации псевдофлоата в char[] у меня своя функция...
сейчас у Вас вывод в сом только в коллбеке. А надо проверить, что именно отдаем на передачу. Хотя дело то Ваше.
Ну я выводил только в сериал только переменную w2 и смотрел что происходит, сравнивал с монитором который через сеть. Тоесть w2 передаётся уже искаженной.
Вторая переменная, которая отсылается раз в секунду, вроде нормально присылается, только что смотрел записи в базе данных, там нормально всё, хотя не факт, сама база данных может это число исправлять.
Так что наверно буду сейчас проверять на всех этапах и отключать по очереди функции и смотреть, что будет.
Спасибо, вы меня хоть оживили немного, а то я вообще тут немного зашился)
Спасибо, вы меня хоть оживили немного, а то я вообще тут немного зашился)
Та да, при отладке в одиночку бывает в такой тупизм попадаю... а вот если даже "чайник" рядом, начинаешь ему рассказывать и тут же все находится.
кто-то тебе в строке терминальный \0 затираеть
Да и вообще - вычисляли бы на стороне сервера свои дробные числа. Ардуине бы попроще было и вам тоже.
Да и вообще - вычисляли бы на стороне сервера свои дробные числа. Ардуине бы попроще было и вам тоже.
Вы имеете в виду на сервак отправлять RAW значение из функции scale.read()?
В принципе хорошая идея, нужно подумать.
А не подскажите scale.read() это int или float?
А как тогда получается float из RAW значения или float считывается функцией scale.get_units()?
А не подскажите scale.read() это int или float?
А как тогда получается float из RAW значения или float считывается функцией scale.get_units()?
HX711.h:
Romhik, по-моему все дело в элементарной ошибке. Если я правильно прочитал описание, функция String.toCharArray() не добавляет к полученной строке нулевой терминатор.
Вставте на строку 141 вот такой оператор и будет вам счастье:
cstr1[str1.length()] = '\0';
Если перед неправильным выводом был правильный типа "12345.23", то b707 прав.
Ааааа... ну тут же суржик :) Все дружно смотрим String.c_str()
Romhik, по-моему все дело в элементарной ошибке. Если я правильно прочитал описание, функция String.toCharArray() не добавляет к полученной строке нулевой терминатор.
Вставте на строку 141 вот такой оператор и будет вам счастье:
cstr1[str1.length()] = '\0';
Да, похоже что так оно и есть, но я уже понял свою ошибку, что нужно перед записью в массив, его очищать, похоже что просто там остаются числа от предыдущей записи.
Еще на одном форуме только что прочитал, что с массивами такое может быть, если массив больше, чем передаваемые в него значения, то там всё что угодно може быть в конце.
Ну как минимум есть два решения. Честно говоря еще не сталкивался на практике до этого на ардуино, на компьютерах еще такой проблемы не возникало...
Ну как минимум есть два простых решения это очистка массива перед записью в него новых значений и добавление в конец данных \0
кто-то тебе в строке терминальный \0 затираеть
Ух какой злой кот!)))) Да, Вы правы!)
И последний вопрос, как обнулить или очистить быстро string array, то есть массив строк cstr1?
Что-то не могу найти быстрое решение пока.
И последний вопрос, как обнулить или очистить быстро string array, то есть массив строк cstr1?
Что-то не могу найти быстрое решение пока.
memset(buffer, 0x00,
sizeof
(buffer))
Так пойдёт?
memset(buffer, 0x00,
sizeof
(buffer))
Спасибо!
Так пойдёт?
Лучше все позиции в массиве забить нулями '\0'
А вообще - имея дело с символьными массивами, совершенно не обязательно их полностью чистить, достаточно записывать нулевой байт в конце.
А вообще - имея дело с символьными массивами, совершенно не обязательно их полностью чистить, достаточно записывать нулевой байт в конце.
Для этого нужно strlen не забыть вычислить или еще как конец отследить, а так сразу зачпекал нулями и не переживаешь на этот счет.
Для этого нужно strlen не забыть вычислить или еще как конец отследить, а так сразу зачпекал нулями и не переживаешь на этот счет.
А если строка пишется в массив в цикле - как у автора? На каждой итерации весь буфер заново нулями забивать? Неужели так трудно вычислить длину строки, которую только что сам и создал? :)
Лучше все позиции в массиве забить нулями '\0'
А вообще - имея дело с символьными массивами, совершенно не обязательно их полностью чистить, достаточно записывать нулевой байт в конце.
В конце записываемых данных в массив или вообще в самый последний байт массива. Размер массива известен мне.
То есть, чтобы его очистить достаточно записать:
Так?
А если строка пишется в массив в цикле - как у автора? На каждой итерации весь буфер заново нулями забивать? Неужели так трудно вычислить длину строки, которую только что сам и создал? :)
Да я вообще не особо вчитывался в эту адскую смесь со String и Ethercard. stlren() все равно бежит по массиву, так же как и memset(), так что оверхед небольшой на помещение 0x00 в ячейку, а перфекционизм удовлетворен. Я и так и сяк пользуюсь.
А если строка пишется в массив в цикле - как у автора? На каждой итерации весь буфер заново нулями забивать? Неужели так трудно вычислить длину строки, которую только что сам и создал? :)
У меня сейчас так и сделано, правда один раз выскочила вторая запятая, без подключенного АЦП, потом сбросил и всё пропало, сейчас уже долго показывает нормально.
Если всё нормально будет, то оставлю так, если снова приклеится вторая запятая, то попробую очищать весь массив.
В конце записываемых данных в массив или вообще в самый последний байт массива. Размер массива известен мне.
То есть, чтобы его очистить достаточно записать:
Так?
неправильно - в конце записываемых данных.
Я вам строчку уже давал.
неправильно - в конце записываемых данных.
Я вам строчку уже давал.
У меня выдаёт ошибку:
exit status 1
cannot convert 'String' to 'void*' for argument '1' to 'void* memset(void*, int, size_t)'
Наверно я не понял как этой функцией пользоваться, пойду курить мануалы...
Что-то вы то за str1 , то за cstr1 хватаетесь.
...лучше поймите, что String class вам тут все карты путает - вы то туда, то сюда. Имхо - связались с Ethercard - используйте везде char[].
М-да уж), сбивают с толку все эти преобразования, да и сам себя запутал, взял строку вместо массива)))
Пора отдыхать)
Спасибо!
Этот код работает.
Нужно действительно всё на массив переделать, спасибо еще раз!
Здравствуйте, всё хорошо работает, прошли сутки, нареканий нет!
У меня остался еще один вопрос к ГУРУ, не подскажите, что означает последняя цифра "10" в этой строке:
Работает одинаково как с цифрой 10, так и без неё.
Заранее спасибо.
в том виде, как написано это означает: "присвоить переменной units значение функции scale.get_units(). И 10."
примерно так.
https://msdn.microsoft.com/ru-ru/library/zs06xbxh.aspx
в том виде, как написано это означает: "присвоить переменной units значение функции scale.get_units(). И 10."
примерно так.
Понял, значит мне "10" здесь вообще не нужно насколько я понял, потому что я взял эту строку отсюда:
Я ничего не усредняю, потому что происходит сильная задержка из-за этого усреднения...
дак и в 6 строке ничего не усредняется. Переменная units делится на 10, результат отбрасывается.
дак и в 6 строке ничего не усредняется. Переменная units делится на 10, результат отбрасывается.
Тогда не понятно к чему здесь второй оператор, 10?))) Шоб был?))) Для красоты?)))
просто рядом стоит
усреднение вот:
просто рядом стоит
И ничего не делает?
Так может его убрать?
Или пусть живёт?))
можно убрать
исправлю, кста