Файл создан, но не записаны данные

Я начинаю использовать Arduino и практически не имею опыта кодирования. Тем не менее, мне удалось закодировать и понять, как это работает.

Проблема, с которой я столкнулся, заключается в том, что я не могу регистрировать (записывать) данные с трех подключенных датчиков (анемометров Adafruit). Все они работают правильно; файл данных создан. Однако в файл не записываются данные (или привязка ко времени). Когда я проверяю код, он утверждается...Следовательно, это должно сработать, не так ли?.=/ Затем я загрузил код.

Я использую Arduino uno с SD Logger Shield (Data Logging Shield v1.0, от Deek-Robot (TM)), который использует DS1307 RTC.

Все комментарии более чем приветствуются!

Заранее спасибо

#include "SD.h"
#include <Wire.h>
#include "RTClib.h"

// Простой регистратор данных для аналоговых выводов Arduino
#define LOG_INTERVAL  60000 // мельницы между записями
#define ECHO_TO_SERIAL   0 // эхо-данные на последовательный порт
#define WAIT_TO_START    0 // Ждать последовательного ввода в setup()

// цифровые контакты, которые подключаются к светодиодам
#define redLEDpin 3
#define greenLEDpin 4

// Аналоговые контакты, которые подключаются к датчикам
#define Anemometer0           // аналоговый 0
#define Anemometer1           // аналоговый 1
#define Anemometer2           // аналоговый 2

RTC_DS1307 RTC; // определяет объект часов реального времени

//Параметры настройки анемометров

// Anemometer0
const int sensorPin0 = A0; // Определяет вывод, к которому подключен выход анемометра
int sensorValue0 = 0; // Переменная сохраняет значение непосредственно с аналогового вывода
float sensorVoltage0 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый pin
float windSpeed0 = 0; // Скорость ветра в метрах в секунду (м/с)

// Anemometer1
const int sensorPin1 = A1; // Определяет вывод, к которому подключен выход анемометра
int sensorValue1 = 0; // Переменная сохраняет значение непосредственно с аналогового вывода
float sensorVoltage1 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый
float windSpeed1 = 0; // Скорость ветра в метрах в секунду (м/с)

// Anemometer2
const int sensorPin2 = A2; // Определяет вывод, к которому подключен выход анемометра
int sensorValue2 = 0; // Переменная сохраняет значение непосредственно с аналогового вывода
float sensorVoltage2 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый
float windSpeed2 = 0; // Скорость ветра в метрах в секунду (м/с)

float voltageConversionConstant = .004882814; // Эта константа отображает значение, полученное из функции аналогового считывания,
// которое находится в диапазоне от 0 до 1023, в фактическое напряжение, которое находится в диапазоне от 0 В до 5
int sensorDelay = 1000; // Задержка между показаниями датчика, измеряется в миллисекундах (мс)

//Технические параметры анемометра
// Следующие переменные соответствуют анемометру, продаваемому компанией Adafruit, но могут быть изменены для соответствия другим анемометрам.

float voltageMin = .4; // Минимальное выходное напряжение от анемометра в мВ.
float windSpeedMin = 0; // Скорость ветра в метрах/сек, соответствующая минимальному напряжению

float voltageMax = 2.0; // Максимальное выходное напряжение от анемометра в мВ.
float windSpeedMax = 32; // Скорость ветра в метрах/сек, соответствующая максимальному напряжению

// для экрана регистрации данных мы используем цифровой вывод 10 для линии SD cs
const int chipSelect = 10;

// файл журнала
File logfile;

void error(char *str)
{
  Serial.print("error: ");
  Serial.println(str);
  
  // красный светодиод указывает на ошибку
  digitalWrite(redLEDpin, HIGH);
  
  while(1);
}

void setup() {
  // поместите сюда свой установочный код, чтобы запустить его один раз:

  Serial.begin(9600);
  Serial.println();
  
#if WAIT_TO_START
  Serial.println("Type any character to start");
  while (!Serial.available());
#endif //ОЖИДАНИЕ НАЧАЛА

  // инициализировать SD-карту
  Serial.print("Initializing SD card...");
  // убедитесь, что пин выбора чипа по умолчанию установлен на
  // вывод, даже если вы его не используете:
  pinMode(10, OUTPUT);
  
  // посмотрите, присутствует ли карта и может ли она быть инициализирована:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // больше ничего не делай:
    return;
  }
  Serial.println("card initialized.");
  
  // создайте новый файл
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // открывайте новый файл только в том случае, если он не существует
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // выйти из цикла!
    }
  }
  
  if (! logfile) {
    error("couldnt create file");
  }
  
  Serial.print("Logging to: ");
  Serial.println(filename);

  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
#if ECHO_TO_SERIAL
    Serial.println("RTC failed");
