Запись данных из Serial porta на SD карту

lexs713
Offline
Зарегистрирован: 13.08.2015

Доброго времени суток!

ОЧЕНЬ ОЧЕНЬ нужна Ваша помощь.

Делаю диплом, точнее пытаюсь :) . В общем идея такова. Будет программа на Androide, которая будет отсылать данные по Bluetooth на Arduino, а он в свою очередь полученные данные будет записавать на SD карту в файл .csv. Надо будет отправить всего два поля Имя и телефон.

Подключить SD карту удалось, из кода программы так же удалось произвести запись и чтение.

Так же удалось реализовать запись отправленных данных из Монитора порта и Блютуза, но есть большое одно НО, отправленные данные, например амя разбивается на символы. Например я ввожу Anna, а запись происходит каждой буквы на отдельную строчку.

A

n

n

a

Прошу помочь и подсказать, как произвести запись введенных данных полностью в одну строку.

/*Тест записи на карту по блютуз (из монитор порта)*/
// Если есть данные на порту
 if (Serial.available() > 0) {
          char incomingByte = ' ';
          incomingByte = Serial.read(); 
          myFile = SD.open("baza.csv", FILE_WRITE);
          if(myFile)
          {
              myFile.println(incomingByte);
              myFile.close();
              Serial.println(incomingByte);
            }
            else
            {
              Serial.println("Net vozmojnosti otkryt kartu");
              }
          delay(200);
 }
/*Конец теста*/
vde69
Offline
Зарегистрирован: 10.01.2016

myFile.print(incomingByte);

lexs713
Offline
Зарегистрирован: 13.08.2015

vde69, Спасибо, но этот метод обсалютно все строки записывает в одну, которые передаются после.

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

vde69
Offline
Зарегистрирован: 10.01.2016

так ты отправляй точку с запятой в порт и будет счастье....

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

lexs713 пишет:

vde69, Спасибо, но этот метод обсалютно все строки записывает в одну, которые передаются после.

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

Если ответите на простой вопрос - как ардуина может предсказать, что вот очередной полученный символ - последний в строке, и надо записать в файл перевод строки, то я вам подскажу, как это сделать.

Суть улавливаете? Ардуина не гадалка, она не знает, чего там может придти в следующую минуту. Пришёл символ - получили, записали. Пришло сразу пять символов - вычитали их в цикле, записали в файл. Где в этом колхозе место предсказаниям, что после очередного символа начинается новая строка или, того хуже, новая ячейка данных?

Вам уже подсказали: шлите то, что нужно записать в файл, и в файл это запишется: нужен перевод строки - шлите \r\n, нужен разделитель полей - шлите точку с запятой, например. Если не хотите так слать - шлите другие спецсимволы: вам в _любом_ случае надо дать понять принимающей стороне, что вы от неё хотите.

Так что самый расово верный вариант - это тупо слать то, что хотим записать в файл, не мучая ардуино непосильной для неё работой в виде угадывания погоды на послезавтра.

lexs713
Offline
Зарегистрирован: 13.08.2015

DIYMan Я обратился за помощью, потому что знаю, что сдесь умные люди сидят. А я в программировании далеко не силен.

Вы хорошо в тексте подсказали, а сам код подскажите пожалуйста.

lexs713
Offline
Зарегистрирован: 13.08.2015

vde69 пишет:

так ты отправляй точку с запятой в порт и будет счастье....

) Если точку с запятой отправляю, то она так же пишется после каждого символа. Нет счастья (

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

Нет, это вы свой код покажите - что там пишется после каждого символа. Ещё раз: отсылайте на ардуино то, что нужно писать: послали с андроида строку "Anna;" - она и попадёт в файл, побайтово. Послали "\r\n" - перевод строки попадёт в файл. В том коде, который вы привели изначально - ничего дописывать не надо, меняйте код отсыла данных на ардуину.

lexs713
Offline
Зарегистрирован: 13.08.2015

Решил обойтись только вводом символов определенной длинны с помощью Serial.readBytes,  имя не буду вводить.

Теперь появился новый вопрос, как можно сравнить данные с SD карты из файла с вновь введенными данными в монитор порта?

Типа, вы уже такой номер вводили ранее.

#include <SD.h> //Библиотека SD карты
int CSpin = 4;
File myFile; // файл
char incomingBytes[8]; //Новый идентификатор 7-и значный


void setup() {
  // инициализация последовательного порта
  Serial.begin(9600);
  Serial.println("Soedinenie gotovo");
  pinMode(CSpin, OUTPUT); // SD пин выход
  // Проверка SD карты
   if(!SD.begin(CSpin))
  {
    Serial.print("Karta ne dostupna");
    return;
    }
    Serial.println("Karta gotova");
}

void loop() {

 if (Serial.available() > 0) {
   int newid;  
    newid = Serial.read();
    // Вызов функции записи на SD карту
    if (newid == 'H') {
     zapis();
    }
    // Вызов функции чтения
     else if (newid == 'L') {
     chtenie();
    }
  }
}

// Запись на SD карту 
void zapis(){
    Serial.println("K zapisi gotov");
    while (!Serial.available()) {
     if (Serial.available()>0){
        Serial.readBytes(incomingBytes, 7);
        Serial.println(incomingBytes);
          myFile = SD.open("baza.csv", FILE_WRITE);
          if(myFile)
          {
              myFile.println(incomingBytes);
              myFile.close();
              Serial.println("Identifikator dobavlen");
              return;
            }
            else
            {
              Serial.println("Net vozmojnosti otkryt kartu");
              return;
              }
     } 
   }
  }
// считываем все данные из файла baza.csv:
void chtenie(){
  myFile = SD.open("baza.csv");
  if (myFile) {
  while (myFile.available()) {
  Serial.write(myFile.read());
  }
  // закрываем файл:
  myFile.close();
  } else {
  // если файл не открылся, отображаем сообщение об ошибке:
  Serial.println("Oshibka baza.csv");
  }
}

 

vde69
Offline
Зарегистрирован: 10.01.2016

это невозможно, причина простая и уже три раза прозвучала в теме...

ардуино не умет выделять из произвольного потока номер... пример:

файл содержит - 14350009655323 , определи вводил я 35 или нет? может я вводил 1, 43, 500,0.... а может 14,35,500

подумайте над этим... тут есть 2 пути

1. разделители полей (о чем тут говорили уже)

2. типизированый файл (строго говоря мы любой знаем какой фиксированой длинны вводились номер, например все номера по 2 байта)

lexs713
Offline
Зарегистрирован: 13.08.2015

Да там номера все будит одинаковой длинны, по 7 символов.

В файле хранится каждый номер на новой строке.

Я и хочу вытащить все числа из файла и поместить их в массив и только после сравнить массив с вновь введеными данными.

Подскажите пожалуйста ка поместить данные из файла в массив?

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

lexs713 пишет:

Я и хочу вытащить все числа из файла и поместить их в массив и только после сравнить массив с вновь введеными данными.

Подскажите пожалуйста ка поместить данные из файла в массив?

Неправильный подход - в случае большого файла оперативки не хватит, и тогда - фьють. На МК не стоит мыслить категориями больших компьютеров. То, что вы хотите сделать, решается по-другому: просто пробегается последовательно по всем записям в файле, вычитывается очередная запись, сравнивается с нужным значением. Если сравнение удовлетворяет условию - вываливаемся из цикла чтения и дальше не читаем.

Псевдокод, читает по 7 байт за раз и сравнивает с переданным номером:


bool IsRecordExist(const char* number)
{
	static char buff[8] = {0}; // буфер для номеров в 7 символов на одну запись
	
	File f = SD.open("file.data",FILE_READ); // открываем файл на чтение
	while(!EndOfFile(f)) // EndOfFile - функция, которая проверяет на то, что достигнут конец файла
	{
		int readed = f.read(buff,7); // читаем очередные 7 символов
		buff[readed] = 0; // добавляем завершающий 0
		if(!Compare(buff,number)) // Compare возвращает 0, если строки равны. Можно юзать strcmp, например.
		{
			f.close();
			return true;
		}
	}
	
	f.close();
	return false;
}

Прошу обратить внимание - это ПСЕВДОКОД, а не рабочий - чтобы потом не возникало вопросов "почему не компилируется?". Дана логика, реализация - на ваше усмотрение.

lexs713
Offline
Зарегистрирован: 13.08.2015

DIYMan, спасибо, буду пробывать.

lexs713
Offline
Зарегистрирован: 13.08.2015

DIYMan пишет:

lexs713 пишет:

Я и хочу вытащить все числа из файла и поместить их в массив и только после сравнить массив с вновь введеными данными.

Подскажите пожалуйста ка поместить данные из файла в массив?

Неправильный подход - в случае большого файла оперативки не хватит, и тогда - фьють. На МК не стоит мыслить категориями больших компьютеров. То, что вы хотите сделать, решается по-другому: просто пробегается последовательно по всем записям в файле, вычитывается очередная запись, сравнивается с нужным значением. Если сравнение удовлетворяет условию - вываливаемся из цикла чтения и дальше не читаем.

Псевдокод, читает по 7 байт за раз и сравнивает с переданным номером:

bool IsRecordExist(const char* number)
{
	static char buff[8] = {0}; // буфер для номеров в 7 символов на одну запись
	
	File f = SD.open("file.data",FILE_READ); // открываем файл на чтение
	while(!EndOfFile(f)) // EndOfFile - функция, которая проверяет на то, что достигнут конец файла
	{
		int readed = f.read(buff,7); // читаем очередные 7 символов
		buff[readed] = 0; // добавляем завершающий 0
		if(!Compare(buff,number)) // Compare возвращает 0, если строки равны. Можно юзать strcmp, например.
		{
			f.close();
			return true;
		}
	}
	
	f.close();
	return false;
}

Прошу обратить внимание - это ПСЕВДОКОД, а не рабочий - чтобы потом не возникало вопросов "почему не компилируется?". Дана логика, реализация - на ваше усмотрение.

 

Добрый день!

У меня не получилось ( EndOfFile - выдает ошибку при компеляции.  Я толь учусь программировать.  DIYMan помогите пожалуйста, с меня вознаграждение ))) Идея на данный момент такова. Я включаю монитор порта, вводя определенную букву, выполняются определенные команды. H - записать новый идентификатор, L - считать все идентификаторы, V - проверить на уникальность (это и не получается).

