Запись на SD карту потока бинарных данных при меняющемся размере информации.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Дело в следующем. Есть Arduino, к нему подключен датчик, выдающий бинарные сообщения и необходимо эти данные записывать неразрывано на SD карту. Ниже показан правильно записанный файл. Сначала идет преамбула (64 бита), потом номер сообщения (16 бит), далее идет количество 32 битных слов (16 бит), потом сами 32-х битные слова и замыкает все дело чексумма.

Смысл заключается в следующем: Т.к преамбула идет первой, то можно пропустить первые 64+16 бит и перейти сразу к числу сообщений. Находим это число, при этом нужно понимать, что порядок следования байт – little-endian (младший байт идет первым), а значит нужно как-то это правильно считать... Нашли что это за число, допустим в примере это 8, значит 8 - 32х битных сообщений + чексумма 32 бита. Считаем общее количество и записываем на SD карту. При этом нужно будет записать идущую вначале приамбулу и номер сообщения, значит их запись нужно начинать в самом начале, потом вычислять оставшуюся длинну сообщения и дозаписывать ее и так по циклу (Запись: преамбула + номер сообщения + оставшееся кол-во бит).

На данном этапе запись осуществляется совсем не по такому плану, т.к я новичок и не знаю как осуществить задуманное...

Вот код который есть на данном этапе.

С помощью него можно просто писать на карту определенное количество информации, но при таком виде много пакетов битых.

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

/* --- Defines --- */
#define USBrate    115200      // USB-COM baud rate (speed)

#define mySerial  Serial1     // UART for GPS
#define UARTrate  115200      // GPS UART baud rate (speed)


#define myFile    "GPSLOG00.TXT" // Log File name
#define GPSECHO  true 

// Set the pins used
#define chipSelect 10
#define ledPin 13

byte rx_byte;

File dataFile;



/*--- Program ---*/
// blink out an error code
void error(uint8_t errno) {

  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}




void setup() {

  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(USBrate);
  Serial.println("\r\nUltimate GPSlogger Shield");
  pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  //if (!SD.begin(chipSelect, 11, 12, 13)) {
  if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(2);
  }
  char filename[15];
  strcpy(filename, myFile);
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }

  dataFile = SD.open(filename, FILE_WRITE);
  if( ! dataFile ) {
    Serial.print("Couldnt create "); Serial.println(filename);
    error(3);
  }
  Serial.print("Writing to "); Serial.println(filename);
  
  // connect to the GPS at the desired rate
  mySerial.begin(UARTrate);
  
  Serial.println("Ready!");
}
 
void loop() {



// отправляем данные только после их получения:
if (mySerial.available()) 
{
rx_byte = mySerial.read();

//Записываем данные в файл
byte data[10000];
dataFile.write(data,mySerial.readBytes((byte*)data,sizeof(data)));
//dataFile.write(data,sizeof(data));
dataFile.flush();
if (GPSECHO)
      if (rx_byte) Serial.print(rx_byte, HEX);
}

} 
Logik
Offline
Зарегистрирован: 05.08.2014

А вот  byte data[10000]; - это щедрость или транжирство? Контроллер какой?

MagicianII
Offline
Зарегистрирован: 30.04.2016

Arduino Due контроллер. Я даже 20 000 ставил, нормально, прет)

Кстати есть непонятка.

if (rx_byte) Serial.print(rx_byte, HEX);

Эта строка выдает мне по 2 символа между записью на карту вроде как. Я думаю, что это потерянная информация, так ли это?

Logik
Offline
Зарегистрирован: 05.08.2014

Так понять из Вашего поста вобще мало чего можна. Опишите протокол. У Вас завершение приема по таймауту шоле? И скоко, где задается? Потому как по коду получается так, если шото принято (все-не все ХЗ но скорей всего, только первые байты) , то читае rx_byte затем читаем все что есть до таймаута (судя по  предку stream.readBytes а скоко таймаут опять ХЗ, и вообще оно так работает? я не пробовал использовать контроль таймаута от stream) и это пишем на карту, а rx_byte не пишем, но выводим в ответ.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Так понять из Вашего поста вобще мало чего можна. Опишите протокол. У Вас завершение приема по таймауту шоле? И скоко, где задается? Потому как по коду получается так, если шото принято (все-не все ХЗ) , то читае rx_byte затем читаем все что есть до таймаута (судя по  предку stream.readBytes а скоко таймаут опять ХЗ, и вообще оно так работает? я не пробовал использовать контроль таймаута от stream) и это пишем на карту, а rx_byte не пишем, но выводим в ответ.

Завершение - это когда я USB вытаскиваю из компьютера) Завершение пока не предусмотрено, но пишется все с помощью dataFile.flush();

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

Logik
Offline
Зарегистрирован: 05.08.2014

Ну както одно сообщение от другого должно отделятся, или все сплошняком пишется? Тогда и rx_byte наверно нужно тоже того. Записать. Чексума выше упоминаемая предполагает разделение на сообщения, она для каждого считается. Тогда как разделять?

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Ну както одно сообщение от другого должно отделятся, или все сплошняком пишется? Тогда и rx_byte наверно нужно тоже того. Записать. Чексума выше упоминаемая предполагает разделение на сообщения, она для каждого считается. Тогда как разделять?

Каждое новое сообщение начинается с преамбулы и завершается чексуммой. А между ними есть еще 32х битные данные, которых N-е количество и всегда разное. Выше я все расписал.

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

Вот так это делается в программе DELPHI. и все работает.


// блок описания переменных
          fbin: file of char;       // бинарный протокол

// создание файла
         AssignFile(fbin,'GeoS3.bin');
         Rewrite(fbin);
          CloseFile(fbin);

// прием байт по последовательному порту и запись в файл
        Reset(fbin); Seek(fbin, FileSize(fbin));
          for ik := 0 to Count-1 do begin                // Count - кол-во байт в буфере обмена порта
                    VaCommBin.ReadBuf(Ch,1);        // чтение одного байта из буфера
                    write(fbin,Ch);
         end;
          CloseFile(fbin);