#endif  //ECHO_TO_SERIAL
  }
 
  pinMode(redLEDpin, OUTPUT);
  pinMode(greenLEDpin, OUTPUT);
 
   // Если вы хотите установить aref на что-то другое, кроме 5 В
  //Аналоговая ссылка (ВНЕШНЯЯ);
}

void loop() {
  // поместите сюда свой основной код для повторного запуска:

  DateTime now;

  // задержка на нужное нам время между показаниями
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
  
  digitalWrite(greenLEDpin, HIGH);

  // регистрировать миллисекунды с момента запуска
  uint32_t m = millis();
  logfile.print(m);           // миллисекунды с момента запуска
  logfile.print(", ");    
#if ECHO_TO_SERIAL
  Serial.print(m);         // миллисекунды с момента запуска
  Serial.print(", ");  
#endif

  // получить время
  now = RTC.now();
  // время регистрации
//logfile.print(); // секунды с 2000 года
  logfile.print(", ");
  logfile.print(now.year(), DEC);
  logfile.print("/");
  logfile.print(now.month(), DEC);
  logfile.print("/");
  logfile.print(now.day(), DEC);
  logfile.print(" ");
  logfile.print(now.hour(), DEC);
  logfile.print(":");
  logfile.print(now.minute(), DEC);
  logfile.print(":");
  logfile.print(now.second(), DEC);

#if ECHO_TO_SERIAL
  Serial.print(now.get()); // секунды с 2000 года
  Serial.print(", ");
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print(":");
  Serial.print(now.second(), DEC);
#endif //ECHO_TO_SERIAL
  
// Anemometer0
const int sensorPin0 = A0; // Определяет вывод, к которому подключен выход анемометра
int sensorValue0 = 0; // Переменная сохраняет значение непосредственно с аналогового вывода
float sensorVoltage0 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый pin
float windSpeed0 = 0; // Скорость ветра в метрах в секунду (м/с)

// Anemometer1
const int sensorPin1 = A1; // Определяет вывод, к которому подключен выход анемометра
int sensorValue1 = 0; // Переменная сохраняет значение непосредственно с аналогового вывода
float sensorVoltage1 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый
float windSpeed1 = 0; // Скорость ветра в метрах в секунду (м/с)

// Anemometer2
const int sensorPin2 = A2; // Определяет вывод, к которому подключен выход анемометра
int sensorValue2 = 0; // Переменная сохраняет значение непосредственно с аналогового вывода
float sensorVoltage2 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый
float windSpeed2 = 0; // Скорость ветра в метрах в секунду (м/с)

float voltageConversionConstant = .004882814; // Эта константа отображает значение, полученное из функции аналогового считывания,
// которое находится в диапазоне от 0 до 1023, в фактическое напряжение, которое находится в диапазоне от 0 В до 5
int sensorDelay = 1000; // Задержка между показаниями датчика, измеряется в миллисекундах (мс)

//Технические параметры анемометра
// Следующие переменные соответствуют анемометру, продаваемому компанией Adafruit, но могут быть изменены для соответствия другим анемометрам.

float voltageMin = .4; // Минимальное выходное напряжение от анемометра в мВ.
float windSpeedMin = 0; // Скорость ветра в метрах/сек, соответствующая минимальному напряжению

float voltageMax = 2.0; // Максимальное выходное напряжение от анемометра в мВ.
float windSpeedMax = 32; // Скорость ветра в метрах/сек, соответствующая максимальному напряжению
  
  logfile.print(", ");    
  logfile.print(A0);
  logfile.print(", ");
  logfile.print(A1);    
  logfile.print(",");
  logfile.println(A2);

#if ECHO_TO_SERIAL
  Serial.print(", ");   
  Serial.print(Anemometer0);
  Serial.print(", ");    
  Serial.print(Anemometer1);
  Serial.print(",");
  Serial.println(Anemometer2);
#endif //ECHO_TO_SERIAL

  digitalWrite(greenLEDpin, LOW);
}
´´´ 

, 👍2

Обсуждение

Вы "проверили", да. Но вы "загрузили"?, @Majenko

вы не открываете файл, если он существует, @Juraj

@Juraj Этот фрагмент кода предназначен для создания нового файла с последовательной нумерацией. Он найдет первый файл, который * не * существует в LOGGER00.CSV, в LOGGER99.CSV и откроет его., @Majenko

Да, @Majenko, код был правильно загружен на плату. Но я не упомянул об этом в письменном объяснении, спасибо, что указали на это. Должен ли файл содержать какие-либо данные и дату / время?, @PedroHerve

Я подозреваю, что вы не даете ему достаточно времени, чтобы сбросить данные на SD-карту, и они находятся только в буфере. Вы должны вызвать logfile.flush(); после каждой итерации., @Majenko

