Datalogger: Analog input values not matching the source

Hello!

I am trying to make a Datalogger with an Arduino UNO and a Datalogger+RTC Shield.

It should work as follows:

  • As long as D2=LOW, Datalogger does nothing (only updates the time)
  • If D2=HIGH, it has to read the values of the analog inputs (A0 to A3) and write the values (with some scaling) to the SD card and turn on an LED attached to D4, so that I can see that the Datalogger is saving data. It has to do this all the time that D2=HIGH. A3 is not currently being used, please ignore it (A4 and A5 are already being used by the shield).

The data coming to the Analog ports is coming from a DAC. To be sure that the conversion is working properly, I measured with an oscillosope the values coming from the DAC and comparing them to the real digital values. Everything is ok.

The problem is that there is a drift between the values that Arduino reads at A0 and A1 to the real values. A2 is working properly (see attached images, please ignore the number of samples, it depends on the sampling rate I am using. I am only interested in the y-axis).

In order to be sure that there is no scaling problem, I already tested to send some static values in the middle of the scale (2.5V) and all analog channels were working properly and showing the right static value.

Does anybody have any idea, what might be happening?

Here you are the code:

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

const int chipSelect = 10; //10 is default by shield, but normally on Pin 4
const int triggerpin = 2; // Interrupt pin
const int led = 4; // Led lights, when data is written

const int SpS = 5;
const int BAP_min = 830;
const int BAP_max = 1000;
const int EAP_min = 850;
const int EAP_max = 1050;
const int BIP_min = 180;
const int BIP_max = 270;
const int EIP_min = 100;
const int EIP_max = 250;

String timestring;

int analog0 = A0;
int analog1 = A1;
int analog2 = A2;
int analog3 = A3;

RTC_DS1307 rtc;

void setup() {
  pinMode(triggerpin, INPUT); // Kein INPUT_PULLUP weil das nur für Knöpfe gut ist
  pinMode(led, OUTPUT);
  
  Serial.begin(9600);
  delay(3000);
  Serial.println("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("SD Card error");
    return;
  }
  Serial.println("card initialized");
  if (! rtc.begin()) {
    Serial.println("No RTC found");
  } else {
    Serial.println("RTC clock found");
  }
  if (! rtc.isrunning()) {
    Serial.println("RTC is not configured");
  }
}

void loop() {
  //timer = millis();
  get_time();
  while (digitalRead(triggerpin) == HIGH){
    digitalWrite(led,HIGH);
    write_data(); 
  }
  digitalWrite(led, LOW);   // turn the LED off
  }

void get_time(){ //Read Time from RTC
  DateTime now = rtc.now();
  timestring = now.day();
  timestring += ".";
  timestring += now.month();
  timestring += ".";
  timestring += now.year();
  timestring += " ";
  timestring += now.hour();
  timestring += ":";
  timestring += now.minute();
  timestring += ":";
  timestring += now.second();
  //Serial.println(timestring);
}

float fmap(float x, float in_min, float in_max, float out_min, float out_max)
{
 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void write_data() { //Write to SD card
  float val0 = fmap(analogRead(analog0),0,1023,BAP_min,BAP_max);
  float val1 = fmap(analogRead(analog1),0,1023,EAP_min,EAP_max);
  float val2 = fmap(analogRead(analog2),0,1023,BIP_min,BIP_max);
  float val3 = fmap(analogRead(analog3),0,1023,EIP_min,EIP_max);
  String dataString = timestring + "," +String(SpS) + "," + String(val0) + "," + String(val1) + "," + String(val2) + "," + String(val3);
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    Serial.println(dataString);
  }
  else {
    Serial.println("error writing datalog.txt");
  }
}

Thanks very much in advance for the help!

A2.png

Avoid use of String objects on the Uno. Your program will crash unexpectedly due to memory fragmentation.

To debug the hardware, first write a simple program that just prints out the values from the analog inputs, and compare those values with what you get using a multimeter. Show us the results.

Hi!

Thanks for your answer.

How can I write data on a SD card iwthout using String objects? I have been reading examples about it and I cannot find another solution. The program is not crashing, it is working and saving the data. The only thing is that I have an "offset" I cannot explain.

About using a multimeter, it is exactly what I already did with the oscilloscope. I have been compairing the input signal I am giving with the values that Arduino stores and they don't match for channels A0 and A1. A2 is working perfectly.

I will try tomorrow with another Arduino UNO board to see whether there is a problem there. I already changed cables to see whether the error is also changing, but it remains the same. So it is not due to the cables...

Thanks for the time and help!

How can I write data on a SD card iwthout using String objects?

  1. Use dataFile.print() statements as you are already doing, but with variables, not Strings. Exactly as you would to the serial monitor.

  2. Use C-strings (zero terminated character arrays) and C-string formatting utilities like snprintf(), itoa(), etc. followed by dataFile.print() statements.

But the problem likely has nothing to do with the SD card.

I have been compairing the input signal I am giving with the values that Arduino stores and they don't match for channels A0 and A1. A2 is working perfectly.

Please post those details (raw ADC values obtained using the simplest possible program) and a complete wiring diagram.