Как сделать на Ардуино? Я не могу сообразить
Logik
Offline
Зарегистрирован: 05.08.2014

Обратите внимание на Count в делфовском коде, если оно известно то и ардуино пишите совершенно аналогично. Цикл, байт приняли - байт записали. Единственное что в делфи ReadBuf блокирующий, а в ардуине mySerial.read(); неблокирующий. Но mySerial.available() позволит проврить есть ли принятые данные и сколько их есть и можно подождать если их нет. Просто надо решить, что делать если данные ещё пока не приняты: тупо ждем следующий байт, выполняем скетч дальше (если вобще есть что делать). Пример для второго варианта,  похожего приема из моего рабочего проекта. Принимает LenRecive байт с проверкой чексумы. Из основног лупа она переодически дергается пока возвращает RECIVE_PROCESS, это значить пока не принято все.

  byte Recive(byte* buf)
  {
    byte len = Serial.available();
    
       
    if(len<LenRecive+1) return RECIVE_PROCESS;

    byte crc=0;
    byte b;
    
    for(byte i=0;i<LenRecive;i++,buf++){b=Serial.read();crc+=b;*buf=b;}
    
    b=Serial.read();
    
    LenRecive=0;
    if(b!=crc) return RECIVE_ERR_CRC;
    return RECIVE_OK;
    
  }

 

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

  byte Recive(byte* buf)
  {
    byte len = Serial.available();
    
       
    if(len<LenRecive+1) return RECIVE_PROCESS;

    byte crc=0;
    byte b;
    
    for(byte i=0;i<LenRecive;i++,buf++){b=Serial.read();crc+=b;*buf=b;}
    
    b=Serial.read();
    
    LenRecive=0;
    if(b!=crc) return RECIVE_ERR_CRC;
    return RECIVE_OK;
    
  }

 

Не совсем понимаю что делает ваш код. Как его применить для моего случая с записью на SD?

Logik
Offline
Зарегистрирован: 05.08.2014

MagicianII пишет:

Logik пишет:

  byte Recive(byte* buf)
  {
    byte len = Serial.available();
    
       
    if(len<LenRecive+1) return RECIVE_PROCESS;

    byte crc=0;
    byte b;
    
    for(byte i=0;i<LenRecive;i++,buf++){b=Serial.read();crc+=b;*buf=b;}
    
    b=Serial.read();
    
    LenRecive=0;
    if(b!=crc) return RECIVE_ERR_CRC;
    return RECIVE_OK;
    
  }

 

Не совсем понимаю что делает ваш код. Как его применить для моего случая с записью на SD?

Достаточно вдумчиво прочитать и проверить  свое представления о действии функций. Код принимает LenRecive байт в буфер и еще одного CRC. При этом учитывается тот факт, что на момент вызова этой функции может быть принято еще не все сообщение. 

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

MagicianII пишет:

Logik пишет:

  byte Recive(byte* buf)
  {
    byte len = Serial.available();
    
       
    if(len<LenRecive+1) return RECIVE_PROCESS;

    byte crc=0;
    byte b;
    
    for(byte i=0;i<LenRecive;i++,buf++){b=Serial.read();crc+=b;*buf=b;}
    
    b=Serial.read();
    
    LenRecive=0;
    if(b!=crc) return RECIVE_ERR_CRC;
    return RECIVE_OK;
    
  }

 

Не совсем понимаю что делает ваш код. Как его применить для моего случая с записью на SD?

Достаточно вдумчиво прочитать и проверить  свое представления о действии функций. Код принимает LenRecive байт в буфер и еще одного CRC. При этом учитывается тот факт, что на момент вызова этой функции может быть принято еще не все сообщение. 

 

Можно увидеть полностью код? С описанием переменных и какие библиотеки подключались

Logik
Offline
Зарегистрирован: 05.08.2014

там здоровенный проект, экран, сервомашинка, линейный привод, датчик температуры и т.д.  2 ардуины общаются и 99% кода совсем не по теме. Это один из методов класса протокола обмена. Чисто как пример, а вызовы  выглядят дето так. 

void loop(void)
{

     byte res=Protocol.Recive(&Data); //прием кода команды и байта данных
      switch(res)
      {
         case DU_PROTOCOL::RECIVE_OK:  // данные уже в Data
           // обрабатываем принятые данные
           break;

         case DU_PROTOCOL::RECIVE_ERR_CRC: //ошибка приема
                   ReciveErr=res;
            break;
        case DU_PROTOCOL::RECIVE_PROCESS:  .//процесс приема не завершен
           break;
      }  

//выполняем другие действия

}

Обратите внимание на общий подход. Все без циклов ожидания, луп крутится максимально быстро, для микроконтролеров это правильно.

Давайте лучше про Ваши проблемы. Код у Вас похож на правду, пропуски данных будут из за несохранения в файл считаного Serial.read, оно потом в буфере уже не  присутствует. Это  если код - аналог дельфовского. Если чего больше то тоже не проблема. 

 

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

там здоровенный проект, экран, сервомашинка, линейный привод, датчик температуры и т.д.  2 ардуины общаются и 99% кода совсем не по теме. Это один из методов класса протокола обмена. Чисто как пример, а вызовы  выглядят дето так. 

void loop(void)
{

     byte res=Protocol.Recive(&Data); //прием кода команды и байта данных
      switch(res)
      {
         case DU_PROTOCOL::RECIVE_OK:  // данные уже в Data
           // обрабатываем принятые данные
           break;

         case DU_PROTOCOL::RECIVE_ERR_CRC: //ошибка приема
                   ReciveErr=res;
            break;
        case DU_PROTOCOL::RECIVE_PROCESS:  .//процесс приема не завершен
           break;
      }  

//выполняем другие действия

}

Обратите внимание на общий подход. Все без циклов ожидания, луп крутится максимально быстро, для микроконтролеров это правильно.

