#arduino #type-conversion #arduino-due
#arduino #преобразование типов #arduino-из-за
Вопрос:
Ценю ваше время.
Я пытаюсь преобразовать «String», считываемую с последовательного порта в serialEvent () Arduino IDE, в целочисленные значения с точным представлением.
Например, если String myString = 200, то int myInt должно быть 200.
Я был несколько успешным, но не смог преобразовать String в точное представление int за пределами 255.
Решения, которые я пробовал:
1) используется .Функция toInt() в Arduino.
2) использовались функции «atoi» и «atol».
3) Serial.parseInt() в loop().
Все эти методы начинают пересчет с 0 после каждых 255 значений.
Я не могу использовать parseInt, поскольку он работает только внутри loop (). Моему приложению требуется постоянно сохранять значение переменной до тех пор, пока через порт не будет передано другое значение. Для этого использовалась флэш-память Arduino Due.
Код хранения в памяти, похоже, работает только внутри serialEvent().
Фрагмент кода выглядит следующим образом:
#include <stdlib.h>
#include <DueFlashStorage.h>
DueFlashStorage memory;
String x = " ";
int x_size;
int threshold;
void setup(){
Serial.begin(115200);
}
void loop{
Serial.println(memory.read(0));
}
void serialEvent(){
while(Serial.available()){
x = Serial.readStringUntil('n');
x_size = x.length();
char a[x_size 1];
x.toCharArray(a, x_size 1);
threshold = atoi(a);
memory.write(0, threshold);
}
}
Ответ №1:
1) Функция .toInt() возвращает LONG, и вы хотите INT (честно говоря, я не знаю почему, но это есть в документации)… вам нужно преобразовать это следующим образом (попробовал на Arduino ATMEGA, и это сработало):
#include <stdlib.h>
String x = "1000";
int x_ = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
x_ = (int) x.toInt();
Serial.println(x_);
delay(1000);
}
2) Я не профессионал… но serilEvent () — это действительно старый способ ведения дел, и использовать его не рекомендуется. Вы можете сделать это «вручную» в функции loop().
Комментарии:
1. Привет, я пробовал это. Основная проблема заключается в том, что все методы приведения / преобразования, похоже, имеют ограничение от 0 до 255. После 255 точное представление числовой строки в integer или long не возвращается. Изначально я пытался запустить код в loop (), только позже я перешел к serialEvent (), который, похоже, лучше справляется с чтением значений из последовательного порта в этом коде. Спасибо. Дайте мне знать, если у вас есть какие-либо другие предложения.
2. Даже Serial.parseInt() не выходит за пределы 255.
Ответ №2:
Вы конвертируете только 1 символ за раз, поэтому ограничение равно 255. Если вы больше ничего не делаете, вы могли бы оставаться в цикле serial.read до тех пор, пока все символы не будут прочитаны. Например:
void loop() {
if(Serial.available()) {
byte count = 0;
char number[10]; // determine max size of array
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == 'n') {
wait = false; // exit while loop
}
count ;
}
}
int threshold = atoi(number);
memory.write(0, threshold);
}
}
Комментарии:
1. Пробовал. Напечатаны как массив символов «number», так и форма int «threshold». То же самое. Напечатанное число правильное, но пороговое значение имеет ограничение 255. Спасибо за предложение.
2. Проблема не в преобразовании: если бы вы добавили
Serial.println(threshold);
, вы бы увидели весь int. НО:memory.write(0, threshold);
записывает (и считывает!) только 1 байт. Смотрите это , как читать и сохранять более 1 байта.3. Согласен. В памяти хранится только один байт, но, как я уже упоминал, я также пробовал использовать «Serial.println (threshold)». Это не сработало. Но можно попробовать еще раз. Будет обновляться.
Ответ №3:
Из-за отсутствия в Arduino IDE хорошей функции для преобразования типа char / String в тип int (имеет ограничение 255), я написал свой собственный код преобразования, который, кажется, работает отлично.
int finalcount=0;
void setup(){
Serial.begin(115200);
}
void loop(){
if(Serial.available()) {
int count = 0;
char number[5]; // determine max size of array as 5
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == 'n') {
finalcount = count; //max array size for integer; could be less than 5
wait = false; // exit while loop
}
count ;
}
}
int val[finalcount]; //array size determined for integer
int placeValue;
int finalval[finalcount];
int temp=0;
int threshold;
for(int i = 0; i<finalcount; i ){
val[i] = (int)number[i]-48; //convert each char to integer separately
placeValue = pow(10,(finalcount-1)-i); //calculate place value with a base of 10
finalval[i] = val[i]*placeValue; //update integers with their place value
temp = finalval[i] ; //add all integers
threshold = temp; //resulting number stored as threshold
}
Serial.println(threshold); //prints beyond 255 successfully !
}
}
Ответ №4:
Я решил проблему, используя высокобайтовые и низкобайтовые функции Arduino. Работает безупречно.
#include <DueFlashStorage.h>
DueFlashStorage m;
byte a1,a2;
int val;
void setup() {
Serial.begin(115200); //start the serial communication
}
void loop()
{
if (Serial.available()>0)
{
val = Serial.parseInt(); //read the integer value from series
if(val>0){
a1 = highByte(val); //get the higher order or leftmost byte
a2 = lowByte(val); //get the lower order or rightmost byte
m.write(0,a1); //save in arduino due flash memory address 0
m.write(1,a2); //save in arduino due flash memory address 1
}
int myInteger;
myInteger = (m.read(0)*256) m.read(1); //convert into the true integer value
Serial.println(myInteger);
}