Допустили ли вы ошибку копирования-вставки при вводе кода в вопрос? У вас есть часть в loop (), где вы снова определяете глобальные переменные, такие как sensorPin0, @chrisl

Ваши заявления о задержке кажутся мне действительно странными. Зачем ты это делаешь? Если вы хотите читать с определенным интервалом, вам следует использовать millis (), как в примере BlinkWithoutDelay, и полностью избегать delay (), @chrisl

@chris|, да... Я допустил ошибку. Спасибо, что заметили!, @PedroHerve


1 ответ


2

Спасибо за всю вашу помощь. Мне удалось записать данные на SD-карту, включая дату и время. Новый код выглядит следующим образом:

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

RTC_DS1307 rtc; // создание локальных экземпляров объектов библиотечного класса

DateTime time;

File dataFile;

const int chipSelect = 10;

// Анемометр при 0,15 магл

const int sensorPinA0 = A0; // Определяет вывод, к которому подключен выход анемометра
int sensorValue0 = 0; // Переменная сохраняет значение непосредственно от аналогового
float sensorVoltage0 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый вывод
float WindSpeed0 = 0; // Скорость ветра в метрах в секунду (м/с)

float voltageConversionConstant0 = .0048828125; // Эта константа отображает значение, полученное из функции аналогового считывания, которое находится в диапазоне от 0 до 1024, в фактическое напряжение, которое находится в диапазоне от 0 В до 5 В
// следовательно, это значение соответствует 5,00 В/1024. Проверить https://forum.allaboutcircuits.com/threads/why-adc-1024-is-correct-and-adc-1023-is-just-plain-wrong.80018/
int sensorDelay0 = 60000; //Задержка между показаниями датчика, измеряемая в миллисекундах (мс)

//Технические параметры анемометра
// Следующие переменные соответствуют анемометру, продаваемому компанией Adafruit, но могут быть изменены для соответствия другим анемометрам.

float voltageMin0 = .4; // Минимальное выходное напряжение от анемометра в мВ.
float windSpeedMin0 = 0; // Скорость ветра в метрах/сек, соответствующая минимальному напряжению

float voltageMax0 = 2.0; // Максимальное выходное напряжение от анемометра в мВ.
float windSpeedMax0 = 32; // Скорость ветра в метрах/сек, соответствующая максимальному напряжению

// Анемометр на 0,5 магл

const int sensorPinA1 = A1; // Определяет вывод, к которому подключен выход анемометра
int sensorValue1 = 0; // Переменная сохраняет значение непосредственно от аналогового
float sensorVoltage1 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый вывод
float WindSpeed1 = 0; // Скорость ветра в метрах в секунду (м/с)

float voltageConversionConstant1 = .0048828125; // Эта константа отображает значение, полученное из функции аналогового считывания, которое находится в диапазоне от 0 до 1024, в фактическое напряжение, которое находится в диапазоне от 0 В до 5 В
// следовательно, это значение соответствует 5,00 В/1024. Проверить https://forum.allaboutcircuits.com/threads/why-adc-1024-is-correct-and-adc-1023-is-just-plain-wrong.80018/
int sensorDelay1 = 1000; //Задержка между показаниями датчика, измеряемая в миллисекундах (мс)

//Технические параметры анемометра
// Следующие переменные соответствуют анемометру, продаваемому компанией Adafruit, но могут быть изменены для соответствия другим анемометрам.

float voltageMin1 = .4; // Минимальное выходное напряжение от анемометра в мВ.
float windSpeedMin1 = 0; // Скорость ветра в метрах/сек, соответствующая минимальному напряжению

float voltageMax1 = 2.0; // Максимальное выходное напряжение от анемометра в мВ.
float windSpeedMax1 = 32; // Скорость ветра в метрах/сек, соответствующая максимальному напряжению

// Анемометр на 1,2 магл

const int sensorPinA2 = A2; // Определяет вывод, к которому подключен выход анемометра
int sensorValue2 = 0; // Переменная сохраняет значение непосредственно от аналогового вывода
float sensorVoltage2 = 0; // Переменная, которая сохраняет напряжение (в вольтах) от анемометра, отправляемого на аналоговый вывод
float WindSpeed2 = 0; // Скорость ветра в метрах в секунду (м/с)

float voltageConversionConstant2 = .0048828125; // Эта константа отображает значение, полученное из функции аналогового считывания, которое находится в диапазоне от 0 до 1024, в фактическое напряжение, которое находится в диапазоне от 0 В до 5 В
// следовательно, это значение соответствует 5,00 В/1024. Проверить https://forum.allaboutcircuits.com/threads/why-adc-1024-is-correct-and-adc-1023-is-just-plain-wrong.80018/
int sensorDelay2 = 60000; //Задержка между показаниями датчика, измеряемая в миллисекундах (мс)