Давайте лучше про Ваши проблемы. Код у Вас похож на правду, пропуски данных будут из за несохранения в файл считаного Serial.read, оно потом в буфере уже не  присутствует. Это  если код - аналог дельфовского. Если чего больше то тоже не проблема. 

 

Вообщем, пока я не понял как сделать так, чтобы ничего не терялось. И не понятно, поможет ли то, если я буду знать длинну сообщения, ведь все равно будет потом запись на карту и данные начнут теряться, мне кажется. Тут следует сделать, что-то хитрое. 2й или 3й буфер, но т.к я новичок, я не знаю как это сделать. Буду признателен, если вы мне поможете откорректировать мой код.

С праздником Пасхи вас!

MagicianII
Offline
Зарегистрирован: 30.04.2016

Кстати говоря, меня бы вполне устроило, если бы сообщения записывались полностью по такому сценарию. (Тут возможны пропуски потока данных, но они будут минимально влиять).

Значит так, нужно сделать терминатор, который будет отслеживать по потоку данных Преамбулу (она имеет известный набор данных). И когда он находит преамбулу, то сразу начинает писать с нее данные, когда начинается следующая преамбула, он заканчивает запись в буфер и идет запись на карту. И так по циклу - нашел 1 преамбулу - запись до следующей приамбулы в буфер и потом на карту. Получается он будет пропускать некоторые сообщения возможно, но зато они будут целыми.

Как так сделать, поможете?

Logik
Offline
Зарегистрирован: 05.08.2014

И Вас с праздниками.

\\\\Значит так, нужно сделать терминатор, который будет отслеживать....

Вполне можно, хотя и громоздко будет отслеживать. Надо будет искать вхождение преамбулы в входящее сообщение. Так делают, но обычно исчут короткий кусок,  несколько байт. Вы тоже можете так сделать, ищете первые допустим 4 байта, если нашли - либо "верите" и отсчитываете длину оставшегося до сообщения и пропускаете,  либо "проверяете" т.е. принимаете и сверяете остальное. В любом случае дальше сообщение, его сохраняете, если длина известна, я так понял у Вас она определяема по сообщению, то лучше/проще конец сообщения ловить по длине.

Вы пока поймите, что у Вас скорей всего нет проблемы с записю на карту.

Есть проблема приема с порта, и она похоже из-за неправильного представления о работе mySerial.read(); и  mySerial.readBytes.

Если что прочитано mySerial.read(); то оно из приемного буфера удаляется и mySerial.readBytes его уже не прочитает. Отсюда пропуски.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

И Вас с праздниками.

\\\\Значит так, нужно сделать терминатор, который будет отслеживать....

Вполне можно, хотя и громоздко будет отслеживать. Надо будет искать вхождение преамбулы в входящее сообщение. Так делают, но обычно исчут короткий кусок,  несколько байт. Вы тоже можете так сделать, ищете первые допустим 4 байта, если нашли - либо "верите" и отсчитываете длину оставшегося до сообщения и пропускаете,  либо "проверяете" т.е. принимаете и сверяете остальное. В любом случае дальше сообщение, его сохраняете, если длина известна, я так понял у Вас она определяема по сообщению, то лучше/проще конец сообщения ловить по длине.

Вы пока поймите, что у Вас скорей всего нет проблемы с записю на карту.

Есть проблема приема с порта, и она похоже из-за неправильного представления о работе mySerial.read(); и  mySerial.readBytes.

Если что прочитано mySerial.read(); то оно из приемного буфера удаляется и mySerial.readBytes его уже не прочитает. Отсюда пропуски.

 

Т.е мне нужно просто убрать ненужные: mySerial.read(); и все будет ок?

Просто это реально не нужные строки, я думал они не мешают.

Logik
Offline
Зарегистрирован: 05.08.2014

Должно быть. Пробуйте! И сюда отпишите.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Должно быть. Пробуйте! И сюда отпишите.

Да, все хорошо пишется теперь без потерь)))))) Но, этого мало, т.к когда я выключаю запись у меня обрывается все на половине сообщения и я не могу сразу работать с таким файлом.....

Теперь нужно чтобы сообщения писались не по фиксированному буферу, а по плавающему. Т.е нужно знать длину сообщения. Ее можно узнать из самого сообщения, это первые 16 бит после преамбулы (с учетом того, что младший байт первый). Порядок следования байт – little-endian (младший байт идет первым). 



Вообщем структура сообщения такая:



<преамбула: 64>< ndat & ncmd: 32><dat1, dat2,......datN><сs: 32>



<преамбула: 64>: преамбула “GEOSr3PS” (64 бита, 534F4547 53503372) 

<ndat> : количество 32-ти разрядных слов данных содержательной части сообщения (16 бит) 

<ncmd> : номер сообщения (16 бит) 

<dat1, dat2,......datN>: содержательная часть сообщения (32-х битные слова); количество данных соответствует параметру ndat 

<сs>: контрольная сумма сообщения (32 бита); вычисляется как «исключающее ИЛИ» по всем полям сообщения, представленным в виде 32-х битных слов. 



Я думаю нужно добавить еще несколько массивов (например) Mas[16] Mas[32] ну и тд и можно будет с ними уже оперировать и узнать необходимый кусок - ndat (16 первых бит, который отвечает за длину конкретного сообщения). Пока нужно получить этот кусок, дальше, когда получим, нужно все куски сложить и получить полную длину сообщения, ее и нужно вбивать в буфер, который уже будет знать полную длину сообщения и сохранять все как нада.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Рано радовался, где-то чето теряется все же.....

Logik
Offline
Зарегистрирован: 05.08.2014

А чего Вы в битах оперируете, этоже мазохизм;)) Считайте в байтах, так проще. Можна несколько массивов, можна и в одном. Его даже можна заполнять не с первого елемента, а с произвольного и не до конца, а как хочется. Это чисто как Вам видится удобней. Можна даже переменные совать в mySerial.readBytes например int R; mySerial.readBytes((byte*)&R, sizeof(R)) заполнит переменную. Причем такая форма годится для любого типа R. Профи часто делают так, описывают протокол в виде структуры и подсовывают указатель на такую структуру в функции типа readBytes. И вуаля! Структура автоматом заполнена, все разложено как положено, а описание структуры уже намек на документацию))) Может я и напрасно расказываю, это сложновато для новичка, но вдруг...

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

