String... Переполнение строки?

georgiev-ruslan
Offline
Зарегистрирован: 31.10.2016

Доброго вечера! Итак, есть arduino uno v3 и ethernet shild. В него вставлена SD карта. Задача следующая: с аналоговых датчиков A1 (temperature), A2 (humidity) читать данные и преобразовав их в строку dataString, записать в текстовый файл на SD карте.... Результат вывести в serial monitor. В начале всё происходит хорошо: arduino читает значения с аналоговых пинов, записывает в txt, выводит в монитор... Но через некоторое время вместо значений и текста начинает выводится "кракозябра"... В файл также пишутся иероглифы... Скорее всего это происходит изза переполнения буфера строки... Но как очистить строку от мусора, возобновив нормальную работу скетча, не могу понять... Ребята, помогите пожалуйста разобраться. Заранее спасибо огромное за помощь.

 

#include <Ethernet.h>
#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;

#define SWITCH_TO_W5100 digitalWrite(4,HIGH); digitalWrite(10,LOW)
#define SWITCH_TO_SD digitalWrite(10,HIGH); digitalWrite(4,LOW)
#define ALL_OFF digitalWrite(10,HIGH); digitalWrite(4,HIGH)
 
File root;
EthernetClient client;
byte server[] = { 10,10,20,1 };
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip ( 10,10,20,1 );
 
void setup()
{
  SWITCH_TO_W5100;
  pinMode(4, OUTPUT);
  pinMode(10, OUTPUT);
  Serial.begin(9600);
  Ethernet.begin(mac,ip);
  Serial.println("Ethernet start");
  Serial.print("Initializing SD card...");
  SWITCH_TO_SD;
  pinMode(10, OUTPUT);
  if (!SD.begin(4)) Serial.println("initialization failed!");
  else Serial.println("initialization done.");
  ALL_OFF;
}
 
void loop()
{
  delay(3000);
  readPage();
}
 
void readPage()
{
Serial.println("connecting...");  //конектимся к серверу по 80 порту
  if (client.connect(server, 80)) Serial.println("connected");
client.stop();
 Serial.println("Disconnected");
 root = SD.open("/");
 if (!SD.begin(chipSelect)) {
        Serial.println("Card failed, or not present");
        return;
    }

  // создать строку для сборки данных в лог:
  String dataString = "";

  // прочитать два датчика и добавить данные к строке:
  
  {
    int sensor1 = analogRead(A1);
    int sensor2 = analogRead(A2);
    
    dataString += String("temperature") + ":" + String(sensor1) + "\n" + String ("humidity") + ":" + String(sensor2) + "\r"; // ключи переноса строки \r файл \n сериал порт
}
  // открыть файл. обратите внимание, что за раз может быть открыт только один файл,
  // поэтому вы должны закрыть его перед открытием другого.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // если файл доступен, то записать в него:
  if (dataFile) 
  {
    dataFile.println(dataString);
    dataFile.close();
    // вывести строку и в последовательный порт:
    Serial.println(dataString);
    Serial.flush();
  }
  // если файл не открыт, вывести сообщение об ошибке:
  else 
  {
    Serial.println("error opening datalog.txt");
  }
 Serial.println("done!");
 

}

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Скетч-то опубликуйте, посмотрим.

georgiev-ruslan
Offline
Зарегистрирован: 31.10.2016

вверху в шапке прикреплённый скетч :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ой, прошу прощения, не заметил за картинкой.

georgiev-ruslan
Offline
Зарегистрирован: 31.10.2016

Ничего страшного, я прям удивился, как это... вроде бы вставлял код и скрин... :) Вообщем, надеюсь кто нибудь поможет справиться с этими "кракозябрами" :)

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

Локалиуйте проблему. У вас в скетче и Ethernet, и SD. Закомментируйте пока всё лишнее, чтобы скетч просто опрашивал датчики и выводил их показания в Serial. После этого постепенно возвращайте функционал.

Densl
Offline
Зарегистрирован: 28.11.2018

45 строчка лишняя. Тем более вы читаете SD задолго до ее инициализации.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Со строками такое бувает, чо...

georgiev-ruslan
Offline
Зарегистрирован: 31.10.2016

убрал 45 строчку... и на всякий случай отформатировал флешку в обычный FAT (не FAT32)... Сбоев нет... Странно. Но действует. Спасибо! :) 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Зачем в строке 60 складывать в одну строку подстроки? Не проще ли просто последовательно писать в файл? Т.е. вместо:

 // создать строку для сборки данных в лог:
  String dataString = "";

  // прочитать два датчика и добавить данные к строке:
  
  {
    int sensor1 = analogRead(A1);
    int sensor2 = analogRead(A2);
    
    dataString += String("temperature") + ":" + String(sensor1) + "\n" + String ("humidity") + ":" + String(sensor2) + "\r"; // ключи переноса строки \r файл \n сериал порт
}
  // открыть файл. обратите внимание, что за раз может быть открыт только один файл,
  // поэтому вы должны закрыть его перед открытием другого.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // если файл доступен, то записать в него:
  if (dataFile) 
  {
    dataFile.println(dataString);
    dataFile.close();
    // вывести строку и в последовательный порт:
    Serial.println(dataString);
    Serial.flush();
  }

сделать нечто вроде этого:

void printInt(Stream& s, const char* message, int val)
{
	s.print(message);
	s.println(val);
} 
  
int sensor1 = analogRead(A1);
int sensor2 = analogRead(A2);

	
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if(dataTile)
{
	const char* message = "temperature:";
	printInt(dataFile,message,sensor1);
	printInt(Serial,message,sensor1);
	
	message = "humidity:";
	printInt(dataFile,message,sensor2);
	printInt(Serial,message,sensor2);

	
	dataFile.close();
}

И в файл выведется, и в Serial, работы с оперативкой - минимум.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

в документации не нашёл описание функции  printInt() - побайтовый вывод? А как реализуется форматирование текста?

Densl
Offline
Зарегистрирован: 28.11.2018

Ее и нет в документации. Смотри внимательнее код выше)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Densl пишет:

Ее и нет в документации. Смотри внимательнее код выше)

смотрел, не понял, то и спрашиваю

Densl
Offline
Зарегистрирован: 28.11.2018

Вот же она

void printInt(Stream& s, const char* message, int val)
{
    s.print(message);
    s.println(val);
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

е понял, то и спрашиваю

Ещё раз посмотрите. Строки с №1 по №5

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

ua6em пишет:

е понял, то и спрашиваю

Ещё раз посмотрите. Строки с №1 по №5

слона то я и не приметил )))
сбило с толку название ...я бы написал myPrint()

georgiev-ruslan
Offline
Зарегистрирован: 31.10.2016

DIYMan: После записи данных с аналоговых пинов в текстовый файл, необходимо будет передавать этот файл с SD карты на компьютер через ethernet по GET запросу. И уже обработав txt через C#, нарисовать график... Пока что подумываю, как это можно будет реализовать, гуглю возможные варианты.

sadman41
Offline
Зарегистрирован: 19.10.2016

Удивляют меня такие прожекты. В планах - создать супернужный девайс и покорить весь мир, но вот в первом же скетче String подставу делает.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Я бы сначала у ТС уточнил что важнее корректно данные отправить или на карту записывать, потом бы уже в скетче приоритеты расставлять, типа если данные не ушли, а на том конце сервер ну очень нужен, то отправлять до успеха, а на карту потом уже записывать.