#include <SD.h> //Библиотека SD карты
#include <SPI.h>
char incomingBytes[8]; //Новый идентификатор 7-и значный
int CSpin = 4;
File myFile; // файл


void setup() {
  // инициализация последовательного порта
  Serial.begin(9600);
  pinMode(CSpin, OUTPUT); // SD пин выход
  // Проверка SD карты
   if(!SD.begin(CSpin))
  {
    Serial.print("Net svjzi s modulem SD");
    return;
    }
    else {
    Serial.println("Modul SD podkluchen");
    }

}
void loop() {
      
      if (Serial.available() > 0) {
                 int newid;  
                 newid = Serial.read();
                 // Вызов функции записи на SD карту
                  if (newid == 'H') {
                  Serial.println("===Zapis===");  
                   zapis();
                  }
                  // Вызов функции чтения
                   else if (newid == 'L') {
                    Serial.println("===Chtenie===");
                   chtenie();
                  }  
                  else if (newid == 'V') {
                    // Сравнение введенного значения 
                  }
              }  
}

/* Начала кода от DIYMan */
bool IsRecordExist(const char* number)
{
    boolean EndOfFile = false;
  static char buff[8] = {0}; // буфер для номеров в 7 символов на одну запись
  
  myFile = SD.open("baza.csv",FILE_READ); // открываем файл на чтение
  while(!EndOfFile(myFile)) // EndOfFile - функция, которая проверяет на то, что достигнут конец файла
  {
    int readed = myFile.read(buff,7); // читаем очередные 7 символов
    buff[readed] = 0; // добавляем завершающий 0
    if(!Compare(buff,number)) // Compare возвращает 0, если строки равны. Можно юзать strcmp, например.
    {
      myFile.close();
      return true;
    }
  }
  
  myFile.close();
  return false;
}
/* Конец кода от DIYMan */

// Запись на SD карту 
void zapis(){
    Serial.println("Podkluchenie k SD karte");
    while (!Serial.available()) {
     if (Serial.available()>0){
        Serial.readBytes(incomingBytes, 7);
        Serial.println(incomingBytes);
          myFile = SD.open("baza.csv", FILE_WRITE);
          if(myFile)
          {
              myFile.println(incomingBytes);
              myFile.close();
              Serial.println("Identifikator dobavlen");
              return;
            }
            else
            {
              Serial.println("Net vozmojnosti otkryt kartu");
              return;
              }
     } 
   }
  }
// считываем все данные из baza.csv:
void chtenie(){
  myFile = SD.open("baza.csv");
  if (myFile) {
  while (myFile.available()) {
  Serial.write(myFile.read());
  
  }
  // закрываем файл:
  myFile.close();
  } else {
  // если файл не открылся, отображаем сообщение об ошибке:
  Serial.println("Oshibka baza.csv");
  }
}

 

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

Я же писал, что это псевдокод. Чтобы привести его в рабочий - достаточно открыть документацию на библиотеку SD и посмотреть, какие функции реализуют тот же функционал. Например, вместо EndOfFile можно юзать метод available класса File. И т.д. Учитесь - именно на таких вот вещах и учаться: программирование - это не передирание кода друг у друга, это умение реализовать алгоритм в понятных конкретному компилятору инструкциях. Я привёл лишь алгоритм.