А чего Вы в битах оперируете, этоже мазохизм;)) Считайте в байтах, так проще. Можна несколько массивов, можна и в одном. Его даже можна заполнять не с первого елемента, а с произвольного и не до конца, а как хочется. Это чисто как Вам видится удобней. Можна даже переменные совать в mySerial.readBytes например int R; mySerial.readBytes((byte*)&R, sizeof(R)) заполнит переменную. Причем такая форма годится для любого типа R. Профи часто делают так, описывают протокол в виде структуры и подсовывают указатель на такую структуру в функции типа readBytes. И вуаля! Структура автоматом заполнена, все разложено как положено, а описание структуры уже намек на документацию))) Может я и напрасно расказываю, это сложновато для новичка, но вдруг...

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

Logik
Offline
Зарегистрирован: 05.08.2014

Так там толком переделывать нечего, десять строк с 92 по 102. Закоментируйте, авось пригодится, вытереть всегда успеете и начинайте писать.  Заливайте, проверяйте, сюда выкладуйте, там все очень просто.  

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Так там толком переделывать нечего, десять строк с 92 по 102. Закоментируйте, авось пригодится, вытереть всегда успеете и начинайте писать.  Заливайте, проверяйте, сюда выкладуйте, там все очень просто.  

Мне не просто) Это моя первая программа и я вообще не бум бум в программировании на C++. Может быть вы поможете, раз там все просто? 

MagicianII
Offline
Зарегистрирован: 30.04.2016

Я вот подумал, может мне сгодиться вот этот код? http://arduino.ru/forum/programmirovanie/peredacha-izobrazheniya-s-arduino-na-kompyuter-cherez-serial

MagicianII
Offline
Зарегистрирован: 30.04.2016

А еще мне кажется у меня вот такая проблема: http://pashkevich.me/article/6.html

 

Подводный камень:

Функция "не отчищает" тот массив в который складывает переданные байты, отсюда возникают ситуации наподобие следующей.

Вы передали строку "Hi max" она состоит ровно из 6 байт, и каждый байт последовательно будет размещен в массиве с самого начала и на мониторе вы получили "Hi max"

Далее, вы передали строку "Hello" эта строка занимает лишь 5 байт, и будет записана в ваш массив с самого начала в результата на мониторе вы получите "Hellox".

Лишняя буква "X" это остаток от предыдущей строки, то есть если вы не запишите все 6 байт или в программе не отчистите массив то при передачи блока меньшего размера вы получите остатки и от старого более длинного блока который хранится в вашем массиве от предыдущего вызова функции.

Logik
Offline
Зарегистрирован: 05.08.2014

MagicianII пишет:

Функция "не отчищает" тот массив в который складывает переданные байты,

Бывает. Эта проблема больше для строк, чем для двоичных данных. Помните, что mySerial.available()  возвращает количество реально принятых байт. Используйте это значение при извлечении из буфера и в прочих случаях. Например, если принято 6 и более байт то извлечем их - byte L=mySerial.available(); if(L>=6) mySerial.readBytes(buf, L); Этот код можно крутить в лупе и он будет ждать момента, когда поступит 6 и более байт. 

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

MagicianII пишет:

Функция "не отчищает" тот массив в который складывает переданные байты,

Бывает. Эта проблема больше для строк, чем для двоичных данных. Помните, что mySerial.available()  возвращает количество реально принятых байт. Используйте это значение при извлечении из буфера и в прочих случаях. Например, если принято 6 и более байт то извлечем их - byte L=mySerial.available(); if(L>=6) mySerial.readBytes(buf, L); Этот код можно крутить в лупе и он будет ждать момента, когда поступит 6 и более байт. 

Да, это понятно, но тут вопрос в другом.... Мне все же нужно точно знать сколько байт придет чтобы буфер был ровно под то количество байт, что приходит.... А этот размер можно узнать только прочитав начало каждого сообщения и вычленив из него нужные байты. Но дело в том, как это сделать, причем нужно иметь ввиду, что начало сообщения тоже нужно будет записать. 

В приницпе мы точно знаем сколько начало весит, это 8 + 2 байта +2 байта - это количество дальнейшей инфы. Их наверно нужно в массив:

byte preambula[12];

byte kolichestvo[10];

if (mySerial.available()>0) 
{
 
//Записываем данные в файл
 
A = dataFile.write(data,mySerial.readBytes((byte*)preambula,sizeof(preambula)));
B = dataFile.write(data,mySerial.readBytes((byte*)kolichestvo,sizeof(kolichestvo)));
C = A - B; //Наше число, определяющее длинну сообщения, осталось еще учесть чексумму
byte ostatok[C*4+4];
D = dataFile.write(data,mySerial.readBytes((byte*)ostatok,sizeof(ostatok)));
dataFile.flush();
 
}
 
Пожалуйста, поправьте код, я знаю, что Ардуино студио меня не поймет, но по логике должно быть так.
Т.е получается, что сначала мы вносим в буфер и сразу записываем 12 байт преславутой преамбулы, а потом дописываем оставшиеся байты информации, после вычисления длинны. НО как я написал это будет работать только с началом, а чтобы работало каждый раз, тут нужно значит прибавлять будет длинну полного предыдущего сообщения + 12 байт. Возможно можно сделать проще и брать сразу нужные байты Byte[m,n] но я не знаю, можно ли.
Logik
Offline
Зарегистрирован: 05.08.2014

Показуйте ошибки. Пока вижу byte ostatok[C*4+4]; Тут переменная недопустима, только константы. Кстати А,В и С не обявлены, тоже плохо. Надо по С немного почитать, например вот http://dfe.petrsu.ru/koi/posob/c/c.htm первое попавшее из гугла, но вроде неплохо и кратко. Про типы данных, переменные. Это основы без них тяжело.