//Технические параметры анемометра
// Следующие переменные соответствуют анемометру, продаваемому компанией Adafruit, но могут быть изменены для соответствия другим анемометрам.

float voltageMin2 = .4; // Минимальное выходное напряжение от анемометра в мВ.
float windSpeedMin2 = 0; // Скорость ветра в метрах/сек, соответствующая минимальному напряжению

float voltageMax2 = 2.0; // Максимальное выходное напряжение от анемометра в мВ.
float windSpeedMax2 = 32; // Скорость ветра в метрах/сек, соответствующая максимальному напряжению

void setup() {
 Serial.begin(9600);
 while (!Serial) {;} // дождитесь подключения последовательного порта.
 Serial.print("Initializing SD card...");
 if (!SD.begin(chipSelect)) {
 Serial.println("Card failed, or not present");
 while (1); // цикл навсегда
 }
 Serial.println("Have SD card");
 rtc.begin();
}

void loop() {
  
sensorValue0 = analogRead(A0); // Получить значение от 0 до 1023 от аналогового вывода, подключенного к анемометру
sensorValue1 = analogRead(A1); // Получить значение от 0 до 1023 от аналогового вывода, подключенного к анемометру
sensorValue2 = analogRead(A2); // Получить значение между 0 и 1023 от аналогового вывода, подключенного к анемометру

sensorVoltage0 = sensorValue0 * voltageConversionConstant0; // Преобразовать значение датчика в фактическое напряжение
sensorVoltage1 = sensorValue1 * voltageConversionConstant1; // Преобразовать значение датчика в фактическое напряжение
sensorVoltage2 = sensorValue2 * voltageConversionConstant2; // Преобразовать значение датчика в фактическое напряжение

//Преобразуйте значение напряжения в скорость ветра, используя диапазон максимальных и минимальных напряжений и скорости ветра для анемометра
if (sensorVoltage0 <= voltageMin0){
WindSpeed0 = 0; //Проверьте, не ниже ли напряжение минимального значения. Если это так, установите скорость ветра равной нулю.
}

else {
  WindSpeed0 = (sensorVoltage0 - voltageMin0)*windSpeedMax0/(voltageMax0 - voltageMin0); // Для напряжений выше минимального значения используйте линейную зависимость для вычисления скорости ветра на A0.
    }

if (sensorVoltage1 <= voltageMin1){
WindSpeed1 = 0; //Проверьте, не ниже ли напряжение минимального значения. Если это так, установите скорость ветра равной нулю.
}

else {
  WindSpeed1 = (sensorVoltage1 - voltageMin1)*windSpeedMax1/(voltageMax1 - voltageMin1); // Для напряжений выше минимального значения используйте линейную зависимость для вычисления скорости ветра на A1.
    }   

if (sensorVoltage2 <= voltageMin2){
WindSpeed2 = 0; //Проверьте, не ниже ли напряжение минимального значения. Если это так, установите скорость ветра равной нулю.
}

else {
  WindSpeed2 = (sensorVoltage2 - voltageMin2)*windSpeedMax2/(voltageMax2 - voltageMin2); // Для напряжений выше минимального значения используйте линейную зависимость для вычисления скорости ветра на A2.
    }

 time = rtc.now(); // Читать RTC
 String dataString = ""; // Собрать данные

log:
 dataString = time.timestamp(DateTime::TIMESTAMP_DATE);
 dataString += ", ";
 dataString += time.timestamp(DateTime::TIMESTAMP_TIME);
 dataString += ", ";
 dataString += String(sensorVoltage0);
 dataString += ", ";
 dataString += String(WindSpeed0);
 dataString += ", ";
 dataString += String(sensorVoltage1);
 dataString += ", ";
 dataString += String(WindSpeed1);
 dataString += ", ";
 dataString += String(sensorVoltage2);
 dataString += ", ";
 dataString  += String(WindSpeed2);
 dataFile = SD.open("Speedlog.txt", FILE_WRITE);
 if (dataFile) { // Запись в файл журнала

 dataFile.println(dataString);
 dataFile.close();
 Serial.println(dataString);
 delay(1000); // пауза в течение одной секунды между регистрациями датчиков
 }
 else {
 Serial.println("error opening datalog.txt");
 }
}
,

Вы не должны использовать строку, да вам это и не нужно, потому что вы можете просто записать все биты в файл, не объединяя их сначала. Если необходимо, вам следует удалить String dataString = ""; из цикла и добавить его в качестве глобального вверху; это может немного помочь сохранить вашу кучу нетронутой, но лучше вообще избегать String ., @ocrdu