Массив переменной длины в принципе возможен, но там нада память распределять освобождать... Пока Вам оно не надо.

Обявляйте массив по максимально допустимому размеру, а используйте только часть нужную. Т.е. byte ostatok[10000];D = dataFile.write(data,mySerial.readBytes((byte*)ostatok,C*4+4)); Ну из предположения что С правильно посчитано и арифметика вокруг него та.

\\\\НО как я написал это будет работать только с началом...

Так после данных, длина которых переменна, снова идет преамбула? Тогда цикл, программа же уже знает, что делать с преамбулой. Новую преамбулу читаем на место старой и т. д.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Показуйте ошибки. Пока вижу byte ostatok[C*4+4]; Тут переменная недопустима, только константы. Кстати А,В и С не обявлены, тоже плохо. Надо по С немного почитать, например вот http://dfe.petrsu.ru/koi/posob/c/c.htm первое попавшее из гугла, но вроде неплохо и кратко. Про типы данных, переменные. Это основы без них тяжело.

Массив переменной длины в принципе возможен, но там нада память распределять освобождать... Пока Вам оно не надо.

Обявляйте массив по максимально допустимому размеру, а используйте только часть нужную. Т.е. byte ostatok[10000];D = dataFile.write(data,mySerial.readBytes((byte*)ostatok,C*4+4)); Ну из предположения что С правильно посчитано и арифметика вокруг него та.

\\\\НО как я написал это будет работать только с началом...

Так после данных, длина которых переменна, снова идет преамбула? Тогда цикл, программа же уже знает, что делать с преамбулой. Новую преамбулу читаем на место старой и т. д.

 

Да, после данных с переменной длинной снова идет преамбула. Получается после того, как все считается полностью, то массив очищается и снова будет новый?

Кстати как быть с тем, что порядок следования байт – little-endian (младший байт идет первым)? Можно ли сразу это объявить глобально как-то? а то получится не верное считывание числа. Ну или считать число, указывающее "количество 4 байтовыйх сообщений" и его сконвертировать уже в little-endian, можно так?

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Показуйте ошибки. Пока вижу byte ostatok[C*4+4]; Тут переменная недопустима, только константы. Кстати А,В и С не обявлены, тоже плохо. Надо по С немного почитать, например вот http://dfe.petrsu.ru/koi/posob/c/c.htm первое попавшее из гугла, но вроде неплохо и кратко. Про типы данных, переменные. Это основы без них тяжело.

Массив переменной длины в принципе возможен, но там нада память распределять освобождать... Пока Вам оно не надо.

Обявляйте массив по максимально допустимому размеру, а используйте только часть нужную. Т.е. byte ostatok[10000];D = dataFile.write(data,mySerial.readBytes((byte*)ostatok,C*4+4)); Ну из предположения что С правильно посчитано и арифметика вокруг него та.

\\\\НО как я написал это будет работать только с началом...

Так после данных, длина которых переменна, снова идет преамбула? Тогда цикл, программа же уже знает, что делать с преамбулой. Новую преамбулу читаем на место старой и т. д.

 

Кстати моя ошибка в том, что у меня написано так, что ниче не заработает, потому что написано куча записей и одна другую перекрывает, как мне кажется.

Logik
Offline
Зарегистрирован: 05.08.2014

MagicianII пишет:

 Получается после того, как все считается полностью, то массив очищается и снова будет новый?

Массив, он как и любая другая переменная, после обявления просто есть. Заполняется, извлекается и т.д. на факт его существования не сказывается. Он как ведро, шоле. Воду наливай, выливай, ведро остается. И статически обявленный масив есть пока есть программа, и как новый.

MagicianII пишет:

Кстати как быть с тем, что порядок следования байт – little-endian (младший байт идет первым)? ...

Не проблема. Если порядок следования байт не тот (сразу твердо даже не вспомню как оно, у разных процессоров разное) то их завсегда можно переставить ручками типа byte a=buf[5];buf[5]=buf[6];buf[6]=a; и два байта переставили. Четыре аналогично.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

MagicianII пишет:

 Получается после того, как все считается полностью, то массив очищается и снова будет новый?

Массив, он как и любая другая переменная, после обявления просто есть. Заполняется, извлекается и т.д. на факт его существования не сказывается. Он как ведро, шоле. Воду наливай, выливай, ведро остается. И статически обявленный масив есть пока есть программа, и как новый.

MagicianII пишет:

Кстати как быть с тем, что порядок следования байт – little-endian (младший байт идет первым)? ...

Не проблема. Если порядок следования байт не тот (сразу твердо даже не вспомню как оно, у разных процессоров разное) то их завсегда можно переставить ручками типа byte a=buf[5];buf[5]=buf[6];buf[6]=a; и два байта переставили. Четыре аналогично.

Может кто-нибудь всю программу написать за 500 рублей? Это ведь легко, кто владеет языком С++. Да и руководство к протоколу, что нужно писать, имеется.

Logik
Offline
Зарегистрирован: 05.08.2014

Так Вы в раздел http://arduino.ru/forumy/ishchu-ispolnitelya напишите, там изголодавшиеся токо и ждут ;)

__Alexander
Offline
Зарегистрирован: 24.10.2012

Датчик самостоятельно без запроса кидает данные? А в общем, если свзяь устойчивая и без ошибок, то пиши по прерыванию прихода байта сразу в файл. )))

MagicianII
Offline
Зарегистрирован: 30.04.2016

__Alexander пишет:

Датчик самостоятельно без запроса кидает данные? А в общем, если свзяь устойчивая и без ошибок, то пиши по прерыванию прихода байта сразу в файл. )))

Да, датчик самостоятельно кидает данные. По прирыванию это как, не очень понимаю?

Logik
Offline
Зарегистрирован: 05.08.2014

MagicianII пишет:

 По прирыванию это как, не очень понимаю?

И правильно, не надо такое понимать, он шутит, из прерывания писать на карту слишком долго, а обработчик должен быть коротким как выстрел. 

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

MagicianII пишет:

 По прирыванию это как, не очень понимаю?

И правильно, не надо такое понимать, он шутит, из прерывания писать на карту слишком долго, а обработчик должен быть коротким как выстрел. 

Мне один человек ответил вот что по моему коду:

int *size;
int *crc;
byte buff[10000];
size=&buff[8];
byte *ptr=buff;
while(1)
{
if (mySerial.available()>10) 
{
mySerial.readBytes(ptr,read=10);
ptr+=read;
//А тут начинается магия :)
// в переменной size уже лежит размер блока данных
mySerial.readBytes(ptr,size*4+4);
read+=size*4+4;
if(read>8+2+2+size*4+4) // преамбула+размер+номер+данные+ксумма
{
crc=&buf[8+2+2+size*4];
if (testcrc(buf+8+2+2,size*4,crc)) // проверяем контрольную сумму данных пропуская преамбулу+размер+номер сообщения
{
dataFile.write(buf,8+2+2+size*4+4);
//очищаем переменные
ptr=buff;
}else{
//Тут генерируем ошибку контрольной суммы
}
}
}
}

Я его залил:

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

/* --- Defines --- */
#define USBrate    115200      // USB-COM baud rate (speed)

#define mySerial  Serial1     // UART for GPS
#define UARTrate  115200      // GPS UART baud rate (speed)


#define myFile    "GPSLOG00.TXT" // Log File name
//#define GPSECHO  true 

// Set the pins used
#define chipSelect 10
#define ledPin 13

//byte rx_byte;
//byte data[1096];
int *size;
int *crc;
byte buff[2192];
size=&buff[8];
byte *ptr=buff;


File dataFile;



/*--- Program ---*/
// blink out an error code
void error(uint8_t errno) {

  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}




void setup() {

  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(USBrate);
  Serial.println("\r\nUltimate GPSlogger Shield");
  pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  //if (!SD.begin(chipSelect, 11, 12, 13)) {
  if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(2);
  }
  char filename[15];
  strcpy(filename, myFile);
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }

  dataFile = SD.open(filename, FILE_WRITE);
  if( ! dataFile ) {
    Serial.print("Couldnt create "); Serial.println(filename);
    error(3);
  }
  Serial.print("Writing to "); Serial.println(filename);
  
  // connect to the GPS at the desired rate
  mySerial.begin(UARTrate);
  
  Serial.println("Ready!");
}


void loop() {

// отправляем данные только после их получения:
while(1)
{
if (mySerial.available()>10) 
{
mySerial.readBytes(ptr,read=10);
ptr+=read;
//А тут начинается магия :)
// в переменной size уже лежит размер блока данных
mySerial.readBytes(ptr,size*4+4);
read+=size*4+4;
if(read>8+2+2+size*4+4) // преамбула+размер+номер+данные+ксумма
{
crc=&buf[8+2+2+size*4];
if (testcrc(buf+8+2+2,size*4,crc)) // проверяем контрольную сумму данных пропуская преамбулу+размер+номер сообщения
{
dataFile.write(buf,8+2+2+size*4+4);
dataFile.flush();
//очищаем переменные
ptr=buff;
}else{
  Serial.print("CRC1");
//Тут генерируем ошибку контрольной суммы
}
}
}
}

}
  

и получил следующие ошибки:

1. error: 'size' does not name a type. size=&buff[8];

2. error: 'read' was not declared in this scope: mySerial.readBytes(ptr,read=10);

3.  error: invalid operands of types 'int*' and 'int' to binary 'operator*' mySerial.readBytes(ptr,size*4+4);

4. error: invalid operands of types 'int*' and 'int' to binary 'operator*'. read+=size*4+4;

5. error: invalid operands of types 'int*' and 'int' to binary 'operator*'. if(read>8+2+2+size*4+4)

6. error: 'buf' was not declared in this scope.

7. error: 'testcrc' was not declared in this scope.

8. error: invalid operands of types 'int*' and 'int' to binary 'operator*'. dataFile.write(buf,8+2+2+size*4+4);

9. 'size' does not name a type

Logik
Offline
Зарегистрирован: 05.08.2014

Ага. Характерно для впервые компилируемого кода. Восновном вокруг size которая то указатель то значение. Для 3-5 и 8 замените size на (*size), read обявите...

Но если это за деньги - пихните ему обратно.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Ага. Характерно для впервые компилируемого кода. Восновном вокруг size которая то указатель то значение. Для 3-5 и 8 замените size на (*size), read обявите...

Но если это за деньги - пихните ему обратно.

Сделал, теперь не пойму как объявить size или куда может ее в другое место нужно поставить?

MagicianII
Offline
Зарегистрирован: 30.04.2016

Logik пишет:

Ага. Характерно для впервые компилируемого кода. Восновном вокруг size которая то указатель то значение. Для 3-5 и 8 замените size на (*size), read обявите...

Но если это за деньги - пихните ему обратно.

Вряд ли это за деньги))))) это же не готовая программа.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Пока ничего не выходит, объявлял переменные как Byte.

Строка size=&buff[8]; точно должна быть там где она есть? Вообщем новые ошибки.

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

/* --- Defines --- */
#define USBrate    115200      // USB-COM baud rate (speed)
#define mySerial  Serial1     // UART for GPS
#define UARTrate  115200      // GPS UART baud rate (speed)
#define myFile    "GPSLOG00.TXT" // Log File name

// Set the pins used
#define chipSelect 10
#define ledPin 13

int *size;
size=&buff[8];
int *crc;
byte buff[2192];
byte read;
byte *ptr=buff;
byte buf;
File dataFile;

/*--- Program ---*/
// blink out an error code
void error(uint8_t errno) {

  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

void setup() {

  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(USBrate);
  Serial.println("\r\nUltimate GPSlogger Shield");
  pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  //if (!SD.begin(chipSelect, 11, 12, 13)) {
  if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(2);
  }
  char filename[15];
  strcpy(filename, myFile);
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }

  dataFile = SD.open(filename, FILE_WRITE);
  if( ! dataFile ) {
    Serial.print("Couldnt create "); Serial.println(filename);
    error(3);
  }
  Serial.print("Writing to "); Serial.println(filename);
  
  // connect to the GPS at the desired rate
  mySerial.begin(UARTrate);
  
  Serial.println("Ready!");
}

void loop() {

// отправляем данные только после их получения:

while(1)
{
if (mySerial.available()>10) 
{
mySerial.readBytes(ptr,read=10);
ptr+=read;
//А тут начинается магия :)
// в переменной size уже лежит размер блока данных
mySerial.readBytes(ptr,(*size)*4+4);
read+=(*size)*4+4;
if(read>8+2+2+(*size)*4+4) // преамбула+размер+номер+данные+ксумма
{
crc=&buf[8+2+2+(*size)*4];
if (testcrc(buf+8+2+2,(*size)*4,crc)) // проверяем контрольную сумму данных пропуская преамбулу+размер+номер сообщения
{
dataFile.write(buf,8+2+2+(*size)*4+4);
dataFile.flush();
//очищаем переменные
ptr=buff;
}else{
  Serial.print("CRC1");
//Тут генерируем ошибку контрольной суммы
}}}}}
 
ZAPIS-BIN7:15: error: 'size' does not name a type
 
 size=&buff[8];
 
 ^
 
C:\Users\Magician\Documents\Arduino\ZAPIS-BIN7\ZAPIS-BIN7.ino: In function 'void loop()':
 
ZAPIS-BIN7:98: error: invalid types 'byte {aka unsigned char}[int]' for array subscript
 
 crc=&buf[8+2+2+(*size)*4];
 
                         ^
 
ZAPIS-BIN7:99: error: 'testcrc' was not declared in this scope
 
 if (testcrc(buf+8+2+2,(*size)*4,crc)) // проверяем контрольную СЃСѓРјРјСѓ данных пропуская преамбулу+размер+номер сообщения
 
                                    ^
 
ZAPIS-BIN7:101: error: call of overloaded 'write(byte&, int)' is ambiguous
 
 dataFile.write(buf,8+2+2+(*size)*4+4);
 
                                     ^
 
C:\Users\Magician\Documents\Arduino\ZAPIS-BIN7\ZAPIS-BIN7.ino:101:37: note: candidates are:
 
In file included from C:\Users\Magician\Documents\Arduino\ZAPIS-BIN7\ZAPIS-BIN7.ino:1:0:
 
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:37:18: note: virtual size_t SDLib::File::write(const uint8_t*, size_t) <near match>
 
   virtual size_t write(const uint8_t *buf, size_t size);
 
                  ^
 
C:\Program Files (x86)\Arduino\libraries\SD\src/SD.h:37:18: note:   no known conversion for argument 1 from 'byte {aka unsigned char}' to 'const uint8_t* {aka const unsigned char*}'
 
In file included from C:\Users\Magician\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.7\cores\arduino/Stream.h:26:0,
 
                 from C:\Users\Magician\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.7\cores\arduino/HardwareSerial.h:24,
 
                 from C:\Users\Magician\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.7\cores\arduino/Arduino.h:195,
 
                 from sketch\ZAPIS-BIN7.ino.cpp:1:
 
C:\Users\Magician\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.7\cores\arduino/Print.h:54:12: note: size_t Print::write(const char*, size_t) <near match>
 
     size_t write(const char *buffer, size_t size) {
 
            ^
 
C:\Users\Magician\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.7\cores\arduino/Print.h:54:12: note:   no known conversion for argument 1 from 'byte {aka unsigned char}' to 'const char*'
 
exit status 1
'size' does not name a type
 
__Alexander
Offline
Зарегистрирован: 24.10.2012

Logik пишет:

И правильно, не надо такое понимать, он шутит, из прерывания писать на карту слишком долго, а обработчик должен быть коротким как выстрел. 

Та я как-бы не то чтобы шучу, а намекаю на первоочередный вопрос, с какой скоростью сыпятся данные? Может там 100 Мбит, и ни какой алгоритм не поможет. 

А насчет долго, то вроде дуе это уже арм, работающий на 84 Мгц. Так что ничего не долго, можно самому создать файл в свободных секторах и писать напрямую, есть фича такая у карточек - автоматом переходят на следующий сектор (write block называется).

 

 

Logik
Offline
Зарегистрирован: 05.08.2014

Скорость в первом сообщении, 115200, откуда по ЮСБ быть 100М. А долго не потому что проц плох, а потому что на карту по SPI всегда долго. А в файловую систему - так вобще трындец. Но Вы правы что момент скорости требует внимания.

__Alexander пишет:

 можно самому создать файл в свободных секторах и писать напрямую, есть фича такая у карточек - автоматом переходят на следующий сектор (write block называется).

А вот это  - грязный хак. Тут или/или надо. Или работать через ФС и использовать её преимущества и отгребать недостатки, или свой формат карты и забыть о совместимости. Каждый подход имеет право на жизнь. Но смешивать нельзя, проблем масса будет.

MagicianII
Offline
Зарегистрирован: 30.04.2016

Мне скорректировали предыдущий код:

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

/* --- Defines --- */
#define USBrate    115200      // USB-COM baud rate (speed)
#define mySerial  Serial1     // UART for GPS
#define UARTrate  115200      // GPS UART baud rate (speed)
#define myFile    "GPSLOG00.TXT" // Log File name

// Set the pins used
#define chipSelect 10
#define ledPin 13


//File dataFile;

/*--- Program ---*/
// blink out an error code
void error(uint8_t errno) {

  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

void setup() {

  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(USBrate);
  Serial.println("\r\nUltimate GPSlogger Shield");
  pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  //if (!SD.begin(chipSelect, 11, 12, 13)) {
  if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(2);
  }
//  char filename[15];
//  strcpy(filename, myFile);
//  for (uint8_t i = 0; i < 100; i++) {
//    filename[6] = '0' + i/10;
//    filename[7] = '0' + i%10;
//    // create if does not exist, do not open existing, write, sync after write
//    if (! SD.exists(filename)) {
//      break;
//    }
//  }
//
//  dataFile = SD.open(filename, FILE_WRITE);
//  if( ! dataFile ) {
//    Serial.print("Couldnt create "); Serial.println(filename);
//    error(3);
//  }
//  Serial.print("Writing to "); Serial.println(filename);
//  
//  // connect to the GPS at the desired rate
//  mySerial.begin(UARTrate);
//  
//  Serial.println("Ready!");
}

void loop() {

// отправляем данные только после их получения:
int *size;
int *crc;
int read;
byte buff[10000];
size=(int *)&buff[8];
byte *ptr=buff;
int testcrc(byte *buff,int size, int crc);

File dataFile = SD.open("test.txt", FILE_WRITE);

while(1)
{
if (mySerial.available()>10) 
{
mySerial.readBytes(ptr,read=10);
ptr+=read;
//А тут начинается магия :)
// в переменной size уже лежит размер блока данных
mySerial.readBytes(ptr,(*size)*4+4);
read+=(*size)*4+4;
if(read>8+2+2+(*size)*4+4) // преамбула+размер+номер+данные+ксумма
{
crc=(int *)&buff[8+2+2+(*size)*4];
if (testcrc(buff+8+2+2,(*size)*4,*crc)) // проверяем контрольную сумму данных пропуская преамбулу+размер+номер сообщения
{
dataFile.write(buff,8+2+2+(*size)*4+4);
//очищаем переменные
ptr=buff;
}else{
  Serial.print("CRC1");
//Тут генерируем ошибку контрольной суммы
}}}}}
 

Теперь только ошибка

sketch\sketch_may05a.ino.cpp.o: In function `loop':
 
C:\Users\Алексей\Documents\Arduino\sketchi\sketch_may05a/sketch_may05a.ino:103: undefined reference to `testcrc(unsigned char*, int, int)'
 
collect2.exe: error: ld returned 1 exit status
 
exit status 1
Ошибка компиляции.
 
Все дело в этой строке: int testcrc(byte *buff,int size, int crc);
 
Ее нужно поправить
 
MagicianII
Offline
Зарегистрирован: 30.04.2016

Подниму тему. Никто не знает как исправить эти ошибки?

MagicianII
Offline
Зарегистрирован: 30.04.2016

у arduino little-endian порядок

соответственно

byte buff[2]={2,0};

int *a=(int*)buff;

в переменной *a будет 2, а не 512

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

MagicianII пишет:
Все дело в этой строке: int testcrc(byte *buff,int size, int crc);
Ее нужно поправить

Верно, реализации функции не хватает

int testcrc(byte *buff,int size, int crc)
{
  //здесь реализация функции
}

 

 

MagicianII
Offline
Зарегистрирован: 30.04.2016
#include <SD.h>
#include <SPI.h>

/* --- Defines --- */
#define USBrate    115200      // USB-COM baud rate (speed)
#define mySerial  Serial1     // UART for GPS
#define UARTrate  115200      // GPS UART baud rate (speed)
//#define myFile    "GPSLOG00.TXT" // Log File name

// Set the pins used
#define chipSelect 10
#define ledPin 13


//File dataFile;

/*--- Program ---*/
// blink out an error code
void error(uint8_t errno) {

  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

void setup() {

  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(USBrate);
  Serial.println("\r\nUltimate GPSlogger Shield");
  pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  //if (!SD.begin(chipSelect, 11, 12, 13)) {
  if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(2);
  }
//  char filename[15];
//  strcpy(filename, myFile);
//  for (uint8_t i = 0; i < 100; i++) {
//    filename[6] = '0' + i/10;
//    filename[7] = '0' + i%10;
//    // create if does not exist, do not open existing, write, sync after write
//    if (! SD.exists(filename)) {
//      break;
//    }
//  }
//
//  dataFile = SD.open(filename, FILE_WRITE);
//  if( ! dataFile ) {
//    Serial.print("Couldnt create "); Serial.println(filename);
//    error(3);
//  }
//  Serial.print("Writing to "); Serial.println(filename);
//  
//  // connect to the GPS at the desired rate
//  mySerial.begin(UARTrate);
//  
//  Serial.println("Ready!");
}

void loop() {

// отправляем данные только после их получения:
int *size;
int *crc;
int read;
byte buff[5000];
size=(int *)&buff[8];
byte *ptr=buff;
//int testcrc(byte *buff,int size, int crc);

File dataFile = SD.open("test1.txt", FILE_WRITE);

while(1)
{
if (mySerial.available()>10) 
{
mySerial.readBytes(ptr,read=10);
ptr+=read;
//А тут начинается магия :)
// в переменной size уже лежит размер блока данных
mySerial.readBytes(ptr,(*size)*4+4);
read+=(*size)*4+4;
//Serial.print(*size, DEC);
if(read>8+2+2+(*size)*4+4) // преамбула+размер+номер+данные+ксумма
{
crc=(int *)&buff[8+2+2+(*size)*4];

//if (testcrc(buff+8+2+2,(*size)*4,*crc)) // проверяем контрольную сумму данных пропуская преамбулу+размер+номер сообщения
//{
dataFile.write(buff,8+2+2+(*size)*4+4);
//очищаем переменные
ptr=buff;
//}else{
//  Serial.print("CRC1");
////Тут генерируем ошибку контрольной суммы
//}
}}}
}
 

Даже без testcrc никакие данные не записываются и мало того, не передаются

 

MagicianII
Offline
Зарегистрирован: 30.04.2016

+ к тому, size показывает заоблочное число, например: 124539593 - а это явно не число 32 битных сообщений

 

Никто не поможет?

MagicianII
Offline
Зарегистрирован: 30.04.2016

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

Logik
Offline
Зарегистрирован: 05.08.2014

MagicianII пишет:

+ к тому, size показывает заоблочное число, например: 124539593 - а это явно не число 32 битных сообщений

 

Никто не поможет?

А у вас и не число 32 битное. Это указатель на int. 2 байта. И соответственно ни как не 124539593.

Все сильно напутано.